From 7cdcb59e723cfa08366386ac0629dd61d2b0685b Mon Sep 17 00:00:00 2001 From: HelloThisWorld Date: Sun, 12 Jul 2026 22:03:06 +0800 Subject: [PATCH] SpecBridge v0.4: deterministic spec drift verification and GitHub Action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kiro helps users write specs; SpecBridge now verifies whether the implementation still matches them — deterministically, offline, with no model, API key, or network access required. Added: - @specbridge/drift verification engine: git comparison resolution (--diff/--base+--head/--working-tree/--staged, -z parsing, rename/ binary/untracked handling, ref-injection rejection, --relative for nested workspaces), versioned policy loader with validated globs, traceability extraction, evidence freshness validation, trusted-command orchestration with evidence reuse, affected-spec resolution, and the explicit rule registry SBV001-SBV025 (heuristic rules never default to error; schema-validated reports). - CLI: spec verify (single/--changed/--all, --fail-on, --strict, four output formats), spec affected, spec policy init/show/validate, and verify rules/explain. Exit codes 0/1/2/3/4/5 documented and tested. - Reports: terminal, versioned JSON, Step-Summary-ready Markdown, and a self-contained HTML report (no scripts, no external requests, CSS-only filters). - GitHub Action (node20, committed reproducible bundle, no pnpm or model for consumers): PR/push/workflow_dispatch diff resolution, validated inputs, ten outputs, bounded rule-ID annotations, Step Summary; never modifies tracked files. Changed: - Task-plan approval hashing distinguishes checkbox progress from plan changes (hash semantics v2): approvedPlanHash (checkbox-normalized) recorded beside the exact approvedHash. [ ] -> [x] progress keeps the approval effective; text/ID/hierarchy/reference edits invalidate it. Requirements/design approvals remain exact-byte. Pre-v0.4 sidecar state keeps validating and migrates on the next sanctioned write. - Evidence records now capture a specContext (approved hashes + checkbox- invariant task fingerprint) so verification can judge freshness exactly; v0.3 records fall back to recorded approval timestamps. Verification: 520 tests in 42 files (baseline 362/30), lint, typecheck, build, and 28 CLI smoke checks all pass; the action bundle rebuild is byte-identical and enforced in CI. All versions bumped to 0.4.0; nothing published. Co-Authored-By: Claude Fable 5 --- .github/workflows/ci.yml | 10 +- .gitignore | 3 + CHANGELOG.md | 83 + README.md | 173 +- docs/affected-spec-detection.md | 58 + docs/architecture.md | 7 +- docs/ci-quality-gates.md | 67 + docs/evidence-freshness.md | 89 + docs/github-action.md | 118 + docs/requirement-task-traceability.md | 72 + docs/roadmap.md | 36 +- docs/security.md | 40 + docs/spec-drift-verification.md | 117 + docs/spec-drift.md | 106 +- docs/verification-policy.md | 97 + docs/verification-rules.md | 89 + eslint.config.js | 3 +- .../claude-code/skills/specbridge/SKILL.md | 13 +- integrations/github-action/README.md | 141 +- integrations/github-action/action.yml | 99 +- integrations/github-action/dist/index.js | 45604 ++++++++++++++++ integrations/github-action/package.json | 23 + integrations/github-action/src/annotations.ts | 71 + integrations/github-action/src/event.ts | 107 + integrations/github-action/src/inputs.ts | 98 + integrations/github-action/src/main.ts | 143 + integrations/github-action/src/version.ts | 2 + integrations/github-action/tsconfig.json | 7 + integrations/github-action/tsup.config.ts | 20 + package.json | 2 +- packages/cli/package.json | 3 +- packages/cli/src/cli.ts | 6 + packages/cli/src/commands/spec-accept-task.ts | 8 +- packages/cli/src/commands/spec-affected.ts | 133 + packages/cli/src/commands/spec-policy.ts | 351 + packages/cli/src/commands/spec-verify.ts | 212 +- packages/cli/src/commands/verify-rules.ts | 112 + packages/cli/src/verify-options.ts | 64 + packages/cli/src/version.ts | 2 +- packages/compat-kiro/package.json | 2 +- packages/compat-kiro/src/index.ts | 2 + packages/compat-kiro/src/task-plan-hash.ts | 82 + packages/compat-kiro/src/traceability.ts | 470 + packages/core/package.json | 2 +- packages/core/src/index.ts | 1 + packages/core/src/spec-state.ts | 35 + packages/core/src/verification-types.ts | 276 + packages/drift/package.json | 5 +- packages/drift/src/index.ts | 24 +- packages/drift/src/verification/affected.ts | 158 + packages/drift/src/verification/commands.ts | 170 + packages/drift/src/verification/comparison.ts | 433 + packages/drift/src/verification/context.ts | 392 + packages/drift/src/verification/policy.ts | 314 + .../drift/src/verification/rule-engine.ts | 186 + packages/drift/src/verification/rules.ts | 1224 + packages/drift/src/verification/verify.ts | 412 + packages/evidence/package.json | 2 +- packages/evidence/src/evidence-store.ts | 26 + packages/evidence/src/freshness.ts | 380 + packages/evidence/src/index.ts | 1 + packages/execution/package.json | 2 +- packages/execution/src/complete-task.ts | 29 +- packages/execution/src/execute-task.ts | 50 +- packages/reporting/package.json | 2 +- packages/reporting/src/index.ts | 3 + packages/reporting/src/verification-html.ts | 202 + .../reporting/src/verification-markdown.ts | 215 + .../reporting/src/verification-terminal.ts | 171 + packages/runners/package.json | 2 +- packages/workflow/package.json | 2 +- packages/workflow/src/approval.ts | 44 +- packages/workflow/src/health.ts | 27 + pnpm-lock.yaml | 85 + pnpm-workspace.yaml | 1 + scripts/smoke.mjs | 50 + tests/action/github-action.test.ts | 365 + tests/cli/cli-smoke.test.ts | 8 +- tests/cli/cli-v04-verify.test.ts | 290 + tests/compatibility/traceability.test.ts | 209 + tests/drift/comparison.test.ts | 146 + tests/drift/evidence-freshness.test.ts | 243 + tests/drift/rule-engine.test.ts | 159 + tests/drift/task-plan-hash.test.ts | 89 + tests/drift/verification-policy.test.ts | 148 + tests/drift/verify-encodings.test.ts | 49 + tests/drift/verify-orchestration.test.ts | 280 + tests/drift/verify-rules.test.ts | 469 + .../fixtures/github-events/pull_request.json | 9 + tests/fixtures/github-events/push.json | 5 + .../github-events/workflow_dispatch.json | 4 + tests/helpers-verify.ts | 245 + tests/workflow/plan-hash-approval.test.ts | 155 + tsconfig.json | 2 + 94 files changed, 56476 insertions(+), 270 deletions(-) create mode 100644 docs/affected-spec-detection.md create mode 100644 docs/ci-quality-gates.md create mode 100644 docs/evidence-freshness.md create mode 100644 docs/github-action.md create mode 100644 docs/requirement-task-traceability.md create mode 100644 docs/spec-drift-verification.md create mode 100644 docs/verification-policy.md create mode 100644 docs/verification-rules.md create mode 100644 integrations/github-action/dist/index.js create mode 100644 integrations/github-action/package.json create mode 100644 integrations/github-action/src/annotations.ts create mode 100644 integrations/github-action/src/event.ts create mode 100644 integrations/github-action/src/inputs.ts create mode 100644 integrations/github-action/src/main.ts create mode 100644 integrations/github-action/src/version.ts create mode 100644 integrations/github-action/tsconfig.json create mode 100644 integrations/github-action/tsup.config.ts create mode 100644 packages/cli/src/commands/spec-affected.ts create mode 100644 packages/cli/src/commands/spec-policy.ts create mode 100644 packages/cli/src/commands/verify-rules.ts create mode 100644 packages/cli/src/verify-options.ts create mode 100644 packages/compat-kiro/src/task-plan-hash.ts create mode 100644 packages/compat-kiro/src/traceability.ts create mode 100644 packages/core/src/verification-types.ts create mode 100644 packages/drift/src/verification/affected.ts create mode 100644 packages/drift/src/verification/commands.ts create mode 100644 packages/drift/src/verification/comparison.ts create mode 100644 packages/drift/src/verification/context.ts create mode 100644 packages/drift/src/verification/policy.ts create mode 100644 packages/drift/src/verification/rule-engine.ts create mode 100644 packages/drift/src/verification/rules.ts create mode 100644 packages/drift/src/verification/verify.ts create mode 100644 packages/evidence/src/freshness.ts create mode 100644 packages/reporting/src/verification-html.ts create mode 100644 packages/reporting/src/verification-markdown.ts create mode 100644 packages/reporting/src/verification-terminal.ts create mode 100644 tests/action/github-action.test.ts create mode 100644 tests/cli/cli-v04-verify.test.ts create mode 100644 tests/compatibility/traceability.test.ts create mode 100644 tests/drift/comparison.test.ts create mode 100644 tests/drift/evidence-freshness.test.ts create mode 100644 tests/drift/rule-engine.test.ts create mode 100644 tests/drift/task-plan-hash.test.ts create mode 100644 tests/drift/verification-policy.test.ts create mode 100644 tests/drift/verify-encodings.test.ts create mode 100644 tests/drift/verify-orchestration.test.ts create mode 100644 tests/drift/verify-rules.test.ts create mode 100644 tests/fixtures/github-events/pull_request.json create mode 100644 tests/fixtures/github-events/push.json create mode 100644 tests/fixtures/github-events/workflow_dispatch.json create mode 100644 tests/helpers-verify.ts create mode 100644 tests/workflow/plan-hash-approval.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f60f12..bb30f13 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,11 +36,15 @@ jobs: - name: Typecheck run: pnpm typecheck - - name: Test (compatibility fixtures, round-trip byte identity, CLI, drift) - run: pnpm test - - name: Build run: pnpm build + - name: Test (compatibility fixtures, round-trip byte identity, CLI, drift, action) + run: pnpm test + - name: CLI smoke test against the example Kiro workspace run: node scripts/smoke.mjs + + - name: GitHub Action bundle is reproducible + if: matrix.os == 'ubuntu-latest' + run: git diff --exit-code integrations/github-action/dist diff --git a/.gitignore b/.gitignore index 6f13ec4..f4ce675 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ node_modules/ dist/ *.tsbuildinfo +# The GitHub Action ships its reproducible bundle in-repo (checked in CI). +!integrations/github-action/dist/ + # Test output coverage/ diff --git a/CHANGELOG.md b/CHANGELOG.md index d0f61c0..086279e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,88 @@ # Changelog +## 0.4.0 + +Added: + +- Deterministic spec drift rule engine (`@specbridge/drift`) with 25 stable, + documented rule IDs (`SBV001`–`SBV025`) across workspace, approval, + requirements, design, tasks, evidence, impact-area, verification-command, + protected-path, mapping, and git categories. Every diagnostic carries a + versioned schema, severity, category, message, remediation, source + location, structured evidence, and a deterministic/heuristic confidence + label. Heuristic rules never default to error severity. +- `specbridge spec verify [name] | --changed | --all` — read-only + verification against a git comparison: `--diff base...head`, + `--base/--head`, `--working-tree` (default), or `--staged`, with + `--fail-on error|warning|never`, `--strict`, `--policy`, `--json`, + `--format terminal|json|markdown|html`, and `--output`. Exit codes: + 0 passed, 1 threshold reached, 2 invalid input/policy/state, 3 comparison + unavailable, 4 command failed to start, 5 command timeout. +- Requirement-to-task traceability extraction: requirement and acceptance + criterion IDs (`R1`, `R1.1`, `REQ-001`, `Requirement 1`, `AC-1`, `AC1.2`), + task references (`_Requirements: 1.1_`, `Requirements: R1`, `[R1]`, + keyword phrases as heuristics), explicit design path references, source + lines, and extraction-method provenance. +- Task evidence freshness validation: recorded approved-content hashes, + checkbox-invariant task fingerprints, commit lineage, repository-path + safety, and timestamp fallbacks for v0.3 records. New evidence records a + `specContext` (approved hashes + task fingerprint) for exact drift checks. +- Spec-specific verification policies under `.specbridge/policies/.json` + (versioned Zod schema; validated globs; advisory/strict modes; per-rule + severity overrides) with `spec policy init|show|validate`. `.git/**` + protection can never be configured away. +- Affected-spec resolution (`spec affected`, `spec verify --changed`): spec + files, sidecar state, policy files, impact areas, accepted task evidence, + and explicit design references; unmapped files (SBV014) and ambiguous + mappings (SBV022) are reported, never silently ignored. +- Trusted verification command orchestration for CI: policy-required + commands run by default, `--run-verification` runs everything configured, + `--no-run-verification` reuses passing results only from valid, fresh + evidence recorded at the exact current HEAD. +- Verification reports: terminal, versioned JSON (`schemaVersion 1.0.0`, + validated before writing), GitHub-flavored Markdown (Step Summary ready), + and a self-contained HTML report (no scripts, no external requests, + CSS-only severity/spec filters). +- Production GitHub Action (`integrations/github-action`, node20, bundled, + no pnpm or model required): pull_request/push/workflow_dispatch diff + resolution, validated inputs, ten documented outputs, bounded file/line + annotations with rule IDs, and a Step Summary. The committed bundle is + rebuilt and diffed in CI. +- `specbridge verify rules` and `specbridge verify explain ` — + deterministic, read-only rule inspection. + +Changed: + +- Task-plan approval hashing distinguishes checkbox progress from plan + changes (hash semantics v2): approving `tasks.md` now records an + `approvedPlanHash` (checkbox state normalized) beside the exact + `approvedHash`. `[ ]` → `[x]` progress keeps the approval effective; task + text, ID, hierarchy, or reference changes still invalidate it. + Requirements and design approvals remain exact-byte. Pre-v0.4 sidecar + state keeps validating with exact-byte semantics until the next sanctioned + write migrates it. +- Verification reports use versioned schemas; reports are validated with Zod + before they are written. + +Security: + +- Verification needs no model, no API key, and no network access. +- Verification commands come only from `.specbridge/config.json` — never + from spec text or model output; argv arrays only, no shell interpolation. +- Git refs are validated (no option injection); git runs argv-only with + timeouts and output limits; SpecBridge never fetches, commits, or pushes. +- Verification never writes to `.kiro`, approval state, task checkboxes, or + evidence; report artifacts are its only writes. +- Policy globs reject absolute paths, traversal, null bytes, and malformed + patterns; evidence paths escaping the repository are flagged (SBV024); + symlinks escaping the repository are detected. +- HTML reports escape all dynamic content and load nothing external. + +Deferred (documented on the roadmap, not claimed): + +- MCP server, Claude Code plugin bundle, additional production runners + (codex/gemini/ollama), extension SDK, template registry, SARIF output. + ## 0.3.0 Added: diff --git a/README.md b/README.md index b1778bf..fac29f8 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,27 @@ Codex, local models, or any supported coding agent. > Your `.kiro` specs remain the source of truth. +Now with deterministic spec drift verification (v0.4) — Kiro helps you +write specs; SpecBridge verifies whether the implementation still matches +them: + +```text +approved spec + + Git diff + + task evidence + + trusted verification + ↓ + SpecBridge quality gate +``` + ```sh cd your-kiro-project # any project that already contains .kiro/ npx specbridge doctor # read-only health check — nothing is modified npx specbridge spec list + +npx specbridge spec verify --changed \ + --diff origin/main...HEAD \ + --run-verification # deterministic, offline, no model required ``` *(Until the first npm release, build from source — see @@ -158,13 +175,18 @@ Working today (fully offline, no model, no API key): | `specbridge spec run ` | **v0.3** — execute ONE approved task; evidence-gated checkbox completion | | `specbridge spec accept-task --task --reason …` | **v0.3** — explicit, audited manual acceptance | | `specbridge run list / show / resume` | **v0.3** — inspect append-only run records; resume interrupted sessions | - -Planned commands (`spec sync/verify/export`) are registered, marked -"(planned)" in `--help`, and exit with an honest error — see the -[roadmap](docs/roadmap.md). Every command supports `--help` with examples. -Exit codes: `0` success · `1` workflow/verification failure · `2` usage or -configuration error · `3` runner unavailable · `4` runner failure · -`5` timeout/cancel · `6` safety violation. +| `specbridge spec verify [name] \| --changed \| --all` | **v0.4** — deterministic drift verification against a git comparison (read-only) | +| `specbridge spec affected` | **v0.4** — which specs does this change set touch (read-only) | +| `specbridge spec policy init / show / validate` | **v0.4** — per-spec verification policies (impact areas, required commands, rule overrides) | +| `specbridge verify rules / explain ` | **v0.4** — inspect the stable rule registry SBV001–SBV025 | + +Planned commands (`spec sync/export`) are registered, marked "(planned)" in +`--help`, and exit with an honest error — see the [roadmap](docs/roadmap.md). +Every command supports `--help` with examples. Exit codes: `0` success · +`1` workflow/verification failure · `2` usage or configuration error · +`3` runner unavailable / git comparison unavailable · `4` runner or +verification-command start failure · `5` timeout/cancel · `6` safety +violation ([details](docs/ci-quality-gates.md)). ## Spec authoring and approval (v0.2) @@ -317,32 +339,79 @@ Two directions, both covered in The CLI remains the product core; the skill is a thin wrapper that never bypasses approval gates or edits checkboxes itself. -## Spec drift verification +## Spec drift verification (v0.4) -The headline differentiator: deterministic, LLM-free verification that code -changes match the spec — tasks marked done without evidence, changes outside -declared impact areas, criteria no task references, and more. - -**Status:** the deterministic checks ship today as a tested library -([`@specbridge/drift`](packages/drift)); the `specbridge spec verify` CLI -command and CI gate land in Phase H. Design: [docs/spec-drift.md](docs/spec-drift.md). - -Planned CI usage: +The headline differentiator: deterministic, LLM-free verification that +implementation changes still match the approved specs. SpecBridge detects +explicit traceability gaps, stale evidence, approval drift, out-of-scope +file changes, and failed configured verification commands — it does **not** +claim to semantically prove that code implements natural-language +requirements, and findings based on pattern recognition are labelled +heuristic and never default to error. ```sh -npx specbridge spec verify --changed --fail-on-drift +specbridge spec verify notification-preferences --working-tree +specbridge spec verify notification-preferences --diff origin/main...HEAD --run-verification +specbridge spec verify --changed --diff origin/main...HEAD +specbridge spec verify --all --working-tree --fail-on warning +specbridge spec affected --diff origin/main...HEAD ``` -Exit codes: `0` passed · `1` drift / quality-gate failure · `2` configuration -or runtime error. - -## GitHub Action +What it checks (25 stable rule IDs, `specbridge verify rules`): + +- **Approval drift** — approved requirements/design/task-plan content that + changed after approval (SBV002/SBV003). Checkbox-only `[ ]`→`[x]` + progress no longer invalidates an approved task plan (normalized plan + hash, v0.4); real plan edits still do. +- **Evidence** — checked tasks without valid evidence, stale evidence + (spec or task changed after it was recorded), manual acceptance + labelled distinctly (SBV004/SBV011/SBV015/SBV024). +- **Traceability** — requirements no task references, tasks referencing + unknown requirements, checked parents with open subtasks + (SBV007–SBV010). +- **Scope** — changes outside declared impact areas, protected-path + modifications, files no spec claims (SBV005/SBV006/SBV014/SBV022). +- **Trusted commands** — failed/missing/timed-out verification commands + from `.specbridge/config.json` (SBV012/SBV013/SBV025) — never from spec + text or model output. + +Reports: terminal, versioned JSON, GitHub-ready Markdown, and a +self-contained HTML file. Verification is read-only — it never edits +`.kiro`, checkboxes, approvals, or evidence. Everything is deterministic +and offline: no model, no API key, no network. + +Docs: [spec drift verification](docs/spec-drift-verification.md) · +[rules](docs/verification-rules.md) · [policies](docs/verification-policy.md) · +[traceability](docs/requirement-task-traceability.md) · +[evidence freshness](docs/evidence-freshness.md) · +[affected specs](docs/affected-spec-detection.md) · +[CI quality gates](docs/ci-quality-gates.md). + +## GitHub Action (v0.4) + +A production node20 action wraps the same verification engine — no model, +no API key, no pnpm, no network access: + +```yaml +- uses: actions/checkout@v4 + with: + fetch-depth: 0 # the action never fetches by itself + +- name: Verify spec alignment + uses: /specbridge/integrations/github-action@v0.4 # placeholder until published + with: + mode: changed + fail-on: error + run-verification: true +``` -A preview composite action runs the read-only gates that exist today -(`doctor` + `compat check`): -[integrations/github-action](integrations/github-action/README.md). Drift -gates join it in Phase H. CI for this repository runs on Linux, macOS, and -Windows with Node 20 and 22 — no model, no API key. +Pull-request and push diffs resolve from the event; `workflow_dispatch` +takes explicit `base-ref`/`head-ref`. The action writes a Step Summary, +emits bounded file/line annotations titled with rule IDs, exposes ten +outputs, and uploads-ready reports land in `.specbridge/action-reports`. +Details: [docs/github-action.md](docs/github-action.md) · +[integrations/github-action](integrations/github-action/README.md). +CI for this repository runs on Linux, macOS, and Windows with Node 20/22. ## Supported runners @@ -375,11 +444,15 @@ SpecBridge stores no credentials of any kind. secrets or environment variables. - Full model: [docs/security.md](docs/security.md). -## Limitations (v0.3) +## Limitations (v0.4) -- Sync, the drift-verification CLI, and export are not implemented yet (they - fail honestly; the drift library primitives exist). v0.3 does **not** yet - implement full spec-to-code drift analysis. +- Verification is deterministic, not semantic: it proves traceability, + approval, evidence, scope, and command facts — it cannot judge whether + code *correctly implements* a natural-language requirement, and it never + claims to. Heuristic findings (test-language detection, keyword + references, chore-task exclusion) are labelled and never default to error. +- `spec sync` and `spec export` are not implemented yet (they fail + honestly). SARIF output is deferred. - Claude Code is the only production runner; codex/ollama/openai-compatible remain stubs. Claude usage happens under your own account and plan. - Task execution requires a git repository, sidecar workflow state, and @@ -387,14 +460,21 @@ SpecBridge stores no credentials of any kind. - Tasks can only auto-verify when verification commands are configured; with none configured, runs end `implemented-unverified`. - One task per run; `--all` is strictly sequential. Parallel execution, - agent teams, sandboxing, and automatic rollback are out of scope for v0.3. -- Analysis is deterministic and structural; it cannot judge whether - requirements are *good*, only whether they are well-formed and complete. + agent teams, sandboxing, and automatic rollback remain out of scope. +- Verification requires git history: shallow clones fail with actionable + guidance (SBV021) rather than guessing; SpecBridge never fetches. +- Sidecar state written before v0.4 has no normalized task-plan hash; + checkbox edits made outside SpecBridge read as stale until the next + approval or sanctioned write records it (documented migration). +- Evidence recorded by v0.3 lacks `specContext` hashes; freshness then + falls back to recorded approval timestamps (deterministic but coarser). - Workflow order cannot be inferred without sidecar state (reported as `unknown` — by design); the first approval of an existing Kiro spec infers it only when unambiguous. - Files that are not valid UTF-8 are read best-effort and never edited. -- The GitHub Action is a preview and needs specbridge installed in the workflow. +- The GitHub Action needs `fetch-depth: 0` and a checked-out `.kiro` + workspace; it is not yet published to a marketplace tag (use the + placeholder path until then). - Setext (`===` underline) headings are not recognized as section boundaries; the bytes are preserved regardless. @@ -402,12 +482,14 @@ SpecBridge stores no credentials of any kind. v0.1: read-only compatibility, doctor, listing, context, round-trip proof. v0.2: offline spec authoring, deterministic analysis, hash-based approvals, -stale-approval detection. v0.3 (this release): agent runner contract, the -Claude Code local runner, model-assisted generation/refinement, approved -task execution with git snapshots, trusted verification, append-only -evidence, verified-only checkbox completion, manual acceptance, and -resumable sessions. Next: sync + drift verification CLI (H), GitHub Action -gates (I), more runners, optional MCP server (K). +stale-approval detection. v0.3: agent runner contract, the Claude Code local +runner, model-assisted generation/refinement, approved task execution with +git snapshots, trusted verification, append-only evidence, verified-only +checkbox completion, manual acceptance, resumable sessions. v0.4 (this +release): deterministic drift verification (rule engine SBV001–SBV025, +policies, affected-spec resolution, evidence freshness, normalized task-plan +approval hash, four report formats) and the production GitHub Action. Next: +MCP server (K), more runners, `spec sync`/`spec export`, SARIF. Full detail: [docs/roadmap.md](docs/roadmap.md). ## Documentation @@ -426,7 +508,14 @@ Full detail: [docs/roadmap.md](docs/roadmap.md). [Task verification](docs/task-verification.md) · [Session resume](docs/session-resume.md) · [Security](docs/security.md) · -[Spec drift](docs/spec-drift.md) · +[Spec drift verification](docs/spec-drift-verification.md) · +[Verification rules](docs/verification-rules.md) · +[Verification policy](docs/verification-policy.md) · +[Traceability](docs/requirement-task-traceability.md) · +[Evidence freshness](docs/evidence-freshness.md) · +[Affected specs](docs/affected-spec-detection.md) · +[GitHub Action](docs/github-action.md) · +[CI quality gates](docs/ci-quality-gates.md) · [Claude Code integration](docs/claude-code-integration.md) · [Migration from Kiro](docs/migration-from-kiro.md) (spoiler: there is none) · [Roadmap](docs/roadmap.md) · diff --git a/docs/affected-spec-detection.md b/docs/affected-spec-detection.md new file mode 100644 index 0000000..4ba06fd --- /dev/null +++ b/docs/affected-spec-detection.md @@ -0,0 +1,58 @@ +# Affected-spec detection + +`specbridge spec affected` (and `spec verify --changed`) resolve which specs +a change set touches. The mapping is deterministic and read-only — no +verification rules run, no commands execute. + +## Signals + +A spec is affected when at least one changed file: + +1. lives under `.kiro/specs//` (spec files), +2. is the spec's sidecar state file + (`.specbridge/state/specs/.json`), +3. is the spec's verification policy + (`.specbridge/policies/.json`), +4. matches one of the policy's declared impact areas, +5. appears in accepted task evidence for the spec (`verified` or + `manually-accepted` records; freshness is judged later by the rules), or +6. is a file `design.md` explicitly references (backtick path or Markdown + link — see + [requirement-task-traceability.md](requirement-task-traceability.md)). + +Every match records *which* signal produced it: + +```text +Affected specs + +notification-preferences + matched: + src/notifications/preferences.ts + via impact area src/notifications/** +``` + +## Unmapped and ambiguous files + +- A changed source or test file that no spec claims is **unmapped**. In + `--changed`/`--all` verification it produces SBV014 (warning by default, + policy-configurable to error). It is never silently ignored. + Workflow/VCS infrastructure (`.kiro/**`, `.specbridge/**`, `.git/**`) is + exempt from the unmapped check — the protected-path and approval rules + govern those paths instead. +- A file claimed by more than one spec is **ambiguous**: every matching + spec is verified, and SBV022 reports the overlap with the matching + patterns per spec. + +Ordering is deterministic: specs sort by name, files by path. + +## Selection semantics + +| Command | Selection | +| --- | --- | +| `spec verify ` | exactly that spec | +| `spec verify --changed` | affected specs (signals above) | +| `spec verify --all` | every spec in the workspace | +| `spec affected` | mapping report only | + +In `--changed` mode, each spec's report records *why* it was selected +(`matchedBy`). diff --git a/docs/architecture.md b/docs/architecture.md index 9fb8e53..066f01c 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -12,7 +12,7 @@ instead of duplicating logic. | `@specbridge/core` | Shared types, errors, workspace detection, path-safety guards, atomic writes, hashing, versioned sidecar state (`.specbridge/`) | | `@specbridge/compat-kiro` | Everything `.kiro`: line-preserving Markdown model, steering loader, spec discovery/classification, tolerant parsers, round-trip writer, workspace analysis, agent-context assembly | | `@specbridge/workflow` | v0.2 authoring and approval engine: spec-name validation, offline templates, atomic spec creation, deterministic analyzers, workflow state machine, approval hashing + stale detection, sidecar audits | -| `@specbridge/drift` | Deterministic drift primitives: git-diff parsing, impact areas, requirement/task coverage, evidence storage, report assembly | +| `@specbridge/drift` | Deterministic drift verification (v0.4): git comparison resolution, spec policies, the SBV001–SBV025 rule engine, affected-spec resolution, trusted-command orchestration, schema-validated report assembly — plus the v0.1 primitives | | `@specbridge/runners` | Model/agent adapters behind one `AgentRunner` interface (mock implemented; CLI runners detection-only) | | `@specbridge/reporting` | Terminal formatting, JSON report envelope, self-contained HTML rendering | | `specbridge` (packages/cli) | Commander-based CLI wiring the above together | @@ -22,8 +22,9 @@ Dependency direction (arrows = "may import"): ``` cli ──▶ workflow ──▶ compat-kiro ──▶ core cli ──▶ reporting ──▶ core -drift ─▶ compat-kiro, core (cli wires drift in Phase H) -runners ─▶ core (cli wires runners in Phase F) +cli ──▶ drift ─▶ compat-kiro, core, workflow, evidence, runners +runners ─▶ core +integrations/github-action ─▶ drift, reporting, core (bundled; no CLI dependency) ``` ## Design principles diff --git a/docs/ci-quality-gates.md b/docs/ci-quality-gates.md new file mode 100644 index 0000000..5aedb2f --- /dev/null +++ b/docs/ci-quality-gates.md @@ -0,0 +1,67 @@ +# CI quality gates + +How to gate merges on deterministic spec verification — locally, in any CI +system, or with the bundled GitHub Action. + +## Exit-code contract (`spec verify`) + +| Code | Meaning | Typical CI reaction | +| --- | --- | --- | +| 0 | passed according to `--fail-on` | continue | +| 1 | diagnostics reached the failure threshold | fail the job | +| 2 | invalid input, invalid policy (SBV020), invalid state | fail and fix configuration | +| 3 | git comparison unavailable (SBV021) | fetch history (`fetch-depth: 0`) | +| 4 | required verification command failed to start | fix the command/tooling | +| 5 | required verification command timed out or was cancelled | raise the timeout or speed the command up | + +Codes 0–2 keep their v0.1 meanings; 3–5 refine the v0.3 runner codes for +verification. Other SpecBridge commands keep their documented contracts. + +## Thresholds + +`--fail-on error` (default) fails on errors only. `--fail-on warning` also +fails on warnings — useful for keeping traceability tight. `--fail-on never` +always exits 0/2/3/4/5 (setup problems still fail) and is meant for +report-only jobs. + +`--strict` applies strict-mode severities (e.g. SBV005 becomes an error) +without editing any policy file; per-spec `mode: strict` makes that +permanent in review-able configuration. + +## Generic CI (any provider) + +```sh +specbridge spec verify --changed \ + --diff "$BASE_SHA...$HEAD_SHA" \ + --run-verification \ + --format markdown --output verification.md +``` + +Publish `verification.md` (and `--format html` / `--json` variants) as build +artifacts. JSON reports validate against a versioned schema +(`schemaVersion 1.0.0`), so downstream tooling can consume them stably. + +## Local pre-push gate + +```sh +specbridge spec verify --changed --diff origin/main...HEAD +specbridge spec verify --working-tree # while iterating +specbridge spec verify --staged # what a commit would contain +``` + +Local runs execute only policy-required commands by default; add +`--run-verification` for the full battery or `--no-run-verification` to +reuse fresh evidence recorded at the current HEAD. + +## GitHub Action + +See [github-action.md](github-action.md) — same engine, event-based diff +resolution, Step Summary, bounded annotations, and report artifacts. + +## What a green gate means — and does not mean + +Green means: approvals match the current documents, checked tasks carry +valid fresh evidence, explicit traceability is intact, changes stay inside +declared impact areas, protected paths are untouched, and the trusted +commands passed. It does **not** mean the implementation semantically +satisfies every requirement — SpecBridge never claims that. diff --git a/docs/evidence-freshness.md b/docs/evidence-freshness.md new file mode 100644 index 0000000..589bdb4 --- /dev/null +++ b/docs/evidence-freshness.md @@ -0,0 +1,89 @@ +# Evidence freshness + +v0.3 evidence records prove what happened at the moment a task ran. Whether +a record still describes the repository *now* is decided at verification +time, deterministically. Model claims inside records (`runnerClaims`) are +audit data and are never consulted. + +## The task-plan hash, semantics v2 + +Approving `tasks.md` records two hashes in the sidecar state: + +```json +{ + "approvedHash": "", + "approvedPlanHash": "", + "hashAlgorithm": "sha256", + "hashSemanticsVersion": "2" +} +``` + +`approvedPlanHash` normalizes exactly one thing: the single state character +inside a recognized checkbox (`[ ]`, `[x]`, `[X]`, `[-]`, `[~]`) outside +code fences. Task text, numbering, indentation, requirement references, line +endings, and the BOM all stay byte-significant. Consequently: + +- `[ ]` → `[x]` progress keeps the task-plan approval effective +- editing task text, IDs, hierarchy, or references invalidates it +- requirements and design approvals remain exact-byte hashes — unchanged + +Sidecar state written before v0.4 has no `approvedPlanHash` and keeps +validating; it simply falls back to exact-byte semantics (v0.3 behavior) +until the next approval or sanctioned checkbox write records the new +fields. Nothing migrates silently. + +## What each evidence record captures (v0.4) + +New records carry a `specContext` (all fields optional, so v0.3 records +keep validating): + +```json +"specContext": { + "documentHash": "", + "designHash": "", + "tasksPlanHash": "", + "taskFingerprint": "", + "taskText": "" +} +``` + +The task fingerprint is checkbox-invariant: progress never changes it, +renaming or renumbering the task does. + +## Validation at verification time + +A record counts toward completion only when its status is `verified` or +`manually-accepted`. It is then bucketed: + +- **valid** — spec name matches; every recorded path stays inside the + repository; the recorded hashes equal the currently approved content + (plan hash for tasks); the task fingerprint matches the task as it exists + now; recorded commits are ancestors of HEAD where resolvable +- **stale** — any of those comparisons fails (SBV011 for evidence-side + drift: task identity, lineage, unapproved stages; SBV015 for spec-side + drift: approved content changed or was re-approved after the evidence) +- **invalid** — structural problems: wrong spec name, unparseable + timestamps, a `manually-accepted` status without its acceptance block, or + paths escaping the repository (SBV024) +- **missing** — no accepted record exists for a checked task (SBV004) + +Legacy v0.3 records without `specContext` are checked by recorded approval +timestamps instead: a stage (re)approved *after* the evidence was evaluated +makes it stale. This is deterministic — both timestamps are recorded data. + +Manual acceptance stays valid only while the spec stages it was recorded +against remain unchanged and the task identity still matches; reports label +it distinctly (`manuallyAccepted` in the evidence summary). + +## Evidence reuse for verification commands + +With `--no-run-verification`, a policy-required command may be satisfied by +recorded evidence only when **all** of these hold: + +1. the evidence record is valid and fresh (rules above), +2. the record shows that command passing, and +3. the record's `headAfter` commit is the exact current HEAD. + +Anything less runs the command or fails honestly (SBV012 explains that the +command did not run and nothing reusable covered it). Reused results are +labelled `reused-evidence` in every report. diff --git a/docs/github-action.md b/docs/github-action.md new file mode 100644 index 0000000..6386756 --- /dev/null +++ b/docs/github-action.md @@ -0,0 +1,118 @@ +# GitHub Action + +`integrations/github-action` is a production node20 action that runs the +same deterministic verification engine as `specbridge spec verify`. It is a +thin wrapper: no rule logic is reimplemented in the action. + +**Requires no model, no API key, no Claude installation, no pnpm, and no +network access.** The committed `dist/index.js` bundle contains everything; +CI rebuilds it and fails when it drifts from the source. + +## Setup + +```yaml +name: Verify specs + +on: + pull_request: + push: + branches: + - main + +jobs: + specbridge: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Verify spec alignment + id: specbridge + # Replace with the repository owner once published. + uses: /specbridge/integrations/github-action@v0.4 + with: + mode: changed + fail-on: error + strict: false + run-verification: true + + - name: Upload SpecBridge reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: specbridge-reports + path: .specbridge/action-reports +``` + +### Shallow checkouts + +`fetch-depth: 0` matters. The action **never fetches by itself**; when the +comparison base is missing from a shallow clone, the run fails with SBV021 +and this exact guidance. + +## Event diff resolution + +| Event | Base | Head | +| --- | --- | --- | +| `pull_request` / `pull_request_target` | PR base SHA | PR head SHA | +| `push` | `before` SHA | pushed SHA (`after`) | +| `workflow_dispatch` and anything else | `base-ref` input (required) | `head-ref` input or `HEAD` | + +The action never assumes `main` and never assumes the default branch exists +locally. A branch-creating push (`before` is the zero SHA) fails with +instructions to pass `base-ref` explicitly. Explicit `base-ref`/`head-ref` +inputs override every event. + +## Inputs + +| Input | Default | Notes | +| --- | --- | --- | +| `mode` | `changed` | `single`, `changed`, or `all` | +| `spec` | — | required when `mode: single`, rejected otherwise | +| `base-ref` / `head-ref` | — | explicit comparison refs | +| `fail-on` | `error` | `error`, `warning`, `never` | +| `strict` | `false` | strict severities for the run | +| `run-verification` | `true` | run trusted commands from `.specbridge/config.json` | +| `report-directory` | `.specbridge/action-reports` | workspace-relative; `..` rejected | +| `annotations` | `true` | file/line annotations | +| `write-step-summary` | `true` | Markdown report into the Step Summary | +| `annotation-limit` | `50` | 0–1000; excess findings are summarized | + +Every input is validated; invalid enum values fail with the accepted values +spelled out. + +## Outputs + +| Output | Content | +| --- | --- | +| `result` | `passed` or `failed` | +| `verification-id` | unique run id | +| `spec-count` | specs verified | +| `error-count` / `warning-count` / `info-count` | diagnostic totals | +| `json-report` / `markdown-report` / `html-report` | workspace-relative report paths | +| `affected-specs` | JSON array string of verified spec names | + +## Annotations + +Diagnostics with a repository file (and line where available) become +`error` / `warning` / `notice` annotations titled with the rule ID and +carrying the remediation. Errors get the budget first; past the +`annotation-limit`, one summary warning states how many findings were +suppressed — the report artifacts always contain everything. Paths outside +the repository are never annotated. + +## Step Summary + +A concise Markdown summary: pass/fail, comparison range, per-spec results +table, blocking issues with rule IDs, command outcomes, and report paths. +No raw command output and no environment data ever appear in it. + +## Failure behavior + +The step fails when the `fail-on` threshold is reached, a policy is invalid, +the comparison cannot be resolved, or a required command fails to start or +times out — always with the reason in the failure message. The action never +modifies tracked project files; its only writes are the reports. diff --git a/docs/requirement-task-traceability.md b/docs/requirement-task-traceability.md new file mode 100644 index 0000000..5fccfa2 --- /dev/null +++ b/docs/requirement-task-traceability.md @@ -0,0 +1,72 @@ +# Requirement–task traceability + +SpecBridge extracts explicit traceability relations from Kiro-compatible +Markdown without regenerating a single byte. Every extracted relation +records its source file, line, extraction method, and whether the +extraction is deterministic (explicit syntax) or heuristic (pattern +recognition). + +## Recognized requirement identifiers + +From `requirements.md` headings and acceptance criteria: + +- `### Requirement 1: Title` and `### R1: Title` (tolerant parser) +- `### REQ-001: Title` (supplemental ID headings) +- numbered acceptance criteria become `.` (e.g. `1.2`) +- explicit `AC-3:` markers at the start of a criterion line become aliases + +Identifiers are canonicalized case-insensitively: an optional `R`, `REQ`, +`AC`, `Requirement`, or `Criterion` prefix (with `-`, `_`, `.`, or space) is +stripped, `-` between numbers reads as `.`, and leading zeros drop — so +`REQ-001` ≡ `R1` ≡ `Requirement 1` ≡ `1`, and `AC1.2` ≡ `1.2`. Free text +like `TBD` is not an identifier. + +## Recognized task references + +From `tasks.md`, attributed to the owning task with source lines: + +| Form | Method | Confidence | +| --- | --- | --- | +| `_Requirements: 1.1, 2.3_` | `underscore-refs` | deterministic | +| `Requirements: R1, R2` | `refs-line` | deterministic | +| `[R1]`, `[REQ-001]` | `bracket-ref` | deterministic | +| `Supports REQ-001`, `Implements 1.2` | `keyword-ref` | heuristic | + +No single format is required; all forms coexist. Unknown references fire +SBV009 (keyword-recognized ones warn instead of erroring, because the +recognition itself is heuristic). + +## Design path references + +From `design.md`: backtick spans that look like repository paths +(`src/notifications/store.ts`) and Markdown links to repository files. +URLs, anchors, code fragments, absolute paths, traversal, and bare +filenames without a directory are ignored. Glob-shaped references +(`src/notifications/**`) are recorded as impact-area hints, not files. +SBV018 checks that explicit non-glob references exist. **No code ownership +is ever inferred from prose.** + +## What the rules do with this + +- SBV007 — a requirement no task references (directly or via a criterion) +- SBV008 — a leaf task without references while linking is in use + (documentation/release/cleanup chores excluded, heuristically) +- SBV009 — a reference to a requirement that does not exist +- SBV017 — test-required language (heuristic) without test evidence + +The per-spec report also carries the counts: + +```json +"traceability": { + "requirements": 5, + "requirementsWithTasks": 4, + "tasks": 9, + "tasksWithRequirements": 7 +} +``` + +## Honest limits + +Traceability here means *explicit links*. SpecBridge detects missing and +broken links deterministically; it does not — and does not claim to — +verify that linked code satisfies the linked requirement semantically. diff --git a/docs/roadmap.md b/docs/roadmap.md index de57e68..edc2b00 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -14,8 +14,8 @@ implemented unless marked ✅ and covered by tests. | E — Spec workflow | `spec new` (offline templates), `spec analyze` (deterministic), `spec approve` (hash-based sidecar approvals, stale detection, revocation), `spec status` | ✅ v0.2 | | F — Runner adapters | generic runner contract, registry, deterministic mock scenarios, Claude Code detection/capabilities/invocation, `runner list/doctor/show`, model-assisted `spec generate`/`spec refine` | ✅ v0.3 (Claude Code only; codex/ollama/openai-compatible stay honest stubs) | | G — Task execution | `spec run` (one task per run, `--all` sequential), git before/after snapshots, trusted verification commands, append-only evidence, verified-only checkbox completion, `spec accept-task`, `run list/show/resume` | ✅ v0.3 | -| H — Sync & drift verification | `spec sync`, `spec verify` CLI over the existing `@specbridge/drift` primitives, terminal/JSON/HTML reports, quality-gate exit codes | 🚧 planned — v0.4 candidate (library primitives ✅ since v0.1) | -| I — GitHub Action | drift gates on PRs, Markdown summaries, report artifacts (read-only preview action ships since v0.1) | 🚧 planned | +| H — Drift verification | `spec verify` (single/`--changed`/`--all`; diff/working-tree/staged), deterministic rule engine SBV001–SBV025, spec policies, affected-spec resolution, evidence freshness, normalized task-plan approval hash, terminal/JSON/Markdown/HTML reports, quality-gate exit codes, `spec affected`, `spec policy init/show/validate`, `verify rules/explain` | ✅ v0.4 (`spec sync` moved to v0.5) | +| I — GitHub Action | node20 bundled action: event diff resolution, validated inputs, ten outputs, bounded rule-ID annotations, Step Summary, report artifacts; no model, no pnpm required | ✅ v0.4 | | J — Claude Code skill | keep the shipped skill aligned with new commands | ✅ updated for v0.3 (thin CLI wrapper, no duplicated logic) | | K — MCP server | same core packages exposed as MCP tools; not before CLI + drift are stable | 🚧 planned, documented in `integrations/mcp-server/` | @@ -26,17 +26,23 @@ implemented unless marked ✅ and covered by tests. | `doctor`, `steering list/show`, `spec list/show/context`, `compat check` | ✅ v0.1 | | `spec new`, `spec analyze`, `spec approve`, `spec status` | ✅ v0.2 — fully offline | | `runner list/doctor/show`, `spec generate/refine`, `spec run`, `spec accept-task`, `run list/show/resume` | ✅ v0.3 — mock runner offline; Claude Code via your local installation | -| `spec sync/verify/export` | ❌ registered as "(planned)", exit 2 with an honest message | +| `spec verify`, `spec affected`, `spec policy init/show/validate`, `verify rules/explain` | ✅ v0.4 — deterministic, offline, read-only | +| `spec sync/export` | ❌ registered as "(planned)", exit 2 with an honest message | -## v0.4 candidates +## v0.5 candidates -- `spec verify` CLI + CI quality gates over the drift primitives (Phase H). -- GitHub Action drift gates (Phase I). -- Additional production runners (codex first) behind the same contract. -- Full spec-to-code drift analysis and cross-spec impact analysis. -- Optional MCP server (Phase K). -- Parallel task execution and worktree orchestration are explicitly **not** - planned until the sequential evidence model has real-world mileage. +- MCP server (Phase K) exposing the read-only inspection and verification + APIs as tools. +- Additional production runners (codex first) behind the existing contract. +- `spec sync` (evidence-aware checkbox reconciliation) and `spec export`. +- SARIF report output for code-scanning integrations (deliberately deferred + from v0.4). +- Optional PR-comment publishing from the GitHub Action (today: Step + Summary + artifacts only; the action never posts by itself). +- Cross-spec impact analysis heuristics — clearly labelled as heuristics. +- Parallel task execution and worktree orchestration remain explicitly + **not** planned until the sequential evidence model has real-world + mileage. ## Sequencing rule @@ -47,9 +53,13 @@ files is the one unrecoverable failure mode this project cannot have. ## Testing debt tracked openly -- GitHub Action smoke test in CI: not yet practical before the action can - install a released package; revisit at first npm publish. +- The GitHub Action is exercised process-level against fixture event + payloads in CI; an end-to-end `uses:` workflow test still needs a + published tag — revisit at first release. - Setext headings: preserved byte-for-byte but not recognized as section boundaries; add to the tolerant reader if real-world specs use them. - The Claude Code capability probe is validated against a fake CLI and one real-world version; broaden the matrix as new CLI versions appear. +- Commit-lineage checks (`merge-base --is-ancestor`) treat unresolvable + SHAs as `unknown` rather than stale; shallow local clones therefore skip + that one freshness signal (content hashes still apply). diff --git a/docs/security.md b/docs/security.md index fcd4368..e09194d 100644 --- a/docs/security.md +++ b/docs/security.md @@ -75,3 +75,43 @@ Failed commands, malformed output, permission denials, timeouts, and truncations are never hidden — every failure is reported with the exact reason and an actionable remediation, and the raw output stays on disk under `.specbridge/runs//`. + +## Verification safety (v0.4) + +`spec verify` and the GitHub Action add drift verification without adding +any write or execution surface: + +- **Read-only by principle.** Verification never edits `.kiro` files, never + marks task checkboxes, never alters approval state, and never touches + evidence. Its only writes are report artifacts (command logs plus + `report.json` under `.specbridge/reports//` when trusted + commands execute) and an explicitly requested `--output` file. A run with + neither writes nothing; tests hash the tree before and after to prove it. +- **Commands are trusted configuration only.** Verification commands come + exclusively from `verification.commands` in `.specbridge/config.json` — + argv arrays with timeouts and output limits. Spec policies may only + *name* configured commands; commands or shell fragments found in spec + text, source files, or model output are never executed. Shell strings are + rejected by the config schema. +- **Git is invoked defensively.** Refs are validated before use (no leading + `-`, no whitespace/glob/control characters — option injection is + impossible), git always runs as an argv array with timeouts and output + caps, `-z` output parsing keeps UTF-8 paths and spaces intact, and + SpecBridge never fetches, commits, or pushes. Diffs run `--relative` so a + nested workspace can never be judged against files outside its subtree. +- **Policies are data.** `.specbridge/policies/.json` is a versioned + Zod schema with validated globs: absolute paths, `..` traversal, null + bytes, backslashes, and malformed patterns are rejected. Invalid policies + fail closed (SBV020, exit 2, defaults applied). `.git/**` protection + cannot be disabled or downgraded by any configuration layer. +- **Evidence is checked before it is believed.** Recorded paths must stay + inside the repository (SBV024); recorded hashes and task fingerprints + must match the currently approved content; model-reported fields + (`runnerClaims`) are never treated as evidence. +- **Reports leak nothing.** HTML output escapes all dynamic content, loads + no external resources, and contains no scripts; Markdown summaries carry + no raw command output and no environment data; only bounded stderr tails + appear in diagnostics. +- **The GitHub Action needs no secrets.** No model, no API key, no network + access; it never modifies tracked files, and its bundle is rebuilt and + diffed in CI so the committed artifact provably matches the source. diff --git a/docs/spec-drift-verification.md b/docs/spec-drift-verification.md new file mode 100644 index 0000000..4dc91b0 --- /dev/null +++ b/docs/spec-drift-verification.md @@ -0,0 +1,117 @@ +# Spec drift verification + +Spec drift is the gap between what an approved spec says and what the +repository does. `specbridge spec verify` measures that gap +**deterministically**: plain data comparisons over the spec documents, the +sidecar approval state, the git comparison, recorded task evidence, and the +exit codes of trusted commands. No model is involved, no network access +happens, and results are reproducible byte for byte. + +```text +approved .kiro specs + + +git diff / working tree / staged changes + + +task execution evidence + + +trusted verification commands + + +spec verification policy + ↓ +deterministic drift diagnostics (SBV001–SBV025) + ↓ +terminal / JSON / Markdown / HTML reports + ↓ +local quality gate or GitHub Action result +``` + +## What deterministic verification can and cannot prove + +It **can** detect, with certainty: + +- approval drift: approved documents whose bytes changed (SBV002/SBV003) +- checked tasks without valid, fresh evidence (SBV004, SBV011, SBV015) +- explicit traceability gaps: unreferenced requirements, unlinked tasks, + references to requirements that do not exist (SBV007–SBV009) +- changes outside declared impact areas and protected-path modifications + (SBV005, SBV006, SBV014) +- failed, missing, or timed-out trusted verification commands + (SBV012, SBV013, SBV025) + +It **cannot** prove that code semantically implements a natural-language +requirement. SpecBridge never claims that. Findings based on pattern +recognition (test-required language, keyword references, chore-task +exclusion) are labelled `heuristic` and never default to error severity. + +## Commands + +```sh +specbridge spec verify # one spec (working tree default) +specbridge spec verify --changed # specs affected by the comparison +specbridge spec verify --all # every spec +specbridge spec affected # mapping only, no rules run +``` + +Comparison modes (mutually exclusive; default `--working-tree`): + +```sh +--diff origin/main...HEAD # revision range (also base..head) +--base [--head ] # explicit endpoints +--working-tree # staged + unstaged + untracked vs HEAD +--staged # staged changes vs HEAD +``` + +Options: `--run-verification` / `--no-run-verification`, `--policy `, +`--fail-on error|warning|never` (default `error`), `--strict`, `--json`, +`--format terminal|json|markdown|html`, `--output `, `--verbose`. + +`--strict` applies strict-mode rule severities for this run without touching +the stored policy files. + +Nested workspaces are supported: diffs run with `--relative`, so a `.kiro` +workspace inside a larger repository is compared within its own subtree. + +## Read-only guarantee + +`spec verify`, `spec affected`, `spec policy show|validate`, and +`verify rules|explain` never modify spec content, approval state, task +checkboxes, or evidence. The only writes are: + +- report artifacts under `.specbridge/reports//` (command + logs plus `report.json`) — created only when trusted commands execute +- the `--output` file you asked for +- policy files created by the explicit `spec policy init` + +A verification run with no command execution and no `--output` writes +nothing at all; tests assert this. + +## Reports + +- **terminal** — concise, glyph-based (`✓ ! ✗ ·`), honors `NO_COLOR` +- **json** — versioned schema (`schemaVersion 1.0.0`), validated with Zod + before it is written; diagnostics sorted deterministically +- **markdown** — ready for GitHub Step Summaries and PR comments +- **html** — one portable file: no scripts, no external requests, CSS-only + severity/spec filters, safe escaping throughout + +## Verification commands + +Trusted commands come only from `verification.commands` in +`.specbridge/config.json` (argv arrays; shell strings are rejected). Spec +policies may *require* configured commands by name — they can never +introduce a new command line. Defaults: + +- locally, only policy-required commands run; `--run-verification` runs + everything configured; `--no-run-verification` runs nothing and reuses a + passing result only from valid, fresh evidence recorded at the exact + current HEAD (the report labels reuse explicitly) +- the GitHub Action runs commands by default (`run-verification: true`) + +## Related documents + +- [verification-rules.md](verification-rules.md) — all rule IDs +- [verification-policy.md](verification-policy.md) — per-spec policies +- [requirement-task-traceability.md](requirement-task-traceability.md) +- [evidence-freshness.md](evidence-freshness.md) +- [affected-spec-detection.md](affected-spec-detection.md) +- [github-action.md](github-action.md) and [ci-quality-gates.md](ci-quality-gates.md) diff --git a/docs/spec-drift.md b/docs/spec-drift.md index 2206849..7e1a6d0 100644 --- a/docs/spec-drift.md +++ b/docs/spec-drift.md @@ -1,86 +1,20 @@ -# Spec drift verification - -Spec drift is the gap between what the spec says and what the code does. -SpecBridge's drift verifier is **deterministic** — plain data comparisons -over the spec, the git diff, and recorded evidence. No LLM is involved, so -results are reproducible and CI-safe. - -## Status - -| Piece | Status | -| --- | --- | -| Deterministic primitives (`@specbridge/drift`) | ✅ Implemented and tested in v0.1 | -| `specbridge spec verify` CLI + git wiring | 🚧 Phase H | -| Terminal / JSON / HTML drift reports | 🚧 Phase H (HTML renderer already exists in `@specbridge/reporting`) | -| GitHub Action drift gate | 🚧 Phase I | - -The primitives shipping today: `parseNameStatus` / `collectChangedFiles` -(git diffs), `evaluateImpactAreas` (glob-based impact areas), -`assessRequirementCoverage`, `assessTaskCoverage`, evidence storage, and -`buildDriftReport` / `driftExitCode`. See `tests/drift/` for executable -specifications. - -## Planned CLI - -```sh -specbridge spec verify --diff origin/main...HEAD -specbridge spec verify --changed # specs affected by the current diff -specbridge spec verify --all -specbridge spec verify --working-tree -``` - -Exit codes: `0` passed · `1` drift or quality-gate failure · `2` invalid -configuration or runtime error. - -## Checks - -Inputs: requirements/bugfix + design + tasks documents, sidecar metadata -(`declaredImpactAreas`, `verificationCommands`), the git diff, and task -evidence. Detections, by category: - -1. Tasks marked complete without evidence (`task-evidence`, fail) -2. Required tests with no test evidence (`test-evidence`, fail) -3. Changed files outside declared impact areas (`impact-area`, fail) -4. Acceptance criteria no task references (`requirement-coverage`, warn) -5. Tasks not linked to requirements where linking is in use (`task-linking`, info) -6. Required files missing (`required-files`) -7. Invalid or inconsistent checkbox state (`checkbox-state`) -8. Spec changed after implementation without re-verification -9. Design-declared components with no implementation evidence -10. Failed verification commands (`verification-command`, fail) - -Checks 1–5 and 7 exist as library functions today; 6 and 8–10 are designed -but not yet implemented anywhere (they are listed here for the record, not -claimed). - -## Report shape - -``` -Spec Drift Report - -Spec: notification-preferences -Diff: origin/main...HEAD - -Requirements: -✓ 1.1 referenced by task 1 -✗ 2.1 has no test evidence - -Impact areas: -✗ src/billing/BillingService.ts changed outside declared impact areas - -Tasks: -✓ 6 verified -! 2 implemented but unverified -✗ 1 marked complete without evidence - -Result: FAILED -``` - -The same data will be emitted as JSON (`specbridge.drift/1` envelope) and as -a self-contained HTML file under `.specbridge/reports/`. - -## Why deterministic first - -A quality gate that can hallucinate is worse than no gate. The MVP verifier -only asserts things it can prove from files, diffs, and exit codes. A future -optional LLM layer may *explain* drift, but will never decide pass/fail. +# Spec drift verification (moved) + +The v0.1 design notes that lived here became reality in v0.4. The canonical +documentation is now: + +- [spec-drift-verification.md](spec-drift-verification.md) — concepts, + commands, comparison modes, read-only guarantee, report formats +- [verification-rules.md](verification-rules.md) — the stable rule IDs + SBV001–SBV025 +- [verification-policy.md](verification-policy.md) — per-spec policies +- [evidence-freshness.md](evidence-freshness.md) — evidence validation and + the normalized task-plan approval hash +- [affected-spec-detection.md](affected-spec-detection.md) — `--changed` + resolution +- [github-action.md](github-action.md) and + [ci-quality-gates.md](ci-quality-gates.md) — CI integration + +The v0.1 library primitives (`parseNameStatus`, `evaluateImpactAreas`, +`assessRequirementCoverage`, `assessTaskCoverage`, `buildDriftReport`) +remain exported from `@specbridge/drift` unchanged. diff --git a/docs/verification-policy.md b/docs/verification-policy.md new file mode 100644 index 0000000..f436a3b --- /dev/null +++ b/docs/verification-policy.md @@ -0,0 +1,97 @@ +# Verification policy + +A verification policy tunes `spec verify` for one spec. It is plain, +versioned configuration under: + +```text +.specbridge/policies/.json +``` + +A policy is **not** a spec stage: it needs no approval, and `spec policy +init` never approves anything. Verification works without any policy file — +secure built-in defaults apply. + +## Schema (1.0.0) + +```json +{ + "schemaVersion": "1.0.0", + "specName": "notification-preferences", + "mode": "advisory", + "impactAreas": [ + "src/notifications/**", + "tests/notifications/**" + ], + "protectedPaths": [ + "infra/terraform/**" + ], + "requiredVerificationCommands": [ + "test", + "typecheck" + ], + "requireVerifiedTaskEvidence": true, + "requireRequirementTaskLinks": false, + "requireTestEvidence": true, + "rules": { + "SBV005": { "enabled": true, "severity": "error" }, + "SBV014": { "enabled": true, "severity": "error" } + } +} +``` + +- `mode` — `advisory` (uncertain mapping issues warn; deterministic + correctness violations still error) or `strict` (outside-impact changes + fail; SBV005 becomes an error). +- `impactAreas` — glob patterns describing where this spec's implementation + may land. No declaration means no impact-area constraint. +- `protectedPaths` — additional protected globs on top of the built-ins + (`.kiro/**`, `.specbridge/state/**`, `.specbridge/config.json`, + `.git/**`). `.git/**` protection can never be removed or downgraded. +- `requiredVerificationCommands` — names of commands from + `.specbridge/config.json` that must pass. A policy can only *name* + configured commands, never define command lines (SBV013 fires when the + name is not configured). +- `requireVerifiedTaskEvidence` — raises SBV004 to error. +- `requireRequirementTaskLinks` — raises SBV007 to error. +- `requireTestEvidence` — raises SBV017 to error. +- `rules` — per-rule `enabled` / `severity` overrides. + +## Glob validation + +Patterns are matched with [picomatch](https://github.com/micromatch/picomatch) +(`dot: true`) against workspace-relative POSIX paths. Rejected outright: + +- absolute paths (`/etc/**`, `C:/…`) +- `..` traversal segments +- null bytes and backslashes +- syntactically invalid globs +- patterns longer than 512 characters + +Symlinks that resolve outside the repository are flagged during comparison +and never followed for content. + +## Precedence + +1. secure built-in defaults (protected paths above) +2. global project configuration (`.specbridge/config.json` — + `execution.protectedPaths`, `verification.commands`) +3. the per-spec policy file +4. explicit CLI flags — `--strict` tightens the mode for the run and never + loosens anything; it does not rewrite the policy file + +An invalid policy file is fail-closed: verification reports SBV020, runs +with defaults, and exits 2. + +## Commands + +```sh +specbridge spec policy init [--mode advisory|strict] [--dry-run] [--json] +specbridge spec policy show [--json] +specbridge spec policy validate [--json] +``` + +`policy init` proposes impact areas from explicit `design.md` path +references and recorded task evidence. The proposals are **hints for +review**, never authoritative facts, and `init` never overwrites an existing +policy. `validate` exits 0 when valid, 1 when invalid (including required +command names that are not configured), and 2 when no policy file exists. diff --git a/docs/verification-rules.md b/docs/verification-rules.md new file mode 100644 index 0000000..10a941f --- /dev/null +++ b/docs/verification-rules.md @@ -0,0 +1,89 @@ +# Verification rules + +Stable rule IDs for `specbridge spec verify`. IDs are never silently +renumbered; removing a rule would leave a documented gap. Inspect them at any +time with `specbridge verify rules` and `specbridge verify explain `. + +Severities: `error`, `warning`, `info`. Confidence: **deterministic** rules +follow from file bytes, hashes, git output, and exit codes; **heuristic** +rules use pattern recognition and never default to error. Policies may +override severity or disable rules per spec (`rules.SBVxxx` in the policy +file) — except that `.git/**` protection under SBV006 always stays an error. + +| ID | Title | Category | Default severity | Confidence | +| --- | --- | --- | --- | --- | +| SBV001 | Required spec file missing | workspace | error | deterministic | +| SBV002 | Spec approval stale | approval | error | deterministic | +| SBV003 | Approval prerequisite invalid | approval | error | deterministic | +| SBV004 | Completed task lacks verified evidence | evidence | warning (error when policy requires evidence) | deterministic | +| SBV005 | Changed file outside declared impact area | impact-area | warning advisory / error strict | deterministic | +| SBV006 | Protected path modified | protected-path | error | deterministic | +| SBV007 | Requirement has no implementation task | requirements | warning (error when policy requires links) | deterministic | +| SBV008 | Task has no requirement reference | tasks | warning | heuristic | +| SBV009 | Task references unknown requirement | tasks | error (warning for keyword-recognized refs) | deterministic | +| SBV010 | Completed parent task has incomplete child task | tasks | error | deterministic | +| SBV011 | Task evidence is stale | evidence | error | deterministic | +| SBV012 | Required verification command failed | verification-command | error | deterministic | +| SBV013 | Required verification command missing | verification-command | error | deterministic | +| SBV014 | Unmapped changed file | mapping | warning (configurable to error) | deterministic | +| SBV015 | Spec changed after implementation evidence | evidence | error | deterministic | +| SBV016 | Task marked complete before task-plan approval | approval | error | deterministic | +| SBV017 | No test evidence for test-required task | evidence | warning (error when policy requires test evidence) | heuristic | +| SBV018 | Design path reference does not exist | design | warning | deterministic | +| SBV019 | Changed file not represented in execution evidence | evidence | warning | deterministic | +| SBV020 | Verification policy invalid | workspace | error | deterministic | +| SBV021 | Diff base unavailable | git | error | deterministic | +| SBV022 | Ambiguous affected-spec mapping | mapping | warning | deterministic | +| SBV023 | Tasks document unexpectedly changed | tasks | error | deterministic | +| SBV024 | Evidence points outside repository | evidence | error | deterministic | +| SBV025 | Verification command timed out | verification-command | error (warning for optional commands) | deterministic | + +## Rule notes + +- **SBV001** — feature specs need `requirements.md`, `design.md`, `tasks.md`; + bugfix specs need `bugfix.md`, `design.md`, `tasks.md`. Specs whose type + cannot be classified are not judged. +- **SBV002** — exact-byte hash comparison for requirements/bugfix/design. + For the task plan, checkbox-only progress is *not* stale (hash semantics + v2, see [evidence-freshness.md](evidence-freshness.md)); any other byte + change is. +- **SBV004** — stale evidence is reported by SBV011/SBV015 instead; + structurally invalid records count as absent here. +- **SBV005** — evaluated for single-spec verification only. In `--changed` / + `--all` runs, cross-spec coverage questions are answered by SBV014. +- **SBV006** — the verified specs' own spec files, sidecar state, and policy + file are exempt (changing them is spec authoring, governed by the approval + rules) and reported as info; checkbox-only `tasks.md` progress is always + expected. Everything else protected errors. Policies may downgrade + non-`.git` findings; `.git/**` stays an error unconditionally. +- **SBV008** — only fires when the tasks document uses requirement linking + at all; clearly non-requirement chores (documentation, release, cleanup) + are excluded. Heuristic by nature. +- **SBV009** — references recognized deterministically (underscore form, + `Requirements:` lines, `[R1]` brackets) error; keyword-phrase references + (`Supports REQ-001`) are heuristic and warn. +- **SBV011 vs SBV015** — SBV011 fires when the *evidence* no longer matches + (task identity changed, commit lineage diverged, a referenced stage is no + longer approved). SBV015 fires when the *spec* moved after the evidence + (approved requirements/design/task-plan content changed or was re-approved + later). +- **SBV016** — managed specs only; existing Kiro projects without SpecBridge + approvals are not judged. +- **SBV017** — test-required detection (task text or referenced requirement + mentioning tests) is heuristic; the rule checks valid evidence for a + passing test-ish command or changed test files. +- **SBV021** — carries the `actions/checkout fetch-depth: 0` guidance when + the clone is shallow. SpecBridge never fetches by itself. +- **SBV023** — compares the checkbox-normalized task plan at the comparison + base against the current file; managed specs only. + +## Exit codes (`spec verify`) + +| Code | Meaning | +| --- | --- | +| 0 | Passed according to `--fail-on` | +| 1 | Diagnostics reached the failure threshold | +| 2 | Invalid input, invalid policy (SBV020), or invalid state | +| 3 | Required git comparison unavailable (SBV021) | +| 4 | Required verification command failed to start | +| 5 | Required verification command timed out or was cancelled | diff --git a/eslint.config.js b/eslint.config.js index bed5599..7ece54f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,7 +8,8 @@ export default tseslint.config( '**/node_modules/**', 'tests/fixtures/**', 'examples/**', - 'integrations/**', + 'integrations/claude-code/**', + 'integrations/mcp-server/**', ], }, js.configs.recommended, diff --git a/integrations/claude-code/skills/specbridge/SKILL.md b/integrations/claude-code/skills/specbridge/SKILL.md index ed551a6..f9038e2 100644 --- a/integrations/claude-code/skills/specbridge/SKILL.md +++ b/integrations/claude-code/skills/specbridge/SKILL.md @@ -74,9 +74,16 @@ Runner-assisted (v0.3): `spec generate`, `spec refine`, `spec run`, requires every stage approved and a clean working tree (or an explicit `--allow-dirty`). -Still planned (exit 2 honestly): `spec sync`, `spec verify`, `spec export` — -if the user asks for them, do the nearest read-only equivalent manually and -say that is what you did. Never claim a planned command ran. +Drift verification (v0.4, read-only, offline): `spec verify ` / +`spec verify --changed` / `spec verify --all` with `--diff base...head`, +`--working-tree`, or `--staged`; `spec affected`; `spec policy +init/show/validate`; `verify rules` / `verify explain `. All support +`--json`. Verification never edits .kiro files, checkboxes, approvals, or +evidence — report findings, never "fix" them by editing state. + +Still planned (exit 2 honestly): `spec sync`, `spec export` — if the user +asks for them, do the nearest read-only equivalent manually and say that is +what you did. Never claim a planned command ran. Reference guides in this skill: diff --git a/integrations/github-action/README.md b/integrations/github-action/README.md index 9ce20ca..169479d 100644 --- a/integrations/github-action/README.md +++ b/integrations/github-action/README.md @@ -1,61 +1,110 @@ -# SpecBridge GitHub Action (preview) +# SpecBridge GitHub Action -Runs the read-only gates that exist in SpecBridge v0.1 on every PR: +Deterministic spec drift verification for Kiro-style specs on every pull +request or push: -- `specbridge doctor` — the `.kiro` workspace is healthy (exit 1 otherwise) -- `specbridge compat check` — every spec and steering file round-trips - byte-identically (exit 1 otherwise) +- approval drift (`SBV002`, `SBV003`) and stale/missing task evidence + (`SBV004`, `SBV011`, `SBV015`) +- requirement-to-task traceability gaps (`SBV007`–`SBV010`) +- changes outside declared impact areas and protected-path modifications + (`SBV005`, `SBV006`, `SBV014`) +- trusted verification commands from `.specbridge/config.json` + (`SBV012`, `SBV013`, `SBV025`) -Neither step needs a model, an API key, or network access beyond installing -the CLI. +**No model, no API key, no Claude installation, no network access.** The +action is a bundled node20 wrapper around the same `@specbridge/drift` +engine the CLI uses — no rule logic is reimplemented here. It never modifies +tracked project files; its only writes are the generated reports. -## Status: preview +## Usage -- **Requires the specbridge CLI to be runnable.** The default - (`npx --yes specbridge`) works once specbridge is published to npm. Until - then, build from source in a prior step and set `specbridge-command`. -- **Drift verification is not part of this action yet.** The planned inputs - below become real in the drift phase (Phase H/I); they are documented so - workflows can be sketched, not because they work today. +```yaml +name: Verify specs -## Usage (today) +on: + pull_request: + push: + branches: + - main -```yaml -- uses: actions/checkout@v4 +jobs: + specbridge: + runs-on: ubuntu-latest -- name: Verify .kiro spec compatibility - uses: /specbridge/integrations/github-action@v0.1 - with: - working-directory: . - # spec: user-authentication # optional: limit to one spec -``` + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + # Full history: the action never fetches by itself, and the diff + # base of a PR usually lies outside a shallow clone. + fetch-depth: 0 -Building from source until the npm release: + - name: Verify spec alignment + id: specbridge + # Replace with the repository owner once published. + uses: /specbridge/integrations/github-action@v0.4 + with: + mode: changed + fail-on: error + strict: false + run-verification: true -```yaml -- uses: actions/checkout@v4 - with: { repository: /specbridge, path: .specbridge-src } -- run: cd .specbridge-src && corepack enable && pnpm install --frozen-lockfile && pnpm build -- uses: /specbridge/integrations/github-action@v0.1 - with: - specbridge-command: node ${{ github.workspace }}/.specbridge-src/packages/cli/dist/index.js + - name: Upload SpecBridge reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: specbridge-reports + path: .specbridge/action-reports ``` -## Planned (Phase H/I — not implemented) +## Diff resolution per event -```yaml -- name: Verify spec alignment - uses: /specbridge/integrations/github-action@v1 - with: - spec: notification-preferences - diff: origin/main...HEAD - fail-on-drift: true -``` +| Event | Base | Head | +| --- | --- | --- | +| `pull_request` / `pull_request_target` | PR base SHA | PR head SHA | +| `push` | `before` SHA | pushed SHA | +| `workflow_dispatch` and others | `base-ref` input (required) | `head-ref` input or `HEAD` | + +The action never assumes `main`, never assumes the default branch exists +locally, and never fetches. When history is missing (shallow clone), the run +fails with `SBV021` and the `fetch-depth: 0` guidance above. + +## Inputs -The drift-phase action will detect changed specs, run the deterministic -verifier, write a Markdown job summary, optionally upload HTML/JSON reports, -and fail the PR on configured quality gates — still with no model required. -Equivalent CLI: `npx specbridge spec verify --changed --fail-on-drift`. +| Input | Default | Description | +| --- | --- | --- | +| `mode` | `changed` | `single`, `changed`, or `all` | +| `spec` | — | Spec name; required when `mode: single` | +| `base-ref` / `head-ref` | — | Explicit comparison refs (override the event) | +| `fail-on` | `error` | `error`, `warning`, or `never` | +| `strict` | `false` | Strict verification behavior (tightens policies) | +| `run-verification` | `true` | Run trusted commands from `.specbridge/config.json` | +| `report-directory` | `.specbridge/action-reports` | Where reports are written | +| `annotations` | `true` | Emit file/line annotations | +| `write-step-summary` | `true` | Write the Markdown report to the Step Summary | +| `annotation-limit` | `50` | Maximum annotations (0–1000); the rest is summarized | + +## Outputs + +`result`, `verification-id`, `spec-count`, `error-count`, `warning-count`, +`info-count`, `json-report`, `markdown-report`, `html-report` (paths relative +to the workspace), and `affected-specs` (a JSON array string). + +## Exit behavior + +The step fails when the `fail-on` threshold is reached, when a policy is +invalid, when the git comparison cannot be resolved, or when a required +verification command fails to start or times out. The Step Summary and the +report artifacts always explain why. + +## Building (maintainers) + +`dist/index.js` is a committed, reproducible bundle: + +```sh +pnpm --filter specbridge-github-action build +git diff --exit-code integrations/github-action/dist +``` -Exit codes across all SpecBridge gates: `0` pass · `1` drift/quality-gate -failure · `2` configuration or runtime error. +CI rebuilds the bundle and fails when the committed file drifts from the +source. diff --git a/integrations/github-action/action.yml b/integrations/github-action/action.yml index 25487c3..ee0206b 100644 --- a/integrations/github-action/action.yml +++ b/integrations/github-action/action.yml @@ -1,39 +1,86 @@ -name: SpecBridge Compatibility Check +name: SpecBridge Spec Drift Verification description: >- - Read-only quality gate for Kiro-style specs: verifies the .kiro workspace is - healthy and every spec/steering file round-trips byte-identically. - PREVIEW: drift verification (spec verify) joins this action in a later - SpecBridge phase. Requires the specbridge CLI to be runnable (see README). + Deterministic spec-to-code drift verification for Kiro-style specs: + approval drift, requirement-task traceability, task evidence freshness, + impact areas, protected paths, and trusted verification commands. + No model, no API key, no network access required. branding: icon: check-circle color: blue inputs: - working-directory: - description: Directory containing the .kiro workspace. + mode: + description: 'Spec selection: "single", "changed" (specs affected by the diff), or "all".' required: false - default: '.' - specbridge-command: + default: changed + spec: + description: Spec name to verify. Required when mode is "single". + required: false + default: '' + base-ref: description: >- - How to invoke the specbridge CLI. Once specbridge is published to npm - the default works as-is; until then point this at a built checkout, - e.g. "node /path/to/specbridge/packages/cli/dist/index.js". + Explicit base git ref. Overrides event-based resolution; required for + workflow_dispatch and other events without a comparison range. required: false - default: 'npx --yes specbridge' - spec: - description: Limit the compat check to one spec name (default checks everything). + default: '' + head-ref: + description: Explicit head git ref (defaults to HEAD when base-ref is set). required: false default: '' + fail-on: + description: 'Failure threshold: "error", "warning", or "never".' + required: false + default: error + strict: + description: Enable strict verification behavior (tightens, never loosens, spec policies). + required: false + default: 'false' + run-verification: + description: >- + Run the trusted verification commands configured in + .specbridge/config.json. When "false", only valid recorded evidence at + the exact current commit can satisfy policy-required commands. + required: false + default: 'true' + report-directory: + description: Directory (workspace-relative) for the generated JSON/Markdown/HTML reports. + required: false + default: .specbridge/action-reports + annotations: + description: Emit GitHub file/line annotations for findings. + required: false + default: 'true' + write-step-summary: + description: Write the Markdown report to the GitHub Step Summary. + required: false + default: 'true' + annotation-limit: + description: Maximum number of annotations to emit (0–1000). + required: false + default: '50' -runs: - using: composite - steps: - - name: SpecBridge doctor (read-only) - shell: bash - working-directory: ${{ inputs.working-directory }} - run: ${{ inputs.specbridge-command }} doctor +outputs: + result: + description: '"passed" or "failed".' + verification-id: + description: Unique id of this verification run. + spec-count: + description: Number of specs verified. + error-count: + description: Total error-severity findings. + warning-count: + description: Total warning-severity findings. + info-count: + description: Total info-severity findings. + json-report: + description: Workspace-relative path of the JSON report. + markdown-report: + description: Workspace-relative path of the Markdown report. + html-report: + description: Workspace-relative path of the self-contained HTML report. + affected-specs: + description: JSON array string of the verified spec names. - - name: Round-trip compatibility check - shell: bash - working-directory: ${{ inputs.working-directory }} - run: ${{ inputs.specbridge-command }} compat check ${{ inputs.spec }} +runs: + using: node20 + main: dist/index.js diff --git a/integrations/github-action/dist/index.js b/integrations/github-action/dist/index.js new file mode 100644 index 0000000..13c0bf2 --- /dev/null +++ b/integrations/github-action/dist/index.js @@ -0,0 +1,45604 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/utils.js +var require_utils = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/utils.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.toCommandProperties = exports2.toCommandValue = void 0; + function toCommandValue(input) { + if (input === null || input === void 0) { + return ""; + } else if (typeof input === "string" || input instanceof String) { + return input; + } + return JSON.stringify(input); + } + exports2.toCommandValue = toCommandValue; + function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; + } + exports2.toCommandProperties = toCommandProperties; + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/command.js +var require_command = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/command.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.issue = exports2.issueCommand = void 0; + var os = __importStar(require("os")); + var utils_1 = require_utils(); + function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); + } + exports2.issueCommand = issueCommand; + function issue(name, message = "") { + issueCommand(name, {}, message); + } + exports2.issue = issue; + var CMD_STRING = "::"; + var Command = class { + constructor(command, properties, message) { + if (!command) { + command = "missing.command"; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += " "; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } else { + cmdStr += ","; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } + }; + function escapeData(s) { + return (0, utils_1.toCommandValue)(s).replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A"); + } + function escapeProperty(s) { + return (0, utils_1.toCommandValue)(s).replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C"); + } + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/file-command.js +var require_file_command = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/file-command.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.prepareKeyValueMessage = exports2.issueFileCommand = void 0; + var crypto = __importStar(require("crypto")); + var fs = __importStar(require("fs")); + var os = __importStar(require("os")); + var utils_1 = require_utils(); + function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os.EOL}`, { + encoding: "utf8" + }); + } + exports2.issueFileCommand = issueFileCommand; + function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${crypto.randomUUID()}`; + const convertedValue = (0, utils_1.toCommandValue)(value); + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; + } + exports2.prepareKeyValueMessage = prepareKeyValueMessage; + } +}); + +// ../../node_modules/.pnpm/@actions+http-client@2.2.3/node_modules/@actions/http-client/lib/proxy.js +var require_proxy = __commonJS({ + "../../node_modules/.pnpm/@actions+http-client@2.2.3/node_modules/@actions/http-client/lib/proxy.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.checkBypass = exports2.getProxyUrl = void 0; + function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === "https:"; + if (checkBypass(reqUrl)) { + return void 0; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env["https_proxy"] || process.env["HTTPS_PROXY"]; + } else { + return process.env["http_proxy"] || process.env["HTTP_PROXY"]; + } + })(); + if (proxyVar) { + try { + return new DecodedURL(proxyVar); + } catch (_a) { + if (!proxyVar.startsWith("http://") && !proxyVar.startsWith("https://")) + return new DecodedURL(`http://${proxyVar}`); + } + } else { + return void 0; + } + } + exports2.getProxyUrl = getProxyUrl; + function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env["no_proxy"] || process.env["NO_PROXY"] || ""; + if (!noProxy) { + return false; + } + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } else if (reqUrl.protocol === "http:") { + reqPort = 80; + } else if (reqUrl.protocol === "https:") { + reqPort = 443; + } + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === "number") { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + for (const upperNoProxyItem of noProxy.split(",").map((x) => x.trim().toUpperCase()).filter((x) => x)) { + if (upperNoProxyItem === "*" || upperReqHosts.some((x) => x === upperNoProxyItem || x.endsWith(`.${upperNoProxyItem}`) || upperNoProxyItem.startsWith(".") && x.endsWith(`${upperNoProxyItem}`))) { + return true; + } + } + return false; + } + exports2.checkBypass = checkBypass; + function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return hostLower === "localhost" || hostLower.startsWith("127.") || hostLower.startsWith("[::1]") || hostLower.startsWith("[0:0:0:0:0:0:0:1]"); + } + var DecodedURL = class extends URL { + constructor(url, base) { + super(url, base); + this._decodedUsername = decodeURIComponent(super.username); + this._decodedPassword = decodeURIComponent(super.password); + } + get username() { + return this._decodedUsername; + } + get password() { + return this._decodedPassword; + } + }; + } +}); + +// ../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/lib/tunnel.js +var require_tunnel = __commonJS({ + "../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/lib/tunnel.js"(exports2) { + "use strict"; + var net = require("net"); + var tls = require("tls"); + var http = require("http"); + var https = require("https"); + var events = require("events"); + var assert = require("assert"); + var util2 = require("util"); + exports2.httpOverHttp = httpOverHttp; + exports2.httpsOverHttp = httpsOverHttp; + exports2.httpOverHttps = httpOverHttps; + exports2.httpsOverHttps = httpsOverHttps; + function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; + } + function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; + } + function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; + } + function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; + } + function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + self.on("free", function onFree(socket, host, port, localAddress) { + var options2 = toOptions(host, port, localAddress); + for (var i2 = 0, len = self.requests.length; i2 < len; ++i2) { + var pending = self.requests[i2]; + if (pending.host === options2.host && pending.port === options2.port) { + self.requests.splice(i2, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); + } + util2.inherits(TunnelingAgent, events.EventEmitter); + TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions2({ request: req }, self.options, toOptions(host, port, localAddress)); + if (self.sockets.length >= this.maxSockets) { + self.requests.push(options); + return; + } + self.createSocket(options, function(socket) { + socket.on("free", onFree); + socket.on("close", onCloseOrRemove); + socket.on("agentRemove", onCloseOrRemove); + req.onSocket(socket); + function onFree() { + self.emit("free", socket, options); + } + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener("free", onFree); + socket.removeListener("close", onCloseOrRemove); + socket.removeListener("agentRemove", onCloseOrRemove); + } + }); + }; + TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + var connectOptions = mergeOptions2({}, self.proxyOptions, { + method: "CONNECT", + path: options.host + ":" + options.port, + agent: false, + headers: { + host: options.host + ":" + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers["Proxy-Authorization"] = "Basic " + new Buffer(connectOptions.proxyAuth).toString("base64"); + } + debug("making CONNECT request"); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; + connectReq.once("response", onResponse); + connectReq.once("upgrade", onUpgrade); + connectReq.once("connect", onConnect); + connectReq.once("error", onError); + connectReq.end(); + function onResponse(res) { + res.upgrade = true; + } + function onUpgrade(res, socket, head) { + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + if (res.statusCode !== 200) { + debug( + "tunneling socket could not be established, statusCode=%d", + res.statusCode + ); + socket.destroy(); + var error = new Error("tunneling socket could not be established, statusCode=" + res.statusCode); + error.code = "ECONNRESET"; + options.request.emit("error", error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug("got illegal response body from proxy"); + socket.destroy(); + var error = new Error("got illegal response body from proxy"); + error.code = "ECONNRESET"; + options.request.emit("error", error); + self.removeSocket(placeholder); + return; + } + debug("tunneling connection has established"); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + function onError(cause) { + connectReq.removeAllListeners(); + debug( + "tunneling socket could not be established, cause=%s\n", + cause.message, + cause.stack + ); + var error = new Error("tunneling socket could not be established, cause=" + cause.message); + error.code = "ECONNRESET"; + options.request.emit("error", error); + self.removeSocket(placeholder); + } + }; + TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket); + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + var pending = this.requests.shift(); + if (pending) { + this.createSocket(pending, function(socket2) { + pending.request.onSocket(socket2); + }); + } + }; + function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader("host"); + var tlsOptions = mergeOptions2({}, self.options, { + socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, "") : options.host + }); + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); + } + function toOptions(host, port, localAddress) { + if (typeof host === "string") { + return { + host, + port, + localAddress + }; + } + return host; + } + function mergeOptions2(target) { + for (var i2 = 1, len = arguments.length; i2 < len; ++i2) { + var overrides = arguments[i2]; + if (typeof overrides === "object") { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== void 0) { + target[k] = overrides[k]; + } + } + } + } + return target; + } + var debug; + if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === "string") { + args[0] = "TUNNEL: " + args[0]; + } else { + args.unshift("TUNNEL:"); + } + console.error.apply(console, args); + }; + } else { + debug = function() { + }; + } + exports2.debug = debug; + } +}); + +// ../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/index.js +var require_tunnel2 = __commonJS({ + "../../node_modules/.pnpm/tunnel@0.0.6/node_modules/tunnel/index.js"(exports2, module2) { + "use strict"; + module2.exports = require_tunnel(); + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/symbols.js +var require_symbols = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kClose: /* @__PURE__ */ Symbol("close"), + kDestroy: /* @__PURE__ */ Symbol("destroy"), + kDispatch: /* @__PURE__ */ Symbol("dispatch"), + kUrl: /* @__PURE__ */ Symbol("url"), + kWriting: /* @__PURE__ */ Symbol("writing"), + kResuming: /* @__PURE__ */ Symbol("resuming"), + kQueue: /* @__PURE__ */ Symbol("queue"), + kConnect: /* @__PURE__ */ Symbol("connect"), + kConnecting: /* @__PURE__ */ Symbol("connecting"), + kHeadersList: /* @__PURE__ */ Symbol("headers list"), + kKeepAliveDefaultTimeout: /* @__PURE__ */ Symbol("default keep alive timeout"), + kKeepAliveMaxTimeout: /* @__PURE__ */ Symbol("max keep alive timeout"), + kKeepAliveTimeoutThreshold: /* @__PURE__ */ Symbol("keep alive timeout threshold"), + kKeepAliveTimeoutValue: /* @__PURE__ */ Symbol("keep alive timeout"), + kKeepAlive: /* @__PURE__ */ Symbol("keep alive"), + kHeadersTimeout: /* @__PURE__ */ Symbol("headers timeout"), + kBodyTimeout: /* @__PURE__ */ Symbol("body timeout"), + kServerName: /* @__PURE__ */ Symbol("server name"), + kLocalAddress: /* @__PURE__ */ Symbol("local address"), + kHost: /* @__PURE__ */ Symbol("host"), + kNoRef: /* @__PURE__ */ Symbol("no ref"), + kBodyUsed: /* @__PURE__ */ Symbol("used"), + kRunning: /* @__PURE__ */ Symbol("running"), + kBlocking: /* @__PURE__ */ Symbol("blocking"), + kPending: /* @__PURE__ */ Symbol("pending"), + kSize: /* @__PURE__ */ Symbol("size"), + kBusy: /* @__PURE__ */ Symbol("busy"), + kQueued: /* @__PURE__ */ Symbol("queued"), + kFree: /* @__PURE__ */ Symbol("free"), + kConnected: /* @__PURE__ */ Symbol("connected"), + kClosed: /* @__PURE__ */ Symbol("closed"), + kNeedDrain: /* @__PURE__ */ Symbol("need drain"), + kReset: /* @__PURE__ */ Symbol("reset"), + kDestroyed: /* @__PURE__ */ Symbol.for("nodejs.stream.destroyed"), + kMaxHeadersSize: /* @__PURE__ */ Symbol("max headers size"), + kRunningIdx: /* @__PURE__ */ Symbol("running index"), + kPendingIdx: /* @__PURE__ */ Symbol("pending index"), + kError: /* @__PURE__ */ Symbol("error"), + kClients: /* @__PURE__ */ Symbol("clients"), + kClient: /* @__PURE__ */ Symbol("client"), + kParser: /* @__PURE__ */ Symbol("parser"), + kOnDestroyed: /* @__PURE__ */ Symbol("destroy callbacks"), + kPipelining: /* @__PURE__ */ Symbol("pipelining"), + kSocket: /* @__PURE__ */ Symbol("socket"), + kHostHeader: /* @__PURE__ */ Symbol("host header"), + kConnector: /* @__PURE__ */ Symbol("connector"), + kStrictContentLength: /* @__PURE__ */ Symbol("strict content length"), + kMaxRedirections: /* @__PURE__ */ Symbol("maxRedirections"), + kMaxRequests: /* @__PURE__ */ Symbol("maxRequestsPerClient"), + kProxy: /* @__PURE__ */ Symbol("proxy agent options"), + kCounter: /* @__PURE__ */ Symbol("socket request counter"), + kInterceptors: /* @__PURE__ */ Symbol("dispatch interceptors"), + kMaxResponseSize: /* @__PURE__ */ Symbol("max response size"), + kHTTP2Session: /* @__PURE__ */ Symbol("http2Session"), + kHTTP2SessionState: /* @__PURE__ */ Symbol("http2Session state"), + kHTTP2BuildRequest: /* @__PURE__ */ Symbol("http2 build request"), + kHTTP1BuildRequest: /* @__PURE__ */ Symbol("http1 build request"), + kHTTP2CopyHeaders: /* @__PURE__ */ Symbol("http2 copy headers"), + kHTTPConnVersion: /* @__PURE__ */ Symbol("http connection version"), + kRetryHandlerDefaultRetry: /* @__PURE__ */ Symbol("retry agent default retry"), + kConstruct: /* @__PURE__ */ Symbol("constructable") + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/errors.js +var require_errors = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/errors.js"(exports2, module2) { + "use strict"; + var UndiciError = class extends Error { + constructor(message) { + super(message); + this.name = "UndiciError"; + this.code = "UND_ERR"; + } + }; + var ConnectTimeoutError = class _ConnectTimeoutError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _ConnectTimeoutError); + this.name = "ConnectTimeoutError"; + this.message = message || "Connect Timeout Error"; + this.code = "UND_ERR_CONNECT_TIMEOUT"; + } + }; + var HeadersTimeoutError = class _HeadersTimeoutError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _HeadersTimeoutError); + this.name = "HeadersTimeoutError"; + this.message = message || "Headers Timeout Error"; + this.code = "UND_ERR_HEADERS_TIMEOUT"; + } + }; + var HeadersOverflowError = class _HeadersOverflowError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _HeadersOverflowError); + this.name = "HeadersOverflowError"; + this.message = message || "Headers Overflow Error"; + this.code = "UND_ERR_HEADERS_OVERFLOW"; + } + }; + var BodyTimeoutError = class _BodyTimeoutError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _BodyTimeoutError); + this.name = "BodyTimeoutError"; + this.message = message || "Body Timeout Error"; + this.code = "UND_ERR_BODY_TIMEOUT"; + } + }; + var ResponseStatusCodeError = class _ResponseStatusCodeError extends UndiciError { + constructor(message, statusCode, headers, body) { + super(message); + Error.captureStackTrace(this, _ResponseStatusCodeError); + this.name = "ResponseStatusCodeError"; + this.message = message || "Response Status Code Error"; + this.code = "UND_ERR_RESPONSE_STATUS_CODE"; + this.body = body; + this.status = statusCode; + this.statusCode = statusCode; + this.headers = headers; + } + }; + var InvalidArgumentError = class _InvalidArgumentError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _InvalidArgumentError); + this.name = "InvalidArgumentError"; + this.message = message || "Invalid Argument Error"; + this.code = "UND_ERR_INVALID_ARG"; + } + }; + var InvalidReturnValueError = class _InvalidReturnValueError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _InvalidReturnValueError); + this.name = "InvalidReturnValueError"; + this.message = message || "Invalid Return Value Error"; + this.code = "UND_ERR_INVALID_RETURN_VALUE"; + } + }; + var RequestAbortedError = class _RequestAbortedError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _RequestAbortedError); + this.name = "AbortError"; + this.message = message || "Request aborted"; + this.code = "UND_ERR_ABORTED"; + } + }; + var InformationalError = class _InformationalError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _InformationalError); + this.name = "InformationalError"; + this.message = message || "Request information"; + this.code = "UND_ERR_INFO"; + } + }; + var RequestContentLengthMismatchError = class _RequestContentLengthMismatchError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _RequestContentLengthMismatchError); + this.name = "RequestContentLengthMismatchError"; + this.message = message || "Request body length does not match content-length header"; + this.code = "UND_ERR_REQ_CONTENT_LENGTH_MISMATCH"; + } + }; + var ResponseContentLengthMismatchError = class _ResponseContentLengthMismatchError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _ResponseContentLengthMismatchError); + this.name = "ResponseContentLengthMismatchError"; + this.message = message || "Response body length does not match content-length header"; + this.code = "UND_ERR_RES_CONTENT_LENGTH_MISMATCH"; + } + }; + var ClientDestroyedError = class _ClientDestroyedError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _ClientDestroyedError); + this.name = "ClientDestroyedError"; + this.message = message || "The client is destroyed"; + this.code = "UND_ERR_DESTROYED"; + } + }; + var ClientClosedError = class _ClientClosedError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _ClientClosedError); + this.name = "ClientClosedError"; + this.message = message || "The client is closed"; + this.code = "UND_ERR_CLOSED"; + } + }; + var SocketError = class _SocketError extends UndiciError { + constructor(message, socket) { + super(message); + Error.captureStackTrace(this, _SocketError); + this.name = "SocketError"; + this.message = message || "Socket error"; + this.code = "UND_ERR_SOCKET"; + this.socket = socket; + } + }; + var NotSupportedError = class _NotSupportedError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _NotSupportedError); + this.name = "NotSupportedError"; + this.message = message || "Not supported error"; + this.code = "UND_ERR_NOT_SUPPORTED"; + } + }; + var BalancedPoolMissingUpstreamError = class extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, NotSupportedError); + this.name = "MissingUpstreamError"; + this.message = message || "No upstream has been added to the BalancedPool"; + this.code = "UND_ERR_BPL_MISSING_UPSTREAM"; + } + }; + var HTTPParserError = class _HTTPParserError extends Error { + constructor(message, code2, data) { + super(message); + Error.captureStackTrace(this, _HTTPParserError); + this.name = "HTTPParserError"; + this.code = code2 ? `HPE_${code2}` : void 0; + this.data = data ? data.toString() : void 0; + } + }; + var ResponseExceededMaxSizeError = class _ResponseExceededMaxSizeError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _ResponseExceededMaxSizeError); + this.name = "ResponseExceededMaxSizeError"; + this.message = message || "Response content exceeded max size"; + this.code = "UND_ERR_RES_EXCEEDED_MAX_SIZE"; + } + }; + var RequestRetryError = class _RequestRetryError extends UndiciError { + constructor(message, code2, { headers, data }) { + super(message); + Error.captureStackTrace(this, _RequestRetryError); + this.name = "RequestRetryError"; + this.message = message || "Request retry error"; + this.code = "UND_ERR_REQ_RETRY"; + this.statusCode = code2; + this.data = data; + this.headers = headers; + } + }; + module2.exports = { + HTTPParserError, + UndiciError, + HeadersTimeoutError, + HeadersOverflowError, + BodyTimeoutError, + RequestContentLengthMismatchError, + ConnectTimeoutError, + ResponseStatusCodeError, + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError, + ClientDestroyedError, + ClientClosedError, + InformationalError, + SocketError, + NotSupportedError, + ResponseContentLengthMismatchError, + BalancedPoolMissingUpstreamError, + ResponseExceededMaxSizeError, + RequestRetryError + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/constants.js +var require_constants = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/constants.js"(exports2, module2) { + "use strict"; + var headerNameLowerCasedRecord = {}; + var wellknownHeaderNames = [ + "Accept", + "Accept-Encoding", + "Accept-Language", + "Accept-Ranges", + "Access-Control-Allow-Credentials", + "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin", + "Access-Control-Expose-Headers", + "Access-Control-Max-Age", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Age", + "Allow", + "Alt-Svc", + "Alt-Used", + "Authorization", + "Cache-Control", + "Clear-Site-Data", + "Connection", + "Content-Disposition", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-Range", + "Content-Security-Policy", + "Content-Security-Policy-Report-Only", + "Content-Type", + "Cookie", + "Cross-Origin-Embedder-Policy", + "Cross-Origin-Opener-Policy", + "Cross-Origin-Resource-Policy", + "Date", + "Device-Memory", + "Downlink", + "ECT", + "ETag", + "Expect", + "Expect-CT", + "Expires", + "Forwarded", + "From", + "Host", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", + "Keep-Alive", + "Last-Modified", + "Link", + "Location", + "Max-Forwards", + "Origin", + "Permissions-Policy", + "Pragma", + "Proxy-Authenticate", + "Proxy-Authorization", + "RTT", + "Range", + "Referer", + "Referrer-Policy", + "Refresh", + "Retry-After", + "Sec-WebSocket-Accept", + "Sec-WebSocket-Extensions", + "Sec-WebSocket-Key", + "Sec-WebSocket-Protocol", + "Sec-WebSocket-Version", + "Server", + "Server-Timing", + "Service-Worker-Allowed", + "Service-Worker-Navigation-Preload", + "Set-Cookie", + "SourceMap", + "Strict-Transport-Security", + "Supports-Loading-Mode", + "TE", + "Timing-Allow-Origin", + "Trailer", + "Transfer-Encoding", + "Upgrade", + "Upgrade-Insecure-Requests", + "User-Agent", + "Vary", + "Via", + "WWW-Authenticate", + "X-Content-Type-Options", + "X-DNS-Prefetch-Control", + "X-Frame-Options", + "X-Permitted-Cross-Domain-Policies", + "X-Powered-By", + "X-Requested-With", + "X-XSS-Protection" + ]; + for (let i2 = 0; i2 < wellknownHeaderNames.length; ++i2) { + const key = wellknownHeaderNames[i2]; + const lowerCasedKey = key.toLowerCase(); + headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = lowerCasedKey; + } + Object.setPrototypeOf(headerNameLowerCasedRecord, null); + module2.exports = { + wellknownHeaderNames, + headerNameLowerCasedRecord + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/util.js +var require_util = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/util.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var { kDestroyed, kBodyUsed } = require_symbols(); + var { IncomingMessage } = require("http"); + var stream = require("stream"); + var net = require("net"); + var { InvalidArgumentError } = require_errors(); + var { Blob: Blob2 } = require("buffer"); + var nodeUtil = require("util"); + var { stringify } = require("querystring"); + var { headerNameLowerCasedRecord } = require_constants(); + var [nodeMajor, nodeMinor] = process.versions.node.split(".").map((v) => Number(v)); + function nop() { + } + function isStream2(obj) { + return obj && typeof obj === "object" && typeof obj.pipe === "function" && typeof obj.on === "function"; + } + function isBlobLike(object) { + return Blob2 && object instanceof Blob2 || object && typeof object === "object" && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && /^(Blob|File)$/.test(object[Symbol.toStringTag]); + } + function buildURL(url, queryParams) { + if (url.includes("?") || url.includes("#")) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".'); + } + const stringified = stringify(queryParams); + if (stringified) { + url += "?" + stringified; + } + return url; + } + function parseURL(url) { + if (typeof url === "string") { + url = new URL(url); + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); + } + return url; + } + if (!url || typeof url !== "object") { + throw new InvalidArgumentError("Invalid URL: The URL argument must be a non-null object."); + } + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); + } + if (!(url instanceof URL)) { + if (url.port != null && url.port !== "" && !Number.isFinite(parseInt(url.port))) { + throw new InvalidArgumentError("Invalid URL: port must be a valid integer or a string representation of an integer."); + } + if (url.path != null && typeof url.path !== "string") { + throw new InvalidArgumentError("Invalid URL path: the path must be a string or null/undefined."); + } + if (url.pathname != null && typeof url.pathname !== "string") { + throw new InvalidArgumentError("Invalid URL pathname: the pathname must be a string or null/undefined."); + } + if (url.hostname != null && typeof url.hostname !== "string") { + throw new InvalidArgumentError("Invalid URL hostname: the hostname must be a string or null/undefined."); + } + if (url.origin != null && typeof url.origin !== "string") { + throw new InvalidArgumentError("Invalid URL origin: the origin must be a string or null/undefined."); + } + const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; + let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`; + let path12 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; + if (origin.endsWith("/")) { + origin = origin.substring(0, origin.length - 1); + } + if (path12 && !path12.startsWith("/")) { + path12 = `/${path12}`; + } + url = new URL(origin + path12); + } + return url; + } + function parseOrigin(url) { + url = parseURL(url); + if (url.pathname !== "/" || url.search || url.hash) { + throw new InvalidArgumentError("invalid url"); + } + return url; + } + function getHostname(host) { + if (host[0] === "[") { + const idx2 = host.indexOf("]"); + assert(idx2 !== -1); + return host.substring(1, idx2); + } + const idx = host.indexOf(":"); + if (idx === -1) return host; + return host.substring(0, idx); + } + function getServerName(host) { + if (!host) { + return null; + } + assert.strictEqual(typeof host, "string"); + const servername = getHostname(host); + if (net.isIP(servername)) { + return ""; + } + return servername; + } + function deepClone(obj) { + return JSON.parse(JSON.stringify(obj)); + } + function isAsyncIterable(obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === "function"); + } + function isIterable(obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === "function" || typeof obj[Symbol.asyncIterator] === "function")); + } + function bodyLength(body) { + if (body == null) { + return 0; + } else if (isStream2(body)) { + const state = body._readableState; + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) ? state.length : null; + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null; + } else if (isBuffer(body)) { + return body.byteLength; + } + return null; + } + function isDestroyed(stream2) { + return !stream2 || !!(stream2.destroyed || stream2[kDestroyed]); + } + function isReadableAborted(stream2) { + const state = stream2 && stream2._readableState; + return isDestroyed(stream2) && state && !state.endEmitted; + } + function destroy(stream2, err) { + if (stream2 == null || !isStream2(stream2) || isDestroyed(stream2)) { + return; + } + if (typeof stream2.destroy === "function") { + if (Object.getPrototypeOf(stream2).constructor === IncomingMessage) { + stream2.socket = null; + } + stream2.destroy(err); + } else if (err) { + process.nextTick((stream3, err2) => { + stream3.emit("error", err2); + }, stream2, err); + } + if (stream2.destroyed !== true) { + stream2[kDestroyed] = true; + } + } + var KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/; + function parseKeepAliveTimeout(val) { + const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR); + return m ? parseInt(m[1], 10) * 1e3 : null; + } + function headerNameToString(value) { + return headerNameLowerCasedRecord[value] || value.toLowerCase(); + } + function parseHeaders(headers, obj = {}) { + if (!Array.isArray(headers)) return headers; + for (let i2 = 0; i2 < headers.length; i2 += 2) { + const key = headers[i2].toString().toLowerCase(); + let val = obj[key]; + if (!val) { + if (Array.isArray(headers[i2 + 1])) { + obj[key] = headers[i2 + 1].map((x) => x.toString("utf8")); + } else { + obj[key] = headers[i2 + 1].toString("utf8"); + } + } else { + if (!Array.isArray(val)) { + val = [val]; + obj[key] = val; + } + val.push(headers[i2 + 1].toString("utf8")); + } + } + if ("content-length" in obj && "content-disposition" in obj) { + obj["content-disposition"] = Buffer.from(obj["content-disposition"]).toString("latin1"); + } + return obj; + } + function parseRawHeaders(headers) { + const ret = []; + let hasContentLength = false; + let contentDispositionIdx = -1; + for (let n2 = 0; n2 < headers.length; n2 += 2) { + const key = headers[n2 + 0].toString(); + const val = headers[n2 + 1].toString("utf8"); + if (key.length === 14 && (key === "content-length" || key.toLowerCase() === "content-length")) { + ret.push(key, val); + hasContentLength = true; + } else if (key.length === 19 && (key === "content-disposition" || key.toLowerCase() === "content-disposition")) { + contentDispositionIdx = ret.push(key, val) - 1; + } else { + ret.push(key, val); + } + } + if (hasContentLength && contentDispositionIdx !== -1) { + ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString("latin1"); + } + return ret; + } + function isBuffer(buffer) { + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer); + } + function validateHandler(handler, method, upgrade) { + if (!handler || typeof handler !== "object") { + throw new InvalidArgumentError("handler must be an object"); + } + if (typeof handler.onConnect !== "function") { + throw new InvalidArgumentError("invalid onConnect method"); + } + if (typeof handler.onError !== "function") { + throw new InvalidArgumentError("invalid onError method"); + } + if (typeof handler.onBodySent !== "function" && handler.onBodySent !== void 0) { + throw new InvalidArgumentError("invalid onBodySent method"); + } + if (upgrade || method === "CONNECT") { + if (typeof handler.onUpgrade !== "function") { + throw new InvalidArgumentError("invalid onUpgrade method"); + } + } else { + if (typeof handler.onHeaders !== "function") { + throw new InvalidArgumentError("invalid onHeaders method"); + } + if (typeof handler.onData !== "function") { + throw new InvalidArgumentError("invalid onData method"); + } + if (typeof handler.onComplete !== "function") { + throw new InvalidArgumentError("invalid onComplete method"); + } + } + } + function isDisturbed(body) { + return !!(body && (stream.isDisturbed ? stream.isDisturbed(body) || body[kBodyUsed] : body[kBodyUsed] || body.readableDidRead || body._readableState && body._readableState.dataEmitted || isReadableAborted(body))); + } + function isErrored(body) { + return !!(body && (stream.isErrored ? stream.isErrored(body) : /state: 'errored'/.test( + nodeUtil.inspect(body) + ))); + } + function isReadable(body) { + return !!(body && (stream.isReadable ? stream.isReadable(body) : /state: 'readable'/.test( + nodeUtil.inspect(body) + ))); + } + function getSocketInfo(socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead + }; + } + async function* convertIterableToBuffer(iterable) { + for await (const chunk of iterable) { + yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); + } + } + var ReadableStream2; + function ReadableStreamFrom(iterable) { + if (!ReadableStream2) { + ReadableStream2 = require("stream/web").ReadableStream; + } + if (ReadableStream2.from) { + return ReadableStream2.from(convertIterableToBuffer(iterable)); + } + let iterator; + return new ReadableStream2( + { + async start() { + iterator = iterable[Symbol.asyncIterator](); + }, + async pull(controller) { + const { done, value } = await iterator.next(); + if (done) { + queueMicrotask(() => { + controller.close(); + }); + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value); + controller.enqueue(new Uint8Array(buf)); + } + return controller.desiredSize > 0; + }, + async cancel(reason) { + await iterator.return(); + } + }, + 0 + ); + } + function isFormDataLike(object) { + return object && typeof object === "object" && typeof object.append === "function" && typeof object.delete === "function" && typeof object.get === "function" && typeof object.getAll === "function" && typeof object.has === "function" && typeof object.set === "function" && object[Symbol.toStringTag] === "FormData"; + } + function throwIfAborted(signal) { + if (!signal) { + return; + } + if (typeof signal.throwIfAborted === "function") { + signal.throwIfAborted(); + } else { + if (signal.aborted) { + const err = new Error("The operation was aborted"); + err.name = "AbortError"; + throw err; + } + } + } + function addAbortListener3(signal, listener) { + if ("addEventListener" in signal) { + signal.addEventListener("abort", listener, { once: true }); + return () => signal.removeEventListener("abort", listener); + } + signal.addListener("abort", listener); + return () => signal.removeListener("abort", listener); + } + var hasToWellFormed = !!String.prototype.toWellFormed; + function toUSVString(val) { + if (hasToWellFormed) { + return `${val}`.toWellFormed(); + } else if (nodeUtil.toUSVString) { + return nodeUtil.toUSVString(val); + } + return `${val}`; + } + function parseRangeHeader(range) { + if (range == null || range === "") return { start: 0, end: null, size: null }; + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null; + return m ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } : null; + } + var kEnumerableProperty = /* @__PURE__ */ Object.create(null); + kEnumerableProperty.enumerable = true; + module2.exports = { + kEnumerableProperty, + nop, + isDisturbed, + isErrored, + isReadable, + toUSVString, + isReadableAborted, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream: isStream2, + isIterable, + isAsyncIterable, + isDestroyed, + headerNameToString, + parseRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + validateHandler, + getSocketInfo, + isFormDataLike, + buildURL, + throwIfAborted, + addAbortListener: addAbortListener3, + parseRangeHeader, + nodeMajor, + nodeMinor, + nodeHasAutoSelectFamily: nodeMajor > 18 || nodeMajor === 18 && nodeMinor >= 13, + safeHTTPMethods: ["GET", "HEAD", "OPTIONS", "TRACE"] + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/timers.js +var require_timers = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/timers.js"(exports2, module2) { + "use strict"; + var fastNow = Date.now(); + var fastNowTimeout; + var fastTimers = []; + function onTimeout() { + fastNow = Date.now(); + let len = fastTimers.length; + let idx = 0; + while (idx < len) { + const timer = fastTimers[idx]; + if (timer.state === 0) { + timer.state = fastNow + timer.delay; + } else if (timer.state > 0 && fastNow >= timer.state) { + timer.state = -1; + timer.callback(timer.opaque); + } + if (timer.state === -1) { + timer.state = -2; + if (idx !== len - 1) { + fastTimers[idx] = fastTimers.pop(); + } else { + fastTimers.pop(); + } + len -= 1; + } else { + idx += 1; + } + } + if (fastTimers.length > 0) { + refreshTimeout(); + } + } + function refreshTimeout() { + if (fastNowTimeout && fastNowTimeout.refresh) { + fastNowTimeout.refresh(); + } else { + clearTimeout(fastNowTimeout); + fastNowTimeout = setTimeout(onTimeout, 1e3); + if (fastNowTimeout.unref) { + fastNowTimeout.unref(); + } + } + } + var Timeout = class { + constructor(callback, delay, opaque) { + this.callback = callback; + this.delay = delay; + this.opaque = opaque; + this.state = -2; + this.refresh(); + } + refresh() { + if (this.state === -2) { + fastTimers.push(this); + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout(); + } + } + this.state = 0; + } + clear() { + this.state = -1; + } + }; + module2.exports = { + setTimeout(callback, delay, opaque) { + return delay < 1e3 ? setTimeout(callback, delay, opaque) : new Timeout(callback, delay, opaque); + }, + clearTimeout(timeout) { + if (timeout instanceof Timeout) { + timeout.clear(); + } else { + clearTimeout(timeout); + } + } + }; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js +var require_sbmh = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js"(exports2, module2) { + "use strict"; + var EventEmitter2 = require("events").EventEmitter; + var inherits = require("util").inherits; + function SBMH(needle) { + if (typeof needle === "string") { + needle = Buffer.from(needle); + } + if (!Buffer.isBuffer(needle)) { + throw new TypeError("The needle has to be a String or a Buffer."); + } + const needleLength = needle.length; + if (needleLength === 0) { + throw new Error("The needle cannot be an empty String/Buffer."); + } + if (needleLength > 256) { + throw new Error("The needle cannot have a length bigger than 256."); + } + this.maxMatches = Infinity; + this.matches = 0; + this._occ = new Array(256).fill(needleLength); + this._lookbehind_size = 0; + this._needle = needle; + this._bufpos = 0; + this._lookbehind = Buffer.alloc(needleLength); + for (var i2 = 0; i2 < needleLength - 1; ++i2) { + this._occ[needle[i2]] = needleLength - 1 - i2; + } + } + inherits(SBMH, EventEmitter2); + SBMH.prototype.reset = function() { + this._lookbehind_size = 0; + this.matches = 0; + this._bufpos = 0; + }; + SBMH.prototype.push = function(chunk, pos) { + if (!Buffer.isBuffer(chunk)) { + chunk = Buffer.from(chunk, "binary"); + } + const chlen = chunk.length; + this._bufpos = pos || 0; + let r; + while (r !== chlen && this.matches < this.maxMatches) { + r = this._sbmh_feed(chunk); + } + return r; + }; + SBMH.prototype._sbmh_feed = function(data) { + const len = data.length; + const needle = this._needle; + const needleLength = needle.length; + const lastNeedleChar = needle[needleLength - 1]; + let pos = -this._lookbehind_size; + let ch; + if (pos < 0) { + while (pos < 0 && pos <= len - needleLength) { + ch = this._sbmh_lookup_char(data, pos + needleLength - 1); + if (ch === lastNeedleChar && this._sbmh_memcmp(data, pos, needleLength - 1)) { + this._lookbehind_size = 0; + ++this.matches; + this.emit("info", true); + return this._bufpos = pos + needleLength; + } + pos += this._occ[ch]; + } + if (pos < 0) { + while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { + ++pos; + } + } + if (pos >= 0) { + this.emit("info", false, this._lookbehind, 0, this._lookbehind_size); + this._lookbehind_size = 0; + } else { + const bytesToCutOff = this._lookbehind_size + pos; + if (bytesToCutOff > 0) { + this.emit("info", false, this._lookbehind, 0, bytesToCutOff); + } + this._lookbehind.copy( + this._lookbehind, + 0, + bytesToCutOff, + this._lookbehind_size - bytesToCutOff + ); + this._lookbehind_size -= bytesToCutOff; + data.copy(this._lookbehind, this._lookbehind_size); + this._lookbehind_size += len; + this._bufpos = len; + return len; + } + } + pos += (pos >= 0) * this._bufpos; + if (data.indexOf(needle, pos) !== -1) { + pos = data.indexOf(needle, pos); + ++this.matches; + if (pos > 0) { + this.emit("info", true, data, this._bufpos, pos); + } else { + this.emit("info", true); + } + return this._bufpos = pos + needleLength; + } else { + pos = len - needleLength; + } + while (pos < len && (data[pos] !== needle[0] || Buffer.compare( + data.subarray(pos, pos + len - pos), + needle.subarray(0, len - pos) + ) !== 0)) { + ++pos; + } + if (pos < len) { + data.copy(this._lookbehind, 0, pos, pos + (len - pos)); + this._lookbehind_size = len - pos; + } + if (pos > 0) { + this.emit("info", false, data, this._bufpos, pos < len ? pos : len); + } + this._bufpos = len; + return len; + }; + SBMH.prototype._sbmh_lookup_char = function(data, pos) { + return pos < 0 ? this._lookbehind[this._lookbehind_size + pos] : data[pos]; + }; + SBMH.prototype._sbmh_memcmp = function(data, pos, len) { + for (var i2 = 0; i2 < len; ++i2) { + if (this._sbmh_lookup_char(data, pos + i2) !== this._needle[i2]) { + return false; + } + } + return true; + }; + module2.exports = SBMH; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js +var require_PartStream = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js"(exports2, module2) { + "use strict"; + var inherits = require("util").inherits; + var ReadableStream2 = require("stream").Readable; + function PartStream(opts) { + ReadableStream2.call(this, opts); + } + inherits(PartStream, ReadableStream2); + PartStream.prototype._read = function(n2) { + }; + module2.exports = PartStream; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/getLimit.js +var require_getLimit = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/getLimit.js"(exports2, module2) { + "use strict"; + module2.exports = function getLimit(limits, name, defaultLimit) { + if (!limits || limits[name] === void 0 || limits[name] === null) { + return defaultLimit; + } + if (typeof limits[name] !== "number" || isNaN(limits[name])) { + throw new TypeError("Limit " + name + " is not a valid number"); + } + return limits[name]; + }; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js +var require_HeaderParser = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js"(exports2, module2) { + "use strict"; + var EventEmitter2 = require("events").EventEmitter; + var inherits = require("util").inherits; + var getLimit = require_getLimit(); + var StreamSearch = require_sbmh(); + var B_DCRLF = Buffer.from("\r\n\r\n"); + var RE_CRLF = /\r\n/g; + var RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/; + function HeaderParser(cfg) { + EventEmitter2.call(this); + cfg = cfg || {}; + const self = this; + this.nread = 0; + this.maxed = false; + this.npairs = 0; + this.maxHeaderPairs = getLimit(cfg, "maxHeaderPairs", 2e3); + this.maxHeaderSize = getLimit(cfg, "maxHeaderSize", 80 * 1024); + this.buffer = ""; + this.header = {}; + this.finished = false; + this.ss = new StreamSearch(B_DCRLF); + this.ss.on("info", function(isMatch, data, start, end) { + if (data && !self.maxed) { + if (self.nread + end - start >= self.maxHeaderSize) { + end = self.maxHeaderSize - self.nread + start; + self.nread = self.maxHeaderSize; + self.maxed = true; + } else { + self.nread += end - start; + } + self.buffer += data.toString("binary", start, end); + } + if (isMatch) { + self._finish(); + } + }); + } + inherits(HeaderParser, EventEmitter2); + HeaderParser.prototype.push = function(data) { + const r = this.ss.push(data); + if (this.finished) { + return r; + } + }; + HeaderParser.prototype.reset = function() { + this.finished = false; + this.buffer = ""; + this.header = {}; + this.ss.reset(); + }; + HeaderParser.prototype._finish = function() { + if (this.buffer) { + this._parseHeader(); + } + this.ss.matches = this.ss.maxMatches; + const header = this.header; + this.header = {}; + this.buffer = ""; + this.finished = true; + this.nread = this.npairs = 0; + this.maxed = false; + this.emit("header", header); + }; + HeaderParser.prototype._parseHeader = function() { + if (this.npairs === this.maxHeaderPairs) { + return; + } + const lines = this.buffer.split(RE_CRLF); + const len = lines.length; + let m, h2; + for (var i2 = 0; i2 < len; ++i2) { + if (lines[i2].length === 0) { + continue; + } + if (lines[i2][0] === " " || lines[i2][0] === " ") { + if (h2) { + this.header[h2][this.header[h2].length - 1] += lines[i2]; + continue; + } + } + const posColon = lines[i2].indexOf(":"); + if (posColon === -1 || posColon === 0) { + return; + } + m = RE_HDR.exec(lines[i2]); + h2 = m[1].toLowerCase(); + this.header[h2] = this.header[h2] || []; + this.header[h2].push(m[2] || ""); + if (++this.npairs === this.maxHeaderPairs) { + break; + } + } + }; + module2.exports = HeaderParser; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js +var require_Dicer = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js"(exports2, module2) { + "use strict"; + var WritableStream = require("stream").Writable; + var inherits = require("util").inherits; + var StreamSearch = require_sbmh(); + var PartStream = require_PartStream(); + var HeaderParser = require_HeaderParser(); + var DASH = 45; + var B_ONEDASH = Buffer.from("-"); + var B_CRLF = Buffer.from("\r\n"); + var EMPTY_FN = function() { + }; + function Dicer(cfg) { + if (!(this instanceof Dicer)) { + return new Dicer(cfg); + } + WritableStream.call(this, cfg); + if (!cfg || !cfg.headerFirst && typeof cfg.boundary !== "string") { + throw new TypeError("Boundary required"); + } + if (typeof cfg.boundary === "string") { + this.setBoundary(cfg.boundary); + } else { + this._bparser = void 0; + } + this._headerFirst = cfg.headerFirst; + this._dashes = 0; + this._parts = 0; + this._finished = false; + this._realFinish = false; + this._isPreamble = true; + this._justMatched = false; + this._firstWrite = true; + this._inHeader = true; + this._part = void 0; + this._cb = void 0; + this._ignoreData = false; + this._partOpts = { highWaterMark: cfg.partHwm }; + this._pause = false; + const self = this; + this._hparser = new HeaderParser(cfg); + this._hparser.on("header", function(header) { + self._inHeader = false; + self._part.emit("header", header); + }); + } + inherits(Dicer, WritableStream); + Dicer.prototype.emit = function(ev) { + if (ev === "finish" && !this._realFinish) { + if (!this._finished) { + const self = this; + process.nextTick(function() { + self.emit("error", new Error("Unexpected end of multipart data")); + if (self._part && !self._ignoreData) { + const type = self._isPreamble ? "Preamble" : "Part"; + self._part.emit("error", new Error(type + " terminated early due to unexpected end of multipart data")); + self._part.push(null); + process.nextTick(function() { + self._realFinish = true; + self.emit("finish"); + self._realFinish = false; + }); + return; + } + self._realFinish = true; + self.emit("finish"); + self._realFinish = false; + }); + } + } else { + WritableStream.prototype.emit.apply(this, arguments); + } + }; + Dicer.prototype._write = function(data, encoding, cb) { + if (!this._hparser && !this._bparser) { + return cb(); + } + if (this._headerFirst && this._isPreamble) { + if (!this._part) { + this._part = new PartStream(this._partOpts); + if (this.listenerCount("preamble") !== 0) { + this.emit("preamble", this._part); + } else { + this._ignore(); + } + } + const r = this._hparser.push(data); + if (!this._inHeader && r !== void 0 && r < data.length) { + data = data.slice(r); + } else { + return cb(); + } + } + if (this._firstWrite) { + this._bparser.push(B_CRLF); + this._firstWrite = false; + } + this._bparser.push(data); + if (this._pause) { + this._cb = cb; + } else { + cb(); + } + }; + Dicer.prototype.reset = function() { + this._part = void 0; + this._bparser = void 0; + this._hparser = void 0; + }; + Dicer.prototype.setBoundary = function(boundary) { + const self = this; + this._bparser = new StreamSearch("\r\n--" + boundary); + this._bparser.on("info", function(isMatch, data, start, end) { + self._oninfo(isMatch, data, start, end); + }); + }; + Dicer.prototype._ignore = function() { + if (this._part && !this._ignoreData) { + this._ignoreData = true; + this._part.on("error", EMPTY_FN); + this._part.resume(); + } + }; + Dicer.prototype._oninfo = function(isMatch, data, start, end) { + let buf; + const self = this; + let i2 = 0; + let r; + let shouldWriteMore = true; + if (!this._part && this._justMatched && data) { + while (this._dashes < 2 && start + i2 < end) { + if (data[start + i2] === DASH) { + ++i2; + ++this._dashes; + } else { + if (this._dashes) { + buf = B_ONEDASH; + } + this._dashes = 0; + break; + } + } + if (this._dashes === 2) { + if (start + i2 < end && this.listenerCount("trailer") !== 0) { + this.emit("trailer", data.slice(start + i2, end)); + } + this.reset(); + this._finished = true; + if (self._parts === 0) { + self._realFinish = true; + self.emit("finish"); + self._realFinish = false; + } + } + if (this._dashes) { + return; + } + } + if (this._justMatched) { + this._justMatched = false; + } + if (!this._part) { + this._part = new PartStream(this._partOpts); + this._part._read = function(n2) { + self._unpause(); + }; + if (this._isPreamble && this.listenerCount("preamble") !== 0) { + this.emit("preamble", this._part); + } else if (this._isPreamble !== true && this.listenerCount("part") !== 0) { + this.emit("part", this._part); + } else { + this._ignore(); + } + if (!this._isPreamble) { + this._inHeader = true; + } + } + if (data && start < end && !this._ignoreData) { + if (this._isPreamble || !this._inHeader) { + if (buf) { + shouldWriteMore = this._part.push(buf); + } + shouldWriteMore = this._part.push(data.slice(start, end)); + if (!shouldWriteMore) { + this._pause = true; + } + } else if (!this._isPreamble && this._inHeader) { + if (buf) { + this._hparser.push(buf); + } + r = this._hparser.push(data.slice(start, end)); + if (!this._inHeader && r !== void 0 && r < end) { + this._oninfo(false, data, start + r, end); + } + } + } + if (isMatch) { + this._hparser.reset(); + if (this._isPreamble) { + this._isPreamble = false; + } else { + if (start !== end) { + ++this._parts; + this._part.on("end", function() { + if (--self._parts === 0) { + if (self._finished) { + self._realFinish = true; + self.emit("finish"); + self._realFinish = false; + } else { + self._unpause(); + } + } + }); + } + } + this._part.push(null); + this._part = void 0; + this._ignoreData = false; + this._justMatched = true; + this._dashes = 0; + } + }; + Dicer.prototype._unpause = function() { + if (!this._pause) { + return; + } + this._pause = false; + if (this._cb) { + const cb = this._cb; + this._cb = void 0; + cb(); + } + }; + module2.exports = Dicer; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/decodeText.js +var require_decodeText = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/decodeText.js"(exports2, module2) { + "use strict"; + var utf8Decoder = new TextDecoder("utf-8"); + var textDecoders = /* @__PURE__ */ new Map([ + ["utf-8", utf8Decoder], + ["utf8", utf8Decoder] + ]); + function getDecoder(charset) { + let lc; + while (true) { + switch (charset) { + case "utf-8": + case "utf8": + return decoders.utf8; + case "latin1": + case "ascii": + // TODO: Make these a separate, strict decoder? + case "us-ascii": + case "iso-8859-1": + case "iso8859-1": + case "iso88591": + case "iso_8859-1": + case "windows-1252": + case "iso_8859-1:1987": + case "cp1252": + case "x-cp1252": + return decoders.latin1; + case "utf16le": + case "utf-16le": + case "ucs2": + case "ucs-2": + return decoders.utf16le; + case "base64": + return decoders.base64; + default: + if (lc === void 0) { + lc = true; + charset = charset.toLowerCase(); + continue; + } + return decoders.other.bind(charset); + } + } + } + var decoders = { + utf8: (data, sourceEncoding) => { + if (data.length === 0) { + return ""; + } + if (typeof data === "string") { + data = Buffer.from(data, sourceEncoding); + } + return data.utf8Slice(0, data.length); + }, + latin1: (data, sourceEncoding) => { + if (data.length === 0) { + return ""; + } + if (typeof data === "string") { + return data; + } + return data.latin1Slice(0, data.length); + }, + utf16le: (data, sourceEncoding) => { + if (data.length === 0) { + return ""; + } + if (typeof data === "string") { + data = Buffer.from(data, sourceEncoding); + } + return data.ucs2Slice(0, data.length); + }, + base64: (data, sourceEncoding) => { + if (data.length === 0) { + return ""; + } + if (typeof data === "string") { + data = Buffer.from(data, sourceEncoding); + } + return data.base64Slice(0, data.length); + }, + other: (data, sourceEncoding) => { + if (data.length === 0) { + return ""; + } + if (typeof data === "string") { + data = Buffer.from(data, sourceEncoding); + } + if (textDecoders.has(exports2.toString())) { + try { + return textDecoders.get(exports2).decode(data); + } catch { + } + } + return typeof data === "string" ? data : data.toString(); + } + }; + function decodeText(text, sourceEncoding, destEncoding) { + if (text) { + return getDecoder(destEncoding)(text, sourceEncoding); + } + return text; + } + module2.exports = decodeText; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/parseParams.js +var require_parseParams = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/parseParams.js"(exports2, module2) { + "use strict"; + var decodeText = require_decodeText(); + var RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g; + var EncodedLookup = { + "%00": "\0", + "%01": "", + "%02": "", + "%03": "", + "%04": "", + "%05": "", + "%06": "", + "%07": "\x07", + "%08": "\b", + "%09": " ", + "%0a": "\n", + "%0A": "\n", + "%0b": "\v", + "%0B": "\v", + "%0c": "\f", + "%0C": "\f", + "%0d": "\r", + "%0D": "\r", + "%0e": "", + "%0E": "", + "%0f": "", + "%0F": "", + "%10": "", + "%11": "", + "%12": "", + "%13": "", + "%14": "", + "%15": "", + "%16": "", + "%17": "", + "%18": "", + "%19": "", + "%1a": "", + "%1A": "", + "%1b": "\x1B", + "%1B": "\x1B", + "%1c": "", + "%1C": "", + "%1d": "", + "%1D": "", + "%1e": "", + "%1E": "", + "%1f": "", + "%1F": "", + "%20": " ", + "%21": "!", + "%22": '"', + "%23": "#", + "%24": "$", + "%25": "%", + "%26": "&", + "%27": "'", + "%28": "(", + "%29": ")", + "%2a": "*", + "%2A": "*", + "%2b": "+", + "%2B": "+", + "%2c": ",", + "%2C": ",", + "%2d": "-", + "%2D": "-", + "%2e": ".", + "%2E": ".", + "%2f": "/", + "%2F": "/", + "%30": "0", + "%31": "1", + "%32": "2", + "%33": "3", + "%34": "4", + "%35": "5", + "%36": "6", + "%37": "7", + "%38": "8", + "%39": "9", + "%3a": ":", + "%3A": ":", + "%3b": ";", + "%3B": ";", + "%3c": "<", + "%3C": "<", + "%3d": "=", + "%3D": "=", + "%3e": ">", + "%3E": ">", + "%3f": "?", + "%3F": "?", + "%40": "@", + "%41": "A", + "%42": "B", + "%43": "C", + "%44": "D", + "%45": "E", + "%46": "F", + "%47": "G", + "%48": "H", + "%49": "I", + "%4a": "J", + "%4A": "J", + "%4b": "K", + "%4B": "K", + "%4c": "L", + "%4C": "L", + "%4d": "M", + "%4D": "M", + "%4e": "N", + "%4E": "N", + "%4f": "O", + "%4F": "O", + "%50": "P", + "%51": "Q", + "%52": "R", + "%53": "S", + "%54": "T", + "%55": "U", + "%56": "V", + "%57": "W", + "%58": "X", + "%59": "Y", + "%5a": "Z", + "%5A": "Z", + "%5b": "[", + "%5B": "[", + "%5c": "\\", + "%5C": "\\", + "%5d": "]", + "%5D": "]", + "%5e": "^", + "%5E": "^", + "%5f": "_", + "%5F": "_", + "%60": "`", + "%61": "a", + "%62": "b", + "%63": "c", + "%64": "d", + "%65": "e", + "%66": "f", + "%67": "g", + "%68": "h", + "%69": "i", + "%6a": "j", + "%6A": "j", + "%6b": "k", + "%6B": "k", + "%6c": "l", + "%6C": "l", + "%6d": "m", + "%6D": "m", + "%6e": "n", + "%6E": "n", + "%6f": "o", + "%6F": "o", + "%70": "p", + "%71": "q", + "%72": "r", + "%73": "s", + "%74": "t", + "%75": "u", + "%76": "v", + "%77": "w", + "%78": "x", + "%79": "y", + "%7a": "z", + "%7A": "z", + "%7b": "{", + "%7B": "{", + "%7c": "|", + "%7C": "|", + "%7d": "}", + "%7D": "}", + "%7e": "~", + "%7E": "~", + "%7f": "\x7F", + "%7F": "\x7F", + "%80": "\x80", + "%81": "\x81", + "%82": "\x82", + "%83": "\x83", + "%84": "\x84", + "%85": "\x85", + "%86": "\x86", + "%87": "\x87", + "%88": "\x88", + "%89": "\x89", + "%8a": "\x8A", + "%8A": "\x8A", + "%8b": "\x8B", + "%8B": "\x8B", + "%8c": "\x8C", + "%8C": "\x8C", + "%8d": "\x8D", + "%8D": "\x8D", + "%8e": "\x8E", + "%8E": "\x8E", + "%8f": "\x8F", + "%8F": "\x8F", + "%90": "\x90", + "%91": "\x91", + "%92": "\x92", + "%93": "\x93", + "%94": "\x94", + "%95": "\x95", + "%96": "\x96", + "%97": "\x97", + "%98": "\x98", + "%99": "\x99", + "%9a": "\x9A", + "%9A": "\x9A", + "%9b": "\x9B", + "%9B": "\x9B", + "%9c": "\x9C", + "%9C": "\x9C", + "%9d": "\x9D", + "%9D": "\x9D", + "%9e": "\x9E", + "%9E": "\x9E", + "%9f": "\x9F", + "%9F": "\x9F", + "%a0": "\xA0", + "%A0": "\xA0", + "%a1": "\xA1", + "%A1": "\xA1", + "%a2": "\xA2", + "%A2": "\xA2", + "%a3": "\xA3", + "%A3": "\xA3", + "%a4": "\xA4", + "%A4": "\xA4", + "%a5": "\xA5", + "%A5": "\xA5", + "%a6": "\xA6", + "%A6": "\xA6", + "%a7": "\xA7", + "%A7": "\xA7", + "%a8": "\xA8", + "%A8": "\xA8", + "%a9": "\xA9", + "%A9": "\xA9", + "%aa": "\xAA", + "%Aa": "\xAA", + "%aA": "\xAA", + "%AA": "\xAA", + "%ab": "\xAB", + "%Ab": "\xAB", + "%aB": "\xAB", + "%AB": "\xAB", + "%ac": "\xAC", + "%Ac": "\xAC", + "%aC": "\xAC", + "%AC": "\xAC", + "%ad": "\xAD", + "%Ad": "\xAD", + "%aD": "\xAD", + "%AD": "\xAD", + "%ae": "\xAE", + "%Ae": "\xAE", + "%aE": "\xAE", + "%AE": "\xAE", + "%af": "\xAF", + "%Af": "\xAF", + "%aF": "\xAF", + "%AF": "\xAF", + "%b0": "\xB0", + "%B0": "\xB0", + "%b1": "\xB1", + "%B1": "\xB1", + "%b2": "\xB2", + "%B2": "\xB2", + "%b3": "\xB3", + "%B3": "\xB3", + "%b4": "\xB4", + "%B4": "\xB4", + "%b5": "\xB5", + "%B5": "\xB5", + "%b6": "\xB6", + "%B6": "\xB6", + "%b7": "\xB7", + "%B7": "\xB7", + "%b8": "\xB8", + "%B8": "\xB8", + "%b9": "\xB9", + "%B9": "\xB9", + "%ba": "\xBA", + "%Ba": "\xBA", + "%bA": "\xBA", + "%BA": "\xBA", + "%bb": "\xBB", + "%Bb": "\xBB", + "%bB": "\xBB", + "%BB": "\xBB", + "%bc": "\xBC", + "%Bc": "\xBC", + "%bC": "\xBC", + "%BC": "\xBC", + "%bd": "\xBD", + "%Bd": "\xBD", + "%bD": "\xBD", + "%BD": "\xBD", + "%be": "\xBE", + "%Be": "\xBE", + "%bE": "\xBE", + "%BE": "\xBE", + "%bf": "\xBF", + "%Bf": "\xBF", + "%bF": "\xBF", + "%BF": "\xBF", + "%c0": "\xC0", + "%C0": "\xC0", + "%c1": "\xC1", + "%C1": "\xC1", + "%c2": "\xC2", + "%C2": "\xC2", + "%c3": "\xC3", + "%C3": "\xC3", + "%c4": "\xC4", + "%C4": "\xC4", + "%c5": "\xC5", + "%C5": "\xC5", + "%c6": "\xC6", + "%C6": "\xC6", + "%c7": "\xC7", + "%C7": "\xC7", + "%c8": "\xC8", + "%C8": "\xC8", + "%c9": "\xC9", + "%C9": "\xC9", + "%ca": "\xCA", + "%Ca": "\xCA", + "%cA": "\xCA", + "%CA": "\xCA", + "%cb": "\xCB", + "%Cb": "\xCB", + "%cB": "\xCB", + "%CB": "\xCB", + "%cc": "\xCC", + "%Cc": "\xCC", + "%cC": "\xCC", + "%CC": "\xCC", + "%cd": "\xCD", + "%Cd": "\xCD", + "%cD": "\xCD", + "%CD": "\xCD", + "%ce": "\xCE", + "%Ce": "\xCE", + "%cE": "\xCE", + "%CE": "\xCE", + "%cf": "\xCF", + "%Cf": "\xCF", + "%cF": "\xCF", + "%CF": "\xCF", + "%d0": "\xD0", + "%D0": "\xD0", + "%d1": "\xD1", + "%D1": "\xD1", + "%d2": "\xD2", + "%D2": "\xD2", + "%d3": "\xD3", + "%D3": "\xD3", + "%d4": "\xD4", + "%D4": "\xD4", + "%d5": "\xD5", + "%D5": "\xD5", + "%d6": "\xD6", + "%D6": "\xD6", + "%d7": "\xD7", + "%D7": "\xD7", + "%d8": "\xD8", + "%D8": "\xD8", + "%d9": "\xD9", + "%D9": "\xD9", + "%da": "\xDA", + "%Da": "\xDA", + "%dA": "\xDA", + "%DA": "\xDA", + "%db": "\xDB", + "%Db": "\xDB", + "%dB": "\xDB", + "%DB": "\xDB", + "%dc": "\xDC", + "%Dc": "\xDC", + "%dC": "\xDC", + "%DC": "\xDC", + "%dd": "\xDD", + "%Dd": "\xDD", + "%dD": "\xDD", + "%DD": "\xDD", + "%de": "\xDE", + "%De": "\xDE", + "%dE": "\xDE", + "%DE": "\xDE", + "%df": "\xDF", + "%Df": "\xDF", + "%dF": "\xDF", + "%DF": "\xDF", + "%e0": "\xE0", + "%E0": "\xE0", + "%e1": "\xE1", + "%E1": "\xE1", + "%e2": "\xE2", + "%E2": "\xE2", + "%e3": "\xE3", + "%E3": "\xE3", + "%e4": "\xE4", + "%E4": "\xE4", + "%e5": "\xE5", + "%E5": "\xE5", + "%e6": "\xE6", + "%E6": "\xE6", + "%e7": "\xE7", + "%E7": "\xE7", + "%e8": "\xE8", + "%E8": "\xE8", + "%e9": "\xE9", + "%E9": "\xE9", + "%ea": "\xEA", + "%Ea": "\xEA", + "%eA": "\xEA", + "%EA": "\xEA", + "%eb": "\xEB", + "%Eb": "\xEB", + "%eB": "\xEB", + "%EB": "\xEB", + "%ec": "\xEC", + "%Ec": "\xEC", + "%eC": "\xEC", + "%EC": "\xEC", + "%ed": "\xED", + "%Ed": "\xED", + "%eD": "\xED", + "%ED": "\xED", + "%ee": "\xEE", + "%Ee": "\xEE", + "%eE": "\xEE", + "%EE": "\xEE", + "%ef": "\xEF", + "%Ef": "\xEF", + "%eF": "\xEF", + "%EF": "\xEF", + "%f0": "\xF0", + "%F0": "\xF0", + "%f1": "\xF1", + "%F1": "\xF1", + "%f2": "\xF2", + "%F2": "\xF2", + "%f3": "\xF3", + "%F3": "\xF3", + "%f4": "\xF4", + "%F4": "\xF4", + "%f5": "\xF5", + "%F5": "\xF5", + "%f6": "\xF6", + "%F6": "\xF6", + "%f7": "\xF7", + "%F7": "\xF7", + "%f8": "\xF8", + "%F8": "\xF8", + "%f9": "\xF9", + "%F9": "\xF9", + "%fa": "\xFA", + "%Fa": "\xFA", + "%fA": "\xFA", + "%FA": "\xFA", + "%fb": "\xFB", + "%Fb": "\xFB", + "%fB": "\xFB", + "%FB": "\xFB", + "%fc": "\xFC", + "%Fc": "\xFC", + "%fC": "\xFC", + "%FC": "\xFC", + "%fd": "\xFD", + "%Fd": "\xFD", + "%fD": "\xFD", + "%FD": "\xFD", + "%fe": "\xFE", + "%Fe": "\xFE", + "%fE": "\xFE", + "%FE": "\xFE", + "%ff": "\xFF", + "%Ff": "\xFF", + "%fF": "\xFF", + "%FF": "\xFF" + }; + function encodedReplacer(match) { + return EncodedLookup[match]; + } + var STATE_KEY = 0; + var STATE_VALUE = 1; + var STATE_CHARSET = 2; + var STATE_LANG = 3; + function parseParams(str) { + const res = []; + let state = STATE_KEY; + let charset = ""; + let inquote = false; + let escaping = false; + let p = 0; + let tmp = ""; + const len = str.length; + for (var i2 = 0; i2 < len; ++i2) { + const char = str[i2]; + if (char === "\\" && inquote) { + if (escaping) { + escaping = false; + } else { + escaping = true; + continue; + } + } else if (char === '"') { + if (!escaping) { + if (inquote) { + inquote = false; + state = STATE_KEY; + } else { + inquote = true; + } + continue; + } else { + escaping = false; + } + } else { + if (escaping && inquote) { + tmp += "\\"; + } + escaping = false; + if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") { + if (state === STATE_CHARSET) { + state = STATE_LANG; + charset = tmp.substring(1); + } else { + state = STATE_VALUE; + } + tmp = ""; + continue; + } else if (state === STATE_KEY && (char === "*" || char === "=") && res.length) { + state = char === "*" ? STATE_CHARSET : STATE_VALUE; + res[p] = [tmp, void 0]; + tmp = ""; + continue; + } else if (!inquote && char === ";") { + state = STATE_KEY; + if (charset) { + if (tmp.length) { + tmp = decodeText( + tmp.replace(RE_ENCODED, encodedReplacer), + "binary", + charset + ); + } + charset = ""; + } else if (tmp.length) { + tmp = decodeText(tmp, "binary", "utf8"); + } + if (res[p] === void 0) { + res[p] = tmp; + } else { + res[p][1] = tmp; + } + tmp = ""; + ++p; + continue; + } else if (!inquote && (char === " " || char === " ")) { + continue; + } + } + tmp += char; + } + if (charset && tmp.length) { + tmp = decodeText( + tmp.replace(RE_ENCODED, encodedReplacer), + "binary", + charset + ); + } else if (tmp) { + tmp = decodeText(tmp, "binary", "utf8"); + } + if (res[p] === void 0) { + if (tmp) { + res[p] = tmp; + } + } else { + res[p][1] = tmp; + } + return res; + } + module2.exports = parseParams; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/basename.js +var require_basename = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) { + "use strict"; + module2.exports = function basename(path12) { + if (typeof path12 !== "string") { + return ""; + } + for (var i2 = path12.length - 1; i2 >= 0; --i2) { + switch (path12.charCodeAt(i2)) { + case 47: + // '/' + case 92: + path12 = path12.slice(i2 + 1); + return path12 === ".." || path12 === "." ? "" : path12; + } + } + return path12 === ".." || path12 === "." ? "" : path12; + }; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/types/multipart.js +var require_multipart = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/types/multipart.js"(exports2, module2) { + "use strict"; + var { Readable: Readable4 } = require("stream"); + var { inherits } = require("util"); + var Dicer = require_Dicer(); + var parseParams = require_parseParams(); + var decodeText = require_decodeText(); + var basename = require_basename(); + var getLimit = require_getLimit(); + var RE_BOUNDARY = /^boundary$/i; + var RE_FIELD = /^form-data$/i; + var RE_CHARSET = /^charset$/i; + var RE_FILENAME = /^filename$/i; + var RE_NAME = /^name$/i; + Multipart.detect = /^multipart\/form-data/i; + function Multipart(boy, cfg) { + let i2; + let len; + const self = this; + let boundary; + const limits = cfg.limits; + const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => contentType === "application/octet-stream" || fileName !== void 0); + const parsedConType = cfg.parsedConType || []; + const defCharset = cfg.defCharset || "utf8"; + const preservePath = cfg.preservePath; + const fileOpts = { highWaterMark: cfg.fileHwm }; + for (i2 = 0, len = parsedConType.length; i2 < len; ++i2) { + if (Array.isArray(parsedConType[i2]) && RE_BOUNDARY.test(parsedConType[i2][0])) { + boundary = parsedConType[i2][1]; + break; + } + } + function checkFinished() { + if (nends === 0 && finished7 && !boy._done) { + finished7 = false; + self.end(); + } + } + if (typeof boundary !== "string") { + throw new Error("Multipart: Boundary not found"); + } + const fieldSizeLimit = getLimit(limits, "fieldSize", 1 * 1024 * 1024); + const fileSizeLimit = getLimit(limits, "fileSize", Infinity); + const filesLimit = getLimit(limits, "files", Infinity); + const fieldsLimit = getLimit(limits, "fields", Infinity); + const partsLimit = getLimit(limits, "parts", Infinity); + const headerPairsLimit = getLimit(limits, "headerPairs", 2e3); + const headerSizeLimit = getLimit(limits, "headerSize", 80 * 1024); + let nfiles = 0; + let nfields = 0; + let nends = 0; + let curFile; + let curField; + let finished7 = false; + this._needDrain = false; + this._pause = false; + this._cb = void 0; + this._nparts = 0; + this._boy = boy; + const parserCfg = { + boundary, + maxHeaderPairs: headerPairsLimit, + maxHeaderSize: headerSizeLimit, + partHwm: fileOpts.highWaterMark, + highWaterMark: cfg.highWaterMark + }; + this.parser = new Dicer(parserCfg); + this.parser.on("drain", function() { + self._needDrain = false; + if (self._cb && !self._pause) { + const cb = self._cb; + self._cb = void 0; + cb(); + } + }).on("part", function onPart(part) { + if (++self._nparts > partsLimit) { + self.parser.removeListener("part", onPart); + self.parser.on("part", skipPart); + boy.hitPartsLimit = true; + boy.emit("partsLimit"); + return skipPart(part); + } + if (curField) { + const field = curField; + field.emit("end"); + field.removeAllListeners("end"); + } + part.on("header", function(header) { + let contype; + let fieldname; + let parsed; + let charset; + let encoding; + let filename; + let nsize = 0; + if (header["content-type"]) { + parsed = parseParams(header["content-type"][0]); + if (parsed[0]) { + contype = parsed[0].toLowerCase(); + for (i2 = 0, len = parsed.length; i2 < len; ++i2) { + if (RE_CHARSET.test(parsed[i2][0])) { + charset = parsed[i2][1].toLowerCase(); + break; + } + } + } + } + if (contype === void 0) { + contype = "text/plain"; + } + if (charset === void 0) { + charset = defCharset; + } + if (header["content-disposition"]) { + parsed = parseParams(header["content-disposition"][0]); + if (!RE_FIELD.test(parsed[0])) { + return skipPart(part); + } + for (i2 = 0, len = parsed.length; i2 < len; ++i2) { + if (RE_NAME.test(parsed[i2][0])) { + fieldname = parsed[i2][1]; + } else if (RE_FILENAME.test(parsed[i2][0])) { + filename = parsed[i2][1]; + if (!preservePath) { + filename = basename(filename); + } + } + } + } else { + return skipPart(part); + } + if (header["content-transfer-encoding"]) { + encoding = header["content-transfer-encoding"][0].toLowerCase(); + } else { + encoding = "7bit"; + } + let onData, onEnd; + if (isPartAFile(fieldname, contype, filename)) { + if (nfiles === filesLimit) { + if (!boy.hitFilesLimit) { + boy.hitFilesLimit = true; + boy.emit("filesLimit"); + } + return skipPart(part); + } + ++nfiles; + if (boy.listenerCount("file") === 0) { + self.parser._ignore(); + return; + } + ++nends; + const file = new FileStream(fileOpts); + curFile = file; + file.on("end", function() { + --nends; + self._pause = false; + checkFinished(); + if (self._cb && !self._needDrain) { + const cb = self._cb; + self._cb = void 0; + cb(); + } + }); + file._read = function(n2) { + if (!self._pause) { + return; + } + self._pause = false; + if (self._cb && !self._needDrain) { + const cb = self._cb; + self._cb = void 0; + cb(); + } + }; + boy.emit("file", fieldname, file, filename, encoding, contype); + onData = function(data) { + if ((nsize += data.length) > fileSizeLimit) { + const extralen = fileSizeLimit - nsize + data.length; + if (extralen > 0) { + file.push(data.slice(0, extralen)); + } + file.truncated = true; + file.bytesRead = fileSizeLimit; + part.removeAllListeners("data"); + file.emit("limit"); + return; + } else if (!file.push(data)) { + self._pause = true; + } + file.bytesRead = nsize; + }; + onEnd = function() { + curFile = void 0; + file.push(null); + }; + } else { + if (nfields === fieldsLimit) { + if (!boy.hitFieldsLimit) { + boy.hitFieldsLimit = true; + boy.emit("fieldsLimit"); + } + return skipPart(part); + } + ++nfields; + ++nends; + let buffer = ""; + let truncated = false; + curField = part; + onData = function(data) { + if ((nsize += data.length) > fieldSizeLimit) { + const extralen = fieldSizeLimit - (nsize - data.length); + buffer += data.toString("binary", 0, extralen); + truncated = true; + part.removeAllListeners("data"); + } else { + buffer += data.toString("binary"); + } + }; + onEnd = function() { + curField = void 0; + if (buffer.length) { + buffer = decodeText(buffer, "binary", charset); + } + boy.emit("field", fieldname, buffer, false, truncated, encoding, contype); + --nends; + checkFinished(); + }; + } + part._readableState.sync = false; + part.on("data", onData); + part.on("end", onEnd); + }).on("error", function(err) { + if (curFile) { + curFile.emit("error", err); + } + }); + }).on("error", function(err) { + boy.emit("error", err); + }).on("finish", function() { + finished7 = true; + checkFinished(); + }); + } + Multipart.prototype.write = function(chunk, cb) { + const r = this.parser.write(chunk); + if (r && !this._pause) { + cb(); + } else { + this._needDrain = !r; + this._cb = cb; + } + }; + Multipart.prototype.end = function() { + const self = this; + if (self.parser.writable) { + self.parser.end(); + } else if (!self._boy._done) { + process.nextTick(function() { + self._boy._done = true; + self._boy.emit("finish"); + }); + } + }; + function skipPart(part) { + part.resume(); + } + function FileStream(opts) { + Readable4.call(this, opts); + this.bytesRead = 0; + this.truncated = false; + } + inherits(FileStream, Readable4); + FileStream.prototype._read = function(n2) { + }; + module2.exports = Multipart; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/Decoder.js +var require_Decoder = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/Decoder.js"(exports2, module2) { + "use strict"; + var RE_PLUS = /\+/g; + var HEX = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ]; + function Decoder() { + this.buffer = void 0; + } + Decoder.prototype.write = function(str) { + str = str.replace(RE_PLUS, " "); + let res = ""; + let i2 = 0; + let p = 0; + const len = str.length; + for (; i2 < len; ++i2) { + if (this.buffer !== void 0) { + if (!HEX[str.charCodeAt(i2)]) { + res += "%" + this.buffer; + this.buffer = void 0; + --i2; + } else { + this.buffer += str[i2]; + ++p; + if (this.buffer.length === 2) { + res += String.fromCharCode(parseInt(this.buffer, 16)); + this.buffer = void 0; + } + } + } else if (str[i2] === "%") { + if (i2 > p) { + res += str.substring(p, i2); + p = i2; + } + this.buffer = ""; + ++p; + } + } + if (p < len && this.buffer === void 0) { + res += str.substring(p); + } + return res; + }; + Decoder.prototype.reset = function() { + this.buffer = void 0; + }; + module2.exports = Decoder; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/types/urlencoded.js +var require_urlencoded = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/types/urlencoded.js"(exports2, module2) { + "use strict"; + var Decoder = require_Decoder(); + var decodeText = require_decodeText(); + var getLimit = require_getLimit(); + var RE_CHARSET = /^charset$/i; + UrlEncoded.detect = /^application\/x-www-form-urlencoded/i; + function UrlEncoded(boy, cfg) { + const limits = cfg.limits; + const parsedConType = cfg.parsedConType; + this.boy = boy; + this.fieldSizeLimit = getLimit(limits, "fieldSize", 1 * 1024 * 1024); + this.fieldNameSizeLimit = getLimit(limits, "fieldNameSize", 100); + this.fieldsLimit = getLimit(limits, "fields", Infinity); + let charset; + for (var i2 = 0, len = parsedConType.length; i2 < len; ++i2) { + if (Array.isArray(parsedConType[i2]) && RE_CHARSET.test(parsedConType[i2][0])) { + charset = parsedConType[i2][1].toLowerCase(); + break; + } + } + if (charset === void 0) { + charset = cfg.defCharset || "utf8"; + } + this.decoder = new Decoder(); + this.charset = charset; + this._fields = 0; + this._state = "key"; + this._checkingBytes = true; + this._bytesKey = 0; + this._bytesVal = 0; + this._key = ""; + this._val = ""; + this._keyTrunc = false; + this._valTrunc = false; + this._hitLimit = false; + } + UrlEncoded.prototype.write = function(data, cb) { + if (this._fields === this.fieldsLimit) { + if (!this.boy.hitFieldsLimit) { + this.boy.hitFieldsLimit = true; + this.boy.emit("fieldsLimit"); + } + return cb(); + } + let idxeq; + let idxamp; + let i2; + let p = 0; + const len = data.length; + while (p < len) { + if (this._state === "key") { + idxeq = idxamp = void 0; + for (i2 = p; i2 < len; ++i2) { + if (!this._checkingBytes) { + ++p; + } + if (data[i2] === 61) { + idxeq = i2; + break; + } else if (data[i2] === 38) { + idxamp = i2; + break; + } + if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) { + this._hitLimit = true; + break; + } else if (this._checkingBytes) { + ++this._bytesKey; + } + } + if (idxeq !== void 0) { + if (idxeq > p) { + this._key += this.decoder.write(data.toString("binary", p, idxeq)); + } + this._state = "val"; + this._hitLimit = false; + this._checkingBytes = true; + this._val = ""; + this._bytesVal = 0; + this._valTrunc = false; + this.decoder.reset(); + p = idxeq + 1; + } else if (idxamp !== void 0) { + ++this._fields; + let key; + const keyTrunc = this._keyTrunc; + if (idxamp > p) { + key = this._key += this.decoder.write(data.toString("binary", p, idxamp)); + } else { + key = this._key; + } + this._hitLimit = false; + this._checkingBytes = true; + this._key = ""; + this._bytesKey = 0; + this._keyTrunc = false; + this.decoder.reset(); + if (key.length) { + this.boy.emit( + "field", + decodeText(key, "binary", this.charset), + "", + keyTrunc, + false + ); + } + p = idxamp + 1; + if (this._fields === this.fieldsLimit) { + return cb(); + } + } else if (this._hitLimit) { + if (i2 > p) { + this._key += this.decoder.write(data.toString("binary", p, i2)); + } + p = i2; + if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) { + this._checkingBytes = false; + this._keyTrunc = true; + } + } else { + if (p < len) { + this._key += this.decoder.write(data.toString("binary", p)); + } + p = len; + } + } else { + idxamp = void 0; + for (i2 = p; i2 < len; ++i2) { + if (!this._checkingBytes) { + ++p; + } + if (data[i2] === 38) { + idxamp = i2; + break; + } + if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) { + this._hitLimit = true; + break; + } else if (this._checkingBytes) { + ++this._bytesVal; + } + } + if (idxamp !== void 0) { + ++this._fields; + if (idxamp > p) { + this._val += this.decoder.write(data.toString("binary", p, idxamp)); + } + this.boy.emit( + "field", + decodeText(this._key, "binary", this.charset), + decodeText(this._val, "binary", this.charset), + this._keyTrunc, + this._valTrunc + ); + this._state = "key"; + this._hitLimit = false; + this._checkingBytes = true; + this._key = ""; + this._bytesKey = 0; + this._keyTrunc = false; + this.decoder.reset(); + p = idxamp + 1; + if (this._fields === this.fieldsLimit) { + return cb(); + } + } else if (this._hitLimit) { + if (i2 > p) { + this._val += this.decoder.write(data.toString("binary", p, i2)); + } + p = i2; + if (this._val === "" && this.fieldSizeLimit === 0 || (this._bytesVal = this._val.length) === this.fieldSizeLimit) { + this._checkingBytes = false; + this._valTrunc = true; + } + } else { + if (p < len) { + this._val += this.decoder.write(data.toString("binary", p)); + } + p = len; + } + } + } + cb(); + }; + UrlEncoded.prototype.end = function() { + if (this.boy._done) { + return; + } + if (this._state === "key" && this._key.length > 0) { + this.boy.emit( + "field", + decodeText(this._key, "binary", this.charset), + "", + this._keyTrunc, + false + ); + } else if (this._state === "val") { + this.boy.emit( + "field", + decodeText(this._key, "binary", this.charset), + decodeText(this._val, "binary", this.charset), + this._keyTrunc, + this._valTrunc + ); + } + this.boy._done = true; + this.boy.emit("finish"); + }; + module2.exports = UrlEncoded; + } +}); + +// ../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/main.js +var require_main = __commonJS({ + "../../node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/main.js"(exports2, module2) { + "use strict"; + var WritableStream = require("stream").Writable; + var { inherits } = require("util"); + var Dicer = require_Dicer(); + var MultipartParser = require_multipart(); + var UrlencodedParser = require_urlencoded(); + var parseParams = require_parseParams(); + function Busboy(opts) { + if (!(this instanceof Busboy)) { + return new Busboy(opts); + } + if (typeof opts !== "object") { + throw new TypeError("Busboy expected an options-Object."); + } + if (typeof opts.headers !== "object") { + throw new TypeError("Busboy expected an options-Object with headers-attribute."); + } + if (typeof opts.headers["content-type"] !== "string") { + throw new TypeError("Missing Content-Type-header."); + } + const { + headers, + ...streamOptions + } = opts; + this.opts = { + autoDestroy: false, + ...streamOptions + }; + WritableStream.call(this, this.opts); + this._done = false; + this._parser = this.getParserByHeaders(headers); + this._finished = false; + } + inherits(Busboy, WritableStream); + Busboy.prototype.emit = function(ev) { + if (ev === "finish") { + if (!this._done) { + this._parser?.end(); + return; + } else if (this._finished) { + return; + } + this._finished = true; + } + WritableStream.prototype.emit.apply(this, arguments); + }; + Busboy.prototype.getParserByHeaders = function(headers) { + const parsed = parseParams(headers["content-type"]); + const cfg = { + defCharset: this.opts.defCharset, + fileHwm: this.opts.fileHwm, + headers, + highWaterMark: this.opts.highWaterMark, + isPartAFile: this.opts.isPartAFile, + limits: this.opts.limits, + parsedConType: parsed, + preservePath: this.opts.preservePath + }; + if (MultipartParser.detect.test(parsed[0])) { + return new MultipartParser(this, cfg); + } + if (UrlencodedParser.detect.test(parsed[0])) { + return new UrlencodedParser(this, cfg); + } + throw new Error("Unsupported Content-Type."); + }; + Busboy.prototype._write = function(chunk, encoding, cb) { + this._parser.write(chunk, cb); + }; + module2.exports = Busboy; + module2.exports.default = Busboy; + module2.exports.Busboy = Busboy; + module2.exports.Dicer = Dicer; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/constants.js +var require_constants2 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/constants.js"(exports2, module2) { + "use strict"; + var { MessageChannel, receiveMessageOnPort } = require("worker_threads"); + var corsSafeListedMethods = ["GET", "HEAD", "POST"]; + var corsSafeListedMethodsSet = new Set(corsSafeListedMethods); + var nullBodyStatus = [101, 204, 205, 304]; + var redirectStatus = [301, 302, 303, 307, 308]; + var redirectStatusSet = new Set(redirectStatus); + var badPorts = [ + "1", + "7", + "9", + "11", + "13", + "15", + "17", + "19", + "20", + "21", + "22", + "23", + "25", + "37", + "42", + "43", + "53", + "69", + "77", + "79", + "87", + "95", + "101", + "102", + "103", + "104", + "109", + "110", + "111", + "113", + "115", + "117", + "119", + "123", + "135", + "137", + "139", + "143", + "161", + "179", + "389", + "427", + "465", + "512", + "513", + "514", + "515", + "526", + "530", + "531", + "532", + "540", + "548", + "554", + "556", + "563", + "587", + "601", + "636", + "989", + "990", + "993", + "995", + "1719", + "1720", + "1723", + "2049", + "3659", + "4045", + "5060", + "5061", + "6000", + "6566", + "6665", + "6666", + "6667", + "6668", + "6669", + "6697", + "10080" + ]; + var badPortsSet = new Set(badPorts); + var referrerPolicy = [ + "", + "no-referrer", + "no-referrer-when-downgrade", + "same-origin", + "origin", + "strict-origin", + "origin-when-cross-origin", + "strict-origin-when-cross-origin", + "unsafe-url" + ]; + var referrerPolicySet = new Set(referrerPolicy); + var requestRedirect = ["follow", "manual", "error"]; + var safeMethods = ["GET", "HEAD", "OPTIONS", "TRACE"]; + var safeMethodsSet = new Set(safeMethods); + var requestMode = ["navigate", "same-origin", "no-cors", "cors"]; + var requestCredentials = ["omit", "same-origin", "include"]; + var requestCache = [ + "default", + "no-store", + "reload", + "no-cache", + "force-cache", + "only-if-cached" + ]; + var requestBodyHeader = [ + "content-encoding", + "content-language", + "content-location", + "content-type", + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + "content-length" + ]; + var requestDuplex = [ + "half" + ]; + var forbiddenMethods = ["CONNECT", "TRACE", "TRACK"]; + var forbiddenMethodsSet = new Set(forbiddenMethods); + var subresource = [ + "audio", + "audioworklet", + "font", + "image", + "manifest", + "paintworklet", + "script", + "style", + "track", + "video", + "xslt", + "" + ]; + var subresourceSet = new Set(subresource); + var DOMException2 = globalThis.DOMException ?? (() => { + try { + atob("~"); + } catch (err) { + return Object.getPrototypeOf(err).constructor; + } + })(); + var channel; + var structuredClone = globalThis.structuredClone ?? // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js + // structuredClone was added in v17.0.0, but fetch supports v16.8 + function structuredClone2(value, options = void 0) { + if (arguments.length === 0) { + throw new TypeError("missing argument"); + } + if (!channel) { + channel = new MessageChannel(); + } + channel.port1.unref(); + channel.port2.unref(); + channel.port1.postMessage(value, options?.transfer); + return receiveMessageOnPort(channel.port2).message; + }; + module2.exports = { + DOMException: DOMException2, + structuredClone, + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicySet + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/global.js +var require_global = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/global.js"(exports2, module2) { + "use strict"; + var globalOrigin = /* @__PURE__ */ Symbol.for("undici.globalOrigin.1"); + function getGlobalOrigin() { + return globalThis[globalOrigin]; + } + function setGlobalOrigin(newOrigin) { + if (newOrigin === void 0) { + Object.defineProperty(globalThis, globalOrigin, { + value: void 0, + writable: true, + enumerable: false, + configurable: false + }); + return; + } + const parsedURL = new URL(newOrigin); + if (parsedURL.protocol !== "http:" && parsedURL.protocol !== "https:") { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`); + } + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }); + } + module2.exports = { + getGlobalOrigin, + setGlobalOrigin + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/util.js +var require_util2 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/util.js"(exports2, module2) { + "use strict"; + var { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require_constants2(); + var { getGlobalOrigin } = require_global(); + var { performance: performance2 } = require("perf_hooks"); + var { isBlobLike, toUSVString, ReadableStreamFrom } = require_util(); + var assert = require("assert"); + var { isUint8Array: isUint8Array2 } = require("util/types"); + var supportedHashes = []; + var crypto; + try { + crypto = require("crypto"); + const possibleRelevantHashes = ["sha256", "sha384", "sha512"]; + supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash)); + } catch { + } + function responseURL(response) { + const urlList = response.urlList; + const length = urlList.length; + return length === 0 ? null : urlList[length - 1].toString(); + } + function responseLocationURL(response, requestFragment) { + if (!redirectStatusSet.has(response.status)) { + return null; + } + let location = response.headersList.get("location"); + if (location !== null && isValidHeaderValue(location)) { + location = new URL(location, responseURL(response)); + } + if (location && !location.hash) { + location.hash = requestFragment; + } + return location; + } + function requestCurrentURL(request) { + return request.urlList[request.urlList.length - 1]; + } + function requestBadPort(request) { + const url = requestCurrentURL(request); + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return "blocked"; + } + return "allowed"; + } + function isErrorLike(object) { + return object instanceof Error || (object?.constructor?.name === "Error" || object?.constructor?.name === "DOMException"); + } + function isValidReasonPhrase(statusText) { + for (let i2 = 0; i2 < statusText.length; ++i2) { + const c3 = statusText.charCodeAt(i2); + if (!(c3 === 9 || // HTAB + c3 >= 32 && c3 <= 126 || // SP / VCHAR + c3 >= 128 && c3 <= 255)) { + return false; + } + } + return true; + } + function isTokenCharCode(c3) { + switch (c3) { + case 34: + case 40: + case 41: + case 44: + case 47: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 91: + case 92: + case 93: + case 123: + case 125: + return false; + default: + return c3 >= 33 && c3 <= 126; + } + } + function isValidHTTPToken(characters) { + if (characters.length === 0) { + return false; + } + for (let i2 = 0; i2 < characters.length; ++i2) { + if (!isTokenCharCode(characters.charCodeAt(i2))) { + return false; + } + } + return true; + } + function isValidHeaderName(potentialValue) { + return isValidHTTPToken(potentialValue); + } + function isValidHeaderValue(potentialValue) { + if (potentialValue.startsWith(" ") || potentialValue.startsWith(" ") || potentialValue.endsWith(" ") || potentialValue.endsWith(" ")) { + return false; + } + if (potentialValue.includes("\0") || potentialValue.includes("\r") || potentialValue.includes("\n")) { + return false; + } + return true; + } + function setRequestReferrerPolicyOnRedirect(request, actualResponse) { + const { headersList } = actualResponse; + const policyHeader = (headersList.get("referrer-policy") ?? "").split(","); + let policy = ""; + if (policyHeader.length > 0) { + for (let i2 = policyHeader.length; i2 !== 0; i2--) { + const token = policyHeader[i2 - 1].trim(); + if (referrerPolicyTokens.has(token)) { + policy = token; + break; + } + } + } + if (policy !== "") { + request.referrerPolicy = policy; + } + } + function crossOriginResourcePolicyCheck() { + return "allowed"; + } + function corsCheck() { + return "success"; + } + function TAOCheck() { + return "success"; + } + function appendFetchMetadata(httpRequest) { + let header = null; + header = httpRequest.mode; + httpRequest.headersList.set("sec-fetch-mode", header); + } + function appendRequestOriginHeader(request) { + let serializedOrigin = request.origin; + if (request.responseTainting === "cors" || request.mode === "websocket") { + if (serializedOrigin) { + request.headersList.append("origin", serializedOrigin); + } + } else if (request.method !== "GET" && request.method !== "HEAD") { + switch (request.referrerPolicy) { + case "no-referrer": + serializedOrigin = null; + break; + case "no-referrer-when-downgrade": + case "strict-origin": + case "strict-origin-when-cross-origin": + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null; + } + break; + case "same-origin": + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null; + } + break; + default: + } + if (serializedOrigin) { + request.headersList.append("origin", serializedOrigin); + } + } + } + function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) { + return performance2.now(); + } + function createOpaqueTimingInfo(timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null + }; + } + function makePolicyContainer() { + return { + referrerPolicy: "strict-origin-when-cross-origin" + }; + } + function clonePolicyContainer(policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy + }; + } + function determineRequestsReferrer(request) { + const policy = request.referrerPolicy; + assert(policy); + let referrerSource = null; + if (request.referrer === "client") { + const globalOrigin = getGlobalOrigin(); + if (!globalOrigin || globalOrigin.origin === "null") { + return "no-referrer"; + } + referrerSource = new URL(globalOrigin); + } else if (request.referrer instanceof URL) { + referrerSource = request.referrer; + } + let referrerURL = stripURLForReferrer(referrerSource); + const referrerOrigin = stripURLForReferrer(referrerSource, true); + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin; + } + const areSameOrigin = sameOrigin(request, referrerURL); + const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(request.url); + switch (policy) { + case "origin": + return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true); + case "unsafe-url": + return referrerURL; + case "same-origin": + return areSameOrigin ? referrerOrigin : "no-referrer"; + case "origin-when-cross-origin": + return areSameOrigin ? referrerURL : referrerOrigin; + case "strict-origin-when-cross-origin": { + const currentURL = requestCurrentURL(request); + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL; + } + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return "no-referrer"; + } + return referrerOrigin; + } + case "strict-origin": + // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + case "no-referrer-when-downgrade": + // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + default: + return isNonPotentiallyTrustWorthy ? "no-referrer" : referrerOrigin; + } + } + function stripURLForReferrer(url, originOnly) { + assert(url instanceof URL); + if (url.protocol === "file:" || url.protocol === "about:" || url.protocol === "blank:") { + return "no-referrer"; + } + url.username = ""; + url.password = ""; + url.hash = ""; + if (originOnly) { + url.pathname = ""; + url.search = ""; + } + return url; + } + function isURLPotentiallyTrustworthy(url) { + if (!(url instanceof URL)) { + return false; + } + if (url.href === "about:blank" || url.href === "about:srcdoc") { + return true; + } + if (url.protocol === "data:") return true; + if (url.protocol === "file:") return true; + return isOriginPotentiallyTrustworthy(url.origin); + function isOriginPotentiallyTrustworthy(origin) { + if (origin == null || origin === "null") return false; + const originAsURL = new URL(origin); + if (originAsURL.protocol === "https:" || originAsURL.protocol === "wss:") { + return true; + } + if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || (originAsURL.hostname === "localhost" || originAsURL.hostname.includes("localhost.")) || originAsURL.hostname.endsWith(".localhost")) { + return true; + } + return false; + } + } + function bytesMatch(bytes, metadataList) { + if (crypto === void 0) { + return true; + } + const parsedMetadata = parseMetadata(metadataList); + if (parsedMetadata === "no metadata") { + return true; + } + if (parsedMetadata.length === 0) { + return true; + } + const strongest = getStrongestMetadata(parsedMetadata); + const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest); + for (const item of metadata) { + const algorithm = item.algo; + const expectedValue = item.hash; + let actualValue = crypto.createHash(algorithm).update(bytes).digest("base64"); + if (actualValue[actualValue.length - 1] === "=") { + if (actualValue[actualValue.length - 2] === "=") { + actualValue = actualValue.slice(0, -2); + } else { + actualValue = actualValue.slice(0, -1); + } + } + if (compareBase64Mixed(actualValue, expectedValue)) { + return true; + } + } + return false; + } + var parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i; + function parseMetadata(metadata) { + const result = []; + let empty = true; + for (const token of metadata.split(" ")) { + empty = false; + const parsedToken = parseHashWithOptions.exec(token); + if (parsedToken === null || parsedToken.groups === void 0 || parsedToken.groups.algo === void 0) { + continue; + } + const algorithm = parsedToken.groups.algo.toLowerCase(); + if (supportedHashes.includes(algorithm)) { + result.push(parsedToken.groups); + } + } + if (empty === true) { + return "no metadata"; + } + return result; + } + function getStrongestMetadata(metadataList) { + let algorithm = metadataList[0].algo; + if (algorithm[3] === "5") { + return algorithm; + } + for (let i2 = 1; i2 < metadataList.length; ++i2) { + const metadata = metadataList[i2]; + if (metadata.algo[3] === "5") { + algorithm = "sha512"; + break; + } else if (algorithm[3] === "3") { + continue; + } else if (metadata.algo[3] === "3") { + algorithm = "sha384"; + } + } + return algorithm; + } + function filterMetadataListByAlgorithm(metadataList, algorithm) { + if (metadataList.length === 1) { + return metadataList; + } + let pos = 0; + for (let i2 = 0; i2 < metadataList.length; ++i2) { + if (metadataList[i2].algo === algorithm) { + metadataList[pos++] = metadataList[i2]; + } + } + metadataList.length = pos; + return metadataList; + } + function compareBase64Mixed(actualValue, expectedValue) { + if (actualValue.length !== expectedValue.length) { + return false; + } + for (let i2 = 0; i2 < actualValue.length; ++i2) { + if (actualValue[i2] !== expectedValue[i2]) { + if (actualValue[i2] === "+" && expectedValue[i2] === "-" || actualValue[i2] === "/" && expectedValue[i2] === "_") { + continue; + } + return false; + } + } + return true; + } + function tryUpgradeRequestToAPotentiallyTrustworthyURL(request) { + } + function sameOrigin(A, B) { + if (A.origin === B.origin && A.origin === "null") { + return true; + } + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true; + } + return false; + } + function createDeferredPromise() { + let res; + let rej; + const promise = new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }); + return { promise, resolve: res, reject: rej }; + } + function isAborted2(fetchParams) { + return fetchParams.controller.state === "aborted"; + } + function isCancelled(fetchParams) { + return fetchParams.controller.state === "aborted" || fetchParams.controller.state === "terminated"; + } + var normalizeMethodRecord = { + delete: "DELETE", + DELETE: "DELETE", + get: "GET", + GET: "GET", + head: "HEAD", + HEAD: "HEAD", + options: "OPTIONS", + OPTIONS: "OPTIONS", + post: "POST", + POST: "POST", + put: "PUT", + PUT: "PUT" + }; + Object.setPrototypeOf(normalizeMethodRecord, null); + function normalizeMethod(method) { + return normalizeMethodRecord[method.toLowerCase()] ?? method; + } + function serializeJavascriptValueToJSONString(value) { + const result = JSON.stringify(value); + if (result === void 0) { + throw new TypeError("Value is not JSON serializable"); + } + assert(typeof result === "string"); + return result; + } + var esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())); + function makeIterator(iterator, name, kind) { + const object = { + index: 0, + kind, + target: iterator + }; + const i2 = { + next() { + if (Object.getPrototypeOf(this) !== i2) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ); + } + const { index, kind: kind2, target } = object; + const values = target(); + const len = values.length; + if (index >= len) { + return { value: void 0, done: true }; + } + const pair = values[index]; + object.index = index + 1; + return iteratorResult(pair, kind2); + }, + // The class string of an iterator prototype object for a given interface is the + // result of concatenating the identifier of the interface and the string " Iterator". + [Symbol.toStringTag]: `${name} Iterator` + }; + Object.setPrototypeOf(i2, esIteratorPrototype); + return Object.setPrototypeOf({}, i2); + } + function iteratorResult(pair, kind) { + let result; + switch (kind) { + case "key": { + result = pair[0]; + break; + } + case "value": { + result = pair[1]; + break; + } + case "key+value": { + result = pair; + break; + } + } + return { value: result, done: false }; + } + async function fullyReadBody(body, processBody, processBodyError) { + const successSteps = processBody; + const errorSteps = processBodyError; + let reader; + try { + reader = body.stream.getReader(); + } catch (e) { + errorSteps(e); + return; + } + try { + const result = await readAllBytes(reader); + successSteps(result); + } catch (e) { + errorSteps(e); + } + } + var ReadableStream2 = globalThis.ReadableStream; + function isReadableStreamLike(stream) { + if (!ReadableStream2) { + ReadableStream2 = require("stream/web").ReadableStream; + } + return stream instanceof ReadableStream2 || stream[Symbol.toStringTag] === "ReadableStream" && typeof stream.tee === "function"; + } + var MAXIMUM_ARGUMENT_LENGTH = 65535; + function isomorphicDecode(input) { + if (input.length < MAXIMUM_ARGUMENT_LENGTH) { + return String.fromCharCode(...input); + } + return input.reduce((previous, current) => previous + String.fromCharCode(current), ""); + } + function readableStreamClose(controller) { + try { + controller.close(); + } catch (err) { + if (!err.message.includes("Controller is already closed")) { + throw err; + } + } + } + function isomorphicEncode(input) { + for (let i2 = 0; i2 < input.length; i2++) { + assert(input.charCodeAt(i2) <= 255); + } + return input; + } + async function readAllBytes(reader) { + const bytes = []; + let byteLength = 0; + while (true) { + const { done, value: chunk } = await reader.read(); + if (done) { + return Buffer.concat(bytes, byteLength); + } + if (!isUint8Array2(chunk)) { + throw new TypeError("Received non-Uint8Array chunk"); + } + bytes.push(chunk); + byteLength += chunk.length; + } + } + function urlIsLocal(url) { + assert("protocol" in url); + const protocol = url.protocol; + return protocol === "about:" || protocol === "blob:" || protocol === "data:"; + } + function urlHasHttpsScheme(url) { + if (typeof url === "string") { + return url.startsWith("https:"); + } + return url.protocol === "https:"; + } + function urlIsHttpHttpsScheme(url) { + assert("protocol" in url); + const protocol = url.protocol; + return protocol === "http:" || protocol === "https:"; + } + var hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key)); + module2.exports = { + isAborted: isAborted2, + isCancelled, + createDeferredPromise, + ReadableStreamFrom, + toUSVString, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isBlobLike, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + serializeJavascriptValueToJSONString, + makeIterator, + isValidHeaderName, + isValidHeaderValue, + hasOwn, + isErrorLike, + fullyReadBody, + bytesMatch, + isReadableStreamLike, + readableStreamClose, + isomorphicEncode, + isomorphicDecode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + normalizeMethodRecord, + parseMetadata + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/symbols.js +var require_symbols2 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kUrl: /* @__PURE__ */ Symbol("url"), + kHeaders: /* @__PURE__ */ Symbol("headers"), + kSignal: /* @__PURE__ */ Symbol("signal"), + kState: /* @__PURE__ */ Symbol("state"), + kGuard: /* @__PURE__ */ Symbol("guard"), + kRealm: /* @__PURE__ */ Symbol("realm") + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/webidl.js +var require_webidl = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/webidl.js"(exports2, module2) { + "use strict"; + var { types } = require("util"); + var { hasOwn, toUSVString } = require_util2(); + var webidl = {}; + webidl.converters = {}; + webidl.util = {}; + webidl.errors = {}; + webidl.errors.exception = function(message) { + return new TypeError(`${message.header}: ${message.message}`); + }; + webidl.errors.conversionFailed = function(context) { + const plural = context.types.length === 1 ? "" : " one of"; + const message = `${context.argument} could not be converted to${plural}: ${context.types.join(", ")}.`; + return webidl.errors.exception({ + header: context.prefix, + message + }); + }; + webidl.errors.invalidArgument = function(context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }); + }; + webidl.brandCheck = function(V, I, opts = void 0) { + if (opts?.strict !== false && !(V instanceof I)) { + throw new TypeError("Illegal invocation"); + } else { + return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag]; + } + }; + webidl.argumentLengthCheck = function({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? "s" : ""} required, but${length ? " only" : ""} ${length} found.`, + ...ctx + }); + } + }; + webidl.illegalConstructor = function() { + throw webidl.errors.exception({ + header: "TypeError", + message: "Illegal constructor" + }); + }; + webidl.util.Type = function(V) { + switch (typeof V) { + case "undefined": + return "Undefined"; + case "boolean": + return "Boolean"; + case "string": + return "String"; + case "symbol": + return "Symbol"; + case "number": + return "Number"; + case "bigint": + return "BigInt"; + case "function": + case "object": { + if (V === null) { + return "Null"; + } + return "Object"; + } + } + }; + webidl.util.ConvertToInt = function(V, bitLength, signedness, opts = {}) { + let upperBound; + let lowerBound; + if (bitLength === 64) { + upperBound = Math.pow(2, 53) - 1; + if (signedness === "unsigned") { + lowerBound = 0; + } else { + lowerBound = Math.pow(-2, 53) + 1; + } + } else if (signedness === "unsigned") { + lowerBound = 0; + upperBound = Math.pow(2, bitLength) - 1; + } else { + lowerBound = Math.pow(-2, bitLength) - 1; + upperBound = Math.pow(2, bitLength - 1) - 1; + } + let x = Number(V); + if (x === 0) { + x = 0; + } + if (opts.enforceRange === true) { + if (Number.isNaN(x) || x === Number.POSITIVE_INFINITY || x === Number.NEGATIVE_INFINITY) { + throw webidl.errors.exception({ + header: "Integer conversion", + message: `Could not convert ${V} to an integer.` + }); + } + x = webidl.util.IntegerPart(x); + if (x < lowerBound || x > upperBound) { + throw webidl.errors.exception({ + header: "Integer conversion", + message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` + }); + } + return x; + } + if (!Number.isNaN(x) && opts.clamp === true) { + x = Math.min(Math.max(x, lowerBound), upperBound); + if (Math.floor(x) % 2 === 0) { + x = Math.floor(x); + } else { + x = Math.ceil(x); + } + return x; + } + if (Number.isNaN(x) || x === 0 && Object.is(0, x) || x === Number.POSITIVE_INFINITY || x === Number.NEGATIVE_INFINITY) { + return 0; + } + x = webidl.util.IntegerPart(x); + x = x % Math.pow(2, bitLength); + if (signedness === "signed" && x >= Math.pow(2, bitLength) - 1) { + return x - Math.pow(2, bitLength); + } + return x; + }; + webidl.util.IntegerPart = function(n2) { + const r = Math.floor(Math.abs(n2)); + if (n2 < 0) { + return -1 * r; + } + return r; + }; + webidl.sequenceConverter = function(converter) { + return (V) => { + if (webidl.util.Type(V) !== "Object") { + throw webidl.errors.exception({ + header: "Sequence", + message: `Value of type ${webidl.util.Type(V)} is not an Object.` + }); + } + const method = V?.[Symbol.iterator]?.(); + const seq = []; + if (method === void 0 || typeof method.next !== "function") { + throw webidl.errors.exception({ + header: "Sequence", + message: "Object is not an iterator." + }); + } + while (true) { + const { done, value } = method.next(); + if (done) { + break; + } + seq.push(converter(value)); + } + return seq; + }; + }; + webidl.recordConverter = function(keyConverter, valueConverter) { + return (O) => { + if (webidl.util.Type(O) !== "Object") { + throw webidl.errors.exception({ + header: "Record", + message: `Value of type ${webidl.util.Type(O)} is not an Object.` + }); + } + const result = {}; + if (!types.isProxy(O)) { + const keys2 = Object.keys(O); + for (const key of keys2) { + const typedKey = keyConverter(key); + const typedValue = valueConverter(O[key]); + result[typedKey] = typedValue; + } + return result; + } + const keys = Reflect.ownKeys(O); + for (const key of keys) { + const desc = Reflect.getOwnPropertyDescriptor(O, key); + if (desc?.enumerable) { + const typedKey = keyConverter(key); + const typedValue = valueConverter(O[key]); + result[typedKey] = typedValue; + } + } + return result; + }; + }; + webidl.interfaceConverter = function(i2) { + return (V, opts = {}) => { + if (opts.strict !== false && !(V instanceof i2)) { + throw webidl.errors.exception({ + header: i2.name, + message: `Expected ${V} to be an instance of ${i2.name}.` + }); + } + return V; + }; + }; + webidl.dictionaryConverter = function(converters) { + return (dictionary) => { + const type = webidl.util.Type(dictionary); + const dict = {}; + if (type === "Null" || type === "Undefined") { + return dict; + } else if (type !== "Object") { + throw webidl.errors.exception({ + header: "Dictionary", + message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` + }); + } + for (const options of converters) { + const { key, defaultValue, required, converter } = options; + if (required === true) { + if (!hasOwn(dictionary, key)) { + throw webidl.errors.exception({ + header: "Dictionary", + message: `Missing required key "${key}".` + }); + } + } + let value = dictionary[key]; + const hasDefault = hasOwn(options, "defaultValue"); + if (hasDefault && value !== null) { + value = value ?? defaultValue; + } + if (required || hasDefault || value !== void 0) { + value = converter(value); + if (options.allowedValues && !options.allowedValues.includes(value)) { + throw webidl.errors.exception({ + header: "Dictionary", + message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(", ")}.` + }); + } + dict[key] = value; + } + } + return dict; + }; + }; + webidl.nullableConverter = function(converter) { + return (V) => { + if (V === null) { + return V; + } + return converter(V); + }; + }; + webidl.converters.DOMString = function(V, opts = {}) { + if (V === null && opts.legacyNullToEmptyString) { + return ""; + } + if (typeof V === "symbol") { + throw new TypeError("Could not convert argument of type symbol to string."); + } + return String(V); + }; + webidl.converters.ByteString = function(V) { + const x = webidl.converters.DOMString(V); + for (let index = 0; index < x.length; index++) { + if (x.charCodeAt(index) > 255) { + throw new TypeError( + `Cannot convert argument to a ByteString because the character at index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` + ); + } + } + return x; + }; + webidl.converters.USVString = toUSVString; + webidl.converters.boolean = function(V) { + const x = Boolean(V); + return x; + }; + webidl.converters.any = function(V) { + return V; + }; + webidl.converters["long long"] = function(V) { + const x = webidl.util.ConvertToInt(V, 64, "signed"); + return x; + }; + webidl.converters["unsigned long long"] = function(V) { + const x = webidl.util.ConvertToInt(V, 64, "unsigned"); + return x; + }; + webidl.converters["unsigned long"] = function(V) { + const x = webidl.util.ConvertToInt(V, 32, "unsigned"); + return x; + }; + webidl.converters["unsigned short"] = function(V, opts) { + const x = webidl.util.ConvertToInt(V, 16, "unsigned", opts); + return x; + }; + webidl.converters.ArrayBuffer = function(V, opts = {}) { + if (webidl.util.Type(V) !== "Object" || !types.isAnyArrayBuffer(V)) { + throw webidl.errors.conversionFailed({ + prefix: `${V}`, + argument: `${V}`, + types: ["ArrayBuffer"] + }); + } + if (opts.allowShared === false && types.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: "ArrayBuffer", + message: "SharedArrayBuffer is not allowed." + }); + } + return V; + }; + webidl.converters.TypedArray = function(V, T, opts = {}) { + if (webidl.util.Type(V) !== "Object" || !types.isTypedArray(V) || V.constructor.name !== T.name) { + throw webidl.errors.conversionFailed({ + prefix: `${T.name}`, + argument: `${V}`, + types: [T.name] + }); + } + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: "ArrayBuffer", + message: "SharedArrayBuffer is not allowed." + }); + } + return V; + }; + webidl.converters.DataView = function(V, opts = {}) { + if (webidl.util.Type(V) !== "Object" || !types.isDataView(V)) { + throw webidl.errors.exception({ + header: "DataView", + message: "Object is not a DataView." + }); + } + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: "ArrayBuffer", + message: "SharedArrayBuffer is not allowed." + }); + } + return V; + }; + webidl.converters.BufferSource = function(V, opts = {}) { + if (types.isAnyArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, opts); + } + if (types.isTypedArray(V)) { + return webidl.converters.TypedArray(V, V.constructor); + } + if (types.isDataView(V)) { + return webidl.converters.DataView(V, opts); + } + throw new TypeError(`Could not convert ${V} to a BufferSource.`); + }; + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.ByteString + ); + webidl.converters["sequence>"] = webidl.sequenceConverter( + webidl.converters["sequence"] + ); + webidl.converters["record"] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString + ); + module2.exports = { + webidl + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/dataURL.js +var require_dataURL = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/dataURL.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var { atob: atob2 } = require("buffer"); + var { isomorphicDecode } = require_util2(); + var encoder = new TextEncoder(); + var HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/; + var HTTP_WHITESPACE_REGEX = /(\u000A|\u000D|\u0009|\u0020)/; + var HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/; + function dataURLProcessor(dataURL) { + assert(dataURL.protocol === "data:"); + let input = URLSerializer(dataURL, true); + input = input.slice(5); + const position = { position: 0 }; + let mimeType = collectASequenceOfCodePointsFast( + ",", + input, + position + ); + const mimeTypeLength = mimeType.length; + mimeType = removeASCIIWhitespace(mimeType, true, true); + if (position.position >= input.length) { + return "failure"; + } + position.position++; + const encodedBody = input.slice(mimeTypeLength + 1); + let body = stringPercentDecode(encodedBody); + if (/;(\u0020){0,}base64$/i.test(mimeType)) { + const stringBody = isomorphicDecode(body); + body = forgivingBase64(stringBody); + if (body === "failure") { + return "failure"; + } + mimeType = mimeType.slice(0, -6); + mimeType = mimeType.replace(/(\u0020)+$/, ""); + mimeType = mimeType.slice(0, -1); + } + if (mimeType.startsWith(";")) { + mimeType = "text/plain" + mimeType; + } + let mimeTypeRecord = parseMIMEType(mimeType); + if (mimeTypeRecord === "failure") { + mimeTypeRecord = parseMIMEType("text/plain;charset=US-ASCII"); + } + return { mimeType: mimeTypeRecord, body }; + } + function URLSerializer(url, excludeFragment = false) { + if (!excludeFragment) { + return url.href; + } + const href = url.href; + const hashLength = url.hash.length; + return hashLength === 0 ? href : href.substring(0, href.length - hashLength); + } + function collectASequenceOfCodePoints(condition, input, position) { + let result = ""; + while (position.position < input.length && condition(input[position.position])) { + result += input[position.position]; + position.position++; + } + return result; + } + function collectASequenceOfCodePointsFast(char, input, position) { + const idx = input.indexOf(char, position.position); + const start = position.position; + if (idx === -1) { + position.position = input.length; + return input.slice(start); + } + position.position = idx; + return input.slice(start, position.position); + } + function stringPercentDecode(input) { + const bytes = encoder.encode(input); + return percentDecode(bytes); + } + function percentDecode(input) { + const output = []; + for (let i2 = 0; i2 < input.length; i2++) { + const byte = input[i2]; + if (byte !== 37) { + output.push(byte); + } else if (byte === 37 && !/^[0-9A-Fa-f]{2}$/i.test(String.fromCharCode(input[i2 + 1], input[i2 + 2]))) { + output.push(37); + } else { + const nextTwoBytes = String.fromCharCode(input[i2 + 1], input[i2 + 2]); + const bytePoint = Number.parseInt(nextTwoBytes, 16); + output.push(bytePoint); + i2 += 2; + } + } + return Uint8Array.from(output); + } + function parseMIMEType(input) { + input = removeHTTPWhitespace(input, true, true); + const position = { position: 0 }; + const type = collectASequenceOfCodePointsFast( + "/", + input, + position + ); + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return "failure"; + } + if (position.position > input.length) { + return "failure"; + } + position.position++; + let subtype = collectASequenceOfCodePointsFast( + ";", + input, + position + ); + subtype = removeHTTPWhitespace(subtype, false, true); + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return "failure"; + } + const typeLowercase = type.toLowerCase(); + const subtypeLowercase = subtype.toLowerCase(); + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: /* @__PURE__ */ new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` + }; + while (position.position < input.length) { + position.position++; + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + (char) => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ); + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ";" && char !== "=", + input, + position + ); + parameterName = parameterName.toLowerCase(); + if (position.position < input.length) { + if (input[position.position] === ";") { + continue; + } + position.position++; + } + if (position.position > input.length) { + break; + } + let parameterValue = null; + if (input[position.position] === '"') { + parameterValue = collectAnHTTPQuotedString(input, position, true); + collectASequenceOfCodePointsFast( + ";", + input, + position + ); + } else { + parameterValue = collectASequenceOfCodePointsFast( + ";", + input, + position + ); + parameterValue = removeHTTPWhitespace(parameterValue, false, true); + if (parameterValue.length === 0) { + continue; + } + } + if (parameterName.length !== 0 && HTTP_TOKEN_CODEPOINTS.test(parameterName) && (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && !mimeType.parameters.has(parameterName)) { + mimeType.parameters.set(parameterName, parameterValue); + } + } + return mimeType; + } + function forgivingBase64(data) { + data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, ""); + if (data.length % 4 === 0) { + data = data.replace(/=?=$/, ""); + } + if (data.length % 4 === 1) { + return "failure"; + } + if (/[^+/0-9A-Za-z]/.test(data)) { + return "failure"; + } + const binary = atob2(data); + const bytes = new Uint8Array(binary.length); + for (let byte = 0; byte < binary.length; byte++) { + bytes[byte] = binary.charCodeAt(byte); + } + return bytes; + } + function collectAnHTTPQuotedString(input, position, extractValue) { + const positionStart = position.position; + let value = ""; + assert(input[position.position] === '"'); + position.position++; + while (true) { + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== "\\", + input, + position + ); + if (position.position >= input.length) { + break; + } + const quoteOrBackslash = input[position.position]; + position.position++; + if (quoteOrBackslash === "\\") { + if (position.position >= input.length) { + value += "\\"; + break; + } + value += input[position.position]; + position.position++; + } else { + assert(quoteOrBackslash === '"'); + break; + } + } + if (extractValue) { + return value; + } + return input.slice(positionStart, position.position); + } + function serializeAMimeType(mimeType) { + assert(mimeType !== "failure"); + const { parameters, essence } = mimeType; + let serialization = essence; + for (let [name, value] of parameters.entries()) { + serialization += ";"; + serialization += name; + serialization += "="; + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + value = value.replace(/(\\|")/g, "\\$1"); + value = '"' + value; + value += '"'; + } + serialization += value; + } + return serialization; + } + function isHTTPWhiteSpace(char) { + return char === "\r" || char === "\n" || char === " " || char === " "; + } + function removeHTTPWhitespace(str, leading = true, trailing = true) { + let lead = 0; + let trail = str.length - 1; + if (leading) { + for (; lead < str.length && isHTTPWhiteSpace(str[lead]); lead++) ; + } + if (trailing) { + for (; trail > 0 && isHTTPWhiteSpace(str[trail]); trail--) ; + } + return str.slice(lead, trail + 1); + } + function isASCIIWhitespace(char) { + return char === "\r" || char === "\n" || char === " " || char === "\f" || char === " "; + } + function removeASCIIWhitespace(str, leading = true, trailing = true) { + let lead = 0; + let trail = str.length - 1; + if (leading) { + for (; lead < str.length && isASCIIWhitespace(str[lead]); lead++) ; + } + if (trailing) { + for (; trail > 0 && isASCIIWhitespace(str[trail]); trail--) ; + } + return str.slice(lead, trail + 1); + } + module2.exports = { + dataURLProcessor, + URLSerializer, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/file.js +var require_file = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/file.js"(exports2, module2) { + "use strict"; + var { Blob: Blob2, File: NativeFile } = require("buffer"); + var { types } = require("util"); + var { kState } = require_symbols2(); + var { isBlobLike } = require_util2(); + var { webidl } = require_webidl(); + var { parseMIMEType, serializeAMimeType } = require_dataURL(); + var { kEnumerableProperty } = require_util(); + var encoder = new TextEncoder(); + var File = class _File extends Blob2 { + constructor(fileBits, fileName, options = {}) { + webidl.argumentLengthCheck(arguments, 2, { header: "File constructor" }); + fileBits = webidl.converters["sequence"](fileBits); + fileName = webidl.converters.USVString(fileName); + options = webidl.converters.FilePropertyBag(options); + const n2 = fileName; + let t = options.type; + let d; + substep: { + if (t) { + t = parseMIMEType(t); + if (t === "failure") { + t = ""; + break substep; + } + t = serializeAMimeType(t).toLowerCase(); + } + d = options.lastModified; + } + super(processBlobParts(fileBits, options), { type: t }); + this[kState] = { + name: n2, + lastModified: d, + type: t + }; + } + get name() { + webidl.brandCheck(this, _File); + return this[kState].name; + } + get lastModified() { + webidl.brandCheck(this, _File); + return this[kState].lastModified; + } + get type() { + webidl.brandCheck(this, _File); + return this[kState].type; + } + }; + var FileLike = class _FileLike { + constructor(blobLike, fileName, options = {}) { + const n2 = fileName; + const t = options.type; + const d = options.lastModified ?? Date.now(); + this[kState] = { + blobLike, + name: n2, + type: t, + lastModified: d + }; + } + stream(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.stream(...args); + } + arrayBuffer(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.arrayBuffer(...args); + } + slice(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.slice(...args); + } + text(...args) { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.text(...args); + } + get size() { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.size; + } + get type() { + webidl.brandCheck(this, _FileLike); + return this[kState].blobLike.type; + } + get name() { + webidl.brandCheck(this, _FileLike); + return this[kState].name; + } + get lastModified() { + webidl.brandCheck(this, _FileLike); + return this[kState].lastModified; + } + get [Symbol.toStringTag]() { + return "File"; + } + }; + Object.defineProperties(File.prototype, { + [Symbol.toStringTag]: { + value: "File", + configurable: true + }, + name: kEnumerableProperty, + lastModified: kEnumerableProperty + }); + webidl.converters.Blob = webidl.interfaceConverter(Blob2); + webidl.converters.BlobPart = function(V, opts) { + if (webidl.util.Type(V) === "Object") { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }); + } + if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { + return webidl.converters.BufferSource(V, opts); + } + } + return webidl.converters.USVString(V, opts); + }; + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.BlobPart + ); + webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ + { + key: "lastModified", + converter: webidl.converters["long long"], + get defaultValue() { + return Date.now(); + } + }, + { + key: "type", + converter: webidl.converters.DOMString, + defaultValue: "" + }, + { + key: "endings", + converter: (value) => { + value = webidl.converters.DOMString(value); + value = value.toLowerCase(); + if (value !== "native") { + value = "transparent"; + } + return value; + }, + defaultValue: "transparent" + } + ]); + function processBlobParts(parts, options) { + const bytes = []; + for (const element of parts) { + if (typeof element === "string") { + let s = element; + if (options.endings === "native") { + s = convertLineEndingsNative(s); + } + bytes.push(encoder.encode(s)); + } else if (types.isAnyArrayBuffer(element) || types.isTypedArray(element)) { + if (!element.buffer) { + bytes.push(new Uint8Array(element)); + } else { + bytes.push( + new Uint8Array(element.buffer, element.byteOffset, element.byteLength) + ); + } + } else if (isBlobLike(element)) { + bytes.push(element); + } + } + return bytes; + } + function convertLineEndingsNative(s) { + let nativeLineEnding = "\n"; + if (process.platform === "win32") { + nativeLineEnding = "\r\n"; + } + return s.replace(/\r?\n/g, nativeLineEnding); + } + function isFileLike(object) { + return NativeFile && object instanceof NativeFile || object instanceof File || object && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && object[Symbol.toStringTag] === "File"; + } + module2.exports = { File, FileLike, isFileLike }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/formdata.js +var require_formdata = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/formdata.js"(exports2, module2) { + "use strict"; + var { isBlobLike, toUSVString, makeIterator } = require_util2(); + var { kState } = require_symbols2(); + var { File: UndiciFile, FileLike, isFileLike } = require_file(); + var { webidl } = require_webidl(); + var { Blob: Blob2, File: NativeFile } = require("buffer"); + var File = NativeFile ?? UndiciFile; + var FormData = class _FormData { + constructor(form) { + if (form !== void 0) { + throw webidl.errors.conversionFailed({ + prefix: "FormData constructor", + argument: "Argument 1", + types: ["undefined"] + }); + } + this[kState] = []; + } + append(name, value, filename = void 0) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 2, { header: "FormData.append" }); + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" + ); + } + name = webidl.converters.USVString(name); + value = isBlobLike(value) ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value); + filename = arguments.length === 3 ? webidl.converters.USVString(filename) : void 0; + const entry = makeEntry(name, value, filename); + this[kState].push(entry); + } + delete(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.delete" }); + name = webidl.converters.USVString(name); + this[kState] = this[kState].filter((entry) => entry.name !== name); + } + get(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.get" }); + name = webidl.converters.USVString(name); + const idx = this[kState].findIndex((entry) => entry.name === name); + if (idx === -1) { + return null; + } + return this[kState][idx].value; + } + getAll(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.getAll" }); + name = webidl.converters.USVString(name); + return this[kState].filter((entry) => entry.name === name).map((entry) => entry.value); + } + has(name) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.has" }); + name = webidl.converters.USVString(name); + return this[kState].findIndex((entry) => entry.name === name) !== -1; + } + set(name, value, filename = void 0) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 2, { header: "FormData.set" }); + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" + ); + } + name = webidl.converters.USVString(name); + value = isBlobLike(value) ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value); + filename = arguments.length === 3 ? toUSVString(filename) : void 0; + const entry = makeEntry(name, value, filename); + const idx = this[kState].findIndex((entry2) => entry2.name === name); + if (idx !== -1) { + this[kState] = [ + ...this[kState].slice(0, idx), + entry, + ...this[kState].slice(idx + 1).filter((entry2) => entry2.name !== name) + ]; + } else { + this[kState].push(entry); + } + } + entries() { + webidl.brandCheck(this, _FormData); + return makeIterator( + () => this[kState].map((pair) => [pair.name, pair.value]), + "FormData", + "key+value" + ); + } + keys() { + webidl.brandCheck(this, _FormData); + return makeIterator( + () => this[kState].map((pair) => [pair.name, pair.value]), + "FormData", + "key" + ); + } + values() { + webidl.brandCheck(this, _FormData); + return makeIterator( + () => this[kState].map((pair) => [pair.name, pair.value]), + "FormData", + "value" + ); + } + /** + * @param {(value: string, key: string, self: FormData) => void} callbackFn + * @param {unknown} thisArg + */ + forEach(callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, _FormData); + webidl.argumentLengthCheck(arguments, 1, { header: "FormData.forEach" }); + if (typeof callbackFn !== "function") { + throw new TypeError( + "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." + ); + } + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]); + } + } + }; + FormData.prototype[Symbol.iterator] = FormData.prototype.entries; + Object.defineProperties(FormData.prototype, { + [Symbol.toStringTag]: { + value: "FormData", + configurable: true + } + }); + function makeEntry(name, value, filename) { + name = Buffer.from(name).toString("utf8"); + if (typeof value === "string") { + value = Buffer.from(value).toString("utf8"); + } else { + if (!isFileLike(value)) { + value = value instanceof Blob2 ? new File([value], "blob", { type: value.type }) : new FileLike(value, "blob", { type: value.type }); + } + if (filename !== void 0) { + const options = { + type: value.type, + lastModified: value.lastModified + }; + value = NativeFile && value instanceof NativeFile || value instanceof UndiciFile ? new File([value], filename, options) : new FileLike(value, filename, options); + } + } + return { name, value }; + } + module2.exports = { FormData }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/body.js +var require_body = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/body.js"(exports2, module2) { + "use strict"; + var Busboy = require_main(); + var util2 = require_util(); + var { + ReadableStreamFrom, + isBlobLike, + isReadableStreamLike, + readableStreamClose, + createDeferredPromise, + fullyReadBody + } = require_util2(); + var { FormData } = require_formdata(); + var { kState } = require_symbols2(); + var { webidl } = require_webidl(); + var { DOMException: DOMException2, structuredClone } = require_constants2(); + var { Blob: Blob2, File: NativeFile } = require("buffer"); + var { kBodyUsed } = require_symbols(); + var assert = require("assert"); + var { isErrored } = require_util(); + var { isUint8Array: isUint8Array2, isArrayBuffer: isArrayBuffer2 } = require("util/types"); + var { File: UndiciFile } = require_file(); + var { parseMIMEType, serializeAMimeType } = require_dataURL(); + var random; + try { + const crypto = require("crypto"); + random = (max) => crypto.randomInt(0, max); + } catch { + random = (max) => Math.floor(Math.random(max)); + } + var ReadableStream2 = globalThis.ReadableStream; + var File = NativeFile ?? UndiciFile; + var textEncoder3 = new TextEncoder(); + var textDecoder2 = new TextDecoder(); + function extractBody(object, keepalive = false) { + if (!ReadableStream2) { + ReadableStream2 = require("stream/web").ReadableStream; + } + let stream = null; + if (object instanceof ReadableStream2) { + stream = object; + } else if (isBlobLike(object)) { + stream = object.stream(); + } else { + stream = new ReadableStream2({ + async pull(controller) { + controller.enqueue( + typeof source === "string" ? textEncoder3.encode(source) : source + ); + queueMicrotask(() => readableStreamClose(controller)); + }, + start() { + }, + type: void 0 + }); + } + assert(isReadableStreamLike(stream)); + let action = null; + let source = null; + let length = null; + let type = null; + if (typeof object === "string") { + source = object; + type = "text/plain;charset=UTF-8"; + } else if (object instanceof URLSearchParams) { + source = object.toString(); + type = "application/x-www-form-urlencoded;charset=UTF-8"; + } else if (isArrayBuffer2(object)) { + source = new Uint8Array(object.slice()); + } else if (ArrayBuffer.isView(object)) { + source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)); + } else if (util2.isFormDataLike(object)) { + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`; + const prefix = `--${boundary}\r +Content-Disposition: form-data`; + const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n"); + const blobParts = []; + const rn = new Uint8Array([13, 10]); + length = 0; + let hasUnknownSizeValue = false; + for (const [name, value] of object) { + if (typeof value === "string") { + const chunk2 = textEncoder3.encode(prefix + `; name="${escape(normalizeLinefeeds(name))}"\r +\r +${normalizeLinefeeds(value)}\r +`); + blobParts.push(chunk2); + length += chunk2.byteLength; + } else { + const chunk2 = textEncoder3.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + (value.name ? `; filename="${escape(value.name)}"` : "") + `\r +Content-Type: ${value.type || "application/octet-stream"}\r +\r +`); + blobParts.push(chunk2, value, rn); + if (typeof value.size === "number") { + length += chunk2.byteLength + value.size + rn.byteLength; + } else { + hasUnknownSizeValue = true; + } + } + } + const chunk = textEncoder3.encode(`--${boundary}--`); + blobParts.push(chunk); + length += chunk.byteLength; + if (hasUnknownSizeValue) { + length = null; + } + source = object; + action = async function* () { + for (const part of blobParts) { + if (part.stream) { + yield* part.stream(); + } else { + yield part; + } + } + }; + type = "multipart/form-data; boundary=" + boundary; + } else if (isBlobLike(object)) { + source = object; + length = object.size; + if (object.type) { + type = object.type; + } + } else if (typeof object[Symbol.asyncIterator] === "function") { + if (keepalive) { + throw new TypeError("keepalive"); + } + if (util2.isDisturbed(object) || object.locked) { + throw new TypeError( + "Response body object should not be disturbed or locked" + ); + } + stream = object instanceof ReadableStream2 ? object : ReadableStreamFrom(object); + } + if (typeof source === "string" || util2.isBuffer(source)) { + length = Buffer.byteLength(source); + } + if (action != null) { + let iterator; + stream = new ReadableStream2({ + async start() { + iterator = action(object)[Symbol.asyncIterator](); + }, + async pull(controller) { + const { value, done } = await iterator.next(); + if (done) { + queueMicrotask(() => { + controller.close(); + }); + } else { + if (!isErrored(stream)) { + controller.enqueue(new Uint8Array(value)); + } + } + return controller.desiredSize > 0; + }, + async cancel(reason) { + await iterator.return(); + }, + type: void 0 + }); + } + const body = { stream, source, length }; + return [body, type]; + } + function safelyExtractBody(object, keepalive = false) { + if (!ReadableStream2) { + ReadableStream2 = require("stream/web").ReadableStream; + } + if (object instanceof ReadableStream2) { + assert(!util2.isDisturbed(object), "The body has already been consumed."); + assert(!object.locked, "The stream is locked."); + } + return extractBody(object, keepalive); + } + function cloneBody(body) { + const [out1, out2] = body.stream.tee(); + const out2Clone = structuredClone(out2, { transfer: [out2] }); + const [, finalClone] = out2Clone.tee(); + body.stream = out1; + return { + stream: finalClone, + length: body.length, + source: body.source + }; + } + async function* consumeBody(body) { + if (body) { + if (isUint8Array2(body)) { + yield body; + } else { + const stream = body.stream; + if (util2.isDisturbed(stream)) { + throw new TypeError("The body has already been consumed."); + } + if (stream.locked) { + throw new TypeError("The stream is locked."); + } + stream[kBodyUsed] = true; + yield* stream; + } + } + } + function throwIfAborted(state) { + if (state.aborted) { + throw new DOMException2("The operation was aborted.", "AbortError"); + } + } + function bodyMixinMethods(instance) { + const methods = { + blob() { + return specConsumeBody(this, (bytes) => { + let mimeType = bodyMimeType(this); + if (mimeType === "failure") { + mimeType = ""; + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType); + } + return new Blob2([bytes], { type: mimeType }); + }, instance); + }, + arrayBuffer() { + return specConsumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer; + }, instance); + }, + text() { + return specConsumeBody(this, utf8DecodeBytes, instance); + }, + json() { + return specConsumeBody(this, parseJSONFromBytes, instance); + }, + async formData() { + webidl.brandCheck(this, instance); + throwIfAborted(this[kState]); + const contentType = this.headers.get("Content-Type"); + if (/multipart\/form-data/.test(contentType)) { + const headers = {}; + for (const [key, value] of this.headers) headers[key.toLowerCase()] = value; + const responseFormData = new FormData(); + let busboy; + try { + busboy = new Busboy({ + headers, + preservePath: true + }); + } catch (err) { + throw new DOMException2(`${err}`, "AbortError"); + } + busboy.on("field", (name, value) => { + responseFormData.append(name, value); + }); + busboy.on("file", (name, value, filename, encoding, mimeType) => { + const chunks = []; + if (encoding === "base64" || encoding.toLowerCase() === "base64") { + let base64chunk = ""; + value.on("data", (chunk) => { + base64chunk += chunk.toString().replace(/[\r\n]/gm, ""); + const end = base64chunk.length - base64chunk.length % 4; + chunks.push(Buffer.from(base64chunk.slice(0, end), "base64")); + base64chunk = base64chunk.slice(end); + }); + value.on("end", () => { + chunks.push(Buffer.from(base64chunk, "base64")); + responseFormData.append(name, new File(chunks, filename, { type: mimeType })); + }); + } else { + value.on("data", (chunk) => { + chunks.push(chunk); + }); + value.on("end", () => { + responseFormData.append(name, new File(chunks, filename, { type: mimeType })); + }); + } + }); + const busboyResolve = new Promise((resolve, reject) => { + busboy.on("finish", resolve); + busboy.on("error", (err) => reject(new TypeError(err))); + }); + if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk); + busboy.end(); + await busboyResolve; + return responseFormData; + } else if (/application\/x-www-form-urlencoded/.test(contentType)) { + let entries; + try { + let text = ""; + const streamingDecoder = new TextDecoder("utf-8", { ignoreBOM: true }); + for await (const chunk of consumeBody(this[kState].body)) { + if (!isUint8Array2(chunk)) { + throw new TypeError("Expected Uint8Array chunk"); + } + text += streamingDecoder.decode(chunk, { stream: true }); + } + text += streamingDecoder.decode(); + entries = new URLSearchParams(text); + } catch (err) { + throw Object.assign(new TypeError(), { cause: err }); + } + const formData = new FormData(); + for (const [name, value] of entries) { + formData.append(name, value); + } + return formData; + } else { + await Promise.resolve(); + throwIfAborted(this[kState]); + throw webidl.errors.exception({ + header: `${instance.name}.formData`, + message: "Could not parse content as FormData." + }); + } + } + }; + return methods; + } + function mixinBody(prototype) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype)); + } + async function specConsumeBody(object, convertBytesToJSValue, instance) { + webidl.brandCheck(object, instance); + throwIfAborted(object[kState]); + if (bodyUnusable(object[kState].body)) { + throw new TypeError("Body is unusable"); + } + const promise = createDeferredPromise(); + const errorSteps = (error) => promise.reject(error); + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)); + } catch (e) { + errorSteps(e); + } + }; + if (object[kState].body == null) { + successSteps(new Uint8Array()); + return promise.promise; + } + await fullyReadBody(object[kState].body, successSteps, errorSteps); + return promise.promise; + } + function bodyUnusable(body) { + return body != null && (body.stream.locked || util2.isDisturbed(body.stream)); + } + function utf8DecodeBytes(buffer) { + if (buffer.length === 0) { + return ""; + } + if (buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) { + buffer = buffer.subarray(3); + } + const output = textDecoder2.decode(buffer); + return output; + } + function parseJSONFromBytes(bytes) { + return JSON.parse(utf8DecodeBytes(bytes)); + } + function bodyMimeType(object) { + const { headersList } = object[kState]; + const contentType = headersList.get("content-type"); + if (contentType === null) { + return "failure"; + } + return parseMIMEType(contentType); + } + module2.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/request.js +var require_request = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/request.js"(exports2, module2) { + "use strict"; + var { + InvalidArgumentError, + NotSupportedError + } = require_errors(); + var assert = require("assert"); + var { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = require_symbols(); + var util2 = require_util(); + var tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/; + var headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; + var invalidPathRegex = /[^\u0021-\u00ff]/; + var kHandler = /* @__PURE__ */ Symbol("handler"); + var channels = {}; + var extractBody; + try { + const diagnosticsChannel = require("diagnostics_channel"); + channels.create = diagnosticsChannel.channel("undici:request:create"); + channels.bodySent = diagnosticsChannel.channel("undici:request:bodySent"); + channels.headers = diagnosticsChannel.channel("undici:request:headers"); + channels.trailers = diagnosticsChannel.channel("undici:request:trailers"); + channels.error = diagnosticsChannel.channel("undici:request:error"); + } catch { + channels.create = { hasSubscribers: false }; + channels.bodySent = { hasSubscribers: false }; + channels.headers = { hasSubscribers: false }; + channels.trailers = { hasSubscribers: false }; + channels.error = { hasSubscribers: false }; + } + var Request = class _Request { + constructor(origin, { + path: path12, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset: reset2, + throwOnError, + expectContinue + }, handler) { + if (typeof path12 !== "string") { + throw new InvalidArgumentError("path must be a string"); + } else if (path12[0] !== "/" && !(path12.startsWith("http://") || path12.startsWith("https://")) && method !== "CONNECT") { + throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); + } else if (invalidPathRegex.exec(path12) !== null) { + throw new InvalidArgumentError("invalid request path"); + } + if (typeof method !== "string") { + throw new InvalidArgumentError("method must be a string"); + } else if (tokenRegExp.exec(method) === null) { + throw new InvalidArgumentError("invalid request method"); + } + if (upgrade && typeof upgrade !== "string") { + throw new InvalidArgumentError("upgrade must be a string"); + } + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError("invalid headersTimeout"); + } + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError("invalid bodyTimeout"); + } + if (reset2 != null && typeof reset2 !== "boolean") { + throw new InvalidArgumentError("invalid reset"); + } + if (expectContinue != null && typeof expectContinue !== "boolean") { + throw new InvalidArgumentError("invalid expectContinue"); + } + this.headersTimeout = headersTimeout; + this.bodyTimeout = bodyTimeout; + this.throwOnError = throwOnError === true; + this.method = method; + this.abort = null; + if (body == null) { + this.body = null; + } else if (util2.isStream(body)) { + this.body = body; + const rState = this.body._readableState; + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy() { + util2.destroy(this); + }; + this.body.on("end", this.endHandler); + } + this.errorHandler = (err) => { + if (this.abort) { + this.abort(err); + } else { + this.error = err; + } + }; + this.body.on("error", this.errorHandler); + } else if (util2.isBuffer(body)) { + this.body = body.byteLength ? body : null; + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null; + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null; + } else if (typeof body === "string") { + this.body = body.length ? Buffer.from(body) : null; + } else if (util2.isFormDataLike(body) || util2.isIterable(body) || util2.isBlobLike(body)) { + this.body = body; + } else { + throw new InvalidArgumentError("body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable"); + } + this.completed = false; + this.aborted = false; + this.upgrade = upgrade || null; + this.path = query ? util2.buildURL(path12, query) : path12; + this.origin = origin; + this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; + this.blocking = blocking == null ? false : blocking; + this.reset = reset2 == null ? null : reset2; + this.host = null; + this.contentLength = null; + this.contentType = null; + this.headers = ""; + this.expectContinue = expectContinue != null ? expectContinue : false; + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError("headers array must be even"); + } + for (let i2 = 0; i2 < headers.length; i2 += 2) { + processHeader(this, headers[i2], headers[i2 + 1]); + } + } else if (headers && typeof headers === "object") { + const keys = Object.keys(headers); + for (let i2 = 0; i2 < keys.length; i2++) { + const key = keys[i2]; + processHeader(this, key, headers[key]); + } + } else if (headers != null) { + throw new InvalidArgumentError("headers must be an object or an array"); + } + if (util2.isFormDataLike(this.body)) { + if (util2.nodeMajor < 16 || util2.nodeMajor === 16 && util2.nodeMinor < 8) { + throw new InvalidArgumentError("Form-Data bodies are only supported in node v16.8 and newer."); + } + if (!extractBody) { + extractBody = require_body().extractBody; + } + const [bodyStream, contentType] = extractBody(body); + if (this.contentType == null) { + this.contentType = contentType; + this.headers += `content-type: ${contentType}\r +`; + } + this.body = bodyStream.stream; + this.contentLength = bodyStream.length; + } else if (util2.isBlobLike(body) && this.contentType == null && body.type) { + this.contentType = body.type; + this.headers += `content-type: ${body.type}\r +`; + } + util2.validateHandler(handler, method, upgrade); + this.servername = util2.getServerName(this.host); + this[kHandler] = handler; + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }); + } + } + onBodySent(chunk) { + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk); + } catch (err) { + this.abort(err); + } + } + } + onRequestSent() { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }); + } + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent(); + } catch (err) { + this.abort(err); + } + } + } + onConnect(abort) { + assert(!this.aborted); + assert(!this.completed); + if (this.error) { + abort(this.error); + } else { + this.abort = abort; + return this[kHandler].onConnect(abort); + } + } + onHeaders(statusCode, headers, resume, statusText) { + assert(!this.aborted); + assert(!this.completed); + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }); + } + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText); + } catch (err) { + this.abort(err); + } + } + onData(chunk) { + assert(!this.aborted); + assert(!this.completed); + try { + return this[kHandler].onData(chunk); + } catch (err) { + this.abort(err); + return false; + } + } + onUpgrade(statusCode, headers, socket) { + assert(!this.aborted); + assert(!this.completed); + return this[kHandler].onUpgrade(statusCode, headers, socket); + } + onComplete(trailers) { + this.onFinally(); + assert(!this.aborted); + this.completed = true; + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }); + } + try { + return this[kHandler].onComplete(trailers); + } catch (err) { + this.onError(err); + } + } + onError(error) { + this.onFinally(); + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }); + } + if (this.aborted) { + return; + } + this.aborted = true; + return this[kHandler].onError(error); + } + onFinally() { + if (this.errorHandler) { + this.body.off("error", this.errorHandler); + this.errorHandler = null; + } + if (this.endHandler) { + this.body.off("end", this.endHandler); + this.endHandler = null; + } + } + // TODO: adjust to support H2 + addHeader(key, value) { + processHeader(this, key, value); + return this; + } + static [kHTTP1BuildRequest](origin, opts, handler) { + return new _Request(origin, opts, handler); + } + static [kHTTP2BuildRequest](origin, opts, handler) { + const headers = opts.headers; + opts = { ...opts, headers: null }; + const request = new _Request(origin, opts, handler); + request.headers = {}; + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError("headers array must be even"); + } + for (let i2 = 0; i2 < headers.length; i2 += 2) { + processHeader(request, headers[i2], headers[i2 + 1], true); + } + } else if (headers && typeof headers === "object") { + const keys = Object.keys(headers); + for (let i2 = 0; i2 < keys.length; i2++) { + const key = keys[i2]; + processHeader(request, key, headers[key], true); + } + } else if (headers != null) { + throw new InvalidArgumentError("headers must be an object or an array"); + } + return request; + } + static [kHTTP2CopyHeaders](raw) { + const rawHeaders = raw.split("\r\n"); + const headers = {}; + for (const header of rawHeaders) { + const [key, value] = header.split(": "); + if (value == null || value.length === 0) continue; + if (headers[key]) headers[key] += `,${value}`; + else headers[key] = value; + } + return headers; + } + }; + function processHeaderValue(key, val, skipAppend) { + if (val && typeof val === "object") { + throw new InvalidArgumentError(`invalid ${key} header`); + } + val = val != null ? `${val}` : ""; + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`); + } + return skipAppend ? val : `${key}: ${val}\r +`; + } + function processHeader(request, key, val, skipAppend = false) { + if (val && (typeof val === "object" && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`); + } else if (val === void 0) { + return; + } + if (request.host === null && key.length === 4 && key.toLowerCase() === "host") { + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`); + } + request.host = val; + } else if (request.contentLength === null && key.length === 14 && key.toLowerCase() === "content-length") { + request.contentLength = parseInt(val, 10); + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError("invalid content-length header"); + } + } else if (request.contentType === null && key.length === 12 && key.toLowerCase() === "content-type") { + request.contentType = val; + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend); + else request.headers += processHeaderValue(key, val); + } else if (key.length === 17 && key.toLowerCase() === "transfer-encoding") { + throw new InvalidArgumentError("invalid transfer-encoding header"); + } else if (key.length === 10 && key.toLowerCase() === "connection") { + const value = typeof val === "string" ? val.toLowerCase() : null; + if (value !== "close" && value !== "keep-alive") { + throw new InvalidArgumentError("invalid connection header"); + } else if (value === "close") { + request.reset = true; + } + } else if (key.length === 10 && key.toLowerCase() === "keep-alive") { + throw new InvalidArgumentError("invalid keep-alive header"); + } else if (key.length === 7 && key.toLowerCase() === "upgrade") { + throw new InvalidArgumentError("invalid upgrade header"); + } else if (key.length === 6 && key.toLowerCase() === "expect") { + throw new NotSupportedError("expect header not supported"); + } else if (tokenRegExp.exec(key) === null) { + throw new InvalidArgumentError("invalid header key"); + } else { + if (Array.isArray(val)) { + for (let i2 = 0; i2 < val.length; i2++) { + if (skipAppend) { + if (request.headers[key]) request.headers[key] += `,${processHeaderValue(key, val[i2], skipAppend)}`; + else request.headers[key] = processHeaderValue(key, val[i2], skipAppend); + } else { + request.headers += processHeaderValue(key, val[i2]); + } + } + } else { + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend); + else request.headers += processHeaderValue(key, val); + } + } + } + module2.exports = Request; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/dispatcher.js +var require_dispatcher = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/dispatcher.js"(exports2, module2) { + "use strict"; + var EventEmitter2 = require("events"); + var Dispatcher = class extends EventEmitter2 { + dispatch() { + throw new Error("not implemented"); + } + close() { + throw new Error("not implemented"); + } + destroy() { + throw new Error("not implemented"); + } + }; + module2.exports = Dispatcher; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/dispatcher-base.js +var require_dispatcher_base = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/dispatcher-base.js"(exports2, module2) { + "use strict"; + var Dispatcher = require_dispatcher(); + var { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError + } = require_errors(); + var { kDestroy, kClose, kDispatch, kInterceptors } = require_symbols(); + var kDestroyed = /* @__PURE__ */ Symbol("destroyed"); + var kClosed = /* @__PURE__ */ Symbol("closed"); + var kOnDestroyed = /* @__PURE__ */ Symbol("onDestroyed"); + var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); + var kInterceptedDispatch = /* @__PURE__ */ Symbol("Intercepted Dispatch"); + var DispatcherBase = class extends Dispatcher { + constructor() { + super(); + this[kDestroyed] = false; + this[kOnDestroyed] = null; + this[kClosed] = false; + this[kOnClosed] = []; + } + get destroyed() { + return this[kDestroyed]; + } + get closed() { + return this[kClosed]; + } + get interceptors() { + return this[kInterceptors]; + } + set interceptors(newInterceptors) { + if (newInterceptors) { + for (let i2 = newInterceptors.length - 1; i2 >= 0; i2--) { + const interceptor = this[kInterceptors][i2]; + if (typeof interceptor !== "function") { + throw new InvalidArgumentError("interceptor must be an function"); + } + } + } + this[kInterceptors] = newInterceptors; + } + close(callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (this[kDestroyed]) { + queueMicrotask(() => callback(new ClientDestroyedError(), null)); + return; + } + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback); + } else { + queueMicrotask(() => callback(null, null)); + } + return; + } + this[kClosed] = true; + this[kOnClosed].push(callback); + const onClosed = () => { + const callbacks = this[kOnClosed]; + this[kOnClosed] = null; + for (let i2 = 0; i2 < callbacks.length; i2++) { + callbacks[i2](null, null); + } + }; + this[kClose]().then(() => this.destroy()).then(() => { + queueMicrotask(onClosed); + }); + } + destroy(err, callback) { + if (typeof err === "function") { + callback = err; + err = null; + } + if (callback === void 0) { + return new Promise((resolve, reject) => { + this.destroy(err, (err2, data) => { + return err2 ? ( + /* istanbul ignore next: should never error */ + reject(err2) + ) : resolve(data); + }); + }); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback); + } else { + queueMicrotask(() => callback(null, null)); + } + return; + } + if (!err) { + err = new ClientDestroyedError(); + } + this[kDestroyed] = true; + this[kOnDestroyed] = this[kOnDestroyed] || []; + this[kOnDestroyed].push(callback); + const onDestroyed = () => { + const callbacks = this[kOnDestroyed]; + this[kOnDestroyed] = null; + for (let i2 = 0; i2 < callbacks.length; i2++) { + callbacks[i2](null, null); + } + }; + this[kDestroy](err).then(() => { + queueMicrotask(onDestroyed); + }); + } + [kInterceptedDispatch](opts, handler) { + if (!this[kInterceptors] || this[kInterceptors].length === 0) { + this[kInterceptedDispatch] = this[kDispatch]; + return this[kDispatch](opts, handler); + } + let dispatch = this[kDispatch].bind(this); + for (let i2 = this[kInterceptors].length - 1; i2 >= 0; i2--) { + dispatch = this[kInterceptors][i2](dispatch); + } + this[kInterceptedDispatch] = dispatch; + return dispatch(opts, handler); + } + dispatch(opts, handler) { + if (!handler || typeof handler !== "object") { + throw new InvalidArgumentError("handler must be an object"); + } + try { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("opts must be an object."); + } + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError(); + } + if (this[kClosed]) { + throw new ClientClosedError(); + } + return this[kInterceptedDispatch](opts, handler); + } catch (err) { + if (typeof handler.onError !== "function") { + throw new InvalidArgumentError("invalid onError method"); + } + handler.onError(err); + return false; + } + } + }; + module2.exports = DispatcherBase; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/connect.js +var require_connect = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/core/connect.js"(exports2, module2) { + "use strict"; + var net = require("net"); + var assert = require("assert"); + var util2 = require_util(); + var { InvalidArgumentError, ConnectTimeoutError } = require_errors(); + var tls; + var SessionCache; + if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) { + SessionCache = class WeakSessionCache { + constructor(maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions; + this._sessionCache = /* @__PURE__ */ new Map(); + this._sessionRegistry = new global.FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return; + } + const ref = this._sessionCache.get(key); + if (ref !== void 0 && ref.deref() === void 0) { + this._sessionCache.delete(key); + } + }); + } + get(sessionKey) { + const ref = this._sessionCache.get(sessionKey); + return ref ? ref.deref() : null; + } + set(sessionKey, session) { + if (this._maxCachedSessions === 0) { + return; + } + this._sessionCache.set(sessionKey, new WeakRef(session)); + this._sessionRegistry.register(session, sessionKey); + } + }; + } else { + SessionCache = class SimpleSessionCache { + constructor(maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions; + this._sessionCache = /* @__PURE__ */ new Map(); + } + get(sessionKey) { + return this._sessionCache.get(sessionKey); + } + set(sessionKey, session) { + if (this._maxCachedSessions === 0) { + return; + } + if (this._sessionCache.size >= this._maxCachedSessions) { + const { value: oldestKey } = this._sessionCache.keys().next(); + this._sessionCache.delete(oldestKey); + } + this._sessionCache.set(sessionKey, session); + } + }; + } + function buildConnector({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError("maxCachedSessions must be a positive integer or zero"); + } + const options = { path: socketPath, ...opts }; + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions); + timeout = timeout == null ? 1e4 : timeout; + allowH2 = allowH2 != null ? allowH2 : false; + return function connect({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket; + if (protocol === "https:") { + if (!tls) { + tls = require("tls"); + } + servername = servername || options.servername || util2.getServerName(host) || null; + const sessionKey = servername || hostname; + const session = sessionCache.get(sessionKey) || null; + assert(sessionKey); + socket = tls.connect({ + highWaterMark: 16384, + // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + // TODO(HTTP/2): Add support for h2c + ALPNProtocols: allowH2 ? ["http/1.1", "h2"] : ["http/1.1"], + socket: httpSocket, + // upgrade socket connection + port: port || 443, + host: hostname + }); + socket.on("session", function(session2) { + sessionCache.set(sessionKey, session2); + }); + } else { + assert(!httpSocket, "httpSocket can only be sent on TLS update"); + socket = net.connect({ + highWaterMark: 64 * 1024, + // Same as nodejs fs streams. + ...options, + localAddress, + port: port || 80, + host: hostname + }); + } + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === void 0 ? 6e4 : options.keepAliveInitialDelay; + socket.setKeepAlive(true, keepAliveInitialDelay); + } + const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout); + socket.setNoDelay(true).once(protocol === "https:" ? "secureConnect" : "connect", function() { + cancelTimeout(); + if (callback) { + const cb = callback; + callback = null; + cb(null, this); + } + }).on("error", function(err) { + cancelTimeout(); + if (callback) { + const cb = callback; + callback = null; + cb(err); + } + }); + return socket; + }; + } + function setupTimeout(onConnectTimeout2, timeout) { + if (!timeout) { + return () => { + }; + } + let s1 = null; + let s2 = null; + const timeoutId = setTimeout(() => { + s1 = setImmediate(() => { + if (process.platform === "win32") { + s2 = setImmediate(() => onConnectTimeout2()); + } else { + onConnectTimeout2(); + } + }); + }, timeout); + return () => { + clearTimeout(timeoutId); + clearImmediate(s1); + clearImmediate(s2); + }; + } + function onConnectTimeout(socket) { + util2.destroy(socket, new ConnectTimeoutError()); + } + module2.exports = buildConnector; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/utils.js +var require_utils2 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/utils.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.enumToMap = void 0; + function enumToMap(obj) { + const res = {}; + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (typeof value === "number") { + res[key] = value; + } + }); + return res; + } + exports2.enumToMap = enumToMap; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/constants.js +var require_constants3 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/constants.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.SPECIAL_HEADERS = exports2.HEADER_STATE = exports2.MINOR = exports2.MAJOR = exports2.CONNECTION_TOKEN_CHARS = exports2.HEADER_CHARS = exports2.TOKEN = exports2.STRICT_TOKEN = exports2.HEX = exports2.URL_CHAR = exports2.STRICT_URL_CHAR = exports2.USERINFO_CHARS = exports2.MARK = exports2.ALPHANUM = exports2.NUM = exports2.HEX_MAP = exports2.NUM_MAP = exports2.ALPHA = exports2.FINISH = exports2.H_METHOD_MAP = exports2.METHOD_MAP = exports2.METHODS_RTSP = exports2.METHODS_ICE = exports2.METHODS_HTTP = exports2.METHODS = exports2.LENIENT_FLAGS = exports2.FLAGS = exports2.TYPE = exports2.ERROR = void 0; + var utils_1 = require_utils2(); + var ERROR; + (function(ERROR2) { + ERROR2[ERROR2["OK"] = 0] = "OK"; + ERROR2[ERROR2["INTERNAL"] = 1] = "INTERNAL"; + ERROR2[ERROR2["STRICT"] = 2] = "STRICT"; + ERROR2[ERROR2["LF_EXPECTED"] = 3] = "LF_EXPECTED"; + ERROR2[ERROR2["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; + ERROR2[ERROR2["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; + ERROR2[ERROR2["INVALID_METHOD"] = 6] = "INVALID_METHOD"; + ERROR2[ERROR2["INVALID_URL"] = 7] = "INVALID_URL"; + ERROR2[ERROR2["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; + ERROR2[ERROR2["INVALID_VERSION"] = 9] = "INVALID_VERSION"; + ERROR2[ERROR2["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; + ERROR2[ERROR2["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; + ERROR2[ERROR2["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; + ERROR2[ERROR2["INVALID_STATUS"] = 13] = "INVALID_STATUS"; + ERROR2[ERROR2["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; + ERROR2[ERROR2["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; + ERROR2[ERROR2["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; + ERROR2[ERROR2["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; + ERROR2[ERROR2["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; + ERROR2[ERROR2["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; + ERROR2[ERROR2["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; + ERROR2[ERROR2["PAUSED"] = 21] = "PAUSED"; + ERROR2[ERROR2["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; + ERROR2[ERROR2["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; + ERROR2[ERROR2["USER"] = 24] = "USER"; + })(ERROR = exports2.ERROR || (exports2.ERROR = {})); + var TYPE; + (function(TYPE2) { + TYPE2[TYPE2["BOTH"] = 0] = "BOTH"; + TYPE2[TYPE2["REQUEST"] = 1] = "REQUEST"; + TYPE2[TYPE2["RESPONSE"] = 2] = "RESPONSE"; + })(TYPE = exports2.TYPE || (exports2.TYPE = {})); + var FLAGS; + (function(FLAGS2) { + FLAGS2[FLAGS2["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; + FLAGS2[FLAGS2["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; + FLAGS2[FLAGS2["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; + FLAGS2[FLAGS2["CHUNKED"] = 8] = "CHUNKED"; + FLAGS2[FLAGS2["UPGRADE"] = 16] = "UPGRADE"; + FLAGS2[FLAGS2["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; + FLAGS2[FLAGS2["SKIPBODY"] = 64] = "SKIPBODY"; + FLAGS2[FLAGS2["TRAILING"] = 128] = "TRAILING"; + FLAGS2[FLAGS2["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; + })(FLAGS = exports2.FLAGS || (exports2.FLAGS = {})); + var LENIENT_FLAGS; + (function(LENIENT_FLAGS2) { + LENIENT_FLAGS2[LENIENT_FLAGS2["HEADERS"] = 1] = "HEADERS"; + LENIENT_FLAGS2[LENIENT_FLAGS2["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; + LENIENT_FLAGS2[LENIENT_FLAGS2["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; + })(LENIENT_FLAGS = exports2.LENIENT_FLAGS || (exports2.LENIENT_FLAGS = {})); + var METHODS; + (function(METHODS2) { + METHODS2[METHODS2["DELETE"] = 0] = "DELETE"; + METHODS2[METHODS2["GET"] = 1] = "GET"; + METHODS2[METHODS2["HEAD"] = 2] = "HEAD"; + METHODS2[METHODS2["POST"] = 3] = "POST"; + METHODS2[METHODS2["PUT"] = 4] = "PUT"; + METHODS2[METHODS2["CONNECT"] = 5] = "CONNECT"; + METHODS2[METHODS2["OPTIONS"] = 6] = "OPTIONS"; + METHODS2[METHODS2["TRACE"] = 7] = "TRACE"; + METHODS2[METHODS2["COPY"] = 8] = "COPY"; + METHODS2[METHODS2["LOCK"] = 9] = "LOCK"; + METHODS2[METHODS2["MKCOL"] = 10] = "MKCOL"; + METHODS2[METHODS2["MOVE"] = 11] = "MOVE"; + METHODS2[METHODS2["PROPFIND"] = 12] = "PROPFIND"; + METHODS2[METHODS2["PROPPATCH"] = 13] = "PROPPATCH"; + METHODS2[METHODS2["SEARCH"] = 14] = "SEARCH"; + METHODS2[METHODS2["UNLOCK"] = 15] = "UNLOCK"; + METHODS2[METHODS2["BIND"] = 16] = "BIND"; + METHODS2[METHODS2["REBIND"] = 17] = "REBIND"; + METHODS2[METHODS2["UNBIND"] = 18] = "UNBIND"; + METHODS2[METHODS2["ACL"] = 19] = "ACL"; + METHODS2[METHODS2["REPORT"] = 20] = "REPORT"; + METHODS2[METHODS2["MKACTIVITY"] = 21] = "MKACTIVITY"; + METHODS2[METHODS2["CHECKOUT"] = 22] = "CHECKOUT"; + METHODS2[METHODS2["MERGE"] = 23] = "MERGE"; + METHODS2[METHODS2["M-SEARCH"] = 24] = "M-SEARCH"; + METHODS2[METHODS2["NOTIFY"] = 25] = "NOTIFY"; + METHODS2[METHODS2["SUBSCRIBE"] = 26] = "SUBSCRIBE"; + METHODS2[METHODS2["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; + METHODS2[METHODS2["PATCH"] = 28] = "PATCH"; + METHODS2[METHODS2["PURGE"] = 29] = "PURGE"; + METHODS2[METHODS2["MKCALENDAR"] = 30] = "MKCALENDAR"; + METHODS2[METHODS2["LINK"] = 31] = "LINK"; + METHODS2[METHODS2["UNLINK"] = 32] = "UNLINK"; + METHODS2[METHODS2["SOURCE"] = 33] = "SOURCE"; + METHODS2[METHODS2["PRI"] = 34] = "PRI"; + METHODS2[METHODS2["DESCRIBE"] = 35] = "DESCRIBE"; + METHODS2[METHODS2["ANNOUNCE"] = 36] = "ANNOUNCE"; + METHODS2[METHODS2["SETUP"] = 37] = "SETUP"; + METHODS2[METHODS2["PLAY"] = 38] = "PLAY"; + METHODS2[METHODS2["PAUSE"] = 39] = "PAUSE"; + METHODS2[METHODS2["TEARDOWN"] = 40] = "TEARDOWN"; + METHODS2[METHODS2["GET_PARAMETER"] = 41] = "GET_PARAMETER"; + METHODS2[METHODS2["SET_PARAMETER"] = 42] = "SET_PARAMETER"; + METHODS2[METHODS2["REDIRECT"] = 43] = "REDIRECT"; + METHODS2[METHODS2["RECORD"] = 44] = "RECORD"; + METHODS2[METHODS2["FLUSH"] = 45] = "FLUSH"; + })(METHODS = exports2.METHODS || (exports2.METHODS = {})); + exports2.METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS["M-SEARCH"], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE + ]; + exports2.METHODS_ICE = [ + METHODS.SOURCE + ]; + exports2.METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + // For AirPlay + METHODS.GET, + METHODS.POST + ]; + exports2.METHOD_MAP = utils_1.enumToMap(METHODS); + exports2.H_METHOD_MAP = {}; + Object.keys(exports2.METHOD_MAP).forEach((key) => { + if (/^H/.test(key)) { + exports2.H_METHOD_MAP[key] = exports2.METHOD_MAP[key]; + } + }); + var FINISH; + (function(FINISH2) { + FINISH2[FINISH2["SAFE"] = 0] = "SAFE"; + FINISH2[FINISH2["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; + FINISH2[FINISH2["UNSAFE"] = 2] = "UNSAFE"; + })(FINISH = exports2.FINISH || (exports2.FINISH = {})); + exports2.ALPHA = []; + for (let i2 = "A".charCodeAt(0); i2 <= "Z".charCodeAt(0); i2++) { + exports2.ALPHA.push(String.fromCharCode(i2)); + exports2.ALPHA.push(String.fromCharCode(i2 + 32)); + } + exports2.NUM_MAP = { + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9 + }; + exports2.HEX_MAP = { + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + A: 10, + B: 11, + C: 12, + D: 13, + E: 14, + F: 15, + a: 10, + b: 11, + c: 12, + d: 13, + e: 14, + f: 15 + }; + exports2.NUM = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ]; + exports2.ALPHANUM = exports2.ALPHA.concat(exports2.NUM); + exports2.MARK = ["-", "_", ".", "!", "~", "*", "'", "(", ")"]; + exports2.USERINFO_CHARS = exports2.ALPHANUM.concat(exports2.MARK).concat(["%", ";", ":", "&", "=", "+", "$", ","]); + exports2.STRICT_URL_CHAR = [ + "!", + '"', + "$", + "%", + "&", + "'", + "(", + ")", + "*", + "+", + ",", + "-", + ".", + "/", + ":", + ";", + "<", + "=", + ">", + "@", + "[", + "\\", + "]", + "^", + "_", + "`", + "{", + "|", + "}", + "~" + ].concat(exports2.ALPHANUM); + exports2.URL_CHAR = exports2.STRICT_URL_CHAR.concat([" ", "\f"]); + for (let i2 = 128; i2 <= 255; i2++) { + exports2.URL_CHAR.push(i2); + } + exports2.HEX = exports2.NUM.concat(["a", "b", "c", "d", "e", "f", "A", "B", "C", "D", "E", "F"]); + exports2.STRICT_TOKEN = [ + "!", + "#", + "$", + "%", + "&", + "'", + "*", + "+", + "-", + ".", + "^", + "_", + "`", + "|", + "~" + ].concat(exports2.ALPHANUM); + exports2.TOKEN = exports2.STRICT_TOKEN.concat([" "]); + exports2.HEADER_CHARS = [" "]; + for (let i2 = 32; i2 <= 255; i2++) { + if (i2 !== 127) { + exports2.HEADER_CHARS.push(i2); + } + } + exports2.CONNECTION_TOKEN_CHARS = exports2.HEADER_CHARS.filter((c3) => c3 !== 44); + exports2.MAJOR = exports2.NUM_MAP; + exports2.MINOR = exports2.MAJOR; + var HEADER_STATE; + (function(HEADER_STATE2) { + HEADER_STATE2[HEADER_STATE2["GENERAL"] = 0] = "GENERAL"; + HEADER_STATE2[HEADER_STATE2["CONNECTION"] = 1] = "CONNECTION"; + HEADER_STATE2[HEADER_STATE2["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; + HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; + HEADER_STATE2[HEADER_STATE2["UPGRADE"] = 4] = "UPGRADE"; + HEADER_STATE2[HEADER_STATE2["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; + HEADER_STATE2[HEADER_STATE2["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; + HEADER_STATE2[HEADER_STATE2["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; + HEADER_STATE2[HEADER_STATE2["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; + })(HEADER_STATE = exports2.HEADER_STATE || (exports2.HEADER_STATE = {})); + exports2.SPECIAL_HEADERS = { + "connection": HEADER_STATE.CONNECTION, + "content-length": HEADER_STATE.CONTENT_LENGTH, + "proxy-connection": HEADER_STATE.CONNECTION, + "transfer-encoding": HEADER_STATE.TRANSFER_ENCODING, + "upgrade": HEADER_STATE.UPGRADE + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/handler/RedirectHandler.js +var require_RedirectHandler = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/handler/RedirectHandler.js"(exports2, module2) { + "use strict"; + var util2 = require_util(); + var { kBodyUsed } = require_symbols(); + var assert = require("assert"); + var { InvalidArgumentError } = require_errors(); + var EE = require("events"); + var redirectableStatusCodes = [300, 301, 302, 303, 307, 308]; + var kBody = /* @__PURE__ */ Symbol("body"); + var BodyAsyncIterable = class { + constructor(body) { + this[kBody] = body; + this[kBodyUsed] = false; + } + async *[Symbol.asyncIterator]() { + assert(!this[kBodyUsed], "disturbed"); + this[kBodyUsed] = true; + yield* this[kBody]; + } + }; + var RedirectHandler = class { + constructor(dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + util2.validateHandler(handler, opts.method, opts.upgrade); + this.dispatch = dispatch; + this.location = null; + this.abort = null; + this.opts = { ...opts, maxRedirections: 0 }; + this.maxRedirections = maxRedirections; + this.handler = handler; + this.history = []; + if (util2.isStream(this.opts.body)) { + if (util2.bodyLength(this.opts.body) === 0) { + this.opts.body.on("data", function() { + assert(false); + }); + } + if (typeof this.opts.body.readableDidRead !== "boolean") { + this.opts.body[kBodyUsed] = false; + EE.prototype.on.call(this.opts.body, "data", function() { + this[kBodyUsed] = true; + }); + } + } else if (this.opts.body && typeof this.opts.body.pipeTo === "function") { + this.opts.body = new BodyAsyncIterable(this.opts.body); + } else if (this.opts.body && typeof this.opts.body !== "string" && !ArrayBuffer.isView(this.opts.body) && util2.isIterable(this.opts.body)) { + this.opts.body = new BodyAsyncIterable(this.opts.body); + } + } + onConnect(abort) { + this.abort = abort; + this.handler.onConnect(abort, { history: this.history }); + } + onUpgrade(statusCode, headers, socket) { + this.handler.onUpgrade(statusCode, headers, socket); + } + onError(error) { + this.handler.onError(error); + } + onHeaders(statusCode, headers, resume, statusText) { + this.location = this.history.length >= this.maxRedirections || util2.isDisturbed(this.opts.body) ? null : parseLocation(statusCode, headers); + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)); + } + if (!this.location) { + return this.handler.onHeaders(statusCode, headers, resume, statusText); + } + const { origin, pathname, search } = util2.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); + const path12 = search ? `${pathname}${search}` : pathname; + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); + this.opts.path = path12; + this.opts.origin = origin; + this.opts.maxRedirections = 0; + this.opts.query = null; + if (statusCode === 303 && this.opts.method !== "HEAD") { + this.opts.method = "GET"; + this.opts.body = null; + } + } + onData(chunk) { + if (this.location) { + } else { + return this.handler.onData(chunk); + } + } + onComplete(trailers) { + if (this.location) { + this.location = null; + this.abort = null; + this.dispatch(this.opts, this); + } else { + this.handler.onComplete(trailers); + } + } + onBodySent(chunk) { + if (this.handler.onBodySent) { + this.handler.onBodySent(chunk); + } + } + }; + function parseLocation(statusCode, headers) { + if (redirectableStatusCodes.indexOf(statusCode) === -1) { + return null; + } + for (let i2 = 0; i2 < headers.length; i2 += 2) { + if (headers[i2].toString().toLowerCase() === "location") { + return headers[i2 + 1]; + } + } + } + function shouldRemoveHeader(header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util2.headerNameToString(header) === "host"; + } + if (removeContent && util2.headerNameToString(header).startsWith("content-")) { + return true; + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util2.headerNameToString(header); + return name === "authorization" || name === "cookie" || name === "proxy-authorization"; + } + return false; + } + function cleanRequestHeaders(headers, removeContent, unknownOrigin) { + const ret = []; + if (Array.isArray(headers)) { + for (let i2 = 0; i2 < headers.length; i2 += 2) { + if (!shouldRemoveHeader(headers[i2], removeContent, unknownOrigin)) { + ret.push(headers[i2], headers[i2 + 1]); + } + } + } else if (headers && typeof headers === "object") { + for (const key of Object.keys(headers)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, headers[key]); + } + } + } else { + assert(headers == null, "headers must be an object or an array"); + } + return ret; + } + module2.exports = RedirectHandler; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/interceptor/redirectInterceptor.js +var require_redirectInterceptor = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/interceptor/redirectInterceptor.js"(exports2, module2) { + "use strict"; + var RedirectHandler = require_RedirectHandler(); + function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections }) { + return (dispatch) => { + return function Intercept(opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts; + if (!maxRedirections) { + return dispatch(opts, handler); + } + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler); + opts = { ...opts, maxRedirections: 0 }; + return dispatch(opts, redirectHandler); + }; + }; + } + module2.exports = createRedirectInterceptor; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/llhttp-wasm.js +var require_llhttp_wasm = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/llhttp-wasm.js"(exports2, module2) { + "use strict"; + module2.exports = "AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8="; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +var require_llhttp_simd_wasm = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js"(exports2, module2) { + "use strict"; + module2.exports = "AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw=="; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/client.js +var require_client = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/client.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var net = require("net"); + var http = require("http"); + var { pipeline } = require("stream"); + var util2 = require_util(); + var timers = require_timers(); + var Request = require_request(); + var DispatcherBase = require_dispatcher_base(); + var { + RequestContentLengthMismatchError, + ResponseContentLengthMismatchError, + InvalidArgumentError, + RequestAbortedError, + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseExceededMaxSizeError, + ClientDestroyedError + } = require_errors(); + var buildConnector = require_connect(); + var { + kUrl, + kReset, + kServerName, + kClient, + kBusy, + kParser, + kConnect, + kBlocking, + kResuming, + kRunning, + kPending, + kSize, + kWriting, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kNoRef, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRedirections, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kInterceptors, + kLocalAddress, + kMaxResponseSize, + kHTTPConnVersion, + // HTTP2 + kHost, + kHTTP2Session, + kHTTP2SessionState, + kHTTP2BuildRequest, + kHTTP2CopyHeaders, + kHTTP1BuildRequest + } = require_symbols(); + var http2; + try { + http2 = require("http2"); + } catch { + http2 = { constants: {} }; + } + var { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS + } + } = http2; + var h2ExperimentalWarned = false; + var FastBuffer = Buffer[Symbol.species]; + var kClosedResolve = /* @__PURE__ */ Symbol("kClosedResolve"); + var channels = {}; + try { + const diagnosticsChannel = require("diagnostics_channel"); + channels.sendHeaders = diagnosticsChannel.channel("undici:client:sendHeaders"); + channels.beforeConnect = diagnosticsChannel.channel("undici:client:beforeConnect"); + channels.connectError = diagnosticsChannel.channel("undici:client:connectError"); + channels.connected = diagnosticsChannel.channel("undici:client:connected"); + } catch { + channels.sendHeaders = { hasSubscribers: false }; + channels.beforeConnect = { hasSubscribers: false }; + channels.connectError = { hasSubscribers: false }; + channels.connected = { hasSubscribers: false }; + } + var Client = class extends DispatcherBase { + /** + * + * @param {string|URL} url + * @param {import('../types/client').Client.Options} options + */ + constructor(url, { + interceptors, + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + maxRedirections, + connect: connect2, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + allowH2, + maxConcurrentStreams + } = {}) { + super(); + if (keepAlive !== void 0) { + throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); + } + if (socketTimeout !== void 0) { + throw new InvalidArgumentError("unsupported socketTimeout, use headersTimeout & bodyTimeout instead"); + } + if (requestTimeout !== void 0) { + throw new InvalidArgumentError("unsupported requestTimeout, use headersTimeout & bodyTimeout instead"); + } + if (idleTimeout !== void 0) { + throw new InvalidArgumentError("unsupported idleTimeout, use keepAliveTimeout instead"); + } + if (maxKeepAliveTimeout !== void 0) { + throw new InvalidArgumentError("unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead"); + } + if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { + throw new InvalidArgumentError("invalid maxHeaderSize"); + } + if (socketPath != null && typeof socketPath !== "string") { + throw new InvalidArgumentError("invalid socketPath"); + } + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError("invalid connectTimeout"); + } + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError("invalid keepAliveTimeout"); + } + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError("invalid keepAliveMaxTimeout"); + } + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError("invalid keepAliveTimeoutThreshold"); + } + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError("headersTimeout must be a positive integer or zero"); + } + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero"); + } + if (connect2 != null && typeof connect2 !== "function" && typeof connect2 !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError("maxRequestsPerClient must be a positive number"); + } + if (localAddress != null && (typeof localAddress !== "string" || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError("localAddress must be valid string IP address"); + } + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError("maxResponseSize must be a positive number"); + } + if (autoSelectFamilyAttemptTimeout != null && (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)) { + throw new InvalidArgumentError("autoSelectFamilyAttemptTimeout must be a positive number"); + } + if (allowH2 != null && typeof allowH2 !== "boolean") { + throw new InvalidArgumentError("allowH2 must be a valid boolean value"); + } + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== "number" || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError("maxConcurrentStreams must be a possitive integer, greater than 0"); + } + if (typeof connect2 !== "function") { + connect2 = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...util2.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect2 + }); + } + this[kInterceptors] = interceptors && interceptors.Client && Array.isArray(interceptors.Client) ? interceptors.Client : [createRedirectInterceptor({ maxRedirections })]; + this[kUrl] = util2.parseOrigin(url); + this[kConnector] = connect2; + this[kSocket] = null; + this[kPipelining] = pipelining != null ? pipelining : 1; + this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize; + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout; + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 6e5 : keepAliveMaxTimeout; + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold; + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout]; + this[kServerName] = null; + this[kLocalAddress] = localAddress != null ? localAddress : null; + this[kResuming] = 0; + this[kNeedDrain] = 0; + this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ""}\r +`; + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 3e5; + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 3e5; + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength; + this[kMaxRedirections] = maxRedirections; + this[kMaxRequests] = maxRequestsPerClient; + this[kClosedResolve] = null; + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1; + this[kHTTPConnVersion] = "h1"; + this[kHTTP2Session] = null; + this[kHTTP2SessionState] = !allowH2 ? null : { + // streams: null, // Fixed queue of streams - For future support of `push` + openStreams: 0, + // Keep track of them to decide wether or not unref the session + maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 + // Max peerConcurrentStreams for a Node h2 server + }; + this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ""}`; + this[kQueue] = []; + this[kRunningIdx] = 0; + this[kPendingIdx] = 0; + } + get pipelining() { + return this[kPipelining]; + } + set pipelining(value) { + this[kPipelining] = value; + resume(this, true); + } + get [kPending]() { + return this[kQueue].length - this[kPendingIdx]; + } + get [kRunning]() { + return this[kPendingIdx] - this[kRunningIdx]; + } + get [kSize]() { + return this[kQueue].length - this[kRunningIdx]; + } + get [kConnected]() { + return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed; + } + get [kBusy]() { + const socket = this[kSocket]; + return socket && (socket[kReset] || socket[kWriting] || socket[kBlocking]) || this[kSize] >= (this[kPipelining] || 1) || this[kPending] > 0; + } + /* istanbul ignore: only used for test */ + [kConnect](cb) { + connect(this); + this.once("connect", cb); + } + [kDispatch](opts, handler) { + const origin = opts.origin || this[kUrl].origin; + const request = this[kHTTPConnVersion] === "h2" ? Request[kHTTP2BuildRequest](origin, opts, handler) : Request[kHTTP1BuildRequest](origin, opts, handler); + this[kQueue].push(request); + if (this[kResuming]) { + } else if (util2.bodyLength(request.body) == null && util2.isIterable(request.body)) { + this[kResuming] = 1; + process.nextTick(resume, this); + } else { + resume(this, true); + } + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2; + } + return this[kNeedDrain] < 2; + } + async [kClose]() { + return new Promise((resolve) => { + if (!this[kSize]) { + resolve(null); + } else { + this[kClosedResolve] = resolve; + } + }); + } + async [kDestroy](err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]); + for (let i2 = 0; i2 < requests.length; i2++) { + const request = requests[i2]; + errorRequest(this, request, err); + } + const callback = () => { + if (this[kClosedResolve]) { + this[kClosedResolve](); + this[kClosedResolve] = null; + } + resolve(); + }; + if (this[kHTTP2Session] != null) { + util2.destroy(this[kHTTP2Session], err); + this[kHTTP2Session] = null; + this[kHTTP2SessionState] = null; + } + if (!this[kSocket]) { + queueMicrotask(callback); + } else { + util2.destroy(this[kSocket].on("close", callback), err); + } + resume(this); + }); + } + }; + function onHttp2SessionError(err) { + assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + this[kSocket][kError] = err; + onError(this[kClient], err); + } + function onHttp2FrameError(type, code2, id) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code2}`); + if (id === 0) { + this[kSocket][kError] = err; + onError(this[kClient], err); + } + } + function onHttp2SessionEnd() { + util2.destroy(this, new SocketError("other side closed")); + util2.destroy(this[kSocket], new SocketError("other side closed")); + } + function onHTTP2GoAway(code2) { + const client = this[kClient]; + const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code2}`); + client[kSocket] = null; + client[kHTTP2Session] = null; + if (client.destroyed) { + assert(this[kPending] === 0); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i2 = 0; i2 < requests.length; i2++) { + const request = requests[i2]; + errorRequest(this, request, err); + } + } else if (client[kRunning] > 0) { + const request = client[kQueue][client[kRunningIdx]]; + client[kQueue][client[kRunningIdx]++] = null; + errorRequest(client, request, err); + } + client[kPendingIdx] = client[kRunningIdx]; + assert(client[kRunning] === 0); + client.emit( + "disconnect", + client[kUrl], + [client], + err + ); + resume(client); + } + var constants4 = require_constants3(); + var createRedirectInterceptor = require_redirectInterceptor(); + var EMPTY_BUF = Buffer.alloc(0); + async function lazyllhttp() { + const llhttpWasmData = process.env.JEST_WORKER_ID ? require_llhttp_wasm() : void 0; + let mod; + try { + mod = await WebAssembly.compile(Buffer.from(require_llhttp_simd_wasm(), "base64")); + } catch (e) { + mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || require_llhttp_wasm(), "base64")); + } + return await WebAssembly.instantiate(mod, { + env: { + /* eslint-disable camelcase */ + wasm_on_url: (p, at, len) => { + return 0; + }, + wasm_on_status: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_message_begin: (p) => { + assert.strictEqual(currentParser.ptr, p); + return currentParser.onMessageBegin() || 0; + }, + wasm_on_header_field: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_header_value: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert.strictEqual(currentParser.ptr, p); + return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0; + }, + wasm_on_body: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p); + const start = at - currentBufferPtr + currentBufferRef.byteOffset; + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0; + }, + wasm_on_message_complete: (p) => { + assert.strictEqual(currentParser.ptr, p); + return currentParser.onMessageComplete() || 0; + } + /* eslint-enable camelcase */ + } + }); + } + var llhttpInstance = null; + var llhttpPromise = lazyllhttp(); + llhttpPromise.catch(); + var currentParser = null; + var currentBufferRef = null; + var currentBufferSize = 0; + var currentBufferPtr = null; + var TIMEOUT_HEADERS = 1; + var TIMEOUT_BODY = 2; + var TIMEOUT_IDLE = 3; + var Parser = class { + constructor(client, socket, { exports: exports3 }) { + assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0); + this.llhttp = exports3; + this.ptr = this.llhttp.llhttp_alloc(constants4.TYPE.RESPONSE); + this.client = client; + this.socket = socket; + this.timeout = null; + this.timeoutValue = null; + this.timeoutType = null; + this.statusCode = null; + this.statusText = ""; + this.upgrade = false; + this.headers = []; + this.headersSize = 0; + this.headersMaxSize = client[kMaxHeadersSize]; + this.shouldKeepAlive = false; + this.paused = false; + this.resume = this.resume.bind(this); + this.bytesRead = 0; + this.keepAlive = ""; + this.contentLength = ""; + this.connection = ""; + this.maxResponseSize = client[kMaxResponseSize]; + } + setTimeout(value, type) { + this.timeoutType = type; + if (value !== this.timeoutValue) { + timers.clearTimeout(this.timeout); + if (value) { + this.timeout = timers.setTimeout(onParserTimeout, value, this); + if (this.timeout.unref) { + this.timeout.unref(); + } + } else { + this.timeout = null; + } + this.timeoutValue = value; + } else if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } + } + } + resume() { + if (this.socket.destroyed || !this.paused) { + return; + } + assert(this.ptr != null); + assert(currentParser == null); + this.llhttp.llhttp_resume(this.ptr); + assert(this.timeoutType === TIMEOUT_BODY); + if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } + } + this.paused = false; + this.execute(this.socket.read() || EMPTY_BUF); + this.readMore(); + } + readMore() { + while (!this.paused && this.ptr) { + const chunk = this.socket.read(); + if (chunk === null) { + break; + } + this.execute(chunk); + } + } + execute(data) { + assert(this.ptr != null); + assert(currentParser == null); + assert(!this.paused); + const { socket, llhttp } = this; + if (data.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr); + } + currentBufferSize = Math.ceil(data.length / 4096) * 4096; + currentBufferPtr = llhttp.malloc(currentBufferSize); + } + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data); + try { + let ret; + try { + currentBufferRef = data; + currentParser = this; + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length); + } catch (err) { + throw err; + } finally { + currentParser = null; + currentBufferRef = null; + } + const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr; + if (ret === constants4.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data.slice(offset)); + } else if (ret === constants4.ERROR.PAUSED) { + this.paused = true; + socket.unshift(data.slice(offset)); + } else if (ret !== constants4.ERROR.OK) { + const ptr = llhttp.llhttp_get_error_reason(this.ptr); + let message = ""; + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0); + message = "Response does not match the HTTP/1.1 protocol (" + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ")"; + } + throw new HTTPParserError(message, constants4.ERROR[ret], data.slice(offset)); + } + } catch (err) { + util2.destroy(socket, err); + } + } + destroy() { + assert(this.ptr != null); + assert(currentParser == null); + this.llhttp.llhttp_free(this.ptr); + this.ptr = null; + timers.clearTimeout(this.timeout); + this.timeout = null; + this.timeoutValue = null; + this.timeoutType = null; + this.paused = false; + } + onStatus(buf) { + this.statusText = buf.toString(); + } + onMessageBegin() { + const { socket, client } = this; + if (socket.destroyed) { + return -1; + } + const request = client[kQueue][client[kRunningIdx]]; + if (!request) { + return -1; + } + } + onHeaderField(buf) { + const len = this.headers.length; + if ((len & 1) === 0) { + this.headers.push(buf); + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); + } + this.trackHeader(buf.length); + } + onHeaderValue(buf) { + let len = this.headers.length; + if ((len & 1) === 1) { + this.headers.push(buf); + len += 1; + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]); + } + const key = this.headers[len - 2]; + if (key.length === 10 && key.toString().toLowerCase() === "keep-alive") { + this.keepAlive += buf.toString(); + } else if (key.length === 10 && key.toString().toLowerCase() === "connection") { + this.connection += buf.toString(); + } else if (key.length === 14 && key.toString().toLowerCase() === "content-length") { + this.contentLength += buf.toString(); + } + this.trackHeader(buf.length); + } + trackHeader(len) { + this.headersSize += len; + if (this.headersSize >= this.headersMaxSize) { + util2.destroy(this.socket, new HeadersOverflowError()); + } + } + onUpgrade(head) { + const { upgrade, client, socket, headers, statusCode } = this; + assert(upgrade); + const request = client[kQueue][client[kRunningIdx]]; + assert(request); + assert(!socket.destroyed); + assert(socket === client[kSocket]); + assert(!this.paused); + assert(request.upgrade || request.method === "CONNECT"); + this.statusCode = null; + this.statusText = ""; + this.shouldKeepAlive = null; + assert(this.headers.length % 2 === 0); + this.headers = []; + this.headersSize = 0; + socket.unshift(head); + socket[kParser].destroy(); + socket[kParser] = null; + socket[kClient] = null; + socket[kError] = null; + socket.removeListener("error", onSocketError).removeListener("readable", onSocketReadable).removeListener("end", onSocketEnd).removeListener("close", onSocketClose); + client[kSocket] = null; + client[kQueue][client[kRunningIdx]++] = null; + client.emit("disconnect", client[kUrl], [client], new InformationalError("upgrade")); + try { + request.onUpgrade(statusCode, headers, socket); + } catch (err) { + util2.destroy(socket, err); + } + resume(client); + } + onHeadersComplete(statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this; + if (socket.destroyed) { + return -1; + } + const request = client[kQueue][client[kRunningIdx]]; + if (!request) { + return -1; + } + assert(!this.upgrade); + assert(this.statusCode < 200); + if (statusCode === 100) { + util2.destroy(socket, new SocketError("bad response", util2.getSocketInfo(socket))); + return -1; + } + if (upgrade && !request.upgrade) { + util2.destroy(socket, new SocketError("bad upgrade", util2.getSocketInfo(socket))); + return -1; + } + assert.strictEqual(this.timeoutType, TIMEOUT_HEADERS); + this.statusCode = statusCode; + this.shouldKeepAlive = shouldKeepAlive || // Override llhttp value which does not allow keepAlive for HEAD. + request.method === "HEAD" && !socket[kReset] && this.connection.toLowerCase() === "keep-alive"; + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null ? request.bodyTimeout : client[kBodyTimeout]; + this.setTimeout(bodyTimeout, TIMEOUT_BODY); + } else if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } + } + if (request.method === "CONNECT") { + assert(client[kRunning] === 1); + this.upgrade = true; + return 2; + } + if (upgrade) { + assert(client[kRunning] === 1); + this.upgrade = true; + return 2; + } + assert(this.headers.length % 2 === 0); + this.headers = []; + this.headersSize = 0; + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util2.parseKeepAliveTimeout(this.keepAlive) : null; + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ); + if (timeout <= 0) { + socket[kReset] = true; + } else { + client[kKeepAliveTimeoutValue] = timeout; + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout]; + } + } else { + socket[kReset] = true; + } + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false; + if (request.aborted) { + return -1; + } + if (request.method === "HEAD") { + return 1; + } + if (statusCode < 200) { + return 1; + } + if (socket[kBlocking]) { + socket[kBlocking] = false; + resume(client); + } + return pause ? constants4.ERROR.PAUSED : 0; + } + onBody(buf) { + const { client, socket, statusCode, maxResponseSize } = this; + if (socket.destroyed) { + return -1; + } + const request = client[kQueue][client[kRunningIdx]]; + assert(request); + assert.strictEqual(this.timeoutType, TIMEOUT_BODY); + if (this.timeout) { + if (this.timeout.refresh) { + this.timeout.refresh(); + } + } + assert(statusCode >= 200); + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util2.destroy(socket, new ResponseExceededMaxSizeError()); + return -1; + } + this.bytesRead += buf.length; + if (request.onData(buf) === false) { + return constants4.ERROR.PAUSED; + } + } + onMessageComplete() { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this; + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1; + } + if (upgrade) { + return; + } + const request = client[kQueue][client[kRunningIdx]]; + assert(request); + assert(statusCode >= 100); + this.statusCode = null; + this.statusText = ""; + this.bytesRead = 0; + this.contentLength = ""; + this.keepAlive = ""; + this.connection = ""; + assert(this.headers.length % 2 === 0); + this.headers = []; + this.headersSize = 0; + if (statusCode < 200) { + return; + } + if (request.method !== "HEAD" && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util2.destroy(socket, new ResponseContentLengthMismatchError()); + return -1; + } + request.onComplete(headers); + client[kQueue][client[kRunningIdx]++] = null; + if (socket[kWriting]) { + assert.strictEqual(client[kRunning], 0); + util2.destroy(socket, new InformationalError("reset")); + return constants4.ERROR.PAUSED; + } else if (!shouldKeepAlive) { + util2.destroy(socket, new InformationalError("reset")); + return constants4.ERROR.PAUSED; + } else if (socket[kReset] && client[kRunning] === 0) { + util2.destroy(socket, new InformationalError("reset")); + return constants4.ERROR.PAUSED; + } else if (client[kPipelining] === 1) { + setImmediate(resume, client); + } else { + resume(client); + } + } + }; + function onParserTimeout(parser) { + const { socket, timeoutType, client } = parser; + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!parser.paused, "cannot be paused while waiting for headers"); + util2.destroy(socket, new HeadersTimeoutError()); + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!parser.paused) { + util2.destroy(socket, new BodyTimeoutError()); + } + } else if (timeoutType === TIMEOUT_IDLE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]); + util2.destroy(socket, new InformationalError("socket idle timeout")); + } + } + function onSocketReadable() { + const { [kParser]: parser } = this; + if (parser) { + parser.readMore(); + } + } + function onSocketError(err) { + const { [kClient]: client, [kParser]: parser } = this; + assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + if (client[kHTTPConnVersion] !== "h2") { + if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { + parser.onMessageComplete(); + return; + } + } + this[kError] = err; + onError(this[kClient], err); + } + function onError(client, err) { + if (client[kRunning] === 0 && err.code !== "UND_ERR_INFO" && err.code !== "UND_ERR_SOCKET") { + assert(client[kPendingIdx] === client[kRunningIdx]); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i2 = 0; i2 < requests.length; i2++) { + const request = requests[i2]; + errorRequest(client, request, err); + } + assert(client[kSize] === 0); + } + } + function onSocketEnd() { + const { [kParser]: parser, [kClient]: client } = this; + if (client[kHTTPConnVersion] !== "h2") { + if (parser.statusCode && !parser.shouldKeepAlive) { + parser.onMessageComplete(); + return; + } + } + util2.destroy(this, new SocketError("other side closed", util2.getSocketInfo(this))); + } + function onSocketClose() { + const { [kClient]: client, [kParser]: parser } = this; + if (client[kHTTPConnVersion] === "h1" && parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + parser.onMessageComplete(); + } + this[kParser].destroy(); + this[kParser] = null; + } + const err = this[kError] || new SocketError("closed", util2.getSocketInfo(this)); + client[kSocket] = null; + if (client.destroyed) { + assert(client[kPending] === 0); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i2 = 0; i2 < requests.length; i2++) { + const request = requests[i2]; + errorRequest(client, request, err); + } + } else if (client[kRunning] > 0 && err.code !== "UND_ERR_INFO") { + const request = client[kQueue][client[kRunningIdx]]; + client[kQueue][client[kRunningIdx]++] = null; + errorRequest(client, request, err); + } + client[kPendingIdx] = client[kRunningIdx]; + assert(client[kRunning] === 0); + client.emit("disconnect", client[kUrl], [client], err); + resume(client); + } + async function connect(client) { + assert(!client[kConnecting]); + assert(!client[kSocket]); + let { host, hostname, protocol, port } = client[kUrl]; + if (hostname[0] === "[") { + const idx = hostname.indexOf("]"); + assert(idx !== -1); + const ip = hostname.substring(1, idx); + assert(net.isIP(ip)); + hostname = ip; + } + client[kConnecting] = true; + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }); + } + try { + const socket = await new Promise((resolve, reject) => { + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket2) => { + if (err) { + reject(err); + } else { + resolve(socket2); + } + }); + }); + if (client.destroyed) { + util2.destroy(socket.on("error", () => { + }), new ClientDestroyedError()); + return; + } + client[kConnecting] = false; + assert(socket); + const isH2 = socket.alpnProtocol === "h2"; + if (isH2) { + if (!h2ExperimentalWarned) { + h2ExperimentalWarned = true; + process.emitWarning("H2 support is experimental, expect them to change at any time.", { + code: "UNDICI-H2" + }); + } + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams + }); + client[kHTTPConnVersion] = "h2"; + session[kClient] = client; + session[kSocket] = socket; + session.on("error", onHttp2SessionError); + session.on("frameError", onHttp2FrameError); + session.on("end", onHttp2SessionEnd); + session.on("goaway", onHTTP2GoAway); + session.on("close", onSocketClose); + session.unref(); + client[kHTTP2Session] = session; + socket[kHTTP2Session] = session; + } else { + if (!llhttpInstance) { + llhttpInstance = await llhttpPromise; + llhttpPromise = null; + } + socket[kNoRef] = false; + socket[kWriting] = false; + socket[kReset] = false; + socket[kBlocking] = false; + socket[kParser] = new Parser(client, socket, llhttpInstance); + } + socket[kCounter] = 0; + socket[kMaxRequests] = client[kMaxRequests]; + socket[kClient] = client; + socket[kError] = null; + socket.on("error", onSocketError).on("readable", onSocketReadable).on("end", onSocketEnd).on("close", onSocketClose); + client[kSocket] = socket; + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }); + } + client.emit("connect", client[kUrl], [client]); + } catch (err) { + if (client.destroyed) { + return; + } + client[kConnecting] = false; + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }); + } + if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + assert(client[kRunning] === 0); + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++]; + errorRequest(client, request, err); + } + } else { + onError(client, err); + } + client.emit("connectionError", client[kUrl], [client], err); + } + resume(client); + } + function emitDrain(client) { + client[kNeedDrain] = 0; + client.emit("drain", client[kUrl], [client]); + } + function resume(client, sync) { + if (client[kResuming] === 2) { + return; + } + client[kResuming] = 2; + _resume(client, sync); + client[kResuming] = 0; + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]); + client[kPendingIdx] -= client[kRunningIdx]; + client[kRunningIdx] = 0; + } + } + function _resume(client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0); + return; + } + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve](); + client[kClosedResolve] = null; + return; + } + const socket = client[kSocket]; + if (socket && !socket.destroyed && socket.alpnProtocol !== "h2") { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref(); + socket[kNoRef] = true; + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref(); + socket[kNoRef] = false; + } + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE); + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request2 = client[kQueue][client[kRunningIdx]]; + const headersTimeout = request2.headersTimeout != null ? request2.headersTimeout : client[kHeadersTimeout]; + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS); + } + } + } + if (client[kBusy]) { + client[kNeedDrain] = 2; + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1; + process.nextTick(emitDrain, client); + } else { + emitDrain(client); + } + continue; + } + if (client[kPending] === 0) { + return; + } + if (client[kRunning] >= (client[kPipelining] || 1)) { + return; + } + const request = client[kQueue][client[kPendingIdx]]; + if (client[kUrl].protocol === "https:" && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return; + } + client[kServerName] = request.servername; + if (socket && socket.servername !== request.servername) { + util2.destroy(socket, new InformationalError("servername changed")); + return; + } + } + if (client[kConnecting]) { + return; + } + if (!socket && !client[kHTTP2Session]) { + connect(client); + return; + } + if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return; + } + if (client[kRunning] > 0 && !request.idempotent) { + return; + } + if (client[kRunning] > 0 && (request.upgrade || request.method === "CONNECT")) { + return; + } + if (client[kRunning] > 0 && util2.bodyLength(request.body) !== 0 && (util2.isStream(request.body) || util2.isAsyncIterable(request.body))) { + return; + } + if (!request.aborted && write(client, request)) { + client[kPendingIdx]++; + } else { + client[kQueue].splice(client[kPendingIdx], 1); + } + } + } + function shouldSendContentLength(method) { + return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; + } + function write(client, request) { + if (client[kHTTPConnVersion] === "h2") { + writeH2(client, client[kHTTP2Session], request); + return; + } + const { body, method, path: path12, host, upgrade, headers, blocking, reset: reset2 } = request; + const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; + if (body && typeof body.read === "function") { + body.read(0); + } + const bodyLength = util2.bodyLength(body); + let contentLength = bodyLength; + if (contentLength === null) { + contentLength = request.contentLength; + } + if (contentLength === 0 && !expectsPayload) { + contentLength = null; + } + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()); + return false; + } + process.emitWarning(new RequestContentLengthMismatchError()); + } + const socket = client[kSocket]; + try { + request.onConnect((err) => { + if (request.aborted || request.completed) { + return; + } + errorRequest(client, request, err || new RequestAbortedError()); + util2.destroy(socket, new InformationalError("aborted")); + }); + } catch (err) { + errorRequest(client, request, err); + } + if (request.aborted) { + return false; + } + if (method === "HEAD") { + socket[kReset] = true; + } + if (upgrade || method === "CONNECT") { + socket[kReset] = true; + } + if (reset2 != null) { + socket[kReset] = reset2; + } + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true; + } + if (blocking) { + socket[kBlocking] = true; + } + let header = `${method} ${path12} HTTP/1.1\r +`; + if (typeof host === "string") { + header += `host: ${host}\r +`; + } else { + header += client[kHostHeader]; + } + if (upgrade) { + header += `connection: upgrade\r +upgrade: ${upgrade}\r +`; + } else if (client[kPipelining] && !socket[kReset]) { + header += "connection: keep-alive\r\n"; + } else { + header += "connection: close\r\n"; + } + if (headers) { + header += headers; + } + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }); + } + if (!body || bodyLength === 0) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r +\r +`, "latin1"); + } else { + assert(contentLength === null, "no body must not have content length"); + socket.write(`${header}\r +`, "latin1"); + } + request.onRequestSent(); + } else if (util2.isBuffer(body)) { + assert(contentLength === body.byteLength, "buffer body must have content length"); + socket.cork(); + socket.write(`${header}content-length: ${contentLength}\r +\r +`, "latin1"); + socket.write(body); + socket.uncork(); + request.onBodySent(body); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + } else if (util2.isBlobLike(body)) { + if (typeof body.stream === "function") { + writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload }); + } else { + writeBlob({ body, client, request, socket, contentLength, header, expectsPayload }); + } + } else if (util2.isStream(body)) { + writeStream({ body, client, request, socket, contentLength, header, expectsPayload }); + } else if (util2.isIterable(body)) { + writeIterable({ body, client, request, socket, contentLength, header, expectsPayload }); + } else { + assert(false); + } + return true; + } + function writeH2(client, session, request) { + const { body, method, path: path12, host, upgrade, expectContinue, signal, headers: reqHeaders } = request; + let headers; + if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()); + else headers = reqHeaders; + if (upgrade) { + errorRequest(client, request, new Error("Upgrade not supported for H2")); + return false; + } + try { + request.onConnect((err) => { + if (request.aborted || request.completed) { + return; + } + errorRequest(client, request, err || new RequestAbortedError()); + }); + } catch (err) { + errorRequest(client, request, err); + } + if (request.aborted) { + return false; + } + let stream; + const h2State = client[kHTTP2SessionState]; + headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost]; + headers[HTTP2_HEADER_METHOD] = method; + if (method === "CONNECT") { + session.ref(); + stream = session.request(headers, { endStream: false, signal }); + if (stream.id && !stream.pending) { + request.onUpgrade(null, null, stream); + ++h2State.openStreams; + } else { + stream.once("ready", () => { + request.onUpgrade(null, null, stream); + ++h2State.openStreams; + }); + } + stream.once("close", () => { + h2State.openStreams -= 1; + if (h2State.openStreams === 0) session.unref(); + }); + return true; + } + headers[HTTP2_HEADER_PATH] = path12; + headers[HTTP2_HEADER_SCHEME] = "https"; + const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; + if (body && typeof body.read === "function") { + body.read(0); + } + let contentLength = util2.bodyLength(body); + if (contentLength == null) { + contentLength = request.contentLength; + } + if (contentLength === 0 || !expectsPayload) { + contentLength = null; + } + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()); + return false; + } + process.emitWarning(new RequestContentLengthMismatchError()); + } + if (contentLength != null) { + assert(body, "no body must not have content length"); + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`; + } + session.ref(); + const shouldEndStream = method === "GET" || method === "HEAD"; + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = "100-continue"; + stream = session.request(headers, { endStream: shouldEndStream, signal }); + stream.once("continue", writeBodyH2); + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }); + writeBodyH2(); + } + ++h2State.openStreams; + stream.once("response", (headers2) => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers2; + if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), "") === false) { + stream.pause(); + } + }); + stream.once("end", () => { + request.onComplete([]); + }); + stream.on("data", (chunk) => { + if (request.onData(chunk) === false) { + stream.pause(); + } + }); + stream.once("close", () => { + h2State.openStreams -= 1; + if (h2State.openStreams === 0) { + session.unref(); + } + }); + stream.once("error", function(err) { + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1; + util2.destroy(stream, err); + } + }); + stream.once("frameError", (type, code2) => { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code2}`); + errorRequest(client, request, err); + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1; + util2.destroy(stream, err); + } + }); + return true; + function writeBodyH2() { + if (!body) { + request.onRequestSent(); + } else if (util2.isBuffer(body)) { + assert(contentLength === body.byteLength, "buffer body must have content length"); + stream.cork(); + stream.write(body); + stream.uncork(); + stream.end(); + request.onBodySent(body); + request.onRequestSent(); + } else if (util2.isBlobLike(body)) { + if (typeof body.stream === "function") { + writeIterable({ + client, + request, + contentLength, + h2stream: stream, + expectsPayload, + body: body.stream(), + socket: client[kSocket], + header: "" + }); + } else { + writeBlob({ + body, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + header: "", + socket: client[kSocket] + }); + } + } else if (util2.isStream(body)) { + writeStream({ + body, + client, + request, + contentLength, + expectsPayload, + socket: client[kSocket], + h2stream: stream, + header: "" + }); + } else if (util2.isIterable(body)) { + writeIterable({ + body, + client, + request, + contentLength, + expectsPayload, + header: "", + h2stream: stream, + socket: client[kSocket] + }); + } else { + assert(false); + } + } + } + function writeStream({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined"); + if (client[kHTTPConnVersion] === "h2") { + let onPipeData = function(chunk) { + request.onBodySent(chunk); + }; + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util2.destroy(body, err); + util2.destroy(h2stream, err); + } else { + request.onRequestSent(); + } + } + ); + pipe.on("data", onPipeData); + pipe.once("end", () => { + pipe.removeListener("data", onPipeData); + util2.destroy(pipe); + }); + return; + } + let finished7 = false; + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }); + const onData = function(chunk) { + if (finished7) { + return; + } + try { + if (!writer.write(chunk) && this.pause) { + this.pause(); + } + } catch (err) { + util2.destroy(this, err); + } + }; + const onDrain = function() { + if (finished7) { + return; + } + if (body.resume) { + body.resume(); + } + }; + const onAbort = function() { + if (finished7) { + return; + } + const err = new RequestAbortedError(); + queueMicrotask(() => onFinished(err)); + }; + const onFinished = function(err) { + if (finished7) { + return; + } + finished7 = true; + assert(socket.destroyed || socket[kWriting] && client[kRunning] <= 1); + socket.off("drain", onDrain).off("error", onFinished); + body.removeListener("data", onData).removeListener("end", onFinished).removeListener("error", onFinished).removeListener("close", onAbort); + if (!err) { + try { + writer.end(); + } catch (er) { + err = er; + } + } + writer.destroy(err); + if (err && (err.code !== "UND_ERR_INFO" || err.message !== "reset")) { + util2.destroy(body, err); + } else { + util2.destroy(body); + } + }; + body.on("data", onData).on("end", onFinished).on("error", onFinished).on("close", onAbort); + if (body.resume) { + body.resume(); + } + socket.on("drain", onDrain).on("error", onFinished); + } + async function writeBlob({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength === body.size, "blob body must have content length"); + const isH2 = client[kHTTPConnVersion] === "h2"; + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError(); + } + const buffer = Buffer.from(await body.arrayBuffer()); + if (isH2) { + h2stream.cork(); + h2stream.write(buffer); + h2stream.uncork(); + } else { + socket.cork(); + socket.write(`${header}content-length: ${contentLength}\r +\r +`, "latin1"); + socket.write(buffer); + socket.uncork(); + } + request.onBodySent(buffer); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + resume(client); + } catch (err) { + util2.destroy(isH2 ? h2stream : socket, err); + } + } + async function writeIterable({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, "iterator body cannot be pipelined"); + let callback = null; + function onDrain() { + if (callback) { + const cb = callback; + callback = null; + cb(); + } + } + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null); + if (socket[kError]) { + reject(socket[kError]); + } else { + callback = resolve; + } + }); + if (client[kHTTPConnVersion] === "h2") { + h2stream.on("close", onDrain).on("drain", onDrain); + try { + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError]; + } + const res = h2stream.write(chunk); + request.onBodySent(chunk); + if (!res) { + await waitForDrain(); + } + } + } catch (err) { + h2stream.destroy(err); + } finally { + request.onRequestSent(); + h2stream.end(); + h2stream.off("close", onDrain).off("drain", onDrain); + } + return; + } + socket.on("close", onDrain).on("drain", onDrain); + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }); + try { + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError]; + } + if (!writer.write(chunk)) { + await waitForDrain(); + } + } + writer.end(); + } catch (err) { + writer.destroy(err); + } finally { + socket.off("close", onDrain).off("drain", onDrain); + } + } + var AsyncWriter = class { + constructor({ socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket; + this.request = request; + this.contentLength = contentLength; + this.client = client; + this.bytesWritten = 0; + this.expectsPayload = expectsPayload; + this.header = header; + socket[kWriting] = true; + } + write(chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this; + if (socket[kError]) { + throw socket[kError]; + } + if (socket.destroyed) { + return false; + } + const len = Buffer.byteLength(chunk); + if (!len) { + return true; + } + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError(); + } + process.emitWarning(new RequestContentLengthMismatchError()); + } + socket.cork(); + if (bytesWritten === 0) { + if (!expectsPayload) { + socket[kReset] = true; + } + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r +`, "latin1"); + } else { + socket.write(`${header}content-length: ${contentLength}\r +\r +`, "latin1"); + } + } + if (contentLength === null) { + socket.write(`\r +${len.toString(16)}\r +`, "latin1"); + } + this.bytesWritten += len; + const ret = socket.write(chunk); + socket.uncork(); + request.onBodySent(chunk); + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh(); + } + } + } + return ret; + } + end() { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this; + request.onRequestSent(); + socket[kWriting] = false; + if (socket[kError]) { + throw socket[kError]; + } + if (socket.destroyed) { + return; + } + if (bytesWritten === 0) { + if (expectsPayload) { + socket.write(`${header}content-length: 0\r +\r +`, "latin1"); + } else { + socket.write(`${header}\r +`, "latin1"); + } + } else if (contentLength === null) { + socket.write("\r\n0\r\n\r\n", "latin1"); + } + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError(); + } else { + process.emitWarning(new RequestContentLengthMismatchError()); + } + } + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh(); + } + } + resume(client); + } + destroy(err) { + const { socket, client } = this; + socket[kWriting] = false; + if (err) { + assert(client[kRunning] <= 1, "pipeline should only contain this request"); + util2.destroy(socket, err); + } + } + }; + function errorRequest(client, request, err) { + try { + request.onError(err); + assert(request.aborted); + } catch (err2) { + client.emit("error", err2); + } + } + module2.exports = Client; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/node/fixed-queue.js +var require_fixed_queue = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/node/fixed-queue.js"(exports2, module2) { + "use strict"; + var kSize = 2048; + var kMask = kSize - 1; + var FixedCircularBuffer = class { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kSize); + this.next = null; + } + isEmpty() { + return this.top === this.bottom; + } + isFull() { + return (this.top + 1 & kMask) === this.bottom; + } + push(data) { + this.list[this.top] = data; + this.top = this.top + 1 & kMask; + } + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === void 0) + return null; + this.list[this.bottom] = void 0; + this.bottom = this.bottom + 1 & kMask; + return nextItem; + } + }; + module2.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); + } + isEmpty() { + return this.head.isEmpty(); + } + push(data) { + if (this.head.isFull()) { + this.head = this.head.next = new FixedCircularBuffer(); + } + this.head.push(data); + } + shift() { + const tail2 = this.tail; + const next = tail2.shift(); + if (tail2.isEmpty() && tail2.next !== null) { + this.tail = tail2.next; + } + return next; + } + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/pool-stats.js +var require_pool_stats = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/pool-stats.js"(exports2, module2) { + "use strict"; + var { kFree, kConnected, kPending, kQueued, kRunning, kSize } = require_symbols(); + var kPool = /* @__PURE__ */ Symbol("pool"); + var PoolStats = class { + constructor(pool) { + this[kPool] = pool; + } + get connected() { + return this[kPool][kConnected]; + } + get free() { + return this[kPool][kFree]; + } + get pending() { + return this[kPool][kPending]; + } + get queued() { + return this[kPool][kQueued]; + } + get running() { + return this[kPool][kRunning]; + } + get size() { + return this[kPool][kSize]; + } + }; + module2.exports = PoolStats; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/pool-base.js +var require_pool_base = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/pool-base.js"(exports2, module2) { + "use strict"; + var DispatcherBase = require_dispatcher_base(); + var FixedQueue = require_fixed_queue(); + var { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = require_symbols(); + var PoolStats = require_pool_stats(); + var kClients = /* @__PURE__ */ Symbol("clients"); + var kNeedDrain = /* @__PURE__ */ Symbol("needDrain"); + var kQueue = /* @__PURE__ */ Symbol("queue"); + var kClosedResolve = /* @__PURE__ */ Symbol("closed resolve"); + var kOnDrain = /* @__PURE__ */ Symbol("onDrain"); + var kOnConnect = /* @__PURE__ */ Symbol("onConnect"); + var kOnDisconnect = /* @__PURE__ */ Symbol("onDisconnect"); + var kOnConnectionError = /* @__PURE__ */ Symbol("onConnectionError"); + var kGetDispatcher = /* @__PURE__ */ Symbol("get dispatcher"); + var kAddClient = /* @__PURE__ */ Symbol("add client"); + var kRemoveClient = /* @__PURE__ */ Symbol("remove client"); + var kStats = /* @__PURE__ */ Symbol("stats"); + var PoolBase = class extends DispatcherBase { + constructor() { + super(); + this[kQueue] = new FixedQueue(); + this[kClients] = []; + this[kQueued] = 0; + const pool = this; + this[kOnDrain] = function onDrain(origin, targets) { + const queue = pool[kQueue]; + let needDrain = false; + while (!needDrain) { + const item = queue.shift(); + if (!item) { + break; + } + pool[kQueued]--; + needDrain = !this.dispatch(item.opts, item.handler); + } + this[kNeedDrain] = needDrain; + if (!this[kNeedDrain] && pool[kNeedDrain]) { + pool[kNeedDrain] = false; + pool.emit("drain", origin, [pool, ...targets]); + } + if (pool[kClosedResolve] && queue.isEmpty()) { + Promise.all(pool[kClients].map((c3) => c3.close())).then(pool[kClosedResolve]); + } + }; + this[kOnConnect] = (origin, targets) => { + pool.emit("connect", origin, [pool, ...targets]); + }; + this[kOnDisconnect] = (origin, targets, err) => { + pool.emit("disconnect", origin, [pool, ...targets], err); + }; + this[kOnConnectionError] = (origin, targets, err) => { + pool.emit("connectionError", origin, [pool, ...targets], err); + }; + this[kStats] = new PoolStats(this); + } + get [kBusy]() { + return this[kNeedDrain]; + } + get [kConnected]() { + return this[kClients].filter((client) => client[kConnected]).length; + } + get [kFree]() { + return this[kClients].filter((client) => client[kConnected] && !client[kNeedDrain]).length; + } + get [kPending]() { + let ret = this[kQueued]; + for (const { [kPending]: pending } of this[kClients]) { + ret += pending; + } + return ret; + } + get [kRunning]() { + let ret = 0; + for (const { [kRunning]: running } of this[kClients]) { + ret += running; + } + return ret; + } + get [kSize]() { + let ret = this[kQueued]; + for (const { [kSize]: size } of this[kClients]) { + ret += size; + } + return ret; + } + get stats() { + return this[kStats]; + } + async [kClose]() { + if (this[kQueue].isEmpty()) { + return Promise.all(this[kClients].map((c3) => c3.close())); + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve; + }); + } + } + async [kDestroy](err) { + while (true) { + const item = this[kQueue].shift(); + if (!item) { + break; + } + item.handler.onError(err); + } + return Promise.all(this[kClients].map((c3) => c3.destroy(err))); + } + [kDispatch](opts, handler) { + const dispatcher = this[kGetDispatcher](); + if (!dispatcher) { + this[kNeedDrain] = true; + this[kQueue].push({ opts, handler }); + this[kQueued]++; + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true; + this[kNeedDrain] = !this[kGetDispatcher](); + } + return !this[kNeedDrain]; + } + [kAddClient](client) { + client.on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); + this[kClients].push(client); + if (this[kNeedDrain]) { + process.nextTick(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client[kUrl], [this, client]); + } + }); + } + return this; + } + [kRemoveClient](client) { + client.close(() => { + const idx = this[kClients].indexOf(client); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + }); + this[kNeedDrain] = this[kClients].some((dispatcher) => !dispatcher[kNeedDrain] && dispatcher.closed !== true && dispatcher.destroyed !== true); + } + }; + module2.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/pool.js +var require_pool = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/pool.js"(exports2, module2) { + "use strict"; + var { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher + } = require_pool_base(); + var Client = require_client(); + var { + InvalidArgumentError + } = require_errors(); + var util2 = require_util(); + var { kUrl, kInterceptors } = require_symbols(); + var buildConnector = require_connect(); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kConnections = /* @__PURE__ */ Symbol("connections"); + var kFactory = /* @__PURE__ */ Symbol("factory"); + function defaultFactory(origin, opts) { + return new Client(origin, opts); + } + var Pool = class extends PoolBase { + constructor(origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + ...options + } = {}) { + super(); + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError("invalid connections"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + if (connect != null && typeof connect !== "function" && typeof connect !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (typeof connect !== "function") { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...util2.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect + }); + } + this[kInterceptors] = options.interceptors && options.interceptors.Pool && Array.isArray(options.interceptors.Pool) ? options.interceptors.Pool : []; + this[kConnections] = connections || null; + this[kUrl] = util2.parseOrigin(origin); + this[kOptions] = { ...util2.deepClone(options), connect, allowH2 }; + this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; + this[kFactory] = factory; + this.on("connectionError", (origin2, targets, error) => { + for (const target of targets) { + const idx = this[kClients].indexOf(target); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + } + }); + } + [kGetDispatcher]() { + let dispatcher = this[kClients].find((dispatcher2) => !dispatcher2[kNeedDrain]); + if (dispatcher) { + return dispatcher; + } + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + } + return dispatcher; + } + }; + module2.exports = Pool; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/balanced-pool.js +var require_balanced_pool = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/balanced-pool.js"(exports2, module2) { + "use strict"; + var { + BalancedPoolMissingUpstreamError, + InvalidArgumentError + } = require_errors(); + var { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher + } = require_pool_base(); + var Pool = require_pool(); + var { kUrl, kInterceptors } = require_symbols(); + var { parseOrigin } = require_util(); + var kFactory = /* @__PURE__ */ Symbol("factory"); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kGreatestCommonDivisor = /* @__PURE__ */ Symbol("kGreatestCommonDivisor"); + var kCurrentWeight = /* @__PURE__ */ Symbol("kCurrentWeight"); + var kIndex = /* @__PURE__ */ Symbol("kIndex"); + var kWeight = /* @__PURE__ */ Symbol("kWeight"); + var kMaxWeightPerServer = /* @__PURE__ */ Symbol("kMaxWeightPerServer"); + var kErrorPenalty = /* @__PURE__ */ Symbol("kErrorPenalty"); + function getGreatestCommonDivisor(a2, b) { + if (b === 0) return a2; + return getGreatestCommonDivisor(b, a2 % b); + } + function defaultFactory(origin, opts) { + return new Pool(origin, opts); + } + var BalancedPool = class extends PoolBase { + constructor(upstreams = [], { factory = defaultFactory, ...opts } = {}) { + super(); + this[kOptions] = opts; + this[kIndex] = -1; + this[kCurrentWeight] = 0; + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100; + this[kErrorPenalty] = this[kOptions].errorPenalty || 15; + if (!Array.isArray(upstreams)) { + upstreams = [upstreams]; + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + this[kInterceptors] = opts.interceptors && opts.interceptors.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) ? opts.interceptors.BalancedPool : []; + this[kFactory] = factory; + for (const upstream of upstreams) { + this.addUpstream(upstream); + } + this._updateBalancedPoolStats(); + } + addUpstream(upstream) { + const upstreamOrigin = parseOrigin(upstream).origin; + if (this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true)) { + return this; + } + const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])); + this[kAddClient](pool); + pool.on("connect", () => { + pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]); + }); + pool.on("connectionError", () => { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]); + this._updateBalancedPoolStats(); + }); + pool.on("disconnect", (...args) => { + const err = args[2]; + if (err && err.code === "UND_ERR_SOCKET") { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]); + this._updateBalancedPoolStats(); + } + }); + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer]; + } + this._updateBalancedPoolStats(); + return this; + } + _updateBalancedPoolStats() { + this[kGreatestCommonDivisor] = this[kClients].map((p) => p[kWeight]).reduce(getGreatestCommonDivisor, 0); + } + removeUpstream(upstream) { + const upstreamOrigin = parseOrigin(upstream).origin; + const pool = this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true); + if (pool) { + this[kRemoveClient](pool); + } + return this; + } + get upstreams() { + return this[kClients].filter((dispatcher) => dispatcher.closed !== true && dispatcher.destroyed !== true).map((p) => p[kUrl].origin); + } + [kGetDispatcher]() { + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError(); + } + const dispatcher = this[kClients].find((dispatcher2) => !dispatcher2[kNeedDrain] && dispatcher2.closed !== true && dispatcher2.destroyed !== true); + if (!dispatcher) { + return; + } + const allClientsBusy = this[kClients].map((pool) => pool[kNeedDrain]).reduce((a2, b) => a2 && b, true); + if (allClientsBusy) { + return; + } + let counter = 0; + let maxWeightIndex = this[kClients].findIndex((pool) => !pool[kNeedDrain]); + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length; + const pool = this[kClients][this[kIndex]]; + if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { + maxWeightIndex = this[kIndex]; + } + if (this[kIndex] === 0) { + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor]; + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer]; + } + } + if (pool[kWeight] >= this[kCurrentWeight] && !pool[kNeedDrain]) { + return pool; + } + } + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight]; + this[kIndex] = maxWeightIndex; + return this[kClients][maxWeightIndex]; + } + }; + module2.exports = BalancedPool; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/compat/dispatcher-weakref.js +var require_dispatcher_weakref = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/compat/dispatcher-weakref.js"(exports2, module2) { + "use strict"; + var { kConnected, kSize } = require_symbols(); + var CompatWeakRef = class { + constructor(value) { + this.value = value; + } + deref() { + return this.value[kConnected] === 0 && this.value[kSize] === 0 ? void 0 : this.value; + } + }; + var CompatFinalizer = class { + constructor(finalizer) { + this.finalizer = finalizer; + } + register(dispatcher, key) { + if (dispatcher.on) { + dispatcher.on("disconnect", () => { + if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { + this.finalizer(key); + } + }); + } + } + }; + module2.exports = function() { + if (process.env.NODE_V8_COVERAGE) { + return { + WeakRef: CompatWeakRef, + FinalizationRegistry: CompatFinalizer + }; + } + return { + WeakRef: global.WeakRef || CompatWeakRef, + FinalizationRegistry: global.FinalizationRegistry || CompatFinalizer + }; + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/agent.js +var require_agent = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/agent.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError } = require_errors(); + var { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require_symbols(); + var DispatcherBase = require_dispatcher_base(); + var Pool = require_pool(); + var Client = require_client(); + var util2 = require_util(); + var createRedirectInterceptor = require_redirectInterceptor(); + var { WeakRef: WeakRef2, FinalizationRegistry } = require_dispatcher_weakref()(); + var kOnConnect = /* @__PURE__ */ Symbol("onConnect"); + var kOnDisconnect = /* @__PURE__ */ Symbol("onDisconnect"); + var kOnConnectionError = /* @__PURE__ */ Symbol("onConnectionError"); + var kMaxRedirections = /* @__PURE__ */ Symbol("maxRedirections"); + var kOnDrain = /* @__PURE__ */ Symbol("onDrain"); + var kFactory = /* @__PURE__ */ Symbol("factory"); + var kFinalizer = /* @__PURE__ */ Symbol("finalizer"); + var kOptions = /* @__PURE__ */ Symbol("options"); + function defaultFactory(origin, opts) { + return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); + } + var Agent = class extends DispatcherBase { + constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + super(); + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + if (connect != null && typeof connect !== "function" && typeof connect !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + if (connect && typeof connect !== "function") { + connect = { ...connect }; + } + this[kInterceptors] = options.interceptors && options.interceptors.Agent && Array.isArray(options.interceptors.Agent) ? options.interceptors.Agent : [createRedirectInterceptor({ maxRedirections })]; + this[kOptions] = { ...util2.deepClone(options), connect }; + this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; + this[kMaxRedirections] = maxRedirections; + this[kFactory] = factory; + this[kClients] = /* @__PURE__ */ new Map(); + this[kFinalizer] = new FinalizationRegistry( + /* istanbul ignore next: gc is undeterministic */ + (key) => { + const ref = this[kClients].get(key); + if (ref !== void 0 && ref.deref() === void 0) { + this[kClients].delete(key); + } + } + ); + const agent = this; + this[kOnDrain] = (origin, targets) => { + agent.emit("drain", origin, [agent, ...targets]); + }; + this[kOnConnect] = (origin, targets) => { + agent.emit("connect", origin, [agent, ...targets]); + }; + this[kOnDisconnect] = (origin, targets, err) => { + agent.emit("disconnect", origin, [agent, ...targets], err); + }; + this[kOnConnectionError] = (origin, targets, err) => { + agent.emit("connectionError", origin, [agent, ...targets], err); + }; + } + get [kRunning]() { + let ret = 0; + for (const ref of this[kClients].values()) { + const client = ref.deref(); + if (client) { + ret += client[kRunning]; + } + } + return ret; + } + [kDispatch](opts, handler) { + let key; + if (opts.origin && (typeof opts.origin === "string" || opts.origin instanceof URL)) { + key = String(opts.origin); + } else { + throw new InvalidArgumentError("opts.origin must be a non-empty string or URL."); + } + const ref = this[kClients].get(key); + let dispatcher = ref ? ref.deref() : null; + if (!dispatcher) { + dispatcher = this[kFactory](opts.origin, this[kOptions]).on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); + this[kClients].set(key, new WeakRef2(dispatcher)); + this[kFinalizer].register(dispatcher, key); + } + return dispatcher.dispatch(opts, handler); + } + async [kClose]() { + const closePromises = []; + for (const ref of this[kClients].values()) { + const client = ref.deref(); + if (client) { + closePromises.push(client.close()); + } + } + await Promise.all(closePromises); + } + async [kDestroy](err) { + const destroyPromises = []; + for (const ref of this[kClients].values()) { + const client = ref.deref(); + if (client) { + destroyPromises.push(client.destroy(err)); + } + } + await Promise.all(destroyPromises); + } + }; + module2.exports = Agent; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/readable.js +var require_readable = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/readable.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var { Readable: Readable4 } = require("stream"); + var { RequestAbortedError, NotSupportedError, InvalidArgumentError } = require_errors(); + var util2 = require_util(); + var { ReadableStreamFrom, toUSVString } = require_util(); + var Blob2; + var kConsume = /* @__PURE__ */ Symbol("kConsume"); + var kReading = /* @__PURE__ */ Symbol("kReading"); + var kBody = /* @__PURE__ */ Symbol("kBody"); + var kAbort = /* @__PURE__ */ Symbol("abort"); + var kContentType = /* @__PURE__ */ Symbol("kContentType"); + var noop3 = () => { + }; + module2.exports = class BodyReadable extends Readable4 { + constructor({ + resume, + abort, + contentType = "", + highWaterMark = 64 * 1024 + // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }); + this._readableState.dataEmitted = false; + this[kAbort] = abort; + this[kConsume] = null; + this[kBody] = null; + this[kContentType] = contentType; + this[kReading] = false; + } + destroy(err) { + if (this.destroyed) { + return this; + } + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError(); + } + if (err) { + this[kAbort](); + } + return super.destroy(err); + } + emit(ev, ...args) { + if (ev === "data") { + this._readableState.dataEmitted = true; + } else if (ev === "error") { + this._readableState.errorEmitted = true; + } + return super.emit(ev, ...args); + } + on(ev, ...args) { + if (ev === "data" || ev === "readable") { + this[kReading] = true; + } + return super.on(ev, ...args); + } + addListener(ev, ...args) { + return this.on(ev, ...args); + } + off(ev, ...args) { + const ret = super.off(ev, ...args); + if (ev === "data" || ev === "readable") { + this[kReading] = this.listenerCount("data") > 0 || this.listenerCount("readable") > 0; + } + return ret; + } + removeListener(ev, ...args) { + return this.off(ev, ...args); + } + push(chunk) { + if (this[kConsume] && chunk !== null && this.readableLength === 0) { + consumePush(this[kConsume], chunk); + return this[kReading] ? super.push(chunk) : true; + } + return super.push(chunk); + } + // https://fetch.spec.whatwg.org/#dom-body-text + async text() { + return consume(this, "text"); + } + // https://fetch.spec.whatwg.org/#dom-body-json + async json() { + return consume(this, "json"); + } + // https://fetch.spec.whatwg.org/#dom-body-blob + async blob() { + return consume(this, "blob"); + } + // https://fetch.spec.whatwg.org/#dom-body-arraybuffer + async arrayBuffer() { + return consume(this, "arrayBuffer"); + } + // https://fetch.spec.whatwg.org/#dom-body-formdata + async formData() { + throw new NotSupportedError(); + } + // https://fetch.spec.whatwg.org/#dom-body-bodyused + get bodyUsed() { + return util2.isDisturbed(this); + } + // https://fetch.spec.whatwg.org/#dom-body-body + get body() { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this); + if (this[kConsume]) { + this[kBody].getReader(); + assert(this[kBody].locked); + } + } + return this[kBody]; + } + dump(opts) { + let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144; + const signal = opts && opts.signal; + if (signal) { + try { + if (typeof signal !== "object" || !("aborted" in signal)) { + throw new InvalidArgumentError("signal must be an AbortSignal"); + } + util2.throwIfAborted(signal); + } catch (err) { + return Promise.reject(err); + } + } + if (this.closed) { + return Promise.resolve(null); + } + return new Promise((resolve, reject) => { + const signalListenerCleanup = signal ? util2.addAbortListener(signal, () => { + this.destroy(); + }) : noop3; + this.on("close", function() { + signalListenerCleanup(); + if (signal && signal.aborted) { + reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" })); + } else { + resolve(null); + } + }).on("error", noop3).on("data", function(chunk) { + limit -= chunk.length; + if (limit <= 0) { + this.destroy(); + } + }).resume(); + }); + } + }; + function isLocked(self) { + return self[kBody] && self[kBody].locked === true || self[kConsume]; + } + function isUnusable(self) { + return util2.isDisturbed(self) || isLocked(self); + } + async function consume(stream, type) { + if (isUnusable(stream)) { + throw new TypeError("unusable"); + } + assert(!stream[kConsume]); + return new Promise((resolve, reject) => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + }; + stream.on("error", function(err) { + consumeFinish(this[kConsume], err); + }).on("close", function() { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()); + } + }); + process.nextTick(consumeStart, stream[kConsume]); + }); + } + function consumeStart(consume2) { + if (consume2.body === null) { + return; + } + const { _readableState: state } = consume2.stream; + for (const chunk of state.buffer) { + consumePush(consume2, chunk); + } + if (state.endEmitted) { + consumeEnd(this[kConsume]); + } else { + consume2.stream.on("end", function() { + consumeEnd(this[kConsume]); + }); + } + consume2.stream.resume(); + while (consume2.stream.read() != null) { + } + } + function consumeEnd(consume2) { + const { type, body, resolve, stream, length } = consume2; + try { + if (type === "text") { + resolve(toUSVString(Buffer.concat(body))); + } else if (type === "json") { + resolve(JSON.parse(Buffer.concat(body))); + } else if (type === "arrayBuffer") { + const dst = new Uint8Array(length); + let pos = 0; + for (const buf of body) { + dst.set(buf, pos); + pos += buf.byteLength; + } + resolve(dst.buffer); + } else if (type === "blob") { + if (!Blob2) { + Blob2 = require("buffer").Blob; + } + resolve(new Blob2(body, { type: stream[kContentType] })); + } + consumeFinish(consume2); + } catch (err) { + stream.destroy(err); + } + } + function consumePush(consume2, chunk) { + consume2.length += chunk.length; + consume2.body.push(chunk); + } + function consumeFinish(consume2, err) { + if (consume2.body === null) { + return; + } + if (err) { + consume2.reject(err); + } else { + consume2.resolve(); + } + consume2.type = null; + consume2.stream = null; + consume2.resolve = null; + consume2.reject = null; + consume2.length = 0; + consume2.body = null; + } + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/util.js +var require_util3 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/util.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var { + ResponseStatusCodeError + } = require_errors(); + var { toUSVString } = require_util(); + async function getResolveErrorBodyCallback({ callback, body, contentType, statusCode, statusMessage, headers }) { + assert(body); + let chunks = []; + let limit = 0; + for await (const chunk of body) { + chunks.push(chunk); + limit += chunk.length; + if (limit > 128 * 1024) { + chunks = null; + break; + } + } + if (statusCode === 204 || !contentType || !chunks) { + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ""}`, statusCode, headers)); + return; + } + try { + if (contentType.startsWith("application/json")) { + const payload = JSON.parse(toUSVString(Buffer.concat(chunks))); + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ""}`, statusCode, headers, payload)); + return; + } + if (contentType.startsWith("text/")) { + const payload = toUSVString(Buffer.concat(chunks)); + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ""}`, statusCode, headers, payload)); + return; + } + } catch (err) { + } + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ""}`, statusCode, headers)); + } + module2.exports = { getResolveErrorBodyCallback }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/abort-signal.js +var require_abort_signal = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/abort-signal.js"(exports2, module2) { + "use strict"; + var { addAbortListener: addAbortListener3 } = require_util(); + var { RequestAbortedError } = require_errors(); + var kListener = /* @__PURE__ */ Symbol("kListener"); + var kSignal = /* @__PURE__ */ Symbol("kSignal"); + function abort(self) { + if (self.abort) { + self.abort(); + } else { + self.onError(new RequestAbortedError()); + } + } + function addSignal(self, signal) { + self[kSignal] = null; + self[kListener] = null; + if (!signal) { + return; + } + if (signal.aborted) { + abort(self); + return; + } + self[kSignal] = signal; + self[kListener] = () => { + abort(self); + }; + addAbortListener3(self[kSignal], self[kListener]); + } + function removeSignal(self) { + if (!self[kSignal]) { + return; + } + if ("removeEventListener" in self[kSignal]) { + self[kSignal].removeEventListener("abort", self[kListener]); + } else { + self[kSignal].removeListener("abort", self[kListener]); + } + self[kSignal] = null; + self[kListener] = null; + } + module2.exports = { + addSignal, + removeSignal + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-request.js +var require_api_request = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-request.js"(exports2, module2) { + "use strict"; + var Readable4 = require_readable(); + var { + InvalidArgumentError, + RequestAbortedError + } = require_errors(); + var util2 = require_util(); + var { getResolveErrorBodyCallback } = require_util3(); + var { AsyncResource } = require("async_hooks"); + var { addSignal, removeSignal } = require_abort_signal(); + var RequestHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts; + try { + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (highWaterMark && (typeof highWaterMark !== "number" || highWaterMark < 0)) { + throw new InvalidArgumentError("invalid highWaterMark"); + } + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_REQUEST"); + } catch (err) { + if (util2.isStream(body)) { + util2.destroy(body.on("error", util2.nop), err); + } + throw err; + } + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.callback = callback; + this.res = null; + this.abort = null; + this.body = body; + this.trailers = {}; + this.context = null; + this.onInfo = onInfo || null; + this.throwOnError = throwOnError; + this.highWaterMark = highWaterMark; + if (util2.isStream(body)) { + body.on("error", (err) => { + this.onError(err); + }); + } + addSignal(this, signal); + } + onConnect(abort, context) { + if (!this.callback) { + throw new RequestAbortedError(); + } + this.abort = abort; + this.context = context; + } + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this; + const headers = responseHeaders === "raw" ? util2.parseRawHeaders(rawHeaders) : util2.parseHeaders(rawHeaders); + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }); + } + return; + } + const parsedHeaders = responseHeaders === "raw" ? util2.parseHeaders(rawHeaders) : headers; + const contentType = parsedHeaders["content-type"]; + const body = new Readable4({ resume, abort, contentType, highWaterMark }); + this.callback = null; + this.res = body; + if (callback !== null) { + if (this.throwOnError && statusCode >= 400) { + this.runInAsyncScope( + getResolveErrorBodyCallback, + null, + { callback, body, contentType, statusCode, statusMessage, headers } + ); + } else { + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + trailers: this.trailers, + opaque, + body, + context + }); + } + } + } + onData(chunk) { + const { res } = this; + return res.push(chunk); + } + onComplete(trailers) { + const { res } = this; + removeSignal(this); + util2.parseHeaders(trailers, this.trailers); + res.push(null); + } + onError(err) { + const { res, callback, body, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + if (res) { + this.res = null; + queueMicrotask(() => { + util2.destroy(res, err); + }); + } + if (body) { + this.body = null; + util2.destroy(body, err); + } + } + }; + function request(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + this.dispatch(opts, new RequestHandler(opts, callback)); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts && opts.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = request; + module2.exports.RequestHandler = RequestHandler; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-stream.js +var require_api_stream = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-stream.js"(exports2, module2) { + "use strict"; + var { finished: finished7, PassThrough: PassThrough2 } = require("stream"); + var { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError + } = require_errors(); + var util2 = require_util(); + var { getResolveErrorBodyCallback } = require_util3(); + var { AsyncResource } = require("async_hooks"); + var { addSignal, removeSignal } = require_abort_signal(); + var StreamHandler = class extends AsyncResource { + constructor(opts, factory, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts; + try { + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("invalid factory"); + } + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_STREAM"); + } catch (err) { + if (util2.isStream(body)) { + util2.destroy(body.on("error", util2.nop), err); + } + throw err; + } + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.factory = factory; + this.callback = callback; + this.res = null; + this.abort = null; + this.context = null; + this.trailers = null; + this.body = body; + this.onInfo = onInfo || null; + this.throwOnError = throwOnError || false; + if (util2.isStream(body)) { + body.on("error", (err) => { + this.onError(err); + }); + } + addSignal(this, signal); + } + onConnect(abort, context) { + if (!this.callback) { + throw new RequestAbortedError(); + } + this.abort = abort; + this.context = context; + } + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, callback, responseHeaders } = this; + const headers = responseHeaders === "raw" ? util2.parseRawHeaders(rawHeaders) : util2.parseHeaders(rawHeaders); + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }); + } + return; + } + this.factory = null; + let res; + if (this.throwOnError && statusCode >= 400) { + const parsedHeaders = responseHeaders === "raw" ? util2.parseHeaders(rawHeaders) : headers; + const contentType = parsedHeaders["content-type"]; + res = new PassThrough2(); + this.callback = null; + this.runInAsyncScope( + getResolveErrorBodyCallback, + null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ); + } else { + if (factory === null) { + return; + } + res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }); + if (!res || typeof res.write !== "function" || typeof res.end !== "function" || typeof res.on !== "function") { + throw new InvalidReturnValueError("expected Writable"); + } + finished7(res, { readable: false }, (err) => { + const { callback: callback2, res: res2, opaque: opaque2, trailers, abort } = this; + this.res = null; + if (err || !res2.readable) { + util2.destroy(res2, err); + } + this.callback = null; + this.runInAsyncScope(callback2, null, err || null, { opaque: opaque2, trailers }); + if (err) { + abort(); + } + }); + } + res.on("drain", resume); + this.res = res; + const needDrain = res.writableNeedDrain !== void 0 ? res.writableNeedDrain : res._writableState && res._writableState.needDrain; + return needDrain !== true; + } + onData(chunk) { + const { res } = this; + return res ? res.write(chunk) : true; + } + onComplete(trailers) { + const { res } = this; + removeSignal(this); + if (!res) { + return; + } + this.trailers = util2.parseHeaders(trailers); + res.end(); + } + onError(err) { + const { res, callback, opaque, body } = this; + removeSignal(this); + this.factory = null; + if (res) { + this.res = null; + util2.destroy(res, err); + } else if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + if (body) { + this.body = null; + util2.destroy(body, err); + } + } + }; + function stream(opts, factory, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + this.dispatch(opts, new StreamHandler(opts, factory, callback)); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts && opts.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = stream; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-pipeline.js +var require_api_pipeline = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-pipeline.js"(exports2, module2) { + "use strict"; + var { + Readable: Readable4, + Duplex: Duplex4, + PassThrough: PassThrough2 + } = require("stream"); + var { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError + } = require_errors(); + var util2 = require_util(); + var { AsyncResource } = require("async_hooks"); + var { addSignal, removeSignal } = require_abort_signal(); + var assert = require("assert"); + var kResume = /* @__PURE__ */ Symbol("resume"); + var PipelineRequest = class extends Readable4 { + constructor() { + super({ autoDestroy: true }); + this[kResume] = null; + } + _read() { + const { [kResume]: resume } = this; + if (resume) { + this[kResume] = null; + resume(); + } + } + _destroy(err, callback) { + this._read(); + callback(err); + } + }; + var PipelineResponse = class extends Readable4 { + constructor(resume) { + super({ autoDestroy: true }); + this[kResume] = resume; + } + _read() { + this[kResume](); + } + _destroy(err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError(); + } + callback(err); + } + }; + var PipelineHandler = class extends AsyncResource { + constructor(opts, handler) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof handler !== "function") { + throw new InvalidArgumentError("invalid handler"); + } + const { signal, method, opaque, onInfo, responseHeaders } = opts; + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_PIPELINE"); + this.opaque = opaque || null; + this.responseHeaders = responseHeaders || null; + this.handler = handler; + this.abort = null; + this.context = null; + this.onInfo = onInfo || null; + this.req = new PipelineRequest().on("error", util2.nop); + this.ret = new Duplex4({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this; + if (body && body.resume) { + body.resume(); + } + }, + write: (chunk, encoding, callback) => { + const { req } = this; + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback(); + } else { + req[kResume] = callback; + } + }, + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this; + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError(); + } + if (abort && err) { + abort(); + } + util2.destroy(body, err); + util2.destroy(req, err); + util2.destroy(res, err); + removeSignal(this); + callback(err); + } + }).on("prefinish", () => { + const { req } = this; + req.push(null); + }); + this.res = null; + addSignal(this, signal); + } + onConnect(abort, context) { + const { ret, res } = this; + assert(!res, "pipeline cannot be retried"); + if (ret.destroyed) { + throw new RequestAbortedError(); + } + this.abort = abort; + this.context = context; + } + onHeaders(statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this; + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === "raw" ? util2.parseRawHeaders(rawHeaders) : util2.parseHeaders(rawHeaders); + this.onInfo({ statusCode, headers }); + } + return; + } + this.res = new PipelineResponse(resume); + let body; + try { + this.handler = null; + const headers = this.responseHeaders === "raw" ? util2.parseRawHeaders(rawHeaders) : util2.parseHeaders(rawHeaders); + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }); + } catch (err) { + this.res.on("error", util2.nop); + throw err; + } + if (!body || typeof body.on !== "function") { + throw new InvalidReturnValueError("expected Readable"); + } + body.on("data", (chunk) => { + const { ret, body: body2 } = this; + if (!ret.push(chunk) && body2.pause) { + body2.pause(); + } + }).on("error", (err) => { + const { ret } = this; + util2.destroy(ret, err); + }).on("end", () => { + const { ret } = this; + ret.push(null); + }).on("close", () => { + const { ret } = this; + if (!ret._readableState.ended) { + util2.destroy(ret, new RequestAbortedError()); + } + }); + this.body = body; + } + onData(chunk) { + const { res } = this; + return res.push(chunk); + } + onComplete(trailers) { + const { res } = this; + res.push(null); + } + onError(err) { + const { ret } = this; + this.handler = null; + util2.destroy(ret, err); + } + }; + function pipeline(opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler); + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler); + return pipelineHandler.ret; + } catch (err) { + return new PassThrough2().destroy(err); + } + } + module2.exports = pipeline; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-upgrade.js +var require_api_upgrade = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-upgrade.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError, RequestAbortedError, SocketError } = require_errors(); + var { AsyncResource } = require("async_hooks"); + var util2 = require_util(); + var { addSignal, removeSignal } = require_abort_signal(); + var assert = require("assert"); + var UpgradeHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + const { signal, opaque, responseHeaders } = opts; + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + super("UNDICI_UPGRADE"); + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.callback = callback; + this.abort = null; + this.context = null; + addSignal(this, signal); + } + onConnect(abort, context) { + if (!this.callback) { + throw new RequestAbortedError(); + } + this.abort = abort; + this.context = null; + } + onHeaders() { + throw new SocketError("bad upgrade", null); + } + onUpgrade(statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this; + assert.strictEqual(statusCode, 101); + removeSignal(this); + this.callback = null; + const headers = this.responseHeaders === "raw" ? util2.parseRawHeaders(rawHeaders) : util2.parseHeaders(rawHeaders); + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }); + } + onError(err) { + const { callback, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + } + }; + function upgrade(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + const upgradeHandler = new UpgradeHandler(opts, callback); + this.dispatch({ + ...opts, + method: opts.method || "GET", + upgrade: opts.protocol || "Websocket" + }, upgradeHandler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts && opts.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = upgrade; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-connect.js +var require_api_connect = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/api-connect.js"(exports2, module2) { + "use strict"; + var { AsyncResource } = require("async_hooks"); + var { InvalidArgumentError, RequestAbortedError, SocketError } = require_errors(); + var util2 = require_util(); + var { addSignal, removeSignal } = require_abort_signal(); + var ConnectHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + const { signal, opaque, responseHeaders } = opts; + if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + super("UNDICI_CONNECT"); + this.opaque = opaque || null; + this.responseHeaders = responseHeaders || null; + this.callback = callback; + this.abort = null; + addSignal(this, signal); + } + onConnect(abort, context) { + if (!this.callback) { + throw new RequestAbortedError(); + } + this.abort = abort; + this.context = context; + } + onHeaders() { + throw new SocketError("bad connect", null); + } + onUpgrade(statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this; + removeSignal(this); + this.callback = null; + let headers = rawHeaders; + if (headers != null) { + headers = this.responseHeaders === "raw" ? util2.parseRawHeaders(rawHeaders) : util2.parseHeaders(rawHeaders); + } + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context + }); + } + onError(err) { + const { callback, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + } + }; + function connect(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data); + }); + }); + } + try { + const connectHandler = new ConnectHandler(opts, callback); + this.dispatch({ ...opts, method: "CONNECT" }, connectHandler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts && opts.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = connect; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/index.js +var require_api = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/api/index.js"(exports2, module2) { + "use strict"; + module2.exports.request = require_api_request(); + module2.exports.stream = require_api_stream(); + module2.exports.pipeline = require_api_pipeline(); + module2.exports.upgrade = require_api_upgrade(); + module2.exports.connect = require_api_connect(); + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-errors.js +var require_mock_errors = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-errors.js"(exports2, module2) { + "use strict"; + var { UndiciError } = require_errors(); + var MockNotMatchedError = class _MockNotMatchedError extends UndiciError { + constructor(message) { + super(message); + Error.captureStackTrace(this, _MockNotMatchedError); + this.name = "MockNotMatchedError"; + this.message = message || "The request does not match any registered mock dispatches"; + this.code = "UND_MOCK_ERR_MOCK_NOT_MATCHED"; + } + }; + module2.exports = { + MockNotMatchedError + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-symbols.js +var require_mock_symbols = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kAgent: /* @__PURE__ */ Symbol("agent"), + kOptions: /* @__PURE__ */ Symbol("options"), + kFactory: /* @__PURE__ */ Symbol("factory"), + kDispatches: /* @__PURE__ */ Symbol("dispatches"), + kDispatchKey: /* @__PURE__ */ Symbol("dispatch key"), + kDefaultHeaders: /* @__PURE__ */ Symbol("default headers"), + kDefaultTrailers: /* @__PURE__ */ Symbol("default trailers"), + kContentLength: /* @__PURE__ */ Symbol("content length"), + kMockAgent: /* @__PURE__ */ Symbol("mock agent"), + kMockAgentSet: /* @__PURE__ */ Symbol("mock agent set"), + kMockAgentGet: /* @__PURE__ */ Symbol("mock agent get"), + kMockDispatch: /* @__PURE__ */ Symbol("mock dispatch"), + kClose: /* @__PURE__ */ Symbol("close"), + kOriginalClose: /* @__PURE__ */ Symbol("original agent close"), + kOrigin: /* @__PURE__ */ Symbol("origin"), + kIsMockActive: /* @__PURE__ */ Symbol("is mock active"), + kNetConnect: /* @__PURE__ */ Symbol("net connect"), + kGetNetConnect: /* @__PURE__ */ Symbol("get net connect"), + kConnected: /* @__PURE__ */ Symbol("connected") + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-utils.js +var require_mock_utils = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-utils.js"(exports2, module2) { + "use strict"; + var { MockNotMatchedError } = require_mock_errors(); + var { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect + } = require_mock_symbols(); + var { buildURL, nop } = require_util(); + var { STATUS_CODES } = require("http"); + var { + types: { + isPromise + } + } = require("util"); + function matchValue(match, value) { + if (typeof match === "string") { + return match === value; + } + if (match instanceof RegExp) { + return match.test(value); + } + if (typeof match === "function") { + return match(value) === true; + } + return false; + } + function lowerCaseEntries(headers) { + return Object.fromEntries( + Object.entries(headers).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue]; + }) + ); + } + function getHeaderByName(headers, key) { + if (Array.isArray(headers)) { + for (let i2 = 0; i2 < headers.length; i2 += 2) { + if (headers[i2].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers[i2 + 1]; + } + } + return void 0; + } else if (typeof headers.get === "function") { + return headers.get(key); + } else { + return lowerCaseEntries(headers)[key.toLocaleLowerCase()]; + } + } + function buildHeadersFromArray(headers) { + const clone = headers.slice(); + const entries = []; + for (let index = 0; index < clone.length; index += 2) { + entries.push([clone[index], clone[index + 1]]); + } + return Object.fromEntries(entries); + } + function matchHeaders(mockDispatch2, headers) { + if (typeof mockDispatch2.headers === "function") { + if (Array.isArray(headers)) { + headers = buildHeadersFromArray(headers); + } + return mockDispatch2.headers(headers ? lowerCaseEntries(headers) : {}); + } + if (typeof mockDispatch2.headers === "undefined") { + return true; + } + if (typeof headers !== "object" || typeof mockDispatch2.headers !== "object") { + return false; + } + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch2.headers)) { + const headerValue = getHeaderByName(headers, matchHeaderName); + if (!matchValue(matchHeaderValue, headerValue)) { + return false; + } + } + return true; + } + function safeUrl(path12) { + if (typeof path12 !== "string") { + return path12; + } + const pathSegments = path12.split("?"); + if (pathSegments.length !== 2) { + return path12; + } + const qp = new URLSearchParams(pathSegments.pop()); + qp.sort(); + return [...pathSegments, qp.toString()].join("?"); + } + function matchKey(mockDispatch2, { path: path12, method, body, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path12); + const methodMatch = matchValue(mockDispatch2.method, method); + const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true; + const headersMatch = matchHeaders(mockDispatch2, headers); + return pathMatch && methodMatch && bodyMatch && headersMatch; + } + function getResponseData(data) { + if (Buffer.isBuffer(data)) { + return data; + } else if (typeof data === "object") { + return JSON.stringify(data); + } else { + return data.toString(); + } + } + function getMockDispatch(mockDispatches, key) { + const basePath = key.query ? buildURL(key.path, key.query) : key.path; + const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path12 }) => matchValue(safeUrl(path12), resolvedPath)); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); + } + matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`); + } + matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== "undefined" ? matchValue(body, key.body) : true); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`); + } + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch2) => matchHeaders(mockDispatch2, key.headers)); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === "object" ? JSON.stringify(key.headers) : key.headers}'`); + } + return matchedMockDispatches[0]; + } + function addMockDispatch(mockDispatches, key, data) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false }; + const replyData = typeof data === "function" ? { callback: data } : { ...data }; + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } }; + mockDispatches.push(newMockDispatch); + return newMockDispatch; + } + function deleteMockDispatch(mockDispatches, key) { + const index = mockDispatches.findIndex((dispatch) => { + if (!dispatch.consumed) { + return false; + } + return matchKey(dispatch, key); + }); + if (index !== -1) { + mockDispatches.splice(index, 1); + } + } + function buildKey(opts) { + const { path: path12, method, body, headers, query } = opts; + return { + path: path12, + method, + body, + headers, + query + }; + } + function generateKeyValues(data) { + return Object.entries(data).reduce((keyValuePairs, [key, value]) => [ + ...keyValuePairs, + Buffer.from(`${key}`), + Array.isArray(value) ? value.map((x) => Buffer.from(`${x}`)) : Buffer.from(`${value}`) + ], []); + } + function getStatusText(statusCode) { + return STATUS_CODES[statusCode] || "unknown"; + } + async function getResponse(body) { + const buffers = []; + for await (const data of body) { + buffers.push(data); + } + return Buffer.concat(buffers).toString("utf8"); + } + function mockDispatch(opts, handler) { + const key = buildKey(opts); + const mockDispatch2 = getMockDispatch(this[kDispatches], key); + mockDispatch2.timesInvoked++; + if (mockDispatch2.data.callback) { + mockDispatch2.data = { ...mockDispatch2.data, ...mockDispatch2.data.callback(opts) }; + } + const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch2; + const { timesInvoked, times } = mockDispatch2; + mockDispatch2.consumed = !persist && timesInvoked >= times; + mockDispatch2.pending = timesInvoked < times; + if (error !== null) { + deleteMockDispatch(this[kDispatches], key); + handler.onError(error); + return true; + } + if (typeof delay === "number" && delay > 0) { + setTimeout(() => { + handleReply(this[kDispatches]); + }, delay); + } else { + handleReply(this[kDispatches]); + } + function handleReply(mockDispatches, _data = data) { + const optsHeaders = Array.isArray(opts.headers) ? buildHeadersFromArray(opts.headers) : opts.headers; + const body = typeof _data === "function" ? _data({ ...opts, headers: optsHeaders }) : _data; + if (isPromise(body)) { + body.then((newData) => handleReply(mockDispatches, newData)); + return; + } + const responseData = getResponseData(body); + const responseHeaders = generateKeyValues(headers); + const responseTrailers = generateKeyValues(trailers); + handler.abort = nop; + handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode)); + handler.onData(Buffer.from(responseData)); + handler.onComplete(responseTrailers); + deleteMockDispatch(mockDispatches, key); + } + function resume() { + } + return true; + } + function buildMockDispatch() { + const agent = this[kMockAgent]; + const origin = this[kOrigin]; + const originalDispatch = this[kOriginalDispatch]; + return function dispatch(opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler); + } catch (error) { + if (error instanceof MockNotMatchedError) { + const netConnect = agent[kGetNetConnect](); + if (netConnect === false) { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`); + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, opts, handler); + } else { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`); + } + } else { + throw error; + } + } + } else { + originalDispatch.call(this, opts, handler); + } + }; + } + function checkNetConnect(netConnect, origin) { + const url = new URL(origin); + if (netConnect === true) { + return true; + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { + return true; + } + return false; + } + function buildMockOptions(opts) { + if (opts) { + const { agent, ...mockOptions } = opts; + return mockOptions; + } + } + module2.exports = { + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildMockOptions, + getHeaderByName + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-interceptor.js +var require_mock_interceptor = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-interceptor.js"(exports2, module2) { + "use strict"; + var { getResponseData, buildKey, addMockDispatch } = require_mock_utils(); + var { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch + } = require_mock_symbols(); + var { InvalidArgumentError } = require_errors(); + var { buildURL } = require_util(); + var MockScope = class { + constructor(mockDispatch) { + this[kMockDispatch] = mockDispatch; + } + /** + * Delay a reply by a set amount in ms. + */ + delay(waitInMs) { + if (typeof waitInMs !== "number" || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError("waitInMs must be a valid integer > 0"); + } + this[kMockDispatch].delay = waitInMs; + return this; + } + /** + * For a defined reply, never mark as consumed. + */ + persist() { + this[kMockDispatch].persist = true; + return this; + } + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times(repeatTimes) { + if (typeof repeatTimes !== "number" || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError("repeatTimes must be a valid integer > 0"); + } + this[kMockDispatch].times = repeatTimes; + return this; + } + }; + var MockInterceptor = class { + constructor(opts, mockDispatches) { + if (typeof opts !== "object") { + throw new InvalidArgumentError("opts must be an object"); + } + if (typeof opts.path === "undefined") { + throw new InvalidArgumentError("opts.path must be defined"); + } + if (typeof opts.method === "undefined") { + opts.method = "GET"; + } + if (typeof opts.path === "string") { + if (opts.query) { + opts.path = buildURL(opts.path, opts.query); + } else { + const parsedURL = new URL(opts.path, "data://"); + opts.path = parsedURL.pathname + parsedURL.search; + } + } + if (typeof opts.method === "string") { + opts.method = opts.method.toUpperCase(); + } + this[kDispatchKey] = buildKey(opts); + this[kDispatches] = mockDispatches; + this[kDefaultHeaders] = {}; + this[kDefaultTrailers] = {}; + this[kContentLength] = false; + } + createMockScopeDispatchData(statusCode, data, responseOptions = {}) { + const responseData = getResponseData(data); + const contentLength = this[kContentLength] ? { "content-length": responseData.length } : {}; + const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers }; + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers }; + return { statusCode, data, headers, trailers }; + } + validateReplyParameters(statusCode, data, responseOptions) { + if (typeof statusCode === "undefined") { + throw new InvalidArgumentError("statusCode must be defined"); + } + if (typeof data === "undefined") { + throw new InvalidArgumentError("data must be defined"); + } + if (typeof responseOptions !== "object") { + throw new InvalidArgumentError("responseOptions must be an object"); + } + } + /** + * Mock an undici request with a defined reply. + */ + reply(replyData) { + if (typeof replyData === "function") { + const wrappedDefaultsCallback = (opts) => { + const resolvedData = replyData(opts); + if (typeof resolvedData !== "object") { + throw new InvalidArgumentError("reply options callback must return an object"); + } + const { statusCode: statusCode2, data: data2 = "", responseOptions: responseOptions2 = {} } = resolvedData; + this.validateReplyParameters(statusCode2, data2, responseOptions2); + return { + ...this.createMockScopeDispatchData(statusCode2, data2, responseOptions2) + }; + }; + const newMockDispatch2 = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback); + return new MockScope(newMockDispatch2); + } + const [statusCode, data = "", responseOptions = {}] = [...arguments]; + this.validateReplyParameters(statusCode, data, responseOptions); + const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions); + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData); + return new MockScope(newMockDispatch); + } + /** + * Mock an undici request with a defined error. + */ + replyWithError(error) { + if (typeof error === "undefined") { + throw new InvalidArgumentError("error must be defined"); + } + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }); + return new MockScope(newMockDispatch); + } + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders(headers) { + if (typeof headers === "undefined") { + throw new InvalidArgumentError("headers must be defined"); + } + this[kDefaultHeaders] = headers; + return this; + } + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers(trailers) { + if (typeof trailers === "undefined") { + throw new InvalidArgumentError("trailers must be defined"); + } + this[kDefaultTrailers] = trailers; + return this; + } + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength() { + this[kContentLength] = true; + return this; + } + }; + module2.exports.MockInterceptor = MockInterceptor; + module2.exports.MockScope = MockScope; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-client.js +var require_mock_client = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-client.js"(exports2, module2) { + "use strict"; + var { promisify: promisify3 } = require("util"); + var Client = require_client(); + var { buildMockDispatch } = require_mock_utils(); + var { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected + } = require_mock_symbols(); + var { MockInterceptor } = require_mock_interceptor(); + var Symbols = require_symbols(); + var { InvalidArgumentError } = require_errors(); + var MockClient = class extends Client { + constructor(origin, opts) { + super(origin, opts); + if (!opts || !opts.agent || typeof opts.agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument opts.agent must implement Agent"); + } + this[kMockAgent] = opts.agent; + this[kOrigin] = origin; + this[kDispatches] = []; + this[kConnected] = 1; + this[kOriginalDispatch] = this.dispatch; + this[kOriginalClose] = this.close.bind(this); + this.dispatch = buildMockDispatch.call(this); + this.close = this[kClose]; + } + get [Symbols.kConnected]() { + return this[kConnected]; + } + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept(opts) { + return new MockInterceptor(opts, this[kDispatches]); + } + async [kClose]() { + await promisify3(this[kOriginalClose])(); + this[kConnected] = 0; + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]); + } + }; + module2.exports = MockClient; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-pool.js +var require_mock_pool = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-pool.js"(exports2, module2) { + "use strict"; + var { promisify: promisify3 } = require("util"); + var Pool = require_pool(); + var { buildMockDispatch } = require_mock_utils(); + var { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected + } = require_mock_symbols(); + var { MockInterceptor } = require_mock_interceptor(); + var Symbols = require_symbols(); + var { InvalidArgumentError } = require_errors(); + var MockPool = class extends Pool { + constructor(origin, opts) { + super(origin, opts); + if (!opts || !opts.agent || typeof opts.agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument opts.agent must implement Agent"); + } + this[kMockAgent] = opts.agent; + this[kOrigin] = origin; + this[kDispatches] = []; + this[kConnected] = 1; + this[kOriginalDispatch] = this.dispatch; + this[kOriginalClose] = this.close.bind(this); + this.dispatch = buildMockDispatch.call(this); + this.close = this[kClose]; + } + get [Symbols.kConnected]() { + return this[kConnected]; + } + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept(opts) { + return new MockInterceptor(opts, this[kDispatches]); + } + async [kClose]() { + await promisify3(this[kOriginalClose])(); + this[kConnected] = 0; + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]); + } + }; + module2.exports = MockPool; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/pluralizer.js +var require_pluralizer = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/pluralizer.js"(exports2, module2) { + "use strict"; + var singulars = { + pronoun: "it", + is: "is", + was: "was", + this: "this" + }; + var plurals = { + pronoun: "they", + is: "are", + was: "were", + this: "these" + }; + module2.exports = class Pluralizer { + constructor(singular, plural) { + this.singular = singular; + this.plural = plural; + } + pluralize(count2) { + const one = count2 === 1; + const keys = one ? singulars : plurals; + const noun = one ? this.singular : this.plural; + return { ...keys, count: count2, noun }; + } + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/pending-interceptors-formatter.js +var require_pending_interceptors_formatter = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/pending-interceptors-formatter.js"(exports2, module2) { + "use strict"; + var { Transform: Transform2 } = require("stream"); + var { Console } = require("console"); + module2.exports = class PendingInterceptorsFormatter { + constructor({ disableColors } = {}) { + this.transform = new Transform2({ + transform(chunk, _enc, cb) { + cb(null, chunk); + } + }); + this.logger = new Console({ + stdout: this.transform, + inspectOptions: { + colors: !disableColors && !process.env.CI + } + }); + } + format(pendingInterceptors) { + const withPrettyHeaders = pendingInterceptors.map( + ({ method, path: path12, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + Method: method, + Origin: origin, + Path: path12, + "Status code": statusCode, + Persistent: persist ? "\u2705" : "\u274C", + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + }) + ); + this.logger.table(withPrettyHeaders); + return this.transform.read().toString(); + } + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-agent.js +var require_mock_agent = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/mock/mock-agent.js"(exports2, module2) { + "use strict"; + var { kClients } = require_symbols(); + var Agent = require_agent(); + var { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory + } = require_mock_symbols(); + var MockClient = require_mock_client(); + var MockPool = require_mock_pool(); + var { matchValue, buildMockOptions } = require_mock_utils(); + var { InvalidArgumentError, UndiciError } = require_errors(); + var Dispatcher = require_dispatcher(); + var Pluralizer = require_pluralizer(); + var PendingInterceptorsFormatter = require_pending_interceptors_formatter(); + var FakeWeakRef = class { + constructor(value) { + this.value = value; + } + deref() { + return this.value; + } + }; + var MockAgent = class extends Dispatcher { + constructor(opts) { + super(opts); + this[kNetConnect] = true; + this[kIsMockActive] = true; + if (opts && opts.agent && typeof opts.agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument opts.agent must implement Agent"); + } + const agent = opts && opts.agent ? opts.agent : new Agent(opts); + this[kAgent] = agent; + this[kClients] = agent[kClients]; + this[kOptions] = buildMockOptions(opts); + } + get(origin) { + let dispatcher = this[kMockAgentGet](origin); + if (!dispatcher) { + dispatcher = this[kFactory](origin); + this[kMockAgentSet](origin, dispatcher); + } + return dispatcher; + } + dispatch(opts, handler) { + this.get(opts.origin); + return this[kAgent].dispatch(opts, handler); + } + async close() { + await this[kAgent].close(); + this[kClients].clear(); + } + deactivate() { + this[kIsMockActive] = false; + } + activate() { + this[kIsMockActive] = true; + } + enableNetConnect(matcher) { + if (typeof matcher === "string" || typeof matcher === "function" || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher); + } else { + this[kNetConnect] = [matcher]; + } + } else if (typeof matcher === "undefined") { + this[kNetConnect] = true; + } else { + throw new InvalidArgumentError("Unsupported matcher. Must be one of String|Function|RegExp."); + } + } + disableNetConnect() { + this[kNetConnect] = false; + } + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive() { + return this[kIsMockActive]; + } + [kMockAgentSet](origin, dispatcher) { + this[kClients].set(origin, new FakeWeakRef(dispatcher)); + } + [kFactory](origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]); + return this[kOptions] && this[kOptions].connections === 1 ? new MockClient(origin, mockOptions) : new MockPool(origin, mockOptions); + } + [kMockAgentGet](origin) { + const ref = this[kClients].get(origin); + if (ref) { + return ref.deref(); + } + if (typeof origin !== "string") { + const dispatcher = this[kFactory]("http://localhost:9999"); + this[kMockAgentSet](origin, dispatcher); + return dispatcher; + } + for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { + const nonExplicitDispatcher = nonExplicitRef.deref(); + if (nonExplicitDispatcher && typeof keyMatcher !== "string" && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin); + this[kMockAgentSet](origin, dispatcher); + dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches]; + return dispatcher; + } + } + } + [kGetNetConnect]() { + return this[kNetConnect]; + } + pendingInterceptors() { + const mockAgentClients = this[kClients]; + return Array.from(mockAgentClients.entries()).flatMap(([origin, scope]) => scope.deref()[kDispatches].map((dispatch) => ({ ...dispatch, origin }))).filter(({ pending }) => pending); + } + assertNoPendingInterceptors({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors(); + if (pending.length === 0) { + return; + } + const pluralizer = new Pluralizer("interceptor", "interceptors").pluralize(pending.length); + throw new UndiciError(` +${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: + +${pendingInterceptorsFormatter.format(pending)} +`.trim()); + } + }; + module2.exports = MockAgent; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/proxy-agent.js +var require_proxy_agent = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/proxy-agent.js"(exports2, module2) { + "use strict"; + var { kProxy, kClose, kDestroy, kInterceptors } = require_symbols(); + var { URL: URL2 } = require("url"); + var Agent = require_agent(); + var Pool = require_pool(); + var DispatcherBase = require_dispatcher_base(); + var { InvalidArgumentError, RequestAbortedError } = require_errors(); + var buildConnector = require_connect(); + var kAgent = /* @__PURE__ */ Symbol("proxy agent"); + var kClient = /* @__PURE__ */ Symbol("proxy client"); + var kProxyHeaders = /* @__PURE__ */ Symbol("proxy headers"); + var kRequestTls = /* @__PURE__ */ Symbol("request tls settings"); + var kProxyTls = /* @__PURE__ */ Symbol("proxy tls settings"); + var kConnectEndpoint = /* @__PURE__ */ Symbol("connect endpoint function"); + function defaultProtocolPort(protocol) { + return protocol === "https:" ? 443 : 80; + } + function buildProxyOptions(opts) { + if (typeof opts === "string") { + opts = { uri: opts }; + } + if (!opts || !opts.uri) { + throw new InvalidArgumentError("Proxy opts.uri is mandatory"); + } + return { + uri: opts.uri, + protocol: opts.protocol || "https" + }; + } + function defaultFactory(origin, opts) { + return new Pool(origin, opts); + } + var ProxyAgent = class extends DispatcherBase { + constructor(opts) { + super(opts); + this[kProxy] = buildProxyOptions(opts); + this[kAgent] = new Agent(opts); + this[kInterceptors] = opts.interceptors && opts.interceptors.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) ? opts.interceptors.ProxyAgent : []; + if (typeof opts === "string") { + opts = { uri: opts }; + } + if (!opts || !opts.uri) { + throw new InvalidArgumentError("Proxy opts.uri is mandatory"); + } + const { clientFactory = defaultFactory } = opts; + if (typeof clientFactory !== "function") { + throw new InvalidArgumentError("Proxy opts.clientFactory must be a function."); + } + this[kRequestTls] = opts.requestTls; + this[kProxyTls] = opts.proxyTls; + this[kProxyHeaders] = opts.headers || {}; + const resolvedUrl = new URL2(opts.uri); + const { origin, port, host, username, password } = resolvedUrl; + if (opts.auth && opts.token) { + throw new InvalidArgumentError("opts.auth cannot be used in combination with opts.token"); + } else if (opts.auth) { + this[kProxyHeaders]["proxy-authorization"] = `Basic ${opts.auth}`; + } else if (opts.token) { + this[kProxyHeaders]["proxy-authorization"] = opts.token; + } else if (username && password) { + this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString("base64")}`; + } + const connect = buildConnector({ ...opts.proxyTls }); + this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }); + this[kClient] = clientFactory(resolvedUrl, { connect }); + this[kAgent] = new Agent({ + ...opts, + connect: async (opts2, callback) => { + let requestedHost = opts2.host; + if (!opts2.port) { + requestedHost += `:${defaultProtocolPort(opts2.protocol)}`; + } + try { + const { socket, statusCode } = await this[kClient].connect({ + origin, + port, + path: requestedHost, + signal: opts2.signal, + headers: { + ...this[kProxyHeaders], + host + } + }); + if (statusCode !== 200) { + socket.on("error", () => { + }).destroy(); + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)); + } + if (opts2.protocol !== "https:") { + callback(null, socket); + return; + } + let servername; + if (this[kRequestTls]) { + servername = this[kRequestTls].servername; + } else { + servername = opts2.servername; + } + this[kConnectEndpoint]({ ...opts2, servername, httpSocket: socket }, callback); + } catch (err) { + callback(err); + } + } + }); + } + dispatch(opts, handler) { + const { host } = new URL2(opts.origin); + const headers = buildHeaders(opts.headers); + throwIfProxyAuthIsSent(headers); + return this[kAgent].dispatch( + { + ...opts, + headers: { + ...headers, + host + } + }, + handler + ); + } + async [kClose]() { + await this[kAgent].close(); + await this[kClient].close(); + } + async [kDestroy]() { + await this[kAgent].destroy(); + await this[kClient].destroy(); + } + }; + function buildHeaders(headers) { + if (Array.isArray(headers)) { + const headersPair = {}; + for (let i2 = 0; i2 < headers.length; i2 += 2) { + headersPair[headers[i2]] = headers[i2 + 1]; + } + return headersPair; + } + return headers; + } + function throwIfProxyAuthIsSent(headers) { + const existProxyAuth = headers && Object.keys(headers).find((key) => key.toLowerCase() === "proxy-authorization"); + if (existProxyAuth) { + throw new InvalidArgumentError("Proxy-Authorization should be sent in ProxyAgent constructor"); + } + } + module2.exports = ProxyAgent; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/handler/RetryHandler.js +var require_RetryHandler = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/handler/RetryHandler.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var { kRetryHandlerDefaultRetry } = require_symbols(); + var { RequestRetryError } = require_errors(); + var { isDisturbed, parseHeaders, parseRangeHeader } = require_util(); + function calculateRetryAfterHeader(retryAfter) { + const current = Date.now(); + const diff = new Date(retryAfter).getTime() - current; + return diff; + } + var RetryHandler = class _RetryHandler { + constructor(opts, handlers) { + const { retryOptions, ...dispatchOpts } = opts; + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes + } = retryOptions ?? {}; + this.dispatch = handlers.dispatch; + this.handler = handlers.handler; + this.opts = dispatchOpts; + this.abort = null; + this.aborted = false; + this.retryOpts = { + retry: retryFn ?? _RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1e3, + // 30s, + timeout: minTimeout ?? 500, + // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ["GET", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + "ECONNRESET", + "ECONNREFUSED", + "ENOTFOUND", + "ENETDOWN", + "ENETUNREACH", + "EHOSTDOWN", + "EHOSTUNREACH", + "EPIPE" + ] + }; + this.retryCount = 0; + this.start = 0; + this.end = null; + this.etag = null; + this.resume = null; + this.handler.onConnect((reason) => { + this.aborted = true; + if (this.abort) { + this.abort(reason); + } else { + this.reason = reason; + } + }); + } + onRequestSent() { + if (this.handler.onRequestSent) { + this.handler.onRequestSent(); + } + } + onUpgrade(statusCode, headers, socket) { + if (this.handler.onUpgrade) { + this.handler.onUpgrade(statusCode, headers, socket); + } + } + onConnect(abort) { + if (this.aborted) { + abort(this.reason); + } else { + this.abort = abort; + } + } + onBodySent(chunk) { + if (this.handler.onBodySent) return this.handler.onBodySent(chunk); + } + static [kRetryHandlerDefaultRetry](err, { state, opts }, cb) { + const { statusCode, code: code2, headers } = err; + const { method, retryOptions } = opts; + const { + maxRetries, + timeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions; + let { counter, currentTimeout } = state; + currentTimeout = currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout; + if (code2 && code2 !== "UND_ERR_REQ_RETRY" && code2 !== "UND_ERR_SOCKET" && !errorCodes.includes(code2)) { + cb(err); + return; + } + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err); + return; + } + if (statusCode != null && Array.isArray(statusCodes) && !statusCodes.includes(statusCode)) { + cb(err); + return; + } + if (counter > maxRetries) { + cb(err); + return; + } + let retryAfterHeader = headers != null && headers["retry-after"]; + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader); + retryAfterHeader = isNaN(retryAfterHeader) ? calculateRetryAfterHeader(retryAfterHeader) : retryAfterHeader * 1e3; + } + const retryTimeout = retryAfterHeader > 0 ? Math.min(retryAfterHeader, maxTimeout) : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout); + state.currentTimeout = retryTimeout; + setTimeout(() => cb(null), retryTimeout); + } + onHeaders(statusCode, rawHeaders, resume, statusMessage) { + const headers = parseHeaders(rawHeaders); + this.retryCount += 1; + if (statusCode >= 300) { + this.abort( + new RequestRetryError("Request failed", statusCode, { + headers, + count: this.retryCount + }) + ); + return false; + } + if (this.resume != null) { + this.resume = null; + if (statusCode !== 206) { + return true; + } + const contentRange = parseRangeHeader(headers["content-range"]); + if (!contentRange) { + this.abort( + new RequestRetryError("Content-Range mismatch", statusCode, { + headers, + count: this.retryCount + }) + ); + return false; + } + if (this.etag != null && this.etag !== headers.etag) { + this.abort( + new RequestRetryError("ETag mismatch", statusCode, { + headers, + count: this.retryCount + }) + ); + return false; + } + const { start, size, end = size } = contentRange; + assert(this.start === start, "content-range mismatch"); + assert(this.end == null || this.end === end, "content-range mismatch"); + this.resume = resume; + return true; + } + if (this.end == null) { + if (statusCode === 206) { + const range = parseRangeHeader(headers["content-range"]); + if (range == null) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ); + } + const { start, size, end = size } = range; + assert( + start != null && Number.isFinite(start) && this.start !== start, + "content-range mismatch" + ); + assert(Number.isFinite(start)); + assert( + end != null && Number.isFinite(end) && this.end !== end, + "invalid content-length" + ); + this.start = start; + this.end = end; + } + if (this.end == null) { + const contentLength = headers["content-length"]; + this.end = contentLength != null ? Number(contentLength) : null; + } + assert(Number.isFinite(this.start)); + assert( + this.end == null || Number.isFinite(this.end), + "invalid content-length" + ); + this.resume = resume; + this.etag = headers.etag != null ? headers.etag : null; + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ); + } + const err = new RequestRetryError("Request failed", statusCode, { + headers, + count: this.retryCount + }); + this.abort(err); + return false; + } + onData(chunk) { + this.start += chunk.length; + return this.handler.onData(chunk); + } + onComplete(rawTrailers) { + this.retryCount = 0; + return this.handler.onComplete(rawTrailers); + } + onError(err) { + if (this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err); + } + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount++, currentTimeout: this.retryAfter }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + onRetry.bind(this) + ); + function onRetry(err2) { + if (err2 != null || this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err2); + } + if (this.start !== 0) { + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + range: `bytes=${this.start}-${this.end ?? ""}` + } + }; + } + try { + this.dispatch(this.opts, this); + } catch (err3) { + this.handler.onError(err3); + } + } + } + }; + module2.exports = RetryHandler; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/global.js +var require_global2 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/global.js"(exports2, module2) { + "use strict"; + var globalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1"); + var { InvalidArgumentError } = require_errors(); + var Agent = require_agent(); + if (getGlobalDispatcher() === void 0) { + setGlobalDispatcher(new Agent()); + } + function setGlobalDispatcher(agent) { + if (!agent || typeof agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument agent must implement Agent"); + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }); + } + function getGlobalDispatcher() { + return globalThis[globalDispatcher]; + } + module2.exports = { + setGlobalDispatcher, + getGlobalDispatcher + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/handler/DecoratorHandler.js +var require_DecoratorHandler = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/handler/DecoratorHandler.js"(exports2, module2) { + "use strict"; + module2.exports = class DecoratorHandler { + constructor(handler) { + this.handler = handler; + } + onConnect(...args) { + return this.handler.onConnect(...args); + } + onError(...args) { + return this.handler.onError(...args); + } + onUpgrade(...args) { + return this.handler.onUpgrade(...args); + } + onHeaders(...args) { + return this.handler.onHeaders(...args); + } + onData(...args) { + return this.handler.onData(...args); + } + onComplete(...args) { + return this.handler.onComplete(...args); + } + onBodySent(...args) { + return this.handler.onBodySent(...args); + } + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/headers.js +var require_headers = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/headers.js"(exports2, module2) { + "use strict"; + var { kHeadersList, kConstruct } = require_symbols(); + var { kGuard } = require_symbols2(); + var { kEnumerableProperty } = require_util(); + var { + makeIterator, + isValidHeaderName, + isValidHeaderValue + } = require_util2(); + var util2 = require("util"); + var { webidl } = require_webidl(); + var assert = require("assert"); + var kHeadersMap = /* @__PURE__ */ Symbol("headers map"); + var kHeadersSortedMap = /* @__PURE__ */ Symbol("headers map sorted"); + function isHTTPWhiteSpaceCharCode(code2) { + return code2 === 10 || code2 === 13 || code2 === 9 || code2 === 32; + } + function headerValueNormalize(potentialValue) { + let i2 = 0; + let j = potentialValue.length; + while (j > i2 && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j; + while (j > i2 && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i2))) ++i2; + return i2 === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i2, j); + } + function fill(headers, object) { + if (Array.isArray(object)) { + for (let i2 = 0; i2 < object.length; ++i2) { + const header = object[i2]; + if (header.length !== 2) { + throw webidl.errors.exception({ + header: "Headers constructor", + message: `expected name/value pair to be length 2, found ${header.length}.` + }); + } + appendHeader(headers, header[0], header[1]); + } + } else if (typeof object === "object" && object !== null) { + const keys = Object.keys(object); + for (let i2 = 0; i2 < keys.length; ++i2) { + appendHeader(headers, keys[i2], object[keys[i2]]); + } + } else { + throw webidl.errors.conversionFailed({ + prefix: "Headers constructor", + argument: "Argument 1", + types: ["sequence>", "record"] + }); + } + } + function appendHeader(headers, name, value) { + value = headerValueNormalize(value); + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.append", + value: name, + type: "header name" + }); + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.append", + value, + type: "header value" + }); + } + if (headers[kGuard] === "immutable") { + throw new TypeError("immutable"); + } else if (headers[kGuard] === "request-no-cors") { + } + return headers[kHeadersList].append(name, value); + } + var HeadersList = class _HeadersList { + /** @type {[string, string][]|null} */ + cookies = null; + constructor(init) { + if (init instanceof _HeadersList) { + this[kHeadersMap] = new Map(init[kHeadersMap]); + this[kHeadersSortedMap] = init[kHeadersSortedMap]; + this.cookies = init.cookies === null ? null : [...init.cookies]; + } else { + this[kHeadersMap] = new Map(init); + this[kHeadersSortedMap] = null; + } + } + // https://fetch.spec.whatwg.org/#header-list-contains + contains(name) { + name = name.toLowerCase(); + return this[kHeadersMap].has(name); + } + clear() { + this[kHeadersMap].clear(); + this[kHeadersSortedMap] = null; + this.cookies = null; + } + // https://fetch.spec.whatwg.org/#concept-header-list-append + append(name, value) { + this[kHeadersSortedMap] = null; + const lowercaseName = name.toLowerCase(); + const exists = this[kHeadersMap].get(lowercaseName); + if (exists) { + const delimiter = lowercaseName === "cookie" ? "; " : ", "; + this[kHeadersMap].set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value}` + }); + } else { + this[kHeadersMap].set(lowercaseName, { name, value }); + } + if (lowercaseName === "set-cookie") { + this.cookies ??= []; + this.cookies.push(value); + } + } + // https://fetch.spec.whatwg.org/#concept-header-list-set + set(name, value) { + this[kHeadersSortedMap] = null; + const lowercaseName = name.toLowerCase(); + if (lowercaseName === "set-cookie") { + this.cookies = [value]; + } + this[kHeadersMap].set(lowercaseName, { name, value }); + } + // https://fetch.spec.whatwg.org/#concept-header-list-delete + delete(name) { + this[kHeadersSortedMap] = null; + name = name.toLowerCase(); + if (name === "set-cookie") { + this.cookies = null; + } + this[kHeadersMap].delete(name); + } + // https://fetch.spec.whatwg.org/#concept-header-list-get + get(name) { + const value = this[kHeadersMap].get(name.toLowerCase()); + return value === void 0 ? null : value.value; + } + *[Symbol.iterator]() { + for (const [name, { value }] of this[kHeadersMap]) { + yield [name, value]; + } + } + get entries() { + const headers = {}; + if (this[kHeadersMap].size) { + for (const { name, value } of this[kHeadersMap].values()) { + headers[name] = value; + } + } + return headers; + } + }; + var Headers = class _Headers { + constructor(init = void 0) { + if (init === kConstruct) { + return; + } + this[kHeadersList] = new HeadersList(); + this[kGuard] = "none"; + if (init !== void 0) { + init = webidl.converters.HeadersInit(init); + fill(this, init); + } + } + // https://fetch.spec.whatwg.org/#dom-headers-append + append(name, value) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 2, { header: "Headers.append" }); + name = webidl.converters.ByteString(name); + value = webidl.converters.ByteString(value); + return appendHeader(this, name, value); + } + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete(name) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, { header: "Headers.delete" }); + name = webidl.converters.ByteString(name); + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.delete", + value: name, + type: "header name" + }); + } + if (this[kGuard] === "immutable") { + throw new TypeError("immutable"); + } else if (this[kGuard] === "request-no-cors") { + } + if (!this[kHeadersList].contains(name)) { + return; + } + this[kHeadersList].delete(name); + } + // https://fetch.spec.whatwg.org/#dom-headers-get + get(name) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, { header: "Headers.get" }); + name = webidl.converters.ByteString(name); + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.get", + value: name, + type: "header name" + }); + } + return this[kHeadersList].get(name); + } + // https://fetch.spec.whatwg.org/#dom-headers-has + has(name) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, { header: "Headers.has" }); + name = webidl.converters.ByteString(name); + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.has", + value: name, + type: "header name" + }); + } + return this[kHeadersList].contains(name); + } + // https://fetch.spec.whatwg.org/#dom-headers-set + set(name, value) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 2, { header: "Headers.set" }); + name = webidl.converters.ByteString(name); + value = webidl.converters.ByteString(value); + value = headerValueNormalize(value); + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.set", + value: name, + type: "header name" + }); + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.set", + value, + type: "header value" + }); + } + if (this[kGuard] === "immutable") { + throw new TypeError("immutable"); + } else if (this[kGuard] === "request-no-cors") { + } + this[kHeadersList].set(name, value); + } + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie() { + webidl.brandCheck(this, _Headers); + const list = this[kHeadersList].cookies; + if (list) { + return [...list]; + } + return []; + } + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + get [kHeadersSortedMap]() { + if (this[kHeadersList][kHeadersSortedMap]) { + return this[kHeadersList][kHeadersSortedMap]; + } + const headers = []; + const names = [...this[kHeadersList]].sort((a2, b) => a2[0] < b[0] ? -1 : 1); + const cookies = this[kHeadersList].cookies; + for (let i2 = 0; i2 < names.length; ++i2) { + const [name, value] = names[i2]; + if (name === "set-cookie") { + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]); + } + } else { + assert(value !== null); + headers.push([name, value]); + } + } + this[kHeadersList][kHeadersSortedMap] = headers; + return headers; + } + keys() { + webidl.brandCheck(this, _Headers); + if (this[kGuard] === "immutable") { + const value = this[kHeadersSortedMap]; + return makeIterator( + () => value, + "Headers", + "key" + ); + } + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + "Headers", + "key" + ); + } + values() { + webidl.brandCheck(this, _Headers); + if (this[kGuard] === "immutable") { + const value = this[kHeadersSortedMap]; + return makeIterator( + () => value, + "Headers", + "value" + ); + } + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + "Headers", + "value" + ); + } + entries() { + webidl.brandCheck(this, _Headers); + if (this[kGuard] === "immutable") { + const value = this[kHeadersSortedMap]; + return makeIterator( + () => value, + "Headers", + "key+value" + ); + } + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + "Headers", + "key+value" + ); + } + /** + * @param {(value: string, key: string, self: Headers) => void} callbackFn + * @param {unknown} thisArg + */ + forEach(callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, { header: "Headers.forEach" }); + if (typeof callbackFn !== "function") { + throw new TypeError( + "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." + ); + } + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]); + } + } + [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() { + webidl.brandCheck(this, _Headers); + return this[kHeadersList]; + } + }; + Headers.prototype[Symbol.iterator] = Headers.prototype.entries; + Object.defineProperties(Headers.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, + keys: kEnumerableProperty, + values: kEnumerableProperty, + entries: kEnumerableProperty, + forEach: kEnumerableProperty, + [Symbol.iterator]: { enumerable: false }, + [Symbol.toStringTag]: { + value: "Headers", + configurable: true + }, + [util2.inspect.custom]: { + enumerable: false + } + }); + webidl.converters.HeadersInit = function(V) { + if (webidl.util.Type(V) === "Object") { + if (V[Symbol.iterator]) { + return webidl.converters["sequence>"](V); + } + return webidl.converters["record"](V); + } + throw webidl.errors.conversionFailed({ + prefix: "Headers constructor", + argument: "Argument 1", + types: ["sequence>", "record"] + }); + }; + module2.exports = { + fill, + Headers, + HeadersList + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/response.js +var require_response = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/response.js"(exports2, module2) { + "use strict"; + var { Headers, HeadersList, fill } = require_headers(); + var { extractBody, cloneBody, mixinBody } = require_body(); + var util2 = require_util(); + var { kEnumerableProperty } = util2; + var { + isValidReasonPhrase, + isCancelled, + isAborted: isAborted2, + isBlobLike, + serializeJavascriptValueToJSONString, + isErrorLike, + isomorphicEncode + } = require_util2(); + var { + redirectStatusSet, + nullBodyStatus, + DOMException: DOMException2 + } = require_constants2(); + var { kState, kHeaders, kGuard, kRealm } = require_symbols2(); + var { webidl } = require_webidl(); + var { FormData } = require_formdata(); + var { getGlobalOrigin } = require_global(); + var { URLSerializer } = require_dataURL(); + var { kHeadersList, kConstruct } = require_symbols(); + var assert = require("assert"); + var { types } = require("util"); + var ReadableStream2 = globalThis.ReadableStream || require("stream/web").ReadableStream; + var textEncoder3 = new TextEncoder("utf-8"); + var Response = class _Response { + // Creates network error Response. + static error() { + const relevantRealm = { settingsObject: {} }; + const responseObject = new _Response(); + responseObject[kState] = makeNetworkError(); + responseObject[kRealm] = relevantRealm; + responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList; + responseObject[kHeaders][kGuard] = "immutable"; + responseObject[kHeaders][kRealm] = relevantRealm; + return responseObject; + } + // https://fetch.spec.whatwg.org/#dom-response-json + static json(data, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: "Response.json" }); + if (init !== null) { + init = webidl.converters.ResponseInit(init); + } + const bytes = textEncoder3.encode( + serializeJavascriptValueToJSONString(data) + ); + const body = extractBody(bytes); + const relevantRealm = { settingsObject: {} }; + const responseObject = new _Response(); + responseObject[kRealm] = relevantRealm; + responseObject[kHeaders][kGuard] = "response"; + responseObject[kHeaders][kRealm] = relevantRealm; + initializeResponse(responseObject, init, { body: body[0], type: "application/json" }); + return responseObject; + } + // Creates a redirect Response that redirects to url with status status. + static redirect(url, status = 302) { + const relevantRealm = { settingsObject: {} }; + webidl.argumentLengthCheck(arguments, 1, { header: "Response.redirect" }); + url = webidl.converters.USVString(url); + status = webidl.converters["unsigned short"](status); + let parsedURL; + try { + parsedURL = new URL(url, getGlobalOrigin()); + } catch (err) { + throw Object.assign(new TypeError("Failed to parse URL from " + url), { + cause: err + }); + } + if (!redirectStatusSet.has(status)) { + throw new RangeError("Invalid status code " + status); + } + const responseObject = new _Response(); + responseObject[kRealm] = relevantRealm; + responseObject[kHeaders][kGuard] = "immutable"; + responseObject[kHeaders][kRealm] = relevantRealm; + responseObject[kState].status = status; + const value = isomorphicEncode(URLSerializer(parsedURL)); + responseObject[kState].headersList.append("location", value); + return responseObject; + } + // https://fetch.spec.whatwg.org/#dom-response + constructor(body = null, init = {}) { + if (body !== null) { + body = webidl.converters.BodyInit(body); + } + init = webidl.converters.ResponseInit(init); + this[kRealm] = { settingsObject: {} }; + this[kState] = makeResponse({}); + this[kHeaders] = new Headers(kConstruct); + this[kHeaders][kGuard] = "response"; + this[kHeaders][kHeadersList] = this[kState].headersList; + this[kHeaders][kRealm] = this[kRealm]; + let bodyWithType = null; + if (body != null) { + const [extractedBody, type] = extractBody(body); + bodyWithType = { body: extractedBody, type }; + } + initializeResponse(this, init, bodyWithType); + } + // Returns response’s type, e.g., "cors". + get type() { + webidl.brandCheck(this, _Response); + return this[kState].type; + } + // Returns response’s URL, if it has one; otherwise the empty string. + get url() { + webidl.brandCheck(this, _Response); + const urlList = this[kState].urlList; + const url = urlList[urlList.length - 1] ?? null; + if (url === null) { + return ""; + } + return URLSerializer(url, true); + } + // Returns whether response was obtained through a redirect. + get redirected() { + webidl.brandCheck(this, _Response); + return this[kState].urlList.length > 1; + } + // Returns response’s status. + get status() { + webidl.brandCheck(this, _Response); + return this[kState].status; + } + // Returns whether response’s status is an ok status. + get ok() { + webidl.brandCheck(this, _Response); + return this[kState].status >= 200 && this[kState].status <= 299; + } + // Returns response’s status message. + get statusText() { + webidl.brandCheck(this, _Response); + return this[kState].statusText; + } + // Returns response’s headers as Headers. + get headers() { + webidl.brandCheck(this, _Response); + return this[kHeaders]; + } + get body() { + webidl.brandCheck(this, _Response); + return this[kState].body ? this[kState].body.stream : null; + } + get bodyUsed() { + webidl.brandCheck(this, _Response); + return !!this[kState].body && util2.isDisturbed(this[kState].body.stream); + } + // Returns a clone of response. + clone() { + webidl.brandCheck(this, _Response); + if (this.bodyUsed || this.body && this.body.locked) { + throw webidl.errors.exception({ + header: "Response.clone", + message: "Body has already been consumed." + }); + } + const clonedResponse = cloneResponse(this[kState]); + const clonedResponseObject = new _Response(); + clonedResponseObject[kState] = clonedResponse; + clonedResponseObject[kRealm] = this[kRealm]; + clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList; + clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard]; + clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm]; + return clonedResponseObject; + } + }; + mixinBody(Response); + Object.defineProperties(Response.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "Response", + configurable: true + } + }); + Object.defineProperties(Response, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty + }); + function cloneResponse(response) { + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ); + } + const newResponse = makeResponse({ ...response, body: null }); + if (response.body != null) { + newResponse.body = cloneBody(response.body); + } + return newResponse; + } + function makeResponse(init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: "default", + status: 200, + timingInfo: null, + cacheState: "", + statusText: "", + ...init, + headersList: init.headersList ? new HeadersList(init.headersList) : new HeadersList(), + urlList: init.urlList ? [...init.urlList] : [] + }; + } + function makeNetworkError(reason) { + const isError = isErrorLike(reason); + return makeResponse({ + type: "error", + status: 0, + error: isError ? reason : new Error(reason ? String(reason) : reason), + aborted: reason && reason.name === "AbortError" + }); + } + function makeFilteredResponse(response, state) { + state = { + internalResponse: response, + ...state + }; + return new Proxy(response, { + get(target, p) { + return p in state ? state[p] : target[p]; + }, + set(target, p, value) { + assert(!(p in state)); + target[p] = value; + return true; + } + }); + } + function filterResponse(response, type) { + if (type === "basic") { + return makeFilteredResponse(response, { + type: "basic", + headersList: response.headersList + }); + } else if (type === "cors") { + return makeFilteredResponse(response, { + type: "cors", + headersList: response.headersList + }); + } else if (type === "opaque") { + return makeFilteredResponse(response, { + type: "opaque", + urlList: Object.freeze([]), + status: 0, + statusText: "", + body: null + }); + } else if (type === "opaqueredirect") { + return makeFilteredResponse(response, { + type: "opaqueredirect", + status: 0, + statusText: "", + headersList: [], + body: null + }); + } else { + assert(false); + } + } + function makeAppropriateNetworkError(fetchParams, err = null) { + assert(isCancelled(fetchParams)); + return isAborted2(fetchParams) ? makeNetworkError(Object.assign(new DOMException2("The operation was aborted.", "AbortError"), { cause: err })) : makeNetworkError(Object.assign(new DOMException2("Request was cancelled."), { cause: err })); + } + function initializeResponse(response, init, body) { + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.'); + } + if ("statusText" in init && init.statusText != null) { + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError("Invalid statusText"); + } + } + if ("status" in init && init.status != null) { + response[kState].status = init.status; + } + if ("statusText" in init && init.statusText != null) { + response[kState].statusText = init.statusText; + } + if ("headers" in init && init.headers != null) { + fill(response[kHeaders], init.headers); + } + if (body) { + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: "Response constructor", + message: "Invalid response status code " + response.status + }); + } + response[kState].body = body.body; + if (body.type != null && !response[kState].headersList.contains("Content-Type")) { + response[kState].headersList.append("content-type", body.type); + } + } + } + webidl.converters.ReadableStream = webidl.interfaceConverter( + ReadableStream2 + ); + webidl.converters.FormData = webidl.interfaceConverter( + FormData + ); + webidl.converters.URLSearchParams = webidl.interfaceConverter( + URLSearchParams + ); + webidl.converters.XMLHttpRequestBodyInit = function(V) { + if (typeof V === "string") { + return webidl.converters.USVString(V); + } + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }); + } + if (types.isArrayBuffer(V) || types.isTypedArray(V) || types.isDataView(V)) { + return webidl.converters.BufferSource(V); + } + if (util2.isFormDataLike(V)) { + return webidl.converters.FormData(V, { strict: false }); + } + if (V instanceof URLSearchParams) { + return webidl.converters.URLSearchParams(V); + } + return webidl.converters.DOMString(V); + }; + webidl.converters.BodyInit = function(V) { + if (V instanceof ReadableStream2) { + return webidl.converters.ReadableStream(V); + } + if (V?.[Symbol.asyncIterator]) { + return V; + } + return webidl.converters.XMLHttpRequestBodyInit(V); + }; + webidl.converters.ResponseInit = webidl.dictionaryConverter([ + { + key: "status", + converter: webidl.converters["unsigned short"], + defaultValue: 200 + }, + { + key: "statusText", + converter: webidl.converters.ByteString, + defaultValue: "" + }, + { + key: "headers", + converter: webidl.converters.HeadersInit + } + ]); + module2.exports = { + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response, + cloneResponse + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/request.js +var require_request2 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/request.js"(exports2, module2) { + "use strict"; + var { extractBody, mixinBody, cloneBody } = require_body(); + var { Headers, fill: fillHeaders, HeadersList } = require_headers(); + var { FinalizationRegistry } = require_dispatcher_weakref()(); + var util2 = require_util(); + var { + isValidHTTPToken, + sameOrigin, + normalizeMethod, + makePolicyContainer, + normalizeMethodRecord + } = require_util2(); + var { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex + } = require_constants2(); + var { kEnumerableProperty } = util2; + var { kHeaders, kSignal, kState, kGuard, kRealm } = require_symbols2(); + var { webidl } = require_webidl(); + var { getGlobalOrigin } = require_global(); + var { URLSerializer } = require_dataURL(); + var { kHeadersList, kConstruct } = require_symbols(); + var assert = require("assert"); + var { getMaxListeners, setMaxListeners: setMaxListeners2, getEventListeners, defaultMaxListeners } = require("events"); + var TransformStream = globalThis.TransformStream; + var kAbortController = /* @__PURE__ */ Symbol("abortController"); + var requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { + signal.removeEventListener("abort", abort); + }); + var Request = class _Request { + // https://fetch.spec.whatwg.org/#dom-request + constructor(input, init = {}) { + if (input === kConstruct) { + return; + } + webidl.argumentLengthCheck(arguments, 1, { header: "Request constructor" }); + input = webidl.converters.RequestInfo(input); + init = webidl.converters.RequestInit(init); + this[kRealm] = { + settingsObject: { + baseUrl: getGlobalOrigin(), + get origin() { + return this.baseUrl?.origin; + }, + policyContainer: makePolicyContainer() + } + }; + let request = null; + let fallbackMode = null; + const baseUrl = this[kRealm].settingsObject.baseUrl; + let signal = null; + if (typeof input === "string") { + let parsedURL; + try { + parsedURL = new URL(input, baseUrl); + } catch (err) { + throw new TypeError("Failed to parse URL from " + input, { cause: err }); + } + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + "Request cannot be constructed from a URL that includes credentials: " + input + ); + } + request = makeRequest({ urlList: [parsedURL] }); + fallbackMode = "cors"; + } else { + assert(input instanceof _Request); + request = input[kState]; + signal = input[kSignal]; + } + const origin = this[kRealm].settingsObject.origin; + let window = "client"; + if (request.window?.constructor?.name === "EnvironmentSettingsObject" && sameOrigin(request.window, origin)) { + window = request.window; + } + if (init.window != null) { + throw new TypeError(`'window' option '${window}' must be null`); + } + if ("window" in init) { + window = "no-window"; + } + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: this[kRealm].settingsObject, + // window window. + window, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }); + const initHasKey = Object.keys(init).length !== 0; + if (initHasKey) { + if (request.mode === "navigate") { + request.mode = "same-origin"; + } + request.reloadNavigation = false; + request.historyNavigation = false; + request.origin = "client"; + request.referrer = "client"; + request.referrerPolicy = ""; + request.url = request.urlList[request.urlList.length - 1]; + request.urlList = [request.url]; + } + if (init.referrer !== void 0) { + const referrer = init.referrer; + if (referrer === "") { + request.referrer = "no-referrer"; + } else { + let parsedReferrer; + try { + parsedReferrer = new URL(referrer, baseUrl); + } catch (err) { + throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }); + } + if (parsedReferrer.protocol === "about:" && parsedReferrer.hostname === "client" || origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl)) { + request.referrer = "client"; + } else { + request.referrer = parsedReferrer; + } + } + } + if (init.referrerPolicy !== void 0) { + request.referrerPolicy = init.referrerPolicy; + } + let mode; + if (init.mode !== void 0) { + mode = init.mode; + } else { + mode = fallbackMode; + } + if (mode === "navigate") { + throw webidl.errors.exception({ + header: "Request constructor", + message: "invalid request mode navigate." + }); + } + if (mode != null) { + request.mode = mode; + } + if (init.credentials !== void 0) { + request.credentials = init.credentials; + } + if (init.cache !== void 0) { + request.cache = init.cache; + } + if (request.cache === "only-if-cached" && request.mode !== "same-origin") { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ); + } + if (init.redirect !== void 0) { + request.redirect = init.redirect; + } + if (init.integrity != null) { + request.integrity = String(init.integrity); + } + if (init.keepalive !== void 0) { + request.keepalive = Boolean(init.keepalive); + } + if (init.method !== void 0) { + let method = init.method; + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`); + } + if (forbiddenMethodsSet.has(method.toUpperCase())) { + throw new TypeError(`'${method}' HTTP method is unsupported.`); + } + method = normalizeMethodRecord[method] ?? normalizeMethod(method); + request.method = method; + } + if (init.signal !== void 0) { + signal = init.signal; + } + this[kState] = request; + const ac = new AbortController(); + this[kSignal] = ac.signal; + this[kSignal][kRealm] = this[kRealm]; + if (signal != null) { + if (!signal || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function") { + throw new TypeError( + "Failed to construct 'Request': member signal is not of type AbortSignal." + ); + } + if (signal.aborted) { + ac.abort(signal.reason); + } else { + this[kAbortController] = ac; + const acRef = new WeakRef(ac); + const abort = function() { + const ac2 = acRef.deref(); + if (ac2 !== void 0) { + ac2.abort(this.reason); + } + }; + try { + if (typeof getMaxListeners === "function" && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners2(100, signal); + } else if (getEventListeners(signal, "abort").length >= defaultMaxListeners) { + setMaxListeners2(100, signal); + } + } catch { + } + util2.addAbortListener(signal, abort); + requestFinalizer.register(ac, { signal, abort }); + } + } + this[kHeaders] = new Headers(kConstruct); + this[kHeaders][kHeadersList] = request.headersList; + this[kHeaders][kGuard] = "request"; + this[kHeaders][kRealm] = this[kRealm]; + if (mode === "no-cors") { + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ); + } + this[kHeaders][kGuard] = "request-no-cors"; + } + if (initHasKey) { + const headersList = this[kHeaders][kHeadersList]; + const headers = init.headers !== void 0 ? init.headers : new HeadersList(headersList); + headersList.clear(); + if (headers instanceof HeadersList) { + for (const [key, val] of headers) { + headersList.append(key, val); + } + headersList.cookies = headers.cookies; + } else { + fillHeaders(this[kHeaders], headers); + } + } + const inputBody = input instanceof _Request ? input[kState].body : null; + if ((init.body != null || inputBody != null) && (request.method === "GET" || request.method === "HEAD")) { + throw new TypeError("Request with GET/HEAD method cannot have body."); + } + let initBody = null; + if (init.body != null) { + const [extractedBody, contentType] = extractBody( + init.body, + request.keepalive + ); + initBody = extractedBody; + if (contentType && !this[kHeaders][kHeadersList].contains("content-type")) { + this[kHeaders].append("content-type", contentType); + } + } + const inputOrInitBody = initBody ?? inputBody; + if (inputOrInitBody != null && inputOrInitBody.source == null) { + if (initBody != null && init.duplex == null) { + throw new TypeError("RequestInit: duplex option is required when sending a body."); + } + if (request.mode !== "same-origin" && request.mode !== "cors") { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ); + } + request.useCORSPreflightFlag = true; + } + let finalBody = inputOrInitBody; + if (initBody == null && inputBody != null) { + if (util2.isDisturbed(inputBody.stream) || inputBody.stream.locked) { + throw new TypeError( + "Cannot construct a Request with a Request object that has already been used." + ); + } + if (!TransformStream) { + TransformStream = require("stream/web").TransformStream; + } + const identityTransform = new TransformStream(); + inputBody.stream.pipeThrough(identityTransform); + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + }; + } + this[kState].body = finalBody; + } + // Returns request’s HTTP method, which is "GET" by default. + get method() { + webidl.brandCheck(this, _Request); + return this[kState].method; + } + // Returns the URL of request as a string. + get url() { + webidl.brandCheck(this, _Request); + return URLSerializer(this[kState].url); + } + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers() { + webidl.brandCheck(this, _Request); + return this[kHeaders]; + } + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination() { + webidl.brandCheck(this, _Request); + return this[kState].destination; + } + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer() { + webidl.brandCheck(this, _Request); + if (this[kState].referrer === "no-referrer") { + return ""; + } + if (this[kState].referrer === "client") { + return "about:client"; + } + return this[kState].referrer.toString(); + } + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy() { + webidl.brandCheck(this, _Request); + return this[kState].referrerPolicy; + } + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode() { + webidl.brandCheck(this, _Request); + return this[kState].mode; + } + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials() { + return this[kState].credentials; + } + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache() { + webidl.brandCheck(this, _Request); + return this[kState].cache; + } + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect() { + webidl.brandCheck(this, _Request); + return this[kState].redirect; + } + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity() { + webidl.brandCheck(this, _Request); + return this[kState].integrity; + } + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive() { + webidl.brandCheck(this, _Request); + return this[kState].keepalive; + } + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation() { + webidl.brandCheck(this, _Request); + return this[kState].reloadNavigation; + } + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-foward navigation). + get isHistoryNavigation() { + webidl.brandCheck(this, _Request); + return this[kState].historyNavigation; + } + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal() { + webidl.brandCheck(this, _Request); + return this[kSignal]; + } + get body() { + webidl.brandCheck(this, _Request); + return this[kState].body ? this[kState].body.stream : null; + } + get bodyUsed() { + webidl.brandCheck(this, _Request); + return !!this[kState].body && util2.isDisturbed(this[kState].body.stream); + } + get duplex() { + webidl.brandCheck(this, _Request); + return "half"; + } + // Returns a clone of request. + clone() { + webidl.brandCheck(this, _Request); + if (this.bodyUsed || this.body?.locked) { + throw new TypeError("unusable"); + } + const clonedRequest = cloneRequest(this[kState]); + const clonedRequestObject = new _Request(kConstruct); + clonedRequestObject[kState] = clonedRequest; + clonedRequestObject[kRealm] = this[kRealm]; + clonedRequestObject[kHeaders] = new Headers(kConstruct); + clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList; + clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard]; + clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm]; + const ac = new AbortController(); + if (this.signal.aborted) { + ac.abort(this.signal.reason); + } else { + util2.addAbortListener( + this.signal, + () => { + ac.abort(this.signal.reason); + } + ); + } + clonedRequestObject[kSignal] = ac.signal; + return clonedRequestObject; + } + }; + mixinBody(Request); + function makeRequest(init) { + const request = { + method: "GET", + localURLsOnly: false, + unsafeRequest: false, + body: null, + client: null, + reservedClient: null, + replacesClientId: "", + window: "client", + keepalive: false, + serviceWorkers: "all", + initiator: "", + destination: "", + priority: null, + origin: "client", + policyContainer: "client", + referrer: "client", + referrerPolicy: "", + mode: "no-cors", + useCORSPreflightFlag: false, + credentials: "same-origin", + useCredentials: false, + cache: "default", + redirect: "follow", + integrity: "", + cryptoGraphicsNonceMetadata: "", + parserMetadata: "", + reloadNavigation: false, + historyNavigation: false, + userActivation: false, + taintedOrigin: false, + redirectCount: 0, + responseTainting: "basic", + preventNoCacheCacheControlHeaderModification: false, + done: false, + timingAllowFailed: false, + ...init, + headersList: init.headersList ? new HeadersList(init.headersList) : new HeadersList() + }; + request.url = request.urlList[0]; + return request; + } + function cloneRequest(request) { + const newRequest = makeRequest({ ...request, body: null }); + if (request.body != null) { + newRequest.body = cloneBody(request.body); + } + return newRequest; + } + Object.defineProperties(Request.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "Request", + configurable: true + } + }); + webidl.converters.Request = webidl.interfaceConverter( + Request + ); + webidl.converters.RequestInfo = function(V) { + if (typeof V === "string") { + return webidl.converters.USVString(V); + } + if (V instanceof Request) { + return webidl.converters.Request(V); + } + return webidl.converters.USVString(V); + }; + webidl.converters.AbortSignal = webidl.interfaceConverter( + AbortSignal + ); + webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: "method", + converter: webidl.converters.ByteString + }, + { + key: "headers", + converter: webidl.converters.HeadersInit + }, + { + key: "body", + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: "referrer", + converter: webidl.converters.USVString + }, + { + key: "referrerPolicy", + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy + }, + { + key: "mode", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: "credentials", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: "cache", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: "redirect", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: "integrity", + converter: webidl.converters.DOMString + }, + { + key: "keepalive", + converter: webidl.converters.boolean + }, + { + key: "signal", + converter: webidl.nullableConverter( + (signal) => webidl.converters.AbortSignal( + signal, + { strict: false } + ) + ) + }, + { + key: "window", + converter: webidl.converters.any + }, + { + key: "duplex", + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + } + ]); + module2.exports = { Request, makeRequest }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/index.js +var require_fetch = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fetch/index.js"(exports2, module2) { + "use strict"; + var { + Response, + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse + } = require_response(); + var { Headers } = require_headers(); + var { Request, makeRequest } = require_request2(); + var zlib = require("zlib"); + var { + bytesMatch, + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + createDeferredPromise, + isBlobLike, + sameOrigin, + isCancelled, + isAborted: isAborted2, + isErrorLike, + fullyReadBody, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme + } = require_util2(); + var { kState, kHeaders, kGuard, kRealm } = require_symbols2(); + var assert = require("assert"); + var { safelyExtractBody } = require_body(); + var { + redirectStatusSet, + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet, + DOMException: DOMException2 + } = require_constants2(); + var { kHeadersList } = require_symbols(); + var EE = require("events"); + var { Readable: Readable4, pipeline } = require("stream"); + var { addAbortListener: addAbortListener3, isErrored, isReadable, nodeMajor, nodeMinor } = require_util(); + var { dataURLProcessor, serializeAMimeType } = require_dataURL(); + var { TransformStream } = require("stream/web"); + var { getGlobalDispatcher } = require_global2(); + var { webidl } = require_webidl(); + var { STATUS_CODES } = require("http"); + var GET_OR_HEAD = ["GET", "HEAD"]; + var resolveObjectURL; + var ReadableStream2 = globalThis.ReadableStream; + var Fetch = class extends EE { + constructor(dispatcher) { + super(); + this.dispatcher = dispatcher; + this.connection = null; + this.dump = false; + this.state = "ongoing"; + this.setMaxListeners(21); + } + terminate(reason) { + if (this.state !== "ongoing") { + return; + } + this.state = "terminated"; + this.connection?.destroy(reason); + this.emit("terminated", reason); + } + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort(error) { + if (this.state !== "ongoing") { + return; + } + this.state = "aborted"; + if (!error) { + error = new DOMException2("The operation was aborted.", "AbortError"); + } + this.serializedAbortReason = error; + this.connection?.destroy(error); + this.emit("terminated", error); + } + }; + function fetch(input, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: "globalThis.fetch" }); + const p = createDeferredPromise(); + let requestObject; + try { + requestObject = new Request(input, init); + } catch (e) { + p.reject(e); + return p.promise; + } + const request = requestObject[kState]; + if (requestObject.signal.aborted) { + abortFetch(p, request, null, requestObject.signal.reason); + return p.promise; + } + const globalObject = request.client.globalObject; + if (globalObject?.constructor?.name === "ServiceWorkerGlobalScope") { + request.serviceWorkers = "none"; + } + let responseObject = null; + const relevantRealm = null; + let locallyAborted = false; + let controller = null; + addAbortListener3( + requestObject.signal, + () => { + locallyAborted = true; + assert(controller != null); + controller.abort(requestObject.signal.reason); + abortFetch(p, request, responseObject, requestObject.signal.reason); + } + ); + const handleFetchDone = (response) => finalizeAndReportTiming(response, "fetch"); + const processResponse = (response) => { + if (locallyAborted) { + return Promise.resolve(); + } + if (response.aborted) { + abortFetch(p, request, responseObject, controller.serializedAbortReason); + return Promise.resolve(); + } + if (response.type === "error") { + p.reject( + Object.assign(new TypeError("fetch failed"), { cause: response.error }) + ); + return Promise.resolve(); + } + responseObject = new Response(); + responseObject[kState] = response; + responseObject[kRealm] = relevantRealm; + responseObject[kHeaders][kHeadersList] = response.headersList; + responseObject[kHeaders][kGuard] = "immutable"; + responseObject[kHeaders][kRealm] = relevantRealm; + p.resolve(responseObject); + }; + controller = fetching({ + request, + processResponseEndOfBody: handleFetchDone, + processResponse, + dispatcher: init.dispatcher ?? getGlobalDispatcher() + // undici + }); + return p.promise; + } + function finalizeAndReportTiming(response, initiatorType = "other") { + if (response.type === "error" && response.aborted) { + return; + } + if (!response.urlList?.length) { + return; + } + const originalURL = response.urlList[0]; + let timingInfo = response.timingInfo; + let cacheState = response.cacheState; + if (!urlIsHttpHttpsScheme(originalURL)) { + return; + } + if (timingInfo === null) { + return; + } + if (!response.timingAllowPassed) { + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }); + cacheState = ""; + } + timingInfo.endTime = coarsenedSharedCurrentTime(); + response.timingInfo = timingInfo; + markResourceTiming( + timingInfo, + originalURL, + initiatorType, + globalThis, + cacheState + ); + } + function markResourceTiming(timingInfo, originalURL, initiatorType, globalThis2, cacheState) { + if (nodeMajor > 18 || nodeMajor === 18 && nodeMinor >= 2) { + performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis2, cacheState); + } + } + function abortFetch(p, request, responseObject, error) { + if (!error) { + error = new DOMException2("The operation was aborted.", "AbortError"); + } + p.reject(error); + if (request.body != null && isReadable(request.body?.stream)) { + request.body.stream.cancel(error).catch((err) => { + if (err.code === "ERR_INVALID_STATE") { + return; + } + throw err; + }); + } + if (responseObject == null) { + return; + } + const response = responseObject[kState]; + if (response.body != null && isReadable(response.body?.stream)) { + response.body.stream.cancel(error).catch((err) => { + if (err.code === "ERR_INVALID_STATE") { + return; + } + throw err; + }); + } + } + function fetching({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher + // undici + }) { + let taskDestination = null; + let crossOriginIsolatedCapability = false; + if (request.client != null) { + taskDestination = request.client.globalObject; + crossOriginIsolatedCapability = request.client.crossOriginIsolatedCapability; + } + const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability); + const timingInfo = createOpaqueTimingInfo({ + startTime: currenTime + }); + const fetchParams = { + controller: new Fetch(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability + }; + assert(!request.body || request.body.stream); + if (request.window === "client") { + request.window = request.client?.globalObject?.constructor?.name === "Window" ? request.client : "no-window"; + } + if (request.origin === "client") { + request.origin = request.client?.origin; + } + if (request.policyContainer === "client") { + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ); + } else { + request.policyContainer = makePolicyContainer(); + } + } + if (!request.headersList.contains("accept")) { + const value = "*/*"; + request.headersList.append("accept", value); + } + if (!request.headersList.contains("accept-language")) { + request.headersList.append("accept-language", "*"); + } + if (request.priority === null) { + } + if (subresourceSet.has(request.destination)) { + } + mainFetch(fetchParams).catch((err) => { + fetchParams.controller.terminate(err); + }); + return fetchParams.controller; + } + async function mainFetch(fetchParams, recursive = false) { + const request = fetchParams.request; + let response = null; + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError("local URLs only"); + } + tryUpgradeRequestToAPotentiallyTrustworthyURL(request); + if (requestBadPort(request) === "blocked") { + response = makeNetworkError("bad port"); + } + if (request.referrerPolicy === "") { + request.referrerPolicy = request.policyContainer.referrerPolicy; + } + if (request.referrer !== "no-referrer") { + request.referrer = determineRequestsReferrer(request); + } + if (response === null) { + response = await (async () => { + const currentURL = requestCurrentURL(request); + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + sameOrigin(currentURL, request.url) && request.responseTainting === "basic" || // request’s current URL’s scheme is "data" + currentURL.protocol === "data:" || // - request’s mode is "navigate" or "websocket" + (request.mode === "navigate" || request.mode === "websocket") + ) { + request.responseTainting = "basic"; + return await schemeFetch(fetchParams); + } + if (request.mode === "same-origin") { + return makeNetworkError('request mode cannot be "same-origin"'); + } + if (request.mode === "no-cors") { + if (request.redirect !== "follow") { + return makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ); + } + request.responseTainting = "opaque"; + return await schemeFetch(fetchParams); + } + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + return makeNetworkError("URL scheme must be a HTTP(S) scheme"); + } + request.responseTainting = "cors"; + return await httpFetch(fetchParams); + })(); + } + if (recursive) { + return response; + } + if (response.status !== 0 && !response.internalResponse) { + if (request.responseTainting === "cors") { + } + if (request.responseTainting === "basic") { + response = filterResponse(response, "basic"); + } else if (request.responseTainting === "cors") { + response = filterResponse(response, "cors"); + } else if (request.responseTainting === "opaque") { + response = filterResponse(response, "opaque"); + } else { + assert(false); + } + } + let internalResponse = response.status === 0 ? response : response.internalResponse; + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList); + } + if (!request.timingAllowFailed) { + response.timingAllowPassed = true; + } + if (response.type === "opaque" && internalResponse.status === 206 && internalResponse.rangeRequested && !request.headers.contains("range")) { + response = internalResponse = makeNetworkError(); + } + if (response.status !== 0 && (request.method === "HEAD" || request.method === "CONNECT" || nullBodyStatus.includes(internalResponse.status))) { + internalResponse.body = null; + fetchParams.controller.dump = true; + } + if (request.integrity) { + const processBodyError = (reason) => fetchFinale(fetchParams, makeNetworkError(reason)); + if (request.responseTainting === "opaque" || response.body == null) { + processBodyError(response.error); + return; + } + const processBody = (bytes) => { + if (!bytesMatch(bytes, request.integrity)) { + processBodyError("integrity mismatch"); + return; + } + response.body = safelyExtractBody(bytes)[0]; + fetchFinale(fetchParams, response); + }; + await fullyReadBody(response.body, processBody, processBodyError); + } else { + fetchFinale(fetchParams, response); + } + } + function schemeFetch(fetchParams) { + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)); + } + const { request } = fetchParams; + const { protocol: scheme } = requestCurrentURL(request); + switch (scheme) { + case "about:": { + return Promise.resolve(makeNetworkError("about scheme is not supported")); + } + case "blob:": { + if (!resolveObjectURL) { + resolveObjectURL = require("buffer").resolveObjectURL; + } + const blobURLEntry = requestCurrentURL(request); + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError("NetworkError when attempting to fetch resource.")); + } + const blobURLEntryObject = resolveObjectURL(blobURLEntry.toString()); + if (request.method !== "GET" || !isBlobLike(blobURLEntryObject)) { + return Promise.resolve(makeNetworkError("invalid method")); + } + const bodyWithType = safelyExtractBody(blobURLEntryObject); + const body = bodyWithType[0]; + const length = isomorphicEncode(`${body.length}`); + const type = bodyWithType[1] ?? ""; + const response = makeResponse({ + statusText: "OK", + headersList: [ + ["content-length", { name: "Content-Length", value: length }], + ["content-type", { name: "Content-Type", value: type }] + ] + }); + response.body = body; + return Promise.resolve(response); + } + case "data:": { + const currentURL = requestCurrentURL(request); + const dataURLStruct = dataURLProcessor(currentURL); + if (dataURLStruct === "failure") { + return Promise.resolve(makeNetworkError("failed to fetch the data URL")); + } + const mimeType = serializeAMimeType(dataURLStruct.mimeType); + return Promise.resolve(makeResponse({ + statusText: "OK", + headersList: [ + ["content-type", { name: "Content-Type", value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })); + } + case "file:": { + return Promise.resolve(makeNetworkError("not implemented... yet...")); + } + case "http:": + case "https:": { + return httpFetch(fetchParams).catch((err) => makeNetworkError(err)); + } + default: { + return Promise.resolve(makeNetworkError("unknown scheme")); + } + } + } + function finalizeResponse(fetchParams, response) { + fetchParams.request.done = true; + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)); + } + } + function fetchFinale(fetchParams, response) { + if (response.type === "error") { + response.urlList = [fetchParams.request.urlList[0]]; + response.timingInfo = createOpaqueTimingInfo({ + startTime: fetchParams.timingInfo.startTime + }); + } + const processResponseEndOfBody = () => { + fetchParams.request.done = true; + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)); + } + }; + if (fetchParams.processResponse != null) { + queueMicrotask(() => fetchParams.processResponse(response)); + } + if (response.body == null) { + processResponseEndOfBody(); + } else { + const identityTransformAlgorithm = (chunk, controller) => { + controller.enqueue(chunk); + }; + const transformStream = new TransformStream({ + start() { + }, + transform: identityTransformAlgorithm, + flush: processResponseEndOfBody + }, { + size() { + return 1; + } + }, { + size() { + return 1; + } + }); + response.body = { stream: response.body.stream.pipeThrough(transformStream) }; + } + if (fetchParams.processResponseConsumeBody != null) { + const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes); + const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure); + if (response.body == null) { + queueMicrotask(() => processBody(null)); + } else { + return fullyReadBody(response.body, processBody, processBodyError); + } + return Promise.resolve(); + } + } + async function httpFetch(fetchParams) { + const request = fetchParams.request; + let response = null; + let actualResponse = null; + const timingInfo = fetchParams.timingInfo; + if (request.serviceWorkers === "all") { + } + if (response === null) { + if (request.redirect === "follow") { + request.serviceWorkers = "none"; + } + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams); + if (request.responseTainting === "cors" && corsCheck(request, response) === "failure") { + return makeNetworkError("cors failure"); + } + if (TAOCheck(request, response) === "failure") { + request.timingAllowFailed = true; + } + } + if ((request.responseTainting === "opaque" || response.type === "opaque") && crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === "blocked") { + return makeNetworkError("blocked"); + } + if (redirectStatusSet.has(actualResponse.status)) { + if (request.redirect !== "manual") { + fetchParams.controller.connection.destroy(); + } + if (request.redirect === "error") { + response = makeNetworkError("unexpected redirect"); + } else if (request.redirect === "manual") { + response = actualResponse; + } else if (request.redirect === "follow") { + response = await httpRedirectFetch(fetchParams, response); + } else { + assert(false); + } + } + response.timingInfo = timingInfo; + return response; + } + function httpRedirectFetch(fetchParams, response) { + const request = fetchParams.request; + const actualResponse = response.internalResponse ? response.internalResponse : response; + let locationURL; + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ); + if (locationURL == null) { + return response; + } + } catch (err) { + return Promise.resolve(makeNetworkError(err)); + } + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError("URL scheme must be a HTTP(S) scheme")); + } + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError("redirect count exceeded")); + } + request.redirectCount += 1; + if (request.mode === "cors" && (locationURL.username || locationURL.password) && !sameOrigin(request, locationURL)) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')); + } + if (request.responseTainting === "cors" && (locationURL.username || locationURL.password)) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )); + } + if (actualResponse.status !== 303 && request.body != null && request.body.source == null) { + return Promise.resolve(makeNetworkError()); + } + if ([301, 302].includes(actualResponse.status) && request.method === "POST" || actualResponse.status === 303 && !GET_OR_HEAD.includes(request.method)) { + request.method = "GET"; + request.body = null; + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName); + } + } + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + request.headersList.delete("authorization"); + request.headersList.delete("proxy-authorization", true); + request.headersList.delete("cookie"); + request.headersList.delete("host"); + } + if (request.body != null) { + assert(request.body.source != null); + request.body = safelyExtractBody(request.body.source)[0]; + } + const timingInfo = fetchParams.timingInfo; + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability); + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime; + } + request.urlList.push(locationURL); + setRequestReferrerPolicyOnRedirect(request, actualResponse); + return mainFetch(fetchParams, true); + } + async function httpNetworkOrCacheFetch(fetchParams, isAuthenticationFetch = false, isNewConnectionFetch = false) { + const request = fetchParams.request; + let httpFetchParams = null; + let httpRequest = null; + let response = null; + const httpCache = null; + const revalidatingFlag = false; + if (request.window === "no-window" && request.redirect === "error") { + httpFetchParams = fetchParams; + httpRequest = request; + } else { + httpRequest = makeRequest(request); + httpFetchParams = { ...fetchParams }; + httpFetchParams.request = httpRequest; + } + const includeCredentials = request.credentials === "include" || request.credentials === "same-origin" && request.responseTainting === "basic"; + const contentLength = httpRequest.body ? httpRequest.body.length : null; + let contentLengthHeaderValue = null; + if (httpRequest.body == null && ["POST", "PUT"].includes(httpRequest.method)) { + contentLengthHeaderValue = "0"; + } + if (contentLength != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`); + } + if (contentLengthHeaderValue != null) { + httpRequest.headersList.append("content-length", contentLengthHeaderValue); + } + if (contentLength != null && httpRequest.keepalive) { + } + if (httpRequest.referrer instanceof URL) { + httpRequest.headersList.append("referer", isomorphicEncode(httpRequest.referrer.href)); + } + appendRequestOriginHeader(httpRequest); + appendFetchMetadata(httpRequest); + if (!httpRequest.headersList.contains("user-agent")) { + httpRequest.headersList.append("user-agent", typeof esbuildDetection === "undefined" ? "undici" : "node"); + } + if (httpRequest.cache === "default" && (httpRequest.headersList.contains("if-modified-since") || httpRequest.headersList.contains("if-none-match") || httpRequest.headersList.contains("if-unmodified-since") || httpRequest.headersList.contains("if-match") || httpRequest.headersList.contains("if-range"))) { + httpRequest.cache = "no-store"; + } + if (httpRequest.cache === "no-cache" && !httpRequest.preventNoCacheCacheControlHeaderModification && !httpRequest.headersList.contains("cache-control")) { + httpRequest.headersList.append("cache-control", "max-age=0"); + } + if (httpRequest.cache === "no-store" || httpRequest.cache === "reload") { + if (!httpRequest.headersList.contains("pragma")) { + httpRequest.headersList.append("pragma", "no-cache"); + } + if (!httpRequest.headersList.contains("cache-control")) { + httpRequest.headersList.append("cache-control", "no-cache"); + } + } + if (httpRequest.headersList.contains("range")) { + httpRequest.headersList.append("accept-encoding", "identity"); + } + if (!httpRequest.headersList.contains("accept-encoding")) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append("accept-encoding", "br, gzip, deflate"); + } else { + httpRequest.headersList.append("accept-encoding", "gzip, deflate"); + } + } + httpRequest.headersList.delete("host"); + if (includeCredentials) { + } + if (httpCache == null) { + httpRequest.cache = "no-store"; + } + if (httpRequest.mode !== "no-store" && httpRequest.mode !== "reload") { + } + if (response == null) { + if (httpRequest.mode === "only-if-cached") { + return makeNetworkError("only if cached"); + } + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ); + if (!safeMethodsSet.has(httpRequest.method) && forwardResponse.status >= 200 && forwardResponse.status <= 399) { + } + if (revalidatingFlag && forwardResponse.status === 304) { + } + if (response == null) { + response = forwardResponse; + } + } + response.urlList = [...httpRequest.urlList]; + if (httpRequest.headersList.contains("range")) { + response.rangeRequested = true; + } + response.requestIncludesCredentials = includeCredentials; + if (response.status === 407) { + if (request.window === "no-window") { + return makeNetworkError(); + } + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams); + } + return makeNetworkError("proxy authentication required"); + } + if ( + // response’s status is 421 + response.status === 421 && // isNewConnectionFetch is false + !isNewConnectionFetch && // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams); + } + fetchParams.controller.connection.destroy(); + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ); + } + if (isAuthenticationFetch) { + } + return response; + } + async function httpNetworkFetch(fetchParams, includeCredentials = false, forceNewConnection = false) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed); + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy(err) { + if (!this.destroyed) { + this.destroyed = true; + this.abort?.(err ?? new DOMException2("The operation was aborted.", "AbortError")); + } + } + }; + const request = fetchParams.request; + let response = null; + const timingInfo = fetchParams.timingInfo; + const httpCache = null; + if (httpCache == null) { + request.cache = "no-store"; + } + const newConnection = forceNewConnection ? "yes" : "no"; + if (request.mode === "websocket") { + } else { + } + let requestBody = null; + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()); + } else if (request.body != null) { + const processBodyChunk = async function* (bytes) { + if (isCancelled(fetchParams)) { + return; + } + yield bytes; + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength); + }; + const processEndOfBody = () => { + if (isCancelled(fetchParams)) { + return; + } + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody(); + } + }; + const processBodyError = (e) => { + if (isCancelled(fetchParams)) { + return; + } + if (e.name === "AbortError") { + fetchParams.controller.abort(); + } else { + fetchParams.controller.terminate(e); + } + }; + requestBody = (async function* () { + try { + for await (const bytes of request.body.stream) { + yield* processBodyChunk(bytes); + } + processEndOfBody(); + } catch (err) { + processBodyError(err); + } + })(); + } + try { + const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }); + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }); + } else { + const iterator = body[Symbol.asyncIterator](); + fetchParams.controller.next = () => iterator.next(); + response = makeResponse({ status, statusText, headersList }); + } + } catch (err) { + if (err.name === "AbortError") { + fetchParams.controller.connection.destroy(); + return makeAppropriateNetworkError(fetchParams, err); + } + return makeNetworkError(err); + } + const pullAlgorithm = () => { + fetchParams.controller.resume(); + }; + const cancelAlgorithm = (reason) => { + fetchParams.controller.abort(reason); + }; + if (!ReadableStream2) { + ReadableStream2 = require("stream/web").ReadableStream; + } + const stream = new ReadableStream2( + { + async start(controller) { + fetchParams.controller.controller = controller; + }, + async pull(controller) { + await pullAlgorithm(controller); + }, + async cancel(reason) { + await cancelAlgorithm(reason); + } + }, + { + highWaterMark: 0, + size() { + return 1; + } + } + ); + response.body = { stream }; + fetchParams.controller.on("terminated", onAborted); + fetchParams.controller.resume = async () => { + while (true) { + let bytes; + let isFailure; + try { + const { done, value } = await fetchParams.controller.next(); + if (isAborted2(fetchParams)) { + break; + } + bytes = done ? void 0 : value; + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + bytes = void 0; + } else { + bytes = err; + isFailure = true; + } + } + if (bytes === void 0) { + readableStreamClose(fetchParams.controller.controller); + finalizeResponse(fetchParams, response); + return; + } + timingInfo.decodedBodySize += bytes?.byteLength ?? 0; + if (isFailure) { + fetchParams.controller.terminate(bytes); + return; + } + fetchParams.controller.controller.enqueue(new Uint8Array(bytes)); + if (isErrored(stream)) { + fetchParams.controller.terminate(); + return; + } + if (!fetchParams.controller.controller.desiredSize) { + return; + } + } + }; + function onAborted(reason) { + if (isAborted2(fetchParams)) { + response.aborted = true; + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ); + } + } else { + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError("terminated", { + cause: isErrorLike(reason) ? reason : void 0 + })); + } + } + fetchParams.controller.connection.destroy(); + } + return response; + async function dispatch({ body }) { + const url = requestCurrentURL(request); + const agent = fetchParams.controller.dispatcher; + return new Promise((resolve, reject) => agent.dispatch( + { + path: url.pathname + url.search, + origin: url.origin, + method: request.method, + body: fetchParams.controller.dispatcher.isMockActive ? request.body && (request.body.source || request.body.stream) : body, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === "websocket" ? "websocket" : void 0 + }, + { + body: null, + abort: null, + onConnect(abort) { + const { connection } = fetchParams.controller; + if (connection.destroyed) { + abort(new DOMException2("The operation was aborted.", "AbortError")); + } else { + fetchParams.controller.on("terminated", abort); + this.abort = connection.abort = abort; + } + }, + onHeaders(status, headersList, resume, statusText) { + if (status < 200) { + return; + } + let codings = []; + let location = ""; + const headers = new Headers(); + if (Array.isArray(headersList)) { + for (let n2 = 0; n2 < headersList.length; n2 += 2) { + const key = headersList[n2 + 0].toString("latin1"); + const val = headersList[n2 + 1].toString("latin1"); + if (key.toLowerCase() === "content-encoding") { + codings = val.toLowerCase().split(",").map((x) => x.trim()); + } else if (key.toLowerCase() === "location") { + location = val; + } + headers[kHeadersList].append(key, val); + } + } else { + const keys = Object.keys(headersList); + for (const key of keys) { + const val = headersList[key]; + if (key.toLowerCase() === "content-encoding") { + codings = val.toLowerCase().split(",").map((x) => x.trim()).reverse(); + } else if (key.toLowerCase() === "location") { + location = val; + } + headers[kHeadersList].append(key, val); + } + } + this.body = new Readable4({ read: resume }); + const decoders = []; + const willFollow = request.redirect === "follow" && location && redirectStatusSet.has(status); + if (request.method !== "HEAD" && request.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { + for (const coding of codings) { + if (coding === "x-gzip" || coding === "gzip") { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })); + } else if (coding === "deflate") { + decoders.push(zlib.createInflate()); + } else if (coding === "br") { + decoders.push(zlib.createBrotliDecompress()); + } else { + decoders.length = 0; + break; + } + } + } + resolve({ + status, + statusText, + headersList: headers[kHeadersList], + body: decoders.length ? pipeline(this.body, ...decoders, () => { + }) : this.body.on("error", () => { + }) + }); + return true; + }, + onData(chunk) { + if (fetchParams.controller.dump) { + return; + } + const bytes = chunk; + timingInfo.encodedBodySize += bytes.byteLength; + return this.body.push(bytes); + }, + onComplete() { + if (this.abort) { + fetchParams.controller.off("terminated", this.abort); + } + fetchParams.controller.ended = true; + this.body.push(null); + }, + onError(error) { + if (this.abort) { + fetchParams.controller.off("terminated", this.abort); + } + this.body?.destroy(error); + fetchParams.controller.terminate(error); + reject(error); + }, + onUpgrade(status, headersList, socket) { + if (status !== 101) { + return; + } + const headers = new Headers(); + for (let n2 = 0; n2 < headersList.length; n2 += 2) { + const key = headersList[n2 + 0].toString("latin1"); + const val = headersList[n2 + 1].toString("latin1"); + headers[kHeadersList].append(key, val); + } + resolve({ + status, + statusText: STATUS_CODES[status], + headersList: headers[kHeadersList], + socket + }); + return true; + } + } + )); + } + } + module2.exports = { + fetch, + Fetch, + fetching, + finalizeAndReportTiming + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/symbols.js +var require_symbols3 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kState: /* @__PURE__ */ Symbol("FileReader state"), + kResult: /* @__PURE__ */ Symbol("FileReader result"), + kError: /* @__PURE__ */ Symbol("FileReader error"), + kLastProgressEventFired: /* @__PURE__ */ Symbol("FileReader last progress event fired timestamp"), + kEvents: /* @__PURE__ */ Symbol("FileReader events"), + kAborted: /* @__PURE__ */ Symbol("FileReader aborted") + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/progressevent.js +var require_progressevent = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/progressevent.js"(exports2, module2) { + "use strict"; + var { webidl } = require_webidl(); + var kState = /* @__PURE__ */ Symbol("ProgressEvent state"); + var ProgressEvent = class _ProgressEvent extends Event { + constructor(type, eventInitDict = {}) { + type = webidl.converters.DOMString(type); + eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}); + super(type, eventInitDict); + this[kState] = { + lengthComputable: eventInitDict.lengthComputable, + loaded: eventInitDict.loaded, + total: eventInitDict.total + }; + } + get lengthComputable() { + webidl.brandCheck(this, _ProgressEvent); + return this[kState].lengthComputable; + } + get loaded() { + webidl.brandCheck(this, _ProgressEvent); + return this[kState].loaded; + } + get total() { + webidl.brandCheck(this, _ProgressEvent); + return this[kState].total; + } + }; + webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ + { + key: "lengthComputable", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "loaded", + converter: webidl.converters["unsigned long long"], + defaultValue: 0 + }, + { + key: "total", + converter: webidl.converters["unsigned long long"], + defaultValue: 0 + }, + { + key: "bubbles", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "cancelable", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "composed", + converter: webidl.converters.boolean, + defaultValue: false + } + ]); + module2.exports = { + ProgressEvent + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/encoding.js +var require_encoding = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/encoding.js"(exports2, module2) { + "use strict"; + function getEncoding(label) { + if (!label) { + return "failure"; + } + switch (label.trim().toLowerCase()) { + case "unicode-1-1-utf-8": + case "unicode11utf8": + case "unicode20utf8": + case "utf-8": + case "utf8": + case "x-unicode20utf8": + return "UTF-8"; + case "866": + case "cp866": + case "csibm866": + case "ibm866": + return "IBM866"; + case "csisolatin2": + case "iso-8859-2": + case "iso-ir-101": + case "iso8859-2": + case "iso88592": + case "iso_8859-2": + case "iso_8859-2:1987": + case "l2": + case "latin2": + return "ISO-8859-2"; + case "csisolatin3": + case "iso-8859-3": + case "iso-ir-109": + case "iso8859-3": + case "iso88593": + case "iso_8859-3": + case "iso_8859-3:1988": + case "l3": + case "latin3": + return "ISO-8859-3"; + case "csisolatin4": + case "iso-8859-4": + case "iso-ir-110": + case "iso8859-4": + case "iso88594": + case "iso_8859-4": + case "iso_8859-4:1988": + case "l4": + case "latin4": + return "ISO-8859-4"; + case "csisolatincyrillic": + case "cyrillic": + case "iso-8859-5": + case "iso-ir-144": + case "iso8859-5": + case "iso88595": + case "iso_8859-5": + case "iso_8859-5:1988": + return "ISO-8859-5"; + case "arabic": + case "asmo-708": + case "csiso88596e": + case "csiso88596i": + case "csisolatinarabic": + case "ecma-114": + case "iso-8859-6": + case "iso-8859-6-e": + case "iso-8859-6-i": + case "iso-ir-127": + case "iso8859-6": + case "iso88596": + case "iso_8859-6": + case "iso_8859-6:1987": + return "ISO-8859-6"; + case "csisolatingreek": + case "ecma-118": + case "elot_928": + case "greek": + case "greek8": + case "iso-8859-7": + case "iso-ir-126": + case "iso8859-7": + case "iso88597": + case "iso_8859-7": + case "iso_8859-7:1987": + case "sun_eu_greek": + return "ISO-8859-7"; + case "csiso88598e": + case "csisolatinhebrew": + case "hebrew": + case "iso-8859-8": + case "iso-8859-8-e": + case "iso-ir-138": + case "iso8859-8": + case "iso88598": + case "iso_8859-8": + case "iso_8859-8:1988": + case "visual": + return "ISO-8859-8"; + case "csiso88598i": + case "iso-8859-8-i": + case "logical": + return "ISO-8859-8-I"; + case "csisolatin6": + case "iso-8859-10": + case "iso-ir-157": + case "iso8859-10": + case "iso885910": + case "l6": + case "latin6": + return "ISO-8859-10"; + case "iso-8859-13": + case "iso8859-13": + case "iso885913": + return "ISO-8859-13"; + case "iso-8859-14": + case "iso8859-14": + case "iso885914": + return "ISO-8859-14"; + case "csisolatin9": + case "iso-8859-15": + case "iso8859-15": + case "iso885915": + case "iso_8859-15": + case "l9": + return "ISO-8859-15"; + case "iso-8859-16": + return "ISO-8859-16"; + case "cskoi8r": + case "koi": + case "koi8": + case "koi8-r": + case "koi8_r": + return "KOI8-R"; + case "koi8-ru": + case "koi8-u": + return "KOI8-U"; + case "csmacintosh": + case "mac": + case "macintosh": + case "x-mac-roman": + return "macintosh"; + case "iso-8859-11": + case "iso8859-11": + case "iso885911": + case "tis-620": + case "windows-874": + return "windows-874"; + case "cp1250": + case "windows-1250": + case "x-cp1250": + return "windows-1250"; + case "cp1251": + case "windows-1251": + case "x-cp1251": + return "windows-1251"; + case "ansi_x3.4-1968": + case "ascii": + case "cp1252": + case "cp819": + case "csisolatin1": + case "ibm819": + case "iso-8859-1": + case "iso-ir-100": + case "iso8859-1": + case "iso88591": + case "iso_8859-1": + case "iso_8859-1:1987": + case "l1": + case "latin1": + case "us-ascii": + case "windows-1252": + case "x-cp1252": + return "windows-1252"; + case "cp1253": + case "windows-1253": + case "x-cp1253": + return "windows-1253"; + case "cp1254": + case "csisolatin5": + case "iso-8859-9": + case "iso-ir-148": + case "iso8859-9": + case "iso88599": + case "iso_8859-9": + case "iso_8859-9:1989": + case "l5": + case "latin5": + case "windows-1254": + case "x-cp1254": + return "windows-1254"; + case "cp1255": + case "windows-1255": + case "x-cp1255": + return "windows-1255"; + case "cp1256": + case "windows-1256": + case "x-cp1256": + return "windows-1256"; + case "cp1257": + case "windows-1257": + case "x-cp1257": + return "windows-1257"; + case "cp1258": + case "windows-1258": + case "x-cp1258": + return "windows-1258"; + case "x-mac-cyrillic": + case "x-mac-ukrainian": + return "x-mac-cyrillic"; + case "chinese": + case "csgb2312": + case "csiso58gb231280": + case "gb2312": + case "gb_2312": + case "gb_2312-80": + case "gbk": + case "iso-ir-58": + case "x-gbk": + return "GBK"; + case "gb18030": + return "gb18030"; + case "big5": + case "big5-hkscs": + case "cn-big5": + case "csbig5": + case "x-x-big5": + return "Big5"; + case "cseucpkdfmtjapanese": + case "euc-jp": + case "x-euc-jp": + return "EUC-JP"; + case "csiso2022jp": + case "iso-2022-jp": + return "ISO-2022-JP"; + case "csshiftjis": + case "ms932": + case "ms_kanji": + case "shift-jis": + case "shift_jis": + case "sjis": + case "windows-31j": + case "x-sjis": + return "Shift_JIS"; + case "cseuckr": + case "csksc56011987": + case "euc-kr": + case "iso-ir-149": + case "korean": + case "ks_c_5601-1987": + case "ks_c_5601-1989": + case "ksc5601": + case "ksc_5601": + case "windows-949": + return "EUC-KR"; + case "csiso2022kr": + case "hz-gb-2312": + case "iso-2022-cn": + case "iso-2022-cn-ext": + case "iso-2022-kr": + case "replacement": + return "replacement"; + case "unicodefffe": + case "utf-16be": + return "UTF-16BE"; + case "csunicode": + case "iso-10646-ucs-2": + case "ucs-2": + case "unicode": + case "unicodefeff": + case "utf-16": + case "utf-16le": + return "UTF-16LE"; + case "x-user-defined": + return "x-user-defined"; + default: + return "failure"; + } + } + module2.exports = { + getEncoding + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/util.js +var require_util4 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/util.js"(exports2, module2) { + "use strict"; + var { + kState, + kError, + kResult, + kAborted, + kLastProgressEventFired + } = require_symbols3(); + var { ProgressEvent } = require_progressevent(); + var { getEncoding } = require_encoding(); + var { DOMException: DOMException2 } = require_constants2(); + var { serializeAMimeType, parseMIMEType } = require_dataURL(); + var { types } = require("util"); + var { StringDecoder: StringDecoder3 } = require("string_decoder"); + var { btoa: btoa2 } = require("buffer"); + var staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false + }; + function readOperation(fr, blob, type, encodingName) { + if (fr[kState] === "loading") { + throw new DOMException2("Invalid state", "InvalidStateError"); + } + fr[kState] = "loading"; + fr[kResult] = null; + fr[kError] = null; + const stream = blob.stream(); + const reader = stream.getReader(); + const bytes = []; + let chunkPromise = reader.read(); + let isFirstChunk = true; + (async () => { + while (!fr[kAborted]) { + try { + const { done, value } = await chunkPromise; + if (isFirstChunk && !fr[kAborted]) { + queueMicrotask(() => { + fireAProgressEvent("loadstart", fr); + }); + } + isFirstChunk = false; + if (!done && types.isUint8Array(value)) { + bytes.push(value); + if ((fr[kLastProgressEventFired] === void 0 || Date.now() - fr[kLastProgressEventFired] >= 50) && !fr[kAborted]) { + fr[kLastProgressEventFired] = Date.now(); + queueMicrotask(() => { + fireAProgressEvent("progress", fr); + }); + } + chunkPromise = reader.read(); + } else if (done) { + queueMicrotask(() => { + fr[kState] = "done"; + try { + const result = packageData(bytes, type, blob.type, encodingName); + if (fr[kAborted]) { + return; + } + fr[kResult] = result; + fireAProgressEvent("load", fr); + } catch (error) { + fr[kError] = error; + fireAProgressEvent("error", fr); + } + if (fr[kState] !== "loading") { + fireAProgressEvent("loadend", fr); + } + }); + break; + } + } catch (error) { + if (fr[kAborted]) { + return; + } + queueMicrotask(() => { + fr[kState] = "done"; + fr[kError] = error; + fireAProgressEvent("error", fr); + if (fr[kState] !== "loading") { + fireAProgressEvent("loadend", fr); + } + }); + break; + } + } + })(); + } + function fireAProgressEvent(e, reader) { + const event = new ProgressEvent(e, { + bubbles: false, + cancelable: false + }); + reader.dispatchEvent(event); + } + function packageData(bytes, type, mimeType, encodingName) { + switch (type) { + case "DataURL": { + let dataURL = "data:"; + const parsed = parseMIMEType(mimeType || "application/octet-stream"); + if (parsed !== "failure") { + dataURL += serializeAMimeType(parsed); + } + dataURL += ";base64,"; + const decoder = new StringDecoder3("latin1"); + for (const chunk of bytes) { + dataURL += btoa2(decoder.write(chunk)); + } + dataURL += btoa2(decoder.end()); + return dataURL; + } + case "Text": { + let encoding = "failure"; + if (encodingName) { + encoding = getEncoding(encodingName); + } + if (encoding === "failure" && mimeType) { + const type2 = parseMIMEType(mimeType); + if (type2 !== "failure") { + encoding = getEncoding(type2.parameters.get("charset")); + } + } + if (encoding === "failure") { + encoding = "UTF-8"; + } + return decode(bytes, encoding); + } + case "ArrayBuffer": { + const sequence = combineByteSequences(bytes); + return sequence.buffer; + } + case "BinaryString": { + let binaryString = ""; + const decoder = new StringDecoder3("latin1"); + for (const chunk of bytes) { + binaryString += decoder.write(chunk); + } + binaryString += decoder.end(); + return binaryString; + } + } + } + function decode(ioQueue, encoding) { + const bytes = combineByteSequences(ioQueue); + const BOMEncoding = BOMSniffing(bytes); + let slice = 0; + if (BOMEncoding !== null) { + encoding = BOMEncoding; + slice = BOMEncoding === "UTF-8" ? 3 : 2; + } + const sliced = bytes.slice(slice); + return new TextDecoder(encoding).decode(sliced); + } + function BOMSniffing(ioQueue) { + const [a2, b, c3] = ioQueue; + if (a2 === 239 && b === 187 && c3 === 191) { + return "UTF-8"; + } else if (a2 === 254 && b === 255) { + return "UTF-16BE"; + } else if (a2 === 255 && b === 254) { + return "UTF-16LE"; + } + return null; + } + function combineByteSequences(sequences) { + const size = sequences.reduce((a2, b) => { + return a2 + b.byteLength; + }, 0); + let offset = 0; + return sequences.reduce((a2, b) => { + a2.set(b, offset); + offset += b.byteLength; + return a2; + }, new Uint8Array(size)); + } + module2.exports = { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/filereader.js +var require_filereader = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/fileapi/filereader.js"(exports2, module2) { + "use strict"; + var { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent + } = require_util4(); + var { + kState, + kError, + kResult, + kEvents, + kAborted + } = require_symbols3(); + var { webidl } = require_webidl(); + var { kEnumerableProperty } = require_util(); + var FileReader = class _FileReader extends EventTarget { + constructor() { + super(); + this[kState] = "empty"; + this[kResult] = null; + this[kError] = null; + this[kEvents] = { + loadend: null, + error: null, + abort: null, + load: null, + progress: null, + loadstart: null + }; + } + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + * @param {import('buffer').Blob} blob + */ + readAsArrayBuffer(blob) { + webidl.brandCheck(this, _FileReader); + webidl.argumentLengthCheck(arguments, 1, { header: "FileReader.readAsArrayBuffer" }); + blob = webidl.converters.Blob(blob, { strict: false }); + readOperation(this, blob, "ArrayBuffer"); + } + /** + * @see https://w3c.github.io/FileAPI/#readAsBinaryString + * @param {import('buffer').Blob} blob + */ + readAsBinaryString(blob) { + webidl.brandCheck(this, _FileReader); + webidl.argumentLengthCheck(arguments, 1, { header: "FileReader.readAsBinaryString" }); + blob = webidl.converters.Blob(blob, { strict: false }); + readOperation(this, blob, "BinaryString"); + } + /** + * @see https://w3c.github.io/FileAPI/#readAsDataText + * @param {import('buffer').Blob} blob + * @param {string?} encoding + */ + readAsText(blob, encoding = void 0) { + webidl.brandCheck(this, _FileReader); + webidl.argumentLengthCheck(arguments, 1, { header: "FileReader.readAsText" }); + blob = webidl.converters.Blob(blob, { strict: false }); + if (encoding !== void 0) { + encoding = webidl.converters.DOMString(encoding); + } + readOperation(this, blob, "Text", encoding); + } + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL + * @param {import('buffer').Blob} blob + */ + readAsDataURL(blob) { + webidl.brandCheck(this, _FileReader); + webidl.argumentLengthCheck(arguments, 1, { header: "FileReader.readAsDataURL" }); + blob = webidl.converters.Blob(blob, { strict: false }); + readOperation(this, blob, "DataURL"); + } + /** + * @see https://w3c.github.io/FileAPI/#dfn-abort + */ + abort() { + if (this[kState] === "empty" || this[kState] === "done") { + this[kResult] = null; + return; + } + if (this[kState] === "loading") { + this[kState] = "done"; + this[kResult] = null; + } + this[kAborted] = true; + fireAProgressEvent("abort", this); + if (this[kState] !== "loading") { + fireAProgressEvent("loadend", this); + } + } + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate + */ + get readyState() { + webidl.brandCheck(this, _FileReader); + switch (this[kState]) { + case "empty": + return this.EMPTY; + case "loading": + return this.LOADING; + case "done": + return this.DONE; + } + } + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-result + */ + get result() { + webidl.brandCheck(this, _FileReader); + return this[kResult]; + } + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-error + */ + get error() { + webidl.brandCheck(this, _FileReader); + return this[kError]; + } + get onloadend() { + webidl.brandCheck(this, _FileReader); + return this[kEvents].loadend; + } + set onloadend(fn) { + webidl.brandCheck(this, _FileReader); + if (this[kEvents].loadend) { + this.removeEventListener("loadend", this[kEvents].loadend); + } + if (typeof fn === "function") { + this[kEvents].loadend = fn; + this.addEventListener("loadend", fn); + } else { + this[kEvents].loadend = null; + } + } + get onerror() { + webidl.brandCheck(this, _FileReader); + return this[kEvents].error; + } + set onerror(fn) { + webidl.brandCheck(this, _FileReader); + if (this[kEvents].error) { + this.removeEventListener("error", this[kEvents].error); + } + if (typeof fn === "function") { + this[kEvents].error = fn; + this.addEventListener("error", fn); + } else { + this[kEvents].error = null; + } + } + get onloadstart() { + webidl.brandCheck(this, _FileReader); + return this[kEvents].loadstart; + } + set onloadstart(fn) { + webidl.brandCheck(this, _FileReader); + if (this[kEvents].loadstart) { + this.removeEventListener("loadstart", this[kEvents].loadstart); + } + if (typeof fn === "function") { + this[kEvents].loadstart = fn; + this.addEventListener("loadstart", fn); + } else { + this[kEvents].loadstart = null; + } + } + get onprogress() { + webidl.brandCheck(this, _FileReader); + return this[kEvents].progress; + } + set onprogress(fn) { + webidl.brandCheck(this, _FileReader); + if (this[kEvents].progress) { + this.removeEventListener("progress", this[kEvents].progress); + } + if (typeof fn === "function") { + this[kEvents].progress = fn; + this.addEventListener("progress", fn); + } else { + this[kEvents].progress = null; + } + } + get onload() { + webidl.brandCheck(this, _FileReader); + return this[kEvents].load; + } + set onload(fn) { + webidl.brandCheck(this, _FileReader); + if (this[kEvents].load) { + this.removeEventListener("load", this[kEvents].load); + } + if (typeof fn === "function") { + this[kEvents].load = fn; + this.addEventListener("load", fn); + } else { + this[kEvents].load = null; + } + } + get onabort() { + webidl.brandCheck(this, _FileReader); + return this[kEvents].abort; + } + set onabort(fn) { + webidl.brandCheck(this, _FileReader); + if (this[kEvents].abort) { + this.removeEventListener("abort", this[kEvents].abort); + } + if (typeof fn === "function") { + this[kEvents].abort = fn; + this.addEventListener("abort", fn); + } else { + this[kEvents].abort = null; + } + } + }; + FileReader.EMPTY = FileReader.prototype.EMPTY = 0; + FileReader.LOADING = FileReader.prototype.LOADING = 1; + FileReader.DONE = FileReader.prototype.DONE = 2; + Object.defineProperties(FileReader.prototype, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors, + readAsArrayBuffer: kEnumerableProperty, + readAsBinaryString: kEnumerableProperty, + readAsText: kEnumerableProperty, + readAsDataURL: kEnumerableProperty, + abort: kEnumerableProperty, + readyState: kEnumerableProperty, + result: kEnumerableProperty, + error: kEnumerableProperty, + onloadstart: kEnumerableProperty, + onprogress: kEnumerableProperty, + onload: kEnumerableProperty, + onabort: kEnumerableProperty, + onerror: kEnumerableProperty, + onloadend: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "FileReader", + writable: false, + enumerable: false, + configurable: true + } + }); + Object.defineProperties(FileReader, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors + }); + module2.exports = { + FileReader + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/symbols.js +var require_symbols4 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kConstruct: require_symbols().kConstruct + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/util.js +var require_util5 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/util.js"(exports2, module2) { + "use strict"; + var assert = require("assert"); + var { URLSerializer } = require_dataURL(); + var { isValidHeaderName } = require_util2(); + function urlEquals(A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment); + const serializedB = URLSerializer(B, excludeFragment); + return serializedA === serializedB; + } + function fieldValues(header) { + assert(header !== null); + const values = []; + for (let value of header.split(",")) { + value = value.trim(); + if (!value.length) { + continue; + } else if (!isValidHeaderName(value)) { + continue; + } + values.push(value); + } + return values; + } + module2.exports = { + urlEquals, + fieldValues + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/cache.js +var require_cache = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/cache.js"(exports2, module2) { + "use strict"; + var { kConstruct } = require_symbols4(); + var { urlEquals, fieldValues: getFieldValues } = require_util5(); + var { kEnumerableProperty, isDisturbed } = require_util(); + var { kHeadersList } = require_symbols(); + var { webidl } = require_webidl(); + var { Response, cloneResponse } = require_response(); + var { Request } = require_request2(); + var { kState, kHeaders, kGuard, kRealm } = require_symbols2(); + var { fetching } = require_fetch(); + var { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = require_util2(); + var assert = require("assert"); + var { getGlobalDispatcher } = require_global2(); + var Cache = class _Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList; + constructor() { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor(); + } + this.#relevantRequestResponseList = arguments[1]; + } + async match(request, options = {}) { + webidl.brandCheck(this, _Cache); + webidl.argumentLengthCheck(arguments, 1, { header: "Cache.match" }); + request = webidl.converters.RequestInfo(request); + options = webidl.converters.CacheQueryOptions(options); + const p = await this.matchAll(request, options); + if (p.length === 0) { + return; + } + return p[0]; + } + async matchAll(request = void 0, options = {}) { + webidl.brandCheck(this, _Cache); + if (request !== void 0) request = webidl.converters.RequestInfo(request); + options = webidl.converters.CacheQueryOptions(options); + let r = null; + if (request !== void 0) { + if (request instanceof Request) { + r = request[kState]; + if (r.method !== "GET" && !options.ignoreMethod) { + return []; + } + } else if (typeof request === "string") { + r = new Request(request)[kState]; + } + } + const responses = []; + if (request === void 0) { + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]); + } + } else { + const requestResponses = this.#queryCache(r, options); + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]); + } + } + const responseList = []; + for (const response of responses) { + const responseObject = new Response(response.body?.source ?? null); + const body = responseObject[kState].body; + responseObject[kState] = response; + responseObject[kState].body = body; + responseObject[kHeaders][kHeadersList] = response.headersList; + responseObject[kHeaders][kGuard] = "immutable"; + responseList.push(responseObject); + } + return Object.freeze(responseList); + } + async add(request) { + webidl.brandCheck(this, _Cache); + webidl.argumentLengthCheck(arguments, 1, { header: "Cache.add" }); + request = webidl.converters.RequestInfo(request); + const requests = [request]; + const responseArrayPromise = this.addAll(requests); + return await responseArrayPromise; + } + async addAll(requests) { + webidl.brandCheck(this, _Cache); + webidl.argumentLengthCheck(arguments, 1, { header: "Cache.addAll" }); + requests = webidl.converters["sequence"](requests); + const responsePromises = []; + const requestList = []; + for (const request of requests) { + if (typeof request === "string") { + continue; + } + const r = request[kState]; + if (!urlIsHttpHttpsScheme(r.url) || r.method !== "GET") { + throw webidl.errors.exception({ + header: "Cache.addAll", + message: "Expected http/s scheme when method is not GET." + }); + } + } + const fetchControllers = []; + for (const request of requests) { + const r = new Request(request)[kState]; + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: "Cache.addAll", + message: "Expected http/s scheme." + }); + } + r.initiator = "fetch"; + r.destination = "subresource"; + requestList.push(r); + const responsePromise = createDeferredPromise(); + fetchControllers.push(fetching({ + request: r, + dispatcher: getGlobalDispatcher(), + processResponse(response) { + if (response.type === "error" || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: "Cache.addAll", + message: "Received an invalid status code or the request failed." + })); + } else if (response.headersList.contains("vary")) { + const fieldValues = getFieldValues(response.headersList.get("vary")); + for (const fieldValue of fieldValues) { + if (fieldValue === "*") { + responsePromise.reject(webidl.errors.exception({ + header: "Cache.addAll", + message: "invalid vary field value" + })); + for (const controller of fetchControllers) { + controller.abort(); + } + return; + } + } + } + }, + processResponseEndOfBody(response) { + if (response.aborted) { + responsePromise.reject(new DOMException("aborted", "AbortError")); + return; + } + responsePromise.resolve(response); + } + })); + responsePromises.push(responsePromise.promise); + } + const p = Promise.all(responsePromises); + const responses = await p; + const operations = []; + let index = 0; + for (const response of responses) { + const operation = { + type: "put", + // 7.3.2 + request: requestList[index], + // 7.3.3 + response + // 7.3.4 + }; + operations.push(operation); + index++; + } + const cacheJobPromise = createDeferredPromise(); + let errorData = null; + try { + this.#batchCacheOperations(operations); + } catch (e) { + errorData = e; + } + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(void 0); + } else { + cacheJobPromise.reject(errorData); + } + }); + return cacheJobPromise.promise; + } + async put(request, response) { + webidl.brandCheck(this, _Cache); + webidl.argumentLengthCheck(arguments, 2, { header: "Cache.put" }); + request = webidl.converters.RequestInfo(request); + response = webidl.converters.Response(response); + let innerRequest = null; + if (request instanceof Request) { + innerRequest = request[kState]; + } else { + innerRequest = new Request(request)[kState]; + } + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== "GET") { + throw webidl.errors.exception({ + header: "Cache.put", + message: "Expected an http/s scheme when method is not GET" + }); + } + const innerResponse = response[kState]; + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: "Cache.put", + message: "Got 206 status" + }); + } + if (innerResponse.headersList.contains("vary")) { + const fieldValues = getFieldValues(innerResponse.headersList.get("vary")); + for (const fieldValue of fieldValues) { + if (fieldValue === "*") { + throw webidl.errors.exception({ + header: "Cache.put", + message: "Got * vary field value" + }); + } + } + } + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: "Cache.put", + message: "Response body is locked or disturbed" + }); + } + const clonedResponse = cloneResponse(innerResponse); + const bodyReadPromise = createDeferredPromise(); + if (innerResponse.body != null) { + const stream = innerResponse.body.stream; + const reader = stream.getReader(); + readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject); + } else { + bodyReadPromise.resolve(void 0); + } + const operations = []; + const operation = { + type: "put", + // 14. + request: innerRequest, + // 15. + response: clonedResponse + // 16. + }; + operations.push(operation); + const bytes = await bodyReadPromise.promise; + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes; + } + const cacheJobPromise = createDeferredPromise(); + let errorData = null; + try { + this.#batchCacheOperations(operations); + } catch (e) { + errorData = e; + } + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(); + } else { + cacheJobPromise.reject(errorData); + } + }); + return cacheJobPromise.promise; + } + async delete(request, options = {}) { + webidl.brandCheck(this, _Cache); + webidl.argumentLengthCheck(arguments, 1, { header: "Cache.delete" }); + request = webidl.converters.RequestInfo(request); + options = webidl.converters.CacheQueryOptions(options); + let r = null; + if (request instanceof Request) { + r = request[kState]; + if (r.method !== "GET" && !options.ignoreMethod) { + return false; + } + } else { + assert(typeof request === "string"); + r = new Request(request)[kState]; + } + const operations = []; + const operation = { + type: "delete", + request: r, + options + }; + operations.push(operation); + const cacheJobPromise = createDeferredPromise(); + let errorData = null; + let requestResponses; + try { + requestResponses = this.#batchCacheOperations(operations); + } catch (e) { + errorData = e; + } + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length); + } else { + cacheJobPromise.reject(errorData); + } + }); + return cacheJobPromise.promise; + } + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../types/cache').CacheQueryOptions} options + * @returns {readonly Request[]} + */ + async keys(request = void 0, options = {}) { + webidl.brandCheck(this, _Cache); + if (request !== void 0) request = webidl.converters.RequestInfo(request); + options = webidl.converters.CacheQueryOptions(options); + let r = null; + if (request !== void 0) { + if (request instanceof Request) { + r = request[kState]; + if (r.method !== "GET" && !options.ignoreMethod) { + return []; + } + } else if (typeof request === "string") { + r = new Request(request)[kState]; + } + } + const promise = createDeferredPromise(); + const requests = []; + if (request === void 0) { + for (const requestResponse of this.#relevantRequestResponseList) { + requests.push(requestResponse[0]); + } + } else { + const requestResponses = this.#queryCache(r, options); + for (const requestResponse of requestResponses) { + requests.push(requestResponse[0]); + } + } + queueMicrotask(() => { + const requestList = []; + for (const request2 of requests) { + const requestObject = new Request("https://a"); + requestObject[kState] = request2; + requestObject[kHeaders][kHeadersList] = request2.headersList; + requestObject[kHeaders][kGuard] = "immutable"; + requestObject[kRealm] = request2.client; + requestList.push(requestObject); + } + promise.resolve(Object.freeze(requestList)); + }); + return promise.promise; + } + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations(operations) { + const cache = this.#relevantRequestResponseList; + const backupCache = [...cache]; + const addedItems = []; + const resultList = []; + try { + for (const operation of operations) { + if (operation.type !== "delete" && operation.type !== "put") { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: 'operation type does not match "delete" or "put"' + }); + } + if (operation.type === "delete" && operation.response != null) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "delete operation should not have an associated response" + }); + } + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException("???", "InvalidStateError"); + } + let requestResponses; + if (operation.type === "delete") { + requestResponses = this.#queryCache(operation.request, operation.options); + if (requestResponses.length === 0) { + return []; + } + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse); + assert(idx !== -1); + cache.splice(idx, 1); + } + } else if (operation.type === "put") { + if (operation.response == null) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "put operation should have an associated response" + }); + } + const r = operation.request; + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "expected http or https scheme" + }); + } + if (r.method !== "GET") { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "not get method" + }); + } + if (operation.options != null) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "options must not be defined" + }); + } + requestResponses = this.#queryCache(operation.request); + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse); + assert(idx !== -1); + cache.splice(idx, 1); + } + cache.push([operation.request, operation.response]); + addedItems.push([operation.request, operation.response]); + } + resultList.push([operation.request, operation.response]); + } + return resultList; + } catch (e) { + this.#relevantRequestResponseList.length = 0; + this.#relevantRequestResponseList = backupCache; + throw e; + } + } + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache(requestQuery, options, targetStorage) { + const resultList = []; + const storage = targetStorage ?? this.#relevantRequestResponseList; + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse] = requestResponse; + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { + resultList.push(requestResponse); + } + } + return resultList; + } + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem(requestQuery, request, response = null, options) { + const queryURL = new URL(requestQuery.url); + const cachedURL = new URL(request.url); + if (options?.ignoreSearch) { + cachedURL.search = ""; + queryURL.search = ""; + } + if (!urlEquals(queryURL, cachedURL, true)) { + return false; + } + if (response == null || options?.ignoreVary || !response.headersList.contains("vary")) { + return true; + } + const fieldValues = getFieldValues(response.headersList.get("vary")); + for (const fieldValue of fieldValues) { + if (fieldValue === "*") { + return false; + } + const requestValue = request.headersList.get(fieldValue); + const queryValue = requestQuery.headersList.get(fieldValue); + if (requestValue !== queryValue) { + return false; + } + } + return true; + } + }; + Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: "Cache", + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty + }); + var cacheQueryOptionConverters = [ + { + key: "ignoreSearch", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "ignoreMethod", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "ignoreVary", + converter: webidl.converters.boolean, + defaultValue: false + } + ]; + webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters); + webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: "cacheName", + converter: webidl.converters.DOMString + } + ]); + webidl.converters.Response = webidl.interfaceConverter(Response); + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.RequestInfo + ); + module2.exports = { + Cache + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/cachestorage.js +var require_cachestorage = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cache/cachestorage.js"(exports2, module2) { + "use strict"; + var { kConstruct } = require_symbols4(); + var { Cache } = require_cache(); + var { webidl } = require_webidl(); + var { kEnumerableProperty } = require_util(); + var CacheStorage = class _CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map} + */ + async has(cacheName) { + webidl.brandCheck(this, _CacheStorage); + webidl.argumentLengthCheck(arguments, 1, { header: "CacheStorage.has" }); + cacheName = webidl.converters.DOMString(cacheName); + return this.#caches.has(cacheName); + } + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open(cacheName) { + webidl.brandCheck(this, _CacheStorage); + webidl.argumentLengthCheck(arguments, 1, { header: "CacheStorage.open" }); + cacheName = webidl.converters.DOMString(cacheName); + if (this.#caches.has(cacheName)) { + const cache2 = this.#caches.get(cacheName); + return new Cache(kConstruct, cache2); + } + const cache = []; + this.#caches.set(cacheName, cache); + return new Cache(kConstruct, cache); + } + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete(cacheName) { + webidl.brandCheck(this, _CacheStorage); + webidl.argumentLengthCheck(arguments, 1, { header: "CacheStorage.delete" }); + cacheName = webidl.converters.DOMString(cacheName); + return this.#caches.delete(cacheName); + } + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {string[]} + */ + async keys() { + webidl.brandCheck(this, _CacheStorage); + const keys = this.#caches.keys(); + return [...keys]; + } + }; + Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: "CacheStorage", + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty + }); + module2.exports = { + CacheStorage + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/constants.js +var require_constants4 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/constants.js"(exports2, module2) { + "use strict"; + var maxAttributeValueSize = 1024; + var maxNameValuePairSize = 4096; + module2.exports = { + maxAttributeValueSize, + maxNameValuePairSize + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/util.js +var require_util6 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/util.js"(exports2, module2) { + "use strict"; + function isCTLExcludingHtab(value) { + if (value.length === 0) { + return false; + } + for (const char of value) { + const code2 = char.charCodeAt(0); + if (code2 >= 0 || code2 <= 8 || (code2 >= 10 || code2 <= 31) || code2 === 127) { + return false; + } + } + } + function validateCookieName(name) { + for (const char of name) { + const code2 = char.charCodeAt(0); + if (code2 <= 32 || code2 > 127 || char === "(" || char === ")" || char === ">" || char === "<" || char === "@" || char === "," || char === ";" || char === ":" || char === "\\" || char === '"' || char === "/" || char === "[" || char === "]" || char === "?" || char === "=" || char === "{" || char === "}") { + throw new Error("Invalid cookie name"); + } + } + } + function validateCookieValue(value) { + for (const char of value) { + const code2 = char.charCodeAt(0); + if (code2 < 33 || // exclude CTLs (0-31) + code2 === 34 || code2 === 44 || code2 === 59 || code2 === 92 || code2 > 126) { + throw new Error("Invalid header value"); + } + } + } + function validateCookiePath(path12) { + for (const char of path12) { + const code2 = char.charCodeAt(0); + if (code2 < 33 || char === ";") { + throw new Error("Invalid cookie path"); + } + } + } + function validateCookieDomain(domain) { + if (domain.startsWith("-") || domain.endsWith(".") || domain.endsWith("-")) { + throw new Error("Invalid cookie domain"); + } + } + function toIMFDate(date) { + if (typeof date === "number") { + date = new Date(date); + } + const days = [ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + ]; + const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ]; + const dayName = days[date.getUTCDay()]; + const day = date.getUTCDate().toString().padStart(2, "0"); + const month = months[date.getUTCMonth()]; + const year = date.getUTCFullYear(); + const hour = date.getUTCHours().toString().padStart(2, "0"); + const minute = date.getUTCMinutes().toString().padStart(2, "0"); + const second = date.getUTCSeconds().toString().padStart(2, "0"); + return `${dayName}, ${day} ${month} ${year} ${hour}:${minute}:${second} GMT`; + } + function validateCookieMaxAge(maxAge) { + if (maxAge < 0) { + throw new Error("Invalid cookie max-age"); + } + } + function stringify(cookie) { + if (cookie.name.length === 0) { + return null; + } + validateCookieName(cookie.name); + validateCookieValue(cookie.value); + const out = [`${cookie.name}=${cookie.value}`]; + if (cookie.name.startsWith("__Secure-")) { + cookie.secure = true; + } + if (cookie.name.startsWith("__Host-")) { + cookie.secure = true; + cookie.domain = null; + cookie.path = "/"; + } + if (cookie.secure) { + out.push("Secure"); + } + if (cookie.httpOnly) { + out.push("HttpOnly"); + } + if (typeof cookie.maxAge === "number") { + validateCookieMaxAge(cookie.maxAge); + out.push(`Max-Age=${cookie.maxAge}`); + } + if (cookie.domain) { + validateCookieDomain(cookie.domain); + out.push(`Domain=${cookie.domain}`); + } + if (cookie.path) { + validateCookiePath(cookie.path); + out.push(`Path=${cookie.path}`); + } + if (cookie.expires && cookie.expires.toString() !== "Invalid Date") { + out.push(`Expires=${toIMFDate(cookie.expires)}`); + } + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`); + } + for (const part of cookie.unparsed) { + if (!part.includes("=")) { + throw new Error("Invalid unparsed"); + } + const [key, ...value] = part.split("="); + out.push(`${key.trim()}=${value.join("=")}`); + } + return out.join("; "); + } + module2.exports = { + isCTLExcludingHtab, + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/parse.js +var require_parse = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/parse.js"(exports2, module2) { + "use strict"; + var { maxNameValuePairSize, maxAttributeValueSize } = require_constants4(); + var { isCTLExcludingHtab } = require_util6(); + var { collectASequenceOfCodePointsFast } = require_dataURL(); + var assert = require("assert"); + function parseSetCookie(header) { + if (isCTLExcludingHtab(header)) { + return null; + } + let nameValuePair = ""; + let unparsedAttributes = ""; + let name = ""; + let value = ""; + if (header.includes(";")) { + const position = { position: 0 }; + nameValuePair = collectASequenceOfCodePointsFast(";", header, position); + unparsedAttributes = header.slice(position.position); + } else { + nameValuePair = header; + } + if (!nameValuePair.includes("=")) { + value = nameValuePair; + } else { + const position = { position: 0 }; + name = collectASequenceOfCodePointsFast( + "=", + nameValuePair, + position + ); + value = nameValuePair.slice(position.position + 1); + } + name = name.trim(); + value = value.trim(); + if (name.length + value.length > maxNameValuePairSize) { + return null; + } + return { + name, + value, + ...parseUnparsedAttributes(unparsedAttributes) + }; + } + function parseUnparsedAttributes(unparsedAttributes, cookieAttributeList = {}) { + if (unparsedAttributes.length === 0) { + return cookieAttributeList; + } + assert(unparsedAttributes[0] === ";"); + unparsedAttributes = unparsedAttributes.slice(1); + let cookieAv = ""; + if (unparsedAttributes.includes(";")) { + cookieAv = collectASequenceOfCodePointsFast( + ";", + unparsedAttributes, + { position: 0 } + ); + unparsedAttributes = unparsedAttributes.slice(cookieAv.length); + } else { + cookieAv = unparsedAttributes; + unparsedAttributes = ""; + } + let attributeName = ""; + let attributeValue = ""; + if (cookieAv.includes("=")) { + const position = { position: 0 }; + attributeName = collectASequenceOfCodePointsFast( + "=", + cookieAv, + position + ); + attributeValue = cookieAv.slice(position.position + 1); + } else { + attributeName = cookieAv; + } + attributeName = attributeName.trim(); + attributeValue = attributeValue.trim(); + if (attributeValue.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + const attributeNameLowercase = attributeName.toLowerCase(); + if (attributeNameLowercase === "expires") { + const expiryTime = new Date(attributeValue); + cookieAttributeList.expires = expiryTime; + } else if (attributeNameLowercase === "max-age") { + const charCode = attributeValue.charCodeAt(0); + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + if (!/^\d+$/.test(attributeValue)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + const deltaSeconds = Number(attributeValue); + cookieAttributeList.maxAge = deltaSeconds; + } else if (attributeNameLowercase === "domain") { + let cookieDomain = attributeValue; + if (cookieDomain[0] === ".") { + cookieDomain = cookieDomain.slice(1); + } + cookieDomain = cookieDomain.toLowerCase(); + cookieAttributeList.domain = cookieDomain; + } else if (attributeNameLowercase === "path") { + let cookiePath = ""; + if (attributeValue.length === 0 || attributeValue[0] !== "/") { + cookiePath = "/"; + } else { + cookiePath = attributeValue; + } + cookieAttributeList.path = cookiePath; + } else if (attributeNameLowercase === "secure") { + cookieAttributeList.secure = true; + } else if (attributeNameLowercase === "httponly") { + cookieAttributeList.httpOnly = true; + } else if (attributeNameLowercase === "samesite") { + let enforcement = "Default"; + const attributeValueLowercase = attributeValue.toLowerCase(); + if (attributeValueLowercase.includes("none")) { + enforcement = "None"; + } + if (attributeValueLowercase.includes("strict")) { + enforcement = "Strict"; + } + if (attributeValueLowercase.includes("lax")) { + enforcement = "Lax"; + } + cookieAttributeList.sameSite = enforcement; + } else { + cookieAttributeList.unparsed ??= []; + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); + } + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + module2.exports = { + parseSetCookie, + parseUnparsedAttributes + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/index.js +var require_cookies = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/cookies/index.js"(exports2, module2) { + "use strict"; + var { parseSetCookie } = require_parse(); + var { stringify } = require_util6(); + var { webidl } = require_webidl(); + var { Headers } = require_headers(); + function getCookies(headers) { + webidl.argumentLengthCheck(arguments, 1, { header: "getCookies" }); + webidl.brandCheck(headers, Headers, { strict: false }); + const cookie = headers.get("cookie"); + const out = {}; + if (!cookie) { + return out; + } + for (const piece of cookie.split(";")) { + const [name, ...value] = piece.split("="); + out[name.trim()] = value.join("="); + } + return out; + } + function deleteCookie(headers, name, attributes) { + webidl.argumentLengthCheck(arguments, 2, { header: "deleteCookie" }); + webidl.brandCheck(headers, Headers, { strict: false }); + name = webidl.converters.DOMString(name); + attributes = webidl.converters.DeleteCookieAttributes(attributes); + setCookie(headers, { + name, + value: "", + expires: /* @__PURE__ */ new Date(0), + ...attributes + }); + } + function getSetCookies(headers) { + webidl.argumentLengthCheck(arguments, 1, { header: "getSetCookies" }); + webidl.brandCheck(headers, Headers, { strict: false }); + const cookies = headers.getSetCookie(); + if (!cookies) { + return []; + } + return cookies.map((pair) => parseSetCookie(pair)); + } + function setCookie(headers, cookie) { + webidl.argumentLengthCheck(arguments, 2, { header: "setCookie" }); + webidl.brandCheck(headers, Headers, { strict: false }); + cookie = webidl.converters.Cookie(cookie); + const str = stringify(cookie); + if (str) { + headers.append("Set-Cookie", stringify(cookie)); + } + } + webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "path", + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "domain", + defaultValue: null + } + ]); + webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: "name" + }, + { + converter: webidl.converters.DOMString, + key: "value" + }, + { + converter: webidl.nullableConverter((value) => { + if (typeof value === "number") { + return webidl.converters["unsigned long long"](value); + } + return new Date(value); + }), + key: "expires", + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters["long long"]), + key: "maxAge", + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "domain", + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "path", + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: "secure", + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: "httpOnly", + defaultValue: null + }, + { + converter: webidl.converters.USVString, + key: "sameSite", + allowedValues: ["Strict", "Lax", "None"] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: "unparsed", + defaultValue: [] + } + ]); + module2.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/constants.js +var require_constants5 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/constants.js"(exports2, module2) { + "use strict"; + var uid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + var staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false + }; + var states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 + }; + var opcodes = { + CONTINUATION: 0, + TEXT: 1, + BINARY: 2, + CLOSE: 8, + PING: 9, + PONG: 10 + }; + var maxUnsigned16Bit = 2 ** 16 - 1; + var parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 + }; + var emptyBuffer = Buffer.allocUnsafe(0); + module2.exports = { + uid, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/symbols.js +var require_symbols5 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kWebSocketURL: /* @__PURE__ */ Symbol("url"), + kReadyState: /* @__PURE__ */ Symbol("ready state"), + kController: /* @__PURE__ */ Symbol("controller"), + kResponse: /* @__PURE__ */ Symbol("response"), + kBinaryType: /* @__PURE__ */ Symbol("binary type"), + kSentClose: /* @__PURE__ */ Symbol("sent close"), + kReceivedClose: /* @__PURE__ */ Symbol("received close"), + kByteParser: /* @__PURE__ */ Symbol("byte parser") + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/events.js +var require_events = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/events.js"(exports2, module2) { + "use strict"; + var { webidl } = require_webidl(); + var { kEnumerableProperty } = require_util(); + var { MessagePort } = require("worker_threads"); + var MessageEvent = class _MessageEvent extends Event { + #eventInit; + constructor(type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: "MessageEvent constructor" }); + type = webidl.converters.DOMString(type); + eventInitDict = webidl.converters.MessageEventInit(eventInitDict); + super(type, eventInitDict); + this.#eventInit = eventInitDict; + } + get data() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.data; + } + get origin() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.origin; + } + get lastEventId() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.lastEventId; + } + get source() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.source; + } + get ports() { + webidl.brandCheck(this, _MessageEvent); + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports); + } + return this.#eventInit.ports; + } + initMessageEvent(type, bubbles = false, cancelable = false, data = null, origin = "", lastEventId = "", source = null, ports = []) { + webidl.brandCheck(this, _MessageEvent); + webidl.argumentLengthCheck(arguments, 1, { header: "MessageEvent.initMessageEvent" }); + return new _MessageEvent(type, { + bubbles, + cancelable, + data, + origin, + lastEventId, + source, + ports + }); + } + }; + var CloseEvent = class _CloseEvent extends Event { + #eventInit; + constructor(type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: "CloseEvent constructor" }); + type = webidl.converters.DOMString(type); + eventInitDict = webidl.converters.CloseEventInit(eventInitDict); + super(type, eventInitDict); + this.#eventInit = eventInitDict; + } + get wasClean() { + webidl.brandCheck(this, _CloseEvent); + return this.#eventInit.wasClean; + } + get code() { + webidl.brandCheck(this, _CloseEvent); + return this.#eventInit.code; + } + get reason() { + webidl.brandCheck(this, _CloseEvent); + return this.#eventInit.reason; + } + }; + var ErrorEvent = class _ErrorEvent extends Event { + #eventInit; + constructor(type, eventInitDict) { + webidl.argumentLengthCheck(arguments, 1, { header: "ErrorEvent constructor" }); + super(type, eventInitDict); + type = webidl.converters.DOMString(type); + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}); + this.#eventInit = eventInitDict; + } + get message() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.message; + } + get filename() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.filename; + } + get lineno() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.lineno; + } + get colno() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.colno; + } + get error() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.error; + } + }; + Object.defineProperties(MessageEvent.prototype, { + [Symbol.toStringTag]: { + value: "MessageEvent", + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty + }); + Object.defineProperties(CloseEvent.prototype, { + [Symbol.toStringTag]: { + value: "CloseEvent", + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty + }); + Object.defineProperties(ErrorEvent.prototype, { + [Symbol.toStringTag]: { + value: "ErrorEvent", + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty + }); + webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort); + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.MessagePort + ); + var eventInit = [ + { + key: "bubbles", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "cancelable", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "composed", + converter: webidl.converters.boolean, + defaultValue: false + } + ]; + webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: "data", + converter: webidl.converters.any, + defaultValue: null + }, + { + key: "origin", + converter: webidl.converters.USVString, + defaultValue: "" + }, + { + key: "lastEventId", + converter: webidl.converters.DOMString, + defaultValue: "" + }, + { + key: "source", + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: null + }, + { + key: "ports", + converter: webidl.converters["sequence"], + get defaultValue() { + return []; + } + } + ]); + webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: "wasClean", + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: "code", + converter: webidl.converters["unsigned short"], + defaultValue: 0 + }, + { + key: "reason", + converter: webidl.converters.USVString, + defaultValue: "" + } + ]); + webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: "message", + converter: webidl.converters.DOMString, + defaultValue: "" + }, + { + key: "filename", + converter: webidl.converters.USVString, + defaultValue: "" + }, + { + key: "lineno", + converter: webidl.converters["unsigned long"], + defaultValue: 0 + }, + { + key: "colno", + converter: webidl.converters["unsigned long"], + defaultValue: 0 + }, + { + key: "error", + converter: webidl.converters.any + } + ]); + module2.exports = { + MessageEvent, + CloseEvent, + ErrorEvent + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/util.js +var require_util7 = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/util.js"(exports2, module2) { + "use strict"; + var { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = require_symbols5(); + var { states, opcodes } = require_constants5(); + var { MessageEvent, ErrorEvent } = require_events(); + function isEstablished(ws) { + return ws[kReadyState] === states.OPEN; + } + function isClosing(ws) { + return ws[kReadyState] === states.CLOSING; + } + function isClosed(ws) { + return ws[kReadyState] === states.CLOSED; + } + function fireEvent(e, target, eventConstructor = Event, eventInitDict) { + const event = new eventConstructor(e, eventInitDict); + target.dispatchEvent(event); + } + function websocketMessageReceived(ws, type, data) { + if (ws[kReadyState] !== states.OPEN) { + return; + } + let dataForEvent; + if (type === opcodes.TEXT) { + try { + dataForEvent = new TextDecoder("utf-8", { fatal: true }).decode(data); + } catch { + failWebsocketConnection(ws, "Received invalid UTF-8 in text frame."); + return; + } + } else if (type === opcodes.BINARY) { + if (ws[kBinaryType] === "blob") { + dataForEvent = new Blob([data]); + } else { + dataForEvent = new Uint8Array(data).buffer; + } + } + fireEvent("message", ws, MessageEvent, { + origin: ws[kWebSocketURL].origin, + data: dataForEvent + }); + } + function isValidSubprotocol(protocol) { + if (protocol.length === 0) { + return false; + } + for (const char of protocol) { + const code2 = char.charCodeAt(0); + if (code2 < 33 || code2 > 126 || char === "(" || char === ")" || char === "<" || char === ">" || char === "@" || char === "," || char === ";" || char === ":" || char === "\\" || char === '"' || char === "/" || char === "[" || char === "]" || char === "?" || char === "=" || char === "{" || char === "}" || code2 === 32 || // SP + code2 === 9) { + return false; + } + } + return true; + } + function isValidStatusCode(code2) { + if (code2 >= 1e3 && code2 < 1015) { + return code2 !== 1004 && // reserved + code2 !== 1005 && // "MUST NOT be set as a status code" + code2 !== 1006; + } + return code2 >= 3e3 && code2 <= 4999; + } + function failWebsocketConnection(ws, reason) { + const { [kController]: controller, [kResponse]: response } = ws; + controller.abort(); + if (response?.socket && !response.socket.destroyed) { + response.socket.destroy(); + } + if (reason) { + fireEvent("error", ws, ErrorEvent, { + error: new Error(reason) + }); + } + } + module2.exports = { + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + failWebsocketConnection, + websocketMessageReceived + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/connection.js +var require_connection = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/connection.js"(exports2, module2) { + "use strict"; + var diagnosticsChannel = require("diagnostics_channel"); + var { uid, states } = require_constants5(); + var { + kReadyState, + kSentClose, + kByteParser, + kReceivedClose + } = require_symbols5(); + var { fireEvent, failWebsocketConnection } = require_util7(); + var { CloseEvent } = require_events(); + var { makeRequest } = require_request2(); + var { fetching } = require_fetch(); + var { Headers } = require_headers(); + var { getGlobalDispatcher } = require_global2(); + var { kHeadersList } = require_symbols(); + var channels = {}; + channels.open = diagnosticsChannel.channel("undici:websocket:open"); + channels.close = diagnosticsChannel.channel("undici:websocket:close"); + channels.socketError = diagnosticsChannel.channel("undici:websocket:socket_error"); + var crypto; + try { + crypto = require("crypto"); + } catch { + } + function establishWebSocketConnection(url, protocols, ws, onEstablish, options) { + const requestURL = url; + requestURL.protocol = url.protocol === "ws:" ? "http:" : "https:"; + const request = makeRequest({ + urlList: [requestURL], + serviceWorkers: "none", + referrer: "no-referrer", + mode: "websocket", + credentials: "include", + cache: "no-store", + redirect: "error" + }); + if (options.headers) { + const headersList = new Headers(options.headers)[kHeadersList]; + request.headersList = headersList; + } + const keyValue = crypto.randomBytes(16).toString("base64"); + request.headersList.append("sec-websocket-key", keyValue); + request.headersList.append("sec-websocket-version", "13"); + for (const protocol of protocols) { + request.headersList.append("sec-websocket-protocol", protocol); + } + const permessageDeflate = ""; + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options.dispatcher ?? getGlobalDispatcher(), + processResponse(response) { + if (response.type === "error" || response.status !== 101) { + failWebsocketConnection(ws, "Received network error or non-101 status code."); + return; + } + if (protocols.length !== 0 && !response.headersList.get("Sec-WebSocket-Protocol")) { + failWebsocketConnection(ws, "Server did not respond with sent protocols."); + return; + } + if (response.headersList.get("Upgrade")?.toLowerCase() !== "websocket") { + failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".'); + return; + } + if (response.headersList.get("Connection")?.toLowerCase() !== "upgrade") { + failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".'); + return; + } + const secWSAccept = response.headersList.get("Sec-WebSocket-Accept"); + const digest = crypto.createHash("sha1").update(keyValue + uid).digest("base64"); + if (secWSAccept !== digest) { + failWebsocketConnection(ws, "Incorrect hash received in Sec-WebSocket-Accept header."); + return; + } + const secExtension = response.headersList.get("Sec-WebSocket-Extensions"); + if (secExtension !== null && secExtension !== permessageDeflate) { + failWebsocketConnection(ws, "Received different permessage-deflate than the one set."); + return; + } + const secProtocol = response.headersList.get("Sec-WebSocket-Protocol"); + if (secProtocol !== null && secProtocol !== request.headersList.get("Sec-WebSocket-Protocol")) { + failWebsocketConnection(ws, "Protocol was not set in the opening handshake."); + return; + } + response.socket.on("data", onSocketData); + response.socket.on("close", onSocketClose); + response.socket.on("error", onSocketError); + if (channels.open.hasSubscribers) { + channels.open.publish({ + address: response.socket.address(), + protocol: secProtocol, + extensions: secExtension + }); + } + onEstablish(response); + } + }); + return controller; + } + function onSocketData(chunk) { + if (!this.ws[kByteParser].write(chunk)) { + this.pause(); + } + } + function onSocketClose() { + const { ws } = this; + const wasClean = ws[kSentClose] && ws[kReceivedClose]; + let code2 = 1005; + let reason = ""; + const result = ws[kByteParser].closingInfo; + if (result) { + code2 = result.code ?? 1005; + reason = result.reason; + } else if (!ws[kSentClose]) { + code2 = 1006; + } + ws[kReadyState] = states.CLOSED; + fireEvent("close", ws, CloseEvent, { + wasClean, + code: code2, + reason + }); + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: ws, + code: code2, + reason + }); + } + } + function onSocketError(error) { + const { ws } = this; + ws[kReadyState] = states.CLOSING; + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(error); + } + this.destroy(); + } + module2.exports = { + establishWebSocketConnection + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/frame.js +var require_frame = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/frame.js"(exports2, module2) { + "use strict"; + var { maxUnsigned16Bit } = require_constants5(); + var crypto; + try { + crypto = require("crypto"); + } catch { + } + var WebsocketFrameSend = class { + /** + * @param {Buffer|undefined} data + */ + constructor(data) { + this.frameData = data; + this.maskKey = crypto.randomBytes(4); + } + createFrame(opcode) { + const bodyLength = this.frameData?.byteLength ?? 0; + let payloadLength = bodyLength; + let offset = 6; + if (bodyLength > maxUnsigned16Bit) { + offset += 8; + payloadLength = 127; + } else if (bodyLength > 125) { + offset += 2; + payloadLength = 126; + } + const buffer = Buffer.allocUnsafe(bodyLength + offset); + buffer[0] = buffer[1] = 0; + buffer[0] |= 128; + buffer[0] = (buffer[0] & 240) + opcode; + buffer[offset - 4] = this.maskKey[0]; + buffer[offset - 3] = this.maskKey[1]; + buffer[offset - 2] = this.maskKey[2]; + buffer[offset - 1] = this.maskKey[3]; + buffer[1] = payloadLength; + if (payloadLength === 126) { + buffer.writeUInt16BE(bodyLength, 2); + } else if (payloadLength === 127) { + buffer[2] = buffer[3] = 0; + buffer.writeUIntBE(bodyLength, 4, 6); + } + buffer[1] |= 128; + for (let i2 = 0; i2 < bodyLength; i2++) { + buffer[offset + i2] = this.frameData[i2] ^ this.maskKey[i2 % 4]; + } + return buffer; + } + }; + module2.exports = { + WebsocketFrameSend + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/receiver.js +var require_receiver = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/receiver.js"(exports2, module2) { + "use strict"; + var { Writable: Writable4 } = require("stream"); + var diagnosticsChannel = require("diagnostics_channel"); + var { parserStates, opcodes, states, emptyBuffer } = require_constants5(); + var { kReadyState, kSentClose, kResponse, kReceivedClose } = require_symbols5(); + var { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = require_util7(); + var { WebsocketFrameSend } = require_frame(); + var channels = {}; + channels.ping = diagnosticsChannel.channel("undici:websocket:ping"); + channels.pong = diagnosticsChannel.channel("undici:websocket:pong"); + var ByteParser = class extends Writable4 { + #buffers = []; + #byteOffset = 0; + #state = parserStates.INFO; + #info = {}; + #fragments = []; + constructor(ws) { + super(); + this.ws = ws; + } + /** + * @param {Buffer} chunk + * @param {() => void} callback + */ + _write(chunk, _, callback) { + this.#buffers.push(chunk); + this.#byteOffset += chunk.length; + this.run(callback); + } + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run(callback) { + while (true) { + if (this.#state === parserStates.INFO) { + if (this.#byteOffset < 2) { + return callback(); + } + const buffer = this.consume(2); + this.#info.fin = (buffer[0] & 128) !== 0; + this.#info.opcode = buffer[0] & 15; + this.#info.originalOpcode ??= this.#info.opcode; + this.#info.fragmented = !this.#info.fin && this.#info.opcode !== opcodes.CONTINUATION; + if (this.#info.fragmented && this.#info.opcode !== opcodes.BINARY && this.#info.opcode !== opcodes.TEXT) { + failWebsocketConnection(this.ws, "Invalid frame type was fragmented."); + return; + } + const payloadLength = buffer[1] & 127; + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength; + this.#state = parserStates.READ_DATA; + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16; + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64; + } + if (this.#info.fragmented && payloadLength > 125) { + failWebsocketConnection(this.ws, "Fragmented frame exceeded 125 bytes."); + return; + } else if ((this.#info.opcode === opcodes.PING || this.#info.opcode === opcodes.PONG || this.#info.opcode === opcodes.CLOSE) && payloadLength > 125) { + failWebsocketConnection(this.ws, "Payload length for control frame exceeded 125 bytes."); + return; + } else if (this.#info.opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.ws, "Received close frame with a 1-byte body."); + return; + } + const body = this.consume(payloadLength); + this.#info.closeInfo = this.parseCloseBody(false, body); + if (!this.ws[kSentClose]) { + const body2 = Buffer.allocUnsafe(2); + body2.writeUInt16BE(this.#info.closeInfo.code, 0); + const closeFrame = new WebsocketFrameSend(body2); + this.ws[kResponse].socket.write( + closeFrame.createFrame(opcodes.CLOSE), + (err) => { + if (!err) { + this.ws[kSentClose] = true; + } + } + ); + } + this.ws[kReadyState] = states.CLOSING; + this.ws[kReceivedClose] = true; + this.end(); + return; + } else if (this.#info.opcode === opcodes.PING) { + const body = this.consume(payloadLength); + if (!this.ws[kReceivedClose]) { + const frame = new WebsocketFrameSend(body); + this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)); + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body + }); + } + } + this.#state = parserStates.INFO; + if (this.#byteOffset > 0) { + continue; + } else { + callback(); + return; + } + } else if (this.#info.opcode === opcodes.PONG) { + const body = this.consume(payloadLength); + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body + }); + } + if (this.#byteOffset > 0) { + continue; + } else { + callback(); + return; + } + } + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback(); + } + const buffer = this.consume(2); + this.#info.payloadLength = buffer.readUInt16BE(0); + this.#state = parserStates.READ_DATA; + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback(); + } + const buffer = this.consume(8); + const upper = buffer.readUInt32BE(0); + if (upper > 2 ** 31 - 1) { + failWebsocketConnection(this.ws, "Received payload length > 2^31 bytes."); + return; + } + const lower = buffer.readUInt32BE(4); + this.#info.payloadLength = (upper << 8) + lower; + this.#state = parserStates.READ_DATA; + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + return callback(); + } else if (this.#byteOffset >= this.#info.payloadLength) { + const body = this.consume(this.#info.payloadLength); + this.#fragments.push(body); + if (!this.#info.fragmented || this.#info.fin && this.#info.opcode === opcodes.CONTINUATION) { + const fullMessage = Buffer.concat(this.#fragments); + websocketMessageReceived(this.ws, this.#info.originalOpcode, fullMessage); + this.#info = {}; + this.#fragments.length = 0; + } + this.#state = parserStates.INFO; + } + } + if (this.#byteOffset > 0) { + continue; + } else { + callback(); + break; + } + } + } + /** + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer|null} + */ + consume(n2) { + if (n2 > this.#byteOffset) { + return null; + } else if (n2 === 0) { + return emptyBuffer; + } + if (this.#buffers[0].length === n2) { + this.#byteOffset -= this.#buffers[0].length; + return this.#buffers.shift(); + } + const buffer = Buffer.allocUnsafe(n2); + let offset = 0; + while (offset !== n2) { + const next = this.#buffers[0]; + const { length } = next; + if (length + offset === n2) { + buffer.set(this.#buffers.shift(), offset); + break; + } else if (length + offset > n2) { + buffer.set(next.subarray(0, n2 - offset), offset); + this.#buffers[0] = next.subarray(n2 - offset); + break; + } else { + buffer.set(this.#buffers.shift(), offset); + offset += next.length; + } + } + this.#byteOffset -= n2; + return buffer; + } + parseCloseBody(onlyCode, data) { + let code2; + if (data.length >= 2) { + code2 = data.readUInt16BE(0); + } + if (onlyCode) { + if (!isValidStatusCode(code2)) { + return null; + } + return { code: code2 }; + } + let reason = data.subarray(2); + if (reason[0] === 239 && reason[1] === 187 && reason[2] === 191) { + reason = reason.subarray(3); + } + if (code2 !== void 0 && !isValidStatusCode(code2)) { + return null; + } + try { + reason = new TextDecoder("utf-8", { fatal: true }).decode(reason); + } catch { + return null; + } + return { code: code2, reason }; + } + get closingInfo() { + return this.#info.closeInfo; + } + }; + module2.exports = { + ByteParser + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/websocket.js +var require_websocket = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/lib/websocket/websocket.js"(exports2, module2) { + "use strict"; + var { webidl } = require_webidl(); + var { DOMException: DOMException2 } = require_constants2(); + var { URLSerializer } = require_dataURL(); + var { getGlobalOrigin } = require_global(); + var { staticPropertyDescriptors, states, opcodes, emptyBuffer } = require_constants5(); + var { + kWebSocketURL, + kReadyState, + kController, + kBinaryType, + kResponse, + kSentClose, + kByteParser + } = require_symbols5(); + var { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = require_util7(); + var { establishWebSocketConnection } = require_connection(); + var { WebsocketFrameSend } = require_frame(); + var { ByteParser } = require_receiver(); + var { kEnumerableProperty, isBlobLike } = require_util(); + var { getGlobalDispatcher } = require_global2(); + var { types } = require("util"); + var experimentalWarned = false; + var WebSocket = class _WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null + }; + #bufferedAmount = 0; + #protocol = ""; + #extensions = ""; + /** + * @param {string} url + * @param {string|string[]} protocols + */ + constructor(url, protocols = []) { + super(); + webidl.argumentLengthCheck(arguments, 1, { header: "WebSocket constructor" }); + if (!experimentalWarned) { + experimentalWarned = true; + process.emitWarning("WebSockets are experimental, expect them to change at any time.", { + code: "UNDICI-WS" + }); + } + const options = webidl.converters["DOMString or sequence or WebSocketInit"](protocols); + url = webidl.converters.USVString(url); + protocols = options.protocols; + const baseURL = getGlobalOrigin(); + let urlRecord; + try { + urlRecord = new URL(url, baseURL); + } catch (e) { + throw new DOMException2(e, "SyntaxError"); + } + if (urlRecord.protocol === "http:") { + urlRecord.protocol = "ws:"; + } else if (urlRecord.protocol === "https:") { + urlRecord.protocol = "wss:"; + } + if (urlRecord.protocol !== "ws:" && urlRecord.protocol !== "wss:") { + throw new DOMException2( + `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, + "SyntaxError" + ); + } + if (urlRecord.hash || urlRecord.href.endsWith("#")) { + throw new DOMException2("Got fragment", "SyntaxError"); + } + if (typeof protocols === "string") { + protocols = [protocols]; + } + if (protocols.length !== new Set(protocols.map((p) => p.toLowerCase())).size) { + throw new DOMException2("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + if (protocols.length > 0 && !protocols.every((p) => isValidSubprotocol(p))) { + throw new DOMException2("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + this[kWebSocketURL] = new URL(urlRecord.href); + this[kController] = establishWebSocketConnection( + urlRecord, + protocols, + this, + (response) => this.#onConnectionEstablished(response), + options + ); + this[kReadyState] = _WebSocket.CONNECTING; + this[kBinaryType] = "blob"; + } + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason + */ + close(code2 = void 0, reason = void 0) { + webidl.brandCheck(this, _WebSocket); + if (code2 !== void 0) { + code2 = webidl.converters["unsigned short"](code2, { clamp: true }); + } + if (reason !== void 0) { + reason = webidl.converters.USVString(reason); + } + if (code2 !== void 0) { + if (code2 !== 1e3 && (code2 < 3e3 || code2 > 4999)) { + throw new DOMException2("invalid code", "InvalidAccessError"); + } + } + let reasonByteLength = 0; + if (reason !== void 0) { + reasonByteLength = Buffer.byteLength(reason); + if (reasonByteLength > 123) { + throw new DOMException2( + `Reason must be less than 123 bytes; received ${reasonByteLength}`, + "SyntaxError" + ); + } + } + if (this[kReadyState] === _WebSocket.CLOSING || this[kReadyState] === _WebSocket.CLOSED) { + } else if (!isEstablished(this)) { + failWebsocketConnection(this, "Connection was closed before it was established."); + this[kReadyState] = _WebSocket.CLOSING; + } else if (!isClosing(this)) { + const frame = new WebsocketFrameSend(); + if (code2 !== void 0 && reason === void 0) { + frame.frameData = Buffer.allocUnsafe(2); + frame.frameData.writeUInt16BE(code2, 0); + } else if (code2 !== void 0 && reason !== void 0) { + frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength); + frame.frameData.writeUInt16BE(code2, 0); + frame.frameData.write(reason, 2, "utf-8"); + } else { + frame.frameData = emptyBuffer; + } + const socket = this[kResponse].socket; + socket.write(frame.createFrame(opcodes.CLOSE), (err) => { + if (!err) { + this[kSentClose] = true; + } + }); + this[kReadyState] = states.CLOSING; + } else { + this[kReadyState] = _WebSocket.CLOSING; + } + } + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send(data) { + webidl.brandCheck(this, _WebSocket); + webidl.argumentLengthCheck(arguments, 1, { header: "WebSocket.send" }); + data = webidl.converters.WebSocketSendData(data); + if (this[kReadyState] === _WebSocket.CONNECTING) { + throw new DOMException2("Sent before connected.", "InvalidStateError"); + } + if (!isEstablished(this) || isClosing(this)) { + return; + } + const socket = this[kResponse].socket; + if (typeof data === "string") { + const value = Buffer.from(data); + const frame = new WebsocketFrameSend(value); + const buffer = frame.createFrame(opcodes.TEXT); + this.#bufferedAmount += value.byteLength; + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength; + }); + } else if (types.isArrayBuffer(data)) { + const value = Buffer.from(data); + const frame = new WebsocketFrameSend(value); + const buffer = frame.createFrame(opcodes.BINARY); + this.#bufferedAmount += value.byteLength; + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength; + }); + } else if (ArrayBuffer.isView(data)) { + const ab = Buffer.from(data, data.byteOffset, data.byteLength); + const frame = new WebsocketFrameSend(ab); + const buffer = frame.createFrame(opcodes.BINARY); + this.#bufferedAmount += ab.byteLength; + socket.write(buffer, () => { + this.#bufferedAmount -= ab.byteLength; + }); + } else if (isBlobLike(data)) { + const frame = new WebsocketFrameSend(); + data.arrayBuffer().then((ab) => { + const value = Buffer.from(ab); + frame.frameData = value; + const buffer = frame.createFrame(opcodes.BINARY); + this.#bufferedAmount += value.byteLength; + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength; + }); + }); + } + } + get readyState() { + webidl.brandCheck(this, _WebSocket); + return this[kReadyState]; + } + get bufferedAmount() { + webidl.brandCheck(this, _WebSocket); + return this.#bufferedAmount; + } + get url() { + webidl.brandCheck(this, _WebSocket); + return URLSerializer(this[kWebSocketURL]); + } + get extensions() { + webidl.brandCheck(this, _WebSocket); + return this.#extensions; + } + get protocol() { + webidl.brandCheck(this, _WebSocket); + return this.#protocol; + } + get onopen() { + webidl.brandCheck(this, _WebSocket); + return this.#events.open; + } + set onopen(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.open) { + this.removeEventListener("open", this.#events.open); + } + if (typeof fn === "function") { + this.#events.open = fn; + this.addEventListener("open", fn); + } else { + this.#events.open = null; + } + } + get onerror() { + webidl.brandCheck(this, _WebSocket); + return this.#events.error; + } + set onerror(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.error) { + this.removeEventListener("error", this.#events.error); + } + if (typeof fn === "function") { + this.#events.error = fn; + this.addEventListener("error", fn); + } else { + this.#events.error = null; + } + } + get onclose() { + webidl.brandCheck(this, _WebSocket); + return this.#events.close; + } + set onclose(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.close) { + this.removeEventListener("close", this.#events.close); + } + if (typeof fn === "function") { + this.#events.close = fn; + this.addEventListener("close", fn); + } else { + this.#events.close = null; + } + } + get onmessage() { + webidl.brandCheck(this, _WebSocket); + return this.#events.message; + } + set onmessage(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.message) { + this.removeEventListener("message", this.#events.message); + } + if (typeof fn === "function") { + this.#events.message = fn; + this.addEventListener("message", fn); + } else { + this.#events.message = null; + } + } + get binaryType() { + webidl.brandCheck(this, _WebSocket); + return this[kBinaryType]; + } + set binaryType(type) { + webidl.brandCheck(this, _WebSocket); + if (type !== "blob" && type !== "arraybuffer") { + this[kBinaryType] = "blob"; + } else { + this[kBinaryType] = type; + } + } + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished(response) { + this[kResponse] = response; + const parser = new ByteParser(this); + parser.on("drain", function onParserDrain() { + this.ws[kResponse].socket.resume(); + }); + response.socket.ws = this; + this[kByteParser] = parser; + this[kReadyState] = states.OPEN; + const extensions = response.headersList.get("sec-websocket-extensions"); + if (extensions !== null) { + this.#extensions = extensions; + } + const protocol = response.headersList.get("sec-websocket-protocol"); + if (protocol !== null) { + this.#protocol = protocol; + } + fireEvent("open", this); + } + }; + WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING; + WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN; + WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING; + WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED; + Object.defineProperties(WebSocket.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "WebSocket", + writable: false, + enumerable: false, + configurable: true + } + }); + Object.defineProperties(WebSocket, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors + }); + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.DOMString + ); + webidl.converters["DOMString or sequence"] = function(V) { + if (webidl.util.Type(V) === "Object" && Symbol.iterator in V) { + return webidl.converters["sequence"](V); + } + return webidl.converters.DOMString(V); + }; + webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: "protocols", + converter: webidl.converters["DOMString or sequence"], + get defaultValue() { + return []; + } + }, + { + key: "dispatcher", + converter: (V) => V, + get defaultValue() { + return getGlobalDispatcher(); + } + }, + { + key: "headers", + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } + ]); + webidl.converters["DOMString or sequence or WebSocketInit"] = function(V) { + if (webidl.util.Type(V) === "Object" && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V); + } + return { protocols: webidl.converters["DOMString or sequence"](V) }; + }; + webidl.converters.WebSocketSendData = function(V) { + if (webidl.util.Type(V) === "Object") { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }); + } + if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { + return webidl.converters.BufferSource(V); + } + } + return webidl.converters.USVString(V); + }; + module2.exports = { + WebSocket + }; + } +}); + +// ../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/index.js +var require_undici = __commonJS({ + "../../node_modules/.pnpm/undici@5.29.0/node_modules/undici/index.js"(exports2, module2) { + "use strict"; + var Client = require_client(); + var Dispatcher = require_dispatcher(); + var errors = require_errors(); + var Pool = require_pool(); + var BalancedPool = require_balanced_pool(); + var Agent = require_agent(); + var util2 = require_util(); + var { InvalidArgumentError } = errors; + var api = require_api(); + var buildConnector = require_connect(); + var MockClient = require_mock_client(); + var MockAgent = require_mock_agent(); + var MockPool = require_mock_pool(); + var mockErrors = require_mock_errors(); + var ProxyAgent = require_proxy_agent(); + var RetryHandler = require_RetryHandler(); + var { getGlobalDispatcher, setGlobalDispatcher } = require_global2(); + var DecoratorHandler = require_DecoratorHandler(); + var RedirectHandler = require_RedirectHandler(); + var createRedirectInterceptor = require_redirectInterceptor(); + var hasCrypto; + try { + require("crypto"); + hasCrypto = true; + } catch { + hasCrypto = false; + } + Object.assign(Dispatcher.prototype, api); + module2.exports.Dispatcher = Dispatcher; + module2.exports.Client = Client; + module2.exports.Pool = Pool; + module2.exports.BalancedPool = BalancedPool; + module2.exports.Agent = Agent; + module2.exports.ProxyAgent = ProxyAgent; + module2.exports.RetryHandler = RetryHandler; + module2.exports.DecoratorHandler = DecoratorHandler; + module2.exports.RedirectHandler = RedirectHandler; + module2.exports.createRedirectInterceptor = createRedirectInterceptor; + module2.exports.buildConnector = buildConnector; + module2.exports.errors = errors; + function makeDispatcher(fn) { + return (url, opts, handler) => { + if (typeof opts === "function") { + handler = opts; + opts = null; + } + if (!url || typeof url !== "string" && typeof url !== "object" && !(url instanceof URL)) { + throw new InvalidArgumentError("invalid url"); + } + if (opts != null && typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (opts && opts.path != null) { + if (typeof opts.path !== "string") { + throw new InvalidArgumentError("invalid opts.path"); + } + let path12 = opts.path; + if (!opts.path.startsWith("/")) { + path12 = `/${path12}`; + } + url = new URL(util2.parseOrigin(url).origin + path12); + } else { + if (!opts) { + opts = typeof url === "object" ? url : {}; + } + url = util2.parseURL(url); + } + const { agent, dispatcher = getGlobalDispatcher() } = opts; + if (agent) { + throw new InvalidArgumentError("unsupported opts.agent. Did you mean opts.client?"); + } + return fn.call(dispatcher, { + ...opts, + origin: url.origin, + path: url.search ? `${url.pathname}${url.search}` : url.pathname, + method: opts.method || (opts.body ? "PUT" : "GET") + }, handler); + }; + } + module2.exports.setGlobalDispatcher = setGlobalDispatcher; + module2.exports.getGlobalDispatcher = getGlobalDispatcher; + if (util2.nodeMajor > 16 || util2.nodeMajor === 16 && util2.nodeMinor >= 8) { + let fetchImpl = null; + module2.exports.fetch = async function fetch(resource) { + if (!fetchImpl) { + fetchImpl = require_fetch().fetch; + } + try { + return await fetchImpl(...arguments); + } catch (err) { + if (typeof err === "object") { + Error.captureStackTrace(err, this); + } + throw err; + } + }; + module2.exports.Headers = require_headers().Headers; + module2.exports.Response = require_response().Response; + module2.exports.Request = require_request2().Request; + module2.exports.FormData = require_formdata().FormData; + module2.exports.File = require_file().File; + module2.exports.FileReader = require_filereader().FileReader; + const { setGlobalOrigin, getGlobalOrigin } = require_global(); + module2.exports.setGlobalOrigin = setGlobalOrigin; + module2.exports.getGlobalOrigin = getGlobalOrigin; + const { CacheStorage } = require_cachestorage(); + const { kConstruct } = require_symbols4(); + module2.exports.caches = new CacheStorage(kConstruct); + } + if (util2.nodeMajor >= 16) { + const { deleteCookie, getCookies, getSetCookies, setCookie } = require_cookies(); + module2.exports.deleteCookie = deleteCookie; + module2.exports.getCookies = getCookies; + module2.exports.getSetCookies = getSetCookies; + module2.exports.setCookie = setCookie; + const { parseMIMEType, serializeAMimeType } = require_dataURL(); + module2.exports.parseMIMEType = parseMIMEType; + module2.exports.serializeAMimeType = serializeAMimeType; + } + if (util2.nodeMajor >= 18 && hasCrypto) { + const { WebSocket } = require_websocket(); + module2.exports.WebSocket = WebSocket; + } + module2.exports.request = makeDispatcher(api.request); + module2.exports.stream = makeDispatcher(api.stream); + module2.exports.pipeline = makeDispatcher(api.pipeline); + module2.exports.connect = makeDispatcher(api.connect); + module2.exports.upgrade = makeDispatcher(api.upgrade); + module2.exports.MockClient = MockClient; + module2.exports.MockPool = MockPool; + module2.exports.MockAgent = MockAgent; + module2.exports.mockErrors = mockErrors; + } +}); + +// ../../node_modules/.pnpm/@actions+http-client@2.2.3/node_modules/@actions/http-client/lib/index.js +var require_lib = __commonJS({ + "../../node_modules/.pnpm/@actions+http-client@2.2.3/node_modules/@actions/http-client/lib/index.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.HttpClient = exports2.isHttps = exports2.HttpClientResponse = exports2.HttpClientError = exports2.getProxyUrl = exports2.MediaTypes = exports2.Headers = exports2.HttpCodes = void 0; + var http = __importStar(require("http")); + var https = __importStar(require("https")); + var pm = __importStar(require_proxy()); + var tunnel = __importStar(require_tunnel2()); + var undici_1 = require_undici(); + var HttpCodes; + (function(HttpCodes2) { + HttpCodes2[HttpCodes2["OK"] = 200] = "OK"; + HttpCodes2[HttpCodes2["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes2[HttpCodes2["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes2[HttpCodes2["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes2[HttpCodes2["SeeOther"] = 303] = "SeeOther"; + HttpCodes2[HttpCodes2["NotModified"] = 304] = "NotModified"; + HttpCodes2[HttpCodes2["UseProxy"] = 305] = "UseProxy"; + HttpCodes2[HttpCodes2["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes2[HttpCodes2["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes2[HttpCodes2["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes2[HttpCodes2["BadRequest"] = 400] = "BadRequest"; + HttpCodes2[HttpCodes2["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes2[HttpCodes2["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes2[HttpCodes2["Forbidden"] = 403] = "Forbidden"; + HttpCodes2[HttpCodes2["NotFound"] = 404] = "NotFound"; + HttpCodes2[HttpCodes2["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes2[HttpCodes2["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes2[HttpCodes2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes2[HttpCodes2["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes2[HttpCodes2["Conflict"] = 409] = "Conflict"; + HttpCodes2[HttpCodes2["Gone"] = 410] = "Gone"; + HttpCodes2[HttpCodes2["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes2[HttpCodes2["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes2[HttpCodes2["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes2[HttpCodes2["BadGateway"] = 502] = "BadGateway"; + HttpCodes2[HttpCodes2["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes2[HttpCodes2["GatewayTimeout"] = 504] = "GatewayTimeout"; + })(HttpCodes || (exports2.HttpCodes = HttpCodes = {})); + var Headers; + (function(Headers2) { + Headers2["Accept"] = "accept"; + Headers2["ContentType"] = "content-type"; + })(Headers || (exports2.Headers = Headers = {})); + var MediaTypes; + (function(MediaTypes2) { + MediaTypes2["ApplicationJson"] = "application/json"; + })(MediaTypes || (exports2.MediaTypes = MediaTypes = {})); + function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ""; + } + exports2.getProxyUrl = getProxyUrl; + var HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect + ]; + var HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout + ]; + var RetryableHttpVerbs = ["OPTIONS", "GET", "DELETE", "HEAD"]; + var ExponentialBackoffCeiling = 10; + var ExponentialBackoffTimeSlice = 5; + var HttpClientError = class _HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = "HttpClientError"; + this.statusCode = statusCode; + Object.setPrototypeOf(this, _HttpClientError.prototype); + } + }; + exports2.HttpClientError = HttpClientError; + var HttpClientResponse = class { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on("data", (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on("end", () => { + resolve(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on("data", (chunk) => { + chunks.push(chunk); + }); + this.message.on("end", () => { + resolve(Buffer.concat(chunks)); + }); + })); + }); + } + }; + exports2.HttpClientResponse = HttpClientResponse; + function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === "https:"; + } + exports2.isHttps = isHttps; + var HttpClient = class { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("OPTIONS", requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("GET", requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("DELETE", requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("POST", requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("PATCH", requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("PUT", requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("HEAD", requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error("Client has already been disposed."); + } + const parsedUrl = new URL(requestUrl); + let info2 = this._prepareRequest(verb, parsedUrl, headers); + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info2, data); + if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info2, data); + } else { + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && HttpRedirectCodes.includes(response.message.statusCode) && this._allowRedirects && redirectsRemaining > 0) { + const redirectUrl = response.message.headers["location"]; + if (!redirectUrl) { + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === "https:" && parsedUrl.protocol !== parsedRedirectUrl.protocol && !this._allowRedirectDowngrade) { + throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true."); + } + yield response.readBody(); + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + if (header.toLowerCase() === "authorization") { + delete headers[header]; + } + } + } + info2 = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info2, data); + redirectsRemaining--; + } + if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) { + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info2, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } else if (!res) { + reject(new Error("Unknown error")); + } else { + resolve(res); + } + } + this.requestRawWithCallback(info2, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info2, data, onResult) { + if (typeof data === "string") { + if (!info2.options.headers) { + info2.options.headers = {}; + } + info2.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8"); + } + let callbackCalled = false; + function handleResult3(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info2.httpModule.request(info2.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult3(void 0, res); + }); + let socket; + req.on("socket", (sock) => { + socket = sock; + }); + req.setTimeout(this._socketTimeout || 3 * 6e4, () => { + if (socket) { + socket.end(); + } + handleResult3(new Error(`Request timeout: ${info2.options.path}`)); + }); + req.on("error", function(err) { + handleResult3(err); + }); + if (data && typeof data === "string") { + req.write(data, "utf8"); + } + if (data && typeof data !== "string") { + data.on("close", function() { + req.end(); + }); + data.pipe(req); + } else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + getAgentDispatcher(serverUrl) { + const parsedUrl = new URL(serverUrl); + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (!useProxy) { + return; + } + return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info2 = {}; + info2.parsedUrl = requestUrl; + const usingSsl = info2.parsedUrl.protocol === "https:"; + info2.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info2.options = {}; + info2.options.host = info2.parsedUrl.hostname; + info2.options.port = info2.parsedUrl.port ? parseInt(info2.parsedUrl.port) : defaultPort; + info2.options.path = (info2.parsedUrl.pathname || "") + (info2.parsedUrl.search || ""); + info2.options.method = method; + info2.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info2.options.headers["user-agent"] = this.userAgent; + } + info2.options.agent = this._getAgent(info2.parsedUrl); + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info2.options); + } + } + return info2; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (!useProxy) { + agent = this._agent; + } + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === "https:"; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, (proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + }), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === "https:"; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + if (!agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + if (usingSsl && this._ignoreSslError) { + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _getProxyAgentDispatcher(parsedUrl, proxyUrl) { + let proxyAgent; + if (this._keepAlive) { + proxyAgent = this._proxyAgentDispatcher; + } + if (proxyAgent) { + return proxyAgent; + } + const usingSsl = parsedUrl.protocol === "https:"; + proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, (proxyUrl.username || proxyUrl.password) && { + token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString("base64")}` + })); + this._proxyAgentDispatcher = proxyAgent; + if (usingSsl && this._ignoreSslError) { + proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { + rejectUnauthorized: false + }); + } + return proxyAgent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise((resolve) => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + function dateTimeDeserializer(key, value) { + if (typeof value === "string") { + const a2 = new Date(value); + if (!isNaN(a2.valueOf())) { + return a2; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } catch (err) { + } + if (statusCode > 299) { + let msg; + if (obj && obj.message) { + msg = obj.message; + } else if (contents && contents.length > 0) { + msg = contents; + } else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } else { + resolve(response); + } + })); + }); + } + }; + exports2.HttpClient = HttpClient; + var lowercaseKeys = (obj) => Object.keys(obj).reduce((c3, k) => (c3[k.toLowerCase()] = obj[k], c3), {}); + } +}); + +// ../../node_modules/.pnpm/@actions+http-client@2.2.3/node_modules/@actions/http-client/lib/auth.js +var require_auth = __commonJS({ + "../../node_modules/.pnpm/@actions+http-client@2.2.3/node_modules/@actions/http-client/lib/auth.js"(exports2) { + "use strict"; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.PersonalAccessTokenCredentialHandler = exports2.BearerCredentialHandler = exports2.BasicCredentialHandler = void 0; + var BasicCredentialHandler = class { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error("The request has no headers"); + } + options.headers["Authorization"] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString("base64")}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error("not implemented"); + }); + } + }; + exports2.BasicCredentialHandler = BasicCredentialHandler; + var BearerCredentialHandler = class { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error("The request has no headers"); + } + options.headers["Authorization"] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error("not implemented"); + }); + } + }; + exports2.BearerCredentialHandler = BearerCredentialHandler; + var PersonalAccessTokenCredentialHandler = class { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error("The request has no headers"); + } + options.headers["Authorization"] = `Basic ${Buffer.from(`PAT:${this.token}`).toString("base64")}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error("not implemented"); + }); + } + }; + exports2.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/oidc-utils.js +var require_oidc_utils = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/oidc-utils.js"(exports2) { + "use strict"; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.OidcClient = void 0; + var http_client_1 = require_lib(); + var auth_1 = require_auth(); + var core_1 = require_core(); + var OidcClient = class _OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient("actions/oidc-client", [new auth_1.BearerCredentialHandler(_OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]; + if (!token) { + throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable"); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env["ACTIONS_ID_TOKEN_REQUEST_URL"]; + if (!runtimeUrl) { + throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable"); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = _OidcClient.createHttpClient(); + const res = yield httpclient.getJson(id_token_url).catch((error) => { + throw new Error(`Failed to get ID Token. + + Error Code : ${error.statusCode} + + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error("Response json body do not have ID Token field"); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + let id_token_url = _OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + (0, core_1.debug)(`ID token url is ${id_token_url}`); + const id_token = yield _OidcClient.getCall(id_token_url); + (0, core_1.setSecret)(id_token); + return id_token; + } catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } + }; + exports2.OidcClient = OidcClient; + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/summary.js +var require_summary = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/summary.js"(exports2) { + "use strict"; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.summary = exports2.markdownSummary = exports2.SUMMARY_DOCS_URL = exports2.SUMMARY_ENV_VAR = void 0; + var os_1 = require("os"); + var fs_1 = require("fs"); + var { access, appendFile, writeFile } = fs_1.promises; + exports2.SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; + exports2.SUMMARY_DOCS_URL = "https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary"; + var Summary = class { + constructor() { + this._buffer = ""; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports2.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports2.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs).map(([key, value]) => ` ${key}="${value}"`).join(""); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ""; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code2, lang) { + const attrs = Object.assign({}, lang && { lang }); + const element = this.wrap("pre", this.wrap("code", code2), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? "ol" : "ul"; + const listItems = items.map((item) => this.wrap("li", item)).join(""); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows.map((row) => { + const cells = row.map((cell2) => { + if (typeof cell2 === "string") { + return this.wrap("td", cell2); + } + const { header, data, colspan, rowspan } = cell2; + const tag = header ? "th" : "td"; + const attrs = Object.assign(Object.assign({}, colspan && { colspan }), rowspan && { rowspan }); + return this.wrap(tag, data, attrs); + }).join(""); + return this.wrap("tr", cells); + }).join(""); + const element = this.wrap("table", tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap("details", this.wrap("summary", label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, width && { width }), height && { height }); + const element = this.wrap("img", null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ["h1", "h2", "h3", "h4", "h5", "h6"].includes(tag) ? tag : "h1"; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap("hr", null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap("br", null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, cite && { cite }); + const element = this.wrap("blockquote", text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap("a", text, { href }); + return this.addRaw(element).addEOL(); + } + }; + var _summary = new Summary(); + exports2.markdownSummary = _summary; + exports2.summary = _summary; + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/path-utils.js +var require_path_utils = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/path-utils.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.toPlatformPath = exports2.toWin32Path = exports2.toPosixPath = void 0; + var path12 = __importStar(require("path")); + function toPosixPath(pth) { + return pth.replace(/[\\]/g, "/"); + } + exports2.toPosixPath = toPosixPath; + function toWin32Path(pth) { + return pth.replace(/[/]/g, "\\"); + } + exports2.toWin32Path = toWin32Path; + function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path12.sep); + } + exports2.toPlatformPath = toPlatformPath; + } +}); + +// ../../node_modules/.pnpm/@actions+io@1.1.3/node_modules/@actions/io/lib/io-util.js +var require_io_util = __commonJS({ + "../../node_modules/.pnpm/@actions+io@1.1.3/node_modules/@actions/io/lib/io-util.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + Object.defineProperty(o2, k2, { enumerable: true, get: function() { + return m[k]; + } }); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var _a; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.getCmdPath = exports2.tryGetExecutablePath = exports2.isRooted = exports2.isDirectory = exports2.exists = exports2.READONLY = exports2.UV_FS_O_EXLOCK = exports2.IS_WINDOWS = exports2.unlink = exports2.symlink = exports2.stat = exports2.rmdir = exports2.rm = exports2.rename = exports2.readlink = exports2.readdir = exports2.open = exports2.mkdir = exports2.lstat = exports2.copyFile = exports2.chmod = void 0; + var fs = __importStar(require("fs")); + var path12 = __importStar(require("path")); + _a = fs.promises, exports2.chmod = _a.chmod, exports2.copyFile = _a.copyFile, exports2.lstat = _a.lstat, exports2.mkdir = _a.mkdir, exports2.open = _a.open, exports2.readdir = _a.readdir, exports2.readlink = _a.readlink, exports2.rename = _a.rename, exports2.rm = _a.rm, exports2.rmdir = _a.rmdir, exports2.stat = _a.stat, exports2.symlink = _a.symlink, exports2.unlink = _a.unlink; + exports2.IS_WINDOWS = process.platform === "win32"; + exports2.UV_FS_O_EXLOCK = 268435456; + exports2.READONLY = fs.constants.O_RDONLY; + function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports2.stat(fsPath); + } catch (err) { + if (err.code === "ENOENT") { + return false; + } + throw err; + } + return true; + }); + } + exports2.exists = exists; + function isDirectory2(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports2.stat(fsPath) : yield exports2.lstat(fsPath); + return stats.isDirectory(); + }); + } + exports2.isDirectory = isDirectory2; + function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports2.IS_WINDOWS) { + return p.startsWith("\\") || /^[A-Z]:/i.test(p); + } + return p.startsWith("/"); + } + exports2.isRooted = isRooted; + function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = void 0; + try { + stats = yield exports2.stat(filePath); + } catch (err) { + if (err.code !== "ENOENT") { + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports2.IS_WINDOWS) { + const upperExt = path12.extname(filePath).toUpperCase(); + if (extensions.some((validExt) => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = void 0; + try { + stats = yield exports2.stat(filePath); + } catch (err) { + if (err.code !== "ENOENT") { + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports2.IS_WINDOWS) { + try { + const directory = path12.dirname(filePath); + const upperName = path12.basename(filePath).toUpperCase(); + for (const actualName of yield exports2.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path12.join(directory, actualName); + break; + } + } + } catch (err) { + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ""; + }); + } + exports2.tryGetExecutablePath = tryGetExecutablePath; + function normalizeSeparators(p) { + p = p || ""; + if (exports2.IS_WINDOWS) { + p = p.replace(/\//g, "\\"); + return p.replace(/\\\\+/g, "\\"); + } + return p.replace(/\/\/+/g, "/"); + } + function isUnixExecutable(stats) { + return (stats.mode & 1) > 0 || (stats.mode & 8) > 0 && stats.gid === process.getgid() || (stats.mode & 64) > 0 && stats.uid === process.getuid(); + } + function getCmdPath() { + var _a2; + return (_a2 = process.env["COMSPEC"]) !== null && _a2 !== void 0 ? _a2 : `cmd.exe`; + } + exports2.getCmdPath = getCmdPath; + } +}); + +// ../../node_modules/.pnpm/@actions+io@1.1.3/node_modules/@actions/io/lib/io.js +var require_io = __commonJS({ + "../../node_modules/.pnpm/@actions+io@1.1.3/node_modules/@actions/io/lib/io.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + Object.defineProperty(o2, k2, { enumerable: true, get: function() { + return m[k]; + } }); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.findInPath = exports2.which = exports2.mkdirP = exports2.rmRF = exports2.mv = exports2.cp = void 0; + var assert_1 = require("assert"); + var path12 = __importStar(require("path")); + var ioUtil = __importStar(require_io_util()); + function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + if (destStat && destStat.isFile() && !force) { + return; + } + const newDest = destStat && destStat.isDirectory() && copySourceDirectory ? path12.join(dest, path12.basename(source)) : dest; + if (!(yield ioUtil.exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } else { + yield cpDirRecursive(source, newDest, 0, force); + } + } else { + if (path12.relative(source, newDest) === "") { + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield copyFile(source, newDest, force); + } + }); + } + exports2.cp = cp; + function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + dest = path12.join(dest, path12.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } else { + throw new Error("Destination already exists"); + } + } + } + yield mkdirP(path12.dirname(dest)); + yield ioUtil.rename(source, dest); + }); + } + exports2.mv = mv; + function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + yield ioUtil.rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); + } + exports2.rmRF = rmRF; + function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, "a path argument must be provided"); + yield ioUtil.mkdir(fsPath, { recursive: true }); + }); + } + exports2.mkdirP = mkdirP; + function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + if (check) { + const result = yield which(tool, false); + if (!result) { + if (ioUtil.IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ""; + }); + } + exports2.which = which; + function findInPath(tool) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + const extensions = []; + if (ioUtil.IS_WINDOWS && process.env["PATHEXT"]) { + for (const extension of process.env["PATHEXT"].split(path12.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + if (ioUtil.isRooted(tool)) { + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + if (tool.includes(path12.sep)) { + return []; + } + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path12.delimiter)) { + if (p) { + directories.push(p); + } + } + } + const matches = []; + for (const directory of directories) { + const filePath = yield ioUtil.tryGetExecutablePath(path12.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); + } + exports2.findInPath = findInPath; + function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null ? true : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; + } + function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield ioUtil.lstat(srcFile); + if (srcFileStat.isDirectory()) { + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } else { + yield copyFile(srcFile, destFile, force); + } + } + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); + } + function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + try { + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } catch (e) { + if (e.code === "EPERM") { + yield ioUtil.chmod(destFile, "0666"); + yield ioUtil.unlink(destFile); + } + } + const symlinkFull = yield ioUtil.readlink(srcFile); + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? "junction" : null); + } else if (!(yield ioUtil.exists(destFile)) || force) { + yield ioUtil.copyFile(srcFile, destFile); + } + }); + } + } +}); + +// ../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/toolrunner.js +var require_toolrunner = __commonJS({ + "../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/toolrunner.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + Object.defineProperty(o2, k2, { enumerable: true, get: function() { + return m[k]; + } }); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.argStringToArray = exports2.ToolRunner = void 0; + var os = __importStar(require("os")); + var events = __importStar(require("events")); + var child = __importStar(require("child_process")); + var path12 = __importStar(require("path")); + var io = __importStar(require_io()); + var ioUtil = __importStar(require_io_util()); + var timers_1 = require("timers"); + var IS_WINDOWS = process.platform === "win32"; + var ToolRunner = class extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? "" : "[command]"; + if (IS_WINDOWS) { + if (this._isCmdFile()) { + cmd += toolPath; + for (const a2 of args) { + cmd += ` ${a2}`; + } + } else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a2 of args) { + cmd += ` ${a2}`; + } + } else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a2 of args) { + cmd += ` ${this._windowsQuoteCmdArg(a2)}`; + } + } + } else { + cmd += toolPath; + for (const a2 of args) { + cmd += ` ${a2}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n2 = s.indexOf(os.EOL); + while (n2 > -1) { + const line = s.substring(0, n2); + onLine(line); + s = s.substring(n2 + os.EOL.length); + n2 = s.indexOf(os.EOL); + } + return s; + } catch (err) { + this._debug(`error processing line. Failed with error ${err}`); + return ""; + } + } + _getSpawnFileName() { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env["COMSPEC"] || "cmd.exe"; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a2 of this.args) { + argline += " "; + argline += options.windowsVerbatimArguments ? a2 : this._windowsQuoteCmdArg(a2); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return this._endsWith(upperToolPath, ".CMD") || this._endsWith(upperToolPath, ".BAT"); + } + _windowsQuoteCmdArg(arg) { + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + if (!arg) { + return '""'; + } + const cmdSpecialChars = [ + " ", + " ", + "&", + "(", + ")", + "[", + "]", + "{", + "}", + "^", + "=", + ";", + "!", + "'", + "+", + ",", + "`", + "~", + "|", + "<", + ">", + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some((x) => x === char)) { + needsQuotes = true; + break; + } + } + if (!needsQuotes) { + return arg; + } + let reverse = '"'; + let quoteHit = true; + for (let i2 = arg.length; i2 > 0; i2--) { + reverse += arg[i2 - 1]; + if (quoteHit && arg[i2 - 1] === "\\") { + reverse += "\\"; + } else if (arg[i2 - 1] === '"') { + quoteHit = true; + reverse += '"'; + } else { + quoteHit = false; + } + } + reverse += '"'; + return reverse.split("").reverse().join(""); + } + _uvQuoteCmdArg(arg) { + if (!arg) { + return '""'; + } + if (!arg.includes(" ") && !arg.includes(" ") && !arg.includes('"')) { + return arg; + } + if (!arg.includes('"') && !arg.includes("\\")) { + return `"${arg}"`; + } + let reverse = '"'; + let quoteHit = true; + for (let i2 = arg.length; i2 > 0; i2--) { + reverse += arg[i2 - 1]; + if (quoteHit && arg[i2 - 1] === "\\") { + reverse += "\\"; + } else if (arg[i2 - 1] === '"') { + quoteHit = true; + reverse += "\\"; + } else { + quoteHit = false; + } + } + reverse += '"'; + return reverse.split("").reverse().join(""); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 1e4 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result["windowsVerbatimArguments"] = options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { + if (!ioUtil.isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS && this.toolPath.includes("\\"))) { + this.toolPath = path12.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + this.toolPath = yield io.which(this.toolPath, true); + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug("arguments:"); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on("debug", (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ""; + if (cp.stdout) { + cp.stdout.on("data", (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ""; + if (cp.stderr) { + cp.stderr.on("data", (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && optionsNonNull.errStream && optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on("error", (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on("exit", (code2) => { + state.processExitCode = code2; + state.processExited = true; + this._debug(`Exit code ${code2} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on("close", (code2) => { + state.processExitCode = code2; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on("done", (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit("stdline", stdbuffer); + } + if (errbuffer.length > 0) { + this.emit("errline", errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error("child process missing stdin"); + } + cp.stdin.end(this.options.input); + } + })); + }); + } + }; + exports2.ToolRunner = ToolRunner; + function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ""; + function append(c3) { + if (escaped && c3 !== '"') { + arg += "\\"; + } + arg += c3; + escaped = false; + } + for (let i2 = 0; i2 < argString.length; i2++) { + const c3 = argString.charAt(i2); + if (c3 === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } else { + append(c3); + } + continue; + } + if (c3 === "\\" && escaped) { + append(c3); + continue; + } + if (c3 === "\\" && inQuotes) { + escaped = true; + continue; + } + if (c3 === " " && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ""; + } + continue; + } + append(c3); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; + } + exports2.argStringToArray = argStringToArray; + var ExecState = class _ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; + this.processError = ""; + this.processExitCode = 0; + this.processExited = false; + this.processStderr = false; + this.delay = 1e4; + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error("toolPath must not be empty"); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } else if (this.processExited) { + this.timeout = timers_1.setTimeout(_ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit("debug", message); + } + _setResult() { + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit("done", error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / 1e3} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } + }; + } +}); + +// ../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/exec.js +var require_exec = __commonJS({ + "../../node_modules/.pnpm/@actions+exec@1.1.1/node_modules/@actions/exec/lib/exec.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + Object.defineProperty(o2, k2, { enumerable: true, get: function() { + return m[k]; + } }); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.getExecOutput = exports2.exec = void 0; + var string_decoder_1 = require("string_decoder"); + var tr = __importStar(require_toolrunner()); + function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); + } + exports2.exec = exec; + function getExecOutput(commandLine, args, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + let stdout = ""; + let stderr = ""; + const stdoutDecoder = new string_decoder_1.StringDecoder("utf8"); + const stderrDecoder = new string_decoder_1.StringDecoder("utf8"); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); + } + exports2.getExecOutput = getExecOutput; + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/platform.js +var require_platform = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/platform.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.getDetails = exports2.isLinux = exports2.isMacOS = exports2.isWindows = exports2.arch = exports2.platform = void 0; + var os_1 = __importDefault(require("os")); + var exec = __importStar(require_exec()); + var getWindowsInfo = () => __awaiter(void 0, void 0, void 0, function* () { + const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', void 0, { + silent: true + }); + const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', void 0, { + silent: true + }); + return { + name: name.trim(), + version: version.trim() + }; + }); + var getMacOsInfo = () => __awaiter(void 0, void 0, void 0, function* () { + var _a, _b, _c, _d; + const { stdout } = yield exec.getExecOutput("sw_vers", void 0, { + silent: true + }); + const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ""; + const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ""; + return { + name, + version + }; + }); + var getLinuxInfo = () => __awaiter(void 0, void 0, void 0, function* () { + const { stdout } = yield exec.getExecOutput("lsb_release", ["-i", "-r", "-s"], { + silent: true + }); + const [name, version] = stdout.trim().split("\n"); + return { + name, + version + }; + }); + exports2.platform = os_1.default.platform(); + exports2.arch = os_1.default.arch(); + exports2.isWindows = exports2.platform === "win32"; + exports2.isMacOS = exports2.platform === "darwin"; + exports2.isLinux = exports2.platform === "linux"; + function getDetails() { + return __awaiter(this, void 0, void 0, function* () { + return Object.assign(Object.assign({}, yield exports2.isWindows ? getWindowsInfo() : exports2.isMacOS ? getMacOsInfo() : getLinuxInfo()), { + platform: exports2.platform, + arch: exports2.arch, + isWindows: exports2.isWindows, + isMacOS: exports2.isMacOS, + isLinux: exports2.isLinux + }); + }); + } + exports2.getDetails = getDetails; + } +}); + +// ../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/core.js +var require_core = __commonJS({ + "../../node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core/lib/core.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + }) : (function(o2, m, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m[k]; + })); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o2, v) { + Object.defineProperty(o2, "default", { enumerable: true, value: v }); + }) : function(o2, v) { + o2["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.platform = exports2.toPlatformPath = exports2.toWin32Path = exports2.toPosixPath = exports2.markdownSummary = exports2.summary = exports2.getIDToken = exports2.getState = exports2.saveState = exports2.group = exports2.endGroup = exports2.startGroup = exports2.info = exports2.notice = exports2.warning = exports2.error = exports2.debug = exports2.isDebug = exports2.setFailed = exports2.setCommandEcho = exports2.setOutput = exports2.getBooleanInput = exports2.getMultilineInput = exports2.getInput = exports2.addPath = exports2.setSecret = exports2.exportVariable = exports2.ExitCode = void 0; + var command_1 = require_command(); + var file_command_1 = require_file_command(); + var utils_1 = require_utils(); + var os = __importStar(require("os")); + var path12 = __importStar(require("path")); + var oidc_utils_1 = require_oidc_utils(); + var ExitCode; + (function(ExitCode2) { + ExitCode2[ExitCode2["Success"] = 0] = "Success"; + ExitCode2[ExitCode2["Failure"] = 1] = "Failure"; + })(ExitCode || (exports2.ExitCode = ExitCode = {})); + function exportVariable(name, val) { + const convertedVal = (0, utils_1.toCommandValue)(val); + process.env[name] = convertedVal; + const filePath = process.env["GITHUB_ENV"] || ""; + if (filePath) { + return (0, file_command_1.issueFileCommand)("ENV", (0, file_command_1.prepareKeyValueMessage)(name, val)); + } + (0, command_1.issueCommand)("set-env", { name }, convertedVal); + } + exports2.exportVariable = exportVariable; + function setSecret(secret) { + (0, command_1.issueCommand)("add-mask", {}, secret); + } + exports2.setSecret = setSecret; + function addPath(inputPath) { + const filePath = process.env["GITHUB_PATH"] || ""; + if (filePath) { + (0, file_command_1.issueFileCommand)("PATH", inputPath); + } else { + (0, command_1.issueCommand)("add-path", {}, inputPath); + } + process.env["PATH"] = `${inputPath}${path12.delimiter}${process.env["PATH"]}`; + } + exports2.addPath = addPath; + function getInput2(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || ""; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); + } + exports2.getInput = getInput2; + function getMultilineInput(name, options) { + const inputs = getInput2(name, options).split("\n").filter((x) => x !== ""); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map((input) => input.trim()); + } + exports2.getMultilineInput = getMultilineInput; + function getBooleanInput(name, options) { + const trueValue = ["true", "True", "TRUE"]; + const falseValue = ["false", "False", "FALSE"]; + const val = getInput2(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name} +Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); + } + exports2.getBooleanInput = getBooleanInput; + function setOutput2(name, value) { + const filePath = process.env["GITHUB_OUTPUT"] || ""; + if (filePath) { + return (0, file_command_1.issueFileCommand)("OUTPUT", (0, file_command_1.prepareKeyValueMessage)(name, value)); + } + process.stdout.write(os.EOL); + (0, command_1.issueCommand)("set-output", { name }, (0, utils_1.toCommandValue)(value)); + } + exports2.setOutput = setOutput2; + function setCommandEcho(enabled) { + (0, command_1.issue)("echo", enabled ? "on" : "off"); + } + exports2.setCommandEcho = setCommandEcho; + function setFailed2(message) { + process.exitCode = ExitCode.Failure; + error(message); + } + exports2.setFailed = setFailed2; + function isDebug() { + return process.env["RUNNER_DEBUG"] === "1"; + } + exports2.isDebug = isDebug; + function debug(message) { + (0, command_1.issueCommand)("debug", {}, message); + } + exports2.debug = debug; + function error(message, properties = {}) { + (0, command_1.issueCommand)("error", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); + } + exports2.error = error; + function warning(message, properties = {}) { + (0, command_1.issueCommand)("warning", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); + } + exports2.warning = warning; + function notice(message, properties = {}) { + (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); + } + exports2.notice = notice; + function info2(message) { + process.stdout.write(message + os.EOL); + } + exports2.info = info2; + function startGroup(name) { + (0, command_1.issue)("group", name); + } + exports2.startGroup = startGroup; + function endGroup() { + (0, command_1.issue)("endgroup"); + } + exports2.endGroup = endGroup; + function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } finally { + endGroup(); + } + return result; + }); + } + exports2.group = group; + function saveState(name, value) { + const filePath = process.env["GITHUB_STATE"] || ""; + if (filePath) { + return (0, file_command_1.issueFileCommand)("STATE", (0, file_command_1.prepareKeyValueMessage)(name, value)); + } + (0, command_1.issueCommand)("save-state", { name }, (0, utils_1.toCommandValue)(value)); + } + exports2.saveState = saveState; + function getState(name) { + return process.env[`STATE_${name}`] || ""; + } + exports2.getState = getState; + function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); + } + exports2.getIDToken = getIDToken; + var summary_1 = require_summary(); + Object.defineProperty(exports2, "summary", { enumerable: true, get: function() { + return summary_1.summary; + } }); + var summary_2 = require_summary(); + Object.defineProperty(exports2, "markdownSummary", { enumerable: true, get: function() { + return summary_2.markdownSummary; + } }); + var path_utils_1 = require_path_utils(); + Object.defineProperty(exports2, "toPosixPath", { enumerable: true, get: function() { + return path_utils_1.toPosixPath; + } }); + Object.defineProperty(exports2, "toWin32Path", { enumerable: true, get: function() { + return path_utils_1.toWin32Path; + } }); + Object.defineProperty(exports2, "toPlatformPath", { enumerable: true, get: function() { + return path_utils_1.toPlatformPath; + } }); + exports2.platform = __importStar(require_platform()); + } +}); + +// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js +var require_windows = __commonJS({ + "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports2, module2) { + "use strict"; + module2.exports = isexe; + isexe.sync = sync; + var fs = require("fs"); + function checkPathExt(path12, options) { + var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT; + if (!pathext) { + return true; + } + pathext = pathext.split(";"); + if (pathext.indexOf("") !== -1) { + return true; + } + for (var i2 = 0; i2 < pathext.length; i2++) { + var p = pathext[i2].toLowerCase(); + if (p && path12.substr(-p.length).toLowerCase() === p) { + return true; + } + } + return false; + } + function checkStat(stat, path12, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false; + } + return checkPathExt(path12, options); + } + function isexe(path12, options, cb) { + fs.stat(path12, function(er, stat) { + cb(er, er ? false : checkStat(stat, path12, options)); + }); + } + function sync(path12, options) { + return checkStat(fs.statSync(path12), path12, options); + } + } +}); + +// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js +var require_mode = __commonJS({ + "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports2, module2) { + "use strict"; + module2.exports = isexe; + isexe.sync = sync; + var fs = require("fs"); + function isexe(path12, options, cb) { + fs.stat(path12, function(er, stat) { + cb(er, er ? false : checkStat(stat, options)); + }); + } + function sync(path12, options) { + return checkStat(fs.statSync(path12), options); + } + function checkStat(stat, options) { + return stat.isFile() && checkMode(stat, options); + } + function checkMode(stat, options) { + var mod = stat.mode; + var uid = stat.uid; + var gid = stat.gid; + var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid(); + var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid(); + var u2 = parseInt("100", 8); + var g = parseInt("010", 8); + var o2 = parseInt("001", 8); + var ug = u2 | g; + var ret = mod & o2 || mod & g && gid === myGid || mod & u2 && uid === myUid || mod & ug && myUid === 0; + return ret; + } + } +}); + +// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js +var require_isexe = __commonJS({ + "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports2, module2) { + "use strict"; + var fs = require("fs"); + var core2; + if (process.platform === "win32" || global.TESTING_WINDOWS) { + core2 = require_windows(); + } else { + core2 = require_mode(); + } + module2.exports = isexe; + isexe.sync = sync; + function isexe(path12, options, cb) { + if (typeof options === "function") { + cb = options; + options = {}; + } + if (!cb) { + if (typeof Promise !== "function") { + throw new TypeError("callback not provided"); + } + return new Promise(function(resolve, reject) { + isexe(path12, options || {}, function(er, is) { + if (er) { + reject(er); + } else { + resolve(is); + } + }); + }); + } + core2(path12, options || {}, function(er, is) { + if (er) { + if (er.code === "EACCES" || options && options.ignoreErrors) { + er = null; + is = false; + } + } + cb(er, is); + }); + } + function sync(path12, options) { + try { + return core2.sync(path12, options || {}); + } catch (er) { + if (options && options.ignoreErrors || er.code === "EACCES") { + return false; + } else { + throw er; + } + } + } + } +}); + +// ../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js +var require_which = __commonJS({ + "../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports2, module2) { + "use strict"; + var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys"; + var path12 = require("path"); + var COLON = isWindows ? ";" : ":"; + var isexe = require_isexe(); + var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" }); + var getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON; + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [ + // windows always checks the cwd first + ...isWindows ? [process.cwd()] : [], + ...(opt.path || process.env.PATH || /* istanbul ignore next: very unusual */ + "").split(colon) + ]; + const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : ""; + const pathExt = isWindows ? pathExtExe.split(colon) : [""]; + if (isWindows) { + if (cmd.indexOf(".") !== -1 && pathExt[0] !== "") + pathExt.unshift(""); + } + return { + pathEnv, + pathExt, + pathExtExe + }; + }; + var which = (cmd, opt, cb) => { + if (typeof opt === "function") { + cb = opt; + opt = {}; + } + if (!opt) + opt = {}; + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + const step = (i2) => new Promise((resolve, reject) => { + if (i2 === pathEnv.length) + return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd)); + const ppRaw = pathEnv[i2]; + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw; + const pCmd = path12.join(pathPart, cmd); + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd; + resolve(subStep(p, i2, 0)); + }); + const subStep = (p, i2, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i2 + 1)); + const ext = pathExt[ii]; + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext); + else + return resolve(p + ext); + } + return resolve(subStep(p, i2, ii + 1)); + }); + }); + return cb ? step(0).then((res) => cb(null, res), cb) : step(0); + }; + var whichSync = (cmd, opt) => { + opt = opt || {}; + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + for (let i2 = 0; i2 < pathEnv.length; i2++) { + const ppRaw = pathEnv[i2]; + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw; + const pCmd = path12.join(pathPart, cmd); + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd; + for (let j = 0; j < pathExt.length; j++) { + const cur = p + pathExt[j]; + try { + const is = isexe.sync(cur, { pathExt: pathExtExe }); + if (is) { + if (opt.all) + found.push(cur); + else + return cur; + } + } catch (ex) { + } + } + } + if (opt.all && found.length) + return found; + if (opt.nothrow) + return null; + throw getNotFoundError(cmd); + }; + module2.exports = which; + which.sync = whichSync; + } +}); + +// ../../node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.js +var require_path_key = __commonJS({ + "../../node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.js"(exports2, module2) { + "use strict"; + var pathKey2 = (options = {}) => { + const environment = options.env || process.env; + const platform2 = options.platform || process.platform; + if (platform2 !== "win32") { + return "PATH"; + } + return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path"; + }; + module2.exports = pathKey2; + module2.exports.default = pathKey2; + } +}); + +// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js +var require_resolveCommand = __commonJS({ + "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports2, module2) { + "use strict"; + var path12 = require("path"); + var which = require_which(); + var getPathKey = require_path_key(); + function resolveCommandAttempt(parsed, withoutPathExt) { + const env = parsed.options.env || process.env; + const cwd = process.cwd(); + const hasCustomCwd = parsed.options.cwd != null; + const shouldSwitchCwd = hasCustomCwd && process.chdir !== void 0 && !process.chdir.disabled; + if (shouldSwitchCwd) { + try { + process.chdir(parsed.options.cwd); + } catch (err) { + } + } + let resolved; + try { + resolved = which.sync(parsed.command, { + path: env[getPathKey({ env })], + pathExt: withoutPathExt ? path12.delimiter : void 0 + }); + } catch (e) { + } finally { + if (shouldSwitchCwd) { + process.chdir(cwd); + } + } + if (resolved) { + resolved = path12.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved); + } + return resolved; + } + function resolveCommand(parsed) { + return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); + } + module2.exports = resolveCommand; + } +}); + +// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js +var require_escape = __commonJS({ + "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js"(exports2, module2) { + "use strict"; + var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; + function escapeCommand(arg) { + arg = arg.replace(metaCharsRegExp, "^$1"); + return arg; + } + function escapeArgument(arg, doubleEscapeMetaChars) { + arg = `${arg}`; + arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"'); + arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1"); + arg = `"${arg}"`; + arg = arg.replace(metaCharsRegExp, "^$1"); + if (doubleEscapeMetaChars) { + arg = arg.replace(metaCharsRegExp, "^$1"); + } + return arg; + } + module2.exports.command = escapeCommand; + module2.exports.argument = escapeArgument; + } +}); + +// ../../node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.js +var require_shebang_regex = __commonJS({ + "../../node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.js"(exports2, module2) { + "use strict"; + module2.exports = /^#!(.*)/; + } +}); + +// ../../node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.js +var require_shebang_command = __commonJS({ + "../../node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.js"(exports2, module2) { + "use strict"; + var shebangRegex = require_shebang_regex(); + module2.exports = (string = "") => { + const match = string.match(shebangRegex); + if (!match) { + return null; + } + const [path12, argument] = match[0].replace(/#! ?/, "").split(" "); + const binary = path12.split("/").pop(); + if (binary === "env") { + return argument; + } + return argument ? `${binary} ${argument}` : binary; + }; + } +}); + +// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js +var require_readShebang = __commonJS({ + "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports2, module2) { + "use strict"; + var fs = require("fs"); + var shebangCommand = require_shebang_command(); + function readShebang(command) { + const size = 150; + const buffer = Buffer.alloc(size); + let fd; + try { + fd = fs.openSync(command, "r"); + fs.readSync(fd, buffer, 0, size, 0); + fs.closeSync(fd); + } catch (e) { + } + return shebangCommand(buffer.toString()); + } + module2.exports = readShebang; + } +}); + +// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js +var require_parse2 = __commonJS({ + "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports2, module2) { + "use strict"; + var path12 = require("path"); + var resolveCommand = require_resolveCommand(); + var escape = require_escape(); + var readShebang = require_readShebang(); + var isWin = process.platform === "win32"; + var isExecutableRegExp = /\.(?:com|exe)$/i; + var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; + function detectShebang(parsed) { + parsed.file = resolveCommand(parsed); + const shebang = parsed.file && readShebang(parsed.file); + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; + return resolveCommand(parsed); + } + return parsed.file; + } + function parseNonShell(parsed) { + if (!isWin) { + return parsed; + } + const commandFile = detectShebang(parsed); + const needsShell = !isExecutableRegExp.test(commandFile); + if (parsed.options.forceShell || needsShell) { + const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); + parsed.command = path12.normalize(parsed.command); + parsed.command = escape.command(parsed.command); + parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); + const shellCommand = [parsed.command].concat(parsed.args).join(" "); + parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`]; + parsed.command = process.env.comspec || "cmd.exe"; + parsed.options.windowsVerbatimArguments = true; + } + return parsed; + } + function parse(command, args, options) { + if (args && !Array.isArray(args)) { + options = args; + args = null; + } + args = args ? args.slice(0) : []; + options = Object.assign({}, options); + const parsed = { + command, + args, + options, + file: void 0, + original: { + command, + args + } + }; + return options.shell ? parsed : parseNonShell(parsed); + } + module2.exports = parse; + } +}); + +// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js +var require_enoent = __commonJS({ + "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js"(exports2, module2) { + "use strict"; + var isWin = process.platform === "win32"; + function notFoundError(original, syscall) { + return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { + code: "ENOENT", + errno: "ENOENT", + syscall: `${syscall} ${original.command}`, + path: original.command, + spawnargs: original.args + }); + } + function hookChildProcess(cp, parsed) { + if (!isWin) { + return; + } + const originalEmit = cp.emit; + cp.emit = function(name, arg1) { + if (name === "exit") { + const err = verifyENOENT(arg1, parsed); + if (err) { + return originalEmit.call(cp, "error", err); + } + } + return originalEmit.apply(cp, arguments); + }; + } + function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, "spawn"); + } + return null; + } + function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, "spawnSync"); + } + return null; + } + module2.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError + }; + } +}); + +// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.js +var require_cross_spawn = __commonJS({ + "../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.js"(exports2, module2) { + "use strict"; + var cp = require("child_process"); + var parse = require_parse2(); + var enoent = require_enoent(); + function spawn2(command, args, options) { + const parsed = parse(command, args, options); + const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); + enoent.hookChildProcess(spawned, parsed); + return spawned; + } + function spawnSync2(command, args, options) { + const parsed = parse(command, args, options); + const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); + return result; + } + module2.exports = spawn2; + module2.exports.spawn = spawn2; + module2.exports.sync = spawnSync2; + module2.exports._parse = parse; + module2.exports._enoent = enoent; + } +}); + +// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/constants.js +var require_constants6 = __commonJS({ + "../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/constants.js"(exports2, module2) { + "use strict"; + var WIN_SLASH = "\\\\/"; + var WIN_NO_SLASH = `[^${WIN_SLASH}]`; + var DEFAULT_MAX_EXTGLOB_RECURSION = 0; + var DOT_LITERAL = "\\."; + var PLUS_LITERAL = "\\+"; + var QMARK_LITERAL = "\\?"; + var SLASH_LITERAL = "\\/"; + var ONE_CHAR = "(?=.)"; + var QMARK = "[^/]"; + var END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; + var START_ANCHOR = `(?:^|${SLASH_LITERAL})`; + var DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; + var NO_DOT = `(?!${DOT_LITERAL})`; + var NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; + var NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; + var NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; + var QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; + var STAR = `${QMARK}*?`; + var SEP = "/"; + var POSIX_CHARS = { + DOT_LITERAL, + PLUS_LITERAL, + QMARK_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + QMARK, + END_ANCHOR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK_NO_DOT, + STAR, + START_ANCHOR, + SEP + }; + var WINDOWS_CHARS = { + ...POSIX_CHARS, + SLASH_LITERAL: `[${WIN_SLASH}]`, + QMARK: WIN_NO_SLASH, + STAR: `${WIN_NO_SLASH}*?`, + DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, + NO_DOT: `(?!${DOT_LITERAL})`, + NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, + NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + QMARK_NO_DOT: `[^.${WIN_SLASH}]`, + START_ANCHOR: `(?:^|[${WIN_SLASH}])`, + END_ANCHOR: `(?:[${WIN_SLASH}]|$)`, + SEP: "\\" + }; + var POSIX_REGEX_SOURCE = { + __proto__: null, + alnum: "a-zA-Z0-9", + alpha: "a-zA-Z", + ascii: "\\x00-\\x7F", + blank: " \\t", + cntrl: "\\x00-\\x1F\\x7F", + digit: "0-9", + graph: "\\x21-\\x7E", + lower: "a-z", + print: "\\x20-\\x7E ", + punct: "\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~", + space: " \\t\\r\\n\\v\\f", + upper: "A-Z", + word: "A-Za-z0-9_", + xdigit: "A-Fa-f0-9" + }; + module2.exports = { + DEFAULT_MAX_EXTGLOB_RECURSION, + MAX_LENGTH: 1024 * 64, + POSIX_REGEX_SOURCE, + // regular expressions + REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, + REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, + REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, + REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, + REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, + REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, + // Replace globs with equivalent patterns to reduce parsing time. + REPLACEMENTS: { + __proto__: null, + "***": "*", + "**/**": "**", + "**/**/**": "**" + }, + // Digits + CHAR_0: 48, + /* 0 */ + CHAR_9: 57, + /* 9 */ + // Alphabet chars. + CHAR_UPPERCASE_A: 65, + /* A */ + CHAR_LOWERCASE_A: 97, + /* a */ + CHAR_UPPERCASE_Z: 90, + /* Z */ + CHAR_LOWERCASE_Z: 122, + /* z */ + CHAR_LEFT_PARENTHESES: 40, + /* ( */ + CHAR_RIGHT_PARENTHESES: 41, + /* ) */ + CHAR_ASTERISK: 42, + /* * */ + // Non-alphabetic chars. + CHAR_AMPERSAND: 38, + /* & */ + CHAR_AT: 64, + /* @ */ + CHAR_BACKWARD_SLASH: 92, + /* \ */ + CHAR_CARRIAGE_RETURN: 13, + /* \r */ + CHAR_CIRCUMFLEX_ACCENT: 94, + /* ^ */ + CHAR_COLON: 58, + /* : */ + CHAR_COMMA: 44, + /* , */ + CHAR_DOT: 46, + /* . */ + CHAR_DOUBLE_QUOTE: 34, + /* " */ + CHAR_EQUAL: 61, + /* = */ + CHAR_EXCLAMATION_MARK: 33, + /* ! */ + CHAR_FORM_FEED: 12, + /* \f */ + CHAR_FORWARD_SLASH: 47, + /* / */ + CHAR_GRAVE_ACCENT: 96, + /* ` */ + CHAR_HASH: 35, + /* # */ + CHAR_HYPHEN_MINUS: 45, + /* - */ + CHAR_LEFT_ANGLE_BRACKET: 60, + /* < */ + CHAR_LEFT_CURLY_BRACE: 123, + /* { */ + CHAR_LEFT_SQUARE_BRACKET: 91, + /* [ */ + CHAR_LINE_FEED: 10, + /* \n */ + CHAR_NO_BREAK_SPACE: 160, + /* \u00A0 */ + CHAR_PERCENT: 37, + /* % */ + CHAR_PLUS: 43, + /* + */ + CHAR_QUESTION_MARK: 63, + /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: 62, + /* > */ + CHAR_RIGHT_CURLY_BRACE: 125, + /* } */ + CHAR_RIGHT_SQUARE_BRACKET: 93, + /* ] */ + CHAR_SEMICOLON: 59, + /* ; */ + CHAR_SINGLE_QUOTE: 39, + /* ' */ + CHAR_SPACE: 32, + /* */ + CHAR_TAB: 9, + /* \t */ + CHAR_UNDERSCORE: 95, + /* _ */ + CHAR_VERTICAL_LINE: 124, + /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, + /* \uFEFF */ + /** + * Create EXTGLOB_CHARS + */ + extglobChars(chars) { + return { + "!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` }, + "?": { type: "qmark", open: "(?:", close: ")?" }, + "+": { type: "plus", open: "(?:", close: ")+" }, + "*": { type: "star", open: "(?:", close: ")*" }, + "@": { type: "at", open: "(?:", close: ")" } + }; + }, + /** + * Create GLOB_CHARS + */ + globChars(win32) { + return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; + } + }; + } +}); + +// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/utils.js +var require_utils3 = __commonJS({ + "../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/utils.js"(exports2) { + "use strict"; + var { + REGEX_BACKSLASH, + REGEX_REMOVE_BACKSLASH, + REGEX_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_GLOBAL + } = require_constants6(); + exports2.isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val); + exports2.hasRegexChars = (str) => REGEX_SPECIAL_CHARS.test(str); + exports2.isRegexChar = (str) => str.length === 1 && exports2.hasRegexChars(str); + exports2.escapeRegex = (str) => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, "\\$1"); + exports2.toPosixSlashes = (str) => str.replace(REGEX_BACKSLASH, "/"); + exports2.isWindows = () => { + if (typeof navigator !== "undefined" && navigator.platform) { + const platform2 = navigator.platform.toLowerCase(); + return platform2 === "win32" || platform2 === "windows"; + } + if (typeof process !== "undefined" && process.platform) { + return process.platform === "win32"; + } + return false; + }; + exports2.removeBackslashes = (str) => { + return str.replace(REGEX_REMOVE_BACKSLASH, (match) => { + return match === "\\" ? "" : match; + }); + }; + exports2.escapeLast = (input, char, lastIdx) => { + const idx = input.lastIndexOf(char, lastIdx); + if (idx === -1) return input; + if (input[idx - 1] === "\\") return exports2.escapeLast(input, char, idx - 1); + return `${input.slice(0, idx)}\\${input.slice(idx)}`; + }; + exports2.removePrefix = (input, state = {}) => { + let output = input; + if (output.startsWith("./")) { + output = output.slice(2); + state.prefix = "./"; + } + return output; + }; + exports2.wrapOutput = (input, state = {}, options = {}) => { + const prepend = options.contains ? "" : "^"; + const append = options.contains ? "" : "$"; + let output = `${prepend}(?:${input})${append}`; + if (state.negated === true) { + output = `(?:^(?!${output}).*$)`; + } + return output; + }; + exports2.basename = (path12, { windows } = {}) => { + const segs = path12.split(windows ? /[\\/]/ : "/"); + const last = segs[segs.length - 1]; + if (last === "") { + return segs[segs.length - 2]; + } + return last; + }; + } +}); + +// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/scan.js +var require_scan = __commonJS({ + "../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/scan.js"(exports2, module2) { + "use strict"; + var utils = require_utils3(); + var { + CHAR_ASTERISK, + /* * */ + CHAR_AT, + /* @ */ + CHAR_BACKWARD_SLASH, + /* \ */ + CHAR_COMMA, + /* , */ + CHAR_DOT, + /* . */ + CHAR_EXCLAMATION_MARK, + /* ! */ + CHAR_FORWARD_SLASH, + /* / */ + CHAR_LEFT_CURLY_BRACE, + /* { */ + CHAR_LEFT_PARENTHESES, + /* ( */ + CHAR_LEFT_SQUARE_BRACKET, + /* [ */ + CHAR_PLUS, + /* + */ + CHAR_QUESTION_MARK, + /* ? */ + CHAR_RIGHT_CURLY_BRACE, + /* } */ + CHAR_RIGHT_PARENTHESES, + /* ) */ + CHAR_RIGHT_SQUARE_BRACKET + /* ] */ + } = require_constants6(); + var isPathSeparator = (code2) => { + return code2 === CHAR_FORWARD_SLASH || code2 === CHAR_BACKWARD_SLASH; + }; + var depth = (token) => { + if (token.isPrefix !== true) { + token.depth = token.isGlobstar ? Infinity : 1; + } + }; + var scan = (input, options) => { + const opts = options || {}; + const length = input.length - 1; + const scanToEnd = opts.parts === true || opts.scanToEnd === true; + const slashes = []; + const tokens = []; + const parts = []; + let str = input; + let index = -1; + let start = 0; + let lastIndex = 0; + let isBrace = false; + let isBracket = false; + let isGlob = false; + let isExtglob = false; + let isGlobstar = false; + let braceEscaped = false; + let backslashes = false; + let negated = false; + let negatedExtglob = false; + let finished7 = false; + let braces = 0; + let prev; + let code2; + let token = { value: "", depth: 0, isGlob: false }; + const eos = () => index >= length; + const peek = () => str.charCodeAt(index + 1); + const advance = () => { + prev = code2; + return str.charCodeAt(++index); + }; + while (index < length) { + code2 = advance(); + let next; + if (code2 === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code2 = advance(); + if (code2 === CHAR_LEFT_CURLY_BRACE) { + braceEscaped = true; + } + continue; + } + if (braceEscaped === true || code2 === CHAR_LEFT_CURLY_BRACE) { + braces++; + while (eos() !== true && (code2 = advance())) { + if (code2 === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (code2 === CHAR_LEFT_CURLY_BRACE) { + braces++; + continue; + } + if (braceEscaped !== true && code2 === CHAR_DOT && (code2 = advance()) === CHAR_DOT) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished7 = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (braceEscaped !== true && code2 === CHAR_COMMA) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished7 = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code2 === CHAR_RIGHT_CURLY_BRACE) { + braces--; + if (braces === 0) { + braceEscaped = false; + isBrace = token.isBrace = true; + finished7 = true; + break; + } + } + } + if (scanToEnd === true) { + continue; + } + break; + } + if (code2 === CHAR_FORWARD_SLASH) { + slashes.push(index); + tokens.push(token); + token = { value: "", depth: 0, isGlob: false }; + if (finished7 === true) continue; + if (prev === CHAR_DOT && index === start + 1) { + start += 2; + continue; + } + lastIndex = index + 1; + continue; + } + if (opts.noext !== true) { + const isExtglobChar = code2 === CHAR_PLUS || code2 === CHAR_AT || code2 === CHAR_ASTERISK || code2 === CHAR_QUESTION_MARK || code2 === CHAR_EXCLAMATION_MARK; + if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + isExtglob = token.isExtglob = true; + finished7 = true; + if (code2 === CHAR_EXCLAMATION_MARK && index === start) { + negatedExtglob = true; + } + if (scanToEnd === true) { + while (eos() !== true && (code2 = advance())) { + if (code2 === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code2 = advance(); + continue; + } + if (code2 === CHAR_RIGHT_PARENTHESES) { + isGlob = token.isGlob = true; + finished7 = true; + break; + } + } + continue; + } + break; + } + } + if (code2 === CHAR_ASTERISK) { + if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; + isGlob = token.isGlob = true; + finished7 = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code2 === CHAR_QUESTION_MARK) { + isGlob = token.isGlob = true; + finished7 = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code2 === CHAR_LEFT_SQUARE_BRACKET) { + while (eos() !== true && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + isBracket = token.isBracket = true; + isGlob = token.isGlob = true; + finished7 = true; + break; + } + } + if (scanToEnd === true) { + continue; + } + break; + } + if (opts.nonegate !== true && code2 === CHAR_EXCLAMATION_MARK && index === start) { + negated = token.negated = true; + start++; + continue; + } + if (opts.noparen !== true && code2 === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + if (scanToEnd === true) { + while (eos() !== true && (code2 = advance())) { + if (code2 === CHAR_LEFT_PARENTHESES) { + backslashes = token.backslashes = true; + code2 = advance(); + continue; + } + if (code2 === CHAR_RIGHT_PARENTHESES) { + finished7 = true; + break; + } + } + continue; + } + break; + } + if (isGlob === true) { + finished7 = true; + if (scanToEnd === true) { + continue; + } + break; + } + } + if (opts.noext === true) { + isExtglob = false; + isGlob = false; + } + let base = str; + let prefix = ""; + let glob = ""; + if (start > 0) { + prefix = str.slice(0, start); + str = str.slice(start); + lastIndex -= start; + } + if (base && isGlob === true && lastIndex > 0) { + base = str.slice(0, lastIndex); + glob = str.slice(lastIndex); + } else if (isGlob === true) { + base = ""; + glob = str; + } else { + base = str; + } + if (base && base !== "" && base !== "/" && base !== str) { + if (isPathSeparator(base.charCodeAt(base.length - 1))) { + base = base.slice(0, -1); + } + } + if (opts.unescape === true) { + if (glob) glob = utils.removeBackslashes(glob); + if (base && backslashes === true) { + base = utils.removeBackslashes(base); + } + } + const state = { + prefix, + input, + start, + base, + glob, + isBrace, + isBracket, + isGlob, + isExtglob, + isGlobstar, + negated, + negatedExtglob + }; + if (opts.tokens === true) { + state.maxDepth = 0; + if (!isPathSeparator(code2)) { + tokens.push(token); + } + state.tokens = tokens; + } + if (opts.parts === true || opts.tokens === true) { + let prevIndex; + for (let idx = 0; idx < slashes.length; idx++) { + const n2 = prevIndex ? prevIndex + 1 : start; + const i2 = slashes[idx]; + const value = input.slice(n2, i2); + if (opts.tokens) { + if (idx === 0 && start !== 0) { + tokens[idx].isPrefix = true; + tokens[idx].value = prefix; + } else { + tokens[idx].value = value; + } + depth(tokens[idx]); + state.maxDepth += tokens[idx].depth; + } + if (idx !== 0 || value !== "") { + parts.push(value); + } + prevIndex = i2; + } + if (prevIndex && prevIndex + 1 < input.length) { + const value = input.slice(prevIndex + 1); + parts.push(value); + if (opts.tokens) { + tokens[tokens.length - 1].value = value; + depth(tokens[tokens.length - 1]); + state.maxDepth += tokens[tokens.length - 1].depth; + } + } + state.slashes = slashes; + state.parts = parts; + } + return state; + }; + module2.exports = scan; + } +}); + +// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/parse.js +var require_parse3 = __commonJS({ + "../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/parse.js"(exports2, module2) { + "use strict"; + var constants4 = require_constants6(); + var utils = require_utils3(); + var { + MAX_LENGTH, + POSIX_REGEX_SOURCE, + REGEX_NON_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_BACKREF, + REPLACEMENTS + } = constants4; + var expandRange = (args, options) => { + if (typeof options.expandRange === "function") { + return options.expandRange(...args, options); + } + args.sort(); + const value = `[${args.join("-")}]`; + try { + new RegExp(value); + } catch (ex) { + return args.map((v) => utils.escapeRegex(v)).join(".."); + } + return value; + }; + var syntaxError = (type, char) => { + return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; + }; + var splitTopLevel = (input) => { + const parts = []; + let bracket = 0; + let paren = 0; + let quote = 0; + let value = ""; + let escaped = false; + for (const ch of input) { + if (escaped === true) { + value += ch; + escaped = false; + continue; + } + if (ch === "\\") { + value += ch; + escaped = true; + continue; + } + if (ch === '"') { + quote = quote === 1 ? 0 : 1; + value += ch; + continue; + } + if (quote === 0) { + if (ch === "[") { + bracket++; + } else if (ch === "]" && bracket > 0) { + bracket--; + } else if (bracket === 0) { + if (ch === "(") { + paren++; + } else if (ch === ")" && paren > 0) { + paren--; + } else if (ch === "|" && paren === 0) { + parts.push(value); + value = ""; + continue; + } + } + } + value += ch; + } + parts.push(value); + return parts; + }; + var isPlainBranch = (branch) => { + let escaped = false; + for (const ch of branch) { + if (escaped === true) { + escaped = false; + continue; + } + if (ch === "\\") { + escaped = true; + continue; + } + if (/[?*+@!()[\]{}]/.test(ch)) { + return false; + } + } + return true; + }; + var normalizeSimpleBranch = (branch) => { + let value = branch.trim(); + let changed = true; + while (changed === true) { + changed = false; + if (/^@\([^\\()[\]{}|]+\)$/.test(value)) { + value = value.slice(2, -1); + changed = true; + } + } + if (!isPlainBranch(value)) { + return; + } + return value.replace(/\\(.)/g, "$1"); + }; + var hasRepeatedCharPrefixOverlap = (branches) => { + const values = branches.map(normalizeSimpleBranch).filter(Boolean); + for (let i2 = 0; i2 < values.length; i2++) { + for (let j = i2 + 1; j < values.length; j++) { + const a2 = values[i2]; + const b = values[j]; + const char = a2[0]; + if (!char || a2 !== char.repeat(a2.length) || b !== char.repeat(b.length)) { + continue; + } + if (a2 === b || a2.startsWith(b) || b.startsWith(a2)) { + return true; + } + } + } + return false; + }; + var parseRepeatedExtglob = (pattern, requireEnd = true) => { + if (pattern[0] !== "+" && pattern[0] !== "*" || pattern[1] !== "(") { + return; + } + let bracket = 0; + let paren = 0; + let quote = 0; + let escaped = false; + for (let i2 = 1; i2 < pattern.length; i2++) { + const ch = pattern[i2]; + if (escaped === true) { + escaped = false; + continue; + } + if (ch === "\\") { + escaped = true; + continue; + } + if (ch === '"') { + quote = quote === 1 ? 0 : 1; + continue; + } + if (quote === 1) { + continue; + } + if (ch === "[") { + bracket++; + continue; + } + if (ch === "]" && bracket > 0) { + bracket--; + continue; + } + if (bracket > 0) { + continue; + } + if (ch === "(") { + paren++; + continue; + } + if (ch === ")") { + paren--; + if (paren === 0) { + if (requireEnd === true && i2 !== pattern.length - 1) { + return; + } + return { + type: pattern[0], + body: pattern.slice(2, i2), + end: i2 + }; + } + } + } + }; + var buildCharClassStar = (chars) => { + const source = chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`; + return `${source}*`; + }; + var getStarExtglobSequenceChars = (pattern) => { + let index = 0; + const chars = []; + while (index < pattern.length) { + const match = parseRepeatedExtglob(pattern.slice(index), false); + if (!match || match.type !== "*") { + return; + } + const branches = splitTopLevel(match.body).map((branch2) => branch2.trim()); + if (branches.length !== 1) { + return; + } + const branch = normalizeSimpleBranch(branches[0]); + if (!branch || branch.length !== 1) { + return; + } + chars.push(branch); + index += match.end + 1; + } + if (chars.length < 1) { + return; + } + return chars; + }; + var repeatedExtglobRecursion = (pattern) => { + let depth = 0; + let value = pattern.trim(); + let match = parseRepeatedExtglob(value); + while (match) { + depth++; + value = match.body.trim(); + match = parseRepeatedExtglob(value); + } + return depth; + }; + var analyzeRepeatedExtglob = (body, options) => { + if (options.maxExtglobRecursion === false) { + return { risky: false }; + } + const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants4.DEFAULT_MAX_EXTGLOB_RECURSION; + const branches = splitTopLevel(body).map((branch) => branch.trim()); + if (branches.length > 1) { + if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) { + return { risky: true }; + } + } + const safeChars = []; + let sawStarSequence = false; + let combinable = true; + for (const branch of branches) { + const chars = getStarExtglobSequenceChars(branch); + if (chars) { + sawStarSequence = true; + safeChars.push(...chars); + continue; + } + const literal = normalizeSimpleBranch(branch); + if (literal && literal.length === 1) { + safeChars.push(literal); + continue; + } + combinable = false; + if (repeatedExtglobRecursion(branch) > max) { + return { risky: true }; + } + } + if (sawStarSequence) { + return combinable ? { risky: true, safeOutput: buildCharClassStar([...new Set(safeChars)]) } : { risky: true }; + } + return { risky: false }; + }; + var parse = (input, options) => { + if (typeof input !== "string") { + throw new TypeError("Expected a string"); + } + input = REPLACEMENTS[input] || input; + const opts = { ...options }; + const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + const bos = { type: "bos", value: "", output: opts.prepend || "" }; + const tokens = [bos]; + const capture = opts.capture ? "" : "?:"; + const PLATFORM_CHARS = constants4.globChars(opts.windows); + const EXTGLOB_CHARS = constants4.extglobChars(PLATFORM_CHARS); + const { + DOT_LITERAL, + PLUS_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK, + QMARK_NO_DOT, + STAR, + START_ANCHOR + } = PLATFORM_CHARS; + const globstar = (opts2) => { + return `(${capture}(?:(?!${START_ANCHOR}${opts2.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; + const nodot = opts.dot ? "" : NO_DOT; + const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; + let star = opts.bash === true ? globstar(opts) : STAR; + if (opts.capture) { + star = `(${star})`; + } + if (typeof opts.noext === "boolean") { + opts.noextglob = opts.noext; + } + const state = { + input, + index: -1, + start: 0, + dot: opts.dot === true, + consumed: "", + output: "", + prefix: "", + backtrack: false, + negated: false, + brackets: 0, + braces: 0, + parens: 0, + quotes: 0, + globstar: false, + tokens + }; + input = utils.removePrefix(input, state); + len = input.length; + const extglobs = []; + const braces = []; + const stack = []; + let prev = bos; + let value; + const eos = () => state.index === len - 1; + const peek = state.peek = (n2 = 1) => input[state.index + n2]; + const advance = state.advance = () => input[++state.index] || ""; + const remaining = () => input.slice(state.index + 1); + const consume = (value2 = "", num = 0) => { + state.consumed += value2; + state.index += num; + }; + const append = (token) => { + state.output += token.output != null ? token.output : token.value; + consume(token.value); + }; + const negate = () => { + let count2 = 1; + while (peek() === "!" && (peek(2) !== "(" || peek(3) === "?")) { + advance(); + state.start++; + count2++; + } + if (count2 % 2 === 0) { + return false; + } + state.negated = true; + state.start++; + return true; + }; + const increment2 = (type) => { + state[type]++; + stack.push(type); + }; + const decrement = (type) => { + state[type]--; + stack.pop(); + }; + const push = (tok) => { + if (prev.type === "globstar") { + const isBrace = state.braces > 0 && (tok.type === "comma" || tok.type === "brace"); + const isExtglob = tok.extglob === true || extglobs.length && (tok.type === "pipe" || tok.type === "paren"); + if (tok.type !== "slash" && tok.type !== "paren" && !isBrace && !isExtglob) { + state.output = state.output.slice(0, -prev.output.length); + prev.type = "star"; + prev.value = "*"; + prev.output = star; + state.output += prev.output; + } + } + if (extglobs.length && tok.type !== "paren") { + extglobs[extglobs.length - 1].inner += tok.value; + } + if (tok.value || tok.output) append(tok); + if (prev && prev.type === "text" && tok.type === "text") { + prev.output = (prev.output || prev.value) + tok.value; + prev.value += tok.value; + return; + } + tok.prev = prev; + tokens.push(tok); + prev = tok; + }; + const extglobOpen = (type, value2) => { + const token = { ...EXTGLOB_CHARS[value2], conditions: 1, inner: "" }; + token.prev = prev; + token.parens = state.parens; + token.output = state.output; + token.startIndex = state.index; + token.tokensIndex = tokens.length; + const output = (opts.capture ? "(" : "") + token.open; + increment2("parens"); + push({ type, value: value2, output: state.output ? "" : ONE_CHAR }); + push({ type: "paren", extglob: true, value: advance(), output }); + extglobs.push(token); + }; + const extglobClose = (token) => { + const literal = input.slice(token.startIndex, state.index + 1); + const body = input.slice(token.startIndex + 2, state.index); + const analysis = analyzeRepeatedExtglob(body, opts); + if ((token.type === "plus" || token.type === "star") && analysis.risky) { + const safeOutput = analysis.safeOutput ? (token.output ? "" : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput) : void 0; + const open = tokens[token.tokensIndex]; + open.type = "text"; + open.value = literal; + open.output = safeOutput || utils.escapeRegex(literal); + for (let i2 = token.tokensIndex + 1; i2 < tokens.length; i2++) { + tokens[i2].value = ""; + tokens[i2].output = ""; + delete tokens[i2].suffix; + } + state.output = token.output + open.output; + state.backtrack = true; + push({ type: "paren", extglob: true, value, output: "" }); + decrement("parens"); + return; + } + let output = token.close + (opts.capture ? ")" : ""); + let rest; + if (token.type === "negate") { + let extglobStar = star; + if (token.inner && token.inner.length > 1 && token.inner.includes("/")) { + extglobStar = globstar(opts); + } + if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { + output = token.close = `)$))${extglobStar}`; + } + if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { + const expression = parse(rest, { ...options, fastpaths: false }).output; + output = token.close = `)${expression})${extglobStar})`; + } + if (token.prev.type === "bos") { + state.negatedExtglob = true; + } + } + push({ type: "paren", extglob: true, value, output }); + decrement("parens"); + }; + if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { + let backslashes = false; + let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { + if (first === "\\") { + backslashes = true; + return m; + } + if (first === "?") { + if (esc) { + return esc + first + (rest ? QMARK.repeat(rest.length) : ""); + } + if (index === 0) { + return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ""); + } + return QMARK.repeat(chars.length); + } + if (first === ".") { + return DOT_LITERAL.repeat(chars.length); + } + if (first === "*") { + if (esc) { + return esc + first + (rest ? star : ""); + } + return star; + } + return esc ? m : `\\${m}`; + }); + if (backslashes === true) { + if (opts.unescape === true) { + output = output.replace(/\\/g, ""); + } else { + output = output.replace(/\\+/g, (m) => { + return m.length % 2 === 0 ? "\\\\" : m ? "\\" : ""; + }); + } + } + if (output === input && opts.contains === true) { + state.output = input; + return state; + } + state.output = utils.wrapOutput(output, state, options); + return state; + } + while (!eos()) { + value = advance(); + if (value === "\0") { + continue; + } + if (value === "\\") { + const next = peek(); + if (next === "/" && opts.bash !== true) { + continue; + } + if (next === "." || next === ";") { + continue; + } + if (!next) { + value += "\\"; + push({ type: "text", value }); + continue; + } + const match = /^\\+/.exec(remaining()); + let slashes = 0; + if (match && match[0].length > 2) { + slashes = match[0].length; + state.index += slashes; + if (slashes % 2 !== 0) { + value += "\\"; + } + } + if (opts.unescape === true) { + value = advance(); + } else { + value += advance(); + } + if (state.brackets === 0) { + push({ type: "text", value }); + continue; + } + } + if (state.brackets > 0 && (value !== "]" || prev.value === "[" || prev.value === "[^")) { + if (opts.posix !== false && value === ":") { + const inner = prev.value.slice(1); + if (inner.includes("[")) { + prev.posix = true; + if (inner.includes(":")) { + const idx = prev.value.lastIndexOf("["); + const pre = prev.value.slice(0, idx); + const rest2 = prev.value.slice(idx + 2); + const posix = POSIX_REGEX_SOURCE[rest2]; + if (posix) { + prev.value = pre + posix; + state.backtrack = true; + advance(); + if (!bos.output && tokens.indexOf(prev) === 1) { + bos.output = ONE_CHAR; + } + continue; + } + } + } + } + if (value === "[" && peek() !== ":" || value === "-" && peek() === "]") { + value = `\\${value}`; + } + if (value === "]" && (prev.value === "[" || prev.value === "[^")) { + value = `\\${value}`; + } + if (opts.posix === true && value === "!" && prev.value === "[") { + value = "^"; + } + prev.value += value; + append({ value }); + continue; + } + if (state.quotes === 1 && value !== '"') { + value = utils.escapeRegex(value); + prev.value += value; + append({ value }); + continue; + } + if (value === '"') { + state.quotes = state.quotes === 1 ? 0 : 1; + if (opts.keepQuotes === true) { + push({ type: "text", value }); + } + continue; + } + if (value === "(") { + increment2("parens"); + push({ type: "paren", value }); + continue; + } + if (value === ")") { + if (state.parens === 0 && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("opening", "(")); + } + const extglob = extglobs[extglobs.length - 1]; + if (extglob && state.parens === extglob.parens + 1) { + extglobClose(extglobs.pop()); + continue; + } + push({ type: "paren", value, output: state.parens ? ")" : "\\)" }); + decrement("parens"); + continue; + } + if (value === "[") { + if (opts.nobracket === true || !remaining().includes("]")) { + if (opts.nobracket !== true && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("closing", "]")); + } + value = `\\${value}`; + } else { + increment2("brackets"); + } + push({ type: "bracket", value }); + continue; + } + if (value === "]") { + if (opts.nobracket === true || prev && prev.type === "bracket" && prev.value.length === 1) { + push({ type: "text", value, output: `\\${value}` }); + continue; + } + if (state.brackets === 0) { + if (opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("opening", "[")); + } + push({ type: "text", value, output: `\\${value}` }); + continue; + } + decrement("brackets"); + const prevValue = prev.value.slice(1); + if (prev.posix !== true && prevValue[0] === "^" && !prevValue.includes("/")) { + value = `/${value}`; + } + prev.value += value; + append({ value }); + if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { + continue; + } + const escaped = utils.escapeRegex(prev.value); + state.output = state.output.slice(0, -prev.value.length); + if (opts.literalBrackets === true) { + state.output += escaped; + prev.value = escaped; + continue; + } + prev.value = `(${capture}${escaped}|${prev.value})`; + state.output += prev.value; + continue; + } + if (value === "{" && opts.nobrace !== true) { + increment2("braces"); + const open = { + type: "brace", + value, + output: "(", + outputIndex: state.output.length, + tokensIndex: state.tokens.length + }; + braces.push(open); + push(open); + continue; + } + if (value === "}") { + const brace = braces[braces.length - 1]; + if (opts.nobrace === true || !brace) { + push({ type: "text", value, output: value }); + continue; + } + let output = ")"; + if (brace.dots === true) { + const arr = tokens.slice(); + const range = []; + for (let i2 = arr.length - 1; i2 >= 0; i2--) { + tokens.pop(); + if (arr[i2].type === "brace") { + break; + } + if (arr[i2].type !== "dots") { + range.unshift(arr[i2].value); + } + } + output = expandRange(range, opts); + state.backtrack = true; + } + if (brace.comma !== true && brace.dots !== true) { + const out = state.output.slice(0, brace.outputIndex); + const toks = state.tokens.slice(brace.tokensIndex); + brace.value = brace.output = "\\{"; + value = output = "\\}"; + state.output = out; + for (const t of toks) { + state.output += t.output || t.value; + } + } + push({ type: "brace", value, output }); + decrement("braces"); + braces.pop(); + continue; + } + if (value === "|") { + if (extglobs.length > 0) { + extglobs[extglobs.length - 1].conditions++; + } + push({ type: "text", value }); + continue; + } + if (value === ",") { + let output = value; + const brace = braces[braces.length - 1]; + if (brace && stack[stack.length - 1] === "braces") { + brace.comma = true; + output = "|"; + } + push({ type: "comma", value, output }); + continue; + } + if (value === "/") { + if (prev.type === "dot" && state.index === state.start + 1) { + state.start = state.index + 1; + state.consumed = ""; + state.output = ""; + tokens.pop(); + prev = bos; + continue; + } + push({ type: "slash", value, output: SLASH_LITERAL }); + continue; + } + if (value === ".") { + if (state.braces > 0 && prev.type === "dot") { + if (prev.value === ".") prev.output = DOT_LITERAL; + const brace = braces[braces.length - 1]; + prev.type = "dots"; + prev.output += value; + prev.value += value; + brace.dots = true; + continue; + } + if (state.braces + state.parens === 0 && prev.type !== "bos" && prev.type !== "slash") { + push({ type: "text", value, output: DOT_LITERAL }); + continue; + } + push({ type: "dot", value, output: DOT_LITERAL }); + continue; + } + if (value === "?") { + const isGroup = prev && prev.value === "("; + if (!isGroup && opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + extglobOpen("qmark", value); + continue; + } + if (prev && prev.type === "paren") { + const next = peek(); + let output = value; + if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) { + output = `\\${value}`; + } + push({ type: "text", value, output }); + continue; + } + if (opts.dot !== true && (prev.type === "slash" || prev.type === "bos")) { + push({ type: "qmark", value, output: QMARK_NO_DOT }); + continue; + } + push({ type: "qmark", value, output: QMARK }); + continue; + } + if (value === "!") { + if (opts.noextglob !== true && peek() === "(") { + if (peek(2) !== "?" || !/[!=<:]/.test(peek(3))) { + extglobOpen("negate", value); + continue; + } + } + if (opts.nonegate !== true && state.index === 0) { + negate(); + continue; + } + } + if (value === "+") { + if (opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + extglobOpen("plus", value); + continue; + } + if (prev && prev.value === "(" || opts.regex === false) { + push({ type: "plus", value, output: PLUS_LITERAL }); + continue; + } + if (prev && (prev.type === "bracket" || prev.type === "paren" || prev.type === "brace") || state.parens > 0) { + push({ type: "plus", value }); + continue; + } + push({ type: "plus", value: PLUS_LITERAL }); + continue; + } + if (value === "@") { + if (opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + push({ type: "at", extglob: true, value, output: "" }); + continue; + } + push({ type: "text", value }); + continue; + } + if (value !== "*") { + if (value === "$" || value === "^") { + value = `\\${value}`; + } + const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); + if (match) { + value += match[0]; + state.index += match[0].length; + } + push({ type: "text", value }); + continue; + } + if (prev && (prev.type === "globstar" || prev.star === true)) { + prev.type = "star"; + prev.star = true; + prev.value += value; + prev.output = star; + state.backtrack = true; + state.globstar = true; + consume(value); + continue; + } + let rest = remaining(); + if (opts.noextglob !== true && /^\([^?]/.test(rest)) { + extglobOpen("star", value); + continue; + } + if (prev.type === "star") { + if (opts.noglobstar === true) { + consume(value); + continue; + } + const prior = prev.prev; + const before = prior.prev; + const isStart = prior.type === "slash" || prior.type === "bos"; + const afterStar = before && (before.type === "star" || before.type === "globstar"); + if (opts.bash === true && (!isStart || rest[0] && rest[0] !== "/")) { + push({ type: "star", value, output: "" }); + continue; + } + const isBrace = state.braces > 0 && (prior.type === "comma" || prior.type === "brace"); + const isExtglob = extglobs.length && (prior.type === "pipe" || prior.type === "paren"); + if (!isStart && prior.type !== "paren" && !isBrace && !isExtglob) { + push({ type: "star", value, output: "" }); + continue; + } + while (rest.slice(0, 3) === "/**") { + const after = input[state.index + 4]; + if (after && after !== "/") { + break; + } + rest = rest.slice(3); + consume("/**", 3); + } + if (prior.type === "bos" && eos()) { + prev.type = "globstar"; + prev.value += value; + prev.output = globstar(opts); + state.output = prev.output; + state.globstar = true; + consume(value); + continue; + } + if (prior.type === "slash" && prior.prev.type !== "bos" && !afterStar && eos()) { + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; + prev.type = "globstar"; + prev.output = globstar(opts) + (opts.strictSlashes ? ")" : "|$)"); + prev.value += value; + state.globstar = true; + state.output += prior.output + prev.output; + consume(value); + continue; + } + if (prior.type === "slash" && prior.prev.type !== "bos" && rest[0] === "/") { + const end = rest[1] !== void 0 ? "|$" : ""; + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; + prev.type = "globstar"; + prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; + prev.value += value; + state.output += prior.output + prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: "slash", value: "/", output: "" }); + continue; + } + if (prior.type === "bos" && rest[0] === "/") { + prev.type = "globstar"; + prev.value += value; + prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; + state.output = prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: "slash", value: "/", output: "" }); + continue; + } + state.output = state.output.slice(0, -prev.output.length); + prev.type = "globstar"; + prev.output = globstar(opts); + prev.value += value; + state.output += prev.output; + state.globstar = true; + consume(value); + continue; + } + const token = { type: "star", value, output: star }; + if (opts.bash === true) { + token.output = ".*?"; + if (prev.type === "bos" || prev.type === "slash") { + token.output = nodot + token.output; + } + push(token); + continue; + } + if (prev && (prev.type === "bracket" || prev.type === "paren") && opts.regex === true) { + token.output = value; + push(token); + continue; + } + if (state.index === state.start || prev.type === "slash" || prev.type === "dot") { + if (prev.type === "dot") { + state.output += NO_DOT_SLASH; + prev.output += NO_DOT_SLASH; + } else if (opts.dot === true) { + state.output += NO_DOTS_SLASH; + prev.output += NO_DOTS_SLASH; + } else { + state.output += nodot; + prev.output += nodot; + } + if (peek() !== "*") { + state.output += ONE_CHAR; + prev.output += ONE_CHAR; + } + } + push(token); + } + while (state.brackets > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError("closing", "]")); + state.output = utils.escapeLast(state.output, "["); + decrement("brackets"); + } + while (state.parens > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError("closing", ")")); + state.output = utils.escapeLast(state.output, "("); + decrement("parens"); + } + while (state.braces > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError("closing", "}")); + state.output = utils.escapeLast(state.output, "{"); + decrement("braces"); + } + if (opts.strictSlashes !== true && (prev.type === "star" || prev.type === "bracket")) { + push({ type: "maybe_slash", value: "", output: `${SLASH_LITERAL}?` }); + } + if (state.backtrack === true) { + state.output = ""; + for (const token of state.tokens) { + state.output += token.output != null ? token.output : token.value; + if (token.suffix) { + state.output += token.suffix; + } + } + } + return state; + }; + parse.fastpaths = (input, options) => { + const opts = { ...options }; + const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + const len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + input = REPLACEMENTS[input] || input; + const { + DOT_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOTS_SLASH, + STAR, + START_ANCHOR + } = constants4.globChars(opts.windows); + const nodot = opts.dot ? NO_DOTS : NO_DOT; + const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; + const capture = opts.capture ? "" : "?:"; + const state = { negated: false, prefix: "" }; + let star = opts.bash === true ? ".*?" : STAR; + if (opts.capture) { + star = `(${star})`; + } + const globstar = (opts2) => { + if (opts2.noglobstar === true) return star; + return `(${capture}(?:(?!${START_ANCHOR}${opts2.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; + const create = (str) => { + switch (str) { + case "*": + return `${nodot}${ONE_CHAR}${star}`; + case ".*": + return `${DOT_LITERAL}${ONE_CHAR}${star}`; + case "*.*": + return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + case "*/*": + return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; + case "**": + return nodot + globstar(opts); + case "**/*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; + case "**/*.*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + case "**/.*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; + default: { + const match = /^(.*?)\.(\w+)$/.exec(str); + if (!match) return; + const source2 = create(match[1]); + if (!source2) return; + return source2 + DOT_LITERAL + match[2]; + } + } + }; + const output = utils.removePrefix(input, state); + let source = create(output); + if (source && opts.strictSlashes !== true) { + source += `${SLASH_LITERAL}?`; + } + return source; + }; + module2.exports = parse; + } +}); + +// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/picomatch.js +var require_picomatch = __commonJS({ + "../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/picomatch.js"(exports2, module2) { + "use strict"; + var scan = require_scan(); + var parse = require_parse3(); + var utils = require_utils3(); + var constants4 = require_constants6(); + var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val); + var picomatch = (glob, options, returnState = false) => { + if (Array.isArray(glob)) { + const fns = glob.map((input) => picomatch(input, options, returnState)); + const arrayMatcher = (str) => { + for (const isMatch of fns) { + const state2 = isMatch(str); + if (state2) return state2; + } + return false; + }; + return arrayMatcher; + } + const isState = isObject2(glob) && glob.tokens && glob.input; + if (glob === "" || typeof glob !== "string" && !isState) { + throw new TypeError("Expected pattern to be a non-empty string"); + } + const opts = options || {}; + const posix = opts.windows; + const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true); + const state = regex.state; + delete regex.state; + let isIgnored = () => false; + if (opts.ignore) { + const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; + isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); + } + const matcher = (input, returnObject = false) => { + const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); + const result = { glob, state, regex, posix, input, output, match, isMatch }; + if (typeof opts.onResult === "function") { + opts.onResult(result); + } + if (isMatch === false) { + result.isMatch = false; + return returnObject ? result : false; + } + if (isIgnored(input)) { + if (typeof opts.onIgnore === "function") { + opts.onIgnore(result); + } + result.isMatch = false; + return returnObject ? result : false; + } + if (typeof opts.onMatch === "function") { + opts.onMatch(result); + } + return returnObject ? result : true; + }; + if (returnState) { + matcher.state = state; + } + return matcher; + }; + picomatch.test = (input, regex, options, { glob, posix } = {}) => { + if (typeof input !== "string") { + throw new TypeError("Expected input to be a string"); + } + if (input === "") { + return { isMatch: false, output: "" }; + } + const opts = options || {}; + const format2 = opts.format || (posix ? utils.toPosixSlashes : null); + let match = input === glob; + let output = match && format2 ? format2(input) : input; + if (match === false) { + output = format2 ? format2(input) : input; + match = output === glob; + } + if (match === false || opts.capture === true) { + if (opts.matchBase === true || opts.basename === true) { + match = picomatch.matchBase(input, regex, options, posix); + } else { + match = regex.exec(output); + } + } + return { isMatch: Boolean(match), match, output }; + }; + picomatch.matchBase = (input, glob, options, posix = options && options.windows) => { + const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); + return regex.test(utils.basename(input, { windows: posix })); + }; + picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); + picomatch.parse = (pattern, options) => { + if (Array.isArray(pattern)) return pattern.map((p) => picomatch.parse(p, options)); + return parse(pattern, { ...options, fastpaths: false }); + }; + picomatch.scan = (input, options) => scan(input, options); + picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { + if (returnOutput === true) { + return state.output; + } + const opts = options || {}; + const prepend = opts.contains ? "" : "^"; + const append = opts.contains ? "" : "$"; + let source = `${prepend}(?:${state.output})${append}`; + if (state && state.negated === true) { + source = `^(?!${source}).*$`; + } + const regex = picomatch.toRegex(source, options); + if (returnState === true) { + regex.state = state; + } + return regex; + }; + picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { + if (!input || typeof input !== "string") { + throw new TypeError("Expected a non-empty string"); + } + let parsed = { negated: false, fastpaths: true }; + if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) { + parsed.output = parse.fastpaths(input, options); + } + if (!parsed.output) { + parsed = parse(input, options); + } + return picomatch.compileRe(parsed, options, returnOutput, returnState); + }; + picomatch.toRegex = (source, options) => { + try { + const opts = options || {}; + return new RegExp(source, opts.flags || (opts.nocase ? "i" : "")); + } catch (err) { + if (options && options.debug === true) throw err; + return /$^/; + } + }; + picomatch.constants = constants4; + module2.exports = picomatch; + } +}); + +// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/index.js +var require_picomatch2 = __commonJS({ + "../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/index.js"(exports2, module2) { + "use strict"; + var pico = require_picomatch(); + var utils = require_utils3(); + function picomatch(glob, options, returnState = false) { + if (options && (options.windows === null || options.windows === void 0)) { + options = { ...options, windows: utils.isWindows() }; + } + return pico(glob, options, returnState); + } + Object.assign(picomatch, pico); + module2.exports = picomatch; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js +var require_identity = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js"(exports2) { + "use strict"; + var ALIAS = /* @__PURE__ */ Symbol.for("yaml.alias"); + var DOC = /* @__PURE__ */ Symbol.for("yaml.document"); + var MAP = /* @__PURE__ */ Symbol.for("yaml.map"); + var PAIR = /* @__PURE__ */ Symbol.for("yaml.pair"); + var SCALAR = /* @__PURE__ */ Symbol.for("yaml.scalar"); + var SEQ = /* @__PURE__ */ Symbol.for("yaml.seq"); + var NODE_TYPE = /* @__PURE__ */ Symbol.for("yaml.node.type"); + var isAlias = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === ALIAS; + var isDocument = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === DOC; + var isMap = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === MAP; + var isPair = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === PAIR; + var isScalar = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === SCALAR; + var isSeq = (node) => !!node && typeof node === "object" && node[NODE_TYPE] === SEQ; + function isCollection(node) { + if (node && typeof node === "object") + switch (node[NODE_TYPE]) { + case MAP: + case SEQ: + return true; + } + return false; + } + function isNode(node) { + if (node && typeof node === "object") + switch (node[NODE_TYPE]) { + case ALIAS: + case MAP: + case SCALAR: + case SEQ: + return true; + } + return false; + } + var hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor; + exports2.ALIAS = ALIAS; + exports2.DOC = DOC; + exports2.MAP = MAP; + exports2.NODE_TYPE = NODE_TYPE; + exports2.PAIR = PAIR; + exports2.SCALAR = SCALAR; + exports2.SEQ = SEQ; + exports2.hasAnchor = hasAnchor; + exports2.isAlias = isAlias; + exports2.isCollection = isCollection; + exports2.isDocument = isDocument; + exports2.isMap = isMap; + exports2.isNode = isNode; + exports2.isPair = isPair; + exports2.isScalar = isScalar; + exports2.isSeq = isSeq; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/visit.js +var require_visit = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/visit.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var BREAK = /* @__PURE__ */ Symbol("break visit"); + var SKIP = /* @__PURE__ */ Symbol("skip children"); + var REMOVE = /* @__PURE__ */ Symbol("remove node"); + function visit(node, visitor) { + const visitor_ = initVisitor(visitor); + if (identity3.isDocument(node)) { + const cd = visit_(null, node.contents, visitor_, Object.freeze([node])); + if (cd === REMOVE) + node.contents = null; + } else + visit_(null, node, visitor_, Object.freeze([])); + } + visit.BREAK = BREAK; + visit.SKIP = SKIP; + visit.REMOVE = REMOVE; + function visit_(key, node, visitor, path12) { + const ctrl = callVisitor(key, node, visitor, path12); + if (identity3.isNode(ctrl) || identity3.isPair(ctrl)) { + replaceNode(key, path12, ctrl); + return visit_(key, ctrl, visitor, path12); + } + if (typeof ctrl !== "symbol") { + if (identity3.isCollection(node)) { + path12 = Object.freeze(path12.concat(node)); + for (let i2 = 0; i2 < node.items.length; ++i2) { + const ci = visit_(i2, node.items[i2], visitor, path12); + if (typeof ci === "number") + i2 = ci - 1; + else if (ci === BREAK) + return BREAK; + else if (ci === REMOVE) { + node.items.splice(i2, 1); + i2 -= 1; + } + } + } else if (identity3.isPair(node)) { + path12 = Object.freeze(path12.concat(node)); + const ck = visit_("key", node.key, visitor, path12); + if (ck === BREAK) + return BREAK; + else if (ck === REMOVE) + node.key = null; + const cv = visit_("value", node.value, visitor, path12); + if (cv === BREAK) + return BREAK; + else if (cv === REMOVE) + node.value = null; + } + } + return ctrl; + } + async function visitAsync(node, visitor) { + const visitor_ = initVisitor(visitor); + if (identity3.isDocument(node)) { + const cd = await visitAsync_(null, node.contents, visitor_, Object.freeze([node])); + if (cd === REMOVE) + node.contents = null; + } else + await visitAsync_(null, node, visitor_, Object.freeze([])); + } + visitAsync.BREAK = BREAK; + visitAsync.SKIP = SKIP; + visitAsync.REMOVE = REMOVE; + async function visitAsync_(key, node, visitor, path12) { + const ctrl = await callVisitor(key, node, visitor, path12); + if (identity3.isNode(ctrl) || identity3.isPair(ctrl)) { + replaceNode(key, path12, ctrl); + return visitAsync_(key, ctrl, visitor, path12); + } + if (typeof ctrl !== "symbol") { + if (identity3.isCollection(node)) { + path12 = Object.freeze(path12.concat(node)); + for (let i2 = 0; i2 < node.items.length; ++i2) { + const ci = await visitAsync_(i2, node.items[i2], visitor, path12); + if (typeof ci === "number") + i2 = ci - 1; + else if (ci === BREAK) + return BREAK; + else if (ci === REMOVE) { + node.items.splice(i2, 1); + i2 -= 1; + } + } + } else if (identity3.isPair(node)) { + path12 = Object.freeze(path12.concat(node)); + const ck = await visitAsync_("key", node.key, visitor, path12); + if (ck === BREAK) + return BREAK; + else if (ck === REMOVE) + node.key = null; + const cv = await visitAsync_("value", node.value, visitor, path12); + if (cv === BREAK) + return BREAK; + else if (cv === REMOVE) + node.value = null; + } + } + return ctrl; + } + function initVisitor(visitor) { + if (typeof visitor === "object" && (visitor.Collection || visitor.Node || visitor.Value)) { + return Object.assign({ + Alias: visitor.Node, + Map: visitor.Node, + Scalar: visitor.Node, + Seq: visitor.Node + }, visitor.Value && { + Map: visitor.Value, + Scalar: visitor.Value, + Seq: visitor.Value + }, visitor.Collection && { + Map: visitor.Collection, + Seq: visitor.Collection + }, visitor); + } + return visitor; + } + function callVisitor(key, node, visitor, path12) { + if (typeof visitor === "function") + return visitor(key, node, path12); + if (identity3.isMap(node)) + return visitor.Map?.(key, node, path12); + if (identity3.isSeq(node)) + return visitor.Seq?.(key, node, path12); + if (identity3.isPair(node)) + return visitor.Pair?.(key, node, path12); + if (identity3.isScalar(node)) + return visitor.Scalar?.(key, node, path12); + if (identity3.isAlias(node)) + return visitor.Alias?.(key, node, path12); + return void 0; + } + function replaceNode(key, path12, node) { + const parent = path12[path12.length - 1]; + if (identity3.isCollection(parent)) { + parent.items[key] = node; + } else if (identity3.isPair(parent)) { + if (key === "key") + parent.key = node; + else + parent.value = node; + } else if (identity3.isDocument(parent)) { + parent.contents = node; + } else { + const pt = identity3.isAlias(parent) ? "alias" : "scalar"; + throw new Error(`Cannot replace node with ${pt} parent`); + } + } + exports2.visit = visit; + exports2.visitAsync = visitAsync; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/directives.js +var require_directives = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/directives.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var visit = require_visit(); + var escapeChars = { + "!": "%21", + ",": "%2C", + "[": "%5B", + "]": "%5D", + "{": "%7B", + "}": "%7D" + }; + var escapeTagName = (tn) => tn.replace(/[!,[\]{}]/g, (ch) => escapeChars[ch]); + var Directives = class _Directives { + constructor(yaml, tags) { + this.docStart = null; + this.docEnd = false; + this.yaml = Object.assign({}, _Directives.defaultYaml, yaml); + this.tags = Object.assign({}, _Directives.defaultTags, tags); + } + clone() { + const copy = new _Directives(this.yaml, this.tags); + copy.docStart = this.docStart; + return copy; + } + /** + * During parsing, get a Directives instance for the current document and + * update the stream state according to the current version's spec. + */ + atDocument() { + const res = new _Directives(this.yaml, this.tags); + switch (this.yaml.version) { + case "1.1": + this.atNextDocument = true; + break; + case "1.2": + this.atNextDocument = false; + this.yaml = { + explicit: _Directives.defaultYaml.explicit, + version: "1.2" + }; + this.tags = Object.assign({}, _Directives.defaultTags); + break; + } + return res; + } + /** + * @param onError - May be called even if the action was successful + * @returns `true` on success + */ + add(line, onError) { + if (this.atNextDocument) { + this.yaml = { explicit: _Directives.defaultYaml.explicit, version: "1.1" }; + this.tags = Object.assign({}, _Directives.defaultTags); + this.atNextDocument = false; + } + const parts = line.trim().split(/[ \t]+/); + const name = parts.shift(); + switch (name) { + case "%TAG": { + if (parts.length !== 2) { + onError(0, "%TAG directive should contain exactly two parts"); + if (parts.length < 2) + return false; + } + const [handle, prefix] = parts; + this.tags[handle] = prefix; + return true; + } + case "%YAML": { + this.yaml.explicit = true; + if (parts.length !== 1) { + onError(0, "%YAML directive should contain exactly one part"); + return false; + } + const [version] = parts; + if (version === "1.1" || version === "1.2") { + this.yaml.version = version; + return true; + } else { + const isValid2 = /^\d+\.\d+$/.test(version); + onError(6, `Unsupported YAML version ${version}`, isValid2); + return false; + } + } + default: + onError(0, `Unknown directive ${name}`, true); + return false; + } + } + /** + * Resolves a tag, matching handles to those defined in %TAG directives. + * + * @returns Resolved tag, which may also be the non-specific tag `'!'` or a + * `'!local'` tag, or `null` if unresolvable. + */ + tagName(source, onError) { + if (source === "!") + return "!"; + if (source[0] !== "!") { + onError(`Not a valid tag: ${source}`); + return null; + } + if (source[1] === "<") { + const verbatim = source.slice(2, -1); + if (verbatim === "!" || verbatim === "!!") { + onError(`Verbatim tags aren't resolved, so ${source} is invalid.`); + return null; + } + if (source[source.length - 1] !== ">") + onError("Verbatim tags must end with a >"); + return verbatim; + } + const [, handle, suffix] = source.match(/^(.*!)([^!]*)$/s); + if (!suffix) + onError(`The ${source} tag has no suffix`); + const prefix = this.tags[handle]; + if (prefix) { + try { + return prefix + decodeURIComponent(suffix); + } catch (error) { + onError(String(error)); + return null; + } + } + if (handle === "!") + return source; + onError(`Could not resolve tag: ${source}`); + return null; + } + /** + * Given a fully resolved tag, returns its printable string form, + * taking into account current tag prefixes and defaults. + */ + tagString(tag) { + for (const [handle, prefix] of Object.entries(this.tags)) { + if (tag.startsWith(prefix)) + return handle + escapeTagName(tag.substring(prefix.length)); + } + return tag[0] === "!" ? tag : `!<${tag}>`; + } + toString(doc) { + const lines = this.yaml.explicit ? [`%YAML ${this.yaml.version || "1.2"}`] : []; + const tagEntries = Object.entries(this.tags); + let tagNames; + if (doc && tagEntries.length > 0 && identity3.isNode(doc.contents)) { + const tags = {}; + visit.visit(doc.contents, (_key, node) => { + if (identity3.isNode(node) && node.tag) + tags[node.tag] = true; + }); + tagNames = Object.keys(tags); + } else + tagNames = []; + for (const [handle, prefix] of tagEntries) { + if (handle === "!!" && prefix === "tag:yaml.org,2002:") + continue; + if (!doc || tagNames.some((tn) => tn.startsWith(prefix))) + lines.push(`%TAG ${handle} ${prefix}`); + } + return lines.join("\n"); + } + }; + Directives.defaultYaml = { explicit: false, version: "1.2" }; + Directives.defaultTags = { "!!": "tag:yaml.org,2002:" }; + exports2.Directives = Directives; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/anchors.js +var require_anchors = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/anchors.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var visit = require_visit(); + function anchorIsValid(anchor) { + if (/[\x00-\x19\s,[\]{}]/.test(anchor)) { + const sa = JSON.stringify(anchor); + const msg = `Anchor must not contain whitespace or control characters: ${sa}`; + throw new Error(msg); + } + return true; + } + function anchorNames(root) { + const anchors = /* @__PURE__ */ new Set(); + visit.visit(root, { + Value(_key, node) { + if (node.anchor) + anchors.add(node.anchor); + } + }); + return anchors; + } + function findNewAnchor(prefix, exclude) { + for (let i2 = 1; true; ++i2) { + const name = `${prefix}${i2}`; + if (!exclude.has(name)) + return name; + } + } + function createNodeAnchors(doc, prefix) { + const aliasObjects = []; + const sourceObjects = /* @__PURE__ */ new Map(); + let prevAnchors = null; + return { + onAnchor: (source) => { + aliasObjects.push(source); + prevAnchors ?? (prevAnchors = anchorNames(doc)); + const anchor = findNewAnchor(prefix, prevAnchors); + prevAnchors.add(anchor); + return anchor; + }, + /** + * With circular references, the source node is only resolved after all + * of its child nodes are. This is why anchors are set only after all of + * the nodes have been created. + */ + setAnchors: () => { + for (const source of aliasObjects) { + const ref = sourceObjects.get(source); + if (typeof ref === "object" && ref.anchor && (identity3.isScalar(ref.node) || identity3.isCollection(ref.node))) { + ref.node.anchor = ref.anchor; + } else { + const error = new Error("Failed to resolve repeated object (this should not happen)"); + error.source = source; + throw error; + } + } + }, + sourceObjects + }; + } + exports2.anchorIsValid = anchorIsValid; + exports2.anchorNames = anchorNames; + exports2.createNodeAnchors = createNodeAnchors; + exports2.findNewAnchor = findNewAnchor; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/applyReviver.js +var require_applyReviver = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/applyReviver.js"(exports2) { + "use strict"; + function applyReviver(reviver, obj, key, val) { + if (val && typeof val === "object") { + if (Array.isArray(val)) { + for (let i2 = 0, len = val.length; i2 < len; ++i2) { + const v0 = val[i2]; + const v1 = applyReviver(reviver, val, String(i2), v0); + if (v1 === void 0) + delete val[i2]; + else if (v1 !== v0) + val[i2] = v1; + } + } else if (val instanceof Map) { + for (const k of Array.from(val.keys())) { + const v0 = val.get(k); + const v1 = applyReviver(reviver, val, k, v0); + if (v1 === void 0) + val.delete(k); + else if (v1 !== v0) + val.set(k, v1); + } + } else if (val instanceof Set) { + for (const v0 of Array.from(val)) { + const v1 = applyReviver(reviver, val, v0, v0); + if (v1 === void 0) + val.delete(v0); + else if (v1 !== v0) { + val.delete(v0); + val.add(v1); + } + } + } else { + for (const [k, v0] of Object.entries(val)) { + const v1 = applyReviver(reviver, val, k, v0); + if (v1 === void 0) + delete val[k]; + else if (v1 !== v0) + val[k] = v1; + } + } + } + return reviver.call(obj, key, val); + } + exports2.applyReviver = applyReviver; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/toJS.js +var require_toJS = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/toJS.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + function toJS(value, arg, ctx) { + if (Array.isArray(value)) + return value.map((v, i2) => toJS(v, String(i2), ctx)); + if (value && typeof value.toJSON === "function") { + if (!ctx || !identity3.hasAnchor(value)) + return value.toJSON(arg, ctx); + const data = { aliasCount: 0, count: 1, res: void 0 }; + ctx.anchors.set(value, data); + ctx.onCreate = (res2) => { + data.res = res2; + delete ctx.onCreate; + }; + const res = value.toJSON(arg, ctx); + if (ctx.onCreate) + ctx.onCreate(res); + return res; + } + if (typeof value === "bigint" && !ctx?.keep) + return Number(value); + return value; + } + exports2.toJS = toJS; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Node.js +var require_Node = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Node.js"(exports2) { + "use strict"; + var applyReviver = require_applyReviver(); + var identity3 = require_identity(); + var toJS = require_toJS(); + var NodeBase = class { + constructor(type) { + Object.defineProperty(this, identity3.NODE_TYPE, { value: type }); + } + /** Create a copy of this node. */ + clone() { + const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this)); + if (this.range) + copy.range = this.range.slice(); + return copy; + } + /** A plain JavaScript representation of this node. */ + toJS(doc, { mapAsMap, maxAliasCount, onAnchor, reviver } = {}) { + if (!identity3.isDocument(doc)) + throw new TypeError("A document argument is required"); + const ctx = { + anchors: /* @__PURE__ */ new Map(), + doc, + keep: true, + mapAsMap: mapAsMap === true, + mapKeyWarned: false, + maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100 + }; + const res = toJS.toJS(this, "", ctx); + if (typeof onAnchor === "function") + for (const { count: count2, res: res2 } of ctx.anchors.values()) + onAnchor(res2, count2); + return typeof reviver === "function" ? applyReviver.applyReviver(reviver, { "": res }, "", res) : res; + } + }; + exports2.NodeBase = NodeBase; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Alias.js +var require_Alias = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Alias.js"(exports2) { + "use strict"; + var anchors = require_anchors(); + var visit = require_visit(); + var identity3 = require_identity(); + var Node = require_Node(); + var toJS = require_toJS(); + var Alias = class extends Node.NodeBase { + constructor(source) { + super(identity3.ALIAS); + this.source = source; + Object.defineProperty(this, "tag", { + set() { + throw new Error("Alias nodes cannot have tags"); + } + }); + } + /** + * Resolve the value of this alias within `doc`, finding the last + * instance of the `source` anchor before this node. + */ + resolve(doc, ctx) { + if (ctx?.maxAliasCount === 0) + throw new ReferenceError("Alias resolution is disabled"); + let nodes; + if (ctx?.aliasResolveCache) { + nodes = ctx.aliasResolveCache; + } else { + nodes = []; + visit.visit(doc, { + Node: (_key, node) => { + if (identity3.isAlias(node) || identity3.hasAnchor(node)) + nodes.push(node); + } + }); + if (ctx) + ctx.aliasResolveCache = nodes; + } + let found = void 0; + for (const node of nodes) { + if (node === this) + break; + if (node.anchor === this.source) + found = node; + } + return found; + } + toJSON(_arg, ctx) { + if (!ctx) + return { source: this.source }; + const { anchors: anchors2, doc, maxAliasCount } = ctx; + const source = this.resolve(doc, ctx); + if (!source) { + const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`; + throw new ReferenceError(msg); + } + let data = anchors2.get(source); + if (!data) { + toJS.toJS(source, null, ctx); + data = anchors2.get(source); + } + if (data?.res === void 0) { + const msg = "This should not happen: Alias anchor was not resolved?"; + throw new ReferenceError(msg); + } + if (maxAliasCount >= 0) { + data.count += 1; + if (data.aliasCount === 0) + data.aliasCount = getAliasCount(doc, source, anchors2); + if (data.count * data.aliasCount > maxAliasCount) { + const msg = "Excessive alias count indicates a resource exhaustion attack"; + throw new ReferenceError(msg); + } + } + return data.res; + } + toString(ctx, _onComment, _onChompKeep) { + const src = `*${this.source}`; + if (ctx) { + anchors.anchorIsValid(this.source); + if (ctx.options.verifyAliasOrder && !ctx.anchors.has(this.source)) { + const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`; + throw new Error(msg); + } + if (ctx.implicitKey) + return `${src} `; + } + return src; + } + }; + function getAliasCount(doc, node, anchors2) { + if (identity3.isAlias(node)) { + const source = node.resolve(doc); + const anchor = anchors2 && source && anchors2.get(source); + return anchor ? anchor.count * anchor.aliasCount : 0; + } else if (identity3.isCollection(node)) { + let count2 = 0; + for (const item of node.items) { + const c3 = getAliasCount(doc, item, anchors2); + if (c3 > count2) + count2 = c3; + } + return count2; + } else if (identity3.isPair(node)) { + const kc = getAliasCount(doc, node.key, anchors2); + const vc = getAliasCount(doc, node.value, anchors2); + return Math.max(kc, vc); + } + return 1; + } + exports2.Alias = Alias; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Scalar.js +var require_Scalar = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Scalar.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Node = require_Node(); + var toJS = require_toJS(); + var isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object"; + var Scalar = class extends Node.NodeBase { + constructor(value) { + super(identity3.SCALAR); + this.value = value; + } + toJSON(arg, ctx) { + return ctx?.keep ? this.value : toJS.toJS(this.value, arg, ctx); + } + toString() { + return String(this.value); + } + }; + Scalar.BLOCK_FOLDED = "BLOCK_FOLDED"; + Scalar.BLOCK_LITERAL = "BLOCK_LITERAL"; + Scalar.PLAIN = "PLAIN"; + Scalar.QUOTE_DOUBLE = "QUOTE_DOUBLE"; + Scalar.QUOTE_SINGLE = "QUOTE_SINGLE"; + exports2.Scalar = Scalar; + exports2.isScalarValue = isScalarValue; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/createNode.js +var require_createNode = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/createNode.js"(exports2) { + "use strict"; + var Alias = require_Alias(); + var identity3 = require_identity(); + var Scalar = require_Scalar(); + var defaultTagPrefix = "tag:yaml.org,2002:"; + function findTagObject(value, tagName, tags) { + if (tagName) { + const match = tags.filter((t) => t.tag === tagName); + const tagObj = match.find((t) => !t.format) ?? match[0]; + if (!tagObj) + throw new Error(`Tag ${tagName} not found`); + return tagObj; + } + return tags.find((t) => t.identify?.(value) && !t.format); + } + function createNode(value, tagName, ctx) { + if (identity3.isDocument(value)) + value = value.contents; + if (identity3.isNode(value)) + return value; + if (identity3.isPair(value)) { + const map = ctx.schema[identity3.MAP].createNode?.(ctx.schema, null, ctx); + map.items.push(value); + return map; + } + if (value instanceof String || value instanceof Number || value instanceof Boolean || typeof BigInt !== "undefined" && value instanceof BigInt) { + value = value.valueOf(); + } + const { aliasDuplicateObjects, onAnchor, onTagObj, schema, sourceObjects } = ctx; + let ref = void 0; + if (aliasDuplicateObjects && value && typeof value === "object") { + ref = sourceObjects.get(value); + if (ref) { + ref.anchor ?? (ref.anchor = onAnchor(value)); + return new Alias.Alias(ref.anchor); + } else { + ref = { anchor: null, node: null }; + sourceObjects.set(value, ref); + } + } + if (tagName?.startsWith("!!")) + tagName = defaultTagPrefix + tagName.slice(2); + let tagObj = findTagObject(value, tagName, schema.tags); + if (!tagObj) { + if (value && typeof value.toJSON === "function") { + value = value.toJSON(); + } + if (!value || typeof value !== "object") { + const node2 = new Scalar.Scalar(value); + if (ref) + ref.node = node2; + return node2; + } + tagObj = value instanceof Map ? schema[identity3.MAP] : Symbol.iterator in Object(value) ? schema[identity3.SEQ] : schema[identity3.MAP]; + } + if (onTagObj) { + onTagObj(tagObj); + delete ctx.onTagObj; + } + const node = tagObj?.createNode ? tagObj.createNode(ctx.schema, value, ctx) : typeof tagObj?.nodeClass?.from === "function" ? tagObj.nodeClass.from(ctx.schema, value, ctx) : new Scalar.Scalar(value); + if (tagName) + node.tag = tagName; + else if (!tagObj.default) + node.tag = tagObj.tag; + if (ref) + ref.node = node; + return node; + } + exports2.createNode = createNode; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Collection.js +var require_Collection = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Collection.js"(exports2) { + "use strict"; + var createNode = require_createNode(); + var identity3 = require_identity(); + var Node = require_Node(); + function collectionFromPath(schema, path12, value) { + let v = value; + for (let i2 = path12.length - 1; i2 >= 0; --i2) { + const k = path12[i2]; + if (typeof k === "number" && Number.isInteger(k) && k >= 0) { + const a2 = []; + a2[k] = v; + v = a2; + } else { + v = /* @__PURE__ */ new Map([[k, v]]); + } + } + return createNode.createNode(v, void 0, { + aliasDuplicateObjects: false, + keepUndefined: false, + onAnchor: () => { + throw new Error("This should not happen, please report a bug."); + }, + schema, + sourceObjects: /* @__PURE__ */ new Map() + }); + } + var isEmptyPath = (path12) => path12 == null || typeof path12 === "object" && !!path12[Symbol.iterator]().next().done; + var Collection = class extends Node.NodeBase { + constructor(type, schema) { + super(type); + Object.defineProperty(this, "schema", { + value: schema, + configurable: true, + enumerable: false, + writable: true + }); + } + /** + * Create a copy of this collection. + * + * @param schema - If defined, overwrites the original's schema + */ + clone(schema) { + const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this)); + if (schema) + copy.schema = schema; + copy.items = copy.items.map((it) => identity3.isNode(it) || identity3.isPair(it) ? it.clone(schema) : it); + if (this.range) + copy.range = this.range.slice(); + return copy; + } + /** + * Adds a value to the collection. For `!!map` and `!!omap` the value must + * be a Pair instance or a `{ key, value }` object, which may not have a key + * that already exists in the map. + */ + addIn(path12, value) { + if (isEmptyPath(path12)) + this.add(value); + else { + const [key, ...rest] = path12; + const node = this.get(key, true); + if (identity3.isCollection(node)) + node.addIn(rest, value); + else if (node === void 0 && this.schema) + this.set(key, collectionFromPath(this.schema, rest, value)); + else + throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`); + } + } + /** + * Removes a value from the collection. + * @returns `true` if the item was found and removed. + */ + deleteIn(path12) { + const [key, ...rest] = path12; + if (rest.length === 0) + return this.delete(key); + const node = this.get(key, true); + if (identity3.isCollection(node)) + return node.deleteIn(rest); + else + throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`); + } + /** + * Returns item at `key`, or `undefined` if not found. By default unwraps + * scalar values from their surrounding node; to disable set `keepScalar` to + * `true` (collections are always returned intact). + */ + getIn(path12, keepScalar) { + const [key, ...rest] = path12; + const node = this.get(key, true); + if (rest.length === 0) + return !keepScalar && identity3.isScalar(node) ? node.value : node; + else + return identity3.isCollection(node) ? node.getIn(rest, keepScalar) : void 0; + } + hasAllNullValues(allowScalar) { + return this.items.every((node) => { + if (!identity3.isPair(node)) + return false; + const n2 = node.value; + return n2 == null || allowScalar && identity3.isScalar(n2) && n2.value == null && !n2.commentBefore && !n2.comment && !n2.tag; + }); + } + /** + * Checks if the collection includes a value with the key `key`. + */ + hasIn(path12) { + const [key, ...rest] = path12; + if (rest.length === 0) + return this.has(key); + const node = this.get(key, true); + return identity3.isCollection(node) ? node.hasIn(rest) : false; + } + /** + * Sets a value in this collection. For `!!set`, `value` needs to be a + * boolean to add/remove the item from the set. + */ + setIn(path12, value) { + const [key, ...rest] = path12; + if (rest.length === 0) { + this.set(key, value); + } else { + const node = this.get(key, true); + if (identity3.isCollection(node)) + node.setIn(rest, value); + else if (node === void 0 && this.schema) + this.set(key, collectionFromPath(this.schema, rest, value)); + else + throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`); + } + } + }; + exports2.Collection = Collection; + exports2.collectionFromPath = collectionFromPath; + exports2.isEmptyPath = isEmptyPath; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyComment.js +var require_stringifyComment = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyComment.js"(exports2) { + "use strict"; + var stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#"); + function indentComment(comment, indent) { + if (/^\n+$/.test(comment)) + return comment.substring(1); + return indent ? comment.replace(/^(?! *$)/gm, indent) : comment; + } + var lineComment = (str, indent, comment) => str.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str.endsWith(" ") ? "" : " ") + comment; + exports2.indentComment = indentComment; + exports2.lineComment = lineComment; + exports2.stringifyComment = stringifyComment; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/foldFlowLines.js +var require_foldFlowLines = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/foldFlowLines.js"(exports2) { + "use strict"; + var FOLD_FLOW = "flow"; + var FOLD_BLOCK = "block"; + var FOLD_QUOTED = "quoted"; + function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) { + if (!lineWidth || lineWidth < 0) + return text; + if (lineWidth < minContentWidth) + minContentWidth = 0; + const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length); + if (text.length <= endStep) + return text; + const folds = []; + const escapedFolds = {}; + let end = lineWidth - indent.length; + if (typeof indentAtStart === "number") { + if (indentAtStart > lineWidth - Math.max(2, minContentWidth)) + folds.push(0); + else + end = lineWidth - indentAtStart; + } + let split = void 0; + let prev = void 0; + let overflow = false; + let i2 = -1; + let escStart = -1; + let escEnd = -1; + if (mode === FOLD_BLOCK) { + i2 = consumeMoreIndentedLines(text, i2, indent.length); + if (i2 !== -1) + end = i2 + endStep; + } + for (let ch; ch = text[i2 += 1]; ) { + if (mode === FOLD_QUOTED && ch === "\\") { + escStart = i2; + switch (text[i2 + 1]) { + case "x": + i2 += 3; + break; + case "u": + i2 += 5; + break; + case "U": + i2 += 9; + break; + default: + i2 += 1; + } + escEnd = i2; + } + if (ch === "\n") { + if (mode === FOLD_BLOCK) + i2 = consumeMoreIndentedLines(text, i2, indent.length); + end = i2 + indent.length + endStep; + split = void 0; + } else { + if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") { + const next = text[i2 + 1]; + if (next && next !== " " && next !== "\n" && next !== " ") + split = i2; + } + if (i2 >= end) { + if (split) { + folds.push(split); + end = split + endStep; + split = void 0; + } else if (mode === FOLD_QUOTED) { + while (prev === " " || prev === " ") { + prev = ch; + ch = text[i2 += 1]; + overflow = true; + } + const j = i2 > escEnd + 1 ? i2 - 2 : escStart - 1; + if (escapedFolds[j]) + return text; + folds.push(j); + escapedFolds[j] = true; + end = j + endStep; + split = void 0; + } else { + overflow = true; + } + } + } + prev = ch; + } + if (overflow && onOverflow) + onOverflow(); + if (folds.length === 0) + return text; + if (onFold) + onFold(); + let res = text.slice(0, folds[0]); + for (let i3 = 0; i3 < folds.length; ++i3) { + const fold = folds[i3]; + const end2 = folds[i3 + 1] || text.length; + if (fold === 0) + res = ` +${indent}${text.slice(0, end2)}`; + else { + if (mode === FOLD_QUOTED && escapedFolds[fold]) + res += `${text[fold]}\\`; + res += ` +${indent}${text.slice(fold + 1, end2)}`; + } + } + return res; + } + function consumeMoreIndentedLines(text, i2, indent) { + let end = i2; + let start = i2 + 1; + let ch = text[start]; + while (ch === " " || ch === " ") { + if (i2 < start + indent) { + ch = text[++i2]; + } else { + do { + ch = text[++i2]; + } while (ch && ch !== "\n"); + end = i2; + start = i2 + 1; + ch = text[start]; + } + } + return end; + } + exports2.FOLD_BLOCK = FOLD_BLOCK; + exports2.FOLD_FLOW = FOLD_FLOW; + exports2.FOLD_QUOTED = FOLD_QUOTED; + exports2.foldFlowLines = foldFlowLines; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyString.js +var require_stringifyString = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyString.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var foldFlowLines = require_foldFlowLines(); + var getFoldOptions = (ctx, isBlock) => ({ + indentAtStart: isBlock ? ctx.indent.length : ctx.indentAtStart, + lineWidth: ctx.options.lineWidth, + minContentWidth: ctx.options.minContentWidth + }); + var containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str); + function lineLengthOverLimit(str, lineWidth, indentLength) { + if (!lineWidth || lineWidth < 0) + return false; + const limit = lineWidth - indentLength; + const strLen = str.length; + if (strLen <= limit) + return false; + for (let i2 = 0, start = 0; i2 < strLen; ++i2) { + if (str[i2] === "\n") { + if (i2 - start > limit) + return true; + start = i2 + 1; + if (strLen - start <= limit) + return false; + } + } + return true; + } + function doubleQuotedString(value, ctx) { + const json = JSON.stringify(value); + if (ctx.options.doubleQuotedAsJSON) + return json; + const { implicitKey } = ctx; + const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength; + const indent = ctx.indent || (containsDocumentMarker(value) ? " " : ""); + let str = ""; + let start = 0; + for (let i2 = 0, ch = json[i2]; ch; ch = json[++i2]) { + if (ch === " " && json[i2 + 1] === "\\" && json[i2 + 2] === "n") { + str += json.slice(start, i2) + "\\ "; + i2 += 1; + start = i2; + ch = "\\"; + } + if (ch === "\\") + switch (json[i2 + 1]) { + case "u": + { + str += json.slice(start, i2); + const code2 = json.substr(i2 + 2, 4); + switch (code2) { + case "0000": + str += "\\0"; + break; + case "0007": + str += "\\a"; + break; + case "000b": + str += "\\v"; + break; + case "001b": + str += "\\e"; + break; + case "0085": + str += "\\N"; + break; + case "00a0": + str += "\\_"; + break; + case "2028": + str += "\\L"; + break; + case "2029": + str += "\\P"; + break; + default: + if (code2.substr(0, 2) === "00") + str += "\\x" + code2.substr(2); + else + str += json.substr(i2, 6); + } + i2 += 5; + start = i2 + 1; + } + break; + case "n": + if (implicitKey || json[i2 + 2] === '"' || json.length < minMultiLineLength) { + i2 += 1; + } else { + str += json.slice(start, i2) + "\n\n"; + while (json[i2 + 2] === "\\" && json[i2 + 3] === "n" && json[i2 + 4] !== '"') { + str += "\n"; + i2 += 2; + } + str += indent; + if (json[i2 + 2] === " ") + str += "\\"; + i2 += 1; + start = i2 + 1; + } + break; + default: + i2 += 1; + } + } + str = start ? str + json.slice(start) : json; + return implicitKey ? str : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx, false)); + } + function singleQuotedString(value, ctx) { + if (ctx.options.singleQuote === false || ctx.implicitKey && value.includes("\n") || /[ \t]\n|\n[ \t]/.test(value)) + return doubleQuotedString(value, ctx); + const indent = ctx.indent || (containsDocumentMarker(value) ? " " : ""); + const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$& +${indent}`) + "'"; + return ctx.implicitKey ? res : foldFlowLines.foldFlowLines(res, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx, false)); + } + function quotedString(value, ctx) { + const { singleQuote } = ctx.options; + let qs; + if (singleQuote === false) + qs = doubleQuotedString; + else { + const hasDouble = value.includes('"'); + const hasSingle = value.includes("'"); + if (hasDouble && !hasSingle) + qs = singleQuotedString; + else if (hasSingle && !hasDouble) + qs = doubleQuotedString; + else + qs = singleQuote ? singleQuotedString : doubleQuotedString; + } + return qs(value, ctx); + } + var blockEndNewlines; + try { + blockEndNewlines = new RegExp("(^|(?\n"; + let chomp; + let endStart; + for (endStart = value.length; endStart > 0; --endStart) { + const ch = value[endStart - 1]; + if (ch !== "\n" && ch !== " " && ch !== " ") + break; + } + let end = value.substring(endStart); + const endNlPos = end.indexOf("\n"); + if (endNlPos === -1) { + chomp = "-"; + } else if (value === end || endNlPos !== end.length - 1) { + chomp = "+"; + if (onChompKeep) + onChompKeep(); + } else { + chomp = ""; + } + if (end) { + value = value.slice(0, -end.length); + if (end[end.length - 1] === "\n") + end = end.slice(0, -1); + end = end.replace(blockEndNewlines, `$&${indent}`); + } + let startWithSpace = false; + let startEnd; + let startNlPos = -1; + for (startEnd = 0; startEnd < value.length; ++startEnd) { + const ch = value[startEnd]; + if (ch === " ") + startWithSpace = true; + else if (ch === "\n") + startNlPos = startEnd; + else + break; + } + let start = value.substring(0, startNlPos < startEnd ? startNlPos + 1 : startEnd); + if (start) { + value = value.substring(start.length); + start = start.replace(/\n+/g, `$&${indent}`); + } + const indentSize = indent ? "2" : "1"; + let header = (startWithSpace ? indentSize : "") + chomp; + if (comment) { + header += " " + commentString(comment.replace(/ ?[\r\n]+/g, " ")); + if (onComment) + onComment(); + } + if (!literal) { + const foldedValue = value.replace(/\n+/g, "\n$&").replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, "$1$2").replace(/\n+/g, `$&${indent}`); + let literalFallback = false; + const foldOptions = getFoldOptions(ctx, true); + if (blockQuote !== "folded" && type !== Scalar.Scalar.BLOCK_FOLDED) { + foldOptions.onOverflow = () => { + literalFallback = true; + }; + } + const body = foldFlowLines.foldFlowLines(`${start}${foldedValue}${end}`, indent, foldFlowLines.FOLD_BLOCK, foldOptions); + if (!literalFallback) + return `>${header} +${indent}${body}`; + } + value = value.replace(/\n+/g, `$&${indent}`); + return `|${header} +${indent}${start}${value}${end}`; + } + function plainString(item, ctx, onComment, onChompKeep) { + const { type, value } = item; + const { actualString, implicitKey, indent, indentStep, inFlow } = ctx; + if (implicitKey && value.includes("\n") || inFlow && /[[\]{},]/.test(value)) { + return quotedString(value, ctx); + } + if (/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) { + return implicitKey || inFlow || !value.includes("\n") ? quotedString(value, ctx) : blockString(item, ctx, onComment, onChompKeep); + } + if (!implicitKey && !inFlow && type !== Scalar.Scalar.PLAIN && value.includes("\n")) { + return blockString(item, ctx, onComment, onChompKeep); + } + if (containsDocumentMarker(value)) { + if (indent === "") { + ctx.forceBlockIndent = true; + return blockString(item, ctx, onComment, onChompKeep); + } else if (implicitKey && indent === indentStep) { + return quotedString(value, ctx); + } + } + const str = value.replace(/\n+/g, `$& +${indent}`); + if (actualString) { + const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(str); + const { compat, tags } = ctx.doc.schema; + if (tags.some(test) || compat?.some(test)) + return quotedString(value, ctx); + } + return implicitKey ? str : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx, false)); + } + function stringifyString(item, ctx, onComment, onChompKeep) { + const { implicitKey, inFlow } = ctx; + const ss = typeof item.value === "string" ? item : Object.assign({}, item, { value: String(item.value) }); + let { type } = item; + if (type !== Scalar.Scalar.QUOTE_DOUBLE) { + if (/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(ss.value)) + type = Scalar.Scalar.QUOTE_DOUBLE; + } + const _stringify = (_type) => { + switch (_type) { + case Scalar.Scalar.BLOCK_FOLDED: + case Scalar.Scalar.BLOCK_LITERAL: + return implicitKey || inFlow ? quotedString(ss.value, ctx) : blockString(ss, ctx, onComment, onChompKeep); + case Scalar.Scalar.QUOTE_DOUBLE: + return doubleQuotedString(ss.value, ctx); + case Scalar.Scalar.QUOTE_SINGLE: + return singleQuotedString(ss.value, ctx); + case Scalar.Scalar.PLAIN: + return plainString(ss, ctx, onComment, onChompKeep); + default: + return null; + } + }; + let res = _stringify(type); + if (res === null) { + const { defaultKeyType, defaultStringType } = ctx.options; + const t = implicitKey && defaultKeyType || defaultStringType; + res = _stringify(t); + if (res === null) + throw new Error(`Unsupported default string type ${t}`); + } + return res; + } + exports2.stringifyString = stringifyString; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringify.js +var require_stringify = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringify.js"(exports2) { + "use strict"; + var anchors = require_anchors(); + var identity3 = require_identity(); + var stringifyComment = require_stringifyComment(); + var stringifyString = require_stringifyString(); + function createStringifyContext(doc, options) { + const opt = Object.assign({ + blockQuote: true, + commentString: stringifyComment.stringifyComment, + defaultKeyType: null, + defaultStringType: "PLAIN", + directives: null, + doubleQuotedAsJSON: false, + doubleQuotedMinMultiLineLength: 40, + falseStr: "false", + flowCollectionPadding: true, + indentSeq: true, + lineWidth: 80, + minContentWidth: 20, + nullStr: "null", + simpleKeys: false, + singleQuote: null, + trailingComma: false, + trueStr: "true", + verifyAliasOrder: true + }, doc.schema.toStringOptions, options); + let inFlow; + switch (opt.collectionStyle) { + case "block": + inFlow = false; + break; + case "flow": + inFlow = true; + break; + default: + inFlow = null; + } + return { + anchors: /* @__PURE__ */ new Set(), + doc, + flowCollectionPadding: opt.flowCollectionPadding ? " " : "", + indent: "", + indentStep: typeof opt.indent === "number" ? " ".repeat(opt.indent) : " ", + inFlow, + options: opt + }; + } + function getTagObject(tags, item) { + if (item.tag) { + const match = tags.filter((t) => t.tag === item.tag); + if (match.length > 0) + return match.find((t) => t.format === item.format) ?? match[0]; + } + let tagObj = void 0; + let obj; + if (identity3.isScalar(item)) { + obj = item.value; + let match = tags.filter((t) => t.identify?.(obj)); + if (match.length > 1) { + const testMatch = match.filter((t) => t.test); + if (testMatch.length > 0) + match = testMatch; + } + tagObj = match.find((t) => t.format === item.format) ?? match.find((t) => !t.format); + } else { + obj = item; + tagObj = tags.find((t) => t.nodeClass && obj instanceof t.nodeClass); + } + if (!tagObj) { + const name = obj?.constructor?.name ?? (obj === null ? "null" : typeof obj); + throw new Error(`Tag not resolved for ${name} value`); + } + return tagObj; + } + function stringifyProps(node, tagObj, { anchors: anchors$1, doc }) { + if (!doc.directives) + return ""; + const props = []; + const anchor = (identity3.isScalar(node) || identity3.isCollection(node)) && node.anchor; + if (anchor && anchors.anchorIsValid(anchor)) { + anchors$1.add(anchor); + props.push(`&${anchor}`); + } + const tag = node.tag ?? (tagObj.default ? null : tagObj.tag); + if (tag) + props.push(doc.directives.tagString(tag)); + return props.join(" "); + } + function stringify(item, ctx, onComment, onChompKeep) { + if (identity3.isPair(item)) + return item.toString(ctx, onComment, onChompKeep); + if (identity3.isAlias(item)) { + if (ctx.doc.directives) + return item.toString(ctx); + if (ctx.resolvedAliases?.has(item)) { + throw new TypeError(`Cannot stringify circular structure without alias nodes`); + } else { + if (ctx.resolvedAliases) + ctx.resolvedAliases.add(item); + else + ctx.resolvedAliases = /* @__PURE__ */ new Set([item]); + item = item.resolve(ctx.doc); + } + } + let tagObj = void 0; + const node = identity3.isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: (o2) => tagObj = o2 }); + tagObj ?? (tagObj = getTagObject(ctx.doc.schema.tags, node)); + const props = stringifyProps(node, tagObj, ctx); + if (props.length > 0) + ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1; + const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node, ctx, onComment, onChompKeep) : identity3.isScalar(node) ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep); + if (!props) + return str; + return identity3.isScalar(node) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props} +${ctx.indent}${str}`; + } + exports2.createStringifyContext = createStringifyContext; + exports2.stringify = stringify; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyPair.js +var require_stringifyPair = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyPair.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Scalar = require_Scalar(); + var stringify = require_stringify(); + var stringifyComment = require_stringifyComment(); + function stringifyPair({ key, value }, ctx, onComment, onChompKeep) { + const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx; + let keyComment = identity3.isNode(key) && key.comment || null; + if (simpleKeys) { + if (keyComment) { + throw new Error("With simple keys, key nodes cannot have comments"); + } + if (identity3.isCollection(key) || !identity3.isNode(key) && typeof key === "object") { + const msg = "With simple keys, collection cannot be used as a key value"; + throw new Error(msg); + } + } + let explicitKey = !simpleKeys && (!key || keyComment && value == null && !ctx.inFlow || identity3.isCollection(key) || (identity3.isScalar(key) ? key.type === Scalar.Scalar.BLOCK_FOLDED || key.type === Scalar.Scalar.BLOCK_LITERAL : typeof key === "object")); + ctx = Object.assign({}, ctx, { + allNullValues: false, + implicitKey: !explicitKey && (simpleKeys || !allNullValues), + indent: indent + indentStep + }); + let keyCommentDone = false; + let chompKeep = false; + let str = stringify.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true); + if (!explicitKey && !ctx.inFlow && str.length > 1024) { + if (simpleKeys) + throw new Error("With simple keys, single line scalar must not span more than 1024 characters"); + explicitKey = true; + } + if (ctx.inFlow) { + if (allNullValues || value == null) { + if (keyCommentDone && onComment) + onComment(); + return str === "" ? "?" : explicitKey ? `? ${str}` : str; + } + } else if (allNullValues && !simpleKeys || value == null && explicitKey) { + str = `? ${str}`; + if (keyComment && !keyCommentDone) { + str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment)); + } else if (chompKeep && onChompKeep) + onChompKeep(); + return str; + } + if (keyCommentDone) + keyComment = null; + if (explicitKey) { + if (keyComment) + str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment)); + str = `? ${str} +${indent}:`; + } else { + str = `${str}:`; + if (keyComment) + str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment)); + } + let vsb, vcb, valueComment; + if (identity3.isNode(value)) { + vsb = !!value.spaceBefore; + vcb = value.commentBefore; + valueComment = value.comment; + } else { + vsb = false; + vcb = null; + valueComment = null; + if (value && typeof value === "object") + value = doc.createNode(value); + } + ctx.implicitKey = false; + if (!explicitKey && !keyComment && identity3.isScalar(value)) + ctx.indentAtStart = str.length + 1; + chompKeep = false; + if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && identity3.isSeq(value) && !value.flow && !value.tag && !value.anchor) { + ctx.indent = ctx.indent.substring(2); + } + let valueCommentDone = false; + const valueStr = stringify.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true); + let ws = " "; + if (keyComment || vsb || vcb) { + ws = vsb ? "\n" : ""; + if (vcb) { + const cs = commentString(vcb); + ws += ` +${stringifyComment.indentComment(cs, ctx.indent)}`; + } + if (valueStr === "" && !ctx.inFlow) { + if (ws === "\n" && valueComment) + ws = "\n\n"; + } else { + ws += ` +${ctx.indent}`; + } + } else if (!explicitKey && identity3.isCollection(value)) { + const vs0 = valueStr[0]; + const nl0 = valueStr.indexOf("\n"); + const hasNewline = nl0 !== -1; + const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0; + if (hasNewline || !flow) { + let hasPropsLine = false; + if (hasNewline && (vs0 === "&" || vs0 === "!")) { + let sp0 = valueStr.indexOf(" "); + if (vs0 === "&" && sp0 !== -1 && sp0 < nl0 && valueStr[sp0 + 1] === "!") { + sp0 = valueStr.indexOf(" ", sp0 + 1); + } + if (sp0 === -1 || nl0 < sp0) + hasPropsLine = true; + } + if (!hasPropsLine) + ws = ` +${ctx.indent}`; + } + } else if (valueStr === "" || valueStr[0] === "\n") { + ws = ""; + } + str += ws + valueStr; + if (ctx.inFlow) { + if (valueCommentDone && onComment) + onComment(); + } else if (valueComment && !valueCommentDone) { + str += stringifyComment.lineComment(str, ctx.indent, commentString(valueComment)); + } else if (chompKeep && onChompKeep) { + onChompKeep(); + } + return str; + } + exports2.stringifyPair = stringifyPair; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/log.js +var require_log = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/log.js"(exports2) { + "use strict"; + var node_process = require("process"); + function debug(logLevel, ...messages) { + if (logLevel === "debug") + console.log(...messages); + } + function warn(logLevel, warning) { + if (logLevel === "debug" || logLevel === "warn") { + if (typeof node_process.emitWarning === "function") + node_process.emitWarning(warning); + else + console.warn(warning); + } + } + exports2.debug = debug; + exports2.warn = warn; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/merge.js +var require_merge = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/merge.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Scalar = require_Scalar(); + var MERGE_KEY = "<<"; + var merge = { + identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY, + default: "key", + tag: "tag:yaml.org,2002:merge", + test: /^<<$/, + resolve: () => Object.assign(new Scalar.Scalar(Symbol(MERGE_KEY)), { + addToJSMap: addMergeToJSMap + }), + stringify: () => MERGE_KEY + }; + var isMergeKey = (ctx, key) => (merge.identify(key) || identity3.isScalar(key) && (!key.type || key.type === Scalar.Scalar.PLAIN) && merge.identify(key.value)) && ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default); + function addMergeToJSMap(ctx, map, value) { + const source = resolveAliasValue(ctx, value); + if (identity3.isSeq(source)) + for (const it of source.items) + mergeValue(ctx, map, it); + else if (Array.isArray(source)) + for (const it of source) + mergeValue(ctx, map, it); + else + mergeValue(ctx, map, source); + } + function mergeValue(ctx, map, value) { + const source = resolveAliasValue(ctx, value); + if (!identity3.isMap(source)) + throw new Error("Merge sources must be maps or map aliases"); + const srcMap = source.toJSON(null, ctx, Map); + for (const [key, value2] of srcMap) { + if (map instanceof Map) { + if (!map.has(key)) + map.set(key, value2); + } else if (map instanceof Set) { + map.add(key); + } else if (!Object.prototype.hasOwnProperty.call(map, key)) { + Object.defineProperty(map, key, { + value: value2, + writable: true, + enumerable: true, + configurable: true + }); + } + } + return map; + } + function resolveAliasValue(ctx, value) { + return ctx && identity3.isAlias(value) ? value.resolve(ctx.doc, ctx) : value; + } + exports2.addMergeToJSMap = addMergeToJSMap; + exports2.isMergeKey = isMergeKey; + exports2.merge = merge; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/addPairToJSMap.js +var require_addPairToJSMap = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/addPairToJSMap.js"(exports2) { + "use strict"; + var log = require_log(); + var merge = require_merge(); + var stringify = require_stringify(); + var identity3 = require_identity(); + var toJS = require_toJS(); + function addPairToJSMap(ctx, map, { key, value }) { + if (identity3.isNode(key) && key.addToJSMap) + key.addToJSMap(ctx, map, value); + else if (merge.isMergeKey(ctx, key)) + merge.addMergeToJSMap(ctx, map, value); + else { + const jsKey = toJS.toJS(key, "", ctx); + if (map instanceof Map) { + map.set(jsKey, toJS.toJS(value, jsKey, ctx)); + } else if (map instanceof Set) { + map.add(jsKey); + } else { + const stringKey = stringifyKey(key, jsKey, ctx); + const jsValue = toJS.toJS(value, stringKey, ctx); + if (stringKey in map) + Object.defineProperty(map, stringKey, { + value: jsValue, + writable: true, + enumerable: true, + configurable: true + }); + else + map[stringKey] = jsValue; + } + } + return map; + } + function stringifyKey(key, jsKey, ctx) { + if (jsKey === null) + return ""; + if (typeof jsKey !== "object") + return String(jsKey); + if (identity3.isNode(key) && ctx?.doc) { + const strCtx = stringify.createStringifyContext(ctx.doc, {}); + strCtx.anchors = /* @__PURE__ */ new Set(); + for (const node of ctx.anchors.keys()) + strCtx.anchors.add(node.anchor); + strCtx.inFlow = true; + strCtx.inStringifyKey = true; + const strKey = key.toString(strCtx); + if (!ctx.mapKeyWarned) { + let jsonStr = JSON.stringify(strKey); + if (jsonStr.length > 40) + jsonStr = jsonStr.substring(0, 36) + '..."'; + log.warn(ctx.doc.options.logLevel, `Keys with collection values will be stringified due to JS Object restrictions: ${jsonStr}. Set mapAsMap: true to use object keys.`); + ctx.mapKeyWarned = true; + } + return strKey; + } + return JSON.stringify(jsKey); + } + exports2.addPairToJSMap = addPairToJSMap; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Pair.js +var require_Pair = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/Pair.js"(exports2) { + "use strict"; + var createNode = require_createNode(); + var stringifyPair = require_stringifyPair(); + var addPairToJSMap = require_addPairToJSMap(); + var identity3 = require_identity(); + function createPair(key, value, ctx) { + const k = createNode.createNode(key, void 0, ctx); + const v = createNode.createNode(value, void 0, ctx); + return new Pair(k, v); + } + var Pair = class _Pair { + constructor(key, value = null) { + Object.defineProperty(this, identity3.NODE_TYPE, { value: identity3.PAIR }); + this.key = key; + this.value = value; + } + clone(schema) { + let { key, value } = this; + if (identity3.isNode(key)) + key = key.clone(schema); + if (identity3.isNode(value)) + value = value.clone(schema); + return new _Pair(key, value); + } + toJSON(_, ctx) { + const pair = ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {}; + return addPairToJSMap.addPairToJSMap(ctx, pair, this); + } + toString(ctx, onComment, onChompKeep) { + return ctx?.doc ? stringifyPair.stringifyPair(this, ctx, onComment, onChompKeep) : JSON.stringify(this); + } + }; + exports2.Pair = Pair; + exports2.createPair = createPair; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyCollection.js +var require_stringifyCollection = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyCollection.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var stringify = require_stringify(); + var stringifyComment = require_stringifyComment(); + function stringifyCollection(collection, ctx, options) { + const flow = ctx.inFlow ?? collection.flow; + const stringify2 = flow ? stringifyFlowCollection : stringifyBlockCollection; + return stringify2(collection, ctx, options); + } + function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) { + const { indent, options: { commentString } } = ctx; + const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null }); + let chompKeep = false; + const lines = []; + for (let i2 = 0; i2 < items.length; ++i2) { + const item = items[i2]; + let comment2 = null; + if (identity3.isNode(item)) { + if (!chompKeep && item.spaceBefore) + lines.push(""); + addCommentBefore(ctx, lines, item.commentBefore, chompKeep); + if (item.comment) + comment2 = item.comment; + } else if (identity3.isPair(item)) { + const ik = identity3.isNode(item.key) ? item.key : null; + if (ik) { + if (!chompKeep && ik.spaceBefore) + lines.push(""); + addCommentBefore(ctx, lines, ik.commentBefore, chompKeep); + } + } + chompKeep = false; + let str2 = stringify.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true); + if (comment2) + str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment2)); + if (chompKeep && comment2) + chompKeep = false; + lines.push(blockItemPrefix + str2); + } + let str; + if (lines.length === 0) { + str = flowChars.start + flowChars.end; + } else { + str = lines[0]; + for (let i2 = 1; i2 < lines.length; ++i2) { + const line = lines[i2]; + str += line ? ` +${indent}${line}` : "\n"; + } + } + if (comment) { + str += "\n" + stringifyComment.indentComment(commentString(comment), indent); + if (onComment) + onComment(); + } else if (chompKeep && onChompKeep) + onChompKeep(); + return str; + } + function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) { + const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx; + itemIndent += indentStep; + const itemCtx = Object.assign({}, ctx, { + indent: itemIndent, + inFlow: true, + type: null + }); + let reqNewline = false; + let linesAtValue = 0; + const lines = []; + for (let i2 = 0; i2 < items.length; ++i2) { + const item = items[i2]; + let comment = null; + if (identity3.isNode(item)) { + if (item.spaceBefore) + lines.push(""); + addCommentBefore(ctx, lines, item.commentBefore, false); + if (item.comment) + comment = item.comment; + } else if (identity3.isPair(item)) { + const ik = identity3.isNode(item.key) ? item.key : null; + if (ik) { + if (ik.spaceBefore) + lines.push(""); + addCommentBefore(ctx, lines, ik.commentBefore, false); + if (ik.comment) + reqNewline = true; + } + const iv = identity3.isNode(item.value) ? item.value : null; + if (iv) { + if (iv.comment) + comment = iv.comment; + if (iv.commentBefore) + reqNewline = true; + } else if (item.value == null && ik?.comment) { + comment = ik.comment; + } + } + if (comment) + reqNewline = true; + let str = stringify.stringify(item, itemCtx, () => comment = null); + reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n")); + if (i2 < items.length - 1) { + str += ","; + } else if (ctx.options.trailingComma) { + if (ctx.options.lineWidth > 0) { + reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth); + } + if (reqNewline) { + str += ","; + } + } + if (comment) + str += stringifyComment.lineComment(str, itemIndent, commentString(comment)); + lines.push(str); + linesAtValue = lines.length; + } + const { start, end } = flowChars; + if (lines.length === 0) { + return start + end; + } else { + if (!reqNewline) { + const len = lines.reduce((sum, line) => sum + line.length + 2, 2); + reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth; + } + if (reqNewline) { + let str = start; + for (const line of lines) + str += line ? ` +${indentStep}${indent}${line}` : "\n"; + return `${str} +${indent}${end}`; + } else { + return `${start}${fcPadding}${lines.join(" ")}${fcPadding}${end}`; + } + } + } + function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) { + if (comment && chompKeep) + comment = comment.replace(/^\n+/, ""); + if (comment) { + const ic = stringifyComment.indentComment(commentString(comment), indent); + lines.push(ic.trimStart()); + } + } + exports2.stringifyCollection = stringifyCollection; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLMap.js +var require_YAMLMap = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLMap.js"(exports2) { + "use strict"; + var stringifyCollection = require_stringifyCollection(); + var addPairToJSMap = require_addPairToJSMap(); + var Collection = require_Collection(); + var identity3 = require_identity(); + var Pair = require_Pair(); + var Scalar = require_Scalar(); + function findPair(items, key) { + const k = identity3.isScalar(key) ? key.value : key; + for (const it of items) { + if (identity3.isPair(it)) { + if (it.key === key || it.key === k) + return it; + if (identity3.isScalar(it.key) && it.key.value === k) + return it; + } + } + return void 0; + } + var YAMLMap = class extends Collection.Collection { + static get tagName() { + return "tag:yaml.org,2002:map"; + } + constructor(schema) { + super(identity3.MAP, schema); + this.items = []; + } + /** + * A generic collection parsing method that can be extended + * to other node classes that inherit from YAMLMap + */ + static from(schema, obj, ctx) { + const { keepUndefined, replacer } = ctx; + const map = new this(schema); + const add = (key, value) => { + if (typeof replacer === "function") + value = replacer.call(obj, key, value); + else if (Array.isArray(replacer) && !replacer.includes(key)) + return; + if (value !== void 0 || keepUndefined) + map.items.push(Pair.createPair(key, value, ctx)); + }; + if (obj instanceof Map) { + for (const [key, value] of obj) + add(key, value); + } else if (obj && typeof obj === "object") { + for (const key of Object.keys(obj)) + add(key, obj[key]); + } + if (typeof schema.sortMapEntries === "function") { + map.items.sort(schema.sortMapEntries); + } + return map; + } + /** + * Adds a value to the collection. + * + * @param overwrite - If not set `true`, using a key that is already in the + * collection will throw. Otherwise, overwrites the previous value. + */ + add(pair, overwrite) { + let _pair; + if (identity3.isPair(pair)) + _pair = pair; + else if (!pair || typeof pair !== "object" || !("key" in pair)) { + _pair = new Pair.Pair(pair, pair?.value); + } else + _pair = new Pair.Pair(pair.key, pair.value); + const prev = findPair(this.items, _pair.key); + const sortEntries = this.schema?.sortMapEntries; + if (prev) { + if (!overwrite) + throw new Error(`Key ${_pair.key} already set`); + if (identity3.isScalar(prev.value) && Scalar.isScalarValue(_pair.value)) + prev.value.value = _pair.value; + else + prev.value = _pair.value; + } else if (sortEntries) { + const i2 = this.items.findIndex((item) => sortEntries(_pair, item) < 0); + if (i2 === -1) + this.items.push(_pair); + else + this.items.splice(i2, 0, _pair); + } else { + this.items.push(_pair); + } + } + delete(key) { + const it = findPair(this.items, key); + if (!it) + return false; + const del = this.items.splice(this.items.indexOf(it), 1); + return del.length > 0; + } + get(key, keepScalar) { + const it = findPair(this.items, key); + const node = it?.value; + return (!keepScalar && identity3.isScalar(node) ? node.value : node) ?? void 0; + } + has(key) { + return !!findPair(this.items, key); + } + set(key, value) { + this.add(new Pair.Pair(key, value), true); + } + /** + * @param ctx - Conversion context, originally set in Document#toJS() + * @param {Class} Type - If set, forces the returned collection type + * @returns Instance of Type, Map, or Object + */ + toJSON(_, ctx, Type) { + const map = Type ? new Type() : ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {}; + if (ctx?.onCreate) + ctx.onCreate(map); + for (const item of this.items) + addPairToJSMap.addPairToJSMap(ctx, map, item); + return map; + } + toString(ctx, onComment, onChompKeep) { + if (!ctx) + return JSON.stringify(this); + for (const item of this.items) { + if (!identity3.isPair(item)) + throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`); + } + if (!ctx.allNullValues && this.hasAllNullValues(false)) + ctx = Object.assign({}, ctx, { allNullValues: true }); + return stringifyCollection.stringifyCollection(this, ctx, { + blockItemPrefix: "", + flowChars: { start: "{", end: "}" }, + itemIndent: ctx.indent || "", + onChompKeep, + onComment + }); + } + }; + exports2.YAMLMap = YAMLMap; + exports2.findPair = findPair; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/map.js +var require_map = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/map.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var YAMLMap = require_YAMLMap(); + var map = { + collection: "map", + default: true, + nodeClass: YAMLMap.YAMLMap, + tag: "tag:yaml.org,2002:map", + resolve(map2, onError) { + if (!identity3.isMap(map2)) + onError("Expected a mapping for this tag"); + return map2; + }, + createNode: (schema, obj, ctx) => YAMLMap.YAMLMap.from(schema, obj, ctx) + }; + exports2.map = map; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLSeq.js +var require_YAMLSeq = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/YAMLSeq.js"(exports2) { + "use strict"; + var createNode = require_createNode(); + var stringifyCollection = require_stringifyCollection(); + var Collection = require_Collection(); + var identity3 = require_identity(); + var Scalar = require_Scalar(); + var toJS = require_toJS(); + var YAMLSeq = class extends Collection.Collection { + static get tagName() { + return "tag:yaml.org,2002:seq"; + } + constructor(schema) { + super(identity3.SEQ, schema); + this.items = []; + } + add(value) { + this.items.push(value); + } + /** + * Removes a value from the collection. + * + * `key` must contain a representation of an integer for this to succeed. + * It may be wrapped in a `Scalar`. + * + * @returns `true` if the item was found and removed. + */ + delete(key) { + const idx = asItemIndex(key); + if (typeof idx !== "number") + return false; + const del = this.items.splice(idx, 1); + return del.length > 0; + } + get(key, keepScalar) { + const idx = asItemIndex(key); + if (typeof idx !== "number") + return void 0; + const it = this.items[idx]; + return !keepScalar && identity3.isScalar(it) ? it.value : it; + } + /** + * Checks if the collection includes a value with the key `key`. + * + * `key` must contain a representation of an integer for this to succeed. + * It may be wrapped in a `Scalar`. + */ + has(key) { + const idx = asItemIndex(key); + return typeof idx === "number" && idx < this.items.length; + } + /** + * Sets a value in this collection. For `!!set`, `value` needs to be a + * boolean to add/remove the item from the set. + * + * If `key` does not contain a representation of an integer, this will throw. + * It may be wrapped in a `Scalar`. + */ + set(key, value) { + const idx = asItemIndex(key); + if (typeof idx !== "number") + throw new Error(`Expected a valid index, not ${key}.`); + const prev = this.items[idx]; + if (identity3.isScalar(prev) && Scalar.isScalarValue(value)) + prev.value = value; + else + this.items[idx] = value; + } + toJSON(_, ctx) { + const seq = []; + if (ctx?.onCreate) + ctx.onCreate(seq); + let i2 = 0; + for (const item of this.items) + seq.push(toJS.toJS(item, String(i2++), ctx)); + return seq; + } + toString(ctx, onComment, onChompKeep) { + if (!ctx) + return JSON.stringify(this); + return stringifyCollection.stringifyCollection(this, ctx, { + blockItemPrefix: "- ", + flowChars: { start: "[", end: "]" }, + itemIndent: (ctx.indent || "") + " ", + onChompKeep, + onComment + }); + } + static from(schema, obj, ctx) { + const { replacer } = ctx; + const seq = new this(schema); + if (obj && Symbol.iterator in Object(obj)) { + let i2 = 0; + for (let it of obj) { + if (typeof replacer === "function") { + const key = obj instanceof Set ? it : String(i2++); + it = replacer.call(obj, key, it); + } + seq.items.push(createNode.createNode(it, void 0, ctx)); + } + } + return seq; + } + }; + function asItemIndex(key) { + let idx = identity3.isScalar(key) ? key.value : key; + if (idx && typeof idx === "string") + idx = Number(idx); + return typeof idx === "number" && Number.isInteger(idx) && idx >= 0 ? idx : null; + } + exports2.YAMLSeq = YAMLSeq; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/seq.js +var require_seq = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/seq.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var YAMLSeq = require_YAMLSeq(); + var seq = { + collection: "seq", + default: true, + nodeClass: YAMLSeq.YAMLSeq, + tag: "tag:yaml.org,2002:seq", + resolve(seq2, onError) { + if (!identity3.isSeq(seq2)) + onError("Expected a sequence for this tag"); + return seq2; + }, + createNode: (schema, obj, ctx) => YAMLSeq.YAMLSeq.from(schema, obj, ctx) + }; + exports2.seq = seq; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/string.js +var require_string = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/string.js"(exports2) { + "use strict"; + var stringifyString = require_stringifyString(); + var string = { + identify: (value) => typeof value === "string", + default: true, + tag: "tag:yaml.org,2002:str", + resolve: (str) => str, + stringify(item, ctx, onComment, onChompKeep) { + ctx = Object.assign({ actualString: true }, ctx); + return stringifyString.stringifyString(item, ctx, onComment, onChompKeep); + } + }; + exports2.string = string; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/null.js +var require_null = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/common/null.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var nullTag = { + identify: (value) => value == null, + createNode: () => new Scalar.Scalar(null), + default: true, + tag: "tag:yaml.org,2002:null", + test: /^(?:~|[Nn]ull|NULL)?$/, + resolve: () => new Scalar.Scalar(null), + stringify: ({ source }, ctx) => typeof source === "string" && nullTag.test.test(source) ? source : ctx.options.nullStr + }; + exports2.nullTag = nullTag; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/bool.js +var require_bool = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/bool.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var boolTag = { + identify: (value) => typeof value === "boolean", + default: true, + tag: "tag:yaml.org,2002:bool", + test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/, + resolve: (str) => new Scalar.Scalar(str[0] === "t" || str[0] === "T"), + stringify({ source, value }, ctx) { + if (source && boolTag.test.test(source)) { + const sv = source[0] === "t" || source[0] === "T"; + if (value === sv) + return source; + } + return value ? ctx.options.trueStr : ctx.options.falseStr; + } + }; + exports2.boolTag = boolTag; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyNumber.js +var require_stringifyNumber = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyNumber.js"(exports2) { + "use strict"; + function stringifyNumber({ format: format2, minFractionDigits, tag, value }) { + if (typeof value === "bigint") + return String(value); + const num = typeof value === "number" ? value : Number(value); + if (!isFinite(num)) + return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf"; + let n2 = Object.is(value, -0) ? "-0" : JSON.stringify(value); + if (!format2 && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n2) && !n2.includes("e")) { + let i2 = n2.indexOf("."); + if (i2 < 0) { + i2 = n2.length; + n2 += "."; + } + let d = minFractionDigits - (n2.length - i2 - 1); + while (d-- > 0) + n2 += "0"; + } + return n2; + } + exports2.stringifyNumber = stringifyNumber; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/float.js +var require_float = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/float.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var stringifyNumber = require_stringifyNumber(); + var floatNaN = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/, + resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY, + stringify: stringifyNumber.stringifyNumber + }; + var floatExp = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + format: "EXP", + test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/, + resolve: (str) => parseFloat(str), + stringify(node) { + const num = Number(node.value); + return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node); + } + }; + var float = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/, + resolve(str) { + const node = new Scalar.Scalar(parseFloat(str)); + const dot = str.indexOf("."); + if (dot !== -1 && str[str.length - 1] === "0") + node.minFractionDigits = str.length - dot - 1; + return node; + }, + stringify: stringifyNumber.stringifyNumber + }; + exports2.float = float; + exports2.floatExp = floatExp; + exports2.floatNaN = floatNaN; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/int.js +var require_int = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/int.js"(exports2) { + "use strict"; + var stringifyNumber = require_stringifyNumber(); + var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value); + var intResolve = (str, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix); + function intStringify(node, radix, prefix) { + const { value } = node; + if (intIdentify(value) && value >= 0) + return prefix + value.toString(radix); + return stringifyNumber.stringifyNumber(node); + } + var intOct = { + identify: (value) => intIdentify(value) && value >= 0, + default: true, + tag: "tag:yaml.org,2002:int", + format: "OCT", + test: /^0o[0-7]+$/, + resolve: (str, _onError, opt) => intResolve(str, 2, 8, opt), + stringify: (node) => intStringify(node, 8, "0o") + }; + var int = { + identify: intIdentify, + default: true, + tag: "tag:yaml.org,2002:int", + test: /^[-+]?[0-9]+$/, + resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt), + stringify: stringifyNumber.stringifyNumber + }; + var intHex = { + identify: (value) => intIdentify(value) && value >= 0, + default: true, + tag: "tag:yaml.org,2002:int", + format: "HEX", + test: /^0x[0-9a-fA-F]+$/, + resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt), + stringify: (node) => intStringify(node, 16, "0x") + }; + exports2.int = int; + exports2.intHex = intHex; + exports2.intOct = intOct; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/schema.js +var require_schema = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/core/schema.js"(exports2) { + "use strict"; + var map = require_map(); + var _null = require_null(); + var seq = require_seq(); + var string = require_string(); + var bool = require_bool(); + var float = require_float(); + var int = require_int(); + var schema = [ + map.map, + seq.seq, + string.string, + _null.nullTag, + bool.boolTag, + int.intOct, + int.int, + int.intHex, + float.floatNaN, + float.floatExp, + float.float + ]; + exports2.schema = schema; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/json/schema.js +var require_schema2 = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/json/schema.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var map = require_map(); + var seq = require_seq(); + function intIdentify(value) { + return typeof value === "bigint" || Number.isInteger(value); + } + var stringifyJSON = ({ value }) => JSON.stringify(value); + var jsonScalars = [ + { + identify: (value) => typeof value === "string", + default: true, + tag: "tag:yaml.org,2002:str", + resolve: (str) => str, + stringify: stringifyJSON + }, + { + identify: (value) => value == null, + createNode: () => new Scalar.Scalar(null), + default: true, + tag: "tag:yaml.org,2002:null", + test: /^null$/, + resolve: () => null, + stringify: stringifyJSON + }, + { + identify: (value) => typeof value === "boolean", + default: true, + tag: "tag:yaml.org,2002:bool", + test: /^true$|^false$/, + resolve: (str) => str === "true", + stringify: stringifyJSON + }, + { + identify: intIdentify, + default: true, + tag: "tag:yaml.org,2002:int", + test: /^-?(?:0|[1-9][0-9]*)$/, + resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10), + stringify: ({ value }) => intIdentify(value) ? value.toString() : JSON.stringify(value) + }, + { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/, + resolve: (str) => parseFloat(str), + stringify: stringifyJSON + } + ]; + var jsonError = { + default: true, + tag: "", + test: /^/, + resolve(str, onError) { + onError(`Unresolved plain scalar ${JSON.stringify(str)}`); + return str; + } + }; + var schema = [map.map, seq.seq].concat(jsonScalars, jsonError); + exports2.schema = schema; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/binary.js +var require_binary = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/binary.js"(exports2) { + "use strict"; + var node_buffer = require("buffer"); + var Scalar = require_Scalar(); + var stringifyString = require_stringifyString(); + var binary = { + identify: (value) => value instanceof Uint8Array, + // Buffer inherits from Uint8Array + default: false, + tag: "tag:yaml.org,2002:binary", + /** + * Returns a Buffer in node and an Uint8Array in browsers + * + * To use the resulting buffer as an image, you'll want to do something like: + * + * const blob = new Blob([buffer], { type: 'image/jpeg' }) + * document.querySelector('#photo').src = URL.createObjectURL(blob) + */ + resolve(src, onError) { + if (typeof node_buffer.Buffer === "function") { + return node_buffer.Buffer.from(src, "base64"); + } else if (typeof atob === "function") { + const str = atob(src.replace(/[\n\r]/g, "")); + const buffer = new Uint8Array(str.length); + for (let i2 = 0; i2 < str.length; ++i2) + buffer[i2] = str.charCodeAt(i2); + return buffer; + } else { + onError("This environment does not support reading binary tags; either Buffer or atob is required"); + return src; + } + }, + stringify({ comment, type, value }, ctx, onComment, onChompKeep) { + if (!value) + return ""; + const buf = value; + let str; + if (typeof node_buffer.Buffer === "function") { + str = buf instanceof node_buffer.Buffer ? buf.toString("base64") : node_buffer.Buffer.from(buf.buffer).toString("base64"); + } else if (typeof btoa === "function") { + let s = ""; + for (let i2 = 0; i2 < buf.length; ++i2) + s += String.fromCharCode(buf[i2]); + str = btoa(s); + } else { + throw new Error("This environment does not support writing binary tags; either Buffer or btoa is required"); + } + type ?? (type = Scalar.Scalar.BLOCK_LITERAL); + if (type !== Scalar.Scalar.QUOTE_DOUBLE) { + const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth); + const n2 = Math.ceil(str.length / lineWidth); + const lines = new Array(n2); + for (let i2 = 0, o2 = 0; i2 < n2; ++i2, o2 += lineWidth) { + lines[i2] = str.substr(o2, lineWidth); + } + str = lines.join(type === Scalar.Scalar.BLOCK_LITERAL ? "\n" : " "); + } + return stringifyString.stringifyString({ comment, type, value: str }, ctx, onComment, onChompKeep); + } + }; + exports2.binary = binary; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +var require_pairs = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/pairs.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Pair = require_Pair(); + var Scalar = require_Scalar(); + var YAMLSeq = require_YAMLSeq(); + function resolvePairs(seq, onError) { + if (identity3.isSeq(seq)) { + for (let i2 = 0; i2 < seq.items.length; ++i2) { + let item = seq.items[i2]; + if (identity3.isPair(item)) + continue; + else if (identity3.isMap(item)) { + if (item.items.length > 1) + onError("Each pair must have its own sequence indicator"); + const pair = item.items[0] || new Pair.Pair(new Scalar.Scalar(null)); + if (item.commentBefore) + pair.key.commentBefore = pair.key.commentBefore ? `${item.commentBefore} +${pair.key.commentBefore}` : item.commentBefore; + if (item.comment) { + const cn = pair.value ?? pair.key; + cn.comment = cn.comment ? `${item.comment} +${cn.comment}` : item.comment; + } + item = pair; + } + seq.items[i2] = identity3.isPair(item) ? item : new Pair.Pair(item); + } + } else + onError("Expected a sequence for this tag"); + return seq; + } + function createPairs(schema, iterable, ctx) { + const { replacer } = ctx; + const pairs2 = new YAMLSeq.YAMLSeq(schema); + pairs2.tag = "tag:yaml.org,2002:pairs"; + let i2 = 0; + if (iterable && Symbol.iterator in Object(iterable)) + for (let it of iterable) { + if (typeof replacer === "function") + it = replacer.call(iterable, String(i2++), it); + let key, value; + if (Array.isArray(it)) { + if (it.length === 2) { + key = it[0]; + value = it[1]; + } else + throw new TypeError(`Expected [key, value] tuple: ${it}`); + } else if (it && it instanceof Object) { + const keys = Object.keys(it); + if (keys.length === 1) { + key = keys[0]; + value = it[key]; + } else { + throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`); + } + } else { + key = it; + } + pairs2.items.push(Pair.createPair(key, value, ctx)); + } + return pairs2; + } + var pairs = { + collection: "seq", + default: false, + tag: "tag:yaml.org,2002:pairs", + resolve: resolvePairs, + createNode: createPairs + }; + exports2.createPairs = createPairs; + exports2.pairs = pairs; + exports2.resolvePairs = resolvePairs; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/omap.js +var require_omap = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/omap.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var toJS = require_toJS(); + var YAMLMap = require_YAMLMap(); + var YAMLSeq = require_YAMLSeq(); + var pairs = require_pairs(); + var YAMLOMap = class _YAMLOMap extends YAMLSeq.YAMLSeq { + constructor() { + super(); + this.add = YAMLMap.YAMLMap.prototype.add.bind(this); + this.delete = YAMLMap.YAMLMap.prototype.delete.bind(this); + this.get = YAMLMap.YAMLMap.prototype.get.bind(this); + this.has = YAMLMap.YAMLMap.prototype.has.bind(this); + this.set = YAMLMap.YAMLMap.prototype.set.bind(this); + this.tag = _YAMLOMap.tag; + } + /** + * If `ctx` is given, the return type is actually `Map`, + * but TypeScript won't allow widening the signature of a child method. + */ + toJSON(_, ctx) { + if (!ctx) + return super.toJSON(_); + const map = /* @__PURE__ */ new Map(); + if (ctx?.onCreate) + ctx.onCreate(map); + for (const pair of this.items) { + let key, value; + if (identity3.isPair(pair)) { + key = toJS.toJS(pair.key, "", ctx); + value = toJS.toJS(pair.value, key, ctx); + } else { + key = toJS.toJS(pair, "", ctx); + } + if (map.has(key)) + throw new Error("Ordered maps must not include duplicate keys"); + map.set(key, value); + } + return map; + } + static from(schema, iterable, ctx) { + const pairs$1 = pairs.createPairs(schema, iterable, ctx); + const omap2 = new this(); + omap2.items = pairs$1.items; + return omap2; + } + }; + YAMLOMap.tag = "tag:yaml.org,2002:omap"; + var omap = { + collection: "seq", + identify: (value) => value instanceof Map, + nodeClass: YAMLOMap, + default: false, + tag: "tag:yaml.org,2002:omap", + resolve(seq, onError) { + const pairs$1 = pairs.resolvePairs(seq, onError); + const seenKeys = []; + for (const { key } of pairs$1.items) { + if (identity3.isScalar(key)) { + if (seenKeys.includes(key.value)) { + onError(`Ordered maps must not include duplicate keys: ${key.value}`); + } else { + seenKeys.push(key.value); + } + } + } + return Object.assign(new YAMLOMap(), pairs$1); + }, + createNode: (schema, iterable, ctx) => YAMLOMap.from(schema, iterable, ctx) + }; + exports2.YAMLOMap = YAMLOMap; + exports2.omap = omap; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/bool.js +var require_bool2 = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/bool.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + function boolStringify({ value, source }, ctx) { + const boolObj = value ? trueTag : falseTag; + if (source && boolObj.test.test(source)) + return source; + return value ? ctx.options.trueStr : ctx.options.falseStr; + } + var trueTag = { + identify: (value) => value === true, + default: true, + tag: "tag:yaml.org,2002:bool", + test: /^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/, + resolve: () => new Scalar.Scalar(true), + stringify: boolStringify + }; + var falseTag = { + identify: (value) => value === false, + default: true, + tag: "tag:yaml.org,2002:bool", + test: /^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/, + resolve: () => new Scalar.Scalar(false), + stringify: boolStringify + }; + exports2.falseTag = falseTag; + exports2.trueTag = trueTag; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/float.js +var require_float2 = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/float.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var stringifyNumber = require_stringifyNumber(); + var floatNaN = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/, + resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY, + stringify: stringifyNumber.stringifyNumber + }; + var floatExp = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + format: "EXP", + test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/, + resolve: (str) => parseFloat(str.replace(/_/g, "")), + stringify(node) { + const num = Number(node.value); + return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node); + } + }; + var float = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/, + resolve(str) { + const node = new Scalar.Scalar(parseFloat(str.replace(/_/g, ""))); + const dot = str.indexOf("."); + if (dot !== -1) { + const f = str.substring(dot + 1).replace(/_/g, ""); + if (f[f.length - 1] === "0") + node.minFractionDigits = f.length; + } + return node; + }, + stringify: stringifyNumber.stringifyNumber + }; + exports2.float = float; + exports2.floatExp = floatExp; + exports2.floatNaN = floatNaN; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/int.js +var require_int2 = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/int.js"(exports2) { + "use strict"; + var stringifyNumber = require_stringifyNumber(); + var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value); + function intResolve(str, offset, radix, { intAsBigInt }) { + const sign = str[0]; + if (sign === "-" || sign === "+") + offset += 1; + str = str.substring(offset).replace(/_/g, ""); + if (intAsBigInt) { + switch (radix) { + case 2: + str = `0b${str}`; + break; + case 8: + str = `0o${str}`; + break; + case 16: + str = `0x${str}`; + break; + } + const n3 = BigInt(str); + return sign === "-" ? BigInt(-1) * n3 : n3; + } + const n2 = parseInt(str, radix); + return sign === "-" ? -1 * n2 : n2; + } + function intStringify(node, radix, prefix) { + const { value } = node; + if (intIdentify(value)) { + const str = value.toString(radix); + return value < 0 ? "-" + prefix + str.substr(1) : prefix + str; + } + return stringifyNumber.stringifyNumber(node); + } + var intBin = { + identify: intIdentify, + default: true, + tag: "tag:yaml.org,2002:int", + format: "BIN", + test: /^[-+]?0b[0-1_]+$/, + resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt), + stringify: (node) => intStringify(node, 2, "0b") + }; + var intOct = { + identify: intIdentify, + default: true, + tag: "tag:yaml.org,2002:int", + format: "OCT", + test: /^[-+]?0[0-7_]+$/, + resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt), + stringify: (node) => intStringify(node, 8, "0") + }; + var int = { + identify: intIdentify, + default: true, + tag: "tag:yaml.org,2002:int", + test: /^[-+]?[0-9][0-9_]*$/, + resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt), + stringify: stringifyNumber.stringifyNumber + }; + var intHex = { + identify: intIdentify, + default: true, + tag: "tag:yaml.org,2002:int", + format: "HEX", + test: /^[-+]?0x[0-9a-fA-F_]+$/, + resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt), + stringify: (node) => intStringify(node, 16, "0x") + }; + exports2.int = int; + exports2.intBin = intBin; + exports2.intHex = intHex; + exports2.intOct = intOct; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/set.js +var require_set = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/set.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Pair = require_Pair(); + var YAMLMap = require_YAMLMap(); + var YAMLSet = class _YAMLSet extends YAMLMap.YAMLMap { + constructor(schema) { + super(schema); + this.tag = _YAMLSet.tag; + } + add(key) { + let pair; + if (identity3.isPair(key)) + pair = key; + else if (key && typeof key === "object" && "key" in key && "value" in key && key.value === null) + pair = new Pair.Pair(key.key, null); + else + pair = new Pair.Pair(key, null); + const prev = YAMLMap.findPair(this.items, pair.key); + if (!prev) + this.items.push(pair); + } + /** + * If `keepPair` is `true`, returns the Pair matching `key`. + * Otherwise, returns the value of that Pair's key. + */ + get(key, keepPair) { + const pair = YAMLMap.findPair(this.items, key); + return !keepPair && identity3.isPair(pair) ? identity3.isScalar(pair.key) ? pair.key.value : pair.key : pair; + } + set(key, value) { + if (typeof value !== "boolean") + throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`); + const prev = YAMLMap.findPair(this.items, key); + if (prev && !value) { + this.items.splice(this.items.indexOf(prev), 1); + } else if (!prev && value) { + this.items.push(new Pair.Pair(key)); + } + } + toJSON(_, ctx) { + return super.toJSON(_, ctx, Set); + } + toString(ctx, onComment, onChompKeep) { + if (!ctx) + return JSON.stringify(this); + if (this.hasAllNullValues(true)) + return super.toString(Object.assign({}, ctx, { allNullValues: true }), onComment, onChompKeep); + else + throw new Error("Set items must all have null values"); + } + static from(schema, iterable, ctx) { + const { replacer } = ctx; + const set2 = new this(schema); + if (iterable && Symbol.iterator in Object(iterable)) + for (let value of iterable) { + if (typeof replacer === "function") + value = replacer.call(iterable, value, value); + set2.items.push(Pair.createPair(value, null, ctx)); + } + return set2; + } + }; + YAMLSet.tag = "tag:yaml.org,2002:set"; + var set = { + collection: "map", + identify: (value) => value instanceof Set, + nodeClass: YAMLSet, + default: false, + tag: "tag:yaml.org,2002:set", + createNode: (schema, iterable, ctx) => YAMLSet.from(schema, iterable, ctx), + resolve(map, onError) { + if (identity3.isMap(map)) { + if (map.hasAllNullValues(true)) + return Object.assign(new YAMLSet(), map); + else + onError("Set items must all have null values"); + } else + onError("Expected a mapping for this tag"); + return map; + } + }; + exports2.YAMLSet = YAMLSet; + exports2.set = set; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +var require_timestamp = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js"(exports2) { + "use strict"; + var stringifyNumber = require_stringifyNumber(); + function parseSexagesimal(str, asBigInt) { + const sign = str[0]; + const parts = sign === "-" || sign === "+" ? str.substring(1) : str; + const num = (n2) => asBigInt ? BigInt(n2) : Number(n2); + const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num(60) + num(p), num(0)); + return sign === "-" ? num(-1) * res : res; + } + function stringifySexagesimal(node) { + let { value } = node; + let num = (n2) => n2; + if (typeof value === "bigint") + num = (n2) => BigInt(n2); + else if (isNaN(value) || !isFinite(value)) + return stringifyNumber.stringifyNumber(node); + let sign = ""; + if (value < 0) { + sign = "-"; + value *= num(-1); + } + const _60 = num(60); + const parts = [value % _60]; + if (value < 60) { + parts.unshift(0); + } else { + value = (value - parts[0]) / _60; + parts.unshift(value % _60); + if (value >= 60) { + value = (value - parts[0]) / _60; + parts.unshift(value); + } + } + return sign + parts.map((n2) => String(n2).padStart(2, "0")).join(":").replace(/000000\d*$/, ""); + } + var intTime = { + identify: (value) => typeof value === "bigint" || Number.isInteger(value), + default: true, + tag: "tag:yaml.org,2002:int", + format: "TIME", + test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/, + resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt), + stringify: stringifySexagesimal + }; + var floatTime = { + identify: (value) => typeof value === "number", + default: true, + tag: "tag:yaml.org,2002:float", + format: "TIME", + test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/, + resolve: (str) => parseSexagesimal(str, false), + stringify: stringifySexagesimal + }; + var timestamp = { + identify: (value) => value instanceof Date, + default: true, + tag: "tag:yaml.org,2002:timestamp", + // If the time zone is omitted, the timestamp is assumed to be specified in UTC. The time part + // may be omitted altogether, resulting in a date format. In such a case, the time part is + // assumed to be 00:00:00Z (start of day, UTC). + test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"), + resolve(str) { + const match = str.match(timestamp.test); + if (!match) + throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd"); + const [, year, month, day, hour, minute, second] = match.map(Number); + const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0; + let date = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec); + const tz = match[8]; + if (tz && tz !== "Z") { + let d = parseSexagesimal(tz, false); + if (Math.abs(d) < 30) + d *= 60; + date -= 6e4 * d; + } + return new Date(date); + }, + stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? "" + }; + exports2.floatTime = floatTime; + exports2.intTime = intTime; + exports2.timestamp = timestamp; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/schema.js +var require_schema3 = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/yaml-1.1/schema.js"(exports2) { + "use strict"; + var map = require_map(); + var _null = require_null(); + var seq = require_seq(); + var string = require_string(); + var binary = require_binary(); + var bool = require_bool2(); + var float = require_float2(); + var int = require_int2(); + var merge = require_merge(); + var omap = require_omap(); + var pairs = require_pairs(); + var set = require_set(); + var timestamp = require_timestamp(); + var schema = [ + map.map, + seq.seq, + string.string, + _null.nullTag, + bool.trueTag, + bool.falseTag, + int.intBin, + int.intOct, + int.int, + int.intHex, + float.floatNaN, + float.floatExp, + float.float, + binary.binary, + merge.merge, + omap.omap, + pairs.pairs, + set.set, + timestamp.intTime, + timestamp.floatTime, + timestamp.timestamp + ]; + exports2.schema = schema; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/tags.js +var require_tags = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/tags.js"(exports2) { + "use strict"; + var map = require_map(); + var _null = require_null(); + var seq = require_seq(); + var string = require_string(); + var bool = require_bool(); + var float = require_float(); + var int = require_int(); + var schema = require_schema(); + var schema$1 = require_schema2(); + var binary = require_binary(); + var merge = require_merge(); + var omap = require_omap(); + var pairs = require_pairs(); + var schema$2 = require_schema3(); + var set = require_set(); + var timestamp = require_timestamp(); + var schemas = /* @__PURE__ */ new Map([ + ["core", schema.schema], + ["failsafe", [map.map, seq.seq, string.string]], + ["json", schema$1.schema], + ["yaml11", schema$2.schema], + ["yaml-1.1", schema$2.schema] + ]); + var tagsByName = { + binary: binary.binary, + bool: bool.boolTag, + float: float.float, + floatExp: float.floatExp, + floatNaN: float.floatNaN, + floatTime: timestamp.floatTime, + int: int.int, + intHex: int.intHex, + intOct: int.intOct, + intTime: timestamp.intTime, + map: map.map, + merge: merge.merge, + null: _null.nullTag, + omap: omap.omap, + pairs: pairs.pairs, + seq: seq.seq, + set: set.set, + timestamp: timestamp.timestamp + }; + var coreKnownTags = { + "tag:yaml.org,2002:binary": binary.binary, + "tag:yaml.org,2002:merge": merge.merge, + "tag:yaml.org,2002:omap": omap.omap, + "tag:yaml.org,2002:pairs": pairs.pairs, + "tag:yaml.org,2002:set": set.set, + "tag:yaml.org,2002:timestamp": timestamp.timestamp + }; + function getTags(customTags, schemaName, addMergeTag) { + const schemaTags = schemas.get(schemaName); + if (schemaTags && !customTags) { + return addMergeTag && !schemaTags.includes(merge.merge) ? schemaTags.concat(merge.merge) : schemaTags.slice(); + } + let tags = schemaTags; + if (!tags) { + if (Array.isArray(customTags)) + tags = []; + else { + const keys = Array.from(schemas.keys()).filter((key) => key !== "yaml11").map((key) => JSON.stringify(key)).join(", "); + throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`); + } + } + if (Array.isArray(customTags)) { + for (const tag of customTags) + tags = tags.concat(tag); + } else if (typeof customTags === "function") { + tags = customTags(tags.slice()); + } + if (addMergeTag) + tags = tags.concat(merge.merge); + return tags.reduce((tags2, tag) => { + const tagObj = typeof tag === "string" ? tagsByName[tag] : tag; + if (!tagObj) { + const tagName = JSON.stringify(tag); + const keys = Object.keys(tagsByName).map((key) => JSON.stringify(key)).join(", "); + throw new Error(`Unknown custom tag ${tagName}; use one of ${keys}`); + } + if (!tags2.includes(tagObj)) + tags2.push(tagObj); + return tags2; + }, []); + } + exports2.coreKnownTags = coreKnownTags; + exports2.getTags = getTags; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/Schema.js +var require_Schema = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/schema/Schema.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var map = require_map(); + var seq = require_seq(); + var string = require_string(); + var tags = require_tags(); + var sortMapEntriesByKey = (a2, b) => a2.key < b.key ? -1 : a2.key > b.key ? 1 : 0; + var Schema = class _Schema { + constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) { + this.compat = Array.isArray(compat) ? tags.getTags(compat, "compat") : compat ? tags.getTags(null, compat) : null; + this.name = typeof schema === "string" && schema || "core"; + this.knownTags = resolveKnownTags ? tags.coreKnownTags : {}; + this.tags = tags.getTags(customTags, this.name, merge); + this.toStringOptions = toStringDefaults ?? null; + Object.defineProperty(this, identity3.MAP, { value: map.map }); + Object.defineProperty(this, identity3.SCALAR, { value: string.string }); + Object.defineProperty(this, identity3.SEQ, { value: seq.seq }); + this.sortMapEntries = typeof sortMapEntries === "function" ? sortMapEntries : sortMapEntries === true ? sortMapEntriesByKey : null; + } + clone() { + const copy = Object.create(_Schema.prototype, Object.getOwnPropertyDescriptors(this)); + copy.tags = this.tags.slice(); + return copy; + } + }; + exports2.Schema = Schema; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyDocument.js +var require_stringifyDocument = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyDocument.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var stringify = require_stringify(); + var stringifyComment = require_stringifyComment(); + function stringifyDocument(doc, options) { + const lines = []; + let hasDirectives = options.directives === true; + if (options.directives !== false && doc.directives) { + const dir = doc.directives.toString(doc); + if (dir) { + lines.push(dir); + hasDirectives = true; + } else if (doc.directives.docStart) + hasDirectives = true; + } + if (hasDirectives) + lines.push("---"); + const ctx = stringify.createStringifyContext(doc, options); + const { commentString } = ctx.options; + if (doc.commentBefore) { + if (lines.length !== 1) + lines.unshift(""); + const cs = commentString(doc.commentBefore); + lines.unshift(stringifyComment.indentComment(cs, "")); + } + let chompKeep = false; + let contentComment = null; + if (doc.contents) { + if (identity3.isNode(doc.contents)) { + if (doc.contents.spaceBefore && hasDirectives) + lines.push(""); + if (doc.contents.commentBefore) { + const cs = commentString(doc.contents.commentBefore); + lines.push(stringifyComment.indentComment(cs, "")); + } + ctx.forceBlockIndent = !!doc.comment; + contentComment = doc.contents.comment; + } + const onChompKeep = contentComment ? void 0 : () => chompKeep = true; + let body = stringify.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep); + if (contentComment) + body += stringifyComment.lineComment(body, "", commentString(contentComment)); + if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") { + lines[lines.length - 1] = `--- ${body}`; + } else + lines.push(body); + } else { + lines.push(stringify.stringify(doc.contents, ctx)); + } + if (doc.directives?.docEnd) { + if (doc.comment) { + const cs = commentString(doc.comment); + if (cs.includes("\n")) { + lines.push("..."); + lines.push(stringifyComment.indentComment(cs, "")); + } else { + lines.push(`... ${cs}`); + } + } else { + lines.push("..."); + } + } else { + let dc = doc.comment; + if (dc && chompKeep) + dc = dc.replace(/^\n+/, ""); + if (dc) { + if ((!chompKeep || contentComment) && lines[lines.length - 1] !== "") + lines.push(""); + lines.push(stringifyComment.indentComment(commentString(dc), "")); + } + } + return lines.join("\n") + "\n"; + } + exports2.stringifyDocument = stringifyDocument; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/Document.js +var require_Document = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/doc/Document.js"(exports2) { + "use strict"; + var Alias = require_Alias(); + var Collection = require_Collection(); + var identity3 = require_identity(); + var Pair = require_Pair(); + var toJS = require_toJS(); + var Schema = require_Schema(); + var stringifyDocument = require_stringifyDocument(); + var anchors = require_anchors(); + var applyReviver = require_applyReviver(); + var createNode = require_createNode(); + var directives = require_directives(); + var Document = class _Document { + constructor(value, replacer, options) { + this.commentBefore = null; + this.comment = null; + this.errors = []; + this.warnings = []; + Object.defineProperty(this, identity3.NODE_TYPE, { value: identity3.DOC }); + let _replacer = null; + if (typeof replacer === "function" || Array.isArray(replacer)) { + _replacer = replacer; + } else if (options === void 0 && replacer) { + options = replacer; + replacer = void 0; + } + const opt = Object.assign({ + intAsBigInt: false, + keepSourceTokens: false, + logLevel: "warn", + prettyErrors: true, + strict: true, + stringKeys: false, + uniqueKeys: true, + version: "1.2" + }, options); + this.options = opt; + let { version } = opt; + if (options?._directives) { + this.directives = options._directives.atDocument(); + if (this.directives.yaml.explicit) + version = this.directives.yaml.version; + } else + this.directives = new directives.Directives({ version }); + this.setSchema(version, options); + this.contents = value === void 0 ? null : this.createNode(value, _replacer, options); + } + /** + * Create a deep copy of this Document and its contents. + * + * Custom Node values that inherit from `Object` still refer to their original instances. + */ + clone() { + const copy = Object.create(_Document.prototype, { + [identity3.NODE_TYPE]: { value: identity3.DOC } + }); + copy.commentBefore = this.commentBefore; + copy.comment = this.comment; + copy.errors = this.errors.slice(); + copy.warnings = this.warnings.slice(); + copy.options = Object.assign({}, this.options); + if (this.directives) + copy.directives = this.directives.clone(); + copy.schema = this.schema.clone(); + copy.contents = identity3.isNode(this.contents) ? this.contents.clone(copy.schema) : this.contents; + if (this.range) + copy.range = this.range.slice(); + return copy; + } + /** Adds a value to the document. */ + add(value) { + if (assertCollection(this.contents)) + this.contents.add(value); + } + /** Adds a value to the document. */ + addIn(path12, value) { + if (assertCollection(this.contents)) + this.contents.addIn(path12, value); + } + /** + * Create a new `Alias` node, ensuring that the target `node` has the required anchor. + * + * If `node` already has an anchor, `name` is ignored. + * Otherwise, the `node.anchor` value will be set to `name`, + * or if an anchor with that name is already present in the document, + * `name` will be used as a prefix for a new unique anchor. + * If `name` is undefined, the generated anchor will use 'a' as a prefix. + */ + createAlias(node, name) { + if (!node.anchor) { + const prev = anchors.anchorNames(this); + node.anchor = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + !name || prev.has(name) ? anchors.findNewAnchor(name || "a", prev) : name; + } + return new Alias.Alias(node.anchor); + } + createNode(value, replacer, options) { + let _replacer = void 0; + if (typeof replacer === "function") { + value = replacer.call({ "": value }, "", value); + _replacer = replacer; + } else if (Array.isArray(replacer)) { + const keyToStr = (v) => typeof v === "number" || v instanceof String || v instanceof Number; + const asStr = replacer.filter(keyToStr).map(String); + if (asStr.length > 0) + replacer = replacer.concat(asStr); + _replacer = replacer; + } else if (options === void 0 && replacer) { + options = replacer; + replacer = void 0; + } + const { aliasDuplicateObjects, anchorPrefix, flow, keepUndefined, onTagObj, tag } = options ?? {}; + const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors( + this, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + anchorPrefix || "a" + ); + const ctx = { + aliasDuplicateObjects: aliasDuplicateObjects ?? true, + keepUndefined: keepUndefined ?? false, + onAnchor, + onTagObj, + replacer: _replacer, + schema: this.schema, + sourceObjects + }; + const node = createNode.createNode(value, tag, ctx); + if (flow && identity3.isCollection(node)) + node.flow = true; + setAnchors(); + return node; + } + /** + * Convert a key and a value into a `Pair` using the current schema, + * recursively wrapping all values as `Scalar` or `Collection` nodes. + */ + createPair(key, value, options = {}) { + const k = this.createNode(key, null, options); + const v = this.createNode(value, null, options); + return new Pair.Pair(k, v); + } + /** + * Removes a value from the document. + * @returns `true` if the item was found and removed. + */ + delete(key) { + return assertCollection(this.contents) ? this.contents.delete(key) : false; + } + /** + * Removes a value from the document. + * @returns `true` if the item was found and removed. + */ + deleteIn(path12) { + if (Collection.isEmptyPath(path12)) { + if (this.contents == null) + return false; + this.contents = null; + return true; + } + return assertCollection(this.contents) ? this.contents.deleteIn(path12) : false; + } + /** + * Returns item at `key`, or `undefined` if not found. By default unwraps + * scalar values from their surrounding node; to disable set `keepScalar` to + * `true` (collections are always returned intact). + */ + get(key, keepScalar) { + return identity3.isCollection(this.contents) ? this.contents.get(key, keepScalar) : void 0; + } + /** + * Returns item at `path`, or `undefined` if not found. By default unwraps + * scalar values from their surrounding node; to disable set `keepScalar` to + * `true` (collections are always returned intact). + */ + getIn(path12, keepScalar) { + if (Collection.isEmptyPath(path12)) + return !keepScalar && identity3.isScalar(this.contents) ? this.contents.value : this.contents; + return identity3.isCollection(this.contents) ? this.contents.getIn(path12, keepScalar) : void 0; + } + /** + * Checks if the document includes a value with the key `key`. + */ + has(key) { + return identity3.isCollection(this.contents) ? this.contents.has(key) : false; + } + /** + * Checks if the document includes a value at `path`. + */ + hasIn(path12) { + if (Collection.isEmptyPath(path12)) + return this.contents !== void 0; + return identity3.isCollection(this.contents) ? this.contents.hasIn(path12) : false; + } + /** + * Sets a value in this document. For `!!set`, `value` needs to be a + * boolean to add/remove the item from the set. + */ + set(key, value) { + if (this.contents == null) { + this.contents = Collection.collectionFromPath(this.schema, [key], value); + } else if (assertCollection(this.contents)) { + this.contents.set(key, value); + } + } + /** + * Sets a value in this document. For `!!set`, `value` needs to be a + * boolean to add/remove the item from the set. + */ + setIn(path12, value) { + if (Collection.isEmptyPath(path12)) { + this.contents = value; + } else if (this.contents == null) { + this.contents = Collection.collectionFromPath(this.schema, Array.from(path12), value); + } else if (assertCollection(this.contents)) { + this.contents.setIn(path12, value); + } + } + /** + * Change the YAML version and schema used by the document. + * A `null` version disables support for directives, explicit tags, anchors, and aliases. + * It also requires the `schema` option to be given as a `Schema` instance value. + * + * Overrides all previously set schema options. + */ + setSchema(version, options = {}) { + if (typeof version === "number") + version = String(version); + let opt; + switch (version) { + case "1.1": + if (this.directives) + this.directives.yaml.version = "1.1"; + else + this.directives = new directives.Directives({ version: "1.1" }); + opt = { resolveKnownTags: false, schema: "yaml-1.1" }; + break; + case "1.2": + case "next": + if (this.directives) + this.directives.yaml.version = version; + else + this.directives = new directives.Directives({ version }); + opt = { resolveKnownTags: true, schema: "core" }; + break; + case null: + if (this.directives) + delete this.directives; + opt = null; + break; + default: { + const sv = JSON.stringify(version); + throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`); + } + } + if (options.schema instanceof Object) + this.schema = options.schema; + else if (opt) + this.schema = new Schema.Schema(Object.assign(opt, options)); + else + throw new Error(`With a null YAML version, the { schema: Schema } option is required`); + } + // json & jsonArg are only used from toJSON() + toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) { + const ctx = { + anchors: /* @__PURE__ */ new Map(), + doc: this, + keep: !json, + mapAsMap: mapAsMap === true, + mapKeyWarned: false, + maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100 + }; + const res = toJS.toJS(this.contents, jsonArg ?? "", ctx); + if (typeof onAnchor === "function") + for (const { count: count2, res: res2 } of ctx.anchors.values()) + onAnchor(res2, count2); + return typeof reviver === "function" ? applyReviver.applyReviver(reviver, { "": res }, "", res) : res; + } + /** + * A JSON representation of the document `contents`. + * + * @param jsonArg Used by `JSON.stringify` to indicate the array index or + * property name. + */ + toJSON(jsonArg, onAnchor) { + return this.toJS({ json: true, jsonArg, mapAsMap: false, onAnchor }); + } + /** A YAML representation of the document. */ + toString(options = {}) { + if (this.errors.length > 0) + throw new Error("Document with errors cannot be stringified"); + if ("indent" in options && (!Number.isInteger(options.indent) || Number(options.indent) <= 0)) { + const s = JSON.stringify(options.indent); + throw new Error(`"indent" option must be a positive integer, not ${s}`); + } + return stringifyDocument.stringifyDocument(this, options); + } + }; + function assertCollection(contents) { + if (identity3.isCollection(contents)) + return true; + throw new Error("Expected a YAML collection as document contents"); + } + exports2.Document = Document; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/errors.js +var require_errors2 = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/errors.js"(exports2) { + "use strict"; + var YAMLError = class extends Error { + constructor(name, pos, code2, message) { + super(); + this.name = name; + this.code = code2; + this.message = message; + this.pos = pos; + } + }; + var YAMLParseError = class extends YAMLError { + constructor(pos, code2, message) { + super("YAMLParseError", pos, code2, message); + } + }; + var YAMLWarning = class extends YAMLError { + constructor(pos, code2, message) { + super("YAMLWarning", pos, code2, message); + } + }; + var prettifyError = (src, lc) => (error) => { + if (error.pos[0] === -1) + return; + error.linePos = error.pos.map((pos) => lc.linePos(pos)); + const { line, col } = error.linePos[0]; + error.message += ` at line ${line}, column ${col}`; + let ci = col - 1; + let lineStr = src.substring(lc.lineStarts[line - 1], lc.lineStarts[line]).replace(/[\n\r]+$/, ""); + if (ci >= 60 && lineStr.length > 80) { + const trimStart = Math.min(ci - 39, lineStr.length - 79); + lineStr = "\u2026" + lineStr.substring(trimStart); + ci -= trimStart - 1; + } + if (lineStr.length > 80) + lineStr = lineStr.substring(0, 79) + "\u2026"; + if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) { + let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]); + if (prev.length > 80) + prev = prev.substring(0, 79) + "\u2026\n"; + lineStr = prev + lineStr; + } + if (/[^ ]/.test(lineStr)) { + let count2 = 1; + const end = error.linePos[1]; + if (end?.line === line && end.col > col) { + count2 = Math.max(1, Math.min(end.col - col, 80 - ci)); + } + const pointer = " ".repeat(ci) + "^".repeat(count2); + error.message += `: + +${lineStr} +${pointer} +`; + } + }; + exports2.YAMLError = YAMLError; + exports2.YAMLParseError = YAMLParseError; + exports2.YAMLWarning = YAMLWarning; + exports2.prettifyError = prettifyError; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js +var require_resolve_props = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-props.js"(exports2) { + "use strict"; + function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) { + let spaceBefore = false; + let atNewline = startOnNewline; + let hasSpace = startOnNewline; + let comment = ""; + let commentSep = ""; + let hasNewline = false; + let reqSpace = false; + let tab = null; + let anchor = null; + let tag = null; + let newlineAfterProp = null; + let comma = null; + let found = null; + let start = null; + for (const token of tokens) { + if (reqSpace) { + if (token.type !== "space" && token.type !== "newline" && token.type !== "comma") + onError(token.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space"); + reqSpace = false; + } + if (tab) { + if (atNewline && token.type !== "comment" && token.type !== "newline") { + onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation"); + } + tab = null; + } + switch (token.type) { + case "space": + if (!flow && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) { + tab = token; + } + hasSpace = true; + break; + case "comment": { + if (!hasSpace) + onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters"); + const cb = token.source.substring(1) || " "; + if (!comment) + comment = cb; + else + comment += commentSep + cb; + commentSep = ""; + atNewline = false; + break; + } + case "newline": + if (atNewline) { + if (comment) + comment += token.source; + else if (!found || indicator !== "seq-item-ind") + spaceBefore = true; + } else + commentSep += token.source; + atNewline = true; + hasNewline = true; + if (anchor || tag) + newlineAfterProp = token; + hasSpace = true; + break; + case "anchor": + if (anchor) + onError(token, "MULTIPLE_ANCHORS", "A node can have at most one anchor"); + if (token.source.endsWith(":")) + onError(token.offset + token.source.length - 1, "BAD_ALIAS", "Anchor ending in : is ambiguous", true); + anchor = token; + start ?? (start = token.offset); + atNewline = false; + hasSpace = false; + reqSpace = true; + break; + case "tag": { + if (tag) + onError(token, "MULTIPLE_TAGS", "A node can have at most one tag"); + tag = token; + start ?? (start = token.offset); + atNewline = false; + hasSpace = false; + reqSpace = true; + break; + } + case indicator: + if (anchor || tag) + onError(token, "BAD_PROP_ORDER", `Anchors and tags must be after the ${token.source} indicator`); + if (found) + onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow ?? "collection"}`); + found = token; + atNewline = indicator === "seq-item-ind" || indicator === "explicit-key-ind"; + hasSpace = false; + break; + case "comma": + if (flow) { + if (comma) + onError(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow}`); + comma = token; + atNewline = false; + hasSpace = false; + break; + } + // else fallthrough + default: + onError(token, "UNEXPECTED_TOKEN", `Unexpected ${token.type} token`); + atNewline = false; + hasSpace = false; + } + } + const last = tokens[tokens.length - 1]; + const end = last ? last.offset + last.source.length : offset; + if (reqSpace && next && next.type !== "space" && next.type !== "newline" && next.type !== "comma" && (next.type !== "scalar" || next.source !== "")) { + onError(next.offset, "MISSING_CHAR", "Tags and anchors must be separated from the next token by white space"); + } + if (tab && (atNewline && tab.indent <= parentIndent || next?.type === "block-map" || next?.type === "block-seq")) + onError(tab, "TAB_AS_INDENT", "Tabs are not allowed as indentation"); + return { + comma, + found, + spaceBefore, + comment, + hasNewline, + anchor, + tag, + newlineAfterProp, + end, + start: start ?? end + }; + } + exports2.resolveProps = resolveProps; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-contains-newline.js +var require_util_contains_newline = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-contains-newline.js"(exports2) { + "use strict"; + function containsNewline(key) { + if (!key) + return null; + switch (key.type) { + case "alias": + case "scalar": + case "double-quoted-scalar": + case "single-quoted-scalar": + if (key.source.includes("\n")) + return true; + if (key.end) { + for (const st of key.end) + if (st.type === "newline") + return true; + } + return false; + case "flow-collection": + for (const it of key.items) { + for (const st of it.start) + if (st.type === "newline") + return true; + if (it.sep) { + for (const st of it.sep) + if (st.type === "newline") + return true; + } + if (containsNewline(it.key) || containsNewline(it.value)) + return true; + } + return false; + default: + return true; + } + } + exports2.containsNewline = containsNewline; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-flow-indent-check.js +var require_util_flow_indent_check = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-flow-indent-check.js"(exports2) { + "use strict"; + var utilContainsNewline = require_util_contains_newline(); + function flowIndentCheck(indent, fc, onError) { + if (fc?.type === "flow-collection") { + const end = fc.end[0]; + if (end.indent === indent && (end.source === "]" || end.source === "}") && utilContainsNewline.containsNewline(fc)) { + const msg = "Flow end indicator should be more indented than parent"; + onError(end, "BAD_INDENT", msg, true); + } + } + } + exports2.flowIndentCheck = flowIndentCheck; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-map-includes.js +var require_util_map_includes = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-map-includes.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + function mapIncludes(ctx, items, search) { + const { uniqueKeys } = ctx.options; + if (uniqueKeys === false) + return false; + const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a2, b) => a2 === b || identity3.isScalar(a2) && identity3.isScalar(b) && a2.value === b.value; + return items.some((pair) => isEqual(pair.key, search)); + } + exports2.mapIncludes = mapIncludes; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-map.js +var require_resolve_block_map = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-map.js"(exports2) { + "use strict"; + var Pair = require_Pair(); + var YAMLMap = require_YAMLMap(); + var resolveProps = require_resolve_props(); + var utilContainsNewline = require_util_contains_newline(); + var utilFlowIndentCheck = require_util_flow_indent_check(); + var utilMapIncludes = require_util_map_includes(); + var startColMsg = "All mapping items must start at the same column"; + function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, tag) { + const NodeClass = tag?.nodeClass ?? YAMLMap.YAMLMap; + const map = new NodeClass(ctx.schema); + if (ctx.atRoot) + ctx.atRoot = false; + let offset = bm.offset; + let commentEnd = null; + for (const collItem of bm.items) { + const { start, key, sep, value } = collItem; + const keyProps = resolveProps.resolveProps(start, { + indicator: "explicit-key-ind", + next: key ?? sep?.[0], + offset, + onError, + parentIndent: bm.indent, + startOnNewline: true + }); + const implicitKey = !keyProps.found; + if (implicitKey) { + if (key) { + if (key.type === "block-seq") + onError(offset, "BLOCK_AS_IMPLICIT_KEY", "A block sequence may not be used as an implicit map key"); + else if ("indent" in key && key.indent !== bm.indent) + onError(offset, "BAD_INDENT", startColMsg); + } + if (!keyProps.anchor && !keyProps.tag && !sep) { + commentEnd = keyProps.end; + if (keyProps.comment) { + if (map.comment) + map.comment += "\n" + keyProps.comment; + else + map.comment = keyProps.comment; + } + continue; + } + if (keyProps.newlineAfterProp || utilContainsNewline.containsNewline(key)) { + onError(key ?? start[start.length - 1], "MULTILINE_IMPLICIT_KEY", "Implicit keys need to be on a single line"); + } + } else if (keyProps.found?.indent !== bm.indent) { + onError(offset, "BAD_INDENT", startColMsg); + } + ctx.atKey = true; + const keyStart = keyProps.end; + const keyNode = key ? composeNode(ctx, key, keyProps, onError) : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError); + if (ctx.schema.compat) + utilFlowIndentCheck.flowIndentCheck(bm.indent, key, onError); + ctx.atKey = false; + if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode)) + onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique"); + const valueProps = resolveProps.resolveProps(sep ?? [], { + indicator: "map-value-ind", + next: value, + offset: keyNode.range[2], + onError, + parentIndent: bm.indent, + startOnNewline: !key || key.type === "block-scalar" + }); + offset = valueProps.end; + if (valueProps.found) { + if (implicitKey) { + if (value?.type === "block-map" && !valueProps.hasNewline) + onError(offset, "BLOCK_AS_IMPLICIT_KEY", "Nested mappings are not allowed in compact mappings"); + if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024) + onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key"); + } + const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep, null, valueProps, onError); + if (ctx.schema.compat) + utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError); + offset = valueNode.range[2]; + const pair = new Pair.Pair(keyNode, valueNode); + if (ctx.options.keepSourceTokens) + pair.srcToken = collItem; + map.items.push(pair); + } else { + if (implicitKey) + onError(keyNode.range, "MISSING_CHAR", "Implicit map keys need to be followed by map values"); + if (valueProps.comment) { + if (keyNode.comment) + keyNode.comment += "\n" + valueProps.comment; + else + keyNode.comment = valueProps.comment; + } + const pair = new Pair.Pair(keyNode); + if (ctx.options.keepSourceTokens) + pair.srcToken = collItem; + map.items.push(pair); + } + } + if (commentEnd && commentEnd < offset) + onError(commentEnd, "IMPOSSIBLE", "Map comment with trailing content"); + map.range = [bm.offset, offset, commentEnd ?? offset]; + return map; + } + exports2.resolveBlockMap = resolveBlockMap; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-seq.js +var require_resolve_block_seq = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-seq.js"(exports2) { + "use strict"; + var YAMLSeq = require_YAMLSeq(); + var resolveProps = require_resolve_props(); + var utilFlowIndentCheck = require_util_flow_indent_check(); + function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, tag) { + const NodeClass = tag?.nodeClass ?? YAMLSeq.YAMLSeq; + const seq = new NodeClass(ctx.schema); + if (ctx.atRoot) + ctx.atRoot = false; + if (ctx.atKey) + ctx.atKey = false; + let offset = bs.offset; + let commentEnd = null; + for (const { start, value } of bs.items) { + const props = resolveProps.resolveProps(start, { + indicator: "seq-item-ind", + next: value, + offset, + onError, + parentIndent: bs.indent, + startOnNewline: true + }); + if (!props.found) { + if (props.anchor || props.tag || value) { + if (value?.type === "block-seq") + onError(props.end, "BAD_INDENT", "All sequence items must start at the same column"); + else + onError(offset, "MISSING_CHAR", "Sequence item without - indicator"); + } else { + commentEnd = props.end; + if (props.comment) + seq.comment = props.comment; + continue; + } + } + const node = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError); + if (ctx.schema.compat) + utilFlowIndentCheck.flowIndentCheck(bs.indent, value, onError); + offset = node.range[2]; + seq.items.push(node); + } + seq.range = [bs.offset, offset, commentEnd ?? offset]; + return seq; + } + exports2.resolveBlockSeq = resolveBlockSeq; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-end.js +var require_resolve_end = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-end.js"(exports2) { + "use strict"; + function resolveEnd(end, offset, reqSpace, onError) { + let comment = ""; + if (end) { + let hasSpace = false; + let sep = ""; + for (const token of end) { + const { source, type } = token; + switch (type) { + case "space": + hasSpace = true; + break; + case "comment": { + if (reqSpace && !hasSpace) + onError(token, "MISSING_CHAR", "Comments must be separated from other tokens by white space characters"); + const cb = source.substring(1) || " "; + if (!comment) + comment = cb; + else + comment += sep + cb; + sep = ""; + break; + } + case "newline": + if (comment) + sep += source; + hasSpace = true; + break; + default: + onError(token, "UNEXPECTED_TOKEN", `Unexpected ${type} at node end`); + } + offset += source.length; + } + } + return { comment, offset }; + } + exports2.resolveEnd = resolveEnd; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-collection.js +var require_resolve_flow_collection = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-collection.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Pair = require_Pair(); + var YAMLMap = require_YAMLMap(); + var YAMLSeq = require_YAMLSeq(); + var resolveEnd = require_resolve_end(); + var resolveProps = require_resolve_props(); + var utilContainsNewline = require_util_contains_newline(); + var utilMapIncludes = require_util_map_includes(); + var blockMsg = "Block collections are not allowed within flow collections"; + var isBlock = (token) => token && (token.type === "block-map" || token.type === "block-seq"); + function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError, tag) { + const isMap = fc.start.source === "{"; + const fcName = isMap ? "flow map" : "flow sequence"; + const NodeClass = tag?.nodeClass ?? (isMap ? YAMLMap.YAMLMap : YAMLSeq.YAMLSeq); + const coll = new NodeClass(ctx.schema); + coll.flow = true; + const atRoot = ctx.atRoot; + if (atRoot) + ctx.atRoot = false; + if (ctx.atKey) + ctx.atKey = false; + let offset = fc.offset + fc.start.source.length; + for (let i2 = 0; i2 < fc.items.length; ++i2) { + const collItem = fc.items[i2]; + const { start, key, sep, value } = collItem; + const props = resolveProps.resolveProps(start, { + flow: fcName, + indicator: "explicit-key-ind", + next: key ?? sep?.[0], + offset, + onError, + parentIndent: fc.indent, + startOnNewline: false + }); + if (!props.found) { + if (!props.anchor && !props.tag && !sep && !value) { + if (i2 === 0 && props.comma) + onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`); + else if (i2 < fc.items.length - 1) + onError(props.start, "UNEXPECTED_TOKEN", `Unexpected empty item in ${fcName}`); + if (props.comment) { + if (coll.comment) + coll.comment += "\n" + props.comment; + else + coll.comment = props.comment; + } + offset = props.end; + continue; + } + if (!isMap && ctx.options.strict && utilContainsNewline.containsNewline(key)) + onError( + key, + // checked by containsNewline() + "MULTILINE_IMPLICIT_KEY", + "Implicit keys of flow sequence pairs need to be on a single line" + ); + } + if (i2 === 0) { + if (props.comma) + onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`); + } else { + if (!props.comma) + onError(props.start, "MISSING_CHAR", `Missing , between ${fcName} items`); + if (props.comment) { + let prevItemComment = ""; + loop: for (const st of start) { + switch (st.type) { + case "comma": + case "space": + break; + case "comment": + prevItemComment = st.source.substring(1); + break loop; + default: + break loop; + } + } + if (prevItemComment) { + let prev = coll.items[coll.items.length - 1]; + if (identity3.isPair(prev)) + prev = prev.value ?? prev.key; + if (prev.comment) + prev.comment += "\n" + prevItemComment; + else + prev.comment = prevItemComment; + props.comment = props.comment.substring(prevItemComment.length + 1); + } + } + } + if (!isMap && !sep && !props.found) { + const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep, null, props, onError); + coll.items.push(valueNode); + offset = valueNode.range[2]; + if (isBlock(value)) + onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg); + } else { + ctx.atKey = true; + const keyStart = props.end; + const keyNode = key ? composeNode(ctx, key, props, onError) : composeEmptyNode(ctx, keyStart, start, null, props, onError); + if (isBlock(key)) + onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg); + ctx.atKey = false; + const valueProps = resolveProps.resolveProps(sep ?? [], { + flow: fcName, + indicator: "map-value-ind", + next: value, + offset: keyNode.range[2], + onError, + parentIndent: fc.indent, + startOnNewline: false + }); + if (valueProps.found) { + if (!isMap && !props.found && ctx.options.strict) { + if (sep) + for (const st of sep) { + if (st === valueProps.found) + break; + if (st.type === "newline") { + onError(st, "MULTILINE_IMPLICIT_KEY", "Implicit keys of flow sequence pairs need to be on a single line"); + break; + } + } + if (props.start < valueProps.found.offset - 1024) + onError(valueProps.found, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit flow sequence key"); + } + } else if (value) { + if ("source" in value && value.source?.[0] === ":") + onError(value, "MISSING_CHAR", `Missing space after : in ${fcName}`); + else + onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`); + } + const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep, null, valueProps, onError) : null; + if (valueNode) { + if (isBlock(value)) + onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg); + } else if (valueProps.comment) { + if (keyNode.comment) + keyNode.comment += "\n" + valueProps.comment; + else + keyNode.comment = valueProps.comment; + } + const pair = new Pair.Pair(keyNode, valueNode); + if (ctx.options.keepSourceTokens) + pair.srcToken = collItem; + if (isMap) { + const map = coll; + if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode)) + onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique"); + map.items.push(pair); + } else { + const map = new YAMLMap.YAMLMap(ctx.schema); + map.flow = true; + map.items.push(pair); + const endRange = (valueNode ?? keyNode).range; + map.range = [keyNode.range[0], endRange[1], endRange[2]]; + coll.items.push(map); + } + offset = valueNode ? valueNode.range[2] : valueProps.end; + } + } + const expectedEnd = isMap ? "}" : "]"; + const [ce, ...ee] = fc.end; + let cePos = offset; + if (ce?.source === expectedEnd) + cePos = ce.offset + ce.source.length; + else { + const name = fcName[0].toUpperCase() + fcName.substring(1); + const msg = atRoot ? `${name} must end with a ${expectedEnd}` : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`; + onError(offset, atRoot ? "MISSING_CHAR" : "BAD_INDENT", msg); + if (ce && ce.source.length !== 1) + ee.unshift(ce); + } + if (ee.length > 0) { + const end = resolveEnd.resolveEnd(ee, cePos, ctx.options.strict, onError); + if (end.comment) { + if (coll.comment) + coll.comment += "\n" + end.comment; + else + coll.comment = end.comment; + } + coll.range = [fc.offset, cePos, end.offset]; + } else { + coll.range = [fc.offset, cePos, cePos]; + } + return coll; + } + exports2.resolveFlowCollection = resolveFlowCollection; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-collection.js +var require_compose_collection = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-collection.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Scalar = require_Scalar(); + var YAMLMap = require_YAMLMap(); + var YAMLSeq = require_YAMLSeq(); + var resolveBlockMap = require_resolve_block_map(); + var resolveBlockSeq = require_resolve_block_seq(); + var resolveFlowCollection = require_resolve_flow_collection(); + function resolveCollection(CN, ctx, token, onError, tagName, tag) { + const coll = token.type === "block-map" ? resolveBlockMap.resolveBlockMap(CN, ctx, token, onError, tag) : token.type === "block-seq" ? resolveBlockSeq.resolveBlockSeq(CN, ctx, token, onError, tag) : resolveFlowCollection.resolveFlowCollection(CN, ctx, token, onError, tag); + const Coll = coll.constructor; + if (tagName === "!" || tagName === Coll.tagName) { + coll.tag = Coll.tagName; + return coll; + } + if (tagName) + coll.tag = tagName; + return coll; + } + function composeCollection(CN, ctx, token, props, onError) { + const tagToken = props.tag; + const tagName = !tagToken ? null : ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg)); + if (token.type === "block-seq") { + const { anchor, newlineAfterProp: nl } = props; + const lastProp = anchor && tagToken ? anchor.offset > tagToken.offset ? anchor : tagToken : anchor ?? tagToken; + if (lastProp && (!nl || nl.offset < lastProp.offset)) { + const message = "Missing newline after block sequence props"; + onError(lastProp, "MISSING_CHAR", message); + } + } + const expType = token.type === "block-map" ? "map" : token.type === "block-seq" ? "seq" : token.start.source === "{" ? "map" : "seq"; + if (!tagToken || !tagName || tagName === "!" || tagName === YAMLMap.YAMLMap.tagName && expType === "map" || tagName === YAMLSeq.YAMLSeq.tagName && expType === "seq") { + return resolveCollection(CN, ctx, token, onError, tagName); + } + let tag = ctx.schema.tags.find((t) => t.tag === tagName && t.collection === expType); + if (!tag) { + const kt = ctx.schema.knownTags[tagName]; + if (kt?.collection === expType) { + ctx.schema.tags.push(Object.assign({}, kt, { default: false })); + tag = kt; + } else { + if (kt) { + onError(tagToken, "BAD_COLLECTION_TYPE", `${kt.tag} used for ${expType} collection, but expects ${kt.collection ?? "scalar"}`, true); + } else { + onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, true); + } + return resolveCollection(CN, ctx, token, onError, tagName); + } + } + const coll = resolveCollection(CN, ctx, token, onError, tagName, tag); + const res = tag.resolve?.(coll, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg), ctx.options) ?? coll; + const node = identity3.isNode(res) ? res : new Scalar.Scalar(res); + node.range = coll.range; + node.tag = tagName; + if (tag?.format) + node.format = tag.format; + return node; + } + exports2.composeCollection = composeCollection; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-scalar.js +var require_resolve_block_scalar = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-block-scalar.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + function resolveBlockScalar(ctx, scalar, onError) { + const start = scalar.offset; + const header = parseBlockScalarHeader(scalar, ctx.options.strict, onError); + if (!header) + return { value: "", type: null, comment: "", range: [start, start, start] }; + const type = header.mode === ">" ? Scalar.Scalar.BLOCK_FOLDED : Scalar.Scalar.BLOCK_LITERAL; + const lines = scalar.source ? splitLines2(scalar.source) : []; + let chompStart = lines.length; + for (let i2 = lines.length - 1; i2 >= 0; --i2) { + const content = lines[i2][1]; + if (content === "" || content === "\r") + chompStart = i2; + else + break; + } + if (chompStart === 0) { + const value2 = header.chomp === "+" && lines.length > 0 ? "\n".repeat(Math.max(1, lines.length - 1)) : ""; + let end2 = start + header.length; + if (scalar.source) + end2 += scalar.source.length; + return { value: value2, type, comment: header.comment, range: [start, end2, end2] }; + } + let trimIndent = scalar.indent + header.indent; + let offset = scalar.offset + header.length; + let contentStart = 0; + for (let i2 = 0; i2 < chompStart; ++i2) { + const [indent, content] = lines[i2]; + if (content === "" || content === "\r") { + if (header.indent === 0 && indent.length > trimIndent) + trimIndent = indent.length; + } else { + if (indent.length < trimIndent) { + const message = "Block scalars with more-indented leading empty lines must use an explicit indentation indicator"; + onError(offset + indent.length, "MISSING_CHAR", message); + } + if (header.indent === 0) + trimIndent = indent.length; + contentStart = i2; + if (trimIndent === 0 && !ctx.atRoot) { + const message = "Block scalar values in collections must be indented"; + onError(offset, "BAD_INDENT", message); + } + break; + } + offset += indent.length + content.length + 1; + } + for (let i2 = lines.length - 1; i2 >= chompStart; --i2) { + if (lines[i2][0].length > trimIndent) + chompStart = i2 + 1; + } + let value = ""; + let sep = ""; + let prevMoreIndented = false; + for (let i2 = 0; i2 < contentStart; ++i2) + value += lines[i2][0].slice(trimIndent) + "\n"; + for (let i2 = contentStart; i2 < chompStart; ++i2) { + let [indent, content] = lines[i2]; + offset += indent.length + content.length + 1; + const crlf = content[content.length - 1] === "\r"; + if (crlf) + content = content.slice(0, -1); + if (content && indent.length < trimIndent) { + const src = header.indent ? "explicit indentation indicator" : "first line"; + const message = `Block scalar lines must not be less indented than their ${src}`; + onError(offset - content.length - (crlf ? 2 : 1), "BAD_INDENT", message); + indent = ""; + } + if (type === Scalar.Scalar.BLOCK_LITERAL) { + value += sep + indent.slice(trimIndent) + content; + sep = "\n"; + } else if (indent.length > trimIndent || content[0] === " ") { + if (sep === " ") + sep = "\n"; + else if (!prevMoreIndented && sep === "\n") + sep = "\n\n"; + value += sep + indent.slice(trimIndent) + content; + sep = "\n"; + prevMoreIndented = true; + } else if (content === "") { + if (sep === "\n") + value += "\n"; + else + sep = "\n"; + } else { + value += sep + content; + sep = " "; + prevMoreIndented = false; + } + } + switch (header.chomp) { + case "-": + break; + case "+": + for (let i2 = chompStart; i2 < lines.length; ++i2) + value += "\n" + lines[i2][0].slice(trimIndent); + if (value[value.length - 1] !== "\n") + value += "\n"; + break; + default: + value += "\n"; + } + const end = start + header.length + scalar.source.length; + return { value, type, comment: header.comment, range: [start, end, end] }; + } + function parseBlockScalarHeader({ offset, props }, strict, onError) { + if (props[0].type !== "block-scalar-header") { + onError(props[0], "IMPOSSIBLE", "Block scalar header not found"); + return null; + } + const { source } = props[0]; + const mode = source[0]; + let indent = 0; + let chomp = ""; + let error = -1; + for (let i2 = 1; i2 < source.length; ++i2) { + const ch = source[i2]; + if (!chomp && (ch === "-" || ch === "+")) + chomp = ch; + else { + const n2 = Number(ch); + if (!indent && n2) + indent = n2; + else if (error === -1) + error = offset + i2; + } + } + if (error !== -1) + onError(error, "UNEXPECTED_TOKEN", `Block scalar header includes extra characters: ${source}`); + let hasSpace = false; + let comment = ""; + let length = source.length; + for (let i2 = 1; i2 < props.length; ++i2) { + const token = props[i2]; + switch (token.type) { + case "space": + hasSpace = true; + // fallthrough + case "newline": + length += token.source.length; + break; + case "comment": + if (strict && !hasSpace) { + const message = "Comments must be separated from other tokens by white space characters"; + onError(token, "MISSING_CHAR", message); + } + length += token.source.length; + comment = token.source.substring(1); + break; + case "error": + onError(token, "UNEXPECTED_TOKEN", token.message); + length += token.source.length; + break; + /* istanbul ignore next should not happen */ + default: { + const message = `Unexpected token in block scalar header: ${token.type}`; + onError(token, "UNEXPECTED_TOKEN", message); + const ts = token.source; + if (ts && typeof ts === "string") + length += ts.length; + } + } + } + return { mode, indent, chomp, comment, length }; + } + function splitLines2(source) { + const split = source.split(/\n( *)/); + const first = split[0]; + const m = first.match(/^( *)/); + const line0 = m?.[1] ? [m[1], first.slice(m[1].length)] : ["", first]; + const lines = [line0]; + for (let i2 = 1; i2 < split.length; i2 += 2) + lines.push([split[i2], split[i2 + 1]]); + return lines; + } + exports2.resolveBlockScalar = resolveBlockScalar; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-scalar.js +var require_resolve_flow_scalar = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/resolve-flow-scalar.js"(exports2) { + "use strict"; + var Scalar = require_Scalar(); + var resolveEnd = require_resolve_end(); + function resolveFlowScalar(scalar, strict, onError) { + const { offset, type, source, end } = scalar; + let _type; + let value; + const _onError = (rel, code2, msg) => onError(offset + rel, code2, msg); + switch (type) { + case "scalar": + _type = Scalar.Scalar.PLAIN; + value = plainValue(source, _onError); + break; + case "single-quoted-scalar": + _type = Scalar.Scalar.QUOTE_SINGLE; + value = singleQuotedValue(source, _onError); + break; + case "double-quoted-scalar": + _type = Scalar.Scalar.QUOTE_DOUBLE; + value = doubleQuotedValue(source, _onError); + break; + /* istanbul ignore next should not happen */ + default: + onError(scalar, "UNEXPECTED_TOKEN", `Expected a flow scalar value, but found: ${type}`); + return { + value: "", + type: null, + comment: "", + range: [offset, offset + source.length, offset + source.length] + }; + } + const valueEnd = offset + source.length; + const re = resolveEnd.resolveEnd(end, valueEnd, strict, onError); + return { + value, + type: _type, + comment: re.comment, + range: [offset, valueEnd, re.offset] + }; + } + function plainValue(source, onError) { + let badChar = ""; + switch (source[0]) { + /* istanbul ignore next should not happen */ + case " ": + badChar = "a tab character"; + break; + case ",": + badChar = "flow indicator character ,"; + break; + case "%": + badChar = "directive indicator character %"; + break; + case "|": + case ">": { + badChar = `block scalar indicator ${source[0]}`; + break; + } + case "@": + case "`": { + badChar = `reserved character ${source[0]}`; + break; + } + } + if (badChar) + onError(0, "BAD_SCALAR_START", `Plain value cannot start with ${badChar}`); + return foldLines(source); + } + function singleQuotedValue(source, onError) { + if (source[source.length - 1] !== "'" || source.length === 1) + onError(source.length, "MISSING_CHAR", "Missing closing 'quote"); + return foldLines(source.slice(1, -1)).replace(/''/g, "'"); + } + function foldLines(source) { + let first, line; + try { + first = new RegExp("(.*?)(? wsStart ? source.slice(wsStart, i2 + 1) : ch; + } else { + res += ch; + } + } + if (source[source.length - 1] !== '"' || source.length === 1) + onError(source.length, "MISSING_CHAR", 'Missing closing "quote'); + return res; + } + function foldNewline(source, offset) { + let fold = ""; + let ch = source[offset + 1]; + while (ch === " " || ch === " " || ch === "\n" || ch === "\r") { + if (ch === "\r" && source[offset + 2] !== "\n") + break; + if (ch === "\n") + fold += "\n"; + offset += 1; + ch = source[offset + 1]; + } + if (!fold) + fold = " "; + return { fold, offset }; + } + var escapeCodes = { + "0": "\0", + // null character + a: "\x07", + // bell character + b: "\b", + // backspace + e: "\x1B", + // escape character + f: "\f", + // form feed + n: "\n", + // line feed + r: "\r", + // carriage return + t: " ", + // horizontal tab + v: "\v", + // vertical tab + N: "\x85", + // Unicode next line + _: "\xA0", + // Unicode non-breaking space + L: "\u2028", + // Unicode line separator + P: "\u2029", + // Unicode paragraph separator + " ": " ", + '"': '"', + "/": "/", + "\\": "\\", + " ": " " + }; + function parseCharCode(source, offset, length, onError) { + const cc = source.substr(offset, length); + const ok = cc.length === length && /^[0-9a-fA-F]+$/.test(cc); + const code2 = ok ? parseInt(cc, 16) : NaN; + try { + return String.fromCodePoint(code2); + } catch { + const raw = source.substr(offset - 2, length + 2); + onError(offset - 2, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`); + return raw; + } + } + exports2.resolveFlowScalar = resolveFlowScalar; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-scalar.js +var require_compose_scalar = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-scalar.js"(exports2) { + "use strict"; + var identity3 = require_identity(); + var Scalar = require_Scalar(); + var resolveBlockScalar = require_resolve_block_scalar(); + var resolveFlowScalar = require_resolve_flow_scalar(); + function composeScalar(ctx, token, tagToken, onError) { + const { value, type, comment, range } = token.type === "block-scalar" ? resolveBlockScalar.resolveBlockScalar(ctx, token, onError) : resolveFlowScalar.resolveFlowScalar(token, ctx.options.strict, onError); + const tagName = tagToken ? ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg)) : null; + let tag; + if (ctx.options.stringKeys && ctx.atKey) { + tag = ctx.schema[identity3.SCALAR]; + } else if (tagName) + tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError); + else if (token.type === "scalar") + tag = findScalarTagByTest(ctx, value, token, onError); + else + tag = ctx.schema[identity3.SCALAR]; + let scalar; + try { + const res = tag.resolve(value, (msg) => onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg), ctx.options); + scalar = identity3.isScalar(res) ? res : new Scalar.Scalar(res); + } catch (error) { + const msg = error instanceof Error ? error.message : String(error); + onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg); + scalar = new Scalar.Scalar(value); + } + scalar.range = range; + scalar.source = value; + if (type) + scalar.type = type; + if (tagName) + scalar.tag = tagName; + if (tag.format) + scalar.format = tag.format; + if (comment) + scalar.comment = comment; + return scalar; + } + function findScalarTagByName(schema, value, tagName, tagToken, onError) { + if (tagName === "!") + return schema[identity3.SCALAR]; + const matchWithTest = []; + for (const tag of schema.tags) { + if (!tag.collection && tag.tag === tagName) { + if (tag.default && tag.test) + matchWithTest.push(tag); + else + return tag; + } + } + for (const tag of matchWithTest) + if (tag.test?.test(value)) + return tag; + const kt = schema.knownTags[tagName]; + if (kt && !kt.collection) { + schema.tags.push(Object.assign({}, kt, { default: false, test: void 0 })); + return kt; + } + onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, tagName !== "tag:yaml.org,2002:str"); + return schema[identity3.SCALAR]; + } + function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) { + const tag = schema.tags.find((tag2) => (tag2.default === true || atKey && tag2.default === "key") && tag2.test?.test(value)) || schema[identity3.SCALAR]; + if (schema.compat) { + const compat = schema.compat.find((tag2) => tag2.default && tag2.test?.test(value)) ?? schema[identity3.SCALAR]; + if (tag.tag !== compat.tag) { + const ts = directives.tagString(tag.tag); + const cs = directives.tagString(compat.tag); + const msg = `Value may be parsed as either ${ts} or ${cs}`; + onError(token, "TAG_RESOLVE_FAILED", msg, true); + } + } + return tag; + } + exports2.composeScalar = composeScalar; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-empty-scalar-position.js +var require_util_empty_scalar_position = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/util-empty-scalar-position.js"(exports2) { + "use strict"; + function emptyScalarPosition(offset, before, pos) { + if (before) { + pos ?? (pos = before.length); + for (let i2 = pos - 1; i2 >= 0; --i2) { + let st = before[i2]; + switch (st.type) { + case "space": + case "comment": + case "newline": + offset -= st.source.length; + continue; + } + st = before[++i2]; + while (st?.type === "space") { + offset += st.source.length; + st = before[++i2]; + } + break; + } + } + return offset; + } + exports2.emptyScalarPosition = emptyScalarPosition; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-node.js +var require_compose_node = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-node.js"(exports2) { + "use strict"; + var Alias = require_Alias(); + var identity3 = require_identity(); + var composeCollection = require_compose_collection(); + var composeScalar = require_compose_scalar(); + var resolveEnd = require_resolve_end(); + var utilEmptyScalarPosition = require_util_empty_scalar_position(); + var CN = { composeNode, composeEmptyNode }; + function composeNode(ctx, token, props, onError) { + const atKey = ctx.atKey; + const { spaceBefore, comment, anchor, tag } = props; + let node; + let isSrcToken = true; + switch (token.type) { + case "alias": + node = composeAlias(ctx, token, onError); + if (anchor || tag) + onError(token, "ALIAS_PROPS", "An alias node must not specify any properties"); + break; + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": + case "block-scalar": + node = composeScalar.composeScalar(ctx, token, tag, onError); + if (anchor) + node.anchor = anchor.source.substring(1); + break; + case "block-map": + case "block-seq": + case "flow-collection": + try { + node = composeCollection.composeCollection(CN, ctx, token, props, onError); + if (anchor) + node.anchor = anchor.source.substring(1); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + onError(token, "RESOURCE_EXHAUSTION", message); + } + break; + default: { + const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`; + onError(token, "UNEXPECTED_TOKEN", message); + isSrcToken = false; + } + } + node ?? (node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError)); + if (anchor && node.anchor === "") + onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string"); + if (atKey && ctx.options.stringKeys && (!identity3.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) { + const msg = "With stringKeys, all keys must be strings"; + onError(tag ?? token, "NON_STRING_KEY", msg); + } + if (spaceBefore) + node.spaceBefore = true; + if (comment) { + if (token.type === "scalar" && token.source === "") + node.comment = comment; + else + node.commentBefore = comment; + } + if (ctx.options.keepSourceTokens && isSrcToken) + node.srcToken = token; + return node; + } + function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag, end }, onError) { + const token = { + type: "scalar", + offset: utilEmptyScalarPosition.emptyScalarPosition(offset, before, pos), + indent: -1, + source: "" + }; + const node = composeScalar.composeScalar(ctx, token, tag, onError); + if (anchor) { + node.anchor = anchor.source.substring(1); + if (node.anchor === "") + onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string"); + } + if (spaceBefore) + node.spaceBefore = true; + if (comment) { + node.comment = comment; + node.range[2] = end; + } + return node; + } + function composeAlias({ options }, { offset, source, end }, onError) { + const alias = new Alias.Alias(source.substring(1)); + if (alias.source === "") + onError(offset, "BAD_ALIAS", "Alias cannot be an empty string"); + if (alias.source.endsWith(":")) + onError(offset + source.length - 1, "BAD_ALIAS", "Alias ending in : is ambiguous", true); + const valueEnd = offset + source.length; + const re = resolveEnd.resolveEnd(end, valueEnd, options.strict, onError); + alias.range = [offset, valueEnd, re.offset]; + if (re.comment) + alias.comment = re.comment; + return alias; + } + exports2.composeEmptyNode = composeEmptyNode; + exports2.composeNode = composeNode; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-doc.js +var require_compose_doc = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/compose-doc.js"(exports2) { + "use strict"; + var Document = require_Document(); + var composeNode = require_compose_node(); + var resolveEnd = require_resolve_end(); + var resolveProps = require_resolve_props(); + function composeDoc(options, directives, { offset, start, value, end }, onError) { + const opts = Object.assign({ _directives: directives }, options); + const doc = new Document.Document(void 0, opts); + const ctx = { + atKey: false, + atRoot: true, + directives: doc.directives, + options: doc.options, + schema: doc.schema + }; + const props = resolveProps.resolveProps(start, { + indicator: "doc-start", + next: value ?? end?.[0], + offset, + onError, + parentIndent: 0, + startOnNewline: true + }); + if (props.found) { + doc.directives.docStart = true; + if (value && (value.type === "block-map" || value.type === "block-seq") && !props.hasNewline) + onError(props.end, "MISSING_CHAR", "Block collection cannot start on same line with directives-end marker"); + } + doc.contents = value ? composeNode.composeNode(ctx, value, props, onError) : composeNode.composeEmptyNode(ctx, props.end, start, null, props, onError); + const contentEnd = doc.contents.range[2]; + const re = resolveEnd.resolveEnd(end, contentEnd, false, onError); + if (re.comment) + doc.comment = re.comment; + doc.range = [offset, contentEnd, re.offset]; + return doc; + } + exports2.composeDoc = composeDoc; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/composer.js +var require_composer = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/compose/composer.js"(exports2) { + "use strict"; + var node_process = require("process"); + var directives = require_directives(); + var Document = require_Document(); + var errors = require_errors2(); + var identity3 = require_identity(); + var composeDoc = require_compose_doc(); + var resolveEnd = require_resolve_end(); + function getErrorPos(src) { + if (typeof src === "number") + return [src, src + 1]; + if (Array.isArray(src)) + return src.length === 2 ? src : [src[0], src[1]]; + const { offset, source } = src; + return [offset, offset + (typeof source === "string" ? source.length : 1)]; + } + function parsePrelude(prelude) { + let comment = ""; + let atComment = false; + let afterEmptyLine = false; + for (let i2 = 0; i2 < prelude.length; ++i2) { + const source = prelude[i2]; + switch (source[0]) { + case "#": + comment += (comment === "" ? "" : afterEmptyLine ? "\n\n" : "\n") + (source.substring(1) || " "); + atComment = true; + afterEmptyLine = false; + break; + case "%": + if (prelude[i2 + 1]?.[0] !== "#") + i2 += 1; + atComment = false; + break; + default: + if (!atComment) + afterEmptyLine = true; + atComment = false; + } + } + return { comment, afterEmptyLine }; + } + var Composer = class { + constructor(options = {}) { + this.doc = null; + this.atDirectives = false; + this.prelude = []; + this.errors = []; + this.warnings = []; + this.onError = (source, code2, message, warning) => { + const pos = getErrorPos(source); + if (warning) + this.warnings.push(new errors.YAMLWarning(pos, code2, message)); + else + this.errors.push(new errors.YAMLParseError(pos, code2, message)); + }; + this.directives = new directives.Directives({ version: options.version || "1.2" }); + this.options = options; + } + decorate(doc, afterDoc) { + const { comment, afterEmptyLine } = parsePrelude(this.prelude); + if (comment) { + const dc = doc.contents; + if (afterDoc) { + doc.comment = doc.comment ? `${doc.comment} +${comment}` : comment; + } else if (afterEmptyLine || doc.directives.docStart || !dc) { + doc.commentBefore = comment; + } else if (identity3.isCollection(dc) && !dc.flow && dc.items.length > 0) { + let it = dc.items[0]; + if (identity3.isPair(it)) + it = it.key; + const cb = it.commentBefore; + it.commentBefore = cb ? `${comment} +${cb}` : comment; + } else { + const cb = dc.commentBefore; + dc.commentBefore = cb ? `${comment} +${cb}` : comment; + } + } + if (afterDoc) { + for (let i2 = 0; i2 < this.errors.length; ++i2) + doc.errors.push(this.errors[i2]); + for (let i2 = 0; i2 < this.warnings.length; ++i2) + doc.warnings.push(this.warnings[i2]); + } else { + doc.errors = this.errors; + doc.warnings = this.warnings; + } + this.prelude = []; + this.errors = []; + this.warnings = []; + } + /** + * Current stream status information. + * + * Mostly useful at the end of input for an empty stream. + */ + streamInfo() { + return { + comment: parsePrelude(this.prelude).comment, + directives: this.directives, + errors: this.errors, + warnings: this.warnings + }; + } + /** + * Compose tokens into documents. + * + * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document. + * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly. + */ + *compose(tokens, forceDoc = false, endOffset = -1) { + for (const token of tokens) + yield* this.next(token); + yield* this.end(forceDoc, endOffset); + } + /** Advance the composer by one CST token. */ + *next(token) { + if (node_process.env.LOG_STREAM) + console.dir(token, { depth: null }); + switch (token.type) { + case "directive": + this.directives.add(token.source, (offset, message, warning) => { + const pos = getErrorPos(token); + pos[0] += offset; + this.onError(pos, "BAD_DIRECTIVE", message, warning); + }); + this.prelude.push(token.source); + this.atDirectives = true; + break; + case "document": { + const doc = composeDoc.composeDoc(this.options, this.directives, token, this.onError); + if (this.atDirectives && !doc.directives.docStart) + this.onError(token, "MISSING_CHAR", "Missing directives-end/doc-start indicator line"); + this.decorate(doc, false); + if (this.doc) + yield this.doc; + this.doc = doc; + this.atDirectives = false; + break; + } + case "byte-order-mark": + case "space": + break; + case "comment": + case "newline": + this.prelude.push(token.source); + break; + case "error": { + const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message; + const error = new errors.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg); + if (this.atDirectives || !this.doc) + this.errors.push(error); + else + this.doc.errors.push(error); + break; + } + case "doc-end": { + if (!this.doc) { + const msg = "Unexpected doc-end without preceding document"; + this.errors.push(new errors.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg)); + break; + } + this.doc.directives.docEnd = true; + const end = resolveEnd.resolveEnd(token.end, token.offset + token.source.length, this.doc.options.strict, this.onError); + this.decorate(this.doc, true); + if (end.comment) { + const dc = this.doc.comment; + this.doc.comment = dc ? `${dc} +${end.comment}` : end.comment; + } + this.doc.range[2] = end.offset; + break; + } + default: + this.errors.push(new errors.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`)); + } + } + /** + * Call at end of input to yield any remaining document. + * + * @param forceDoc - If the stream contains no document, still emit a final document including any comments and directives that would be applied to a subsequent document. + * @param endOffset - Should be set if `forceDoc` is also set, to set the document range end and to indicate errors correctly. + */ + *end(forceDoc = false, endOffset = -1) { + if (this.doc) { + this.decorate(this.doc, true); + yield this.doc; + this.doc = null; + } else if (forceDoc) { + const opts = Object.assign({ _directives: this.directives }, this.options); + const doc = new Document.Document(void 0, opts); + if (this.atDirectives) + this.onError(endOffset, "MISSING_CHAR", "Missing directives-end indicator line"); + doc.range = [0, endOffset, endOffset]; + this.decorate(doc, false); + yield doc; + } + } + }; + exports2.Composer = Composer; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-scalar.js +var require_cst_scalar = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-scalar.js"(exports2) { + "use strict"; + var resolveBlockScalar = require_resolve_block_scalar(); + var resolveFlowScalar = require_resolve_flow_scalar(); + var errors = require_errors2(); + var stringifyString = require_stringifyString(); + function resolveAsScalar(token, strict = true, onError) { + if (token) { + const _onError = (pos, code2, message) => { + const offset = typeof pos === "number" ? pos : Array.isArray(pos) ? pos[0] : pos.offset; + if (onError) + onError(offset, code2, message); + else + throw new errors.YAMLParseError([offset, offset + 1], code2, message); + }; + switch (token.type) { + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": + return resolveFlowScalar.resolveFlowScalar(token, strict, _onError); + case "block-scalar": + return resolveBlockScalar.resolveBlockScalar({ options: { strict } }, token, _onError); + } + } + return null; + } + function createScalarToken(value, context) { + const { implicitKey = false, indent, inFlow = false, offset = -1, type = "PLAIN" } = context; + const source = stringifyString.stringifyString({ type, value }, { + implicitKey, + indent: indent > 0 ? " ".repeat(indent) : "", + inFlow, + options: { blockQuote: true, lineWidth: -1 } + }); + const end = context.end ?? [ + { type: "newline", offset: -1, indent, source: "\n" } + ]; + switch (source[0]) { + case "|": + case ">": { + const he = source.indexOf("\n"); + const head = source.substring(0, he); + const body = source.substring(he + 1) + "\n"; + const props = [ + { type: "block-scalar-header", offset, indent, source: head } + ]; + if (!addEndtoBlockProps(props, end)) + props.push({ type: "newline", offset: -1, indent, source: "\n" }); + return { type: "block-scalar", offset, indent, props, source: body }; + } + case '"': + return { type: "double-quoted-scalar", offset, indent, source, end }; + case "'": + return { type: "single-quoted-scalar", offset, indent, source, end }; + default: + return { type: "scalar", offset, indent, source, end }; + } + } + function setScalarValue(token, value, context = {}) { + let { afterKey = false, implicitKey = false, inFlow = false, type } = context; + let indent = "indent" in token ? token.indent : null; + if (afterKey && typeof indent === "number") + indent += 2; + if (!type) + switch (token.type) { + case "single-quoted-scalar": + type = "QUOTE_SINGLE"; + break; + case "double-quoted-scalar": + type = "QUOTE_DOUBLE"; + break; + case "block-scalar": { + const header = token.props[0]; + if (header.type !== "block-scalar-header") + throw new Error("Invalid block scalar header"); + type = header.source[0] === ">" ? "BLOCK_FOLDED" : "BLOCK_LITERAL"; + break; + } + default: + type = "PLAIN"; + } + const source = stringifyString.stringifyString({ type, value }, { + implicitKey: implicitKey || indent === null, + indent: indent !== null && indent > 0 ? " ".repeat(indent) : "", + inFlow, + options: { blockQuote: true, lineWidth: -1 } + }); + switch (source[0]) { + case "|": + case ">": + setBlockScalarValue(token, source); + break; + case '"': + setFlowScalarValue(token, source, "double-quoted-scalar"); + break; + case "'": + setFlowScalarValue(token, source, "single-quoted-scalar"); + break; + default: + setFlowScalarValue(token, source, "scalar"); + } + } + function setBlockScalarValue(token, source) { + const he = source.indexOf("\n"); + const head = source.substring(0, he); + const body = source.substring(he + 1) + "\n"; + if (token.type === "block-scalar") { + const header = token.props[0]; + if (header.type !== "block-scalar-header") + throw new Error("Invalid block scalar header"); + header.source = head; + token.source = body; + } else { + const { offset } = token; + const indent = "indent" in token ? token.indent : -1; + const props = [ + { type: "block-scalar-header", offset, indent, source: head } + ]; + if (!addEndtoBlockProps(props, "end" in token ? token.end : void 0)) + props.push({ type: "newline", offset: -1, indent, source: "\n" }); + for (const key of Object.keys(token)) + if (key !== "type" && key !== "offset") + delete token[key]; + Object.assign(token, { type: "block-scalar", indent, props, source: body }); + } + } + function addEndtoBlockProps(props, end) { + if (end) + for (const st of end) + switch (st.type) { + case "space": + case "comment": + props.push(st); + break; + case "newline": + props.push(st); + return true; + } + return false; + } + function setFlowScalarValue(token, source, type) { + switch (token.type) { + case "scalar": + case "double-quoted-scalar": + case "single-quoted-scalar": + token.type = type; + token.source = source; + break; + case "block-scalar": { + const end = token.props.slice(1); + let oa = source.length; + if (token.props[0].type === "block-scalar-header") + oa -= token.props[0].source.length; + for (const tok of end) + tok.offset += oa; + delete token.props; + Object.assign(token, { type, source, end }); + break; + } + case "block-map": + case "block-seq": { + const offset = token.offset + source.length; + const nl = { type: "newline", offset, indent: token.indent, source: "\n" }; + delete token.items; + Object.assign(token, { type, source, end: [nl] }); + break; + } + default: { + const indent = "indent" in token ? token.indent : -1; + const end = "end" in token && Array.isArray(token.end) ? token.end.filter((st) => st.type === "space" || st.type === "comment" || st.type === "newline") : []; + for (const key of Object.keys(token)) + if (key !== "type" && key !== "offset") + delete token[key]; + Object.assign(token, { type, indent, source, end }); + } + } + } + exports2.createScalarToken = createScalarToken; + exports2.resolveAsScalar = resolveAsScalar; + exports2.setScalarValue = setScalarValue; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-stringify.js +var require_cst_stringify = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-stringify.js"(exports2) { + "use strict"; + var stringify = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst); + function stringifyToken(token) { + switch (token.type) { + case "block-scalar": { + let res = ""; + for (const tok of token.props) + res += stringifyToken(tok); + return res + token.source; + } + case "block-map": + case "block-seq": { + let res = ""; + for (const item of token.items) + res += stringifyItem(item); + return res; + } + case "flow-collection": { + let res = token.start.source; + for (const item of token.items) + res += stringifyItem(item); + for (const st of token.end) + res += st.source; + return res; + } + case "document": { + let res = stringifyItem(token); + if (token.end) + for (const st of token.end) + res += st.source; + return res; + } + default: { + let res = token.source; + if ("end" in token && token.end) + for (const st of token.end) + res += st.source; + return res; + } + } + } + function stringifyItem({ start, key, sep, value }) { + let res = ""; + for (const st of start) + res += st.source; + if (key) + res += stringifyToken(key); + if (sep) + for (const st of sep) + res += st.source; + if (value) + res += stringifyToken(value); + return res; + } + exports2.stringify = stringify; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-visit.js +var require_cst_visit = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-visit.js"(exports2) { + "use strict"; + var BREAK = /* @__PURE__ */ Symbol("break visit"); + var SKIP = /* @__PURE__ */ Symbol("skip children"); + var REMOVE = /* @__PURE__ */ Symbol("remove item"); + function visit(cst, visitor) { + if ("type" in cst && cst.type === "document") + cst = { start: cst.start, value: cst.value }; + _visit(Object.freeze([]), cst, visitor); + } + visit.BREAK = BREAK; + visit.SKIP = SKIP; + visit.REMOVE = REMOVE; + visit.itemAtPath = (cst, path12) => { + let item = cst; + for (const [field, index] of path12) { + const tok = item?.[field]; + if (tok && "items" in tok) { + item = tok.items[index]; + } else + return void 0; + } + return item; + }; + visit.parentCollection = (cst, path12) => { + const parent = visit.itemAtPath(cst, path12.slice(0, -1)); + const field = path12[path12.length - 1][0]; + const coll = parent?.[field]; + if (coll && "items" in coll) + return coll; + throw new Error("Parent collection not found"); + }; + function _visit(path12, item, visitor) { + let ctrl = visitor(item, path12); + if (typeof ctrl === "symbol") + return ctrl; + for (const field of ["key", "value"]) { + const token = item[field]; + if (token && "items" in token) { + for (let i2 = 0; i2 < token.items.length; ++i2) { + const ci = _visit(Object.freeze(path12.concat([[field, i2]])), token.items[i2], visitor); + if (typeof ci === "number") + i2 = ci - 1; + else if (ci === BREAK) + return BREAK; + else if (ci === REMOVE) { + token.items.splice(i2, 1); + i2 -= 1; + } + } + if (typeof ctrl === "function" && field === "key") + ctrl = ctrl(item, path12); + } + } + return typeof ctrl === "function" ? ctrl(item, path12) : ctrl; + } + exports2.visit = visit; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst.js +var require_cst = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst.js"(exports2) { + "use strict"; + var cstScalar = require_cst_scalar(); + var cstStringify = require_cst_stringify(); + var cstVisit = require_cst_visit(); + var BOM2 = "\uFEFF"; + var DOCUMENT = ""; + var FLOW_END = ""; + var SCALAR = ""; + var isCollection = (token) => !!token && "items" in token; + var isScalar = (token) => !!token && (token.type === "scalar" || token.type === "single-quoted-scalar" || token.type === "double-quoted-scalar" || token.type === "block-scalar"); + function prettyToken(token) { + switch (token) { + case BOM2: + return ""; + case DOCUMENT: + return ""; + case FLOW_END: + return ""; + case SCALAR: + return ""; + default: + return JSON.stringify(token); + } + } + function tokenType(source) { + switch (source) { + case BOM2: + return "byte-order-mark"; + case DOCUMENT: + return "doc-mode"; + case FLOW_END: + return "flow-error-end"; + case SCALAR: + return "scalar"; + case "---": + return "doc-start"; + case "...": + return "doc-end"; + case "": + case "\n": + case "\r\n": + return "newline"; + case "-": + return "seq-item-ind"; + case "?": + return "explicit-key-ind"; + case ":": + return "map-value-ind"; + case "{": + return "flow-map-start"; + case "}": + return "flow-map-end"; + case "[": + return "flow-seq-start"; + case "]": + return "flow-seq-end"; + case ",": + return "comma"; + } + switch (source[0]) { + case " ": + case " ": + return "space"; + case "#": + return "comment"; + case "%": + return "directive-line"; + case "*": + return "alias"; + case "&": + return "anchor"; + case "!": + return "tag"; + case "'": + return "single-quoted-scalar"; + case '"': + return "double-quoted-scalar"; + case "|": + case ">": + return "block-scalar-header"; + } + return null; + } + exports2.createScalarToken = cstScalar.createScalarToken; + exports2.resolveAsScalar = cstScalar.resolveAsScalar; + exports2.setScalarValue = cstScalar.setScalarValue; + exports2.stringify = cstStringify.stringify; + exports2.visit = cstVisit.visit; + exports2.BOM = BOM2; + exports2.DOCUMENT = DOCUMENT; + exports2.FLOW_END = FLOW_END; + exports2.SCALAR = SCALAR; + exports2.isCollection = isCollection; + exports2.isScalar = isScalar; + exports2.prettyToken = prettyToken; + exports2.tokenType = tokenType; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/lexer.js +var require_lexer = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/lexer.js"(exports2) { + "use strict"; + var cst = require_cst(); + function isEmpty(ch) { + switch (ch) { + case void 0: + case " ": + case "\n": + case "\r": + case " ": + return true; + default: + return false; + } + } + var hexDigits = new Set("0123456789ABCDEFabcdef"); + var tagChars = new Set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()"); + var flowIndicatorChars = new Set(",[]{}"); + var invalidAnchorChars = new Set(" ,[]{}\n\r "); + var isNotAnchorChar = (ch) => !ch || invalidAnchorChars.has(ch); + var Lexer = class { + constructor() { + this.atEnd = false; + this.blockScalarIndent = -1; + this.blockScalarKeep = false; + this.buffer = ""; + this.flowKey = false; + this.flowLevel = 0; + this.indentNext = 0; + this.indentValue = 0; + this.lineEndPos = null; + this.next = null; + this.pos = 0; + } + /** + * Generate YAML tokens from the `source` string. If `incomplete`, + * a part of the last line may be left as a buffer for the next call. + * + * @returns A generator of lexical tokens + */ + *lex(source, incomplete = false) { + if (source) { + if (typeof source !== "string") + throw TypeError("source is not a string"); + this.buffer = this.buffer ? this.buffer + source : source; + this.lineEndPos = null; + } + this.atEnd = !incomplete; + let next = this.next ?? "stream"; + while (next && (incomplete || this.hasChars(1))) + next = yield* this.parseNext(next); + } + atLineEnd() { + let i2 = this.pos; + let ch = this.buffer[i2]; + while (ch === " " || ch === " ") + ch = this.buffer[++i2]; + if (!ch || ch === "#" || ch === "\n") + return true; + if (ch === "\r") + return this.buffer[i2 + 1] === "\n"; + return false; + } + charAt(n2) { + return this.buffer[this.pos + n2]; + } + continueScalar(offset) { + let ch = this.buffer[offset]; + if (this.indentNext > 0) { + let indent = 0; + while (ch === " ") + ch = this.buffer[++indent + offset]; + if (ch === "\r") { + const next = this.buffer[indent + offset + 1]; + if (next === "\n" || !next && !this.atEnd) + return offset + indent + 1; + } + return ch === "\n" || indent >= this.indentNext || !ch && !this.atEnd ? offset + indent : -1; + } + if (ch === "-" || ch === ".") { + const dt = this.buffer.substr(offset, 3); + if ((dt === "---" || dt === "...") && isEmpty(this.buffer[offset + 3])) + return -1; + } + return offset; + } + getLine() { + let end = this.lineEndPos; + if (typeof end !== "number" || end !== -1 && end < this.pos) { + end = this.buffer.indexOf("\n", this.pos); + this.lineEndPos = end; + } + if (end === -1) + return this.atEnd ? this.buffer.substring(this.pos) : null; + if (this.buffer[end - 1] === "\r") + end -= 1; + return this.buffer.substring(this.pos, end); + } + hasChars(n2) { + return this.pos + n2 <= this.buffer.length; + } + setNext(state) { + this.buffer = this.buffer.substring(this.pos); + this.pos = 0; + this.lineEndPos = null; + this.next = state; + return null; + } + peek(n2) { + return this.buffer.substr(this.pos, n2); + } + *parseNext(next) { + switch (next) { + case "stream": + return yield* this.parseStream(); + case "line-start": + return yield* this.parseLineStart(); + case "block-start": + return yield* this.parseBlockStart(); + case "doc": + return yield* this.parseDocument(); + case "flow": + return yield* this.parseFlowCollection(); + case "quoted-scalar": + return yield* this.parseQuotedScalar(); + case "block-scalar": + return yield* this.parseBlockScalar(); + case "plain-scalar": + return yield* this.parsePlainScalar(); + } + } + *parseStream() { + let line = this.getLine(); + if (line === null) + return this.setNext("stream"); + if (line[0] === cst.BOM) { + yield* this.pushCount(1); + line = line.substring(1); + } + if (line[0] === "%") { + let dirEnd = line.length; + let cs = line.indexOf("#"); + while (cs !== -1) { + const ch = line[cs - 1]; + if (ch === " " || ch === " ") { + dirEnd = cs - 1; + break; + } else { + cs = line.indexOf("#", cs + 1); + } + } + while (true) { + const ch = line[dirEnd - 1]; + if (ch === " " || ch === " ") + dirEnd -= 1; + else + break; + } + const n2 = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true)); + yield* this.pushCount(line.length - n2); + this.pushNewline(); + return "stream"; + } + if (this.atLineEnd()) { + const sp = yield* this.pushSpaces(true); + yield* this.pushCount(line.length - sp); + yield* this.pushNewline(); + return "stream"; + } + yield cst.DOCUMENT; + return yield* this.parseLineStart(); + } + *parseLineStart() { + const ch = this.charAt(0); + if (!ch && !this.atEnd) + return this.setNext("line-start"); + if (ch === "-" || ch === ".") { + if (!this.atEnd && !this.hasChars(4)) + return this.setNext("line-start"); + const s = this.peek(3); + if ((s === "---" || s === "...") && isEmpty(this.charAt(3))) { + yield* this.pushCount(3); + this.indentValue = 0; + this.indentNext = 0; + return s === "---" ? "doc" : "stream"; + } + } + this.indentValue = yield* this.pushSpaces(false); + if (this.indentNext > this.indentValue && !isEmpty(this.charAt(1))) + this.indentNext = this.indentValue; + return yield* this.parseBlockStart(); + } + *parseBlockStart() { + const [ch0, ch1] = this.peek(2); + if (!ch1 && !this.atEnd) + return this.setNext("block-start"); + if ((ch0 === "-" || ch0 === "?" || ch0 === ":") && isEmpty(ch1)) { + const n2 = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true)); + this.indentNext = this.indentValue + 1; + this.indentValue += n2; + return "block-start"; + } + return "doc"; + } + *parseDocument() { + yield* this.pushSpaces(true); + const line = this.getLine(); + if (line === null) + return this.setNext("doc"); + let n2 = yield* this.pushIndicators(); + switch (line[n2]) { + case "#": + yield* this.pushCount(line.length - n2); + // fallthrough + case void 0: + yield* this.pushNewline(); + return yield* this.parseLineStart(); + case "{": + case "[": + yield* this.pushCount(1); + this.flowKey = false; + this.flowLevel = 1; + return "flow"; + case "}": + case "]": + yield* this.pushCount(1); + return "doc"; + case "*": + yield* this.pushUntil(isNotAnchorChar); + return "doc"; + case '"': + case "'": + return yield* this.parseQuotedScalar(); + case "|": + case ">": + n2 += yield* this.parseBlockScalarHeader(); + n2 += yield* this.pushSpaces(true); + yield* this.pushCount(line.length - n2); + yield* this.pushNewline(); + return yield* this.parseBlockScalar(); + default: + return yield* this.parsePlainScalar(); + } + } + *parseFlowCollection() { + let nl, sp; + let indent = -1; + do { + nl = yield* this.pushNewline(); + if (nl > 0) { + sp = yield* this.pushSpaces(false); + this.indentValue = indent = sp; + } else { + sp = 0; + } + sp += yield* this.pushSpaces(true); + } while (nl + sp > 0); + const line = this.getLine(); + if (line === null) + return this.setNext("flow"); + if (indent !== -1 && indent < this.indentNext && line[0] !== "#" || indent === 0 && (line.startsWith("---") || line.startsWith("...")) && isEmpty(line[3])) { + const atFlowEndMarker = indent === this.indentNext - 1 && this.flowLevel === 1 && (line[0] === "]" || line[0] === "}"); + if (!atFlowEndMarker) { + this.flowLevel = 0; + yield cst.FLOW_END; + return yield* this.parseLineStart(); + } + } + let n2 = 0; + while (line[n2] === ",") { + n2 += yield* this.pushCount(1); + n2 += yield* this.pushSpaces(true); + this.flowKey = false; + } + n2 += yield* this.pushIndicators(); + switch (line[n2]) { + case void 0: + return "flow"; + case "#": + yield* this.pushCount(line.length - n2); + return "flow"; + case "{": + case "[": + yield* this.pushCount(1); + this.flowKey = false; + this.flowLevel += 1; + return "flow"; + case "}": + case "]": + yield* this.pushCount(1); + this.flowKey = true; + this.flowLevel -= 1; + return this.flowLevel ? "flow" : "doc"; + case "*": + yield* this.pushUntil(isNotAnchorChar); + return "flow"; + case '"': + case "'": + this.flowKey = true; + return yield* this.parseQuotedScalar(); + case ":": { + const next = this.charAt(1); + if (this.flowKey || isEmpty(next) || next === ",") { + this.flowKey = false; + yield* this.pushCount(1); + yield* this.pushSpaces(true); + return "flow"; + } + } + // fallthrough + default: + this.flowKey = false; + return yield* this.parsePlainScalar(); + } + } + *parseQuotedScalar() { + const quote = this.charAt(0); + let end = this.buffer.indexOf(quote, this.pos + 1); + if (quote === "'") { + while (end !== -1 && this.buffer[end + 1] === "'") + end = this.buffer.indexOf("'", end + 2); + } else { + while (end !== -1) { + let n2 = 0; + while (this.buffer[end - 1 - n2] === "\\") + n2 += 1; + if (n2 % 2 === 0) + break; + end = this.buffer.indexOf('"', end + 1); + } + } + const qb = this.buffer.substring(0, end); + let nl = qb.indexOf("\n", this.pos); + if (nl !== -1) { + while (nl !== -1) { + const cs = this.continueScalar(nl + 1); + if (cs === -1) + break; + nl = qb.indexOf("\n", cs); + } + if (nl !== -1) { + end = nl - (qb[nl - 1] === "\r" ? 2 : 1); + } + } + if (end === -1) { + if (!this.atEnd) + return this.setNext("quoted-scalar"); + end = this.buffer.length; + } + yield* this.pushToIndex(end + 1, false); + return this.flowLevel ? "flow" : "doc"; + } + *parseBlockScalarHeader() { + this.blockScalarIndent = -1; + this.blockScalarKeep = false; + let i2 = this.pos; + while (true) { + const ch = this.buffer[++i2]; + if (ch === "+") + this.blockScalarKeep = true; + else if (ch > "0" && ch <= "9") + this.blockScalarIndent = Number(ch) - 1; + else if (ch !== "-") + break; + } + return yield* this.pushUntil((ch) => isEmpty(ch) || ch === "#"); + } + *parseBlockScalar() { + let nl = this.pos - 1; + let indent = 0; + let ch; + loop: for (let i3 = this.pos; ch = this.buffer[i3]; ++i3) { + switch (ch) { + case " ": + indent += 1; + break; + case "\n": + nl = i3; + indent = 0; + break; + case "\r": { + const next = this.buffer[i3 + 1]; + if (!next && !this.atEnd) + return this.setNext("block-scalar"); + if (next === "\n") + break; + } + // fallthrough + default: + break loop; + } + } + if (!ch && !this.atEnd) + return this.setNext("block-scalar"); + if (indent >= this.indentNext) { + if (this.blockScalarIndent === -1) + this.indentNext = indent; + else { + this.indentNext = this.blockScalarIndent + (this.indentNext === 0 ? 1 : this.indentNext); + } + do { + const cs = this.continueScalar(nl + 1); + if (cs === -1) + break; + nl = this.buffer.indexOf("\n", cs); + } while (nl !== -1); + if (nl === -1) { + if (!this.atEnd) + return this.setNext("block-scalar"); + nl = this.buffer.length; + } + } + let i2 = nl + 1; + ch = this.buffer[i2]; + while (ch === " ") + ch = this.buffer[++i2]; + if (ch === " ") { + while (ch === " " || ch === " " || ch === "\r" || ch === "\n") + ch = this.buffer[++i2]; + nl = i2 - 1; + } else if (!this.blockScalarKeep) { + do { + let i3 = nl - 1; + let ch2 = this.buffer[i3]; + if (ch2 === "\r") + ch2 = this.buffer[--i3]; + const lastChar = i3; + while (ch2 === " ") + ch2 = this.buffer[--i3]; + if (ch2 === "\n" && i3 >= this.pos && i3 + 1 + indent > lastChar) + nl = i3; + else + break; + } while (true); + } + yield cst.SCALAR; + yield* this.pushToIndex(nl + 1, true); + return yield* this.parseLineStart(); + } + *parsePlainScalar() { + const inFlow = this.flowLevel > 0; + let end = this.pos - 1; + let i2 = this.pos - 1; + let ch; + while (ch = this.buffer[++i2]) { + if (ch === ":") { + const next = this.buffer[i2 + 1]; + if (isEmpty(next) || inFlow && flowIndicatorChars.has(next)) + break; + end = i2; + } else if (isEmpty(ch)) { + let next = this.buffer[i2 + 1]; + if (ch === "\r") { + if (next === "\n") { + i2 += 1; + ch = "\n"; + next = this.buffer[i2 + 1]; + } else + end = i2; + } + if (next === "#" || inFlow && flowIndicatorChars.has(next)) + break; + if (ch === "\n") { + const cs = this.continueScalar(i2 + 1); + if (cs === -1) + break; + i2 = Math.max(i2, cs - 2); + } + } else { + if (inFlow && flowIndicatorChars.has(ch)) + break; + end = i2; + } + } + if (!ch && !this.atEnd) + return this.setNext("plain-scalar"); + yield cst.SCALAR; + yield* this.pushToIndex(end + 1, true); + return inFlow ? "flow" : "doc"; + } + *pushCount(n2) { + if (n2 > 0) { + yield this.buffer.substr(this.pos, n2); + this.pos += n2; + return n2; + } + return 0; + } + *pushToIndex(i2, allowEmpty) { + const s = this.buffer.slice(this.pos, i2); + if (s) { + yield s; + this.pos += s.length; + return s.length; + } else if (allowEmpty) + yield ""; + return 0; + } + *pushIndicators() { + let n2 = 0; + loop: while (true) { + switch (this.charAt(0)) { + case "!": + n2 += yield* this.pushTag(); + n2 += yield* this.pushSpaces(true); + continue loop; + case "&": + n2 += yield* this.pushUntil(isNotAnchorChar); + n2 += yield* this.pushSpaces(true); + continue loop; + case "-": + // this is an error + case "?": + // this is an error outside flow collections + case ":": { + const inFlow = this.flowLevel > 0; + const ch1 = this.charAt(1); + if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) { + if (!inFlow) + this.indentNext = this.indentValue + 1; + else if (this.flowKey) + this.flowKey = false; + n2 += yield* this.pushCount(1); + n2 += yield* this.pushSpaces(true); + continue loop; + } + } + } + break loop; + } + return n2; + } + *pushTag() { + if (this.charAt(1) === "<") { + let i2 = this.pos + 2; + let ch = this.buffer[i2]; + while (!isEmpty(ch) && ch !== ">") + ch = this.buffer[++i2]; + return yield* this.pushToIndex(ch === ">" ? i2 + 1 : i2, false); + } else { + let i2 = this.pos + 1; + let ch = this.buffer[i2]; + while (ch) { + if (tagChars.has(ch)) + ch = this.buffer[++i2]; + else if (ch === "%" && hexDigits.has(this.buffer[i2 + 1]) && hexDigits.has(this.buffer[i2 + 2])) { + ch = this.buffer[i2 += 3]; + } else + break; + } + return yield* this.pushToIndex(i2, false); + } + } + *pushNewline() { + const ch = this.buffer[this.pos]; + if (ch === "\n") + return yield* this.pushCount(1); + else if (ch === "\r" && this.charAt(1) === "\n") + return yield* this.pushCount(2); + else + return 0; + } + *pushSpaces(allowTabs) { + let i2 = this.pos - 1; + let ch; + do { + ch = this.buffer[++i2]; + } while (ch === " " || allowTabs && ch === " "); + const n2 = i2 - this.pos; + if (n2 > 0) { + yield this.buffer.substr(this.pos, n2); + this.pos = i2; + } + return n2; + } + *pushUntil(test) { + let i2 = this.pos; + let ch = this.buffer[i2]; + while (!test(ch)) + ch = this.buffer[++i2]; + return yield* this.pushToIndex(i2, false); + } + }; + exports2.Lexer = Lexer; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/line-counter.js +var require_line_counter = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/line-counter.js"(exports2) { + "use strict"; + var LineCounter = class { + constructor() { + this.lineStarts = []; + this.addNewLine = (offset) => this.lineStarts.push(offset); + this.linePos = (offset) => { + let low = 0; + let high = this.lineStarts.length; + while (low < high) { + const mid = low + high >> 1; + if (this.lineStarts[mid] < offset) + low = mid + 1; + else + high = mid; + } + if (this.lineStarts[low] === offset) + return { line: low + 1, col: 1 }; + if (low === 0) + return { line: 0, col: offset }; + const start = this.lineStarts[low - 1]; + return { line: low, col: offset - start + 1 }; + }; + } + }; + exports2.LineCounter = LineCounter; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/parser.js +var require_parser = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/parser.js"(exports2) { + "use strict"; + var node_process = require("process"); + var cst = require_cst(); + var lexer = require_lexer(); + function includesToken(list, type) { + for (let i2 = 0; i2 < list.length; ++i2) + if (list[i2].type === type) + return true; + return false; + } + function findNonEmptyIndex(list) { + for (let i2 = 0; i2 < list.length; ++i2) { + switch (list[i2].type) { + case "space": + case "comment": + case "newline": + break; + default: + return i2; + } + } + return -1; + } + function isFlowToken(token) { + switch (token?.type) { + case "alias": + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": + case "flow-collection": + return true; + default: + return false; + } + } + function getPrevProps(parent) { + switch (parent.type) { + case "document": + return parent.start; + case "block-map": { + const it = parent.items[parent.items.length - 1]; + return it.sep ?? it.start; + } + case "block-seq": + return parent.items[parent.items.length - 1].start; + /* istanbul ignore next should not happen */ + default: + return []; + } + } + function getFirstKeyStartProps(prev) { + if (prev.length === 0) + return []; + let i2 = prev.length; + loop: while (--i2 >= 0) { + switch (prev[i2].type) { + case "doc-start": + case "explicit-key-ind": + case "map-value-ind": + case "seq-item-ind": + case "newline": + break loop; + } + } + while (prev[++i2]?.type === "space") { + } + return prev.splice(i2, prev.length); + } + function arrayPushArray(target, source) { + if (source.length < 1e5) + Array.prototype.push.apply(target, source); + else + for (let i2 = 0; i2 < source.length; ++i2) + target.push(source[i2]); + } + function fixFlowSeqItems(fc) { + if (fc.start.type === "flow-seq-start") { + for (const it of fc.items) { + if (it.sep && !it.value && !includesToken(it.start, "explicit-key-ind") && !includesToken(it.sep, "map-value-ind")) { + if (it.key) + it.value = it.key; + delete it.key; + if (isFlowToken(it.value)) { + if (it.value.end) + arrayPushArray(it.value.end, it.sep); + else + it.value.end = it.sep; + } else + arrayPushArray(it.start, it.sep); + delete it.sep; + } + } + } + } + var Parser = class { + /** + * @param onNewLine - If defined, called separately with the start position of + * each new line (in `parse()`, including the start of input). + */ + constructor(onNewLine) { + this.atNewLine = true; + this.atScalar = false; + this.indent = 0; + this.offset = 0; + this.onKeyLine = false; + this.stack = []; + this.source = ""; + this.type = ""; + this.lexer = new lexer.Lexer(); + this.onNewLine = onNewLine; + } + /** + * Parse `source` as a YAML stream. + * If `incomplete`, a part of the last line may be left as a buffer for the next call. + * + * Errors are not thrown, but yielded as `{ type: 'error', message }` tokens. + * + * @returns A generator of tokens representing each directive, document, and other structure. + */ + *parse(source, incomplete = false) { + if (this.onNewLine && this.offset === 0) + this.onNewLine(0); + for (const lexeme of this.lexer.lex(source, incomplete)) + yield* this.next(lexeme); + if (!incomplete) + yield* this.end(); + } + /** + * Advance the parser by the `source` of one lexical token. + */ + *next(source) { + this.source = source; + if (node_process.env.LOG_TOKENS) + console.log("|", cst.prettyToken(source)); + if (this.atScalar) { + this.atScalar = false; + yield* this.step(); + this.offset += source.length; + return; + } + const type = cst.tokenType(source); + if (!type) { + const message = `Not a YAML token: ${source}`; + yield* this.pop({ type: "error", offset: this.offset, message, source }); + this.offset += source.length; + } else if (type === "scalar") { + this.atNewLine = false; + this.atScalar = true; + this.type = "scalar"; + } else { + this.type = type; + yield* this.step(); + switch (type) { + case "newline": + this.atNewLine = true; + this.indent = 0; + if (this.onNewLine) + this.onNewLine(this.offset + source.length); + break; + case "space": + if (this.atNewLine && source[0] === " ") + this.indent += source.length; + break; + case "explicit-key-ind": + case "map-value-ind": + case "seq-item-ind": + if (this.atNewLine) + this.indent += source.length; + break; + case "doc-mode": + case "flow-error-end": + return; + default: + this.atNewLine = false; + } + this.offset += source.length; + } + } + /** Call at end of input to push out any remaining constructions */ + *end() { + while (this.stack.length > 0) + yield* this.pop(); + } + get sourceToken() { + const st = { + type: this.type, + offset: this.offset, + indent: this.indent, + source: this.source + }; + return st; + } + *step() { + const top = this.peek(1); + if (this.type === "doc-end" && top?.type !== "doc-end") { + while (this.stack.length > 0) + yield* this.pop(); + this.stack.push({ + type: "doc-end", + offset: this.offset, + source: this.source + }); + return; + } + if (!top) + return yield* this.stream(); + switch (top.type) { + case "document": + return yield* this.document(top); + case "alias": + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": + return yield* this.scalar(top); + case "block-scalar": + return yield* this.blockScalar(top); + case "block-map": + return yield* this.blockMap(top); + case "block-seq": + return yield* this.blockSequence(top); + case "flow-collection": + return yield* this.flowCollection(top); + case "doc-end": + return yield* this.documentEnd(top); + } + yield* this.pop(); + } + peek(n2) { + return this.stack[this.stack.length - n2]; + } + *pop(error) { + const token = error ?? this.stack.pop(); + if (!token) { + const message = "Tried to pop an empty stack"; + yield { type: "error", offset: this.offset, source: "", message }; + } else if (this.stack.length === 0) { + yield token; + } else { + const top = this.peek(1); + if (token.type === "block-scalar") { + token.indent = "indent" in top ? top.indent : 0; + } else if (token.type === "flow-collection" && top.type === "document") { + token.indent = 0; + } + if (token.type === "flow-collection") + fixFlowSeqItems(token); + switch (top.type) { + case "document": + top.value = token; + break; + case "block-scalar": + top.props.push(token); + break; + case "block-map": { + const it = top.items[top.items.length - 1]; + if (it.value) { + top.items.push({ start: [], key: token, sep: [] }); + this.onKeyLine = true; + return; + } else if (it.sep) { + it.value = token; + } else { + Object.assign(it, { key: token, sep: [] }); + this.onKeyLine = !it.explicitKey; + return; + } + break; + } + case "block-seq": { + const it = top.items[top.items.length - 1]; + if (it.value) + top.items.push({ start: [], value: token }); + else + it.value = token; + break; + } + case "flow-collection": { + const it = top.items[top.items.length - 1]; + if (!it || it.value) + top.items.push({ start: [], key: token, sep: [] }); + else if (it.sep) + it.value = token; + else + Object.assign(it, { key: token, sep: [] }); + return; + } + /* istanbul ignore next should not happen */ + default: + yield* this.pop(); + yield* this.pop(token); + } + if ((top.type === "document" || top.type === "block-map" || top.type === "block-seq") && (token.type === "block-map" || token.type === "block-seq")) { + const last = token.items[token.items.length - 1]; + if (last && !last.sep && !last.value && last.start.length > 0 && findNonEmptyIndex(last.start) === -1 && (token.indent === 0 || last.start.every((st) => st.type !== "comment" || st.indent < token.indent))) { + if (top.type === "document") + top.end = last.start; + else + top.items.push({ start: last.start }); + token.items.splice(-1, 1); + } + } + } + } + *stream() { + switch (this.type) { + case "directive-line": + yield { type: "directive", offset: this.offset, source: this.source }; + return; + case "byte-order-mark": + case "space": + case "comment": + case "newline": + yield this.sourceToken; + return; + case "doc-mode": + case "doc-start": { + const doc = { + type: "document", + offset: this.offset, + start: [] + }; + if (this.type === "doc-start") + doc.start.push(this.sourceToken); + this.stack.push(doc); + return; + } + } + yield { + type: "error", + offset: this.offset, + message: `Unexpected ${this.type} token in YAML stream`, + source: this.source + }; + } + *document(doc) { + if (doc.value) + return yield* this.lineEnd(doc); + switch (this.type) { + case "doc-start": { + if (findNonEmptyIndex(doc.start) !== -1) { + yield* this.pop(); + yield* this.step(); + } else + doc.start.push(this.sourceToken); + return; + } + case "anchor": + case "tag": + case "space": + case "comment": + case "newline": + doc.start.push(this.sourceToken); + return; + } + const bv = this.startBlockValue(doc); + if (bv) + this.stack.push(bv); + else { + yield { + type: "error", + offset: this.offset, + message: `Unexpected ${this.type} token in YAML document`, + source: this.source + }; + } + } + *scalar(scalar) { + if (this.type === "map-value-ind") { + const prev = getPrevProps(this.peek(2)); + const start = getFirstKeyStartProps(prev); + let sep; + if (scalar.end) { + sep = scalar.end; + sep.push(this.sourceToken); + delete scalar.end; + } else + sep = [this.sourceToken]; + const map = { + type: "block-map", + offset: scalar.offset, + indent: scalar.indent, + items: [{ start, key: scalar, sep }] + }; + this.onKeyLine = true; + this.stack[this.stack.length - 1] = map; + } else + yield* this.lineEnd(scalar); + } + *blockScalar(scalar) { + switch (this.type) { + case "space": + case "comment": + case "newline": + scalar.props.push(this.sourceToken); + return; + case "scalar": + scalar.source = this.source; + this.atNewLine = true; + this.indent = 0; + if (this.onNewLine) { + let nl = this.source.indexOf("\n") + 1; + while (nl !== 0) { + this.onNewLine(this.offset + nl); + nl = this.source.indexOf("\n", nl) + 1; + } + } + yield* this.pop(); + break; + /* istanbul ignore next should not happen */ + default: + yield* this.pop(); + yield* this.step(); + } + } + *blockMap(map) { + const it = map.items[map.items.length - 1]; + switch (this.type) { + case "newline": + this.onKeyLine = false; + if (it.value) { + const end = "end" in it.value ? it.value.end : void 0; + const last = Array.isArray(end) ? end[end.length - 1] : void 0; + if (last?.type === "comment") + end?.push(this.sourceToken); + else + map.items.push({ start: [this.sourceToken] }); + } else if (it.sep) { + it.sep.push(this.sourceToken); + } else { + it.start.push(this.sourceToken); + } + return; + case "space": + case "comment": + if (it.value) { + map.items.push({ start: [this.sourceToken] }); + } else if (it.sep) { + it.sep.push(this.sourceToken); + } else { + if (this.atIndentedComment(it.start, map.indent)) { + const prev = map.items[map.items.length - 2]; + const end = prev?.value?.end; + if (Array.isArray(end)) { + arrayPushArray(end, it.start); + end.push(this.sourceToken); + map.items.pop(); + return; + } + } + it.start.push(this.sourceToken); + } + return; + } + if (this.indent >= map.indent) { + const atMapIndent = !this.onKeyLine && this.indent === map.indent; + const atNextItem = atMapIndent && (it.sep || it.explicitKey) && this.type !== "seq-item-ind"; + let start = []; + if (atNextItem && it.sep && !it.value) { + const nl = []; + for (let i2 = 0; i2 < it.sep.length; ++i2) { + const st = it.sep[i2]; + switch (st.type) { + case "newline": + nl.push(i2); + break; + case "space": + break; + case "comment": + if (st.indent > map.indent) + nl.length = 0; + break; + default: + nl.length = 0; + } + } + if (nl.length >= 2) + start = it.sep.splice(nl[1]); + } + switch (this.type) { + case "anchor": + case "tag": + if (atNextItem || it.value) { + start.push(this.sourceToken); + map.items.push({ start }); + this.onKeyLine = true; + } else if (it.sep) { + it.sep.push(this.sourceToken); + } else { + it.start.push(this.sourceToken); + } + return; + case "explicit-key-ind": + if (!it.sep && !it.explicitKey) { + it.start.push(this.sourceToken); + it.explicitKey = true; + } else if (atNextItem || it.value) { + start.push(this.sourceToken); + map.items.push({ start, explicitKey: true }); + } else { + this.stack.push({ + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start: [this.sourceToken], explicitKey: true }] + }); + } + this.onKeyLine = true; + return; + case "map-value-ind": + if (it.explicitKey) { + if (!it.sep) { + if (includesToken(it.start, "newline")) { + Object.assign(it, { key: null, sep: [this.sourceToken] }); + } else { + const start2 = getFirstKeyStartProps(it.start); + this.stack.push({ + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start: start2, key: null, sep: [this.sourceToken] }] + }); + } + } else if (it.value) { + map.items.push({ start: [], key: null, sep: [this.sourceToken] }); + } else if (includesToken(it.sep, "map-value-ind")) { + this.stack.push({ + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start, key: null, sep: [this.sourceToken] }] + }); + } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) { + const start2 = getFirstKeyStartProps(it.start); + const key = it.key; + const sep = it.sep; + sep.push(this.sourceToken); + delete it.key; + delete it.sep; + this.stack.push({ + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start: start2, key, sep }] + }); + } else if (start.length > 0) { + it.sep = it.sep.concat(start, this.sourceToken); + } else { + it.sep.push(this.sourceToken); + } + } else { + if (!it.sep) { + Object.assign(it, { key: null, sep: [this.sourceToken] }); + } else if (it.value || atNextItem) { + map.items.push({ start, key: null, sep: [this.sourceToken] }); + } else if (includesToken(it.sep, "map-value-ind")) { + this.stack.push({ + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start: [], key: null, sep: [this.sourceToken] }] + }); + } else { + it.sep.push(this.sourceToken); + } + } + this.onKeyLine = true; + return; + case "alias": + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": { + const fs = this.flowScalar(this.type); + if (atNextItem || it.value) { + map.items.push({ start, key: fs, sep: [] }); + this.onKeyLine = true; + } else if (it.sep) { + this.stack.push(fs); + } else { + Object.assign(it, { key: fs, sep: [] }); + this.onKeyLine = true; + } + return; + } + default: { + const bv = this.startBlockValue(map); + if (bv) { + if (bv.type === "block-seq") { + if (!it.explicitKey && it.sep && !includesToken(it.sep, "newline")) { + yield* this.pop({ + type: "error", + offset: this.offset, + message: "Unexpected block-seq-ind on same line with key", + source: this.source + }); + return; + } + } else if (atMapIndent) { + map.items.push({ start }); + } + this.stack.push(bv); + return; + } + } + } + } + yield* this.pop(); + yield* this.step(); + } + *blockSequence(seq) { + const it = seq.items[seq.items.length - 1]; + switch (this.type) { + case "newline": + if (it.value) { + const end = "end" in it.value ? it.value.end : void 0; + const last = Array.isArray(end) ? end[end.length - 1] : void 0; + if (last?.type === "comment") + end?.push(this.sourceToken); + else + seq.items.push({ start: [this.sourceToken] }); + } else + it.start.push(this.sourceToken); + return; + case "space": + case "comment": + if (it.value) + seq.items.push({ start: [this.sourceToken] }); + else { + if (this.atIndentedComment(it.start, seq.indent)) { + const prev = seq.items[seq.items.length - 2]; + const end = prev?.value?.end; + if (Array.isArray(end)) { + arrayPushArray(end, it.start); + end.push(this.sourceToken); + seq.items.pop(); + return; + } + } + it.start.push(this.sourceToken); + } + return; + case "anchor": + case "tag": + if (it.value || this.indent <= seq.indent) + break; + it.start.push(this.sourceToken); + return; + case "seq-item-ind": + if (this.indent !== seq.indent) + break; + if (it.value || includesToken(it.start, "seq-item-ind")) + seq.items.push({ start: [this.sourceToken] }); + else + it.start.push(this.sourceToken); + return; + } + if (this.indent > seq.indent) { + const bv = this.startBlockValue(seq); + if (bv) { + this.stack.push(bv); + return; + } + } + yield* this.pop(); + yield* this.step(); + } + *flowCollection(fc) { + const it = fc.items[fc.items.length - 1]; + if (this.type === "flow-error-end") { + let top; + do { + yield* this.pop(); + top = this.peek(1); + } while (top?.type === "flow-collection"); + } else if (fc.end.length === 0) { + switch (this.type) { + case "comma": + case "explicit-key-ind": + if (!it || it.sep) + fc.items.push({ start: [this.sourceToken] }); + else + it.start.push(this.sourceToken); + return; + case "map-value-ind": + if (!it || it.value) + fc.items.push({ start: [], key: null, sep: [this.sourceToken] }); + else if (it.sep) + it.sep.push(this.sourceToken); + else + Object.assign(it, { key: null, sep: [this.sourceToken] }); + return; + case "space": + case "comment": + case "newline": + case "anchor": + case "tag": + if (!it || it.value) + fc.items.push({ start: [this.sourceToken] }); + else if (it.sep) + it.sep.push(this.sourceToken); + else + it.start.push(this.sourceToken); + return; + case "alias": + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": { + const fs = this.flowScalar(this.type); + if (!it || it.value) + fc.items.push({ start: [], key: fs, sep: [] }); + else if (it.sep) + this.stack.push(fs); + else + Object.assign(it, { key: fs, sep: [] }); + return; + } + case "flow-map-end": + case "flow-seq-end": + fc.end.push(this.sourceToken); + return; + } + const bv = this.startBlockValue(fc); + if (bv) + this.stack.push(bv); + else { + yield* this.pop(); + yield* this.step(); + } + } else { + const parent = this.peek(2); + if (parent.type === "block-map" && (this.type === "map-value-ind" && parent.indent === fc.indent || this.type === "newline" && !parent.items[parent.items.length - 1].sep)) { + yield* this.pop(); + yield* this.step(); + } else if (this.type === "map-value-ind" && parent.type !== "flow-collection") { + const prev = getPrevProps(parent); + const start = getFirstKeyStartProps(prev); + fixFlowSeqItems(fc); + const sep = fc.end.splice(1, fc.end.length); + sep.push(this.sourceToken); + const map = { + type: "block-map", + offset: fc.offset, + indent: fc.indent, + items: [{ start, key: fc, sep }] + }; + this.onKeyLine = true; + this.stack[this.stack.length - 1] = map; + } else { + yield* this.lineEnd(fc); + } + } + } + flowScalar(type) { + if (this.onNewLine) { + let nl = this.source.indexOf("\n") + 1; + while (nl !== 0) { + this.onNewLine(this.offset + nl); + nl = this.source.indexOf("\n", nl) + 1; + } + } + return { + type, + offset: this.offset, + indent: this.indent, + source: this.source + }; + } + startBlockValue(parent) { + switch (this.type) { + case "alias": + case "scalar": + case "single-quoted-scalar": + case "double-quoted-scalar": + return this.flowScalar(this.type); + case "block-scalar-header": + return { + type: "block-scalar", + offset: this.offset, + indent: this.indent, + props: [this.sourceToken], + source: "" + }; + case "flow-map-start": + case "flow-seq-start": + return { + type: "flow-collection", + offset: this.offset, + indent: this.indent, + start: this.sourceToken, + items: [], + end: [] + }; + case "seq-item-ind": + return { + type: "block-seq", + offset: this.offset, + indent: this.indent, + items: [{ start: [this.sourceToken] }] + }; + case "explicit-key-ind": { + this.onKeyLine = true; + const prev = getPrevProps(parent); + const start = getFirstKeyStartProps(prev); + start.push(this.sourceToken); + return { + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start, explicitKey: true }] + }; + } + case "map-value-ind": { + this.onKeyLine = true; + const prev = getPrevProps(parent); + const start = getFirstKeyStartProps(prev); + return { + type: "block-map", + offset: this.offset, + indent: this.indent, + items: [{ start, key: null, sep: [this.sourceToken] }] + }; + } + } + return null; + } + atIndentedComment(start, indent) { + if (this.type !== "comment") + return false; + if (this.indent <= indent) + return false; + return start.every((st) => st.type === "newline" || st.type === "space"); + } + *documentEnd(docEnd) { + if (this.type !== "doc-mode") { + if (docEnd.end) + docEnd.end.push(this.sourceToken); + else + docEnd.end = [this.sourceToken]; + if (this.type === "newline") + yield* this.pop(); + } + } + *lineEnd(token) { + switch (this.type) { + case "comma": + case "doc-start": + case "doc-end": + case "flow-seq-end": + case "flow-map-end": + case "map-value-ind": + yield* this.pop(); + yield* this.step(); + break; + case "newline": + this.onKeyLine = false; + // fallthrough + case "space": + case "comment": + default: + if (token.end) + token.end.push(this.sourceToken); + else + token.end = [this.sourceToken]; + if (this.type === "newline") + yield* this.pop(); + } + } + }; + exports2.Parser = Parser; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/public-api.js +var require_public_api = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/public-api.js"(exports2) { + "use strict"; + var composer = require_composer(); + var Document = require_Document(); + var errors = require_errors2(); + var log = require_log(); + var identity3 = require_identity(); + var lineCounter = require_line_counter(); + var parser = require_parser(); + function parseOptions(options) { + const prettyErrors = options.prettyErrors !== false; + const lineCounter$1 = options.lineCounter || prettyErrors && new lineCounter.LineCounter() || null; + return { lineCounter: lineCounter$1, prettyErrors }; + } + function parseAllDocuments(source, options = {}) { + const { lineCounter: lineCounter2, prettyErrors } = parseOptions(options); + const parser$1 = new parser.Parser(lineCounter2?.addNewLine); + const composer$1 = new composer.Composer(options); + const docs = Array.from(composer$1.compose(parser$1.parse(source))); + if (prettyErrors && lineCounter2) + for (const doc of docs) { + doc.errors.forEach(errors.prettifyError(source, lineCounter2)); + doc.warnings.forEach(errors.prettifyError(source, lineCounter2)); + } + if (docs.length > 0) + return docs; + return Object.assign([], { empty: true }, composer$1.streamInfo()); + } + function parseDocument(source, options = {}) { + const { lineCounter: lineCounter2, prettyErrors } = parseOptions(options); + const parser$1 = new parser.Parser(lineCounter2?.addNewLine); + const composer$1 = new composer.Composer(options); + let doc = null; + for (const _doc of composer$1.compose(parser$1.parse(source), true, source.length)) { + if (!doc) + doc = _doc; + else if (doc.options.logLevel !== "silent") { + doc.errors.push(new errors.YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()")); + break; + } + } + if (prettyErrors && lineCounter2) { + doc.errors.forEach(errors.prettifyError(source, lineCounter2)); + doc.warnings.forEach(errors.prettifyError(source, lineCounter2)); + } + return doc; + } + function parse(src, reviver, options) { + let _reviver = void 0; + if (typeof reviver === "function") { + _reviver = reviver; + } else if (options === void 0 && reviver && typeof reviver === "object") { + options = reviver; + } + const doc = parseDocument(src, options); + if (!doc) + return null; + doc.warnings.forEach((warning) => log.warn(doc.options.logLevel, warning)); + if (doc.errors.length > 0) { + if (doc.options.logLevel !== "silent") + throw doc.errors[0]; + else + doc.errors = []; + } + return doc.toJS(Object.assign({ reviver: _reviver }, options)); + } + function stringify(value, replacer, options) { + let _replacer = null; + if (typeof replacer === "function" || Array.isArray(replacer)) { + _replacer = replacer; + } else if (options === void 0 && replacer) { + options = replacer; + } + if (typeof options === "string") + options = options.length; + if (typeof options === "number") { + const indent = Math.round(options); + options = indent < 1 ? void 0 : indent > 8 ? { indent: 8 } : { indent }; + } + if (value === void 0) { + const { keepUndefined } = options ?? replacer ?? {}; + if (!keepUndefined) + return void 0; + } + if (identity3.isDocument(value) && !_replacer) + return value.toString(options); + return new Document.Document(value, _replacer, options).toString(options); + } + exports2.parse = parse; + exports2.parseAllDocuments = parseAllDocuments; + exports2.parseDocument = parseDocument; + exports2.stringify = stringify; + } +}); + +// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/index.js +var require_dist = __commonJS({ + "../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/index.js"(exports2) { + "use strict"; + var composer = require_composer(); + var Document = require_Document(); + var Schema = require_Schema(); + var errors = require_errors2(); + var Alias = require_Alias(); + var identity3 = require_identity(); + var Pair = require_Pair(); + var Scalar = require_Scalar(); + var YAMLMap = require_YAMLMap(); + var YAMLSeq = require_YAMLSeq(); + var cst = require_cst(); + var lexer = require_lexer(); + var lineCounter = require_line_counter(); + var parser = require_parser(); + var publicApi = require_public_api(); + var visit = require_visit(); + exports2.Composer = composer.Composer; + exports2.Document = Document.Document; + exports2.Schema = Schema.Schema; + exports2.YAMLError = errors.YAMLError; + exports2.YAMLParseError = errors.YAMLParseError; + exports2.YAMLWarning = errors.YAMLWarning; + exports2.Alias = Alias.Alias; + exports2.isAlias = identity3.isAlias; + exports2.isCollection = identity3.isCollection; + exports2.isDocument = identity3.isDocument; + exports2.isMap = identity3.isMap; + exports2.isNode = identity3.isNode; + exports2.isPair = identity3.isPair; + exports2.isScalar = identity3.isScalar; + exports2.isSeq = identity3.isSeq; + exports2.Pair = Pair.Pair; + exports2.Scalar = Scalar.Scalar; + exports2.YAMLMap = YAMLMap.YAMLMap; + exports2.YAMLSeq = YAMLSeq.YAMLSeq; + exports2.CST = cst; + exports2.Lexer = lexer.Lexer; + exports2.LineCounter = lineCounter.LineCounter; + exports2.Parser = parser.Parser; + exports2.parse = publicApi.parse; + exports2.parseAllDocuments = publicApi.parseAllDocuments; + exports2.parseDocument = publicApi.parseDocument; + exports2.stringify = publicApi.stringify; + exports2.visit = visit.visit; + exports2.visitAsync = visit.visitAsync; + } +}); + +// src/main.ts +var main_exports = {}; +__export(main_exports, { + run: () => run +}); +module.exports = __toCommonJS(main_exports); +var import_node_fs6 = require("fs"); +var import_node_path6 = __toESM(require("path")); +var core = __toESM(require_core()); + +// ../../packages/core/dist/index.js +var import_fs = require("fs"); +var import_path = __toESM(require("path"), 1); +var import_crypto = require("crypto"); +var import_fs2 = require("fs"); +var import_fs3 = require("fs"); +var import_path2 = __toESM(require("path"), 1); + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js +var external_exports = {}; +__export(external_exports, { + BRAND: () => BRAND, + DIRTY: () => DIRTY, + EMPTY_PATH: () => EMPTY_PATH, + INVALID: () => INVALID, + NEVER: () => NEVER, + OK: () => OK, + ParseStatus: () => ParseStatus, + Schema: () => ZodType, + ZodAny: () => ZodAny, + ZodArray: () => ZodArray, + ZodBigInt: () => ZodBigInt, + ZodBoolean: () => ZodBoolean, + ZodBranded: () => ZodBranded, + ZodCatch: () => ZodCatch, + ZodDate: () => ZodDate, + ZodDefault: () => ZodDefault, + ZodDiscriminatedUnion: () => ZodDiscriminatedUnion, + ZodEffects: () => ZodEffects, + ZodEnum: () => ZodEnum, + ZodError: () => ZodError, + ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind, + ZodFunction: () => ZodFunction, + ZodIntersection: () => ZodIntersection, + ZodIssueCode: () => ZodIssueCode, + ZodLazy: () => ZodLazy, + ZodLiteral: () => ZodLiteral, + ZodMap: () => ZodMap, + ZodNaN: () => ZodNaN, + ZodNativeEnum: () => ZodNativeEnum, + ZodNever: () => ZodNever, + ZodNull: () => ZodNull, + ZodNullable: () => ZodNullable, + ZodNumber: () => ZodNumber, + ZodObject: () => ZodObject, + ZodOptional: () => ZodOptional, + ZodParsedType: () => ZodParsedType, + ZodPipeline: () => ZodPipeline, + ZodPromise: () => ZodPromise, + ZodReadonly: () => ZodReadonly, + ZodRecord: () => ZodRecord, + ZodSchema: () => ZodType, + ZodSet: () => ZodSet, + ZodString: () => ZodString, + ZodSymbol: () => ZodSymbol, + ZodTransformer: () => ZodEffects, + ZodTuple: () => ZodTuple, + ZodType: () => ZodType, + ZodUndefined: () => ZodUndefined, + ZodUnion: () => ZodUnion, + ZodUnknown: () => ZodUnknown, + ZodVoid: () => ZodVoid, + addIssueToContext: () => addIssueToContext, + any: () => anyType, + array: () => arrayType, + bigint: () => bigIntType, + boolean: () => booleanType, + coerce: () => coerce, + custom: () => custom, + date: () => dateType, + datetimeRegex: () => datetimeRegex, + defaultErrorMap: () => en_default, + discriminatedUnion: () => discriminatedUnionType, + effect: () => effectsType, + enum: () => enumType, + function: () => functionType, + getErrorMap: () => getErrorMap, + getParsedType: () => getParsedType, + instanceof: () => instanceOfType, + intersection: () => intersectionType, + isAborted: () => isAborted, + isAsync: () => isAsync, + isDirty: () => isDirty, + isValid: () => isValid, + late: () => late, + lazy: () => lazyType, + literal: () => literalType, + makeIssue: () => makeIssue, + map: () => mapType, + nan: () => nanType, + nativeEnum: () => nativeEnumType, + never: () => neverType, + null: () => nullType, + nullable: () => nullableType, + number: () => numberType, + object: () => objectType, + objectUtil: () => objectUtil, + oboolean: () => oboolean, + onumber: () => onumber, + optional: () => optionalType, + ostring: () => ostring, + pipeline: () => pipelineType, + preprocess: () => preprocessType, + promise: () => promiseType, + quotelessJson: () => quotelessJson, + record: () => recordType, + set: () => setType, + setErrorMap: () => setErrorMap, + strictObject: () => strictObjectType, + string: () => stringType, + symbol: () => symbolType, + transformer: () => effectsType, + tuple: () => tupleType, + undefined: () => undefinedType, + union: () => unionType, + unknown: () => unknownType, + util: () => util, + void: () => voidType +}); + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js +var util; +(function(util2) { + util2.assertEqual = (_) => { + }; + function assertIs(_arg) { + } + util2.assertIs = assertIs; + function assertNever(_x) { + throw new Error(); + } + util2.assertNever = assertNever; + util2.arrayToEnum = (items) => { + const obj = {}; + for (const item of items) { + obj[item] = item; + } + return obj; + }; + util2.getValidEnumValues = (obj) => { + const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number"); + const filtered = {}; + for (const k of validKeys) { + filtered[k] = obj[k]; + } + return util2.objectValues(filtered); + }; + util2.objectValues = (obj) => { + return util2.objectKeys(obj).map(function(e) { + return obj[e]; + }); + }; + util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => { + const keys = []; + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key)) { + keys.push(key); + } + } + return keys; + }; + util2.find = (arr, checker) => { + for (const item of arr) { + if (checker(item)) + return item; + } + return void 0; + }; + util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val; + function joinValues(array, separator = " | ") { + return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator); + } + util2.joinValues = joinValues; + util2.jsonStringifyReplacer = (_, value) => { + if (typeof value === "bigint") { + return value.toString(); + } + return value; + }; +})(util || (util = {})); +var objectUtil; +(function(objectUtil2) { + objectUtil2.mergeShapes = (first, second) => { + return { + ...first, + ...second + // second overwrites first + }; + }; +})(objectUtil || (objectUtil = {})); +var ZodParsedType = util.arrayToEnum([ + "string", + "nan", + "number", + "integer", + "float", + "boolean", + "date", + "bigint", + "symbol", + "function", + "undefined", + "null", + "array", + "object", + "unknown", + "promise", + "void", + "never", + "map", + "set" +]); +var getParsedType = (data) => { + const t = typeof data; + switch (t) { + case "undefined": + return ZodParsedType.undefined; + case "string": + return ZodParsedType.string; + case "number": + return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number; + case "boolean": + return ZodParsedType.boolean; + case "function": + return ZodParsedType.function; + case "bigint": + return ZodParsedType.bigint; + case "symbol": + return ZodParsedType.symbol; + case "object": + if (Array.isArray(data)) { + return ZodParsedType.array; + } + if (data === null) { + return ZodParsedType.null; + } + if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { + return ZodParsedType.promise; + } + if (typeof Map !== "undefined" && data instanceof Map) { + return ZodParsedType.map; + } + if (typeof Set !== "undefined" && data instanceof Set) { + return ZodParsedType.set; + } + if (typeof Date !== "undefined" && data instanceof Date) { + return ZodParsedType.date; + } + return ZodParsedType.object; + default: + return ZodParsedType.unknown; + } +}; + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js +var ZodIssueCode = util.arrayToEnum([ + "invalid_type", + "invalid_literal", + "custom", + "invalid_union", + "invalid_union_discriminator", + "invalid_enum_value", + "unrecognized_keys", + "invalid_arguments", + "invalid_return_type", + "invalid_date", + "invalid_string", + "too_small", + "too_big", + "invalid_intersection_types", + "not_multiple_of", + "not_finite" +]); +var quotelessJson = (obj) => { + const json = JSON.stringify(obj, null, 2); + return json.replace(/"([^"]+)":/g, "$1:"); +}; +var ZodError = class _ZodError extends Error { + get errors() { + return this.issues; + } + constructor(issues) { + super(); + this.issues = []; + this.addIssue = (sub) => { + this.issues = [...this.issues, sub]; + }; + this.addIssues = (subs = []) => { + this.issues = [...this.issues, ...subs]; + }; + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } else { + this.__proto__ = actualProto; + } + this.name = "ZodError"; + this.issues = issues; + } + format(_mapper) { + const mapper = _mapper || function(issue) { + return issue.message; + }; + const fieldErrors = { _errors: [] }; + const processError = (error) => { + for (const issue of error.issues) { + if (issue.code === "invalid_union") { + issue.unionErrors.map(processError); + } else if (issue.code === "invalid_return_type") { + processError(issue.returnTypeError); + } else if (issue.code === "invalid_arguments") { + processError(issue.argumentsError); + } else if (issue.path.length === 0) { + fieldErrors._errors.push(mapper(issue)); + } else { + let curr = fieldErrors; + let i2 = 0; + while (i2 < issue.path.length) { + const el = issue.path[i2]; + const terminal = i2 === issue.path.length - 1; + if (!terminal) { + curr[el] = curr[el] || { _errors: [] }; + } else { + curr[el] = curr[el] || { _errors: [] }; + curr[el]._errors.push(mapper(issue)); + } + curr = curr[el]; + i2++; + } + } + } + }; + processError(this); + return fieldErrors; + } + static assert(value) { + if (!(value instanceof _ZodError)) { + throw new Error(`Not a ZodError: ${value}`); + } + } + toString() { + return this.message; + } + get message() { + return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2); + } + get isEmpty() { + return this.issues.length === 0; + } + flatten(mapper = (issue) => issue.message) { + const fieldErrors = {}; + const formErrors = []; + for (const sub of this.issues) { + if (sub.path.length > 0) { + const firstEl = sub.path[0]; + fieldErrors[firstEl] = fieldErrors[firstEl] || []; + fieldErrors[firstEl].push(mapper(sub)); + } else { + formErrors.push(mapper(sub)); + } + } + return { formErrors, fieldErrors }; + } + get formErrors() { + return this.flatten(); + } +}; +ZodError.create = (issues) => { + const error = new ZodError(issues); + return error; +}; + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js +var errorMap = (issue, _ctx) => { + let message; + switch (issue.code) { + case ZodIssueCode.invalid_type: + if (issue.received === ZodParsedType.undefined) { + message = "Required"; + } else { + message = `Expected ${issue.expected}, received ${issue.received}`; + } + break; + case ZodIssueCode.invalid_literal: + message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`; + break; + case ZodIssueCode.unrecognized_keys: + message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`; + break; + case ZodIssueCode.invalid_union: + message = `Invalid input`; + break; + case ZodIssueCode.invalid_union_discriminator: + message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`; + break; + case ZodIssueCode.invalid_enum_value: + message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`; + break; + case ZodIssueCode.invalid_arguments: + message = `Invalid function arguments`; + break; + case ZodIssueCode.invalid_return_type: + message = `Invalid function return type`; + break; + case ZodIssueCode.invalid_date: + message = `Invalid date`; + break; + case ZodIssueCode.invalid_string: + if (typeof issue.validation === "object") { + if ("includes" in issue.validation) { + message = `Invalid input: must include "${issue.validation.includes}"`; + if (typeof issue.validation.position === "number") { + message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`; + } + } else if ("startsWith" in issue.validation) { + message = `Invalid input: must start with "${issue.validation.startsWith}"`; + } else if ("endsWith" in issue.validation) { + message = `Invalid input: must end with "${issue.validation.endsWith}"`; + } else { + util.assertNever(issue.validation); + } + } else if (issue.validation !== "regex") { + message = `Invalid ${issue.validation}`; + } else { + message = "Invalid"; + } + break; + case ZodIssueCode.too_small: + if (issue.type === "array") + message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`; + else if (issue.type === "string") + message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`; + else if (issue.type === "number") + message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`; + else if (issue.type === "bigint") + message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`; + else if (issue.type === "date") + message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`; + else + message = "Invalid input"; + break; + case ZodIssueCode.too_big: + if (issue.type === "array") + message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`; + else if (issue.type === "string") + message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`; + else if (issue.type === "number") + message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`; + else if (issue.type === "bigint") + message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`; + else if (issue.type === "date") + message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`; + else + message = "Invalid input"; + break; + case ZodIssueCode.custom: + message = `Invalid input`; + break; + case ZodIssueCode.invalid_intersection_types: + message = `Intersection results could not be merged`; + break; + case ZodIssueCode.not_multiple_of: + message = `Number must be a multiple of ${issue.multipleOf}`; + break; + case ZodIssueCode.not_finite: + message = "Number must be finite"; + break; + default: + message = _ctx.defaultError; + util.assertNever(issue); + } + return { message }; +}; +var en_default = errorMap; + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js +var overrideErrorMap = en_default; +function setErrorMap(map) { + overrideErrorMap = map; +} +function getErrorMap() { + return overrideErrorMap; +} + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js +var makeIssue = (params) => { + const { data, path: path12, errorMaps, issueData } = params; + const fullPath = [...path12, ...issueData.path || []]; + const fullIssue = { + ...issueData, + path: fullPath + }; + if (issueData.message !== void 0) { + return { + ...issueData, + path: fullPath, + message: issueData.message + }; + } + let errorMessage = ""; + const maps = errorMaps.filter((m) => !!m).slice().reverse(); + for (const map of maps) { + errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message; + } + return { + ...issueData, + path: fullPath, + message: errorMessage + }; +}; +var EMPTY_PATH = []; +function addIssueToContext(ctx, issueData) { + const overrideMap = getErrorMap(); + const issue = makeIssue({ + issueData, + data: ctx.data, + path: ctx.path, + errorMaps: [ + ctx.common.contextualErrorMap, + // contextual error map is first priority + ctx.schemaErrorMap, + // then schema-bound map if available + overrideMap, + // then global override map + overrideMap === en_default ? void 0 : en_default + // then global default map + ].filter((x) => !!x) + }); + ctx.common.issues.push(issue); +} +var ParseStatus = class _ParseStatus { + constructor() { + this.value = "valid"; + } + dirty() { + if (this.value === "valid") + this.value = "dirty"; + } + abort() { + if (this.value !== "aborted") + this.value = "aborted"; + } + static mergeArray(status, results) { + const arrayValue = []; + for (const s of results) { + if (s.status === "aborted") + return INVALID; + if (s.status === "dirty") + status.dirty(); + arrayValue.push(s.value); + } + return { status: status.value, value: arrayValue }; + } + static async mergeObjectAsync(status, pairs) { + const syncPairs = []; + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; + syncPairs.push({ + key, + value + }); + } + return _ParseStatus.mergeObjectSync(status, syncPairs); + } + static mergeObjectSync(status, pairs) { + const finalObject = {}; + for (const pair of pairs) { + const { key, value } = pair; + if (key.status === "aborted") + return INVALID; + if (value.status === "aborted") + return INVALID; + if (key.status === "dirty") + status.dirty(); + if (value.status === "dirty") + status.dirty(); + if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) { + finalObject[key.value] = value.value; + } + } + return { status: status.value, value: finalObject }; + } +}; +var INVALID = Object.freeze({ + status: "aborted" +}); +var DIRTY = (value) => ({ status: "dirty", value }); +var OK = (value) => ({ status: "valid", value }); +var isAborted = (x) => x.status === "aborted"; +var isDirty = (x) => x.status === "dirty"; +var isValid = (x) => x.status === "valid"; +var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise; + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js +var errorUtil; +(function(errorUtil2) { + errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {}; + errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message; +})(errorUtil || (errorUtil = {})); + +// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js +var ParseInputLazyPath = class { + constructor(parent, value, path12, key) { + this._cachedPath = []; + this.parent = parent; + this.data = value; + this._path = path12; + this._key = key; + } + get path() { + if (!this._cachedPath.length) { + if (Array.isArray(this._key)) { + this._cachedPath.push(...this._path, ...this._key); + } else { + this._cachedPath.push(...this._path, this._key); + } + } + return this._cachedPath; + } +}; +var handleResult = (ctx, result) => { + if (isValid(result)) { + return { success: true, data: result.value }; + } else { + if (!ctx.common.issues.length) { + throw new Error("Validation failed but no issues detected."); + } + return { + success: false, + get error() { + if (this._error) + return this._error; + const error = new ZodError(ctx.common.issues); + this._error = error; + return this._error; + } + }; + } +}; +function processCreateParams(params) { + if (!params) + return {}; + const { errorMap: errorMap2, invalid_type_error, required_error, description } = params; + if (errorMap2 && (invalid_type_error || required_error)) { + throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`); + } + if (errorMap2) + return { errorMap: errorMap2, description }; + const customMap = (iss, ctx) => { + const { message } = params; + if (iss.code === "invalid_enum_value") { + return { message: message ?? ctx.defaultError }; + } + if (typeof ctx.data === "undefined") { + return { message: message ?? required_error ?? ctx.defaultError }; + } + if (iss.code !== "invalid_type") + return { message: ctx.defaultError }; + return { message: message ?? invalid_type_error ?? ctx.defaultError }; + }; + return { errorMap: customMap, description }; +} +var ZodType = class { + get description() { + return this._def.description; + } + _getType(input) { + return getParsedType(input.data); + } + _getOrReturnCtx(input, ctx) { + return ctx || { + common: input.parent.common, + data: input.data, + parsedType: getParsedType(input.data), + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent + }; + } + _processInputParams(input) { + return { + status: new ParseStatus(), + ctx: { + common: input.parent.common, + data: input.data, + parsedType: getParsedType(input.data), + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent + } + }; + } + _parseSync(input) { + const result = this._parse(input); + if (isAsync(result)) { + throw new Error("Synchronous parse encountered promise."); + } + return result; + } + _parseAsync(input) { + const result = this._parse(input); + return Promise.resolve(result); + } + parse(data, params) { + const result = this.safeParse(data, params); + if (result.success) + return result.data; + throw result.error; + } + safeParse(data, params) { + const ctx = { + common: { + issues: [], + async: params?.async ?? false, + contextualErrorMap: params?.errorMap + }, + path: params?.path || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: getParsedType(data) + }; + const result = this._parseSync({ data, path: ctx.path, parent: ctx }); + return handleResult(ctx, result); + } + "~validate"(data) { + const ctx = { + common: { + issues: [], + async: !!this["~standard"].async + }, + path: [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: getParsedType(data) + }; + if (!this["~standard"].async) { + try { + const result = this._parseSync({ data, path: [], parent: ctx }); + return isValid(result) ? { + value: result.value + } : { + issues: ctx.common.issues + }; + } catch (err) { + if (err?.message?.toLowerCase()?.includes("encountered")) { + this["~standard"].async = true; + } + ctx.common = { + issues: [], + async: true + }; + } + } + return this._parseAsync({ data, path: [], parent: ctx }).then((result) => isValid(result) ? { + value: result.value + } : { + issues: ctx.common.issues + }); + } + async parseAsync(data, params) { + const result = await this.safeParseAsync(data, params); + if (result.success) + return result.data; + throw result.error; + } + async safeParseAsync(data, params) { + const ctx = { + common: { + issues: [], + contextualErrorMap: params?.errorMap, + async: true + }, + path: params?.path || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: getParsedType(data) + }; + const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx }); + const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); + return handleResult(ctx, result); + } + refine(check, message) { + const getIssueProperties = (val) => { + if (typeof message === "string" || typeof message === "undefined") { + return { message }; + } else if (typeof message === "function") { + return message(val); + } else { + return message; + } + }; + return this._refinement((val, ctx) => { + const result = check(val); + const setError = () => ctx.addIssue({ + code: ZodIssueCode.custom, + ...getIssueProperties(val) + }); + if (typeof Promise !== "undefined" && result instanceof Promise) { + return result.then((data) => { + if (!data) { + setError(); + return false; + } else { + return true; + } + }); + } + if (!result) { + setError(); + return false; + } else { + return true; + } + }); + } + refinement(check, refinementData) { + return this._refinement((val, ctx) => { + if (!check(val)) { + ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); + return false; + } else { + return true; + } + }); + } + _refinement(refinement) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { type: "refinement", refinement } + }); + } + superRefine(refinement) { + return this._refinement(refinement); + } + constructor(def) { + this.spa = this.safeParseAsync; + this._def = def; + this.parse = this.parse.bind(this); + this.safeParse = this.safeParse.bind(this); + this.parseAsync = this.parseAsync.bind(this); + this.safeParseAsync = this.safeParseAsync.bind(this); + this.spa = this.spa.bind(this); + this.refine = this.refine.bind(this); + this.refinement = this.refinement.bind(this); + this.superRefine = this.superRefine.bind(this); + this.optional = this.optional.bind(this); + this.nullable = this.nullable.bind(this); + this.nullish = this.nullish.bind(this); + this.array = this.array.bind(this); + this.promise = this.promise.bind(this); + this.or = this.or.bind(this); + this.and = this.and.bind(this); + this.transform = this.transform.bind(this); + this.brand = this.brand.bind(this); + this.default = this.default.bind(this); + this.catch = this.catch.bind(this); + this.describe = this.describe.bind(this); + this.pipe = this.pipe.bind(this); + this.readonly = this.readonly.bind(this); + this.isNullable = this.isNullable.bind(this); + this.isOptional = this.isOptional.bind(this); + this["~standard"] = { + version: 1, + vendor: "zod", + validate: (data) => this["~validate"](data) + }; + } + optional() { + return ZodOptional.create(this, this._def); + } + nullable() { + return ZodNullable.create(this, this._def); + } + nullish() { + return this.nullable().optional(); + } + array() { + return ZodArray.create(this); + } + promise() { + return ZodPromise.create(this, this._def); + } + or(option) { + return ZodUnion.create([this, option], this._def); + } + and(incoming) { + return ZodIntersection.create(this, incoming, this._def); + } + transform(transform) { + return new ZodEffects({ + ...processCreateParams(this._def), + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { type: "transform", transform } + }); + } + default(def) { + const defaultValueFunc = typeof def === "function" ? def : () => def; + return new ZodDefault({ + ...processCreateParams(this._def), + innerType: this, + defaultValue: defaultValueFunc, + typeName: ZodFirstPartyTypeKind.ZodDefault + }); + } + brand() { + return new ZodBranded({ + typeName: ZodFirstPartyTypeKind.ZodBranded, + type: this, + ...processCreateParams(this._def) + }); + } + catch(def) { + const catchValueFunc = typeof def === "function" ? def : () => def; + return new ZodCatch({ + ...processCreateParams(this._def), + innerType: this, + catchValue: catchValueFunc, + typeName: ZodFirstPartyTypeKind.ZodCatch + }); + } + describe(description) { + const This = this.constructor; + return new This({ + ...this._def, + description + }); + } + pipe(target) { + return ZodPipeline.create(this, target); + } + readonly() { + return ZodReadonly.create(this); + } + isOptional() { + return this.safeParse(void 0).success; + } + isNullable() { + return this.safeParse(null).success; + } +}; +var cuidRegex = /^c[^\s-]{8,}$/i; +var cuid2Regex = /^[0-9a-z]+$/; +var ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i; +var uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i; +var nanoidRegex = /^[a-z0-9_-]{21}$/i; +var jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/; +var durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/; +var emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; +var _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`; +var emojiRegex; +var ipv4Regex = /^(?:(?: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])$/; +var ipv4CidrRegex = /^(?:(?: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])\/(3[0-2]|[12]?[0-9])$/; +var ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,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}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; +var ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,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}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/; +var base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; +var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/; +var dateRegexSource = `((\\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])))`; +var dateRegex = new RegExp(`^${dateRegexSource}$`); +function timeRegexSource(args) { + let secondsRegexSource = `[0-5]\\d`; + if (args.precision) { + secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`; + } else if (args.precision == null) { + secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`; + } + const secondsQuantifier = args.precision ? "+" : "?"; + return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`; +} +function timeRegex(args) { + return new RegExp(`^${timeRegexSource(args)}$`); +} +function datetimeRegex(args) { + let regex = `${dateRegexSource}T${timeRegexSource(args)}`; + const opts = []; + opts.push(args.local ? `Z?` : `Z`); + if (args.offset) + opts.push(`([+-]\\d{2}:?\\d{2})`); + regex = `${regex}(${opts.join("|")})`; + return new RegExp(`^${regex}$`); +} +function isValidIP(ip, version) { + if ((version === "v4" || !version) && ipv4Regex.test(ip)) { + return true; + } + if ((version === "v6" || !version) && ipv6Regex.test(ip)) { + return true; + } + return false; +} +function isValidJWT(jwt, alg) { + if (!jwtRegex.test(jwt)) + return false; + try { + const [header] = jwt.split("."); + if (!header) + return false; + const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "="); + const decoded = JSON.parse(atob(base64)); + if (typeof decoded !== "object" || decoded === null) + return false; + if ("typ" in decoded && decoded?.typ !== "JWT") + return false; + if (!decoded.alg) + return false; + if (alg && decoded.alg !== alg) + return false; + return true; + } catch { + return false; + } +} +function isValidCidr(ip, version) { + if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) { + return true; + } + if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) { + return true; + } + return false; +} +var ZodString = class _ZodString extends ZodType { + _parse(input) { + if (this._def.coerce) { + input.data = String(input.data); + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.string) { + const ctx2 = this._getOrReturnCtx(input); + addIssueToContext(ctx2, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.string, + received: ctx2.parsedType + }); + return INVALID; + } + const status = new ParseStatus(); + let ctx = void 0; + for (const check of this._def.checks) { + if (check.kind === "min") { + if (input.data.length < check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: check.value, + type: "string", + inclusive: true, + exact: false, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + if (input.data.length > check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: check.value, + type: "string", + inclusive: true, + exact: false, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "length") { + const tooBig = input.data.length > check.value; + const tooSmall = input.data.length < check.value; + if (tooBig || tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + if (tooBig) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: check.value, + type: "string", + inclusive: true, + exact: true, + message: check.message + }); + } else if (tooSmall) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: check.value, + type: "string", + inclusive: true, + exact: true, + message: check.message + }); + } + status.dirty(); + } + } else if (check.kind === "email") { + if (!emailRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "email", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "emoji") { + if (!emojiRegex) { + emojiRegex = new RegExp(_emojiRegex, "u"); + } + if (!emojiRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "emoji", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "uuid") { + if (!uuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "uuid", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "nanoid") { + if (!nanoidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "nanoid", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "cuid") { + if (!cuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "cuid", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "cuid2") { + if (!cuid2Regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "cuid2", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "ulid") { + if (!ulidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "ulid", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "url") { + try { + new URL(input.data); + } catch { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "url", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "regex") { + check.regex.lastIndex = 0; + const testResult = check.regex.test(input.data); + if (!testResult) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "regex", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "trim") { + input.data = input.data.trim(); + } else if (check.kind === "includes") { + if (!input.data.includes(check.value, check.position)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: { includes: check.value, position: check.position }, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "toLowerCase") { + input.data = input.data.toLowerCase(); + } else if (check.kind === "toUpperCase") { + input.data = input.data.toUpperCase(); + } else if (check.kind === "startsWith") { + if (!input.data.startsWith(check.value)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: { startsWith: check.value }, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "endsWith") { + if (!input.data.endsWith(check.value)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: { endsWith: check.value }, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "datetime") { + const regex = datetimeRegex(check); + if (!regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: "datetime", + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "date") { + const regex = dateRegex; + if (!regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: "date", + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "time") { + const regex = timeRegex(check); + if (!regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: "time", + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "duration") { + if (!durationRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "duration", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "ip") { + if (!isValidIP(input.data, check.version)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "ip", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "jwt") { + if (!isValidJWT(input.data, check.alg)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "jwt", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "cidr") { + if (!isValidCidr(input.data, check.version)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "cidr", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "base64") { + if (!base64Regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "base64", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "base64url") { + if (!base64urlRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "base64url", + code: ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + return { status: status.value, value: input.data }; + } + _regex(regex, validation, message) { + return this.refinement((data) => regex.test(data), { + validation, + code: ZodIssueCode.invalid_string, + ...errorUtil.errToObj(message) + }); + } + _addCheck(check) { + return new _ZodString({ + ...this._def, + checks: [...this._def.checks, check] + }); + } + email(message) { + return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) }); + } + url(message) { + return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) }); + } + emoji(message) { + return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) }); + } + uuid(message) { + return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) }); + } + nanoid(message) { + return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) }); + } + cuid(message) { + return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) }); + } + cuid2(message) { + return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) }); + } + ulid(message) { + return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) }); + } + base64(message) { + return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) }); + } + base64url(message) { + return this._addCheck({ + kind: "base64url", + ...errorUtil.errToObj(message) + }); + } + jwt(options) { + return this._addCheck({ kind: "jwt", ...errorUtil.errToObj(options) }); + } + ip(options) { + return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) }); + } + cidr(options) { + return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) }); + } + datetime(options) { + if (typeof options === "string") { + return this._addCheck({ + kind: "datetime", + precision: null, + offset: false, + local: false, + message: options + }); + } + return this._addCheck({ + kind: "datetime", + precision: typeof options?.precision === "undefined" ? null : options?.precision, + offset: options?.offset ?? false, + local: options?.local ?? false, + ...errorUtil.errToObj(options?.message) + }); + } + date(message) { + return this._addCheck({ kind: "date", message }); + } + time(options) { + if (typeof options === "string") { + return this._addCheck({ + kind: "time", + precision: null, + message: options + }); + } + return this._addCheck({ + kind: "time", + precision: typeof options?.precision === "undefined" ? null : options?.precision, + ...errorUtil.errToObj(options?.message) + }); + } + duration(message) { + return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) }); + } + regex(regex, message) { + return this._addCheck({ + kind: "regex", + regex, + ...errorUtil.errToObj(message) + }); + } + includes(value, options) { + return this._addCheck({ + kind: "includes", + value, + position: options?.position, + ...errorUtil.errToObj(options?.message) + }); + } + startsWith(value, message) { + return this._addCheck({ + kind: "startsWith", + value, + ...errorUtil.errToObj(message) + }); + } + endsWith(value, message) { + return this._addCheck({ + kind: "endsWith", + value, + ...errorUtil.errToObj(message) + }); + } + min(minLength, message) { + return this._addCheck({ + kind: "min", + value: minLength, + ...errorUtil.errToObj(message) + }); + } + max(maxLength, message) { + return this._addCheck({ + kind: "max", + value: maxLength, + ...errorUtil.errToObj(message) + }); + } + length(len, message) { + return this._addCheck({ + kind: "length", + value: len, + ...errorUtil.errToObj(message) + }); + } + /** + * Equivalent to `.min(1)` + */ + nonempty(message) { + return this.min(1, errorUtil.errToObj(message)); + } + trim() { + return new _ZodString({ + ...this._def, + checks: [...this._def.checks, { kind: "trim" }] + }); + } + toLowerCase() { + return new _ZodString({ + ...this._def, + checks: [...this._def.checks, { kind: "toLowerCase" }] + }); + } + toUpperCase() { + return new _ZodString({ + ...this._def, + checks: [...this._def.checks, { kind: "toUpperCase" }] + }); + } + get isDatetime() { + return !!this._def.checks.find((ch) => ch.kind === "datetime"); + } + get isDate() { + return !!this._def.checks.find((ch) => ch.kind === "date"); + } + get isTime() { + return !!this._def.checks.find((ch) => ch.kind === "time"); + } + get isDuration() { + return !!this._def.checks.find((ch) => ch.kind === "duration"); + } + get isEmail() { + return !!this._def.checks.find((ch) => ch.kind === "email"); + } + get isURL() { + return !!this._def.checks.find((ch) => ch.kind === "url"); + } + get isEmoji() { + return !!this._def.checks.find((ch) => ch.kind === "emoji"); + } + get isUUID() { + return !!this._def.checks.find((ch) => ch.kind === "uuid"); + } + get isNANOID() { + return !!this._def.checks.find((ch) => ch.kind === "nanoid"); + } + get isCUID() { + return !!this._def.checks.find((ch) => ch.kind === "cuid"); + } + get isCUID2() { + return !!this._def.checks.find((ch) => ch.kind === "cuid2"); + } + get isULID() { + return !!this._def.checks.find((ch) => ch.kind === "ulid"); + } + get isIP() { + return !!this._def.checks.find((ch) => ch.kind === "ip"); + } + get isCIDR() { + return !!this._def.checks.find((ch) => ch.kind === "cidr"); + } + get isBase64() { + return !!this._def.checks.find((ch) => ch.kind === "base64"); + } + get isBase64url() { + return !!this._def.checks.find((ch) => ch.kind === "base64url"); + } + get minLength() { + let min = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) + min = ch.value; + } + } + return min; + } + get maxLength() { + let max = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) + max = ch.value; + } + } + return max; + } +}; +ZodString.create = (params) => { + return new ZodString({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodString, + coerce: params?.coerce ?? false, + ...processCreateParams(params) + }); +}; +function floatSafeRemainder(val, step) { + const valDecCount = (val.toString().split(".")[1] || "").length; + const stepDecCount = (step.toString().split(".")[1] || "").length; + const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; + const valInt = Number.parseInt(val.toFixed(decCount).replace(".", "")); + const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", "")); + return valInt % stepInt / 10 ** decCount; +} +var ZodNumber = class _ZodNumber extends ZodType { + constructor() { + super(...arguments); + this.min = this.gte; + this.max = this.lte; + this.step = this.multipleOf; + } + _parse(input) { + if (this._def.coerce) { + input.data = Number(input.data); + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.number) { + const ctx2 = this._getOrReturnCtx(input); + addIssueToContext(ctx2, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.number, + received: ctx2.parsedType + }); + return INVALID; + } + let ctx = void 0; + const status = new ParseStatus(); + for (const check of this._def.checks) { + if (check.kind === "int") { + if (!util.isInteger(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: "integer", + received: "float", + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "min") { + const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; + if (tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: check.value, + type: "number", + inclusive: check.inclusive, + exact: false, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; + if (tooBig) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: check.value, + type: "number", + inclusive: check.inclusive, + exact: false, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "multipleOf") { + if (floatSafeRemainder(input.data, check.value) !== 0) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.not_multiple_of, + multipleOf: check.value, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "finite") { + if (!Number.isFinite(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.not_finite, + message: check.message + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + return { status: status.value, value: input.data }; + } + gte(value, message) { + return this.setLimit("min", value, true, errorUtil.toString(message)); + } + gt(value, message) { + return this.setLimit("min", value, false, errorUtil.toString(message)); + } + lte(value, message) { + return this.setLimit("max", value, true, errorUtil.toString(message)); + } + lt(value, message) { + return this.setLimit("max", value, false, errorUtil.toString(message)); + } + setLimit(kind, value, inclusive, message) { + return new _ZodNumber({ + ...this._def, + checks: [ + ...this._def.checks, + { + kind, + value, + inclusive, + message: errorUtil.toString(message) + } + ] + }); + } + _addCheck(check) { + return new _ZodNumber({ + ...this._def, + checks: [...this._def.checks, check] + }); + } + int(message) { + return this._addCheck({ + kind: "int", + message: errorUtil.toString(message) + }); + } + positive(message) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: false, + message: errorUtil.toString(message) + }); + } + negative(message) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: false, + message: errorUtil.toString(message) + }); + } + nonpositive(message) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: true, + message: errorUtil.toString(message) + }); + } + nonnegative(message) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: true, + message: errorUtil.toString(message) + }); + } + multipleOf(value, message) { + return this._addCheck({ + kind: "multipleOf", + value, + message: errorUtil.toString(message) + }); + } + finite(message) { + return this._addCheck({ + kind: "finite", + message: errorUtil.toString(message) + }); + } + safe(message) { + return this._addCheck({ + kind: "min", + inclusive: true, + value: Number.MIN_SAFE_INTEGER, + message: errorUtil.toString(message) + })._addCheck({ + kind: "max", + inclusive: true, + value: Number.MAX_SAFE_INTEGER, + message: errorUtil.toString(message) + }); + } + get minValue() { + let min = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) + min = ch.value; + } + } + return min; + } + get maxValue() { + let max = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) + max = ch.value; + } + } + return max; + } + get isInt() { + return !!this._def.checks.find((ch) => ch.kind === "int" || ch.kind === "multipleOf" && util.isInteger(ch.value)); + } + get isFinite() { + let max = null; + let min = null; + for (const ch of this._def.checks) { + if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") { + return true; + } else if (ch.kind === "min") { + if (min === null || ch.value > min) + min = ch.value; + } else if (ch.kind === "max") { + if (max === null || ch.value < max) + max = ch.value; + } + } + return Number.isFinite(min) && Number.isFinite(max); + } +}; +ZodNumber.create = (params) => { + return new ZodNumber({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodNumber, + coerce: params?.coerce || false, + ...processCreateParams(params) + }); +}; +var ZodBigInt = class _ZodBigInt extends ZodType { + constructor() { + super(...arguments); + this.min = this.gte; + this.max = this.lte; + } + _parse(input) { + if (this._def.coerce) { + try { + input.data = BigInt(input.data); + } catch { + return this._getInvalidInput(input); + } + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.bigint) { + return this._getInvalidInput(input); + } + let ctx = void 0; + const status = new ParseStatus(); + for (const check of this._def.checks) { + if (check.kind === "min") { + const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; + if (tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + type: "bigint", + minimum: check.value, + inclusive: check.inclusive, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; + if (tooBig) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + type: "bigint", + maximum: check.value, + inclusive: check.inclusive, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "multipleOf") { + if (input.data % check.value !== BigInt(0)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.not_multiple_of, + multipleOf: check.value, + message: check.message + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + return { status: status.value, value: input.data }; + } + _getInvalidInput(input) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.bigint, + received: ctx.parsedType + }); + return INVALID; + } + gte(value, message) { + return this.setLimit("min", value, true, errorUtil.toString(message)); + } + gt(value, message) { + return this.setLimit("min", value, false, errorUtil.toString(message)); + } + lte(value, message) { + return this.setLimit("max", value, true, errorUtil.toString(message)); + } + lt(value, message) { + return this.setLimit("max", value, false, errorUtil.toString(message)); + } + setLimit(kind, value, inclusive, message) { + return new _ZodBigInt({ + ...this._def, + checks: [ + ...this._def.checks, + { + kind, + value, + inclusive, + message: errorUtil.toString(message) + } + ] + }); + } + _addCheck(check) { + return new _ZodBigInt({ + ...this._def, + checks: [...this._def.checks, check] + }); + } + positive(message) { + return this._addCheck({ + kind: "min", + value: BigInt(0), + inclusive: false, + message: errorUtil.toString(message) + }); + } + negative(message) { + return this._addCheck({ + kind: "max", + value: BigInt(0), + inclusive: false, + message: errorUtil.toString(message) + }); + } + nonpositive(message) { + return this._addCheck({ + kind: "max", + value: BigInt(0), + inclusive: true, + message: errorUtil.toString(message) + }); + } + nonnegative(message) { + return this._addCheck({ + kind: "min", + value: BigInt(0), + inclusive: true, + message: errorUtil.toString(message) + }); + } + multipleOf(value, message) { + return this._addCheck({ + kind: "multipleOf", + value, + message: errorUtil.toString(message) + }); + } + get minValue() { + let min = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) + min = ch.value; + } + } + return min; + } + get maxValue() { + let max = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) + max = ch.value; + } + } + return max; + } +}; +ZodBigInt.create = (params) => { + return new ZodBigInt({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodBigInt, + coerce: params?.coerce ?? false, + ...processCreateParams(params) + }); +}; +var ZodBoolean = class extends ZodType { + _parse(input) { + if (this._def.coerce) { + input.data = Boolean(input.data); + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.boolean) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.boolean, + received: ctx.parsedType + }); + return INVALID; + } + return OK(input.data); + } +}; +ZodBoolean.create = (params) => { + return new ZodBoolean({ + typeName: ZodFirstPartyTypeKind.ZodBoolean, + coerce: params?.coerce || false, + ...processCreateParams(params) + }); +}; +var ZodDate = class _ZodDate extends ZodType { + _parse(input) { + if (this._def.coerce) { + input.data = new Date(input.data); + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.date) { + const ctx2 = this._getOrReturnCtx(input); + addIssueToContext(ctx2, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.date, + received: ctx2.parsedType + }); + return INVALID; + } + if (Number.isNaN(input.data.getTime())) { + const ctx2 = this._getOrReturnCtx(input); + addIssueToContext(ctx2, { + code: ZodIssueCode.invalid_date + }); + return INVALID; + } + const status = new ParseStatus(); + let ctx = void 0; + for (const check of this._def.checks) { + if (check.kind === "min") { + if (input.data.getTime() < check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + message: check.message, + inclusive: true, + exact: false, + minimum: check.value, + type: "date" + }); + status.dirty(); + } + } else if (check.kind === "max") { + if (input.data.getTime() > check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + message: check.message, + inclusive: true, + exact: false, + maximum: check.value, + type: "date" + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + return { + status: status.value, + value: new Date(input.data.getTime()) + }; + } + _addCheck(check) { + return new _ZodDate({ + ...this._def, + checks: [...this._def.checks, check] + }); + } + min(minDate, message) { + return this._addCheck({ + kind: "min", + value: minDate.getTime(), + message: errorUtil.toString(message) + }); + } + max(maxDate, message) { + return this._addCheck({ + kind: "max", + value: maxDate.getTime(), + message: errorUtil.toString(message) + }); + } + get minDate() { + let min = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) + min = ch.value; + } + } + return min != null ? new Date(min) : null; + } + get maxDate() { + let max = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) + max = ch.value; + } + } + return max != null ? new Date(max) : null; + } +}; +ZodDate.create = (params) => { + return new ZodDate({ + checks: [], + coerce: params?.coerce || false, + typeName: ZodFirstPartyTypeKind.ZodDate, + ...processCreateParams(params) + }); +}; +var ZodSymbol = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.symbol) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.symbol, + received: ctx.parsedType + }); + return INVALID; + } + return OK(input.data); + } +}; +ZodSymbol.create = (params) => { + return new ZodSymbol({ + typeName: ZodFirstPartyTypeKind.ZodSymbol, + ...processCreateParams(params) + }); +}; +var ZodUndefined = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.undefined) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.undefined, + received: ctx.parsedType + }); + return INVALID; + } + return OK(input.data); + } +}; +ZodUndefined.create = (params) => { + return new ZodUndefined({ + typeName: ZodFirstPartyTypeKind.ZodUndefined, + ...processCreateParams(params) + }); +}; +var ZodNull = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.null) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.null, + received: ctx.parsedType + }); + return INVALID; + } + return OK(input.data); + } +}; +ZodNull.create = (params) => { + return new ZodNull({ + typeName: ZodFirstPartyTypeKind.ZodNull, + ...processCreateParams(params) + }); +}; +var ZodAny = class extends ZodType { + constructor() { + super(...arguments); + this._any = true; + } + _parse(input) { + return OK(input.data); + } +}; +ZodAny.create = (params) => { + return new ZodAny({ + typeName: ZodFirstPartyTypeKind.ZodAny, + ...processCreateParams(params) + }); +}; +var ZodUnknown = class extends ZodType { + constructor() { + super(...arguments); + this._unknown = true; + } + _parse(input) { + return OK(input.data); + } +}; +ZodUnknown.create = (params) => { + return new ZodUnknown({ + typeName: ZodFirstPartyTypeKind.ZodUnknown, + ...processCreateParams(params) + }); +}; +var ZodNever = class extends ZodType { + _parse(input) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.never, + received: ctx.parsedType + }); + return INVALID; + } +}; +ZodNever.create = (params) => { + return new ZodNever({ + typeName: ZodFirstPartyTypeKind.ZodNever, + ...processCreateParams(params) + }); +}; +var ZodVoid = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.undefined) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.void, + received: ctx.parsedType + }); + return INVALID; + } + return OK(input.data); + } +}; +ZodVoid.create = (params) => { + return new ZodVoid({ + typeName: ZodFirstPartyTypeKind.ZodVoid, + ...processCreateParams(params) + }); +}; +var ZodArray = class _ZodArray extends ZodType { + _parse(input) { + const { ctx, status } = this._processInputParams(input); + const def = this._def; + if (ctx.parsedType !== ZodParsedType.array) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.array, + received: ctx.parsedType + }); + return INVALID; + } + if (def.exactLength !== null) { + const tooBig = ctx.data.length > def.exactLength.value; + const tooSmall = ctx.data.length < def.exactLength.value; + if (tooBig || tooSmall) { + addIssueToContext(ctx, { + code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small, + minimum: tooSmall ? def.exactLength.value : void 0, + maximum: tooBig ? def.exactLength.value : void 0, + type: "array", + inclusive: true, + exact: true, + message: def.exactLength.message + }); + status.dirty(); + } + } + if (def.minLength !== null) { + if (ctx.data.length < def.minLength.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: def.minLength.value, + type: "array", + inclusive: true, + exact: false, + message: def.minLength.message + }); + status.dirty(); + } + } + if (def.maxLength !== null) { + if (ctx.data.length > def.maxLength.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: def.maxLength.value, + type: "array", + inclusive: true, + exact: false, + message: def.maxLength.message + }); + status.dirty(); + } + } + if (ctx.common.async) { + return Promise.all([...ctx.data].map((item, i2) => { + return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i2)); + })).then((result2) => { + return ParseStatus.mergeArray(status, result2); + }); + } + const result = [...ctx.data].map((item, i2) => { + return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i2)); + }); + return ParseStatus.mergeArray(status, result); + } + get element() { + return this._def.type; + } + min(minLength, message) { + return new _ZodArray({ + ...this._def, + minLength: { value: minLength, message: errorUtil.toString(message) } + }); + } + max(maxLength, message) { + return new _ZodArray({ + ...this._def, + maxLength: { value: maxLength, message: errorUtil.toString(message) } + }); + } + length(len, message) { + return new _ZodArray({ + ...this._def, + exactLength: { value: len, message: errorUtil.toString(message) } + }); + } + nonempty(message) { + return this.min(1, message); + } +}; +ZodArray.create = (schema, params) => { + return new ZodArray({ + type: schema, + minLength: null, + maxLength: null, + exactLength: null, + typeName: ZodFirstPartyTypeKind.ZodArray, + ...processCreateParams(params) + }); +}; +function deepPartialify(schema) { + if (schema instanceof ZodObject) { + const newShape = {}; + for (const key in schema.shape) { + const fieldSchema = schema.shape[key]; + newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); + } + return new ZodObject({ + ...schema._def, + shape: () => newShape + }); + } else if (schema instanceof ZodArray) { + return new ZodArray({ + ...schema._def, + type: deepPartialify(schema.element) + }); + } else if (schema instanceof ZodOptional) { + return ZodOptional.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodNullable) { + return ZodNullable.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodTuple) { + return ZodTuple.create(schema.items.map((item) => deepPartialify(item))); + } else { + return schema; + } +} +var ZodObject = class _ZodObject extends ZodType { + constructor() { + super(...arguments); + this._cached = null; + this.nonstrict = this.passthrough; + this.augment = this.extend; + } + _getCached() { + if (this._cached !== null) + return this._cached; + const shape = this._def.shape(); + const keys = util.objectKeys(shape); + this._cached = { shape, keys }; + return this._cached; + } + _parse(input) { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.object) { + const ctx2 = this._getOrReturnCtx(input); + addIssueToContext(ctx2, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ctx2.parsedType + }); + return INVALID; + } + const { status, ctx } = this._processInputParams(input); + const { shape, keys: shapeKeys } = this._getCached(); + const extraKeys = []; + if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) { + for (const key in ctx.data) { + if (!shapeKeys.includes(key)) { + extraKeys.push(key); + } + } + } + const pairs = []; + for (const key of shapeKeys) { + const keyValidator = shape[key]; + const value = ctx.data[key]; + pairs.push({ + key: { status: "valid", value: key }, + value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), + alwaysSet: key in ctx.data + }); + } + if (this._def.catchall instanceof ZodNever) { + const unknownKeys = this._def.unknownKeys; + if (unknownKeys === "passthrough") { + for (const key of extraKeys) { + pairs.push({ + key: { status: "valid", value: key }, + value: { status: "valid", value: ctx.data[key] } + }); + } + } else if (unknownKeys === "strict") { + if (extraKeys.length > 0) { + addIssueToContext(ctx, { + code: ZodIssueCode.unrecognized_keys, + keys: extraKeys + }); + status.dirty(); + } + } else if (unknownKeys === "strip") { + } else { + throw new Error(`Internal ZodObject error: invalid unknownKeys value.`); + } + } else { + const catchall = this._def.catchall; + for (const key of extraKeys) { + const value = ctx.data[key]; + pairs.push({ + key: { status: "valid", value: key }, + value: catchall._parse( + new ParseInputLazyPath(ctx, value, ctx.path, key) + //, ctx.child(key), value, getParsedType(value) + ), + alwaysSet: key in ctx.data + }); + } + } + if (ctx.common.async) { + return Promise.resolve().then(async () => { + const syncPairs = []; + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; + syncPairs.push({ + key, + value, + alwaysSet: pair.alwaysSet + }); + } + return syncPairs; + }).then((syncPairs) => { + return ParseStatus.mergeObjectSync(status, syncPairs); + }); + } else { + return ParseStatus.mergeObjectSync(status, pairs); + } + } + get shape() { + return this._def.shape(); + } + strict(message) { + errorUtil.errToObj; + return new _ZodObject({ + ...this._def, + unknownKeys: "strict", + ...message !== void 0 ? { + errorMap: (issue, ctx) => { + const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError; + if (issue.code === "unrecognized_keys") + return { + message: errorUtil.errToObj(message).message ?? defaultError + }; + return { + message: defaultError + }; + } + } : {} + }); + } + strip() { + return new _ZodObject({ + ...this._def, + unknownKeys: "strip" + }); + } + passthrough() { + return new _ZodObject({ + ...this._def, + unknownKeys: "passthrough" + }); + } + // const AugmentFactory = + // (def: Def) => + // ( + // augmentation: Augmentation + // ): ZodObject< + // extendShape, Augmentation>, + // Def["unknownKeys"], + // Def["catchall"] + // > => { + // return new ZodObject({ + // ...def, + // shape: () => ({ + // ...def.shape(), + // ...augmentation, + // }), + // }) as any; + // }; + extend(augmentation) { + return new _ZodObject({ + ...this._def, + shape: () => ({ + ...this._def.shape(), + ...augmentation + }) + }); + } + /** + * Prior to zod@1.0.12 there was a bug in the + * inferred type of merged objects. Please + * upgrade if you are experiencing issues. + */ + merge(merging) { + const merged = new _ZodObject({ + unknownKeys: merging._def.unknownKeys, + catchall: merging._def.catchall, + shape: () => ({ + ...this._def.shape(), + ...merging._def.shape() + }), + typeName: ZodFirstPartyTypeKind.ZodObject + }); + return merged; + } + // merge< + // Incoming extends AnyZodObject, + // Augmentation extends Incoming["shape"], + // NewOutput extends { + // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation + // ? Augmentation[k]["_output"] + // : k extends keyof Output + // ? Output[k] + // : never; + // }, + // NewInput extends { + // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation + // ? Augmentation[k]["_input"] + // : k extends keyof Input + // ? Input[k] + // : never; + // } + // >( + // merging: Incoming + // ): ZodObject< + // extendShape>, + // Incoming["_def"]["unknownKeys"], + // Incoming["_def"]["catchall"], + // NewOutput, + // NewInput + // > { + // const merged: any = new ZodObject({ + // unknownKeys: merging._def.unknownKeys, + // catchall: merging._def.catchall, + // shape: () => + // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), + // typeName: ZodFirstPartyTypeKind.ZodObject, + // }) as any; + // return merged; + // } + setKey(key, schema) { + return this.augment({ [key]: schema }); + } + // merge( + // merging: Incoming + // ): //ZodObject = (merging) => { + // ZodObject< + // extendShape>, + // Incoming["_def"]["unknownKeys"], + // Incoming["_def"]["catchall"] + // > { + // // const mergedShape = objectUtil.mergeShapes( + // // this._def.shape(), + // // merging._def.shape() + // // ); + // const merged: any = new ZodObject({ + // unknownKeys: merging._def.unknownKeys, + // catchall: merging._def.catchall, + // shape: () => + // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), + // typeName: ZodFirstPartyTypeKind.ZodObject, + // }) as any; + // return merged; + // } + catchall(index) { + return new _ZodObject({ + ...this._def, + catchall: index + }); + } + pick(mask) { + const shape = {}; + for (const key of util.objectKeys(mask)) { + if (mask[key] && this.shape[key]) { + shape[key] = this.shape[key]; + } + } + return new _ZodObject({ + ...this._def, + shape: () => shape + }); + } + omit(mask) { + const shape = {}; + for (const key of util.objectKeys(this.shape)) { + if (!mask[key]) { + shape[key] = this.shape[key]; + } + } + return new _ZodObject({ + ...this._def, + shape: () => shape + }); + } + /** + * @deprecated + */ + deepPartial() { + return deepPartialify(this); + } + partial(mask) { + const newShape = {}; + for (const key of util.objectKeys(this.shape)) { + const fieldSchema = this.shape[key]; + if (mask && !mask[key]) { + newShape[key] = fieldSchema; + } else { + newShape[key] = fieldSchema.optional(); + } + } + return new _ZodObject({ + ...this._def, + shape: () => newShape + }); + } + required(mask) { + const newShape = {}; + for (const key of util.objectKeys(this.shape)) { + if (mask && !mask[key]) { + newShape[key] = this.shape[key]; + } else { + const fieldSchema = this.shape[key]; + let newField = fieldSchema; + while (newField instanceof ZodOptional) { + newField = newField._def.innerType; + } + newShape[key] = newField; + } + } + return new _ZodObject({ + ...this._def, + shape: () => newShape + }); + } + keyof() { + return createZodEnum(util.objectKeys(this.shape)); + } +}; +ZodObject.create = (shape, params) => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; +ZodObject.strictCreate = (shape, params) => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strict", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; +ZodObject.lazycreate = (shape, params) => { + return new ZodObject({ + shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; +var ZodUnion = class extends ZodType { + _parse(input) { + const { ctx } = this._processInputParams(input); + const options = this._def.options; + function handleResults(results) { + for (const result of results) { + if (result.result.status === "valid") { + return result.result; + } + } + for (const result of results) { + if (result.result.status === "dirty") { + ctx.common.issues.push(...result.ctx.common.issues); + return result.result; + } + } + const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues)); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_union, + unionErrors + }); + return INVALID; + } + if (ctx.common.async) { + return Promise.all(options.map(async (option) => { + const childCtx = { + ...ctx, + common: { + ...ctx.common, + issues: [] + }, + parent: null + }; + return { + result: await option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: childCtx + }), + ctx: childCtx + }; + })).then(handleResults); + } else { + let dirty = void 0; + const issues = []; + for (const option of options) { + const childCtx = { + ...ctx, + common: { + ...ctx.common, + issues: [] + }, + parent: null + }; + const result = option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: childCtx + }); + if (result.status === "valid") { + return result; + } else if (result.status === "dirty" && !dirty) { + dirty = { result, ctx: childCtx }; + } + if (childCtx.common.issues.length) { + issues.push(childCtx.common.issues); + } + } + if (dirty) { + ctx.common.issues.push(...dirty.ctx.common.issues); + return dirty.result; + } + const unionErrors = issues.map((issues2) => new ZodError(issues2)); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_union, + unionErrors + }); + return INVALID; + } + } + get options() { + return this._def.options; + } +}; +ZodUnion.create = (types, params) => { + return new ZodUnion({ + options: types, + typeName: ZodFirstPartyTypeKind.ZodUnion, + ...processCreateParams(params) + }); +}; +var getDiscriminator = (type) => { + if (type instanceof ZodLazy) { + return getDiscriminator(type.schema); + } else if (type instanceof ZodEffects) { + return getDiscriminator(type.innerType()); + } else if (type instanceof ZodLiteral) { + return [type.value]; + } else if (type instanceof ZodEnum) { + return type.options; + } else if (type instanceof ZodNativeEnum) { + return util.objectValues(type.enum); + } else if (type instanceof ZodDefault) { + return getDiscriminator(type._def.innerType); + } else if (type instanceof ZodUndefined) { + return [void 0]; + } else if (type instanceof ZodNull) { + return [null]; + } else if (type instanceof ZodOptional) { + return [void 0, ...getDiscriminator(type.unwrap())]; + } else if (type instanceof ZodNullable) { + return [null, ...getDiscriminator(type.unwrap())]; + } else if (type instanceof ZodBranded) { + return getDiscriminator(type.unwrap()); + } else if (type instanceof ZodReadonly) { + return getDiscriminator(type.unwrap()); + } else if (type instanceof ZodCatch) { + return getDiscriminator(type._def.innerType); + } else { + return []; + } +}; +var ZodDiscriminatedUnion = class _ZodDiscriminatedUnion extends ZodType { + _parse(input) { + const { ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.object) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ctx.parsedType + }); + return INVALID; + } + const discriminator = this.discriminator; + const discriminatorValue = ctx.data[discriminator]; + const option = this.optionsMap.get(discriminatorValue); + if (!option) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_union_discriminator, + options: Array.from(this.optionsMap.keys()), + path: [discriminator] + }); + return INVALID; + } + if (ctx.common.async) { + return option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + } else { + return option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + } + } + get discriminator() { + return this._def.discriminator; + } + get options() { + return this._def.options; + } + get optionsMap() { + return this._def.optionsMap; + } + /** + * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. + * However, it only allows a union of objects, all of which need to share a discriminator property. This property must + * have a different value for each object in the union. + * @param discriminator the name of the discriminator property + * @param types an array of object schemas + * @param params + */ + static create(discriminator, options, params) { + const optionsMap = /* @__PURE__ */ new Map(); + for (const type of options) { + const discriminatorValues = getDiscriminator(type.shape[discriminator]); + if (!discriminatorValues.length) { + throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`); + } + for (const value of discriminatorValues) { + if (optionsMap.has(value)) { + throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`); + } + optionsMap.set(value, type); + } + } + return new _ZodDiscriminatedUnion({ + typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, + discriminator, + options, + optionsMap, + ...processCreateParams(params) + }); + } +}; +function mergeValues(a2, b) { + const aType = getParsedType(a2); + const bType = getParsedType(b); + if (a2 === b) { + return { valid: true, data: a2 }; + } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) { + const bKeys = util.objectKeys(b); + const sharedKeys = util.objectKeys(a2).filter((key) => bKeys.indexOf(key) !== -1); + const newObj = { ...a2, ...b }; + for (const key of sharedKeys) { + const sharedValue = mergeValues(a2[key], b[key]); + if (!sharedValue.valid) { + return { valid: false }; + } + newObj[key] = sharedValue.data; + } + return { valid: true, data: newObj }; + } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) { + if (a2.length !== b.length) { + return { valid: false }; + } + const newArray = []; + for (let index = 0; index < a2.length; index++) { + const itemA = a2[index]; + const itemB = b[index]; + const sharedValue = mergeValues(itemA, itemB); + if (!sharedValue.valid) { + return { valid: false }; + } + newArray.push(sharedValue.data); + } + return { valid: true, data: newArray }; + } else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a2 === +b) { + return { valid: true, data: a2 }; + } else { + return { valid: false }; + } +} +var ZodIntersection = class extends ZodType { + _parse(input) { + const { status, ctx } = this._processInputParams(input); + const handleParsed = (parsedLeft, parsedRight) => { + if (isAborted(parsedLeft) || isAborted(parsedRight)) { + return INVALID; + } + const merged = mergeValues(parsedLeft.value, parsedRight.value); + if (!merged.valid) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_intersection_types + }); + return INVALID; + } + if (isDirty(parsedLeft) || isDirty(parsedRight)) { + status.dirty(); + } + return { status: status.value, value: merged.data }; + }; + if (ctx.common.async) { + return Promise.all([ + this._def.left._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }), + this._def.right._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }) + ]).then(([left, right]) => handleParsed(left, right)); + } else { + return handleParsed(this._def.left._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }), this._def.right._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + })); + } + } +}; +ZodIntersection.create = (left, right, params) => { + return new ZodIntersection({ + left, + right, + typeName: ZodFirstPartyTypeKind.ZodIntersection, + ...processCreateParams(params) + }); +}; +var ZodTuple = class _ZodTuple extends ZodType { + _parse(input) { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.array) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.array, + received: ctx.parsedType + }); + return INVALID; + } + if (ctx.data.length < this._def.items.length) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: this._def.items.length, + inclusive: true, + exact: false, + type: "array" + }); + return INVALID; + } + const rest = this._def.rest; + if (!rest && ctx.data.length > this._def.items.length) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: this._def.items.length, + inclusive: true, + exact: false, + type: "array" + }); + status.dirty(); + } + const items = [...ctx.data].map((item, itemIndex) => { + const schema = this._def.items[itemIndex] || this._def.rest; + if (!schema) + return null; + return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); + }).filter((x) => !!x); + if (ctx.common.async) { + return Promise.all(items).then((results) => { + return ParseStatus.mergeArray(status, results); + }); + } else { + return ParseStatus.mergeArray(status, items); + } + } + get items() { + return this._def.items; + } + rest(rest) { + return new _ZodTuple({ + ...this._def, + rest + }); + } +}; +ZodTuple.create = (schemas, params) => { + if (!Array.isArray(schemas)) { + throw new Error("You must pass an array of schemas to z.tuple([ ... ])"); + } + return new ZodTuple({ + items: schemas, + typeName: ZodFirstPartyTypeKind.ZodTuple, + rest: null, + ...processCreateParams(params) + }); +}; +var ZodRecord = class _ZodRecord extends ZodType { + get keySchema() { + return this._def.keyType; + } + get valueSchema() { + return this._def.valueType; + } + _parse(input) { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.object) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ctx.parsedType + }); + return INVALID; + } + const pairs = []; + const keyType = this._def.keyType; + const valueType = this._def.valueType; + for (const key in ctx.data) { + pairs.push({ + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), + value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)), + alwaysSet: key in ctx.data + }); + } + if (ctx.common.async) { + return ParseStatus.mergeObjectAsync(status, pairs); + } else { + return ParseStatus.mergeObjectSync(status, pairs); + } + } + get element() { + return this._def.valueType; + } + static create(first, second, third) { + if (second instanceof ZodType) { + return new _ZodRecord({ + keyType: first, + valueType: second, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(third) + }); + } + return new _ZodRecord({ + keyType: ZodString.create(), + valueType: first, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(second) + }); + } +}; +var ZodMap = class extends ZodType { + get keySchema() { + return this._def.keyType; + } + get valueSchema() { + return this._def.valueType; + } + _parse(input) { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.map) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.map, + received: ctx.parsedType + }); + return INVALID; + } + const keyType = this._def.keyType; + const valueType = this._def.valueType; + const pairs = [...ctx.data.entries()].map(([key, value], index) => { + return { + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), + value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])) + }; + }); + if (ctx.common.async) { + const finalMap = /* @__PURE__ */ new Map(); + return Promise.resolve().then(async () => { + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; + if (key.status === "aborted" || value.status === "aborted") { + return INVALID; + } + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } + finalMap.set(key.value, value.value); + } + return { status: status.value, value: finalMap }; + }); + } else { + const finalMap = /* @__PURE__ */ new Map(); + for (const pair of pairs) { + const key = pair.key; + const value = pair.value; + if (key.status === "aborted" || value.status === "aborted") { + return INVALID; + } + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } + finalMap.set(key.value, value.value); + } + return { status: status.value, value: finalMap }; + } + } +}; +ZodMap.create = (keyType, valueType, params) => { + return new ZodMap({ + valueType, + keyType, + typeName: ZodFirstPartyTypeKind.ZodMap, + ...processCreateParams(params) + }); +}; +var ZodSet = class _ZodSet extends ZodType { + _parse(input) { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.set) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.set, + received: ctx.parsedType + }); + return INVALID; + } + const def = this._def; + if (def.minSize !== null) { + if (ctx.data.size < def.minSize.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: def.minSize.value, + type: "set", + inclusive: true, + exact: false, + message: def.minSize.message + }); + status.dirty(); + } + } + if (def.maxSize !== null) { + if (ctx.data.size > def.maxSize.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: def.maxSize.value, + type: "set", + inclusive: true, + exact: false, + message: def.maxSize.message + }); + status.dirty(); + } + } + const valueType = this._def.valueType; + function finalizeSet(elements2) { + const parsedSet = /* @__PURE__ */ new Set(); + for (const element of elements2) { + if (element.status === "aborted") + return INVALID; + if (element.status === "dirty") + status.dirty(); + parsedSet.add(element.value); + } + return { status: status.value, value: parsedSet }; + } + const elements = [...ctx.data.values()].map((item, i2) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i2))); + if (ctx.common.async) { + return Promise.all(elements).then((elements2) => finalizeSet(elements2)); + } else { + return finalizeSet(elements); + } + } + min(minSize, message) { + return new _ZodSet({ + ...this._def, + minSize: { value: minSize, message: errorUtil.toString(message) } + }); + } + max(maxSize, message) { + return new _ZodSet({ + ...this._def, + maxSize: { value: maxSize, message: errorUtil.toString(message) } + }); + } + size(size, message) { + return this.min(size, message).max(size, message); + } + nonempty(message) { + return this.min(1, message); + } +}; +ZodSet.create = (valueType, params) => { + return new ZodSet({ + valueType, + minSize: null, + maxSize: null, + typeName: ZodFirstPartyTypeKind.ZodSet, + ...processCreateParams(params) + }); +}; +var ZodFunction = class _ZodFunction extends ZodType { + constructor() { + super(...arguments); + this.validate = this.implement; + } + _parse(input) { + const { ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.function) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.function, + received: ctx.parsedType + }); + return INVALID; + } + function makeArgsIssue(args, error) { + return makeIssue({ + data: args, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x), + issueData: { + code: ZodIssueCode.invalid_arguments, + argumentsError: error + } + }); + } + function makeReturnsIssue(returns, error) { + return makeIssue({ + data: returns, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x), + issueData: { + code: ZodIssueCode.invalid_return_type, + returnTypeError: error + } + }); + } + const params = { errorMap: ctx.common.contextualErrorMap }; + const fn = ctx.data; + if (this._def.returns instanceof ZodPromise) { + const me = this; + return OK(async function(...args) { + const error = new ZodError([]); + const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) => { + error.addIssue(makeArgsIssue(args, e)); + throw error; + }); + const result = await Reflect.apply(fn, this, parsedArgs); + const parsedReturns = await me._def.returns._def.type.parseAsync(result, params).catch((e) => { + error.addIssue(makeReturnsIssue(result, e)); + throw error; + }); + return parsedReturns; + }); + } else { + const me = this; + return OK(function(...args) { + const parsedArgs = me._def.args.safeParse(args, params); + if (!parsedArgs.success) { + throw new ZodError([makeArgsIssue(args, parsedArgs.error)]); + } + const result = Reflect.apply(fn, this, parsedArgs.data); + const parsedReturns = me._def.returns.safeParse(result, params); + if (!parsedReturns.success) { + throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]); + } + return parsedReturns.data; + }); + } + } + parameters() { + return this._def.args; + } + returnType() { + return this._def.returns; + } + args(...items) { + return new _ZodFunction({ + ...this._def, + args: ZodTuple.create(items).rest(ZodUnknown.create()) + }); + } + returns(returnType) { + return new _ZodFunction({ + ...this._def, + returns: returnType + }); + } + implement(func) { + const validatedFunc = this.parse(func); + return validatedFunc; + } + strictImplement(func) { + const validatedFunc = this.parse(func); + return validatedFunc; + } + static create(args, returns, params) { + return new _ZodFunction({ + args: args ? args : ZodTuple.create([]).rest(ZodUnknown.create()), + returns: returns || ZodUnknown.create(), + typeName: ZodFirstPartyTypeKind.ZodFunction, + ...processCreateParams(params) + }); + } +}; +var ZodLazy = class extends ZodType { + get schema() { + return this._def.getter(); + } + _parse(input) { + const { ctx } = this._processInputParams(input); + const lazySchema = this._def.getter(); + return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx }); + } +}; +ZodLazy.create = (getter, params) => { + return new ZodLazy({ + getter, + typeName: ZodFirstPartyTypeKind.ZodLazy, + ...processCreateParams(params) + }); +}; +var ZodLiteral = class extends ZodType { + _parse(input) { + if (input.data !== this._def.value) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + received: ctx.data, + code: ZodIssueCode.invalid_literal, + expected: this._def.value + }); + return INVALID; + } + return { status: "valid", value: input.data }; + } + get value() { + return this._def.value; + } +}; +ZodLiteral.create = (value, params) => { + return new ZodLiteral({ + value, + typeName: ZodFirstPartyTypeKind.ZodLiteral, + ...processCreateParams(params) + }); +}; +function createZodEnum(values, params) { + return new ZodEnum({ + values, + typeName: ZodFirstPartyTypeKind.ZodEnum, + ...processCreateParams(params) + }); +} +var ZodEnum = class _ZodEnum extends ZodType { + _parse(input) { + if (typeof input.data !== "string") { + const ctx = this._getOrReturnCtx(input); + const expectedValues = this._def.values; + addIssueToContext(ctx, { + expected: util.joinValues(expectedValues), + received: ctx.parsedType, + code: ZodIssueCode.invalid_type + }); + return INVALID; + } + if (!this._cache) { + this._cache = new Set(this._def.values); + } + if (!this._cache.has(input.data)) { + const ctx = this._getOrReturnCtx(input); + const expectedValues = this._def.values; + addIssueToContext(ctx, { + received: ctx.data, + code: ZodIssueCode.invalid_enum_value, + options: expectedValues + }); + return INVALID; + } + return OK(input.data); + } + get options() { + return this._def.values; + } + get enum() { + const enumValues = {}; + for (const val of this._def.values) { + enumValues[val] = val; + } + return enumValues; + } + get Values() { + const enumValues = {}; + for (const val of this._def.values) { + enumValues[val] = val; + } + return enumValues; + } + get Enum() { + const enumValues = {}; + for (const val of this._def.values) { + enumValues[val] = val; + } + return enumValues; + } + extract(values, newDef = this._def) { + return _ZodEnum.create(values, { + ...this._def, + ...newDef + }); + } + exclude(values, newDef = this._def) { + return _ZodEnum.create(this.options.filter((opt) => !values.includes(opt)), { + ...this._def, + ...newDef + }); + } +}; +ZodEnum.create = createZodEnum; +var ZodNativeEnum = class extends ZodType { + _parse(input) { + const nativeEnumValues = util.getValidEnumValues(this._def.values); + const ctx = this._getOrReturnCtx(input); + if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) { + const expectedValues = util.objectValues(nativeEnumValues); + addIssueToContext(ctx, { + expected: util.joinValues(expectedValues), + received: ctx.parsedType, + code: ZodIssueCode.invalid_type + }); + return INVALID; + } + if (!this._cache) { + this._cache = new Set(util.getValidEnumValues(this._def.values)); + } + if (!this._cache.has(input.data)) { + const expectedValues = util.objectValues(nativeEnumValues); + addIssueToContext(ctx, { + received: ctx.data, + code: ZodIssueCode.invalid_enum_value, + options: expectedValues + }); + return INVALID; + } + return OK(input.data); + } + get enum() { + return this._def.values; + } +}; +ZodNativeEnum.create = (values, params) => { + return new ZodNativeEnum({ + values, + typeName: ZodFirstPartyTypeKind.ZodNativeEnum, + ...processCreateParams(params) + }); +}; +var ZodPromise = class extends ZodType { + unwrap() { + return this._def.type; + } + _parse(input) { + const { ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.promise, + received: ctx.parsedType + }); + return INVALID; + } + const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); + return OK(promisified.then((data) => { + return this._def.type.parseAsync(data, { + path: ctx.path, + errorMap: ctx.common.contextualErrorMap + }); + })); + } +}; +ZodPromise.create = (schema, params) => { + return new ZodPromise({ + type: schema, + typeName: ZodFirstPartyTypeKind.ZodPromise, + ...processCreateParams(params) + }); +}; +var ZodEffects = class extends ZodType { + innerType() { + return this._def.schema; + } + sourceType() { + return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects ? this._def.schema.sourceType() : this._def.schema; + } + _parse(input) { + const { status, ctx } = this._processInputParams(input); + const effect = this._def.effect || null; + const checkCtx = { + addIssue: (arg) => { + addIssueToContext(ctx, arg); + if (arg.fatal) { + status.abort(); + } else { + status.dirty(); + } + }, + get path() { + return ctx.path; + } + }; + checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); + if (effect.type === "preprocess") { + const processed = effect.transform(ctx.data, checkCtx); + if (ctx.common.async) { + return Promise.resolve(processed).then(async (processed2) => { + if (status.value === "aborted") + return INVALID; + const result = await this._def.schema._parseAsync({ + data: processed2, + path: ctx.path, + parent: ctx + }); + if (result.status === "aborted") + return INVALID; + if (result.status === "dirty") + return DIRTY(result.value); + if (status.value === "dirty") + return DIRTY(result.value); + return result; + }); + } else { + if (status.value === "aborted") + return INVALID; + const result = this._def.schema._parseSync({ + data: processed, + path: ctx.path, + parent: ctx + }); + if (result.status === "aborted") + return INVALID; + if (result.status === "dirty") + return DIRTY(result.value); + if (status.value === "dirty") + return DIRTY(result.value); + return result; + } + } + if (effect.type === "refinement") { + const executeRefinement = (acc) => { + const result = effect.refinement(acc, checkCtx); + if (ctx.common.async) { + return Promise.resolve(result); + } + if (result instanceof Promise) { + throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); + } + return acc; + }; + if (ctx.common.async === false) { + const inner = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + if (inner.status === "aborted") + return INVALID; + if (inner.status === "dirty") + status.dirty(); + executeRefinement(inner.value); + return { status: status.value, value: inner.value }; + } else { + return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => { + if (inner.status === "aborted") + return INVALID; + if (inner.status === "dirty") + status.dirty(); + return executeRefinement(inner.value).then(() => { + return { status: status.value, value: inner.value }; + }); + }); + } + } + if (effect.type === "transform") { + if (ctx.common.async === false) { + const base = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + if (!isValid(base)) + return INVALID; + const result = effect.transform(base.value, checkCtx); + if (result instanceof Promise) { + throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`); + } + return { status: status.value, value: result }; + } else { + return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => { + if (!isValid(base)) + return INVALID; + return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({ + status: status.value, + value: result + })); + }); + } + } + util.assertNever(effect); + } +}; +ZodEffects.create = (schema, effect, params) => { + return new ZodEffects({ + schema, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect, + ...processCreateParams(params) + }); +}; +ZodEffects.createWithPreprocess = (preprocess, schema, params) => { + return new ZodEffects({ + schema, + effect: { type: "preprocess", transform: preprocess }, + typeName: ZodFirstPartyTypeKind.ZodEffects, + ...processCreateParams(params) + }); +}; +var ZodOptional = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType === ZodParsedType.undefined) { + return OK(void 0); + } + return this._def.innerType._parse(input); + } + unwrap() { + return this._def.innerType; + } +}; +ZodOptional.create = (type, params) => { + return new ZodOptional({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodOptional, + ...processCreateParams(params) + }); +}; +var ZodNullable = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType === ZodParsedType.null) { + return OK(null); + } + return this._def.innerType._parse(input); + } + unwrap() { + return this._def.innerType; + } +}; +ZodNullable.create = (type, params) => { + return new ZodNullable({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodNullable, + ...processCreateParams(params) + }); +}; +var ZodDefault = class extends ZodType { + _parse(input) { + const { ctx } = this._processInputParams(input); + let data = ctx.data; + if (ctx.parsedType === ZodParsedType.undefined) { + data = this._def.defaultValue(); + } + return this._def.innerType._parse({ + data, + path: ctx.path, + parent: ctx + }); + } + removeDefault() { + return this._def.innerType; + } +}; +ZodDefault.create = (type, params) => { + return new ZodDefault({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodDefault, + defaultValue: typeof params.default === "function" ? params.default : () => params.default, + ...processCreateParams(params) + }); +}; +var ZodCatch = class extends ZodType { + _parse(input) { + const { ctx } = this._processInputParams(input); + const newCtx = { + ...ctx, + common: { + ...ctx.common, + issues: [] + } + }; + const result = this._def.innerType._parse({ + data: newCtx.data, + path: newCtx.path, + parent: { + ...newCtx + } + }); + if (isAsync(result)) { + return result.then((result2) => { + return { + status: "valid", + value: result2.status === "valid" ? result2.value : this._def.catchValue({ + get error() { + return new ZodError(newCtx.common.issues); + }, + input: newCtx.data + }) + }; + }); + } else { + return { + status: "valid", + value: result.status === "valid" ? result.value : this._def.catchValue({ + get error() { + return new ZodError(newCtx.common.issues); + }, + input: newCtx.data + }) + }; + } + } + removeCatch() { + return this._def.innerType; + } +}; +ZodCatch.create = (type, params) => { + return new ZodCatch({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodCatch, + catchValue: typeof params.catch === "function" ? params.catch : () => params.catch, + ...processCreateParams(params) + }); +}; +var ZodNaN = class extends ZodType { + _parse(input) { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.nan) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.nan, + received: ctx.parsedType + }); + return INVALID; + } + return { status: "valid", value: input.data }; + } +}; +ZodNaN.create = (params) => { + return new ZodNaN({ + typeName: ZodFirstPartyTypeKind.ZodNaN, + ...processCreateParams(params) + }); +}; +var BRAND = /* @__PURE__ */ Symbol("zod_brand"); +var ZodBranded = class extends ZodType { + _parse(input) { + const { ctx } = this._processInputParams(input); + const data = ctx.data; + return this._def.type._parse({ + data, + path: ctx.path, + parent: ctx + }); + } + unwrap() { + return this._def.type; + } +}; +var ZodPipeline = class _ZodPipeline extends ZodType { + _parse(input) { + const { status, ctx } = this._processInputParams(input); + if (ctx.common.async) { + const handleAsync = async () => { + const inResult = await this._def.in._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + if (inResult.status === "aborted") + return INVALID; + if (inResult.status === "dirty") { + status.dirty(); + return DIRTY(inResult.value); + } else { + return this._def.out._parseAsync({ + data: inResult.value, + path: ctx.path, + parent: ctx + }); + } + }; + return handleAsync(); + } else { + const inResult = this._def.in._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + if (inResult.status === "aborted") + return INVALID; + if (inResult.status === "dirty") { + status.dirty(); + return { + status: "dirty", + value: inResult.value + }; + } else { + return this._def.out._parseSync({ + data: inResult.value, + path: ctx.path, + parent: ctx + }); + } + } + } + static create(a2, b) { + return new _ZodPipeline({ + in: a2, + out: b, + typeName: ZodFirstPartyTypeKind.ZodPipeline + }); + } +}; +var ZodReadonly = class extends ZodType { + _parse(input) { + const result = this._def.innerType._parse(input); + const freeze = (data) => { + if (isValid(data)) { + data.value = Object.freeze(data.value); + } + return data; + }; + return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result); + } + unwrap() { + return this._def.innerType; + } +}; +ZodReadonly.create = (type, params) => { + return new ZodReadonly({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodReadonly, + ...processCreateParams(params) + }); +}; +function cleanParams(params, data) { + const p = typeof params === "function" ? params(data) : typeof params === "string" ? { message: params } : params; + const p2 = typeof p === "string" ? { message: p } : p; + return p2; +} +function custom(check, _params = {}, fatal) { + if (check) + return ZodAny.create().superRefine((data, ctx) => { + const r = check(data); + if (r instanceof Promise) { + return r.then((r2) => { + if (!r2) { + const params = cleanParams(_params, data); + const _fatal = params.fatal ?? fatal ?? true; + ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); + } + }); + } + if (!r) { + const params = cleanParams(_params, data); + const _fatal = params.fatal ?? fatal ?? true; + ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); + } + return; + }); + return ZodAny.create(); +} +var late = { + object: ZodObject.lazycreate +}; +var ZodFirstPartyTypeKind; +(function(ZodFirstPartyTypeKind2) { + ZodFirstPartyTypeKind2["ZodString"] = "ZodString"; + ZodFirstPartyTypeKind2["ZodNumber"] = "ZodNumber"; + ZodFirstPartyTypeKind2["ZodNaN"] = "ZodNaN"; + ZodFirstPartyTypeKind2["ZodBigInt"] = "ZodBigInt"; + ZodFirstPartyTypeKind2["ZodBoolean"] = "ZodBoolean"; + ZodFirstPartyTypeKind2["ZodDate"] = "ZodDate"; + ZodFirstPartyTypeKind2["ZodSymbol"] = "ZodSymbol"; + ZodFirstPartyTypeKind2["ZodUndefined"] = "ZodUndefined"; + ZodFirstPartyTypeKind2["ZodNull"] = "ZodNull"; + ZodFirstPartyTypeKind2["ZodAny"] = "ZodAny"; + ZodFirstPartyTypeKind2["ZodUnknown"] = "ZodUnknown"; + ZodFirstPartyTypeKind2["ZodNever"] = "ZodNever"; + ZodFirstPartyTypeKind2["ZodVoid"] = "ZodVoid"; + ZodFirstPartyTypeKind2["ZodArray"] = "ZodArray"; + ZodFirstPartyTypeKind2["ZodObject"] = "ZodObject"; + ZodFirstPartyTypeKind2["ZodUnion"] = "ZodUnion"; + ZodFirstPartyTypeKind2["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion"; + ZodFirstPartyTypeKind2["ZodIntersection"] = "ZodIntersection"; + ZodFirstPartyTypeKind2["ZodTuple"] = "ZodTuple"; + ZodFirstPartyTypeKind2["ZodRecord"] = "ZodRecord"; + ZodFirstPartyTypeKind2["ZodMap"] = "ZodMap"; + ZodFirstPartyTypeKind2["ZodSet"] = "ZodSet"; + ZodFirstPartyTypeKind2["ZodFunction"] = "ZodFunction"; + ZodFirstPartyTypeKind2["ZodLazy"] = "ZodLazy"; + ZodFirstPartyTypeKind2["ZodLiteral"] = "ZodLiteral"; + ZodFirstPartyTypeKind2["ZodEnum"] = "ZodEnum"; + ZodFirstPartyTypeKind2["ZodEffects"] = "ZodEffects"; + ZodFirstPartyTypeKind2["ZodNativeEnum"] = "ZodNativeEnum"; + ZodFirstPartyTypeKind2["ZodOptional"] = "ZodOptional"; + ZodFirstPartyTypeKind2["ZodNullable"] = "ZodNullable"; + ZodFirstPartyTypeKind2["ZodDefault"] = "ZodDefault"; + ZodFirstPartyTypeKind2["ZodCatch"] = "ZodCatch"; + ZodFirstPartyTypeKind2["ZodPromise"] = "ZodPromise"; + ZodFirstPartyTypeKind2["ZodBranded"] = "ZodBranded"; + ZodFirstPartyTypeKind2["ZodPipeline"] = "ZodPipeline"; + ZodFirstPartyTypeKind2["ZodReadonly"] = "ZodReadonly"; +})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {})); +var instanceOfType = (cls, params = { + message: `Input not instance of ${cls.name}` +}) => custom((data) => data instanceof cls, params); +var stringType = ZodString.create; +var numberType = ZodNumber.create; +var nanType = ZodNaN.create; +var bigIntType = ZodBigInt.create; +var booleanType = ZodBoolean.create; +var dateType = ZodDate.create; +var symbolType = ZodSymbol.create; +var undefinedType = ZodUndefined.create; +var nullType = ZodNull.create; +var anyType = ZodAny.create; +var unknownType = ZodUnknown.create; +var neverType = ZodNever.create; +var voidType = ZodVoid.create; +var arrayType = ZodArray.create; +var objectType = ZodObject.create; +var strictObjectType = ZodObject.strictCreate; +var unionType = ZodUnion.create; +var discriminatedUnionType = ZodDiscriminatedUnion.create; +var intersectionType = ZodIntersection.create; +var tupleType = ZodTuple.create; +var recordType = ZodRecord.create; +var mapType = ZodMap.create; +var setType = ZodSet.create; +var functionType = ZodFunction.create; +var lazyType = ZodLazy.create; +var literalType = ZodLiteral.create; +var enumType = ZodEnum.create; +var nativeEnumType = ZodNativeEnum.create; +var promiseType = ZodPromise.create; +var effectsType = ZodEffects.create; +var optionalType = ZodOptional.create; +var nullableType = ZodNullable.create; +var preprocessType = ZodEffects.createWithPreprocess; +var pipelineType = ZodPipeline.create; +var ostring = () => stringType().optional(); +var onumber = () => numberType().optional(); +var oboolean = () => booleanType().optional(); +var coerce = { + string: ((arg) => ZodString.create({ ...arg, coerce: true })), + number: ((arg) => ZodNumber.create({ ...arg, coerce: true })), + boolean: ((arg) => ZodBoolean.create({ + ...arg, + coerce: true + })), + bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })), + date: ((arg) => ZodDate.create({ ...arg, coerce: true })) +}; +var NEVER = INVALID; + +// ../../packages/core/dist/index.js +var import_fs4 = require("fs"); +var import_path3 = __toESM(require("path"), 1); +var KIRO_DIR_NAME = ".kiro"; +var KIRO_STEERING_DIR = "steering"; +var KIRO_SPECS_DIR = "specs"; +var SIDECAR_DIR_NAME = ".specbridge"; +var WORKFLOW_STATUS_VALUES = [ + "REQUIREMENTS_DRAFT", + "REQUIREMENTS_APPROVED", + "BUGFIX_DRAFT", + "BUGFIX_APPROVED", + "DESIGN_DRAFT", + "DESIGN_APPROVED", + "TASKS_DRAFT", + "READY_FOR_REVIEW", + "READY_FOR_IMPLEMENTATION" +]; +var EMPTY_TASK_PROGRESS = { + total: 0, + completed: 0, + inProgress: 0, + optionalTotal: 0, + optionalCompleted: 0 +}; +var SpecBridgeError = class extends Error { + code; + details; + constructor(code2, message, details) { + super(message); + this.name = "SpecBridgeError"; + this.code = code2; + this.details = details; + } +}; +function ioError(action, targetPath, cause) { + const reason = cause instanceof Error ? cause.message : String(cause); + return new SpecBridgeError("IO_ERROR", `Failed to ${action} ${targetPath}: ${reason}`, { + path: targetPath + }); +} +function isDirectory(p) { + try { + return (0, import_fs.statSync)(p).isDirectory(); + } catch { + return false; + } +} +function walkUp(startDir, predicate) { + let dir = import_path.default.resolve(startDir); + for (; ; ) { + if (predicate(dir)) return dir; + const parent = import_path.default.dirname(dir); + if (parent === dir) return void 0; + dir = parent; + } +} +function findKiroRoot(startDir) { + return walkUp(startDir, (dir) => isDirectory(import_path.default.join(dir, KIRO_DIR_NAME))); +} +function findGitRoot(startDir) { + return walkUp(startDir, (dir) => (0, import_fs.existsSync)(import_path.default.join(dir, ".git"))); +} +function resolveWorkspace(startDir) { + const rootDir = findKiroRoot(startDir); + if (rootDir === void 0) return void 0; + const kiroDir = import_path.default.join(rootDir, KIRO_DIR_NAME); + const steeringDir = import_path.default.join(kiroDir, KIRO_STEERING_DIR); + const specsDir = import_path.default.join(kiroDir, KIRO_SPECS_DIR); + const sidecarDir = import_path.default.join(rootDir, SIDECAR_DIR_NAME); + const gitRootDir = findGitRoot(rootDir); + return { + rootDir, + kiroDir, + ...isDirectory(steeringDir) ? { steeringDir } : {}, + ...isDirectory(specsDir) ? { specsDir } : {}, + ...gitRootDir !== void 0 ? { gitRootDir } : {}, + sidecarDir, + sidecarExists: isDirectory(sidecarDir) + }; +} +function assertInsideWorkspace(rootDir, target) { + const resolvedRoot = import_path.default.resolve(rootDir); + const resolved = import_path.default.resolve(resolvedRoot, target); + const relative = import_path.default.relative(resolvedRoot, resolved); + if (relative.startsWith("..") || import_path.default.isAbsolute(relative)) { + throw new SpecBridgeError( + "PATH_OUTSIDE_WORKSPACE", + `Refusing to touch ${resolved}: it is outside the workspace root ${resolvedRoot}.`, + { rootDir: resolvedRoot, target: resolved } + ); + } + return resolved; +} +function writeFileAtomic(filePath, data) { + const dir = import_path.default.dirname(filePath); + const tempPath = import_path.default.join( + dir, + `.${import_path.default.basename(filePath)}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp` + ); + try { + (0, import_fs.mkdirSync)(dir, { recursive: true }); + const fd = (0, import_fs.openSync)(tempPath, "w"); + try { + (0, import_fs.writeSync)(fd, typeof data === "string" ? Buffer.from(data, "utf8") : data); + (0, import_fs.fsyncSync)(fd); + } finally { + (0, import_fs.closeSync)(fd); + } + (0, import_fs.renameSync)(tempPath, filePath); + } catch (cause) { + (0, import_fs.rmSync)(tempPath, { force: true }); + throw ioError("write", filePath, cause); + } +} +function sha256Hex(data) { + return (0, import_crypto.createHash)("sha256").update(data).digest("hex"); +} +function trySha256File(filePath) { + try { + return sha256Hex((0, import_fs2.readFileSync)(filePath)); + } catch { + return void 0; + } +} +var SHA256_HEX = /^[0-9a-f]{64}$/; +var stageApprovalSchema = external_exports.object({ + status: external_exports.enum(["blocked", "draft", "approved"]), + /** Workspace-relative path with forward slashes, e.g. `.kiro/specs/x/design.md`. */ + file: external_exports.string().min(1), + /** ISO-8601 timestamp of the recorded approval, or null when not approved. */ + approvedAt: external_exports.string().datetime({ offset: true }).nullable(), + /** SHA-256 (hex) of the exact approved file bytes, or null when not approved. */ + approvedHash: external_exports.string().regex(SHA256_HEX, "must be a lowercase sha256 hex digest").nullable(), + /** + * Tasks stage only: SHA-256 of the approved document with checkbox state + * normalized (semantics version 2). Absent on stages approved before v0.4 + * and on non-tasks stages; the exact `approvedHash` remains authoritative + * for audit either way. + */ + approvedPlanHash: external_exports.string().regex(SHA256_HEX, "must be a lowercase sha256 hex digest").nullable().optional(), + hashAlgorithm: external_exports.literal("sha256").optional(), + hashSemanticsVersion: external_exports.string().optional() +}); +var stagesSchema = external_exports.object({ + requirements: stageApprovalSchema.optional(), + bugfix: stageApprovalSchema.optional(), + design: stageApprovalSchema, + tasks: stageApprovalSchema +}).passthrough(); +var specWorkflowStateSchema = external_exports.object({ + schemaVersion: external_exports.string().regex(/^\d+\.\d+\.\d+$/), + specName: external_exports.string().min(1), + specType: external_exports.enum(["feature", "bugfix"]), + workflowMode: external_exports.enum(["requirements-first", "design-first", "quick"]), + origin: external_exports.enum(["created-by-specbridge", "existing-kiro-workspace"]).default("created-by-specbridge"), + status: external_exports.enum(WORKFLOW_STATUS_VALUES), + createdAt: external_exports.string().datetime({ offset: true }), + updatedAt: external_exports.string().datetime({ offset: true }), + stages: stagesSchema +}).passthrough().superRefine((state, ctx) => { + const documentStage = state.specType === "bugfix" ? "bugfix" : "requirements"; + const wrongStage = state.specType === "bugfix" ? "requirements" : "bugfix"; + if (state.stages[documentStage] === void 0) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["stages", documentStage], + message: `a ${state.specType} spec must have a "${documentStage}" stage` + }); + } + if (state.stages[wrongStage] !== void 0) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["stages", wrongStage], + message: `a ${state.specType} spec must not have a "${wrongStage}" stage` + }); + } + for (const [name, stage] of Object.entries(state.stages)) { + if (stage === void 0 || typeof stage !== "object") continue; + const approval = stage; + const approved = approval.status === "approved"; + if (approved && (approval.approvedAt === null || approval.approvedHash === null)) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["stages", name], + message: "an approved stage must record approvedAt and approvedHash" + }); + } + if (!approved && (approval.approvedAt !== null || approval.approvedHash !== null)) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["stages", name], + message: "a stage that is not approved must have null approvedAt and approvedHash" + }); + } + if (!approved && approval.approvedPlanHash !== null && approval.approvedPlanHash !== void 0) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["stages", name], + message: "a stage that is not approved must not record approvedPlanHash" + }); + } + } +}); +function stateStage(state, stage) { + const value = state.stages[stage]; + return value === void 0 ? void 0 : value; +} +var specbridgeConfigSchema = external_exports.object({ + defaultRunner: external_exports.string().optional(), + runners: external_exports.record(external_exports.object({ command: external_exports.string().optional() }).passthrough()).optional() +}).passthrough(); +function specStatePath(workspace, specName) { + return assertInsideWorkspace( + workspace.rootDir, + import_path2.default.join(workspace.sidecarDir, "state", "specs", `${specName}.json`) + ); +} +function invalidStateDiagnostic(statePath, parsed, issues) { + const record = typeof parsed === "object" && parsed !== null ? parsed : {}; + if (record["schemaVersion"] === void 0 && record["specName"] !== void 0) { + return { + severity: "warning", + code: "SIDECAR_STATE_LEGACY", + message: "Sidecar state file predates the versioned 1.0.0 schema; ignoring it. Re-approve the stages you trust to regenerate it (the .kiro files are unaffected).", + file: statePath + }; + } + const version = record["schemaVersion"]; + if (typeof version === "string" && !version.startsWith("1.")) { + return { + severity: "warning", + code: "SIDECAR_STATE_UNSUPPORTED_VERSION", + message: `Sidecar state schema version ${version} is not supported by this SpecBridge version; ignoring it.`, + file: statePath + }; + } + return { + severity: "warning", + code: "SIDECAR_STATE_INVALID_SHAPE", + message: `Sidecar state file does not match the expected schema; ignoring it. (${issues})`, + file: statePath + }; +} +function readSpecState(workspace, specName) { + const statePath = specStatePath(workspace, specName); + if (!(0, import_fs3.existsSync)(statePath)) { + return { path: statePath, exists: false, diagnostics: [] }; + } + let raw; + try { + raw = (0, import_fs3.readFileSync)(statePath, "utf8"); + } catch (cause) { + return { + path: statePath, + exists: true, + diagnostics: [ + { + severity: "warning", + code: "SIDECAR_STATE_UNREADABLE", + message: `Could not read sidecar state: ${cause instanceof Error ? cause.message : String(cause)}`, + file: statePath + } + ] + }; + } + let parsed; + try { + parsed = JSON.parse(raw); + } catch { + return { + path: statePath, + exists: true, + diagnostics: [ + { + severity: "warning", + code: "SIDECAR_STATE_INVALID_JSON", + message: "Sidecar state file is not valid JSON; ignoring it.", + file: statePath + } + ] + }; + } + const result = specWorkflowStateSchema.safeParse(parsed); + if (!result.success) { + const issues = result.error.issues.map((i2) => `${i2.path.join(".")}: ${i2.message}`).join("; "); + return { + path: statePath, + exists: true, + diagnostics: [invalidStateDiagnostic(statePath, parsed, issues)] + }; + } + if (result.data.specName !== specName) { + return { + path: statePath, + exists: true, + diagnostics: [ + { + severity: "warning", + code: "SIDECAR_STATE_NAME_MISMATCH", + message: `Sidecar state file records specName "${result.data.specName}" but is stored as ${specName}.json; ignoring it.`, + file: statePath + } + ] + }; + } + return { path: statePath, exists: true, state: result.data, diagnostics: [] }; +} +var EVIDENCE_STATUS_VALUES = [ + "no-change", + "implemented-unverified", + "verified", + "failed", + "blocked", + "cancelled", + "timed-out", + "manually-accepted" +]; +var RUNNER_OUTPUT_SCHEMA_VERSION = "1.0.0"; +var schemaVersionField = external_exports.string().regex(/^\d+\.\d+\.\d+$/).default(RUNNER_OUTPUT_SCHEMA_VERSION); +var REPORTED_OUTCOMES = ["completed", "blocked", "failed", "no-change"]; +var reportedTestSchema = external_exports.object({ + name: external_exports.string().min(1), + status: external_exports.enum(["passed", "failed", "skipped"]) +}); +var taskRunnerReportSchema = external_exports.object({ + schemaVersion: schemaVersionField, + outcome: external_exports.enum(REPORTED_OUTCOMES), + summary: external_exports.string().min(1), + changedFiles: external_exports.array(external_exports.string()).default([]), + commandsReported: external_exports.array(external_exports.string()).default([]), + testsReported: external_exports.array(reportedTestSchema).default([]), + remainingRisks: external_exports.array(external_exports.string()).default([]), + blockingQuestions: external_exports.array(external_exports.string()).default([]), + recommendedNextActions: external_exports.array(external_exports.string()).default([]) +}).strict(); +var stageRunnerReportSchema = external_exports.object({ + schemaVersion: schemaVersionField, + stage: external_exports.enum(["requirements", "bugfix", "design", "tasks"]), + markdown: external_exports.string().min(1), + summary: external_exports.string().min(1), + assumptions: external_exports.array(external_exports.string()).default([]), + openQuestions: external_exports.array(external_exports.string()).default([]), + /** Workspace-relative paths the model consulted. Validated before use. */ + referencedFiles: external_exports.array(external_exports.string()).default([]) +}).strict(); +var TASK_RUNNER_REPORT_JSON_SCHEMA = { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + additionalProperties: false, + required: ["schemaVersion", "outcome", "summary"], + properties: { + schemaVersion: { type: "string", pattern: "^\\d+\\.\\d+\\.\\d+$" }, + outcome: { type: "string", enum: [...REPORTED_OUTCOMES] }, + summary: { type: "string", minLength: 1 }, + changedFiles: { type: "array", items: { type: "string" } }, + commandsReported: { type: "array", items: { type: "string" } }, + testsReported: { + type: "array", + items: { + type: "object", + additionalProperties: false, + required: ["name", "status"], + properties: { + name: { type: "string", minLength: 1 }, + status: { type: "string", enum: ["passed", "failed", "skipped"] } + } + } + }, + remainingRisks: { type: "array", items: { type: "string" } }, + blockingQuestions: { type: "array", items: { type: "string" } }, + recommendedNextActions: { type: "array", items: { type: "string" } } + } +}; +var VERIFICATION_DIAGNOSTIC_SCHEMA_VERSION = "1.0.0"; +var VERIFICATION_REPORT_SCHEMA_VERSION = "1.0.0"; +var VERIFICATION_SEVERITIES = ["error", "warning", "info"]; +var VERIFICATION_CATEGORIES = [ + "workspace", + "approval", + "requirements", + "design", + "tasks", + "evidence", + "impact-area", + "verification-command", + "protected-path", + "mapping", + "git" +]; +var VERIFICATION_CONFIDENCE_VALUES = ["deterministic", "heuristic"]; +var VERIFICATION_RULE_ID_PATTERN = /^SBV\d{3}$/; +var verificationFileLocationSchema = external_exports.object({ + path: external_exports.string().min(1), + line: external_exports.number().int().min(1).nullable(), + column: external_exports.number().int().min(1).nullable() +}); +var verificationDiagnosticSchema = external_exports.object({ + schemaVersion: external_exports.string().regex(/^\d+\.\d+\.\d+$/), + ruleId: external_exports.string().regex(VERIFICATION_RULE_ID_PATTERN), + title: external_exports.string().min(1), + severity: external_exports.enum(VERIFICATION_SEVERITIES), + category: external_exports.enum(VERIFICATION_CATEGORIES), + message: external_exports.string().min(1), + remediation: external_exports.string().min(1), + specName: external_exports.string().nullable(), + taskId: external_exports.string().nullable(), + requirementId: external_exports.string().nullable(), + file: verificationFileLocationSchema.nullable(), + /** Structured, rule-specific supporting data (always JSON-serializable). */ + evidence: external_exports.record(external_exports.unknown()), + confidence: external_exports.enum(VERIFICATION_CONFIDENCE_VALUES) +}); +var COMPARISON_MODES = ["diff", "working-tree", "staged"]; +var comparisonDescriptorSchema = external_exports.object({ + mode: external_exports.enum(COMPARISON_MODES), + /** Base ref as given by the user/event; null for working-tree and staged. */ + base: external_exports.string().nullable(), + head: external_exports.string().nullable(), + /** Resolved commit SHAs where available. */ + baseSha: external_exports.string().nullable(), + headSha: external_exports.string().nullable(), + /** Human-readable label, e.g. `origin/main...HEAD` or `working tree vs HEAD`. */ + label: external_exports.string().min(1) +}); +var CHANGED_FILE_TYPES = [ + "added", + "modified", + "deleted", + "renamed", + "copied", + "untracked" +]; +var reportChangedFileSchema = external_exports.object({ + /** Repository-relative path with forward slashes. */ + path: external_exports.string().min(1), + oldPath: external_exports.string().nullable(), + changeType: external_exports.enum(CHANGED_FILE_TYPES), + binary: external_exports.boolean(), + insertions: external_exports.number().int().min(0).nullable(), + deletions: external_exports.number().int().min(0).nullable() +}); +var VERIFICATION_COMMAND_DISPOSITIONS = [ + /** The command ran during this verification. */ + "executed", + /** A passing result was reused from valid, fresh task evidence. */ + "reused-evidence", + /** The command did not run (per options) and nothing could be reused. */ + "not-run" +]; +var verificationCommandReportSchema = external_exports.object({ + name: external_exports.string().min(1), + argv: external_exports.array(external_exports.string()), + required: external_exports.boolean(), + disposition: external_exports.enum(VERIFICATION_COMMAND_DISPOSITIONS), + exitCode: external_exports.number().int().nullable(), + durationMs: external_exports.number().min(0).nullable(), + timedOut: external_exports.boolean(), + passed: external_exports.boolean(), + /** Specs whose policy required this command by name. */ + requiredBySpecs: external_exports.array(external_exports.string()) +}); +var SELECTION_MODES = ["single", "changed", "all"]; +var VERIFICATION_RESULTS = ["passed", "failed"]; +var POLICY_MODES = ["advisory", "strict"]; +var specTraceabilitySummarySchema = external_exports.object({ + requirements: external_exports.number().int().min(0), + requirementsWithTasks: external_exports.number().int().min(0), + tasks: external_exports.number().int().min(0), + tasksWithRequirements: external_exports.number().int().min(0) +}); +var specEvidenceSummarySchema = external_exports.object({ + /** Completed tasks with valid, fresh verified evidence. */ + valid: external_exports.number().int().min(0), + /** Completed tasks whose best evidence is stale. */ + stale: external_exports.number().int().min(0), + /** Completed tasks with no accepted evidence at all. */ + missing: external_exports.number().int().min(0), + /** Structurally invalid evidence records encountered. */ + invalid: external_exports.number().int().min(0), + /** Completed tasks covered by valid manual acceptance (subset of valid). */ + manuallyAccepted: external_exports.number().int().min(0) +}); +var specVerificationResultSchema = external_exports.object({ + specName: external_exports.string().min(1), + specType: external_exports.enum(["feature", "bugfix", "unknown"]), + workflowMode: external_exports.enum(["requirements-first", "design-first", "quick", "unknown"]), + /** True when SpecBridge sidecar workflow state exists for the spec. */ + managed: external_exports.boolean(), + result: external_exports.enum(VERIFICATION_RESULTS), + policyMode: external_exports.enum(POLICY_MODES), + /** Workspace-relative policy file path; null when defaults were used. */ + policyPath: external_exports.string().nullable(), + /** Why the spec was selected (affected-spec reasons; empty for single/all). */ + matchedBy: external_exports.array(external_exports.string()), + changedFiles: external_exports.array(reportChangedFileSchema), + traceability: specTraceabilitySummarySchema, + evidence: specEvidenceSummarySchema, + diagnostics: external_exports.array(verificationDiagnosticSchema) +}); +var verificationSummarySchema = external_exports.object({ + result: external_exports.enum(VERIFICATION_RESULTS), + specsVerified: external_exports.number().int().min(0), + errors: external_exports.number().int().min(0), + warnings: external_exports.number().int().min(0), + info: external_exports.number().int().min(0) +}); +var verificationReportSchema = external_exports.object({ + schemaVersion: external_exports.string().regex(/^\d+\.\d+\.\d+$/), + tool: external_exports.object({ + name: external_exports.string().min(1), + version: external_exports.string().min(1) + }), + verificationId: external_exports.string().min(1), + createdAt: external_exports.string().datetime({ offset: true }), + comparison: comparisonDescriptorSchema, + selection: external_exports.object({ + mode: external_exports.enum(SELECTION_MODES), + specs: external_exports.array(external_exports.string()) + }), + summary: verificationSummarySchema, + specResults: external_exports.array(specVerificationResultSchema), + /** Diagnostics not attributable to a single selected spec. */ + globalDiagnostics: external_exports.array(verificationDiagnosticSchema), + verificationCommands: external_exports.array(verificationCommandReportSchema) +}); +var SEVERITY_RANK = { + error: 0, + warning: 1, + info: 2 +}; +function compareVerificationDiagnostics(a2, b) { + const bySeverity = SEVERITY_RANK[a2.severity] - SEVERITY_RANK[b.severity]; + if (bySeverity !== 0) return bySeverity; + const byRule = a2.ruleId.localeCompare(b.ruleId, "en"); + if (byRule !== 0) return byRule; + const byFile = (a2.file?.path ?? "").localeCompare(b.file?.path ?? "", "en"); + if (byFile !== 0) return byFile; + const byLine = (a2.file?.line ?? 0) - (b.file?.line ?? 0); + if (byLine !== 0) return byLine; + const byTask = (a2.taskId ?? "").localeCompare(b.taskId ?? "", "en"); + if (byTask !== 0) return byTask; + const byRequirement = (a2.requirementId ?? "").localeCompare(b.requirementId ?? "", "en"); + if (byRequirement !== 0) return byRequirement; + return a2.message.localeCompare(b.message, "en"); +} +function sortVerificationDiagnostics(diagnostics) { + return [...diagnostics].sort(compareVerificationDiagnostics); +} +function countDiagnostics(diagnostics) { + const counts = { errors: 0, warnings: 0, info: 0 }; + for (const diagnostic of diagnostics) { + if (diagnostic.severity === "error") counts.errors += 1; + else if (diagnostic.severity === "warning") counts.warnings += 1; + else counts.info += 1; + } + return counts; +} +function reachesFailureThreshold(counts, threshold) { + if (threshold === "never") return false; + if (threshold === "warning") return counts.errors > 0 || counts.warnings > 0; + return counts.errors > 0; +} +var AGENT_CONFIG_SCHEMA_VERSION = "1.0.0"; +var FORBIDDEN_PERMISSION_MODE = "bypassPermissions"; +var FORBIDDEN_FLAG_FRAGMENTS = ["dangerously-skip-permissions", "dangerously_skip_permissions"]; +function containsNullByte(value) { + return value.includes("\0"); +} +var safeString = external_exports.string().refine((value) => !containsNullByte(value), { message: "must not contain null bytes" }); +var safeNonEmptyString = safeString.refine((value) => value.length > 0, { + message: "must not be empty" +}); +var verificationCommandSchema = external_exports.object({ + name: safeNonEmptyString, + argv: external_exports.array(safeNonEmptyString).min(1, "argv must contain at least the executable").superRefine((argv, ctx) => { + if (argv.length === 1 && /\s/.test(argv[0] ?? "")) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + message: `"${argv[0]}" looks like a shell command string. Verification commands must be argv arrays, e.g. ["pnpm", "test"].` + }); + } + }), + timeoutMs: external_exports.number().int().min(1e3).max(864e5).default(6e5), + required: external_exports.boolean().default(true) +}).passthrough(); +var CLAUDE_PERMISSION_MODES = ["default", "acceptEdits", "plan"]; +var DEFAULT_CLAUDE_TOOLS = ["Read", "Glob", "Grep", "Edit", "Write", "Bash"]; +var DEFAULT_ALLOWED_BASH_RULES = [ + "Bash(git status *)", + "Bash(git diff *)", + "Bash(git log *)", + "Bash(pnpm test *)", + "Bash(pnpm typecheck *)", + "Bash(pnpm lint *)", + "Bash(pnpm build *)", + "Bash(npm test *)", + "Bash(npm run test *)", + "Bash(npm run build *)" +]; +var claudeRunnerConfigSchema = external_exports.object({ + enabled: external_exports.boolean().default(true), + /** Executable name or path, resolved without any shell interpolation. */ + command: safeNonEmptyString.default("claude"), + /** + * Arguments always placed before SpecBridge's own arguments. Lets the + * executable be an interpreter (e.g. command "node", commandArgs + * ["path/to/cli.js"]). Used by the offline test harness. + */ + commandArgs: external_exports.array(safeNonEmptyString).default([]), + model: safeNonEmptyString.nullable().default(null), + effort: safeNonEmptyString.nullable().default(null), + maxTurns: external_exports.number().int().min(1).max(1e3).default(30), + maxBudgetUsd: external_exports.number().positive().nullable().default(null), + timeoutMs: external_exports.number().int().min(1e3).max(864e5).default(18e5), + permissionMode: external_exports.enum(CLAUDE_PERMISSION_MODES).default("acceptEdits"), + loadProjectConfiguration: external_exports.boolean().default(true), + /** Tools available during task execution. Stage generation restricts further. */ + tools: external_exports.array(safeNonEmptyString).default([...DEFAULT_CLAUDE_TOOLS]), + allowedBashRules: external_exports.array(safeNonEmptyString).default([...DEFAULT_ALLOWED_BASH_RULES]), + maxStdoutBytes: external_exports.number().int().min(1024).default(10 * 1024 * 1024), + maxStderrBytes: external_exports.number().int().min(1024).default(1024 * 1024) +}).passthrough(); +var MOCK_SCENARIOS = [ + "success", + "invalid-markdown", + "malformed-output", + "no-change", + "blocked", + "failed", + "timeout", + "cancelled", + "permission-denied", + "stderr-noise", + "claims-untested", + "protected-path", + "modify-tasks-doc", + "resume-failure" +]; +var mockRunnerConfigSchema = external_exports.object({ + enabled: external_exports.boolean().default(true), + scenario: external_exports.enum(MOCK_SCENARIOS).default("success"), + /** + * Workspace-relative file the mock runner creates/appends for successful + * task scenarios. Must stay inside the workspace. + */ + changeFile: safeNonEmptyString.refine((value) => !import_path3.default.isAbsolute(value) && !value.split(/[\\/]/).includes(".."), { + message: 'must be a workspace-relative path without ".." segments' + }).default("specbridge-mock-change.txt") +}).passthrough(); +var genericRunnerConfigSchema = external_exports.object({ + enabled: external_exports.boolean().optional(), + command: safeNonEmptyString.optional() +}).passthrough(); +var executionPolicySchema = external_exports.object({ + requireCleanWorkingTree: external_exports.boolean().default(true), + stopOnUnverifiedTask: external_exports.boolean().default(true), + capturePatch: external_exports.boolean().default(true), + maximumPatchBytes: external_exports.number().int().min(1024).default(10485760), + /** + * Additional protected path prefixes (workspace-relative, forward + * slashes). `.kiro`, `.specbridge`, and `.git` are always protected. + */ + protectedPaths: external_exports.array( + safeNonEmptyString.refine( + (value) => !import_path3.default.isAbsolute(value) && !value.split(/[\\/]/).includes(".."), + { message: 'must be a workspace-relative path without ".." segments' } + ) + ).default([]) +}).passthrough(); +var verificationConfigSchema = external_exports.object({ + commands: external_exports.array(verificationCommandSchema).default([]) +}).passthrough(); +var agentConfigSchema = external_exports.object({ + schemaVersion: external_exports.string().regex(/^\d+\.\d+\.\d+$/).default(AGENT_CONFIG_SCHEMA_VERSION), + defaultRunner: safeNonEmptyString.default("claude-code"), + runners: external_exports.object({ + "claude-code": claudeRunnerConfigSchema.default({}), + mock: mockRunnerConfigSchema.default({}) + }).catchall(genericRunnerConfigSchema).default({}), + verification: verificationConfigSchema.default({}), + execution: executionPolicySchema.default({}) +}).passthrough().superRefine((config, ctx) => { + if (config.schemaVersion !== void 0 && !config.schemaVersion.startsWith("1.")) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["schemaVersion"], + message: `schema version ${config.schemaVersion} is not supported by this SpecBridge version` + }); + } + const serialized = JSON.stringify(config); + for (const fragment of FORBIDDEN_FLAG_FRAGMENTS) { + if (serialized.toLowerCase().includes(fragment)) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + message: `configuration contains "${fragment}", which SpecBridge never passes to any runner. Remove it; there is no supported way to skip runner permission checks.` + }); + } + } + if (serialized.includes(FORBIDDEN_PERMISSION_MODE)) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + message: `"${FORBIDDEN_PERMISSION_MODE}" is not a supported permission mode. SpecBridge only supports: ${CLAUDE_PERMISSION_MODES.join(", ")}.` + }); + } +}); +function defaultAgentConfig() { + return agentConfigSchema.parse({}); +} +function readAgentConfig(workspace) { + const configPath = import_path3.default.join(workspace.sidecarDir, "config.json"); + if (!(0, import_fs4.existsSync)(configPath)) { + return { path: configPath, exists: false, config: defaultAgentConfig(), diagnostics: [] }; + } + let parsed; + try { + parsed = JSON.parse((0, import_fs4.readFileSync)(configPath, "utf8")); + } catch (cause) { + return { + path: configPath, + exists: true, + diagnostics: [ + { + severity: "error", + code: "CONFIG_INVALID_JSON", + message: `Configuration file could not be parsed: ${cause instanceof Error ? cause.message : String(cause)}`, + file: configPath + } + ] + }; + } + const result = agentConfigSchema.safeParse(parsed); + if (!result.success) { + const issues = result.error.issues.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; "); + return { + path: configPath, + exists: true, + diagnostics: [ + { + severity: "error", + code: "CONFIG_INVALID_SHAPE", + message: `Configuration file is not a valid runner configuration: ${issues}`, + file: configPath + } + ] + }; + } + return { path: configPath, exists: true, config: result.data, diagnostics: [] }; +} + +// ../../node_modules/.pnpm/is-plain-obj@4.1.0/node_modules/is-plain-obj/index.js +function isPlainObject(value) { + if (typeof value !== "object" || value === null) { + return false; + } + const prototype = Object.getPrototypeOf(value); + return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value); +} + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/file-url.js +var import_node_url = require("url"); +var safeNormalizeFileUrl = (file, name) => { + const fileString = normalizeFileUrl(normalizeDenoExecPath(file)); + if (typeof fileString !== "string") { + throw new TypeError(`${name} must be a string or a file URL: ${fileString}.`); + } + return fileString; +}; +var normalizeDenoExecPath = (file) => isDenoExecPath(file) ? file.toString() : file; +var isDenoExecPath = (file) => typeof file !== "string" && file && Object.getPrototypeOf(file) === String.prototype; +var normalizeFileUrl = (file) => file instanceof URL ? (0, import_node_url.fileURLToPath)(file) : file; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/parameters.js +var normalizeParameters = (rawFile, rawArguments = [], rawOptions = {}) => { + const filePath = safeNormalizeFileUrl(rawFile, "First argument"); + const [commandArguments, options] = isPlainObject(rawArguments) ? [[], rawArguments] : [rawArguments, rawOptions]; + if (!Array.isArray(commandArguments)) { + throw new TypeError(`Second argument must be either an array of arguments or an options object: ${commandArguments}`); + } + if (commandArguments.some((commandArgument) => typeof commandArgument === "object" && commandArgument !== null)) { + throw new TypeError(`Second argument must be an array of strings: ${commandArguments}`); + } + const normalizedArguments = commandArguments.map(String); + const nullByteArgument = normalizedArguments.find((normalizedArgument) => normalizedArgument.includes("\0")); + if (nullByteArgument !== void 0) { + throw new TypeError(`Arguments cannot contain null bytes ("\\0"): ${nullByteArgument}`); + } + if (!isPlainObject(options)) { + throw new TypeError(`Last argument must be an options object: ${options}`); + } + return [filePath, normalizedArguments, options]; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/template.js +var import_node_child_process = require("child_process"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/utils/uint-array.js +var import_node_string_decoder = require("string_decoder"); +var { toString: objectToString } = Object.prototype; +var isArrayBuffer = (value) => objectToString.call(value) === "[object ArrayBuffer]"; +var isUint8Array = (value) => objectToString.call(value) === "[object Uint8Array]"; +var bufferToUint8Array = (buffer) => new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); +var textEncoder = new TextEncoder(); +var stringToUint8Array = (string) => textEncoder.encode(string); +var textDecoder = new TextDecoder(); +var uint8ArrayToString = (uint8Array) => textDecoder.decode(uint8Array); +var joinToString = (uint8ArraysOrStrings, encoding) => { + const strings = uint8ArraysToStrings(uint8ArraysOrStrings, encoding); + return strings.join(""); +}; +var uint8ArraysToStrings = (uint8ArraysOrStrings, encoding) => { + if (encoding === "utf8" && uint8ArraysOrStrings.every((uint8ArrayOrString) => typeof uint8ArrayOrString === "string")) { + return uint8ArraysOrStrings; + } + const decoder = new import_node_string_decoder.StringDecoder(encoding); + const strings = uint8ArraysOrStrings.map((uint8ArrayOrString) => typeof uint8ArrayOrString === "string" ? stringToUint8Array(uint8ArrayOrString) : uint8ArrayOrString).map((uint8Array) => decoder.write(uint8Array)); + const finalString = decoder.end(); + return finalString === "" ? strings : [...strings, finalString]; +}; +var joinToUint8Array = (uint8ArraysOrStrings) => { + if (uint8ArraysOrStrings.length === 1 && isUint8Array(uint8ArraysOrStrings[0])) { + return uint8ArraysOrStrings[0]; + } + return concatUint8Arrays(stringsToUint8Arrays(uint8ArraysOrStrings)); +}; +var stringsToUint8Arrays = (uint8ArraysOrStrings) => uint8ArraysOrStrings.map((uint8ArrayOrString) => typeof uint8ArrayOrString === "string" ? stringToUint8Array(uint8ArrayOrString) : uint8ArrayOrString); +var concatUint8Arrays = (uint8Arrays) => { + const result = new Uint8Array(getJoinLength(uint8Arrays)); + let index = 0; + for (const uint8Array of uint8Arrays) { + result.set(uint8Array, index); + index += uint8Array.length; + } + return result; +}; +var getJoinLength = (uint8Arrays) => { + let joinLength = 0; + for (const uint8Array of uint8Arrays) { + joinLength += uint8Array.length; + } + return joinLength; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/template.js +var isTemplateString = (templates) => Array.isArray(templates) && Array.isArray(templates.raw); +var parseTemplates = (templates, expressions) => { + let tokens = []; + for (const [index, template] of templates.entries()) { + tokens = parseTemplate({ + templates, + expressions, + tokens, + index, + template + }); + } + if (tokens.length === 0) { + throw new TypeError("Template script must not be empty"); + } + const [file, ...commandArguments] = tokens; + return [file, commandArguments, {}]; +}; +var parseTemplate = ({ templates, expressions, tokens, index, template }) => { + if (template === void 0) { + throw new TypeError(`Invalid backslash sequence: ${templates.raw[index]}`); + } + const { nextTokens, leadingWhitespaces, trailingWhitespaces } = splitByWhitespaces(template, templates.raw[index]); + const newTokens = concatTokens(tokens, nextTokens, leadingWhitespaces); + if (index === expressions.length) { + return newTokens; + } + const expression = expressions[index]; + const expressionTokens = Array.isArray(expression) ? expression.map((expression2) => parseExpression(expression2)) : [parseExpression(expression)]; + return concatTokens(newTokens, expressionTokens, trailingWhitespaces); +}; +var splitByWhitespaces = (template, rawTemplate) => { + if (rawTemplate.length === 0) { + return { nextTokens: [], leadingWhitespaces: false, trailingWhitespaces: false }; + } + const nextTokens = []; + let templateStart = 0; + const leadingWhitespaces = DELIMITERS.has(rawTemplate[0]); + for (let templateIndex = 0, rawIndex = 0; templateIndex < template.length; templateIndex += 1, rawIndex += 1) { + const rawCharacter = rawTemplate[rawIndex]; + if (DELIMITERS.has(rawCharacter)) { + if (templateStart !== templateIndex) { + nextTokens.push(template.slice(templateStart, templateIndex)); + } + templateStart = templateIndex + 1; + } else if (rawCharacter === "\\") { + const nextRawCharacter = rawTemplate[rawIndex + 1]; + if (nextRawCharacter === "\n") { + templateIndex -= 1; + rawIndex += 1; + } else if (nextRawCharacter === "u" && rawTemplate[rawIndex + 2] === "{") { + rawIndex = rawTemplate.indexOf("}", rawIndex + 3); + } else { + rawIndex += ESCAPE_LENGTH[nextRawCharacter] ?? 1; + } + } + } + const trailingWhitespaces = templateStart === template.length; + if (!trailingWhitespaces) { + nextTokens.push(template.slice(templateStart)); + } + return { nextTokens, leadingWhitespaces, trailingWhitespaces }; +}; +var DELIMITERS = /* @__PURE__ */ new Set([" ", " ", "\r", "\n"]); +var ESCAPE_LENGTH = { x: 3, u: 5 }; +var concatTokens = (tokens, nextTokens, isSeparated) => isSeparated || tokens.length === 0 || nextTokens.length === 0 ? [...tokens, ...nextTokens] : [ + ...tokens.slice(0, -1), + `${tokens.at(-1)}${nextTokens[0]}`, + ...nextTokens.slice(1) +]; +var parseExpression = (expression) => { + const typeOfExpression = typeof expression; + if (typeOfExpression === "string") { + return expression; + } + if (typeOfExpression === "number") { + return String(expression); + } + if (isPlainObject(expression) && ("stdout" in expression || "isMaxBuffer" in expression)) { + return getSubprocessResult(expression); + } + if (expression instanceof import_node_child_process.ChildProcess || Object.prototype.toString.call(expression) === "[object Promise]") { + throw new TypeError("Unexpected subprocess in template expression. Please use ${await subprocess} instead of ${subprocess}."); + } + throw new TypeError(`Unexpected "${typeOfExpression}" in template expression`); +}; +var getSubprocessResult = ({ stdout }) => { + if (typeof stdout === "string") { + return stdout; + } + if (isUint8Array(stdout)) { + return uint8ArrayToString(stdout); + } + if (stdout === void 0) { + throw new TypeError(`Missing result.stdout in template expression. This is probably due to the previous subprocess' "stdout" option.`); + } + throw new TypeError(`Unexpected "${typeof stdout}" stdout in template expression`); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/main-sync.js +var import_node_child_process3 = require("child_process"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/specific.js +var import_node_util = require("util"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/utils/standard-stream.js +var import_node_process = __toESM(require("process"), 1); +var isStandardStream = (stream) => STANDARD_STREAMS.includes(stream); +var STANDARD_STREAMS = [import_node_process.default.stdin, import_node_process.default.stdout, import_node_process.default.stderr]; +var STANDARD_STREAMS_ALIASES = ["stdin", "stdout", "stderr"]; +var getStreamName = (fdNumber) => STANDARD_STREAMS_ALIASES[fdNumber] ?? `stdio[${fdNumber}]`; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/specific.js +var normalizeFdSpecificOptions = (options) => { + const optionsCopy = { ...options }; + for (const optionName of FD_SPECIFIC_OPTIONS) { + optionsCopy[optionName] = normalizeFdSpecificOption(options, optionName); + } + return optionsCopy; +}; +var normalizeFdSpecificOption = (options, optionName) => { + const optionBaseArray = Array.from({ length: getStdioLength(options) + 1 }); + const optionArray = normalizeFdSpecificValue(options[optionName], optionBaseArray, optionName); + return addDefaultValue(optionArray, optionName); +}; +var getStdioLength = ({ stdio }) => Array.isArray(stdio) ? Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length) : STANDARD_STREAMS_ALIASES.length; +var normalizeFdSpecificValue = (optionValue, optionArray, optionName) => isPlainObject(optionValue) ? normalizeOptionObject(optionValue, optionArray, optionName) : optionArray.fill(optionValue); +var normalizeOptionObject = (optionValue, optionArray, optionName) => { + for (const fdName of Object.keys(optionValue).sort(compareFdName)) { + for (const fdNumber of parseFdName(fdName, optionName, optionArray)) { + optionArray[fdNumber] = optionValue[fdName]; + } + } + return optionArray; +}; +var compareFdName = (fdNameA, fdNameB) => getFdNameOrder(fdNameA) < getFdNameOrder(fdNameB) ? 1 : -1; +var getFdNameOrder = (fdName) => { + if (fdName === "stdout" || fdName === "stderr") { + return 0; + } + return fdName === "all" ? 2 : 1; +}; +var parseFdName = (fdName, optionName, optionArray) => { + if (fdName === "ipc") { + return [optionArray.length - 1]; + } + const fdNumber = parseFd(fdName); + if (fdNumber === void 0 || fdNumber === 0) { + throw new TypeError(`"${optionName}.${fdName}" is invalid. +It must be "${optionName}.stdout", "${optionName}.stderr", "${optionName}.all", "${optionName}.ipc", or "${optionName}.fd3", "${optionName}.fd4" (and so on).`); + } + if (fdNumber >= optionArray.length) { + throw new TypeError(`"${optionName}.${fdName}" is invalid: that file descriptor does not exist. +Please set the "stdio" option to ensure that file descriptor exists.`); + } + return fdNumber === "all" ? [1, 2] : [fdNumber]; +}; +var parseFd = (fdName) => { + if (fdName === "all") { + return fdName; + } + if (STANDARD_STREAMS_ALIASES.includes(fdName)) { + return STANDARD_STREAMS_ALIASES.indexOf(fdName); + } + const regexpResult = FD_REGEXP.exec(fdName); + if (regexpResult !== null) { + return Number(regexpResult[1]); + } +}; +var FD_REGEXP = /^fd(\d+)$/; +var addDefaultValue = (optionArray, optionName) => optionArray.map((optionValue) => optionValue === void 0 ? DEFAULT_OPTIONS[optionName] : optionValue); +var verboseDefault = (0, import_node_util.debuglog)("execa").enabled ? "full" : "none"; +var DEFAULT_OPTIONS = { + lines: false, + buffer: true, + maxBuffer: 1e3 * 1e3 * 100, + verbose: verboseDefault, + stripFinalNewline: true +}; +var FD_SPECIFIC_OPTIONS = ["lines", "buffer", "maxBuffer", "verbose", "stripFinalNewline"]; +var getFdSpecificValue = (optionArray, fdNumber) => fdNumber === "ipc" ? optionArray.at(-1) : optionArray[fdNumber]; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/values.js +var isVerbose = ({ verbose }, fdNumber) => getFdVerbose(verbose, fdNumber) !== "none"; +var isFullVerbose = ({ verbose }, fdNumber) => !["none", "short"].includes(getFdVerbose(verbose, fdNumber)); +var getVerboseFunction = ({ verbose }, fdNumber) => { + const fdVerbose = getFdVerbose(verbose, fdNumber); + return isVerboseFunction(fdVerbose) ? fdVerbose : void 0; +}; +var getFdVerbose = (verbose, fdNumber) => fdNumber === void 0 ? getFdGenericVerbose(verbose) : getFdSpecificValue(verbose, fdNumber); +var getFdGenericVerbose = (verbose) => verbose.find((fdVerbose) => isVerboseFunction(fdVerbose)) ?? VERBOSE_VALUES.findLast((fdVerbose) => verbose.includes(fdVerbose)); +var isVerboseFunction = (fdVerbose) => typeof fdVerbose === "function"; +var VERBOSE_VALUES = ["none", "short", "full"]; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/log.js +var import_node_util3 = require("util"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/escape.js +var import_node_process2 = require("process"); +var import_node_util2 = require("util"); +var joinCommand = (filePath, rawArguments) => { + const fileAndArguments = [filePath, ...rawArguments]; + const command = fileAndArguments.join(" "); + const escapedCommand = fileAndArguments.map((fileAndArgument) => quoteString(escapeControlCharacters(fileAndArgument))).join(" "); + return { command, escapedCommand }; +}; +var escapeLines = (lines) => (0, import_node_util2.stripVTControlCharacters)(lines).split("\n").map((line) => escapeControlCharacters(line)).join("\n"); +var escapeControlCharacters = (line) => line.replaceAll(SPECIAL_CHAR_REGEXP, (character) => escapeControlCharacter(character)); +var escapeControlCharacter = (character) => { + const commonEscape = COMMON_ESCAPES[character]; + if (commonEscape !== void 0) { + return commonEscape; + } + const codepoint = character.codePointAt(0); + const codepointHex = codepoint.toString(16); + return codepoint <= ASTRAL_START ? `\\u${codepointHex.padStart(4, "0")}` : `\\U${codepointHex}`; +}; +var getSpecialCharRegExp = () => { + try { + return new RegExp("\\p{Separator}|\\p{Other}", "gu"); + } catch { + return /[\s\u0000-\u001F\u007F-\u009F\u00AD]/g; + } +}; +var SPECIAL_CHAR_REGEXP = getSpecialCharRegExp(); +var COMMON_ESCAPES = { + " ": " ", + "\b": "\\b", + "\f": "\\f", + "\n": "\\n", + "\r": "\\r", + " ": "\\t" +}; +var ASTRAL_START = 65535; +var quoteString = (escapedArgument) => { + if (NO_ESCAPE_REGEXP.test(escapedArgument)) { + return escapedArgument; + } + return import_node_process2.platform === "win32" ? `"${escapedArgument.replaceAll('"', '""')}"` : `'${escapedArgument.replaceAll("'", "'\\''")}'`; +}; +var NO_ESCAPE_REGEXP = /^[\w./-]+$/; + +// ../../node_modules/.pnpm/is-unicode-supported@2.1.0/node_modules/is-unicode-supported/index.js +var import_node_process3 = __toESM(require("process"), 1); +function isUnicodeSupported() { + const { env } = import_node_process3.default; + const { TERM, TERM_PROGRAM } = env; + if (import_node_process3.default.platform !== "win32") { + return TERM !== "linux"; + } + return Boolean(env.WT_SESSION) || Boolean(env.TERMINUS_SUBLIME) || env.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env.TERMINAL_EMULATOR === "JetBrains-JediTerm"; +} + +// ../../node_modules/.pnpm/figures@6.1.0/node_modules/figures/index.js +var common = { + circleQuestionMark: "(?)", + questionMarkPrefix: "(?)", + square: "\u2588", + squareDarkShade: "\u2593", + squareMediumShade: "\u2592", + squareLightShade: "\u2591", + squareTop: "\u2580", + squareBottom: "\u2584", + squareLeft: "\u258C", + squareRight: "\u2590", + squareCenter: "\u25A0", + bullet: "\u25CF", + dot: "\u2024", + ellipsis: "\u2026", + pointerSmall: "\u203A", + triangleUp: "\u25B2", + triangleUpSmall: "\u25B4", + triangleDown: "\u25BC", + triangleDownSmall: "\u25BE", + triangleLeftSmall: "\u25C2", + triangleRightSmall: "\u25B8", + home: "\u2302", + heart: "\u2665", + musicNote: "\u266A", + musicNoteBeamed: "\u266B", + arrowUp: "\u2191", + arrowDown: "\u2193", + arrowLeft: "\u2190", + arrowRight: "\u2192", + arrowLeftRight: "\u2194", + arrowUpDown: "\u2195", + almostEqual: "\u2248", + notEqual: "\u2260", + lessOrEqual: "\u2264", + greaterOrEqual: "\u2265", + identical: "\u2261", + infinity: "\u221E", + subscriptZero: "\u2080", + subscriptOne: "\u2081", + subscriptTwo: "\u2082", + subscriptThree: "\u2083", + subscriptFour: "\u2084", + subscriptFive: "\u2085", + subscriptSix: "\u2086", + subscriptSeven: "\u2087", + subscriptEight: "\u2088", + subscriptNine: "\u2089", + oneHalf: "\xBD", + oneThird: "\u2153", + oneQuarter: "\xBC", + oneFifth: "\u2155", + oneSixth: "\u2159", + oneEighth: "\u215B", + twoThirds: "\u2154", + twoFifths: "\u2156", + threeQuarters: "\xBE", + threeFifths: "\u2157", + threeEighths: "\u215C", + fourFifths: "\u2158", + fiveSixths: "\u215A", + fiveEighths: "\u215D", + sevenEighths: "\u215E", + line: "\u2500", + lineBold: "\u2501", + lineDouble: "\u2550", + lineDashed0: "\u2504", + lineDashed1: "\u2505", + lineDashed2: "\u2508", + lineDashed3: "\u2509", + lineDashed4: "\u254C", + lineDashed5: "\u254D", + lineDashed6: "\u2574", + lineDashed7: "\u2576", + lineDashed8: "\u2578", + lineDashed9: "\u257A", + lineDashed10: "\u257C", + lineDashed11: "\u257E", + lineDashed12: "\u2212", + lineDashed13: "\u2013", + lineDashed14: "\u2010", + lineDashed15: "\u2043", + lineVertical: "\u2502", + lineVerticalBold: "\u2503", + lineVerticalDouble: "\u2551", + lineVerticalDashed0: "\u2506", + lineVerticalDashed1: "\u2507", + lineVerticalDashed2: "\u250A", + lineVerticalDashed3: "\u250B", + lineVerticalDashed4: "\u254E", + lineVerticalDashed5: "\u254F", + lineVerticalDashed6: "\u2575", + lineVerticalDashed7: "\u2577", + lineVerticalDashed8: "\u2579", + lineVerticalDashed9: "\u257B", + lineVerticalDashed10: "\u257D", + lineVerticalDashed11: "\u257F", + lineDownLeft: "\u2510", + lineDownLeftArc: "\u256E", + lineDownBoldLeftBold: "\u2513", + lineDownBoldLeft: "\u2512", + lineDownLeftBold: "\u2511", + lineDownDoubleLeftDouble: "\u2557", + lineDownDoubleLeft: "\u2556", + lineDownLeftDouble: "\u2555", + lineDownRight: "\u250C", + lineDownRightArc: "\u256D", + lineDownBoldRightBold: "\u250F", + lineDownBoldRight: "\u250E", + lineDownRightBold: "\u250D", + lineDownDoubleRightDouble: "\u2554", + lineDownDoubleRight: "\u2553", + lineDownRightDouble: "\u2552", + lineUpLeft: "\u2518", + lineUpLeftArc: "\u256F", + lineUpBoldLeftBold: "\u251B", + lineUpBoldLeft: "\u251A", + lineUpLeftBold: "\u2519", + lineUpDoubleLeftDouble: "\u255D", + lineUpDoubleLeft: "\u255C", + lineUpLeftDouble: "\u255B", + lineUpRight: "\u2514", + lineUpRightArc: "\u2570", + lineUpBoldRightBold: "\u2517", + lineUpBoldRight: "\u2516", + lineUpRightBold: "\u2515", + lineUpDoubleRightDouble: "\u255A", + lineUpDoubleRight: "\u2559", + lineUpRightDouble: "\u2558", + lineUpDownLeft: "\u2524", + lineUpBoldDownBoldLeftBold: "\u252B", + lineUpBoldDownBoldLeft: "\u2528", + lineUpDownLeftBold: "\u2525", + lineUpBoldDownLeftBold: "\u2529", + lineUpDownBoldLeftBold: "\u252A", + lineUpDownBoldLeft: "\u2527", + lineUpBoldDownLeft: "\u2526", + lineUpDoubleDownDoubleLeftDouble: "\u2563", + lineUpDoubleDownDoubleLeft: "\u2562", + lineUpDownLeftDouble: "\u2561", + lineUpDownRight: "\u251C", + lineUpBoldDownBoldRightBold: "\u2523", + lineUpBoldDownBoldRight: "\u2520", + lineUpDownRightBold: "\u251D", + lineUpBoldDownRightBold: "\u2521", + lineUpDownBoldRightBold: "\u2522", + lineUpDownBoldRight: "\u251F", + lineUpBoldDownRight: "\u251E", + lineUpDoubleDownDoubleRightDouble: "\u2560", + lineUpDoubleDownDoubleRight: "\u255F", + lineUpDownRightDouble: "\u255E", + lineDownLeftRight: "\u252C", + lineDownBoldLeftBoldRightBold: "\u2533", + lineDownLeftBoldRightBold: "\u252F", + lineDownBoldLeftRight: "\u2530", + lineDownBoldLeftBoldRight: "\u2531", + lineDownBoldLeftRightBold: "\u2532", + lineDownLeftRightBold: "\u252E", + lineDownLeftBoldRight: "\u252D", + lineDownDoubleLeftDoubleRightDouble: "\u2566", + lineDownDoubleLeftRight: "\u2565", + lineDownLeftDoubleRightDouble: "\u2564", + lineUpLeftRight: "\u2534", + lineUpBoldLeftBoldRightBold: "\u253B", + lineUpLeftBoldRightBold: "\u2537", + lineUpBoldLeftRight: "\u2538", + lineUpBoldLeftBoldRight: "\u2539", + lineUpBoldLeftRightBold: "\u253A", + lineUpLeftRightBold: "\u2536", + lineUpLeftBoldRight: "\u2535", + lineUpDoubleLeftDoubleRightDouble: "\u2569", + lineUpDoubleLeftRight: "\u2568", + lineUpLeftDoubleRightDouble: "\u2567", + lineUpDownLeftRight: "\u253C", + lineUpBoldDownBoldLeftBoldRightBold: "\u254B", + lineUpDownBoldLeftBoldRightBold: "\u2548", + lineUpBoldDownLeftBoldRightBold: "\u2547", + lineUpBoldDownBoldLeftRightBold: "\u254A", + lineUpBoldDownBoldLeftBoldRight: "\u2549", + lineUpBoldDownLeftRight: "\u2540", + lineUpDownBoldLeftRight: "\u2541", + lineUpDownLeftBoldRight: "\u253D", + lineUpDownLeftRightBold: "\u253E", + lineUpBoldDownBoldLeftRight: "\u2542", + lineUpDownLeftBoldRightBold: "\u253F", + lineUpBoldDownLeftBoldRight: "\u2543", + lineUpBoldDownLeftRightBold: "\u2544", + lineUpDownBoldLeftBoldRight: "\u2545", + lineUpDownBoldLeftRightBold: "\u2546", + lineUpDoubleDownDoubleLeftDoubleRightDouble: "\u256C", + lineUpDoubleDownDoubleLeftRight: "\u256B", + lineUpDownLeftDoubleRightDouble: "\u256A", + lineCross: "\u2573", + lineBackslash: "\u2572", + lineSlash: "\u2571" +}; +var specialMainSymbols = { + tick: "\u2714", + info: "\u2139", + warning: "\u26A0", + cross: "\u2718", + squareSmall: "\u25FB", + squareSmallFilled: "\u25FC", + circle: "\u25EF", + circleFilled: "\u25C9", + circleDotted: "\u25CC", + circleDouble: "\u25CE", + circleCircle: "\u24DE", + circleCross: "\u24E7", + circlePipe: "\u24BE", + radioOn: "\u25C9", + radioOff: "\u25EF", + checkboxOn: "\u2612", + checkboxOff: "\u2610", + checkboxCircleOn: "\u24E7", + checkboxCircleOff: "\u24BE", + pointer: "\u276F", + triangleUpOutline: "\u25B3", + triangleLeft: "\u25C0", + triangleRight: "\u25B6", + lozenge: "\u25C6", + lozengeOutline: "\u25C7", + hamburger: "\u2630", + smiley: "\u32E1", + mustache: "\u0DF4", + star: "\u2605", + play: "\u25B6", + nodejs: "\u2B22", + oneSeventh: "\u2150", + oneNinth: "\u2151", + oneTenth: "\u2152" +}; +var specialFallbackSymbols = { + tick: "\u221A", + info: "i", + warning: "\u203C", + cross: "\xD7", + squareSmall: "\u25A1", + squareSmallFilled: "\u25A0", + circle: "( )", + circleFilled: "(*)", + circleDotted: "( )", + circleDouble: "( )", + circleCircle: "(\u25CB)", + circleCross: "(\xD7)", + circlePipe: "(\u2502)", + radioOn: "(*)", + radioOff: "( )", + checkboxOn: "[\xD7]", + checkboxOff: "[ ]", + checkboxCircleOn: "(\xD7)", + checkboxCircleOff: "( )", + pointer: ">", + triangleUpOutline: "\u2206", + triangleLeft: "\u25C4", + triangleRight: "\u25BA", + lozenge: "\u2666", + lozengeOutline: "\u25CA", + hamburger: "\u2261", + smiley: "\u263A", + mustache: "\u250C\u2500\u2510", + star: "\u2736", + play: "\u25BA", + nodejs: "\u2666", + oneSeventh: "1/7", + oneNinth: "1/9", + oneTenth: "1/10" +}; +var mainSymbols = { ...common, ...specialMainSymbols }; +var fallbackSymbols = { ...common, ...specialFallbackSymbols }; +var shouldUseMain = isUnicodeSupported(); +var figures = shouldUseMain ? mainSymbols : fallbackSymbols; +var figures_default = figures; +var replacements = Object.entries(specialMainSymbols); + +// ../../node_modules/.pnpm/yoctocolors@2.1.2/node_modules/yoctocolors/base.js +var import_node_tty = __toESM(require("tty"), 1); +var hasColors = import_node_tty.default?.WriteStream?.prototype?.hasColors?.() ?? false; +var format = (open, close) => { + if (!hasColors) { + return (input) => input; + } + const openCode = `\x1B[${open}m`; + const closeCode = `\x1B[${close}m`; + return (input) => { + const string = input + ""; + let index = string.indexOf(closeCode); + if (index === -1) { + return openCode + string + closeCode; + } + let result = openCode; + let lastIndex = 0; + const reopenOnNestedClose = close === 22; + const replaceCode = (reopenOnNestedClose ? closeCode : "") + openCode; + while (index !== -1) { + result += string.slice(lastIndex, index) + replaceCode; + lastIndex = index + closeCode.length; + index = string.indexOf(closeCode, lastIndex); + } + result += string.slice(lastIndex) + closeCode; + return result; + }; +}; +var reset = format(0, 0); +var bold = format(1, 22); +var dim = format(2, 22); +var italic = format(3, 23); +var underline = format(4, 24); +var overline = format(53, 55); +var inverse = format(7, 27); +var hidden = format(8, 28); +var strikethrough = format(9, 29); +var black = format(30, 39); +var red = format(31, 39); +var green = format(32, 39); +var yellow = format(33, 39); +var blue = format(34, 39); +var magenta = format(35, 39); +var cyan = format(36, 39); +var white = format(37, 39); +var gray = format(90, 39); +var bgBlack = format(40, 49); +var bgRed = format(41, 49); +var bgGreen = format(42, 49); +var bgYellow = format(43, 49); +var bgBlue = format(44, 49); +var bgMagenta = format(45, 49); +var bgCyan = format(46, 49); +var bgWhite = format(47, 49); +var bgGray = format(100, 49); +var redBright = format(91, 39); +var greenBright = format(92, 39); +var yellowBright = format(93, 39); +var blueBright = format(94, 39); +var magentaBright = format(95, 39); +var cyanBright = format(96, 39); +var whiteBright = format(97, 39); +var bgRedBright = format(101, 49); +var bgGreenBright = format(102, 49); +var bgYellowBright = format(103, 49); +var bgBlueBright = format(104, 49); +var bgMagentaBright = format(105, 49); +var bgCyanBright = format(106, 49); +var bgWhiteBright = format(107, 49); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/default.js +var defaultVerboseFunction = ({ + type, + message, + timestamp, + piped, + commandId, + result: { failed = false } = {}, + options: { reject = true } +}) => { + const timestampString = serializeTimestamp(timestamp); + const icon = ICONS[type]({ failed, reject, piped }); + const color = COLORS[type]({ reject }); + return `${gray(`[${timestampString}]`)} ${gray(`[${commandId}]`)} ${color(icon)} ${color(message)}`; +}; +var serializeTimestamp = (timestamp) => `${padField(timestamp.getHours(), 2)}:${padField(timestamp.getMinutes(), 2)}:${padField(timestamp.getSeconds(), 2)}.${padField(timestamp.getMilliseconds(), 3)}`; +var padField = (field, padding) => String(field).padStart(padding, "0"); +var getFinalIcon = ({ failed, reject }) => { + if (!failed) { + return figures_default.tick; + } + return reject ? figures_default.cross : figures_default.warning; +}; +var ICONS = { + command: ({ piped }) => piped ? "|" : "$", + output: () => " ", + ipc: () => "*", + error: getFinalIcon, + duration: getFinalIcon +}; +var identity = (string) => string; +var COLORS = { + command: () => bold, + output: () => identity, + ipc: () => identity, + error: ({ reject }) => reject ? redBright : yellowBright, + duration: () => gray +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/custom.js +var applyVerboseOnLines = (printedLines, verboseInfo, fdNumber) => { + const verboseFunction = getVerboseFunction(verboseInfo, fdNumber); + return printedLines.map(({ verboseLine, verboseObject }) => applyVerboseFunction(verboseLine, verboseObject, verboseFunction)).filter((printedLine) => printedLine !== void 0).map((printedLine) => appendNewline(printedLine)).join(""); +}; +var applyVerboseFunction = (verboseLine, verboseObject, verboseFunction) => { + if (verboseFunction === void 0) { + return verboseLine; + } + const printedLine = verboseFunction(verboseLine, verboseObject); + if (typeof printedLine === "string") { + return printedLine; + } +}; +var appendNewline = (printedLine) => printedLine.endsWith("\n") ? printedLine : `${printedLine} +`; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/log.js +var verboseLog = ({ type, verboseMessage, fdNumber, verboseInfo, result }) => { + const verboseObject = getVerboseObject({ type, result, verboseInfo }); + const printedLines = getPrintedLines(verboseMessage, verboseObject); + const finalLines = applyVerboseOnLines(printedLines, verboseInfo, fdNumber); + if (finalLines !== "") { + console.warn(finalLines.slice(0, -1)); + } +}; +var getVerboseObject = ({ + type, + result, + verboseInfo: { escapedCommand, commandId, rawOptions: { piped = false, ...options } } +}) => ({ + type, + escapedCommand, + commandId: `${commandId}`, + timestamp: /* @__PURE__ */ new Date(), + piped, + result, + options +}); +var getPrintedLines = (verboseMessage, verboseObject) => verboseMessage.split("\n").map((message) => getPrintedLine({ ...verboseObject, message })); +var getPrintedLine = (verboseObject) => { + const verboseLine = defaultVerboseFunction(verboseObject); + return { verboseLine, verboseObject }; +}; +var serializeVerboseMessage = (message) => { + const messageString = typeof message === "string" ? message : (0, import_node_util3.inspect)(message); + const escapedMessage = escapeLines(messageString); + return escapedMessage.replaceAll(" ", " ".repeat(TAB_SIZE)); +}; +var TAB_SIZE = 2; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/start.js +var logCommand = (escapedCommand, verboseInfo) => { + if (!isVerbose(verboseInfo)) { + return; + } + verboseLog({ + type: "command", + verboseMessage: escapedCommand, + verboseInfo + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/info.js +var getVerboseInfo = (verbose, escapedCommand, rawOptions) => { + validateVerbose(verbose); + const commandId = getCommandId(verbose); + return { + verbose, + escapedCommand, + commandId, + rawOptions + }; +}; +var getCommandId = (verbose) => isVerbose({ verbose }) ? COMMAND_ID++ : void 0; +var COMMAND_ID = 0n; +var validateVerbose = (verbose) => { + for (const fdVerbose of verbose) { + if (fdVerbose === false) { + throw new TypeError(`The "verbose: false" option was renamed to "verbose: 'none'".`); + } + if (fdVerbose === true) { + throw new TypeError(`The "verbose: true" option was renamed to "verbose: 'short'".`); + } + if (!VERBOSE_VALUES.includes(fdVerbose) && !isVerboseFunction(fdVerbose)) { + const allowedValues = VERBOSE_VALUES.map((allowedValue) => `'${allowedValue}'`).join(", "); + throw new TypeError(`The "verbose" option must not be ${fdVerbose}. Allowed values are: ${allowedValues} or a function.`); + } + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/duration.js +var import_node_process4 = require("process"); +var getStartTime = () => import_node_process4.hrtime.bigint(); +var getDurationMs = (startTime) => Number(import_node_process4.hrtime.bigint() - startTime) / 1e6; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/command.js +var handleCommand = (filePath, rawArguments, rawOptions) => { + const startTime = getStartTime(); + const { command, escapedCommand } = joinCommand(filePath, rawArguments); + const verbose = normalizeFdSpecificOption(rawOptions, "verbose"); + const verboseInfo = getVerboseInfo(verbose, escapedCommand, { ...rawOptions }); + logCommand(escapedCommand, verboseInfo); + return { + command, + escapedCommand, + startTime, + verboseInfo + }; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/options.js +var import_node_path5 = __toESM(require("path"), 1); +var import_node_process8 = __toESM(require("process"), 1); +var import_cross_spawn = __toESM(require_cross_spawn(), 1); + +// ../../node_modules/.pnpm/npm-run-path@6.0.0/node_modules/npm-run-path/index.js +var import_node_process5 = __toESM(require("process"), 1); +var import_node_path2 = __toESM(require("path"), 1); + +// ../../node_modules/.pnpm/path-key@4.0.0/node_modules/path-key/index.js +function pathKey(options = {}) { + const { + env = process.env, + platform: platform2 = process.platform + } = options; + if (platform2 !== "win32") { + return "PATH"; + } + return Object.keys(env).reverse().find((key) => key.toUpperCase() === "PATH") || "Path"; +} + +// ../../node_modules/.pnpm/unicorn-magic@0.3.0/node_modules/unicorn-magic/node.js +var import_node_util4 = require("util"); +var import_node_child_process2 = require("child_process"); +var import_node_path = __toESM(require("path"), 1); +var import_node_url2 = require("url"); +var execFileOriginal = (0, import_node_util4.promisify)(import_node_child_process2.execFile); +function toPath(urlOrPath) { + return urlOrPath instanceof URL ? (0, import_node_url2.fileURLToPath)(urlOrPath) : urlOrPath; +} +function traversePathUp(startPath) { + return { + *[Symbol.iterator]() { + let currentPath = import_node_path.default.resolve(toPath(startPath)); + let previousPath; + while (previousPath !== currentPath) { + yield currentPath; + previousPath = currentPath; + currentPath = import_node_path.default.resolve(currentPath, ".."); + } + } + }; +} +var TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024; + +// ../../node_modules/.pnpm/npm-run-path@6.0.0/node_modules/npm-run-path/index.js +var npmRunPath = ({ + cwd = import_node_process5.default.cwd(), + path: pathOption = import_node_process5.default.env[pathKey()], + preferLocal = true, + execPath: execPath2 = import_node_process5.default.execPath, + addExecPath = true +} = {}) => { + const cwdPath = import_node_path2.default.resolve(toPath(cwd)); + const result = []; + const pathParts = pathOption.split(import_node_path2.default.delimiter); + if (preferLocal) { + applyPreferLocal(result, pathParts, cwdPath); + } + if (addExecPath) { + applyExecPath(result, pathParts, execPath2, cwdPath); + } + return pathOption === "" || pathOption === import_node_path2.default.delimiter ? `${result.join(import_node_path2.default.delimiter)}${pathOption}` : [...result, pathOption].join(import_node_path2.default.delimiter); +}; +var applyPreferLocal = (result, pathParts, cwdPath) => { + for (const directory of traversePathUp(cwdPath)) { + const pathPart = import_node_path2.default.join(directory, "node_modules/.bin"); + if (!pathParts.includes(pathPart)) { + result.push(pathPart); + } + } +}; +var applyExecPath = (result, pathParts, execPath2, cwdPath) => { + const pathPart = import_node_path2.default.resolve(cwdPath, toPath(execPath2), ".."); + if (!pathParts.includes(pathPart)) { + result.push(pathPart); + } +}; +var npmRunPathEnv = ({ env = import_node_process5.default.env, ...options } = {}) => { + env = { ...env }; + const pathName = pathKey({ env }); + options.path = env[pathName]; + env[pathName] = npmRunPath(options); + return env; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/kill.js +var import_promises = require("timers/promises"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/final-error.js +var getFinalError = (originalError, message, isSync) => { + const ErrorClass = isSync ? ExecaSyncError : ExecaError; + const options = originalError instanceof DiscardedError ? {} : { cause: originalError }; + return new ErrorClass(message, options); +}; +var DiscardedError = class extends Error { +}; +var setErrorName = (ErrorClass, value) => { + Object.defineProperty(ErrorClass.prototype, "name", { + value, + writable: true, + enumerable: false, + configurable: true + }); + Object.defineProperty(ErrorClass.prototype, execaErrorSymbol, { + value: true, + writable: false, + enumerable: false, + configurable: false + }); +}; +var isExecaError = (error) => isErrorInstance(error) && execaErrorSymbol in error; +var execaErrorSymbol = /* @__PURE__ */ Symbol("isExecaError"); +var isErrorInstance = (value) => Object.prototype.toString.call(value) === "[object Error]"; +var ExecaError = class extends Error { +}; +setErrorName(ExecaError, ExecaError.name); +var ExecaSyncError = class extends Error { +}; +setErrorName(ExecaSyncError, ExecaSyncError.name); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/signal.js +var import_node_os3 = require("os"); + +// ../../node_modules/.pnpm/human-signals@8.0.1/node_modules/human-signals/build/src/main.js +var import_node_os2 = require("os"); + +// ../../node_modules/.pnpm/human-signals@8.0.1/node_modules/human-signals/build/src/realtime.js +var getRealtimeSignals = () => { + const length = SIGRTMAX - SIGRTMIN + 1; + return Array.from({ length }, getRealtimeSignal); +}; +var getRealtimeSignal = (value, index) => ({ + name: `SIGRT${index + 1}`, + number: SIGRTMIN + index, + action: "terminate", + description: "Application-specific signal (realtime)", + standard: "posix" +}); +var SIGRTMIN = 34; +var SIGRTMAX = 64; + +// ../../node_modules/.pnpm/human-signals@8.0.1/node_modules/human-signals/build/src/signals.js +var import_node_os = require("os"); + +// ../../node_modules/.pnpm/human-signals@8.0.1/node_modules/human-signals/build/src/core.js +var SIGNALS = [ + { + name: "SIGHUP", + number: 1, + action: "terminate", + description: "Terminal closed", + standard: "posix" + }, + { + name: "SIGINT", + number: 2, + action: "terminate", + description: "User interruption with CTRL-C", + standard: "ansi" + }, + { + name: "SIGQUIT", + number: 3, + action: "core", + description: "User interruption with CTRL-\\", + standard: "posix" + }, + { + name: "SIGILL", + number: 4, + action: "core", + description: "Invalid machine instruction", + standard: "ansi" + }, + { + name: "SIGTRAP", + number: 5, + action: "core", + description: "Debugger breakpoint", + standard: "posix" + }, + { + name: "SIGABRT", + number: 6, + action: "core", + description: "Aborted", + standard: "ansi" + }, + { + name: "SIGIOT", + number: 6, + action: "core", + description: "Aborted", + standard: "bsd" + }, + { + name: "SIGBUS", + number: 7, + action: "core", + description: "Bus error due to misaligned, non-existing address or paging error", + standard: "bsd" + }, + { + name: "SIGEMT", + number: 7, + action: "terminate", + description: "Command should be emulated but is not implemented", + standard: "other" + }, + { + name: "SIGFPE", + number: 8, + action: "core", + description: "Floating point arithmetic error", + standard: "ansi" + }, + { + name: "SIGKILL", + number: 9, + action: "terminate", + description: "Forced termination", + standard: "posix", + forced: true + }, + { + name: "SIGUSR1", + number: 10, + action: "terminate", + description: "Application-specific signal", + standard: "posix" + }, + { + name: "SIGSEGV", + number: 11, + action: "core", + description: "Segmentation fault", + standard: "ansi" + }, + { + name: "SIGUSR2", + number: 12, + action: "terminate", + description: "Application-specific signal", + standard: "posix" + }, + { + name: "SIGPIPE", + number: 13, + action: "terminate", + description: "Broken pipe or socket", + standard: "posix" + }, + { + name: "SIGALRM", + number: 14, + action: "terminate", + description: "Timeout or timer", + standard: "posix" + }, + { + name: "SIGTERM", + number: 15, + action: "terminate", + description: "Termination", + standard: "ansi" + }, + { + name: "SIGSTKFLT", + number: 16, + action: "terminate", + description: "Stack is empty or overflowed", + standard: "other" + }, + { + name: "SIGCHLD", + number: 17, + action: "ignore", + description: "Child process terminated, paused or unpaused", + standard: "posix" + }, + { + name: "SIGCLD", + number: 17, + action: "ignore", + description: "Child process terminated, paused or unpaused", + standard: "other" + }, + { + name: "SIGCONT", + number: 18, + action: "unpause", + description: "Unpaused", + standard: "posix", + forced: true + }, + { + name: "SIGSTOP", + number: 19, + action: "pause", + description: "Paused", + standard: "posix", + forced: true + }, + { + name: "SIGTSTP", + number: 20, + action: "pause", + description: 'Paused using CTRL-Z or "suspend"', + standard: "posix" + }, + { + name: "SIGTTIN", + number: 21, + action: "pause", + description: "Background process cannot read terminal input", + standard: "posix" + }, + { + name: "SIGBREAK", + number: 21, + action: "terminate", + description: "User interruption with CTRL-BREAK", + standard: "other" + }, + { + name: "SIGTTOU", + number: 22, + action: "pause", + description: "Background process cannot write to terminal output", + standard: "posix" + }, + { + name: "SIGURG", + number: 23, + action: "ignore", + description: "Socket received out-of-band data", + standard: "bsd" + }, + { + name: "SIGXCPU", + number: 24, + action: "core", + description: "Process timed out", + standard: "bsd" + }, + { + name: "SIGXFSZ", + number: 25, + action: "core", + description: "File too big", + standard: "bsd" + }, + { + name: "SIGVTALRM", + number: 26, + action: "terminate", + description: "Timeout or timer", + standard: "bsd" + }, + { + name: "SIGPROF", + number: 27, + action: "terminate", + description: "Timeout or timer", + standard: "bsd" + }, + { + name: "SIGWINCH", + number: 28, + action: "ignore", + description: "Terminal window size changed", + standard: "bsd" + }, + { + name: "SIGIO", + number: 29, + action: "terminate", + description: "I/O is available", + standard: "other" + }, + { + name: "SIGPOLL", + number: 29, + action: "terminate", + description: "Watched event", + standard: "other" + }, + { + name: "SIGINFO", + number: 29, + action: "ignore", + description: "Request for process information", + standard: "other" + }, + { + name: "SIGPWR", + number: 30, + action: "terminate", + description: "Device running out of power", + standard: "systemv" + }, + { + name: "SIGSYS", + number: 31, + action: "core", + description: "Invalid system call", + standard: "other" + }, + { + name: "SIGUNUSED", + number: 31, + action: "terminate", + description: "Invalid system call", + standard: "other" + } +]; + +// ../../node_modules/.pnpm/human-signals@8.0.1/node_modules/human-signals/build/src/signals.js +var getSignals = () => { + const realtimeSignals = getRealtimeSignals(); + const signals2 = [...SIGNALS, ...realtimeSignals].map(normalizeSignal); + return signals2; +}; +var normalizeSignal = ({ + name, + number: defaultNumber, + description, + action, + forced = false, + standard +}) => { + const { + signals: { [name]: constantSignal } + } = import_node_os.constants; + const supported = constantSignal !== void 0; + const number = supported ? constantSignal : defaultNumber; + return { name, number, description, supported, action, forced, standard }; +}; + +// ../../node_modules/.pnpm/human-signals@8.0.1/node_modules/human-signals/build/src/main.js +var getSignalsByName = () => { + const signals2 = getSignals(); + return Object.fromEntries(signals2.map(getSignalByName)); +}; +var getSignalByName = ({ + name, + number, + description, + supported, + action, + forced, + standard +}) => [name, { name, number, description, supported, action, forced, standard }]; +var signalsByName = getSignalsByName(); +var getSignalsByNumber = () => { + const signals2 = getSignals(); + const length = SIGRTMAX + 1; + const signalsA = Array.from( + { length }, + (value, number) => getSignalByNumber(number, signals2) + ); + return Object.assign({}, ...signalsA); +}; +var getSignalByNumber = (number, signals2) => { + const signal = findSignalByNumber(number, signals2); + if (signal === void 0) { + return {}; + } + const { name, description, supported, action, forced, standard } = signal; + return { + [number]: { + name, + number, + description, + supported, + action, + forced, + standard + } + }; +}; +var findSignalByNumber = (number, signals2) => { + const signal = signals2.find(({ name }) => import_node_os2.constants.signals[name] === number); + if (signal !== void 0) { + return signal; + } + return signals2.find((signalA) => signalA.number === number); +}; +var signalsByNumber = getSignalsByNumber(); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/signal.js +var normalizeKillSignal = (killSignal) => { + const optionName = "option `killSignal`"; + if (killSignal === 0) { + throw new TypeError(`Invalid ${optionName}: 0 cannot be used.`); + } + return normalizeSignal2(killSignal, optionName); +}; +var normalizeSignalArgument = (signal) => signal === 0 ? signal : normalizeSignal2(signal, "`subprocess.kill()`'s argument"); +var normalizeSignal2 = (signalNameOrInteger, optionName) => { + if (Number.isInteger(signalNameOrInteger)) { + return normalizeSignalInteger(signalNameOrInteger, optionName); + } + if (typeof signalNameOrInteger === "string") { + return normalizeSignalName(signalNameOrInteger, optionName); + } + throw new TypeError(`Invalid ${optionName} ${String(signalNameOrInteger)}: it must be a string or an integer. +${getAvailableSignals()}`); +}; +var normalizeSignalInteger = (signalInteger, optionName) => { + if (signalsIntegerToName.has(signalInteger)) { + return signalsIntegerToName.get(signalInteger); + } + throw new TypeError(`Invalid ${optionName} ${signalInteger}: this signal integer does not exist. +${getAvailableSignals()}`); +}; +var getSignalsIntegerToName = () => new Map(Object.entries(import_node_os3.constants.signals).reverse().map(([signalName, signalInteger]) => [signalInteger, signalName])); +var signalsIntegerToName = getSignalsIntegerToName(); +var normalizeSignalName = (signalName, optionName) => { + if (signalName in import_node_os3.constants.signals) { + return signalName; + } + if (signalName.toUpperCase() in import_node_os3.constants.signals) { + throw new TypeError(`Invalid ${optionName} '${signalName}': please rename it to '${signalName.toUpperCase()}'.`); + } + throw new TypeError(`Invalid ${optionName} '${signalName}': this signal name does not exist. +${getAvailableSignals()}`); +}; +var getAvailableSignals = () => `Available signal names: ${getAvailableSignalNames()}. +Available signal numbers: ${getAvailableSignalIntegers()}.`; +var getAvailableSignalNames = () => Object.keys(import_node_os3.constants.signals).sort().map((signalName) => `'${signalName}'`).join(", "); +var getAvailableSignalIntegers = () => [...new Set(Object.values(import_node_os3.constants.signals).sort((signalInteger, signalIntegerTwo) => signalInteger - signalIntegerTwo))].join(", "); +var getSignalDescription = (signal) => signalsByName[signal].description; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/kill.js +var normalizeForceKillAfterDelay = (forceKillAfterDelay) => { + if (forceKillAfterDelay === false) { + return forceKillAfterDelay; + } + if (forceKillAfterDelay === true) { + return DEFAULT_FORCE_KILL_TIMEOUT; + } + if (!Number.isFinite(forceKillAfterDelay) || forceKillAfterDelay < 0) { + throw new TypeError(`Expected the \`forceKillAfterDelay\` option to be a non-negative integer, got \`${forceKillAfterDelay}\` (${typeof forceKillAfterDelay})`); + } + return forceKillAfterDelay; +}; +var DEFAULT_FORCE_KILL_TIMEOUT = 1e3 * 5; +var subprocessKill = ({ kill, options: { forceKillAfterDelay, killSignal }, onInternalError, context, controller }, signalOrError, errorArgument) => { + const { signal, error } = parseKillArguments(signalOrError, errorArgument, killSignal); + emitKillError(error, onInternalError); + const killResult = kill(signal); + setKillTimeout({ + kill, + signal, + forceKillAfterDelay, + killSignal, + killResult, + context, + controller + }); + return killResult; +}; +var parseKillArguments = (signalOrError, errorArgument, killSignal) => { + const [signal = killSignal, error] = isErrorInstance(signalOrError) ? [void 0, signalOrError] : [signalOrError, errorArgument]; + if (typeof signal !== "string" && !Number.isInteger(signal)) { + throw new TypeError(`The first argument must be an error instance or a signal name string/integer: ${String(signal)}`); + } + if (error !== void 0 && !isErrorInstance(error)) { + throw new TypeError(`The second argument is optional. If specified, it must be an error instance: ${error}`); + } + return { signal: normalizeSignalArgument(signal), error }; +}; +var emitKillError = (error, onInternalError) => { + if (error !== void 0) { + onInternalError.reject(error); + } +}; +var setKillTimeout = async ({ kill, signal, forceKillAfterDelay, killSignal, killResult, context, controller }) => { + if (signal === killSignal && killResult) { + killOnTimeout({ + kill, + forceKillAfterDelay, + context, + controllerSignal: controller.signal + }); + } +}; +var killOnTimeout = async ({ kill, forceKillAfterDelay, context, controllerSignal }) => { + if (forceKillAfterDelay === false) { + return; + } + try { + await (0, import_promises.setTimeout)(forceKillAfterDelay, void 0, { signal: controllerSignal }); + if (kill("SIGKILL")) { + context.isForcefullyTerminated ??= true; + } + } catch { + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/utils/abort-signal.js +var import_node_events = require("events"); +var onAbortedSignal = async (mainSignal, stopSignal) => { + if (!mainSignal.aborted) { + await (0, import_node_events.once)(mainSignal, "abort", { signal: stopSignal }); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/cancel.js +var validateCancelSignal = ({ cancelSignal }) => { + if (cancelSignal !== void 0 && Object.prototype.toString.call(cancelSignal) !== "[object AbortSignal]") { + throw new Error(`The \`cancelSignal\` option must be an AbortSignal: ${String(cancelSignal)}`); + } +}; +var throwOnCancel = ({ subprocess, cancelSignal, gracefulCancel, context, controller }) => cancelSignal === void 0 || gracefulCancel ? [] : [terminateOnCancel(subprocess, cancelSignal, context, controller)]; +var terminateOnCancel = async (subprocess, cancelSignal, context, { signal }) => { + await onAbortedSignal(cancelSignal, signal); + context.terminationReason ??= "cancel"; + subprocess.kill(); + throw cancelSignal.reason; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/graceful.js +var import_promises3 = require("timers/promises"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/send.js +var import_node_util5 = require("util"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/validation.js +var validateIpcMethod = ({ methodName, isSubprocess, ipc, isConnected: isConnected2 }) => { + validateIpcOption(methodName, isSubprocess, ipc); + validateConnection(methodName, isSubprocess, isConnected2); +}; +var validateIpcOption = (methodName, isSubprocess, ipc) => { + if (!ipc) { + throw new Error(`${getMethodName(methodName, isSubprocess)} can only be used if the \`ipc\` option is \`true\`.`); + } +}; +var validateConnection = (methodName, isSubprocess, isConnected2) => { + if (!isConnected2) { + throw new Error(`${getMethodName(methodName, isSubprocess)} cannot be used: the ${getOtherProcessName(isSubprocess)} has already exited or disconnected.`); + } +}; +var throwOnEarlyDisconnect = (isSubprocess) => { + throw new Error(`${getMethodName("getOneMessage", isSubprocess)} could not complete: the ${getOtherProcessName(isSubprocess)} exited or disconnected.`); +}; +var throwOnStrictDeadlockError = (isSubprocess) => { + throw new Error(`${getMethodName("sendMessage", isSubprocess)} failed: the ${getOtherProcessName(isSubprocess)} is sending a message too, instead of listening to incoming messages. +This can be fixed by both sending a message and listening to incoming messages at the same time: + +const [receivedMessage] = await Promise.all([ + ${getMethodName("getOneMessage", isSubprocess)}, + ${getMethodName("sendMessage", isSubprocess, "message, {strict: true}")}, +]);`); +}; +var getStrictResponseError = (error, isSubprocess) => new Error(`${getMethodName("sendMessage", isSubprocess)} failed when sending an acknowledgment response to the ${getOtherProcessName(isSubprocess)}.`, { cause: error }); +var throwOnMissingStrict = (isSubprocess) => { + throw new Error(`${getMethodName("sendMessage", isSubprocess)} failed: the ${getOtherProcessName(isSubprocess)} is not listening to incoming messages.`); +}; +var throwOnStrictDisconnect = (isSubprocess) => { + throw new Error(`${getMethodName("sendMessage", isSubprocess)} failed: the ${getOtherProcessName(isSubprocess)} exited without listening to incoming messages.`); +}; +var getAbortDisconnectError = () => new Error(`\`cancelSignal\` aborted: the ${getOtherProcessName(true)} disconnected.`); +var throwOnMissingParent = () => { + throw new Error("`getCancelSignal()` cannot be used without setting the `cancelSignal` subprocess option."); +}; +var handleEpipeError = ({ error, methodName, isSubprocess }) => { + if (error.code === "EPIPE") { + throw new Error(`${getMethodName(methodName, isSubprocess)} cannot be used: the ${getOtherProcessName(isSubprocess)} is disconnecting.`, { cause: error }); + } +}; +var handleSerializationError = ({ error, methodName, isSubprocess, message }) => { + if (isSerializationError(error)) { + throw new Error(`${getMethodName(methodName, isSubprocess)}'s argument type is invalid: the message cannot be serialized: ${String(message)}.`, { cause: error }); + } +}; +var isSerializationError = ({ code: code2, message }) => SERIALIZATION_ERROR_CODES.has(code2) || SERIALIZATION_ERROR_MESSAGES.some((serializationErrorMessage) => message.includes(serializationErrorMessage)); +var SERIALIZATION_ERROR_CODES = /* @__PURE__ */ new Set([ + // Message is `undefined` + "ERR_MISSING_ARGS", + // Message is a function, a bigint, a symbol + "ERR_INVALID_ARG_TYPE" +]); +var SERIALIZATION_ERROR_MESSAGES = [ + // Message is a promise or a proxy, with `serialization: 'advanced'` + "could not be cloned", + // Message has cycles, with `serialization: 'json'` + "circular structure", + // Message has cycles inside toJSON(), with `serialization: 'json'` + "call stack size exceeded" +]; +var getMethodName = (methodName, isSubprocess, parameters = "") => methodName === "cancelSignal" ? "`cancelSignal`'s `controller.abort()`" : `${getNamespaceName(isSubprocess)}${methodName}(${parameters})`; +var getNamespaceName = (isSubprocess) => isSubprocess ? "" : "subprocess."; +var getOtherProcessName = (isSubprocess) => isSubprocess ? "parent process" : "subprocess"; +var disconnect = (anyProcess) => { + if (anyProcess.connected) { + anyProcess.disconnect(); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/utils/deferred.js +var createDeferred = () => { + const methods = {}; + const promise = new Promise((resolve, reject) => { + Object.assign(methods, { resolve, reject }); + }); + return Object.assign(promise, methods); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/fd-options.js +var getToStream = (destination, to = "stdin") => { + const isWritable = true; + const { options, fileDescriptors } = SUBPROCESS_OPTIONS.get(destination); + const fdNumber = getFdNumber(fileDescriptors, to, isWritable); + const destinationStream = destination.stdio[fdNumber]; + if (destinationStream === null) { + throw new TypeError(getInvalidStdioOptionMessage(fdNumber, to, options, isWritable)); + } + return destinationStream; +}; +var getFromStream = (source, from = "stdout") => { + const isWritable = false; + const { options, fileDescriptors } = SUBPROCESS_OPTIONS.get(source); + const fdNumber = getFdNumber(fileDescriptors, from, isWritable); + const sourceStream = fdNumber === "all" ? source.all : source.stdio[fdNumber]; + if (sourceStream === null || sourceStream === void 0) { + throw new TypeError(getInvalidStdioOptionMessage(fdNumber, from, options, isWritable)); + } + return sourceStream; +}; +var SUBPROCESS_OPTIONS = /* @__PURE__ */ new WeakMap(); +var getFdNumber = (fileDescriptors, fdName, isWritable) => { + const fdNumber = parseFdNumber(fdName, isWritable); + validateFdNumber(fdNumber, fdName, isWritable, fileDescriptors); + return fdNumber; +}; +var parseFdNumber = (fdName, isWritable) => { + const fdNumber = parseFd(fdName); + if (fdNumber !== void 0) { + return fdNumber; + } + const { validOptions, defaultValue } = isWritable ? { validOptions: '"stdin"', defaultValue: "stdin" } : { validOptions: '"stdout", "stderr", "all"', defaultValue: "stdout" }; + throw new TypeError(`"${getOptionName(isWritable)}" must not be "${fdName}". +It must be ${validOptions} or "fd3", "fd4" (and so on). +It is optional and defaults to "${defaultValue}".`); +}; +var validateFdNumber = (fdNumber, fdName, isWritable, fileDescriptors) => { + const fileDescriptor = fileDescriptors[getUsedDescriptor(fdNumber)]; + if (fileDescriptor === void 0) { + throw new TypeError(`"${getOptionName(isWritable)}" must not be ${fdName}. That file descriptor does not exist. +Please set the "stdio" option to ensure that file descriptor exists.`); + } + if (fileDescriptor.direction === "input" && !isWritable) { + throw new TypeError(`"${getOptionName(isWritable)}" must not be ${fdName}. It must be a readable stream, not writable.`); + } + if (fileDescriptor.direction !== "input" && isWritable) { + throw new TypeError(`"${getOptionName(isWritable)}" must not be ${fdName}. It must be a writable stream, not readable.`); + } +}; +var getInvalidStdioOptionMessage = (fdNumber, fdName, options, isWritable) => { + if (fdNumber === "all" && !options.all) { + return `The "all" option must be true to use "from: 'all'".`; + } + const { optionName, optionValue } = getInvalidStdioOption(fdNumber, options); + return `The "${optionName}: ${serializeOptionValue(optionValue)}" option is incompatible with using "${getOptionName(isWritable)}: ${serializeOptionValue(fdName)}". +Please set this option with "pipe" instead.`; +}; +var getInvalidStdioOption = (fdNumber, { stdin, stdout, stderr, stdio }) => { + const usedDescriptor = getUsedDescriptor(fdNumber); + if (usedDescriptor === 0 && stdin !== void 0) { + return { optionName: "stdin", optionValue: stdin }; + } + if (usedDescriptor === 1 && stdout !== void 0) { + return { optionName: "stdout", optionValue: stdout }; + } + if (usedDescriptor === 2 && stderr !== void 0) { + return { optionName: "stderr", optionValue: stderr }; + } + return { optionName: `stdio[${usedDescriptor}]`, optionValue: stdio[usedDescriptor] }; +}; +var getUsedDescriptor = (fdNumber) => fdNumber === "all" ? 1 : fdNumber; +var getOptionName = (isWritable) => isWritable ? "to" : "from"; +var serializeOptionValue = (value) => { + if (typeof value === "string") { + return `'${value}'`; + } + return typeof value === "number" ? `${value}` : "Stream"; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/strict.js +var import_node_events5 = require("events"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/utils/max-listeners.js +var import_node_events2 = require("events"); +var incrementMaxListeners = (eventEmitter, maxListenersIncrement, signal) => { + const maxListeners = eventEmitter.getMaxListeners(); + if (maxListeners === 0 || maxListeners === Number.POSITIVE_INFINITY) { + return; + } + eventEmitter.setMaxListeners(maxListeners + maxListenersIncrement); + (0, import_node_events2.addAbortListener)(signal, () => { + eventEmitter.setMaxListeners(eventEmitter.getMaxListeners() - maxListenersIncrement); + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/forward.js +var import_node_events4 = require("events"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/incoming.js +var import_node_events3 = require("events"); +var import_promises2 = require("timers/promises"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/reference.js +var addReference = (channel, reference) => { + if (reference) { + addReferenceCount(channel); + } +}; +var addReferenceCount = (channel) => { + channel.refCounted(); +}; +var removeReference = (channel, reference) => { + if (reference) { + removeReferenceCount(channel); + } +}; +var removeReferenceCount = (channel) => { + channel.unrefCounted(); +}; +var undoAddedReferences = (channel, isSubprocess) => { + if (isSubprocess) { + removeReferenceCount(channel); + removeReferenceCount(channel); + } +}; +var redoAddedReferences = (channel, isSubprocess) => { + if (isSubprocess) { + addReferenceCount(channel); + addReferenceCount(channel); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/incoming.js +var onMessage = async ({ anyProcess, channel, isSubprocess, ipcEmitter }, wrappedMessage) => { + if (handleStrictResponse(wrappedMessage) || handleAbort(wrappedMessage)) { + return; + } + if (!INCOMING_MESSAGES.has(anyProcess)) { + INCOMING_MESSAGES.set(anyProcess, []); + } + const incomingMessages = INCOMING_MESSAGES.get(anyProcess); + incomingMessages.push(wrappedMessage); + if (incomingMessages.length > 1) { + return; + } + while (incomingMessages.length > 0) { + await waitForOutgoingMessages(anyProcess, ipcEmitter, wrappedMessage); + await import_promises2.scheduler.yield(); + const message = await handleStrictRequest({ + wrappedMessage: incomingMessages[0], + anyProcess, + channel, + isSubprocess, + ipcEmitter + }); + incomingMessages.shift(); + ipcEmitter.emit("message", message); + ipcEmitter.emit("message:done"); + } +}; +var onDisconnect = async ({ anyProcess, channel, isSubprocess, ipcEmitter, boundOnMessage }) => { + abortOnDisconnect(); + const incomingMessages = INCOMING_MESSAGES.get(anyProcess); + while (incomingMessages?.length > 0) { + await (0, import_node_events3.once)(ipcEmitter, "message:done"); + } + anyProcess.removeListener("message", boundOnMessage); + redoAddedReferences(channel, isSubprocess); + ipcEmitter.connected = false; + ipcEmitter.emit("disconnect"); +}; +var INCOMING_MESSAGES = /* @__PURE__ */ new WeakMap(); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/forward.js +var getIpcEmitter = (anyProcess, channel, isSubprocess) => { + if (IPC_EMITTERS.has(anyProcess)) { + return IPC_EMITTERS.get(anyProcess); + } + const ipcEmitter = new import_node_events4.EventEmitter(); + ipcEmitter.connected = true; + IPC_EMITTERS.set(anyProcess, ipcEmitter); + forwardEvents({ + ipcEmitter, + anyProcess, + channel, + isSubprocess + }); + return ipcEmitter; +}; +var IPC_EMITTERS = /* @__PURE__ */ new WeakMap(); +var forwardEvents = ({ ipcEmitter, anyProcess, channel, isSubprocess }) => { + const boundOnMessage = onMessage.bind(void 0, { + anyProcess, + channel, + isSubprocess, + ipcEmitter + }); + anyProcess.on("message", boundOnMessage); + anyProcess.once("disconnect", onDisconnect.bind(void 0, { + anyProcess, + channel, + isSubprocess, + ipcEmitter, + boundOnMessage + })); + undoAddedReferences(channel, isSubprocess); +}; +var isConnected = (anyProcess) => { + const ipcEmitter = IPC_EMITTERS.get(anyProcess); + return ipcEmitter === void 0 ? anyProcess.channel !== null : ipcEmitter.connected; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/strict.js +var handleSendStrict = ({ anyProcess, channel, isSubprocess, message, strict }) => { + if (!strict) { + return message; + } + const ipcEmitter = getIpcEmitter(anyProcess, channel, isSubprocess); + const hasListeners = hasMessageListeners(anyProcess, ipcEmitter); + return { + id: count++, + type: REQUEST_TYPE, + message, + hasListeners + }; +}; +var count = 0n; +var validateStrictDeadlock = (outgoingMessages, wrappedMessage) => { + if (wrappedMessage?.type !== REQUEST_TYPE || wrappedMessage.hasListeners) { + return; + } + for (const { id } of outgoingMessages) { + if (id !== void 0) { + STRICT_RESPONSES[id].resolve({ isDeadlock: true, hasListeners: false }); + } + } +}; +var handleStrictRequest = async ({ wrappedMessage, anyProcess, channel, isSubprocess, ipcEmitter }) => { + if (wrappedMessage?.type !== REQUEST_TYPE || !anyProcess.connected) { + return wrappedMessage; + } + const { id, message } = wrappedMessage; + const response = { id, type: RESPONSE_TYPE, message: hasMessageListeners(anyProcess, ipcEmitter) }; + try { + await sendMessage({ + anyProcess, + channel, + isSubprocess, + ipc: true + }, response); + } catch (error) { + ipcEmitter.emit("strict:error", error); + } + return message; +}; +var handleStrictResponse = (wrappedMessage) => { + if (wrappedMessage?.type !== RESPONSE_TYPE) { + return false; + } + const { id, message: hasListeners } = wrappedMessage; + STRICT_RESPONSES[id]?.resolve({ isDeadlock: false, hasListeners }); + return true; +}; +var waitForStrictResponse = async (wrappedMessage, anyProcess, isSubprocess) => { + if (wrappedMessage?.type !== REQUEST_TYPE) { + return; + } + const deferred = createDeferred(); + STRICT_RESPONSES[wrappedMessage.id] = deferred; + const controller = new AbortController(); + try { + const { isDeadlock, hasListeners } = await Promise.race([ + deferred, + throwOnDisconnect(anyProcess, isSubprocess, controller) + ]); + if (isDeadlock) { + throwOnStrictDeadlockError(isSubprocess); + } + if (!hasListeners) { + throwOnMissingStrict(isSubprocess); + } + } finally { + controller.abort(); + delete STRICT_RESPONSES[wrappedMessage.id]; + } +}; +var STRICT_RESPONSES = {}; +var throwOnDisconnect = async (anyProcess, isSubprocess, { signal }) => { + incrementMaxListeners(anyProcess, 1, signal); + await (0, import_node_events5.once)(anyProcess, "disconnect", { signal }); + throwOnStrictDisconnect(isSubprocess); +}; +var REQUEST_TYPE = "execa:ipc:request"; +var RESPONSE_TYPE = "execa:ipc:response"; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/outgoing.js +var startSendMessage = (anyProcess, wrappedMessage, strict) => { + if (!OUTGOING_MESSAGES.has(anyProcess)) { + OUTGOING_MESSAGES.set(anyProcess, /* @__PURE__ */ new Set()); + } + const outgoingMessages = OUTGOING_MESSAGES.get(anyProcess); + const onMessageSent = createDeferred(); + const id = strict ? wrappedMessage.id : void 0; + const outgoingMessage = { onMessageSent, id }; + outgoingMessages.add(outgoingMessage); + return { outgoingMessages, outgoingMessage }; +}; +var endSendMessage = ({ outgoingMessages, outgoingMessage }) => { + outgoingMessages.delete(outgoingMessage); + outgoingMessage.onMessageSent.resolve(); +}; +var waitForOutgoingMessages = async (anyProcess, ipcEmitter, wrappedMessage) => { + while (!hasMessageListeners(anyProcess, ipcEmitter) && OUTGOING_MESSAGES.get(anyProcess)?.size > 0) { + const outgoingMessages = [...OUTGOING_MESSAGES.get(anyProcess)]; + validateStrictDeadlock(outgoingMessages, wrappedMessage); + await Promise.all(outgoingMessages.map(({ onMessageSent }) => onMessageSent)); + } +}; +var OUTGOING_MESSAGES = /* @__PURE__ */ new WeakMap(); +var hasMessageListeners = (anyProcess, ipcEmitter) => ipcEmitter.listenerCount("message") > getMinListenerCount(anyProcess); +var getMinListenerCount = (anyProcess) => SUBPROCESS_OPTIONS.has(anyProcess) && !getFdSpecificValue(SUBPROCESS_OPTIONS.get(anyProcess).options.buffer, "ipc") ? 1 : 0; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/send.js +var sendMessage = ({ anyProcess, channel, isSubprocess, ipc }, message, { strict = false } = {}) => { + const methodName = "sendMessage"; + validateIpcMethod({ + methodName, + isSubprocess, + ipc, + isConnected: anyProcess.connected + }); + return sendMessageAsync({ + anyProcess, + channel, + methodName, + isSubprocess, + message, + strict + }); +}; +var sendMessageAsync = async ({ anyProcess, channel, methodName, isSubprocess, message, strict }) => { + const wrappedMessage = handleSendStrict({ + anyProcess, + channel, + isSubprocess, + message, + strict + }); + const outgoingMessagesState = startSendMessage(anyProcess, wrappedMessage, strict); + try { + await sendOneMessage({ + anyProcess, + methodName, + isSubprocess, + wrappedMessage, + message + }); + } catch (error) { + disconnect(anyProcess); + throw error; + } finally { + endSendMessage(outgoingMessagesState); + } +}; +var sendOneMessage = async ({ anyProcess, methodName, isSubprocess, wrappedMessage, message }) => { + const sendMethod = getSendMethod(anyProcess); + try { + await Promise.all([ + waitForStrictResponse(wrappedMessage, anyProcess, isSubprocess), + sendMethod(wrappedMessage) + ]); + } catch (error) { + handleEpipeError({ error, methodName, isSubprocess }); + handleSerializationError({ + error, + methodName, + isSubprocess, + message + }); + throw error; + } +}; +var getSendMethod = (anyProcess) => { + if (PROCESS_SEND_METHODS.has(anyProcess)) { + return PROCESS_SEND_METHODS.get(anyProcess); + } + const sendMethod = (0, import_node_util5.promisify)(anyProcess.send.bind(anyProcess)); + PROCESS_SEND_METHODS.set(anyProcess, sendMethod); + return sendMethod; +}; +var PROCESS_SEND_METHODS = /* @__PURE__ */ new WeakMap(); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/graceful.js +var sendAbort = (subprocess, message) => { + const methodName = "cancelSignal"; + validateConnection(methodName, false, subprocess.connected); + return sendOneMessage({ + anyProcess: subprocess, + methodName, + isSubprocess: false, + wrappedMessage: { type: GRACEFUL_CANCEL_TYPE, message }, + message + }); +}; +var getCancelSignal = async ({ anyProcess, channel, isSubprocess, ipc }) => { + await startIpc({ + anyProcess, + channel, + isSubprocess, + ipc + }); + return cancelController.signal; +}; +var startIpc = async ({ anyProcess, channel, isSubprocess, ipc }) => { + if (cancelListening) { + return; + } + cancelListening = true; + if (!ipc) { + throwOnMissingParent(); + return; + } + if (channel === null) { + abortOnDisconnect(); + return; + } + getIpcEmitter(anyProcess, channel, isSubprocess); + await import_promises3.scheduler.yield(); +}; +var cancelListening = false; +var handleAbort = (wrappedMessage) => { + if (wrappedMessage?.type !== GRACEFUL_CANCEL_TYPE) { + return false; + } + cancelController.abort(wrappedMessage.message); + return true; +}; +var GRACEFUL_CANCEL_TYPE = "execa:ipc:cancel"; +var abortOnDisconnect = () => { + cancelController.abort(getAbortDisconnectError()); +}; +var cancelController = new AbortController(); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/graceful.js +var validateGracefulCancel = ({ gracefulCancel, cancelSignal, ipc, serialization }) => { + if (!gracefulCancel) { + return; + } + if (cancelSignal === void 0) { + throw new Error("The `cancelSignal` option must be defined when setting the `gracefulCancel` option."); + } + if (!ipc) { + throw new Error("The `ipc` option cannot be false when setting the `gracefulCancel` option."); + } + if (serialization === "json") { + throw new Error("The `serialization` option cannot be 'json' when setting the `gracefulCancel` option."); + } +}; +var throwOnGracefulCancel = ({ + subprocess, + cancelSignal, + gracefulCancel, + forceKillAfterDelay, + context, + controller +}) => gracefulCancel ? [sendOnAbort({ + subprocess, + cancelSignal, + forceKillAfterDelay, + context, + controller +})] : []; +var sendOnAbort = async ({ subprocess, cancelSignal, forceKillAfterDelay, context, controller: { signal } }) => { + await onAbortedSignal(cancelSignal, signal); + const reason = getReason(cancelSignal); + await sendAbort(subprocess, reason); + killOnTimeout({ + kill: subprocess.kill, + forceKillAfterDelay, + context, + controllerSignal: signal + }); + context.terminationReason ??= "gracefulCancel"; + throw cancelSignal.reason; +}; +var getReason = ({ reason }) => { + if (!(reason instanceof DOMException)) { + return reason; + } + const error = new Error(reason.message); + Object.defineProperty(error, "stack", { + value: reason.stack, + enumerable: false, + configurable: true, + writable: true + }); + return error; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/timeout.js +var import_promises4 = require("timers/promises"); +var validateTimeout = ({ timeout }) => { + if (timeout !== void 0 && (!Number.isFinite(timeout) || timeout < 0)) { + throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); + } +}; +var throwOnTimeout = (subprocess, timeout, context, controller) => timeout === 0 || timeout === void 0 ? [] : [killAfterTimeout(subprocess, timeout, context, controller)]; +var killAfterTimeout = async (subprocess, timeout, context, { signal }) => { + await (0, import_promises4.setTimeout)(timeout, void 0, { signal }); + context.terminationReason ??= "timeout"; + subprocess.kill(); + throw new DiscardedError(); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/node.js +var import_node_process6 = require("process"); +var import_node_path3 = __toESM(require("path"), 1); +var mapNode = ({ options }) => { + if (options.node === false) { + throw new TypeError('The "node" option cannot be false with `execaNode()`.'); + } + return { options: { ...options, node: true } }; +}; +var handleNodeOption = (file, commandArguments, { + node: shouldHandleNode = false, + nodePath = import_node_process6.execPath, + nodeOptions = import_node_process6.execArgv.filter((nodeOption) => !nodeOption.startsWith("--inspect")), + cwd, + execPath: formerNodePath, + ...options +}) => { + if (formerNodePath !== void 0) { + throw new TypeError('The "execPath" option has been removed. Please use the "nodePath" option instead.'); + } + const normalizedNodePath = safeNormalizeFileUrl(nodePath, 'The "nodePath" option'); + const resolvedNodePath = import_node_path3.default.resolve(cwd, normalizedNodePath); + const newOptions = { + ...options, + nodePath: resolvedNodePath, + node: shouldHandleNode, + cwd + }; + if (!shouldHandleNode) { + return [file, commandArguments, newOptions]; + } + if (import_node_path3.default.basename(file, ".exe") === "node") { + throw new TypeError('When the "node" option is true, the first argument does not need to be "node".'); + } + return [ + resolvedNodePath, + [...nodeOptions, file, ...commandArguments], + { ipc: true, ...newOptions, shell: false } + ]; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/ipc-input.js +var import_node_v8 = require("v8"); +var validateIpcInputOption = ({ ipcInput, ipc, serialization }) => { + if (ipcInput === void 0) { + return; + } + if (!ipc) { + throw new Error("The `ipcInput` option cannot be set unless the `ipc` option is `true`."); + } + validateIpcInput[serialization](ipcInput); +}; +var validateAdvancedInput = (ipcInput) => { + try { + (0, import_node_v8.serialize)(ipcInput); + } catch (error) { + throw new Error("The `ipcInput` option is not serializable with a structured clone.", { cause: error }); + } +}; +var validateJsonInput = (ipcInput) => { + try { + JSON.stringify(ipcInput); + } catch (error) { + throw new Error("The `ipcInput` option is not serializable with JSON.", { cause: error }); + } +}; +var validateIpcInput = { + advanced: validateAdvancedInput, + json: validateJsonInput +}; +var sendIpcInput = async (subprocess, ipcInput) => { + if (ipcInput === void 0) { + return; + } + await subprocess.sendMessage(ipcInput); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/encoding-option.js +var validateEncoding = ({ encoding }) => { + if (ENCODINGS.has(encoding)) { + return; + } + const correctEncoding = getCorrectEncoding(encoding); + if (correctEncoding !== void 0) { + throw new TypeError(`Invalid option \`encoding: ${serializeEncoding(encoding)}\`. +Please rename it to ${serializeEncoding(correctEncoding)}.`); + } + const correctEncodings = [...ENCODINGS].map((correctEncoding2) => serializeEncoding(correctEncoding2)).join(", "); + throw new TypeError(`Invalid option \`encoding: ${serializeEncoding(encoding)}\`. +Please rename it to one of: ${correctEncodings}.`); +}; +var TEXT_ENCODINGS = /* @__PURE__ */ new Set(["utf8", "utf16le"]); +var BINARY_ENCODINGS = /* @__PURE__ */ new Set(["buffer", "hex", "base64", "base64url", "latin1", "ascii"]); +var ENCODINGS = /* @__PURE__ */ new Set([...TEXT_ENCODINGS, ...BINARY_ENCODINGS]); +var getCorrectEncoding = (encoding) => { + if (encoding === null) { + return "buffer"; + } + if (typeof encoding !== "string") { + return; + } + const lowerEncoding = encoding.toLowerCase(); + if (lowerEncoding in ENCODING_ALIASES) { + return ENCODING_ALIASES[lowerEncoding]; + } + if (ENCODINGS.has(lowerEncoding)) { + return lowerEncoding; + } +}; +var ENCODING_ALIASES = { + // eslint-disable-next-line unicorn/text-encoding-identifier-case + "utf-8": "utf8", + "utf-16le": "utf16le", + "ucs-2": "utf16le", + ucs2: "utf16le", + binary: "latin1" +}; +var serializeEncoding = (encoding) => typeof encoding === "string" ? `"${encoding}"` : String(encoding); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/cwd.js +var import_node_fs = require("fs"); +var import_node_path4 = __toESM(require("path"), 1); +var import_node_process7 = __toESM(require("process"), 1); +var normalizeCwd = (cwd = getDefaultCwd()) => { + const cwdString = safeNormalizeFileUrl(cwd, 'The "cwd" option'); + return import_node_path4.default.resolve(cwdString); +}; +var getDefaultCwd = () => { + try { + return import_node_process7.default.cwd(); + } catch (error) { + error.message = `The current directory does not exist. +${error.message}`; + throw error; + } +}; +var fixCwdError = (originalMessage, cwd) => { + if (cwd === getDefaultCwd()) { + return originalMessage; + } + let cwdStat; + try { + cwdStat = (0, import_node_fs.statSync)(cwd); + } catch (error) { + return `The "cwd" option is invalid: ${cwd}. +${error.message} +${originalMessage}`; + } + if (!cwdStat.isDirectory()) { + return `The "cwd" option is not a directory: ${cwd}. +${originalMessage}`; + } + return originalMessage; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/options.js +var normalizeOptions = (filePath, rawArguments, rawOptions) => { + rawOptions.cwd = normalizeCwd(rawOptions.cwd); + const [processedFile, processedArguments, processedOptions] = handleNodeOption(filePath, rawArguments, rawOptions); + const { command: file, args: commandArguments, options: initialOptions } = import_cross_spawn.default._parse(processedFile, processedArguments, processedOptions); + const fdOptions = normalizeFdSpecificOptions(initialOptions); + const options = addDefaultOptions(fdOptions); + validateTimeout(options); + validateEncoding(options); + validateIpcInputOption(options); + validateCancelSignal(options); + validateGracefulCancel(options); + options.shell = normalizeFileUrl(options.shell); + options.env = getEnv(options); + options.killSignal = normalizeKillSignal(options.killSignal); + options.forceKillAfterDelay = normalizeForceKillAfterDelay(options.forceKillAfterDelay); + options.lines = options.lines.map((lines, fdNumber) => lines && !BINARY_ENCODINGS.has(options.encoding) && options.buffer[fdNumber]); + if (import_node_process8.default.platform === "win32" && import_node_path5.default.basename(file, ".exe") === "cmd") { + commandArguments.unshift("/q"); + } + return { file, commandArguments, options }; +}; +var addDefaultOptions = ({ + extendEnv = true, + preferLocal = false, + cwd, + localDir: localDirectory = cwd, + encoding = "utf8", + reject = true, + cleanup = true, + all = false, + windowsHide = true, + killSignal = "SIGTERM", + forceKillAfterDelay = true, + gracefulCancel = false, + ipcInput, + ipc = ipcInput !== void 0 || gracefulCancel, + serialization = "advanced", + ...options +}) => ({ + ...options, + extendEnv, + preferLocal, + cwd, + localDirectory, + encoding, + reject, + cleanup, + all, + windowsHide, + killSignal, + forceKillAfterDelay, + gracefulCancel, + ipcInput, + ipc, + serialization +}); +var getEnv = ({ env: envOption, extendEnv, preferLocal, node, localDirectory, nodePath }) => { + const env = extendEnv ? { ...import_node_process8.default.env, ...envOption } : envOption; + if (preferLocal || node) { + return npmRunPathEnv({ + env, + cwd: localDirectory, + execPath: nodePath, + preferLocal, + addExecPath: node + }); + } + return env; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/arguments/shell.js +var concatenateShell = (file, commandArguments, options) => options.shell && commandArguments.length > 0 ? [[file, ...commandArguments].join(" "), [], options] : [file, commandArguments, options]; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/message.js +var import_node_util6 = require("util"); + +// ../../node_modules/.pnpm/strip-final-newline@4.0.0/node_modules/strip-final-newline/index.js +function stripFinalNewline(input) { + if (typeof input === "string") { + return stripFinalNewlineString(input); + } + if (!(ArrayBuffer.isView(input) && input.BYTES_PER_ELEMENT === 1)) { + throw new Error("Input must be a string or a Uint8Array"); + } + return stripFinalNewlineBinary(input); +} +var stripFinalNewlineString = (input) => input.at(-1) === LF ? input.slice(0, input.at(-2) === CR ? -2 : -1) : input; +var stripFinalNewlineBinary = (input) => input.at(-1) === LF_BINARY ? input.subarray(0, input.at(-2) === CR_BINARY ? -2 : -1) : input; +var LF = "\n"; +var LF_BINARY = LF.codePointAt(0); +var CR = "\r"; +var CR_BINARY = CR.codePointAt(0); + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/index.js +var import_node_events6 = require("events"); +var import_promises5 = require("stream/promises"); + +// ../../node_modules/.pnpm/is-stream@4.0.1/node_modules/is-stream/index.js +function isStream(stream, { checkOpen = true } = {}) { + return stream !== null && typeof stream === "object" && (stream.writable || stream.readable || !checkOpen || stream.writable === void 0 && stream.readable === void 0) && typeof stream.pipe === "function"; +} +function isWritableStream(stream, { checkOpen = true } = {}) { + return isStream(stream, { checkOpen }) && (stream.writable || !checkOpen) && typeof stream.write === "function" && typeof stream.end === "function" && typeof stream.writable === "boolean" && typeof stream.writableObjectMode === "boolean" && typeof stream.destroy === "function" && typeof stream.destroyed === "boolean"; +} +function isReadableStream(stream, { checkOpen = true } = {}) { + return isStream(stream, { checkOpen }) && (stream.readable || !checkOpen) && typeof stream.read === "function" && typeof stream.readable === "boolean" && typeof stream.readableObjectMode === "boolean" && typeof stream.destroy === "function" && typeof stream.destroyed === "boolean"; +} +function isDuplexStream(stream, options) { + return isWritableStream(stream, options) && isReadableStream(stream, options); +} + +// ../../node_modules/.pnpm/@sec-ant+readable-stream@0.4.1/node_modules/@sec-ant/readable-stream/dist/ponyfill/asyncIterator.js +var a = Object.getPrototypeOf( + Object.getPrototypeOf( + /* istanbul ignore next */ + async function* () { + } + ).prototype +); +var c = class { + #t; + #n; + #r = false; + #e = void 0; + constructor(e, t) { + this.#t = e, this.#n = t; + } + next() { + const e = () => this.#s(); + return this.#e = this.#e ? this.#e.then(e, e) : e(), this.#e; + } + return(e) { + const t = () => this.#i(e); + return this.#e ? this.#e.then(t, t) : t(); + } + async #s() { + if (this.#r) + return { + done: true, + value: void 0 + }; + let e; + try { + e = await this.#t.read(); + } catch (t) { + throw this.#e = void 0, this.#r = true, this.#t.releaseLock(), t; + } + return e.done && (this.#e = void 0, this.#r = true, this.#t.releaseLock()), e; + } + async #i(e) { + if (this.#r) + return { + done: true, + value: e + }; + if (this.#r = true, !this.#n) { + const t = this.#t.cancel(e); + return this.#t.releaseLock(), await t, { + done: true, + value: e + }; + } + return this.#t.releaseLock(), { + done: true, + value: e + }; + } +}; +var n = /* @__PURE__ */ Symbol(); +function i() { + return this[n].next(); +} +Object.defineProperty(i, "name", { value: "next" }); +function o(r) { + return this[n].return(r); +} +Object.defineProperty(o, "name", { value: "return" }); +var u = Object.create(a, { + next: { + enumerable: true, + configurable: true, + writable: true, + value: i + }, + return: { + enumerable: true, + configurable: true, + writable: true, + value: o + } +}); +function h({ preventCancel: r = false } = {}) { + const e = this.getReader(), t = new c( + e, + r + ), s = Object.create(u); + return s[n] = t, s; +} + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/stream.js +var getAsyncIterable = (stream) => { + if (isReadableStream(stream, { checkOpen: false }) && nodeImports.on !== void 0) { + return getStreamIterable(stream); + } + if (typeof stream?.[Symbol.asyncIterator] === "function") { + return stream; + } + if (toString.call(stream) === "[object ReadableStream]") { + return h.call(stream); + } + throw new TypeError("The first argument must be a Readable, a ReadableStream, or an async iterable."); +}; +var { toString } = Object.prototype; +var getStreamIterable = async function* (stream) { + const controller = new AbortController(); + const state = {}; + handleStreamEnd(stream, controller, state); + try { + for await (const [chunk] of nodeImports.on(stream, "data", { signal: controller.signal })) { + yield chunk; + } + } catch (error) { + if (state.error !== void 0) { + throw state.error; + } else if (!controller.signal.aborted) { + throw error; + } + } finally { + stream.destroy(); + } +}; +var handleStreamEnd = async (stream, controller, state) => { + try { + await nodeImports.finished(stream, { + cleanup: true, + readable: true, + writable: false, + error: false + }); + } catch (error) { + state.error = error; + } finally { + controller.abort(); + } +}; +var nodeImports = {}; + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/contents.js +var getStreamContents = async (stream, { init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize }, { maxBuffer = Number.POSITIVE_INFINITY } = {}) => { + const asyncIterable = getAsyncIterable(stream); + const state = init(); + state.length = 0; + try { + for await (const chunk of asyncIterable) { + const chunkType = getChunkType(chunk); + const convertedChunk = convertChunk[chunkType](chunk, state); + appendChunk({ + convertedChunk, + state, + getSize, + truncateChunk, + addChunk, + maxBuffer + }); + } + appendFinalChunk({ + state, + convertChunk, + getSize, + truncateChunk, + addChunk, + getFinalChunk, + maxBuffer + }); + return finalize(state); + } catch (error) { + const normalizedError = typeof error === "object" && error !== null ? error : new Error(error); + normalizedError.bufferedData = finalize(state); + throw normalizedError; + } +}; +var appendFinalChunk = ({ state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer }) => { + const convertedChunk = getFinalChunk(state); + if (convertedChunk !== void 0) { + appendChunk({ + convertedChunk, + state, + getSize, + truncateChunk, + addChunk, + maxBuffer + }); + } +}; +var appendChunk = ({ convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer }) => { + const chunkSize = getSize(convertedChunk); + const newLength = state.length + chunkSize; + if (newLength <= maxBuffer) { + addNewChunk(convertedChunk, state, addChunk, newLength); + return; + } + const truncatedChunk = truncateChunk(convertedChunk, maxBuffer - state.length); + if (truncatedChunk !== void 0) { + addNewChunk(truncatedChunk, state, addChunk, maxBuffer); + } + throw new MaxBufferError(); +}; +var addNewChunk = (convertedChunk, state, addChunk, newLength) => { + state.contents = addChunk(convertedChunk, state, newLength); + state.length = newLength; +}; +var getChunkType = (chunk) => { + const typeOfChunk = typeof chunk; + if (typeOfChunk === "string") { + return "string"; + } + if (typeOfChunk !== "object" || chunk === null) { + return "others"; + } + if (globalThis.Buffer?.isBuffer(chunk)) { + return "buffer"; + } + const prototypeName = objectToString2.call(chunk); + if (prototypeName === "[object ArrayBuffer]") { + return "arrayBuffer"; + } + if (prototypeName === "[object DataView]") { + return "dataView"; + } + if (Number.isInteger(chunk.byteLength) && Number.isInteger(chunk.byteOffset) && objectToString2.call(chunk.buffer) === "[object ArrayBuffer]") { + return "typedArray"; + } + return "others"; +}; +var { toString: objectToString2 } = Object.prototype; +var MaxBufferError = class extends Error { + name = "MaxBufferError"; + constructor() { + super("maxBuffer exceeded"); + } +}; + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/utils.js +var identity2 = (value) => value; +var noop = () => void 0; +var getContentsProperty = ({ contents }) => contents; +var throwObjectStream = (chunk) => { + throw new Error(`Streams in object mode are not supported: ${String(chunk)}`); +}; +var getLengthProperty = (convertedChunk) => convertedChunk.length; + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/array.js +async function getStreamAsArray(stream, options) { + return getStreamContents(stream, arrayMethods, options); +} +var initArray = () => ({ contents: [] }); +var increment = () => 1; +var addArrayChunk = (convertedChunk, { contents }) => { + contents.push(convertedChunk); + return contents; +}; +var arrayMethods = { + init: initArray, + convertChunk: { + string: identity2, + buffer: identity2, + arrayBuffer: identity2, + dataView: identity2, + typedArray: identity2, + others: identity2 + }, + getSize: increment, + truncateChunk: noop, + addChunk: addArrayChunk, + getFinalChunk: noop, + finalize: getContentsProperty +}; + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/array-buffer.js +async function getStreamAsArrayBuffer(stream, options) { + return getStreamContents(stream, arrayBufferMethods, options); +} +var initArrayBuffer = () => ({ contents: new ArrayBuffer(0) }); +var useTextEncoder = (chunk) => textEncoder2.encode(chunk); +var textEncoder2 = new TextEncoder(); +var useUint8Array = (chunk) => new Uint8Array(chunk); +var useUint8ArrayWithOffset = (chunk) => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); +var truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); +var addArrayBufferChunk = (convertedChunk, { contents, length: previousLength }, length) => { + const newContents = hasArrayBufferResize() ? resizeArrayBuffer(contents, length) : resizeArrayBufferSlow(contents, length); + new Uint8Array(newContents).set(convertedChunk, previousLength); + return newContents; +}; +var resizeArrayBufferSlow = (contents, length) => { + if (length <= contents.byteLength) { + return contents; + } + const arrayBuffer = new ArrayBuffer(getNewContentsLength(length)); + new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); + return arrayBuffer; +}; +var resizeArrayBuffer = (contents, length) => { + if (length <= contents.maxByteLength) { + contents.resize(length); + return contents; + } + const arrayBuffer = new ArrayBuffer(length, { maxByteLength: getNewContentsLength(length) }); + new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); + return arrayBuffer; +}; +var getNewContentsLength = (length) => SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(SCALE_FACTOR)); +var SCALE_FACTOR = 2; +var finalizeArrayBuffer = ({ contents, length }) => hasArrayBufferResize() ? contents : contents.slice(0, length); +var hasArrayBufferResize = () => "resize" in ArrayBuffer.prototype; +var arrayBufferMethods = { + init: initArrayBuffer, + convertChunk: { + string: useTextEncoder, + buffer: useUint8Array, + arrayBuffer: useUint8Array, + dataView: useUint8ArrayWithOffset, + typedArray: useUint8ArrayWithOffset, + others: throwObjectStream + }, + getSize: getLengthProperty, + truncateChunk: truncateArrayBufferChunk, + addChunk: addArrayBufferChunk, + getFinalChunk: noop, + finalize: finalizeArrayBuffer +}; + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/string.js +async function getStreamAsString(stream, options) { + return getStreamContents(stream, stringMethods, options); +} +var initString = () => ({ contents: "", textDecoder: new TextDecoder() }); +var useTextDecoder = (chunk, { textDecoder: textDecoder2 }) => textDecoder2.decode(chunk, { stream: true }); +var addStringChunk = (convertedChunk, { contents }) => contents + convertedChunk; +var truncateStringChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); +var getFinalStringChunk = ({ textDecoder: textDecoder2 }) => { + const finalChunk = textDecoder2.decode(); + return finalChunk === "" ? void 0 : finalChunk; +}; +var stringMethods = { + init: initString, + convertChunk: { + string: identity2, + buffer: useTextDecoder, + arrayBuffer: useTextDecoder, + dataView: useTextDecoder, + typedArray: useTextDecoder, + others: throwObjectStream + }, + getSize: getLengthProperty, + truncateChunk: truncateStringChunk, + addChunk: addStringChunk, + getFinalChunk: getFinalStringChunk, + finalize: getContentsProperty +}; + +// ../../node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/index.js +Object.assign(nodeImports, { on: import_node_events6.on, finished: import_promises5.finished }); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/max-buffer.js +var handleMaxBuffer = ({ error, stream, readableObjectMode, lines, encoding, fdNumber }) => { + if (!(error instanceof MaxBufferError)) { + throw error; + } + if (fdNumber === "all") { + return error; + } + const unit = getMaxBufferUnit(readableObjectMode, lines, encoding); + error.maxBufferInfo = { fdNumber, unit }; + stream.destroy(); + throw error; +}; +var getMaxBufferUnit = (readableObjectMode, lines, encoding) => { + if (readableObjectMode) { + return "objects"; + } + if (lines) { + return "lines"; + } + if (encoding === "buffer") { + return "bytes"; + } + return "characters"; +}; +var checkIpcMaxBuffer = (subprocess, ipcOutput, maxBuffer) => { + if (ipcOutput.length !== maxBuffer) { + return; + } + const error = new MaxBufferError(); + error.maxBufferInfo = { fdNumber: "ipc" }; + throw error; +}; +var getMaxBufferMessage = (error, maxBuffer) => { + const { streamName, threshold, unit } = getMaxBufferInfo(error, maxBuffer); + return `Command's ${streamName} was larger than ${threshold} ${unit}`; +}; +var getMaxBufferInfo = (error, maxBuffer) => { + if (error?.maxBufferInfo === void 0) { + return { streamName: "output", threshold: maxBuffer[1], unit: "bytes" }; + } + const { maxBufferInfo: { fdNumber, unit } } = error; + delete error.maxBufferInfo; + const threshold = getFdSpecificValue(maxBuffer, fdNumber); + if (fdNumber === "ipc") { + return { streamName: "IPC output", threshold, unit: "messages" }; + } + return { streamName: getStreamName(fdNumber), threshold, unit }; +}; +var isMaxBufferSync = (resultError, output, maxBuffer) => resultError?.code === "ENOBUFS" && output !== null && output.some((result) => result !== null && result.length > getMaxBufferSync(maxBuffer)); +var truncateMaxBufferSync = (result, isMaxBuffer, maxBuffer) => { + if (!isMaxBuffer) { + return result; + } + const maxBufferValue = getMaxBufferSync(maxBuffer); + return result.length > maxBufferValue ? result.slice(0, maxBufferValue) : result; +}; +var getMaxBufferSync = ([, stdoutMaxBuffer]) => stdoutMaxBuffer; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/message.js +var createMessages = ({ + stdio, + all, + ipcOutput, + originalError, + signal, + signalDescription, + exitCode, + escapedCommand, + timedOut, + isCanceled, + isGracefullyCanceled, + isMaxBuffer, + isForcefullyTerminated, + forceKillAfterDelay, + killSignal, + maxBuffer, + timeout, + cwd +}) => { + const errorCode = originalError?.code; + const prefix = getErrorPrefix({ + originalError, + timedOut, + timeout, + isMaxBuffer, + maxBuffer, + errorCode, + signal, + signalDescription, + exitCode, + isCanceled, + isGracefullyCanceled, + isForcefullyTerminated, + forceKillAfterDelay, + killSignal + }); + const originalMessage = getOriginalMessage(originalError, cwd); + const suffix = originalMessage === void 0 ? "" : ` +${originalMessage}`; + const shortMessage = `${prefix}: ${escapedCommand}${suffix}`; + const messageStdio = all === void 0 ? [stdio[2], stdio[1]] : [all]; + const message = [ + shortMessage, + ...messageStdio, + ...stdio.slice(3), + ipcOutput.map((ipcMessage) => serializeIpcMessage(ipcMessage)).join("\n") + ].map((messagePart) => escapeLines(stripFinalNewline(serializeMessagePart(messagePart)))).filter(Boolean).join("\n\n"); + return { originalMessage, shortMessage, message }; +}; +var getErrorPrefix = ({ + originalError, + timedOut, + timeout, + isMaxBuffer, + maxBuffer, + errorCode, + signal, + signalDescription, + exitCode, + isCanceled, + isGracefullyCanceled, + isForcefullyTerminated, + forceKillAfterDelay, + killSignal +}) => { + const forcefulSuffix = getForcefulSuffix(isForcefullyTerminated, forceKillAfterDelay); + if (timedOut) { + return `Command timed out after ${timeout} milliseconds${forcefulSuffix}`; + } + if (isGracefullyCanceled) { + if (signal === void 0) { + return `Command was gracefully canceled with exit code ${exitCode}`; + } + return isForcefullyTerminated ? `Command was gracefully canceled${forcefulSuffix}` : `Command was gracefully canceled with ${signal} (${signalDescription})`; + } + if (isCanceled) { + return `Command was canceled${forcefulSuffix}`; + } + if (isMaxBuffer) { + return `${getMaxBufferMessage(originalError, maxBuffer)}${forcefulSuffix}`; + } + if (errorCode !== void 0) { + return `Command failed with ${errorCode}${forcefulSuffix}`; + } + if (isForcefullyTerminated) { + return `Command was killed with ${killSignal} (${getSignalDescription(killSignal)})${forcefulSuffix}`; + } + if (signal !== void 0) { + return `Command was killed with ${signal} (${signalDescription})`; + } + if (exitCode !== void 0) { + return `Command failed with exit code ${exitCode}`; + } + return "Command failed"; +}; +var getForcefulSuffix = (isForcefullyTerminated, forceKillAfterDelay) => isForcefullyTerminated ? ` and was forcefully terminated after ${forceKillAfterDelay} milliseconds` : ""; +var getOriginalMessage = (originalError, cwd) => { + if (originalError instanceof DiscardedError) { + return; + } + const originalMessage = isExecaError(originalError) ? originalError.originalMessage : String(originalError?.message ?? originalError); + const escapedOriginalMessage = escapeLines(fixCwdError(originalMessage, cwd)); + return escapedOriginalMessage === "" ? void 0 : escapedOriginalMessage; +}; +var serializeIpcMessage = (ipcMessage) => typeof ipcMessage === "string" ? ipcMessage : (0, import_node_util6.inspect)(ipcMessage); +var serializeMessagePart = (messagePart) => Array.isArray(messagePart) ? messagePart.map((messageItem) => stripFinalNewline(serializeMessageItem(messageItem))).filter(Boolean).join("\n") : serializeMessageItem(messagePart); +var serializeMessageItem = (messageItem) => { + if (typeof messageItem === "string") { + return messageItem; + } + if (isUint8Array(messageItem)) { + return uint8ArrayToString(messageItem); + } + return ""; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/result.js +var makeSuccessResult = ({ + command, + escapedCommand, + stdio, + all, + ipcOutput, + options: { cwd }, + startTime +}) => omitUndefinedProperties({ + command, + escapedCommand, + cwd, + durationMs: getDurationMs(startTime), + failed: false, + timedOut: false, + isCanceled: false, + isGracefullyCanceled: false, + isTerminated: false, + isMaxBuffer: false, + isForcefullyTerminated: false, + exitCode: 0, + stdout: stdio[1], + stderr: stdio[2], + all, + stdio, + ipcOutput, + pipedFrom: [] +}); +var makeEarlyError = ({ + error, + command, + escapedCommand, + fileDescriptors, + options, + startTime, + isSync +}) => makeError({ + error, + command, + escapedCommand, + startTime, + timedOut: false, + isCanceled: false, + isGracefullyCanceled: false, + isMaxBuffer: false, + isForcefullyTerminated: false, + stdio: Array.from({ length: fileDescriptors.length }), + ipcOutput: [], + options, + isSync +}); +var makeError = ({ + error: originalError, + command, + escapedCommand, + startTime, + timedOut, + isCanceled, + isGracefullyCanceled, + isMaxBuffer, + isForcefullyTerminated, + exitCode: rawExitCode, + signal: rawSignal, + stdio, + all, + ipcOutput, + options: { + timeoutDuration, + timeout = timeoutDuration, + forceKillAfterDelay, + killSignal, + cwd, + maxBuffer + }, + isSync +}) => { + const { exitCode, signal, signalDescription } = normalizeExitPayload(rawExitCode, rawSignal); + const { originalMessage, shortMessage, message } = createMessages({ + stdio, + all, + ipcOutput, + originalError, + signal, + signalDescription, + exitCode, + escapedCommand, + timedOut, + isCanceled, + isGracefullyCanceled, + isMaxBuffer, + isForcefullyTerminated, + forceKillAfterDelay, + killSignal, + maxBuffer, + timeout, + cwd + }); + const error = getFinalError(originalError, message, isSync); + Object.assign(error, getErrorProperties({ + error, + command, + escapedCommand, + startTime, + timedOut, + isCanceled, + isGracefullyCanceled, + isMaxBuffer, + isForcefullyTerminated, + exitCode, + signal, + signalDescription, + stdio, + all, + ipcOutput, + cwd, + originalMessage, + shortMessage + })); + return error; +}; +var getErrorProperties = ({ + error, + command, + escapedCommand, + startTime, + timedOut, + isCanceled, + isGracefullyCanceled, + isMaxBuffer, + isForcefullyTerminated, + exitCode, + signal, + signalDescription, + stdio, + all, + ipcOutput, + cwd, + originalMessage, + shortMessage +}) => omitUndefinedProperties({ + shortMessage, + originalMessage, + command, + escapedCommand, + cwd, + durationMs: getDurationMs(startTime), + failed: true, + timedOut, + isCanceled, + isGracefullyCanceled, + isTerminated: signal !== void 0, + isMaxBuffer, + isForcefullyTerminated, + exitCode, + signal, + signalDescription, + code: error.cause?.code, + stdout: stdio[1], + stderr: stdio[2], + all, + stdio, + ipcOutput, + pipedFrom: [] +}); +var omitUndefinedProperties = (result) => Object.fromEntries(Object.entries(result).filter(([, value]) => value !== void 0)); +var normalizeExitPayload = (rawExitCode, rawSignal) => { + const exitCode = rawExitCode === null ? void 0 : rawExitCode; + const signal = rawSignal === null ? void 0 : rawSignal; + const signalDescription = signal === void 0 ? void 0 : getSignalDescription(rawSignal); + return { exitCode, signal, signalDescription }; +}; + +// ../../node_modules/.pnpm/parse-ms@4.0.0/node_modules/parse-ms/index.js +var toZeroIfInfinity = (value) => Number.isFinite(value) ? value : 0; +function parseNumber(milliseconds) { + return { + days: Math.trunc(milliseconds / 864e5), + hours: Math.trunc(milliseconds / 36e5 % 24), + minutes: Math.trunc(milliseconds / 6e4 % 60), + seconds: Math.trunc(milliseconds / 1e3 % 60), + milliseconds: Math.trunc(milliseconds % 1e3), + microseconds: Math.trunc(toZeroIfInfinity(milliseconds * 1e3) % 1e3), + nanoseconds: Math.trunc(toZeroIfInfinity(milliseconds * 1e6) % 1e3) + }; +} +function parseBigint(milliseconds) { + return { + days: milliseconds / 86400000n, + hours: milliseconds / 3600000n % 24n, + minutes: milliseconds / 60000n % 60n, + seconds: milliseconds / 1000n % 60n, + milliseconds: milliseconds % 1000n, + microseconds: 0n, + nanoseconds: 0n + }; +} +function parseMilliseconds(milliseconds) { + switch (typeof milliseconds) { + case "number": { + if (Number.isFinite(milliseconds)) { + return parseNumber(milliseconds); + } + break; + } + case "bigint": { + return parseBigint(milliseconds); + } + } + throw new TypeError("Expected a finite number or bigint"); +} + +// ../../node_modules/.pnpm/pretty-ms@9.3.0/node_modules/pretty-ms/index.js +var isZero = (value) => value === 0 || value === 0n; +var pluralize = (word, count2) => count2 === 1 || count2 === 1n ? word : `${word}s`; +var SECOND_ROUNDING_EPSILON = 1e-7; +var ONE_DAY_IN_MILLISECONDS = 24n * 60n * 60n * 1000n; +function prettyMilliseconds(milliseconds, options) { + const isBigInt = typeof milliseconds === "bigint"; + if (!isBigInt && !Number.isFinite(milliseconds)) { + throw new TypeError("Expected a finite number or bigint"); + } + options = { ...options }; + const sign = milliseconds < 0 ? "-" : ""; + milliseconds = milliseconds < 0 ? -milliseconds : milliseconds; + if (options.colonNotation) { + options.compact = false; + options.formatSubMilliseconds = false; + options.separateMilliseconds = false; + options.verbose = false; + } + if (options.compact) { + options.unitCount = 1; + options.secondsDecimalDigits = 0; + options.millisecondsDecimalDigits = 0; + } + let result = []; + const floorDecimals = (value, decimalDigits) => { + const flooredInterimValue = Math.floor(value * 10 ** decimalDigits + SECOND_ROUNDING_EPSILON); + const flooredValue = Math.round(flooredInterimValue) / 10 ** decimalDigits; + return flooredValue.toFixed(decimalDigits); + }; + const add = (value, long, short, valueString) => { + if ((result.length === 0 || !options.colonNotation) && isZero(value) && !(options.colonNotation && short === "m")) { + return; + } + valueString ??= String(value); + if (options.colonNotation) { + const wholeDigits = valueString.includes(".") ? valueString.split(".")[0].length : valueString.length; + const minLength = result.length > 0 ? 2 : 1; + valueString = "0".repeat(Math.max(0, minLength - wholeDigits)) + valueString; + } else { + valueString += options.verbose ? " " + pluralize(long, value) : short; + } + result.push(valueString); + }; + const parsed = parseMilliseconds(milliseconds); + const days = BigInt(parsed.days); + if (options.hideYearAndDays) { + add(BigInt(days) * 24n + BigInt(parsed.hours), "hour", "h"); + } else { + if (options.hideYear) { + add(days, "day", "d"); + } else { + add(days / 365n, "year", "y"); + add(days % 365n, "day", "d"); + } + add(Number(parsed.hours), "hour", "h"); + } + add(Number(parsed.minutes), "minute", "m"); + if (!options.hideSeconds) { + if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3 && !options.subSecondsAsDecimals) { + const seconds = Number(parsed.seconds); + const milliseconds2 = Number(parsed.milliseconds); + const microseconds = Number(parsed.microseconds); + const nanoseconds = Number(parsed.nanoseconds); + add(seconds, "second", "s"); + if (options.formatSubMilliseconds) { + add(milliseconds2, "millisecond", "ms"); + add(microseconds, "microsecond", "\xB5s"); + add(nanoseconds, "nanosecond", "ns"); + } else { + const millisecondsAndBelow = milliseconds2 + microseconds / 1e3 + nanoseconds / 1e6; + const millisecondsDecimalDigits = typeof options.millisecondsDecimalDigits === "number" ? options.millisecondsDecimalDigits : 0; + const roundedMilliseconds = millisecondsAndBelow >= 1 ? Math.round(millisecondsAndBelow) : Math.ceil(millisecondsAndBelow); + const millisecondsString = millisecondsDecimalDigits ? millisecondsAndBelow.toFixed(millisecondsDecimalDigits) : roundedMilliseconds; + add( + Number.parseFloat(millisecondsString), + "millisecond", + "ms", + millisecondsString + ); + } + } else { + const seconds = (isBigInt ? Number(milliseconds % ONE_DAY_IN_MILLISECONDS) : milliseconds) / 1e3 % 60; + const secondsDecimalDigits = typeof options.secondsDecimalDigits === "number" ? options.secondsDecimalDigits : 1; + const secondsFixed = floorDecimals(seconds, secondsDecimalDigits); + const secondsString = options.keepDecimalsOnWholeSeconds ? secondsFixed : secondsFixed.replace(/\.0+$/, ""); + add(Number.parseFloat(secondsString), "second", "s", secondsString); + } + } + if (result.length === 0) { + return sign + "0" + (options.verbose ? " milliseconds" : "ms"); + } + const separator = options.colonNotation ? ":" : " "; + if (typeof options.unitCount === "number") { + result = result.slice(0, Math.max(options.unitCount, 1)); + } + return sign + result.join(separator); +} + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/error.js +var logError = (result, verboseInfo) => { + if (result.failed) { + verboseLog({ + type: "error", + verboseMessage: result.shortMessage, + verboseInfo, + result + }); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/complete.js +var logResult = (result, verboseInfo) => { + if (!isVerbose(verboseInfo)) { + return; + } + logError(result, verboseInfo); + logDuration(result, verboseInfo); +}; +var logDuration = (result, verboseInfo) => { + const verboseMessage = `(done in ${prettyMilliseconds(result.durationMs)})`; + verboseLog({ + type: "duration", + verboseMessage, + verboseInfo, + result + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/reject.js +var handleResult2 = (result, verboseInfo, { reject }) => { + logResult(result, verboseInfo); + if (result.failed && reject) { + throw result; + } + return result; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/handle-sync.js +var import_node_fs3 = require("fs"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/type.js +var getStdioItemType = (value, optionName) => { + if (isAsyncGenerator(value)) { + return "asyncGenerator"; + } + if (isSyncGenerator(value)) { + return "generator"; + } + if (isUrl(value)) { + return "fileUrl"; + } + if (isFilePathObject(value)) { + return "filePath"; + } + if (isWebStream(value)) { + return "webStream"; + } + if (isStream(value, { checkOpen: false })) { + return "native"; + } + if (isUint8Array(value)) { + return "uint8Array"; + } + if (isAsyncIterableObject(value)) { + return "asyncIterable"; + } + if (isIterableObject(value)) { + return "iterable"; + } + if (isTransformStream(value)) { + return getTransformStreamType({ transform: value }, optionName); + } + if (isTransformOptions(value)) { + return getTransformObjectType(value, optionName); + } + return "native"; +}; +var getTransformObjectType = (value, optionName) => { + if (isDuplexStream(value.transform, { checkOpen: false })) { + return getDuplexType(value, optionName); + } + if (isTransformStream(value.transform)) { + return getTransformStreamType(value, optionName); + } + return getGeneratorObjectType(value, optionName); +}; +var getDuplexType = (value, optionName) => { + validateNonGeneratorType(value, optionName, "Duplex stream"); + return "duplex"; +}; +var getTransformStreamType = (value, optionName) => { + validateNonGeneratorType(value, optionName, "web TransformStream"); + return "webTransform"; +}; +var validateNonGeneratorType = ({ final, binary, objectMode }, optionName, typeName) => { + checkUndefinedOption(final, `${optionName}.final`, typeName); + checkUndefinedOption(binary, `${optionName}.binary`, typeName); + checkBooleanOption(objectMode, `${optionName}.objectMode`); +}; +var checkUndefinedOption = (value, optionName, typeName) => { + if (value !== void 0) { + throw new TypeError(`The \`${optionName}\` option can only be defined when using a generator, not a ${typeName}.`); + } +}; +var getGeneratorObjectType = ({ transform, final, binary, objectMode }, optionName) => { + if (transform !== void 0 && !isGenerator(transform)) { + throw new TypeError(`The \`${optionName}.transform\` option must be a generator, a Duplex stream or a web TransformStream.`); + } + if (isDuplexStream(final, { checkOpen: false })) { + throw new TypeError(`The \`${optionName}.final\` option must not be a Duplex stream.`); + } + if (isTransformStream(final)) { + throw new TypeError(`The \`${optionName}.final\` option must not be a web TransformStream.`); + } + if (final !== void 0 && !isGenerator(final)) { + throw new TypeError(`The \`${optionName}.final\` option must be a generator.`); + } + checkBooleanOption(binary, `${optionName}.binary`); + checkBooleanOption(objectMode, `${optionName}.objectMode`); + return isAsyncGenerator(transform) || isAsyncGenerator(final) ? "asyncGenerator" : "generator"; +}; +var checkBooleanOption = (value, optionName) => { + if (value !== void 0 && typeof value !== "boolean") { + throw new TypeError(`The \`${optionName}\` option must use a boolean.`); + } +}; +var isGenerator = (value) => isAsyncGenerator(value) || isSyncGenerator(value); +var isAsyncGenerator = (value) => Object.prototype.toString.call(value) === "[object AsyncGeneratorFunction]"; +var isSyncGenerator = (value) => Object.prototype.toString.call(value) === "[object GeneratorFunction]"; +var isTransformOptions = (value) => isPlainObject(value) && (value.transform !== void 0 || value.final !== void 0); +var isUrl = (value) => Object.prototype.toString.call(value) === "[object URL]"; +var isRegularUrl = (value) => isUrl(value) && value.protocol !== "file:"; +var isFilePathObject = (value) => isPlainObject(value) && Object.keys(value).length > 0 && Object.keys(value).every((key) => FILE_PATH_KEYS.has(key)) && isFilePathString(value.file); +var FILE_PATH_KEYS = /* @__PURE__ */ new Set(["file", "append"]); +var isFilePathString = (file) => typeof file === "string"; +var isUnknownStdioString = (type, value) => type === "native" && typeof value === "string" && !KNOWN_STDIO_STRINGS.has(value); +var KNOWN_STDIO_STRINGS = /* @__PURE__ */ new Set(["ipc", "ignore", "inherit", "overlapped", "pipe"]); +var isReadableStream2 = (value) => Object.prototype.toString.call(value) === "[object ReadableStream]"; +var isWritableStream2 = (value) => Object.prototype.toString.call(value) === "[object WritableStream]"; +var isWebStream = (value) => isReadableStream2(value) || isWritableStream2(value); +var isTransformStream = (value) => isReadableStream2(value?.readable) && isWritableStream2(value?.writable); +var isAsyncIterableObject = (value) => isObject(value) && typeof value[Symbol.asyncIterator] === "function"; +var isIterableObject = (value) => isObject(value) && typeof value[Symbol.iterator] === "function"; +var isObject = (value) => typeof value === "object" && value !== null; +var TRANSFORM_TYPES = /* @__PURE__ */ new Set(["generator", "asyncGenerator", "duplex", "webTransform"]); +var FILE_TYPES = /* @__PURE__ */ new Set(["fileUrl", "filePath", "fileNumber"]); +var SPECIAL_DUPLICATE_TYPES_SYNC = /* @__PURE__ */ new Set(["fileUrl", "filePath"]); +var SPECIAL_DUPLICATE_TYPES = /* @__PURE__ */ new Set([...SPECIAL_DUPLICATE_TYPES_SYNC, "webStream", "nodeStream"]); +var FORBID_DUPLICATE_TYPES = /* @__PURE__ */ new Set(["webTransform", "duplex"]); +var TYPE_TO_MESSAGE = { + generator: "a generator", + asyncGenerator: "an async generator", + fileUrl: "a file URL", + filePath: "a file path string", + fileNumber: "a file descriptor number", + webStream: "a web stream", + nodeStream: "a Node.js stream", + webTransform: "a web TransformStream", + duplex: "a Duplex stream", + native: "any value", + iterable: "an iterable", + asyncIterable: "an async iterable", + string: "a string", + uint8Array: "a Uint8Array" +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/object-mode.js +var getTransformObjectModes = (objectMode, index, newTransforms, direction) => direction === "output" ? getOutputObjectModes(objectMode, index, newTransforms) : getInputObjectModes(objectMode, index, newTransforms); +var getOutputObjectModes = (objectMode, index, newTransforms) => { + const writableObjectMode = index !== 0 && newTransforms[index - 1].value.readableObjectMode; + const readableObjectMode = objectMode ?? writableObjectMode; + return { writableObjectMode, readableObjectMode }; +}; +var getInputObjectModes = (objectMode, index, newTransforms) => { + const writableObjectMode = index === 0 ? objectMode === true : newTransforms[index - 1].value.readableObjectMode; + const readableObjectMode = index !== newTransforms.length - 1 && (objectMode ?? writableObjectMode); + return { writableObjectMode, readableObjectMode }; +}; +var getFdObjectMode = (stdioItems, direction) => { + const lastTransform = stdioItems.findLast(({ type }) => TRANSFORM_TYPES.has(type)); + if (lastTransform === void 0) { + return false; + } + return direction === "input" ? lastTransform.value.writableObjectMode : lastTransform.value.readableObjectMode; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/normalize.js +var normalizeTransforms = (stdioItems, optionName, direction, options) => [ + ...stdioItems.filter(({ type }) => !TRANSFORM_TYPES.has(type)), + ...getTransforms(stdioItems, optionName, direction, options) +]; +var getTransforms = (stdioItems, optionName, direction, { encoding }) => { + const transforms = stdioItems.filter(({ type }) => TRANSFORM_TYPES.has(type)); + const newTransforms = Array.from({ length: transforms.length }); + for (const [index, stdioItem] of Object.entries(transforms)) { + newTransforms[index] = normalizeTransform({ + stdioItem, + index: Number(index), + newTransforms, + optionName, + direction, + encoding + }); + } + return sortTransforms(newTransforms, direction); +}; +var normalizeTransform = ({ stdioItem, stdioItem: { type }, index, newTransforms, optionName, direction, encoding }) => { + if (type === "duplex") { + return normalizeDuplex({ stdioItem, optionName }); + } + if (type === "webTransform") { + return normalizeTransformStream({ + stdioItem, + index, + newTransforms, + direction + }); + } + return normalizeGenerator({ + stdioItem, + index, + newTransforms, + direction, + encoding + }); +}; +var normalizeDuplex = ({ + stdioItem, + stdioItem: { + value: { + transform, + transform: { writableObjectMode, readableObjectMode }, + objectMode = readableObjectMode + } + }, + optionName +}) => { + if (objectMode && !readableObjectMode) { + throw new TypeError(`The \`${optionName}.objectMode\` option can only be \`true\` if \`new Duplex({objectMode: true})\` is used.`); + } + if (!objectMode && readableObjectMode) { + throw new TypeError(`The \`${optionName}.objectMode\` option cannot be \`false\` if \`new Duplex({objectMode: true})\` is used.`); + } + return { + ...stdioItem, + value: { transform, writableObjectMode, readableObjectMode } + }; +}; +var normalizeTransformStream = ({ stdioItem, stdioItem: { value }, index, newTransforms, direction }) => { + const { transform, objectMode } = isPlainObject(value) ? value : { transform: value }; + const { writableObjectMode, readableObjectMode } = getTransformObjectModes(objectMode, index, newTransforms, direction); + return { + ...stdioItem, + value: { transform, writableObjectMode, readableObjectMode } + }; +}; +var normalizeGenerator = ({ stdioItem, stdioItem: { value }, index, newTransforms, direction, encoding }) => { + const { + transform, + final, + binary: binaryOption = false, + preserveNewlines = false, + objectMode + } = isPlainObject(value) ? value : { transform: value }; + const binary = binaryOption || BINARY_ENCODINGS.has(encoding); + const { writableObjectMode, readableObjectMode } = getTransformObjectModes(objectMode, index, newTransforms, direction); + return { + ...stdioItem, + value: { + transform, + final, + binary, + preserveNewlines, + writableObjectMode, + readableObjectMode + } + }; +}; +var sortTransforms = (newTransforms, direction) => direction === "input" ? newTransforms.reverse() : newTransforms; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/direction.js +var import_node_process9 = __toESM(require("process"), 1); +var getStreamDirection = (stdioItems, fdNumber, optionName) => { + const directions = stdioItems.map((stdioItem) => getStdioItemDirection(stdioItem, fdNumber)); + if (directions.includes("input") && directions.includes("output")) { + throw new TypeError(`The \`${optionName}\` option must not be an array of both readable and writable values.`); + } + return directions.find(Boolean) ?? DEFAULT_DIRECTION; +}; +var getStdioItemDirection = ({ type, value }, fdNumber) => KNOWN_DIRECTIONS[fdNumber] ?? guessStreamDirection[type](value); +var KNOWN_DIRECTIONS = ["input", "output", "output"]; +var anyDirection = () => void 0; +var alwaysInput = () => "input"; +var guessStreamDirection = { + generator: anyDirection, + asyncGenerator: anyDirection, + fileUrl: anyDirection, + filePath: anyDirection, + iterable: alwaysInput, + asyncIterable: alwaysInput, + uint8Array: alwaysInput, + webStream: (value) => isWritableStream2(value) ? "output" : "input", + nodeStream(value) { + if (!isReadableStream(value, { checkOpen: false })) { + return "output"; + } + return isWritableStream(value, { checkOpen: false }) ? void 0 : "input"; + }, + webTransform: anyDirection, + duplex: anyDirection, + native(value) { + const standardStreamDirection = getStandardStreamDirection(value); + if (standardStreamDirection !== void 0) { + return standardStreamDirection; + } + if (isStream(value, { checkOpen: false })) { + return guessStreamDirection.nodeStream(value); + } + } +}; +var getStandardStreamDirection = (value) => { + if ([0, import_node_process9.default.stdin].includes(value)) { + return "input"; + } + if ([1, 2, import_node_process9.default.stdout, import_node_process9.default.stderr].includes(value)) { + return "output"; + } +}; +var DEFAULT_DIRECTION = "output"; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/array.js +var normalizeIpcStdioArray = (stdioArray, ipc) => ipc && !stdioArray.includes("ipc") ? [...stdioArray, "ipc"] : stdioArray; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/stdio-option.js +var normalizeStdioOption = ({ stdio, ipc, buffer, ...options }, verboseInfo, isSync) => { + const stdioArray = getStdioArray(stdio, options).map((stdioOption, fdNumber) => addDefaultValue2(stdioOption, fdNumber)); + return isSync ? normalizeStdioSync(stdioArray, buffer, verboseInfo) : normalizeIpcStdioArray(stdioArray, ipc); +}; +var getStdioArray = (stdio, options) => { + if (stdio === void 0) { + return STANDARD_STREAMS_ALIASES.map((alias) => options[alias]); + } + if (hasAlias(options)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${STANDARD_STREAMS_ALIASES.map((alias) => `\`${alias}\``).join(", ")}`); + } + if (typeof stdio === "string") { + return [stdio, stdio, stdio]; + } + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } + const length = Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length); + return Array.from({ length }, (_, fdNumber) => stdio[fdNumber]); +}; +var hasAlias = (options) => STANDARD_STREAMS_ALIASES.some((alias) => options[alias] !== void 0); +var addDefaultValue2 = (stdioOption, fdNumber) => { + if (Array.isArray(stdioOption)) { + return stdioOption.map((item) => addDefaultValue2(item, fdNumber)); + } + if (stdioOption === null || stdioOption === void 0) { + return fdNumber >= STANDARD_STREAMS_ALIASES.length ? "ignore" : "pipe"; + } + return stdioOption; +}; +var normalizeStdioSync = (stdioArray, buffer, verboseInfo) => stdioArray.map((stdioOption, fdNumber) => !buffer[fdNumber] && fdNumber !== 0 && !isFullVerbose(verboseInfo, fdNumber) && isOutputPipeOnly(stdioOption) ? "ignore" : stdioOption); +var isOutputPipeOnly = (stdioOption) => stdioOption === "pipe" || Array.isArray(stdioOption) && stdioOption.every((item) => item === "pipe"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/native.js +var import_node_fs2 = require("fs"); +var import_node_tty2 = __toESM(require("tty"), 1); +var handleNativeStream = ({ stdioItem, stdioItem: { type }, isStdioArray, fdNumber, direction, isSync }) => { + if (!isStdioArray || type !== "native") { + return stdioItem; + } + return isSync ? handleNativeStreamSync({ stdioItem, fdNumber, direction }) : handleNativeStreamAsync({ stdioItem, fdNumber }); +}; +var handleNativeStreamSync = ({ stdioItem, stdioItem: { value, optionName }, fdNumber, direction }) => { + const targetFd = getTargetFd({ + value, + optionName, + fdNumber, + direction + }); + if (targetFd !== void 0) { + return targetFd; + } + if (isStream(value, { checkOpen: false })) { + throw new TypeError(`The \`${optionName}: Stream\` option cannot both be an array and include a stream with synchronous methods.`); + } + return stdioItem; +}; +var getTargetFd = ({ value, optionName, fdNumber, direction }) => { + const targetFdNumber = getTargetFdNumber(value, fdNumber); + if (targetFdNumber === void 0) { + return; + } + if (direction === "output") { + return { type: "fileNumber", value: targetFdNumber, optionName }; + } + if (import_node_tty2.default.isatty(targetFdNumber)) { + throw new TypeError(`The \`${optionName}: ${serializeOptionValue(value)}\` option is invalid: it cannot be a TTY with synchronous methods.`); + } + return { type: "uint8Array", value: bufferToUint8Array((0, import_node_fs2.readFileSync)(targetFdNumber)), optionName }; +}; +var getTargetFdNumber = (value, fdNumber) => { + if (value === "inherit") { + return fdNumber; + } + if (typeof value === "number") { + return value; + } + const standardStreamIndex = STANDARD_STREAMS.indexOf(value); + if (standardStreamIndex !== -1) { + return standardStreamIndex; + } +}; +var handleNativeStreamAsync = ({ stdioItem, stdioItem: { value, optionName }, fdNumber }) => { + if (value === "inherit") { + return { type: "nodeStream", value: getStandardStream(fdNumber, value, optionName), optionName }; + } + if (typeof value === "number") { + return { type: "nodeStream", value: getStandardStream(value, value, optionName), optionName }; + } + if (isStream(value, { checkOpen: false })) { + return { type: "nodeStream", value, optionName }; + } + return stdioItem; +}; +var getStandardStream = (fdNumber, value, optionName) => { + const standardStream = STANDARD_STREAMS[fdNumber]; + if (standardStream === void 0) { + throw new TypeError(`The \`${optionName}: ${value}\` option is invalid: no such standard stream.`); + } + return standardStream; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/input-option.js +var handleInputOptions = ({ input, inputFile }, fdNumber) => fdNumber === 0 ? [ + ...handleInputOption(input), + ...handleInputFileOption(inputFile) +] : []; +var handleInputOption = (input) => input === void 0 ? [] : [{ + type: getInputType(input), + value: input, + optionName: "input" +}]; +var getInputType = (input) => { + if (isReadableStream(input, { checkOpen: false })) { + return "nodeStream"; + } + if (typeof input === "string") { + return "string"; + } + if (isUint8Array(input)) { + return "uint8Array"; + } + throw new Error("The `input` option must be a string, a Uint8Array or a Node.js Readable stream."); +}; +var handleInputFileOption = (inputFile) => inputFile === void 0 ? [] : [{ + ...getInputFileType(inputFile), + optionName: "inputFile" +}]; +var getInputFileType = (inputFile) => { + if (isUrl(inputFile)) { + return { type: "fileUrl", value: inputFile }; + } + if (isFilePathString(inputFile)) { + return { type: "filePath", value: { file: inputFile } }; + } + throw new Error("The `inputFile` option must be a file path string or a file URL."); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/duplicate.js +var filterDuplicates = (stdioItems) => stdioItems.filter((stdioItemOne, indexOne) => stdioItems.every((stdioItemTwo, indexTwo) => stdioItemOne.value !== stdioItemTwo.value || indexOne >= indexTwo || stdioItemOne.type === "generator" || stdioItemOne.type === "asyncGenerator")); +var getDuplicateStream = ({ stdioItem: { type, value, optionName }, direction, fileDescriptors, isSync }) => { + const otherStdioItems = getOtherStdioItems(fileDescriptors, type); + if (otherStdioItems.length === 0) { + return; + } + if (isSync) { + validateDuplicateStreamSync({ + otherStdioItems, + type, + value, + optionName, + direction + }); + return; + } + if (SPECIAL_DUPLICATE_TYPES.has(type)) { + return getDuplicateStreamInstance({ + otherStdioItems, + type, + value, + optionName, + direction + }); + } + if (FORBID_DUPLICATE_TYPES.has(type)) { + validateDuplicateTransform({ + otherStdioItems, + type, + value, + optionName + }); + } +}; +var getOtherStdioItems = (fileDescriptors, type) => fileDescriptors.flatMap(({ direction, stdioItems }) => stdioItems.filter((stdioItem) => stdioItem.type === type).map(((stdioItem) => ({ ...stdioItem, direction })))); +var validateDuplicateStreamSync = ({ otherStdioItems, type, value, optionName, direction }) => { + if (SPECIAL_DUPLICATE_TYPES_SYNC.has(type)) { + getDuplicateStreamInstance({ + otherStdioItems, + type, + value, + optionName, + direction + }); + } +}; +var getDuplicateStreamInstance = ({ otherStdioItems, type, value, optionName, direction }) => { + const duplicateStdioItems = otherStdioItems.filter((stdioItem) => hasSameValue(stdioItem, value)); + if (duplicateStdioItems.length === 0) { + return; + } + const differentStdioItem = duplicateStdioItems.find((stdioItem) => stdioItem.direction !== direction); + throwOnDuplicateStream(differentStdioItem, optionName, type); + return direction === "output" ? duplicateStdioItems[0].stream : void 0; +}; +var hasSameValue = ({ type, value }, secondValue) => { + if (type === "filePath") { + return value.file === secondValue.file; + } + if (type === "fileUrl") { + return value.href === secondValue.href; + } + return value === secondValue; +}; +var validateDuplicateTransform = ({ otherStdioItems, type, value, optionName }) => { + const duplicateStdioItem = otherStdioItems.find(({ value: { transform } }) => transform === value.transform); + throwOnDuplicateStream(duplicateStdioItem, optionName, type); +}; +var throwOnDuplicateStream = (stdioItem, optionName, type) => { + if (stdioItem !== void 0) { + throw new TypeError(`The \`${stdioItem.optionName}\` and \`${optionName}\` options must not target ${TYPE_TO_MESSAGE[type]} that is the same.`); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/handle.js +var handleStdio = (addProperties3, options, verboseInfo, isSync) => { + const stdio = normalizeStdioOption(options, verboseInfo, isSync); + const initialFileDescriptors = stdio.map((stdioOption, fdNumber) => getFileDescriptor({ + stdioOption, + fdNumber, + options, + isSync + })); + const fileDescriptors = getFinalFileDescriptors({ + initialFileDescriptors, + addProperties: addProperties3, + options, + isSync + }); + options.stdio = fileDescriptors.map(({ stdioItems }) => forwardStdio(stdioItems)); + return fileDescriptors; +}; +var getFileDescriptor = ({ stdioOption, fdNumber, options, isSync }) => { + const optionName = getStreamName(fdNumber); + const { stdioItems: initialStdioItems, isStdioArray } = initializeStdioItems({ + stdioOption, + fdNumber, + options, + optionName + }); + const direction = getStreamDirection(initialStdioItems, fdNumber, optionName); + const stdioItems = initialStdioItems.map((stdioItem) => handleNativeStream({ + stdioItem, + isStdioArray, + fdNumber, + direction, + isSync + })); + const normalizedStdioItems = normalizeTransforms(stdioItems, optionName, direction, options); + const objectMode = getFdObjectMode(normalizedStdioItems, direction); + validateFileObjectMode(normalizedStdioItems, objectMode); + return { direction, objectMode, stdioItems: normalizedStdioItems }; +}; +var initializeStdioItems = ({ stdioOption, fdNumber, options, optionName }) => { + const values = Array.isArray(stdioOption) ? stdioOption : [stdioOption]; + const initialStdioItems = [ + ...values.map((value) => initializeStdioItem(value, optionName)), + ...handleInputOptions(options, fdNumber) + ]; + const stdioItems = filterDuplicates(initialStdioItems); + const isStdioArray = stdioItems.length > 1; + validateStdioArray(stdioItems, isStdioArray, optionName); + validateStreams(stdioItems); + return { stdioItems, isStdioArray }; +}; +var initializeStdioItem = (value, optionName) => ({ + type: getStdioItemType(value, optionName), + value, + optionName +}); +var validateStdioArray = (stdioItems, isStdioArray, optionName) => { + if (stdioItems.length === 0) { + throw new TypeError(`The \`${optionName}\` option must not be an empty array.`); + } + if (!isStdioArray) { + return; + } + for (const { value, optionName: optionName2 } of stdioItems) { + if (INVALID_STDIO_ARRAY_OPTIONS.has(value)) { + throw new Error(`The \`${optionName2}\` option must not include \`${value}\`.`); + } + } +}; +var INVALID_STDIO_ARRAY_OPTIONS = /* @__PURE__ */ new Set(["ignore", "ipc"]); +var validateStreams = (stdioItems) => { + for (const stdioItem of stdioItems) { + validateFileStdio(stdioItem); + } +}; +var validateFileStdio = ({ type, value, optionName }) => { + if (isRegularUrl(value)) { + throw new TypeError(`The \`${optionName}: URL\` option must use the \`file:\` scheme. +For example, you can use the \`pathToFileURL()\` method of the \`url\` core module.`); + } + if (isUnknownStdioString(type, value)) { + throw new TypeError(`The \`${optionName}: { file: '...' }\` option must be used instead of \`${optionName}: '...'\`.`); + } +}; +var validateFileObjectMode = (stdioItems, objectMode) => { + if (!objectMode) { + return; + } + const fileStdioItem = stdioItems.find(({ type }) => FILE_TYPES.has(type)); + if (fileStdioItem !== void 0) { + throw new TypeError(`The \`${fileStdioItem.optionName}\` option cannot use both files and transforms in objectMode.`); + } +}; +var getFinalFileDescriptors = ({ initialFileDescriptors, addProperties: addProperties3, options, isSync }) => { + const fileDescriptors = []; + try { + for (const fileDescriptor of initialFileDescriptors) { + fileDescriptors.push(getFinalFileDescriptor({ + fileDescriptor, + fileDescriptors, + addProperties: addProperties3, + options, + isSync + })); + } + return fileDescriptors; + } catch (error) { + cleanupCustomStreams(fileDescriptors); + throw error; + } +}; +var getFinalFileDescriptor = ({ + fileDescriptor: { direction, objectMode, stdioItems }, + fileDescriptors, + addProperties: addProperties3, + options, + isSync +}) => { + const finalStdioItems = stdioItems.map((stdioItem) => addStreamProperties({ + stdioItem, + addProperties: addProperties3, + direction, + options, + fileDescriptors, + isSync + })); + return { direction, objectMode, stdioItems: finalStdioItems }; +}; +var addStreamProperties = ({ stdioItem, addProperties: addProperties3, direction, options, fileDescriptors, isSync }) => { + const duplicateStream = getDuplicateStream({ + stdioItem, + direction, + fileDescriptors, + isSync + }); + if (duplicateStream !== void 0) { + return { ...stdioItem, stream: duplicateStream }; + } + return { + ...stdioItem, + ...addProperties3[direction][stdioItem.type](stdioItem, options) + }; +}; +var cleanupCustomStreams = (fileDescriptors) => { + for (const { stdioItems } of fileDescriptors) { + for (const { stream } of stdioItems) { + if (stream !== void 0 && !isStandardStream(stream)) { + stream.destroy(); + } + } + } +}; +var forwardStdio = (stdioItems) => { + if (stdioItems.length > 1) { + return stdioItems.some(({ value: value2 }) => value2 === "overlapped") ? "overlapped" : "pipe"; + } + const [{ type, value }] = stdioItems; + return type === "native" ? value : "pipe"; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/handle-sync.js +var handleStdioSync = (options, verboseInfo) => handleStdio(addPropertiesSync, options, verboseInfo, true); +var forbiddenIfSync = ({ type, optionName }) => { + throwInvalidSyncValue(optionName, TYPE_TO_MESSAGE[type]); +}; +var forbiddenNativeIfSync = ({ optionName, value }) => { + if (value === "ipc" || value === "overlapped") { + throwInvalidSyncValue(optionName, `"${value}"`); + } + return {}; +}; +var throwInvalidSyncValue = (optionName, value) => { + throw new TypeError(`The \`${optionName}\` option cannot be ${value} with synchronous methods.`); +}; +var addProperties = { + generator() { + }, + asyncGenerator: forbiddenIfSync, + webStream: forbiddenIfSync, + nodeStream: forbiddenIfSync, + webTransform: forbiddenIfSync, + duplex: forbiddenIfSync, + asyncIterable: forbiddenIfSync, + native: forbiddenNativeIfSync +}; +var addPropertiesSync = { + input: { + ...addProperties, + fileUrl: ({ value }) => ({ contents: [bufferToUint8Array((0, import_node_fs3.readFileSync)(value))] }), + filePath: ({ value: { file } }) => ({ contents: [bufferToUint8Array((0, import_node_fs3.readFileSync)(file))] }), + fileNumber: forbiddenIfSync, + iterable: ({ value }) => ({ contents: [...value] }), + string: ({ value }) => ({ contents: [value] }), + uint8Array: ({ value }) => ({ contents: [value] }) + }, + output: { + ...addProperties, + fileUrl: ({ value }) => ({ path: value }), + filePath: ({ value: { file, append } }) => ({ path: file, append }), + fileNumber: ({ value }) => ({ path: value }), + iterable: forbiddenIfSync, + string: forbiddenIfSync, + uint8Array: forbiddenIfSync + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/strip-newline.js +var stripNewline = (value, { stripFinalNewline: stripFinalNewline2 }, fdNumber) => getStripFinalNewline(stripFinalNewline2, fdNumber) && value !== void 0 && !Array.isArray(value) ? stripFinalNewline(value) : value; +var getStripFinalNewline = (stripFinalNewline2, fdNumber) => fdNumber === "all" ? stripFinalNewline2[1] || stripFinalNewline2[2] : stripFinalNewline2[fdNumber]; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/generator.js +var import_node_stream = require("stream"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/split.js +var getSplitLinesGenerator = (binary, preserveNewlines, skipped, state) => binary || skipped ? void 0 : initializeSplitLines(preserveNewlines, state); +var splitLinesSync = (chunk, preserveNewlines, objectMode) => objectMode ? chunk.flatMap((item) => splitLinesItemSync(item, preserveNewlines)) : splitLinesItemSync(chunk, preserveNewlines); +var splitLinesItemSync = (chunk, preserveNewlines) => { + const { transform, final } = initializeSplitLines(preserveNewlines, {}); + return [...transform(chunk), ...final()]; +}; +var initializeSplitLines = (preserveNewlines, state) => { + state.previousChunks = ""; + return { + transform: splitGenerator.bind(void 0, state, preserveNewlines), + final: linesFinal.bind(void 0, state) + }; +}; +var splitGenerator = function* (state, preserveNewlines, chunk) { + if (typeof chunk !== "string") { + yield chunk; + return; + } + let { previousChunks } = state; + let start = -1; + for (let end = 0; end < chunk.length; end += 1) { + if (chunk[end] === "\n") { + const newlineLength = getNewlineLength(chunk, end, preserveNewlines, state); + let line = chunk.slice(start + 1, end + 1 - newlineLength); + if (previousChunks.length > 0) { + line = concatString(previousChunks, line); + previousChunks = ""; + } + yield line; + start = end; + } + } + if (start !== chunk.length - 1) { + previousChunks = concatString(previousChunks, chunk.slice(start + 1)); + } + state.previousChunks = previousChunks; +}; +var getNewlineLength = (chunk, end, preserveNewlines, state) => { + if (preserveNewlines) { + return 0; + } + state.isWindowsNewline = end !== 0 && chunk[end - 1] === "\r"; + return state.isWindowsNewline ? 2 : 1; +}; +var linesFinal = function* ({ previousChunks }) { + if (previousChunks.length > 0) { + yield previousChunks; + } +}; +var getAppendNewlineGenerator = ({ binary, preserveNewlines, readableObjectMode, state }) => binary || preserveNewlines || readableObjectMode ? void 0 : { transform: appendNewlineGenerator.bind(void 0, state) }; +var appendNewlineGenerator = function* ({ isWindowsNewline = false }, chunk) { + const { unixNewline, windowsNewline, LF: LF2, concatBytes } = typeof chunk === "string" ? linesStringInfo : linesUint8ArrayInfo; + if (chunk.at(-1) === LF2) { + yield chunk; + return; + } + const newline = isWindowsNewline ? windowsNewline : unixNewline; + yield concatBytes(chunk, newline); +}; +var concatString = (firstChunk, secondChunk) => `${firstChunk}${secondChunk}`; +var linesStringInfo = { + windowsNewline: "\r\n", + unixNewline: "\n", + LF: "\n", + concatBytes: concatString +}; +var concatUint8Array = (firstChunk, secondChunk) => { + const chunk = new Uint8Array(firstChunk.length + secondChunk.length); + chunk.set(firstChunk, 0); + chunk.set(secondChunk, firstChunk.length); + return chunk; +}; +var linesUint8ArrayInfo = { + windowsNewline: new Uint8Array([13, 10]), + unixNewline: new Uint8Array([10]), + LF: 10, + concatBytes: concatUint8Array +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/validate.js +var import_node_buffer = require("buffer"); +var getValidateTransformInput = (writableObjectMode, optionName) => writableObjectMode ? void 0 : validateStringTransformInput.bind(void 0, optionName); +var validateStringTransformInput = function* (optionName, chunk) { + if (typeof chunk !== "string" && !isUint8Array(chunk) && !import_node_buffer.Buffer.isBuffer(chunk)) { + throw new TypeError(`The \`${optionName}\` option's transform must use "objectMode: true" to receive as input: ${typeof chunk}.`); + } + yield chunk; +}; +var getValidateTransformReturn = (readableObjectMode, optionName) => readableObjectMode ? validateObjectTransformReturn.bind(void 0, optionName) : validateStringTransformReturn.bind(void 0, optionName); +var validateObjectTransformReturn = function* (optionName, chunk) { + validateEmptyReturn(optionName, chunk); + yield chunk; +}; +var validateStringTransformReturn = function* (optionName, chunk) { + validateEmptyReturn(optionName, chunk); + if (typeof chunk !== "string" && !isUint8Array(chunk)) { + throw new TypeError(`The \`${optionName}\` option's function must yield a string or an Uint8Array, not ${typeof chunk}.`); + } + yield chunk; +}; +var validateEmptyReturn = (optionName, chunk) => { + if (chunk === null || chunk === void 0) { + throw new TypeError(`The \`${optionName}\` option's function must not call \`yield ${chunk}\`. +Instead, \`yield\` should either be called with a value, or not be called at all. For example: + if (condition) { yield value; }`); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/encoding-transform.js +var import_node_buffer2 = require("buffer"); +var import_node_string_decoder2 = require("string_decoder"); +var getEncodingTransformGenerator = (binary, encoding, skipped) => { + if (skipped) { + return; + } + if (binary) { + return { transform: encodingUint8ArrayGenerator.bind(void 0, new TextEncoder()) }; + } + const stringDecoder = new import_node_string_decoder2.StringDecoder(encoding); + return { + transform: encodingStringGenerator.bind(void 0, stringDecoder), + final: encodingStringFinal.bind(void 0, stringDecoder) + }; +}; +var encodingUint8ArrayGenerator = function* (textEncoder3, chunk) { + if (import_node_buffer2.Buffer.isBuffer(chunk)) { + yield bufferToUint8Array(chunk); + } else if (typeof chunk === "string") { + yield textEncoder3.encode(chunk); + } else { + yield chunk; + } +}; +var encodingStringGenerator = function* (stringDecoder, chunk) { + yield isUint8Array(chunk) ? stringDecoder.write(chunk) : chunk; +}; +var encodingStringFinal = function* (stringDecoder) { + const lastChunk = stringDecoder.end(); + if (lastChunk !== "") { + yield lastChunk; + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/run-async.js +var import_node_util7 = require("util"); +var pushChunks = (0, import_node_util7.callbackify)(async (getChunks, state, getChunksArguments, transformStream) => { + state.currentIterable = getChunks(...getChunksArguments); + try { + for await (const chunk of state.currentIterable) { + transformStream.push(chunk); + } + } finally { + delete state.currentIterable; + } +}); +var transformChunk = async function* (chunk, generators, index) { + if (index === generators.length) { + yield chunk; + return; + } + const { transform = identityGenerator } = generators[index]; + for await (const transformedChunk of transform(chunk)) { + yield* transformChunk(transformedChunk, generators, index + 1); + } +}; +var finalChunks = async function* (generators) { + for (const [index, { final }] of Object.entries(generators)) { + yield* generatorFinalChunks(final, Number(index), generators); + } +}; +var generatorFinalChunks = async function* (final, index, generators) { + if (final === void 0) { + return; + } + for await (const finalChunk of final()) { + yield* transformChunk(finalChunk, generators, index + 1); + } +}; +var destroyTransform = (0, import_node_util7.callbackify)(async ({ currentIterable }, error) => { + if (currentIterable !== void 0) { + await (error ? currentIterable.throw(error) : currentIterable.return()); + return; + } + if (error) { + throw error; + } +}); +var identityGenerator = function* (chunk) { + yield chunk; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/run-sync.js +var pushChunksSync = (getChunksSync, getChunksArguments, transformStream, done) => { + try { + for (const chunk of getChunksSync(...getChunksArguments)) { + transformStream.push(chunk); + } + done(); + } catch (error) { + done(error); + } +}; +var runTransformSync = (generators, chunks) => [ + ...chunks.flatMap((chunk) => [...transformChunkSync(chunk, generators, 0)]), + ...finalChunksSync(generators) +]; +var transformChunkSync = function* (chunk, generators, index) { + if (index === generators.length) { + yield chunk; + return; + } + const { transform = identityGenerator2 } = generators[index]; + for (const transformedChunk of transform(chunk)) { + yield* transformChunkSync(transformedChunk, generators, index + 1); + } +}; +var finalChunksSync = function* (generators) { + for (const [index, { final }] of Object.entries(generators)) { + yield* generatorFinalChunksSync(final, Number(index), generators); + } +}; +var generatorFinalChunksSync = function* (final, index, generators) { + if (final === void 0) { + return; + } + for (const finalChunk of final()) { + yield* transformChunkSync(finalChunk, generators, index + 1); + } +}; +var identityGenerator2 = function* (chunk) { + yield chunk; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/transform/generator.js +var generatorToStream = ({ + value, + value: { transform, final, writableObjectMode, readableObjectMode }, + optionName +}, { encoding }) => { + const state = {}; + const generators = addInternalGenerators(value, encoding, optionName); + const transformAsync = isAsyncGenerator(transform); + const finalAsync = isAsyncGenerator(final); + const transformMethod = transformAsync ? pushChunks.bind(void 0, transformChunk, state) : pushChunksSync.bind(void 0, transformChunkSync); + const finalMethod = transformAsync || finalAsync ? pushChunks.bind(void 0, finalChunks, state) : pushChunksSync.bind(void 0, finalChunksSync); + const destroyMethod = transformAsync || finalAsync ? destroyTransform.bind(void 0, state) : void 0; + const stream = new import_node_stream.Transform({ + writableObjectMode, + writableHighWaterMark: (0, import_node_stream.getDefaultHighWaterMark)(writableObjectMode), + readableObjectMode, + readableHighWaterMark: (0, import_node_stream.getDefaultHighWaterMark)(readableObjectMode), + transform(chunk, encoding2, done) { + transformMethod([chunk, generators, 0], this, done); + }, + flush(done) { + finalMethod([generators], this, done); + }, + destroy: destroyMethod + }); + return { stream }; +}; +var runGeneratorsSync = (chunks, stdioItems, encoding, isInput) => { + const generators = stdioItems.filter(({ type }) => type === "generator"); + const reversedGenerators = isInput ? generators.reverse() : generators; + for (const { value, optionName } of reversedGenerators) { + const generators2 = addInternalGenerators(value, encoding, optionName); + chunks = runTransformSync(generators2, chunks); + } + return chunks; +}; +var addInternalGenerators = ({ transform, final, binary, writableObjectMode, readableObjectMode, preserveNewlines }, encoding, optionName) => { + const state = {}; + return [ + { transform: getValidateTransformInput(writableObjectMode, optionName) }, + getEncodingTransformGenerator(binary, encoding, writableObjectMode), + getSplitLinesGenerator(binary, preserveNewlines, writableObjectMode, state), + { transform, final }, + { transform: getValidateTransformReturn(readableObjectMode, optionName) }, + getAppendNewlineGenerator({ + binary, + preserveNewlines, + readableObjectMode, + state + }) + ].filter(Boolean); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/input-sync.js +var addInputOptionsSync = (fileDescriptors, options) => { + for (const fdNumber of getInputFdNumbers(fileDescriptors)) { + addInputOptionSync(fileDescriptors, fdNumber, options); + } +}; +var getInputFdNumbers = (fileDescriptors) => new Set(Object.entries(fileDescriptors).filter(([, { direction }]) => direction === "input").map(([fdNumber]) => Number(fdNumber))); +var addInputOptionSync = (fileDescriptors, fdNumber, options) => { + const { stdioItems } = fileDescriptors[fdNumber]; + const allStdioItems = stdioItems.filter(({ contents }) => contents !== void 0); + if (allStdioItems.length === 0) { + return; + } + if (fdNumber !== 0) { + const [{ type, optionName }] = allStdioItems; + throw new TypeError(`Only the \`stdin\` option, not \`${optionName}\`, can be ${TYPE_TO_MESSAGE[type]} with synchronous methods.`); + } + const allContents = allStdioItems.map(({ contents }) => contents); + const transformedContents = allContents.map((contents) => applySingleInputGeneratorsSync(contents, stdioItems)); + options.input = joinToUint8Array(transformedContents); +}; +var applySingleInputGeneratorsSync = (contents, stdioItems) => { + const newContents = runGeneratorsSync(contents, stdioItems, "utf8", true); + validateSerializable(newContents); + return joinToUint8Array(newContents); +}; +var validateSerializable = (newContents) => { + const invalidItem = newContents.find((item) => typeof item !== "string" && !isUint8Array(item)); + if (invalidItem !== void 0) { + throw new TypeError(`The \`stdin\` option is invalid: when passing objects as input, a transform must be used to serialize them to strings or Uint8Arrays: ${invalidItem}.`); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/output-sync.js +var import_node_fs4 = require("fs"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/output.js +var shouldLogOutput = ({ stdioItems, encoding, verboseInfo, fdNumber }) => fdNumber !== "all" && isFullVerbose(verboseInfo, fdNumber) && !BINARY_ENCODINGS.has(encoding) && fdUsesVerbose(fdNumber) && (stdioItems.some(({ type, value }) => type === "native" && PIPED_STDIO_VALUES.has(value)) || stdioItems.every(({ type }) => TRANSFORM_TYPES.has(type))); +var fdUsesVerbose = (fdNumber) => fdNumber === 1 || fdNumber === 2; +var PIPED_STDIO_VALUES = /* @__PURE__ */ new Set(["pipe", "overlapped"]); +var logLines = async (linesIterable, stream, fdNumber, verboseInfo) => { + for await (const line of linesIterable) { + if (!isPipingStream(stream)) { + logLine(line, fdNumber, verboseInfo); + } + } +}; +var logLinesSync = (linesArray, fdNumber, verboseInfo) => { + for (const line of linesArray) { + logLine(line, fdNumber, verboseInfo); + } +}; +var isPipingStream = (stream) => stream._readableState.pipes.length > 0; +var logLine = (line, fdNumber, verboseInfo) => { + const verboseMessage = serializeVerboseMessage(line); + verboseLog({ + type: "output", + verboseMessage, + fdNumber, + verboseInfo + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/output-sync.js +var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options, isMaxBuffer, verboseInfo }) => { + if (output === null) { + return { output: Array.from({ length: 3 }) }; + } + const state = {}; + const outputFiles = /* @__PURE__ */ new Set([]); + const transformedOutput = output.map((result, fdNumber) => transformOutputResultSync({ + result, + fileDescriptors, + fdNumber, + state, + outputFiles, + isMaxBuffer, + verboseInfo + }, options)); + return { output: transformedOutput, ...state }; +}; +var transformOutputResultSync = ({ result, fileDescriptors, fdNumber, state, outputFiles, isMaxBuffer, verboseInfo }, { buffer, encoding, lines, stripFinalNewline: stripFinalNewline2, maxBuffer }) => { + if (result === null) { + return; + } + const truncatedResult = truncateMaxBufferSync(result, isMaxBuffer, maxBuffer); + const uint8ArrayResult = bufferToUint8Array(truncatedResult); + const { stdioItems, objectMode } = fileDescriptors[fdNumber]; + const chunks = runOutputGeneratorsSync([uint8ArrayResult], stdioItems, encoding, state); + const { serializedResult, finalResult = serializedResult } = serializeChunks({ + chunks, + objectMode, + encoding, + lines, + stripFinalNewline: stripFinalNewline2, + fdNumber + }); + logOutputSync({ + serializedResult, + fdNumber, + state, + verboseInfo, + encoding, + stdioItems, + objectMode + }); + const returnedResult = buffer[fdNumber] ? finalResult : void 0; + try { + if (state.error === void 0) { + writeToFiles(serializedResult, stdioItems, outputFiles); + } + return returnedResult; + } catch (error) { + state.error = error; + return returnedResult; + } +}; +var runOutputGeneratorsSync = (chunks, stdioItems, encoding, state) => { + try { + return runGeneratorsSync(chunks, stdioItems, encoding, false); + } catch (error) { + state.error = error; + return chunks; + } +}; +var serializeChunks = ({ chunks, objectMode, encoding, lines, stripFinalNewline: stripFinalNewline2, fdNumber }) => { + if (objectMode) { + return { serializedResult: chunks }; + } + if (encoding === "buffer") { + return { serializedResult: joinToUint8Array(chunks) }; + } + const serializedResult = joinToString(chunks, encoding); + if (lines[fdNumber]) { + return { serializedResult, finalResult: splitLinesSync(serializedResult, !stripFinalNewline2[fdNumber], objectMode) }; + } + return { serializedResult }; +}; +var logOutputSync = ({ serializedResult, fdNumber, state, verboseInfo, encoding, stdioItems, objectMode }) => { + if (!shouldLogOutput({ + stdioItems, + encoding, + verboseInfo, + fdNumber + })) { + return; + } + const linesArray = splitLinesSync(serializedResult, false, objectMode); + try { + logLinesSync(linesArray, fdNumber, verboseInfo); + } catch (error) { + state.error ??= error; + } +}; +var writeToFiles = (serializedResult, stdioItems, outputFiles) => { + for (const { path: path12, append } of stdioItems.filter(({ type }) => FILE_TYPES.has(type))) { + const pathString = typeof path12 === "string" ? path12 : path12.toString(); + if (append || outputFiles.has(pathString)) { + (0, import_node_fs4.appendFileSync)(path12, serializedResult); + } else { + outputFiles.add(pathString); + (0, import_node_fs4.writeFileSync)(path12, serializedResult); + } + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/all-sync.js +var getAllSync = ([, stdout, stderr], options) => { + if (!options.all) { + return; + } + if (stdout === void 0) { + return stderr; + } + if (stderr === void 0) { + return stdout; + } + if (Array.isArray(stdout)) { + return Array.isArray(stderr) ? [...stdout, ...stderr] : [...stdout, stripNewline(stderr, options, "all")]; + } + if (Array.isArray(stderr)) { + return [stripNewline(stdout, options, "all"), ...stderr]; + } + if (isUint8Array(stdout) && isUint8Array(stderr)) { + return concatUint8Arrays([stdout, stderr]); + } + return `${stdout}${stderr}`; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/exit-async.js +var import_node_events7 = require("events"); +var waitForExit = async (subprocess, context) => { + const [exitCode, signal] = await waitForExitOrError(subprocess); + context.isForcefullyTerminated ??= false; + return [exitCode, signal]; +}; +var waitForExitOrError = async (subprocess) => { + const [spawnPayload, exitPayload] = await Promise.allSettled([ + (0, import_node_events7.once)(subprocess, "spawn"), + (0, import_node_events7.once)(subprocess, "exit") + ]); + if (spawnPayload.status === "rejected") { + return []; + } + return exitPayload.status === "rejected" ? waitForSubprocessExit(subprocess) : exitPayload.value; +}; +var waitForSubprocessExit = async (subprocess) => { + try { + return await (0, import_node_events7.once)(subprocess, "exit"); + } catch { + return waitForSubprocessExit(subprocess); + } +}; +var waitForSuccessfulExit = async (exitPromise) => { + const [exitCode, signal] = await exitPromise; + if (!isSubprocessErrorExit(exitCode, signal) && isFailedExit(exitCode, signal)) { + throw new DiscardedError(); + } + return [exitCode, signal]; +}; +var isSubprocessErrorExit = (exitCode, signal) => exitCode === void 0 && signal === void 0; +var isFailedExit = (exitCode, signal) => exitCode !== 0 || signal !== null; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/exit-sync.js +var getExitResultSync = ({ error, status: exitCode, signal, output }, { maxBuffer }) => { + const resultError = getResultError(error, exitCode, signal); + const timedOut = resultError?.code === "ETIMEDOUT"; + const isMaxBuffer = isMaxBufferSync(resultError, output, maxBuffer); + return { + resultError, + exitCode, + signal, + timedOut, + isMaxBuffer + }; +}; +var getResultError = (error, exitCode, signal) => { + if (error !== void 0) { + return error; + } + return isFailedExit(exitCode, signal) ? new DiscardedError() : void 0; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/main-sync.js +var execaCoreSync = (rawFile, rawArguments, rawOptions) => { + const { file, commandArguments, command, escapedCommand, startTime, verboseInfo, options, fileDescriptors } = handleSyncArguments(rawFile, rawArguments, rawOptions); + const result = spawnSubprocessSync({ + file, + commandArguments, + options, + command, + escapedCommand, + verboseInfo, + fileDescriptors, + startTime + }); + return handleResult2(result, verboseInfo, options); +}; +var handleSyncArguments = (rawFile, rawArguments, rawOptions) => { + const { command, escapedCommand, startTime, verboseInfo } = handleCommand(rawFile, rawArguments, rawOptions); + const syncOptions = normalizeSyncOptions(rawOptions); + const { file, commandArguments, options } = normalizeOptions(rawFile, rawArguments, syncOptions); + validateSyncOptions(options); + const fileDescriptors = handleStdioSync(options, verboseInfo); + return { + file, + commandArguments, + command, + escapedCommand, + startTime, + verboseInfo, + options, + fileDescriptors + }; +}; +var normalizeSyncOptions = (options) => options.node && !options.ipc ? { ...options, ipc: false } : options; +var validateSyncOptions = ({ ipc, ipcInput, detached, cancelSignal }) => { + if (ipcInput) { + throwInvalidSyncOption("ipcInput"); + } + if (ipc) { + throwInvalidSyncOption("ipc: true"); + } + if (detached) { + throwInvalidSyncOption("detached: true"); + } + if (cancelSignal) { + throwInvalidSyncOption("cancelSignal"); + } +}; +var throwInvalidSyncOption = (value) => { + throw new TypeError(`The "${value}" option cannot be used with synchronous methods.`); +}; +var spawnSubprocessSync = ({ file, commandArguments, options, command, escapedCommand, verboseInfo, fileDescriptors, startTime }) => { + const syncResult = runSubprocessSync({ + file, + commandArguments, + options, + command, + escapedCommand, + fileDescriptors, + startTime + }); + if (syncResult.failed) { + return syncResult; + } + const { resultError, exitCode, signal, timedOut, isMaxBuffer } = getExitResultSync(syncResult, options); + const { output, error = resultError } = transformOutputSync({ + fileDescriptors, + syncResult, + options, + isMaxBuffer, + verboseInfo + }); + const stdio = output.map((stdioOutput, fdNumber) => stripNewline(stdioOutput, options, fdNumber)); + const all = stripNewline(getAllSync(output, options), options, "all"); + return getSyncResult({ + error, + exitCode, + signal, + timedOut, + isMaxBuffer, + stdio, + all, + options, + command, + escapedCommand, + startTime + }); +}; +var runSubprocessSync = ({ file, commandArguments, options, command, escapedCommand, fileDescriptors, startTime }) => { + try { + addInputOptionsSync(fileDescriptors, options); + const normalizedOptions = normalizeSpawnSyncOptions(options); + return (0, import_node_child_process3.spawnSync)(...concatenateShell(file, commandArguments, normalizedOptions)); + } catch (error) { + return makeEarlyError({ + error, + command, + escapedCommand, + fileDescriptors, + options, + startTime, + isSync: true + }); + } +}; +var normalizeSpawnSyncOptions = ({ encoding, maxBuffer, ...options }) => ({ ...options, encoding: "buffer", maxBuffer: getMaxBufferSync(maxBuffer) }); +var getSyncResult = ({ error, exitCode, signal, timedOut, isMaxBuffer, stdio, all, options, command, escapedCommand, startTime }) => error === void 0 ? makeSuccessResult({ + command, + escapedCommand, + stdio, + all, + ipcOutput: [], + options, + startTime +}) : makeError({ + error, + command, + escapedCommand, + timedOut, + isCanceled: false, + isGracefullyCanceled: false, + isMaxBuffer, + isForcefullyTerminated: false, + exitCode, + signal, + stdio, + all, + ipcOutput: [], + options, + startTime, + isSync: true +}); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/main-async.js +var import_node_events14 = require("events"); +var import_node_child_process5 = require("child_process"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/methods.js +var import_node_process10 = __toESM(require("process"), 1); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/get-one.js +var import_node_events8 = require("events"); +var getOneMessage = ({ anyProcess, channel, isSubprocess, ipc }, { reference = true, filter } = {}) => { + validateIpcMethod({ + methodName: "getOneMessage", + isSubprocess, + ipc, + isConnected: isConnected(anyProcess) + }); + return getOneMessageAsync({ + anyProcess, + channel, + isSubprocess, + filter, + reference + }); +}; +var getOneMessageAsync = async ({ anyProcess, channel, isSubprocess, filter, reference }) => { + addReference(channel, reference); + const ipcEmitter = getIpcEmitter(anyProcess, channel, isSubprocess); + const controller = new AbortController(); + try { + return await Promise.race([ + getMessage(ipcEmitter, filter, controller), + throwOnDisconnect2(ipcEmitter, isSubprocess, controller), + throwOnStrictError(ipcEmitter, isSubprocess, controller) + ]); + } catch (error) { + disconnect(anyProcess); + throw error; + } finally { + controller.abort(); + removeReference(channel, reference); + } +}; +var getMessage = async (ipcEmitter, filter, { signal }) => { + if (filter === void 0) { + const [message] = await (0, import_node_events8.once)(ipcEmitter, "message", { signal }); + return message; + } + for await (const [message] of (0, import_node_events8.on)(ipcEmitter, "message", { signal })) { + if (filter(message)) { + return message; + } + } +}; +var throwOnDisconnect2 = async (ipcEmitter, isSubprocess, { signal }) => { + await (0, import_node_events8.once)(ipcEmitter, "disconnect", { signal }); + throwOnEarlyDisconnect(isSubprocess); +}; +var throwOnStrictError = async (ipcEmitter, isSubprocess, { signal }) => { + const [error] = await (0, import_node_events8.once)(ipcEmitter, "strict:error", { signal }); + throw getStrictResponseError(error, isSubprocess); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/get-each.js +var import_node_events9 = require("events"); +var getEachMessage = ({ anyProcess, channel, isSubprocess, ipc }, { reference = true } = {}) => loopOnMessages({ + anyProcess, + channel, + isSubprocess, + ipc, + shouldAwait: !isSubprocess, + reference +}); +var loopOnMessages = ({ anyProcess, channel, isSubprocess, ipc, shouldAwait, reference }) => { + validateIpcMethod({ + methodName: "getEachMessage", + isSubprocess, + ipc, + isConnected: isConnected(anyProcess) + }); + addReference(channel, reference); + const ipcEmitter = getIpcEmitter(anyProcess, channel, isSubprocess); + const controller = new AbortController(); + const state = {}; + stopOnDisconnect(anyProcess, ipcEmitter, controller); + abortOnStrictError({ + ipcEmitter, + isSubprocess, + controller, + state + }); + return iterateOnMessages({ + anyProcess, + channel, + ipcEmitter, + isSubprocess, + shouldAwait, + controller, + state, + reference + }); +}; +var stopOnDisconnect = async (anyProcess, ipcEmitter, controller) => { + try { + await (0, import_node_events9.once)(ipcEmitter, "disconnect", { signal: controller.signal }); + controller.abort(); + } catch { + } +}; +var abortOnStrictError = async ({ ipcEmitter, isSubprocess, controller, state }) => { + try { + const [error] = await (0, import_node_events9.once)(ipcEmitter, "strict:error", { signal: controller.signal }); + state.error = getStrictResponseError(error, isSubprocess); + controller.abort(); + } catch { + } +}; +var iterateOnMessages = async function* ({ anyProcess, channel, ipcEmitter, isSubprocess, shouldAwait, controller, state, reference }) { + try { + for await (const [message] of (0, import_node_events9.on)(ipcEmitter, "message", { signal: controller.signal })) { + throwIfStrictError(state); + yield message; + } + } catch { + throwIfStrictError(state); + } finally { + controller.abort(); + removeReference(channel, reference); + if (!isSubprocess) { + disconnect(anyProcess); + } + if (shouldAwait) { + await anyProcess; + } + } +}; +var throwIfStrictError = ({ error }) => { + if (error) { + throw error; + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/methods.js +var addIpcMethods = (subprocess, { ipc }) => { + Object.assign(subprocess, getIpcMethods(subprocess, false, ipc)); +}; +var getIpcExport = () => { + const anyProcess = import_node_process10.default; + const isSubprocess = true; + const ipc = import_node_process10.default.channel !== void 0; + return { + ...getIpcMethods(anyProcess, isSubprocess, ipc), + getCancelSignal: getCancelSignal.bind(void 0, { + anyProcess, + channel: anyProcess.channel, + isSubprocess, + ipc + }) + }; +}; +var getIpcMethods = (anyProcess, isSubprocess, ipc) => ({ + sendMessage: sendMessage.bind(void 0, { + anyProcess, + channel: anyProcess.channel, + isSubprocess, + ipc + }), + getOneMessage: getOneMessage.bind(void 0, { + anyProcess, + channel: anyProcess.channel, + isSubprocess, + ipc + }), + getEachMessage: getEachMessage.bind(void 0, { + anyProcess, + channel: anyProcess.channel, + isSubprocess, + ipc + }) +}); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/early-error.js +var import_node_child_process4 = require("child_process"); +var import_node_stream2 = require("stream"); +var handleEarlyError = ({ error, command, escapedCommand, fileDescriptors, options, startTime, verboseInfo }) => { + cleanupCustomStreams(fileDescriptors); + const subprocess = new import_node_child_process4.ChildProcess(); + createDummyStreams(subprocess, fileDescriptors); + Object.assign(subprocess, { readable, writable, duplex }); + const earlyError = makeEarlyError({ + error, + command, + escapedCommand, + fileDescriptors, + options, + startTime, + isSync: false + }); + const promise = handleDummyPromise(earlyError, verboseInfo, options); + return { subprocess, promise }; +}; +var createDummyStreams = (subprocess, fileDescriptors) => { + const stdin = createDummyStream(); + const stdout = createDummyStream(); + const stderr = createDummyStream(); + const extraStdio = Array.from({ length: fileDescriptors.length - 3 }, createDummyStream); + const all = createDummyStream(); + const stdio = [stdin, stdout, stderr, ...extraStdio]; + Object.assign(subprocess, { + stdin, + stdout, + stderr, + all, + stdio + }); +}; +var createDummyStream = () => { + const stream = new import_node_stream2.PassThrough(); + stream.end(); + return stream; +}; +var readable = () => new import_node_stream2.Readable({ read() { +} }); +var writable = () => new import_node_stream2.Writable({ write() { +} }); +var duplex = () => new import_node_stream2.Duplex({ read() { +}, write() { +} }); +var handleDummyPromise = async (error, verboseInfo, options) => handleResult2(error, verboseInfo, options); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/handle-async.js +var import_node_fs5 = require("fs"); +var import_node_buffer3 = require("buffer"); +var import_node_stream3 = require("stream"); +var handleStdioAsync = (options, verboseInfo) => handleStdio(addPropertiesAsync, options, verboseInfo, false); +var forbiddenIfAsync = ({ type, optionName }) => { + throw new TypeError(`The \`${optionName}\` option cannot be ${TYPE_TO_MESSAGE[type]}.`); +}; +var addProperties2 = { + fileNumber: forbiddenIfAsync, + generator: generatorToStream, + asyncGenerator: generatorToStream, + nodeStream: ({ value }) => ({ stream: value }), + webTransform({ value: { transform, writableObjectMode, readableObjectMode } }) { + const objectMode = writableObjectMode || readableObjectMode; + const stream = import_node_stream3.Duplex.fromWeb(transform, { objectMode }); + return { stream }; + }, + duplex: ({ value: { transform } }) => ({ stream: transform }), + native() { + } +}; +var addPropertiesAsync = { + input: { + ...addProperties2, + fileUrl: ({ value }) => ({ stream: (0, import_node_fs5.createReadStream)(value) }), + filePath: ({ value: { file } }) => ({ stream: (0, import_node_fs5.createReadStream)(file) }), + webStream: ({ value }) => ({ stream: import_node_stream3.Readable.fromWeb(value) }), + iterable: ({ value }) => ({ stream: import_node_stream3.Readable.from(value) }), + asyncIterable: ({ value }) => ({ stream: import_node_stream3.Readable.from(value) }), + string: ({ value }) => ({ stream: import_node_stream3.Readable.from(value) }), + uint8Array: ({ value }) => ({ stream: import_node_stream3.Readable.from(import_node_buffer3.Buffer.from(value)) }) + }, + output: { + ...addProperties2, + fileUrl: ({ value }) => ({ stream: (0, import_node_fs5.createWriteStream)(value) }), + filePath: ({ value: { file, append } }) => ({ stream: (0, import_node_fs5.createWriteStream)(file, append ? { flags: "a" } : {}) }), + webStream: ({ value }) => ({ stream: import_node_stream3.Writable.fromWeb(value) }), + iterable: forbiddenIfAsync, + asyncIterable: forbiddenIfAsync, + string: forbiddenIfAsync, + uint8Array: forbiddenIfAsync + } +}; + +// ../../node_modules/.pnpm/@sindresorhus+merge-streams@4.0.0/node_modules/@sindresorhus/merge-streams/index.js +var import_node_events10 = require("events"); +var import_node_stream4 = require("stream"); +var import_promises6 = require("stream/promises"); +function mergeStreams(streams) { + if (!Array.isArray(streams)) { + throw new TypeError(`Expected an array, got \`${typeof streams}\`.`); + } + for (const stream of streams) { + validateStream(stream); + } + const objectMode = streams.some(({ readableObjectMode }) => readableObjectMode); + const highWaterMark = getHighWaterMark(streams, objectMode); + const passThroughStream = new MergedStream({ + objectMode, + writableHighWaterMark: highWaterMark, + readableHighWaterMark: highWaterMark + }); + for (const stream of streams) { + passThroughStream.add(stream); + } + return passThroughStream; +} +var getHighWaterMark = (streams, objectMode) => { + if (streams.length === 0) { + return (0, import_node_stream4.getDefaultHighWaterMark)(objectMode); + } + const highWaterMarks = streams.filter(({ readableObjectMode }) => readableObjectMode === objectMode).map(({ readableHighWaterMark }) => readableHighWaterMark); + return Math.max(...highWaterMarks); +}; +var MergedStream = class extends import_node_stream4.PassThrough { + #streams = /* @__PURE__ */ new Set([]); + #ended = /* @__PURE__ */ new Set([]); + #aborted = /* @__PURE__ */ new Set([]); + #onFinished; + #unpipeEvent = /* @__PURE__ */ Symbol("unpipe"); + #streamPromises = /* @__PURE__ */ new WeakMap(); + add(stream) { + validateStream(stream); + if (this.#streams.has(stream)) { + return; + } + this.#streams.add(stream); + this.#onFinished ??= onMergedStreamFinished(this, this.#streams, this.#unpipeEvent); + const streamPromise = endWhenStreamsDone({ + passThroughStream: this, + stream, + streams: this.#streams, + ended: this.#ended, + aborted: this.#aborted, + onFinished: this.#onFinished, + unpipeEvent: this.#unpipeEvent + }); + this.#streamPromises.set(stream, streamPromise); + stream.pipe(this, { end: false }); + } + async remove(stream) { + validateStream(stream); + if (!this.#streams.has(stream)) { + return false; + } + const streamPromise = this.#streamPromises.get(stream); + if (streamPromise === void 0) { + return false; + } + this.#streamPromises.delete(stream); + stream.unpipe(this); + await streamPromise; + return true; + } +}; +var onMergedStreamFinished = async (passThroughStream, streams, unpipeEvent) => { + updateMaxListeners(passThroughStream, PASSTHROUGH_LISTENERS_COUNT); + const controller = new AbortController(); + try { + await Promise.race([ + onMergedStreamEnd(passThroughStream, controller), + onInputStreamsUnpipe(passThroughStream, streams, unpipeEvent, controller) + ]); + } finally { + controller.abort(); + updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_COUNT); + } +}; +var onMergedStreamEnd = async (passThroughStream, { signal }) => { + try { + await (0, import_promises6.finished)(passThroughStream, { signal, cleanup: true }); + } catch (error) { + errorOrAbortStream(passThroughStream, error); + throw error; + } +}; +var onInputStreamsUnpipe = async (passThroughStream, streams, unpipeEvent, { signal }) => { + for await (const [unpipedStream] of (0, import_node_events10.on)(passThroughStream, "unpipe", { signal })) { + if (streams.has(unpipedStream)) { + unpipedStream.emit(unpipeEvent); + } + } +}; +var validateStream = (stream) => { + if (typeof stream?.pipe !== "function") { + throw new TypeError(`Expected a readable stream, got: \`${typeof stream}\`.`); + } +}; +var endWhenStreamsDone = async ({ passThroughStream, stream, streams, ended, aborted: aborted2, onFinished, unpipeEvent }) => { + updateMaxListeners(passThroughStream, PASSTHROUGH_LISTENERS_PER_STREAM); + const controller = new AbortController(); + try { + await Promise.race([ + afterMergedStreamFinished(onFinished, stream, controller), + onInputStreamEnd({ + passThroughStream, + stream, + streams, + ended, + aborted: aborted2, + controller + }), + onInputStreamUnpipe({ + stream, + streams, + ended, + aborted: aborted2, + unpipeEvent, + controller + }) + ]); + } finally { + controller.abort(); + updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_PER_STREAM); + } + if (streams.size > 0 && streams.size === ended.size + aborted2.size) { + if (ended.size === 0 && aborted2.size > 0) { + abortStream(passThroughStream); + } else { + endStream(passThroughStream); + } + } +}; +var afterMergedStreamFinished = async (onFinished, stream, { signal }) => { + try { + await onFinished; + if (!signal.aborted) { + abortStream(stream); + } + } catch (error) { + if (!signal.aborted) { + errorOrAbortStream(stream, error); + } + } +}; +var onInputStreamEnd = async ({ passThroughStream, stream, streams, ended, aborted: aborted2, controller: { signal } }) => { + try { + await (0, import_promises6.finished)(stream, { + signal, + cleanup: true, + readable: true, + writable: false + }); + if (streams.has(stream)) { + ended.add(stream); + } + } catch (error) { + if (signal.aborted || !streams.has(stream)) { + return; + } + if (isAbortError(error)) { + aborted2.add(stream); + } else { + errorStream(passThroughStream, error); + } + } +}; +var onInputStreamUnpipe = async ({ stream, streams, ended, aborted: aborted2, unpipeEvent, controller: { signal } }) => { + await (0, import_node_events10.once)(stream, unpipeEvent, { signal }); + if (!stream.readable) { + return (0, import_node_events10.once)(signal, "abort", { signal }); + } + streams.delete(stream); + ended.delete(stream); + aborted2.delete(stream); +}; +var endStream = (stream) => { + if (stream.writable) { + stream.end(); + } +}; +var errorOrAbortStream = (stream, error) => { + if (isAbortError(error)) { + abortStream(stream); + } else { + errorStream(stream, error); + } +}; +var isAbortError = (error) => error?.code === "ERR_STREAM_PREMATURE_CLOSE"; +var abortStream = (stream) => { + if (stream.readable || stream.writable) { + stream.destroy(); + } +}; +var errorStream = (stream, error) => { + if (!stream.destroyed) { + stream.once("error", noop2); + stream.destroy(error); + } +}; +var noop2 = () => { +}; +var updateMaxListeners = (passThroughStream, increment2) => { + const maxListeners = passThroughStream.getMaxListeners(); + if (maxListeners !== 0 && maxListeners !== Number.POSITIVE_INFINITY) { + passThroughStream.setMaxListeners(maxListeners + increment2); + } +}; +var PASSTHROUGH_LISTENERS_COUNT = 2; +var PASSTHROUGH_LISTENERS_PER_STREAM = 1; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/pipeline.js +var import_promises7 = require("stream/promises"); +var pipeStreams = (source, destination) => { + source.pipe(destination); + onSourceFinish(source, destination); + onDestinationFinish(source, destination); +}; +var onSourceFinish = async (source, destination) => { + if (isStandardStream(source) || isStandardStream(destination)) { + return; + } + try { + await (0, import_promises7.finished)(source, { cleanup: true, readable: true, writable: false }); + } catch { + } + endDestinationStream(destination); +}; +var endDestinationStream = (destination) => { + if (destination.writable) { + destination.end(); + } +}; +var onDestinationFinish = async (source, destination) => { + if (isStandardStream(source) || isStandardStream(destination)) { + return; + } + try { + await (0, import_promises7.finished)(destination, { cleanup: true, readable: false, writable: true }); + } catch { + } + abortSourceStream(source); +}; +var abortSourceStream = (source) => { + if (source.readable) { + source.destroy(); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/output-async.js +var pipeOutputAsync = (subprocess, fileDescriptors, controller) => { + const pipeGroups = /* @__PURE__ */ new Map(); + for (const [fdNumber, { stdioItems, direction }] of Object.entries(fileDescriptors)) { + for (const { stream } of stdioItems.filter(({ type }) => TRANSFORM_TYPES.has(type))) { + pipeTransform(subprocess, stream, direction, fdNumber); + } + for (const { stream } of stdioItems.filter(({ type }) => !TRANSFORM_TYPES.has(type))) { + pipeStdioItem({ + subprocess, + stream, + direction, + fdNumber, + pipeGroups, + controller + }); + } + } + for (const [outputStream, inputStreams] of pipeGroups.entries()) { + const inputStream = inputStreams.length === 1 ? inputStreams[0] : mergeStreams(inputStreams); + pipeStreams(inputStream, outputStream); + } +}; +var pipeTransform = (subprocess, stream, direction, fdNumber) => { + if (direction === "output") { + pipeStreams(subprocess.stdio[fdNumber], stream); + } else { + pipeStreams(stream, subprocess.stdio[fdNumber]); + } + const streamProperty = SUBPROCESS_STREAM_PROPERTIES[fdNumber]; + if (streamProperty !== void 0) { + subprocess[streamProperty] = stream; + } + subprocess.stdio[fdNumber] = stream; +}; +var SUBPROCESS_STREAM_PROPERTIES = ["stdin", "stdout", "stderr"]; +var pipeStdioItem = ({ subprocess, stream, direction, fdNumber, pipeGroups, controller }) => { + if (stream === void 0) { + return; + } + setStandardStreamMaxListeners(stream, controller); + const [inputStream, outputStream] = direction === "output" ? [stream, subprocess.stdio[fdNumber]] : [subprocess.stdio[fdNumber], stream]; + const outputStreams = pipeGroups.get(inputStream) ?? []; + pipeGroups.set(inputStream, [...outputStreams, outputStream]); +}; +var setStandardStreamMaxListeners = (stream, { signal }) => { + if (isStandardStream(stream)) { + incrementMaxListeners(stream, MAX_LISTENERS_INCREMENT, signal); + } +}; +var MAX_LISTENERS_INCREMENT = 2; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/cleanup.js +var import_node_events11 = require("events"); + +// ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js +var signals = []; +signals.push("SIGHUP", "SIGINT", "SIGTERM"); +if (process.platform !== "win32") { + signals.push( + "SIGALRM", + "SIGABRT", + "SIGVTALRM", + "SIGXCPU", + "SIGXFSZ", + "SIGUSR2", + "SIGTRAP", + "SIGSYS", + "SIGQUIT", + "SIGIOT" + // should detect profiler and enable/disable accordingly. + // see #21 + // 'SIGPROF' + ); +} +if (process.platform === "linux") { + signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT"); +} + +// ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js +var processOk = (process10) => !!process10 && typeof process10 === "object" && typeof process10.removeListener === "function" && typeof process10.emit === "function" && typeof process10.reallyExit === "function" && typeof process10.listeners === "function" && typeof process10.kill === "function" && typeof process10.pid === "number" && typeof process10.on === "function"; +var kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter"); +var global2 = globalThis; +var ObjectDefineProperty = Object.defineProperty.bind(Object); +var Emitter = class { + emitted = { + afterExit: false, + exit: false + }; + listeners = { + afterExit: [], + exit: [] + }; + count = 0; + id = Math.random(); + constructor() { + if (global2[kExitEmitter]) { + return global2[kExitEmitter]; + } + ObjectDefineProperty(global2, kExitEmitter, { + value: this, + writable: false, + enumerable: false, + configurable: false + }); + } + on(ev, fn) { + this.listeners[ev].push(fn); + } + removeListener(ev, fn) { + const list = this.listeners[ev]; + const i2 = list.indexOf(fn); + if (i2 === -1) { + return; + } + if (i2 === 0 && list.length === 1) { + list.length = 0; + } else { + list.splice(i2, 1); + } + } + emit(ev, code2, signal) { + if (this.emitted[ev]) { + return false; + } + this.emitted[ev] = true; + let ret = false; + for (const fn of this.listeners[ev]) { + ret = fn(code2, signal) === true || ret; + } + if (ev === "exit") { + ret = this.emit("afterExit", code2, signal) || ret; + } + return ret; + } +}; +var SignalExitBase = class { +}; +var signalExitWrap = (handler) => { + return { + onExit(cb, opts) { + return handler.onExit(cb, opts); + }, + load() { + return handler.load(); + }, + unload() { + return handler.unload(); + } + }; +}; +var SignalExitFallback = class extends SignalExitBase { + onExit() { + return () => { + }; + } + load() { + } + unload() { + } +}; +var SignalExit = class extends SignalExitBase { + // "SIGHUP" throws an `ENOSYS` error on Windows, + // so use a supported signal instead + /* c8 ignore start */ + #hupSig = process9.platform === "win32" ? "SIGINT" : "SIGHUP"; + /* c8 ignore stop */ + #emitter = new Emitter(); + #process; + #originalProcessEmit; + #originalProcessReallyExit; + #sigListeners = {}; + #loaded = false; + constructor(process10) { + super(); + this.#process = process10; + this.#sigListeners = {}; + for (const sig of signals) { + this.#sigListeners[sig] = () => { + const listeners = this.#process.listeners(sig); + let { count: count2 } = this.#emitter; + const p = process10; + if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") { + count2 += p.__signal_exit_emitter__.count; + } + if (listeners.length === count2) { + this.unload(); + const ret = this.#emitter.emit("exit", null, sig); + const s = sig === "SIGHUP" ? this.#hupSig : sig; + if (!ret) + process10.kill(process10.pid, s); + } + }; + } + this.#originalProcessReallyExit = process10.reallyExit; + this.#originalProcessEmit = process10.emit; + } + onExit(cb, opts) { + if (!processOk(this.#process)) { + return () => { + }; + } + if (this.#loaded === false) { + this.load(); + } + const ev = opts?.alwaysLast ? "afterExit" : "exit"; + this.#emitter.on(ev, cb); + return () => { + this.#emitter.removeListener(ev, cb); + if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) { + this.unload(); + } + }; + } + load() { + if (this.#loaded) { + return; + } + this.#loaded = true; + this.#emitter.count += 1; + for (const sig of signals) { + try { + const fn = this.#sigListeners[sig]; + if (fn) + this.#process.on(sig, fn); + } catch (_) { + } + } + this.#process.emit = (ev, ...a2) => { + return this.#processEmit(ev, ...a2); + }; + this.#process.reallyExit = (code2) => { + return this.#processReallyExit(code2); + }; + } + unload() { + if (!this.#loaded) { + return; + } + this.#loaded = false; + signals.forEach((sig) => { + const listener = this.#sigListeners[sig]; + if (!listener) { + throw new Error("Listener not defined for signal: " + sig); + } + try { + this.#process.removeListener(sig, listener); + } catch (_) { + } + }); + this.#process.emit = this.#originalProcessEmit; + this.#process.reallyExit = this.#originalProcessReallyExit; + this.#emitter.count -= 1; + } + #processReallyExit(code2) { + if (!processOk(this.#process)) { + return 0; + } + this.#process.exitCode = code2 || 0; + this.#emitter.emit("exit", this.#process.exitCode, null); + return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode); + } + #processEmit(ev, ...args) { + const og = this.#originalProcessEmit; + if (ev === "exit" && processOk(this.#process)) { + if (typeof args[0] === "number") { + this.#process.exitCode = args[0]; + } + const ret = og.call(this.#process, ev, ...args); + this.#emitter.emit("exit", this.#process.exitCode, null); + return ret; + } else { + return og.call(this.#process, ev, ...args); + } + } +}; +var process9 = globalThis.process; +var { + /** + * Called when the process is exiting, whether via signal, explicit + * exit, or running out of stuff to do. + * + * If the global process object is not suitable for instrumentation, + * then this will be a no-op. + * + * Returns a function that may be used to unload signal-exit. + */ + onExit, + /** + * Load the listeners. Likely you never need to call this, unless + * doing a rather deep integration with signal-exit functionality. + * Mostly exposed for the benefit of testing. + * + * @internal + */ + load, + /** + * Unload the listeners. Likely you never need to call this, unless + * doing a rather deep integration with signal-exit functionality. + * Mostly exposed for the benefit of testing. + * + * @internal + */ + unload +} = signalExitWrap(processOk(process9) ? new SignalExit(process9) : new SignalExitFallback()); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/terminate/cleanup.js +var cleanupOnExit = (subprocess, { cleanup, detached }, { signal }) => { + if (!cleanup || detached) { + return; + } + const removeExitHandler = onExit(() => { + subprocess.kill(); + }); + (0, import_node_events11.addAbortListener)(signal, () => { + removeExitHandler(); + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/pipe/pipe-arguments.js +var normalizePipeArguments = ({ source, sourcePromise, boundOptions, createNested }, ...pipeArguments) => { + const startTime = getStartTime(); + const { + destination, + destinationStream, + destinationError, + from, + unpipeSignal + } = getDestinationStream(boundOptions, createNested, pipeArguments); + const { sourceStream, sourceError } = getSourceStream(source, from); + const { options: sourceOptions, fileDescriptors } = SUBPROCESS_OPTIONS.get(source); + return { + sourcePromise, + sourceStream, + sourceOptions, + sourceError, + destination, + destinationStream, + destinationError, + unpipeSignal, + fileDescriptors, + startTime + }; +}; +var getDestinationStream = (boundOptions, createNested, pipeArguments) => { + try { + const { + destination, + pipeOptions: { from, to, unpipeSignal } = {} + } = getDestination(boundOptions, createNested, ...pipeArguments); + const destinationStream = getToStream(destination, to); + return { + destination, + destinationStream, + from, + unpipeSignal + }; + } catch (error) { + return { destinationError: error }; + } +}; +var getDestination = (boundOptions, createNested, firstArgument, ...pipeArguments) => { + if (Array.isArray(firstArgument)) { + const destination = createNested(mapDestinationArguments, boundOptions)(firstArgument, ...pipeArguments); + return { destination, pipeOptions: boundOptions }; + } + if (typeof firstArgument === "string" || firstArgument instanceof URL || isDenoExecPath(firstArgument)) { + if (Object.keys(boundOptions).length > 0) { + throw new TypeError('Please use .pipe("file", ..., options) or .pipe(execa("file", ..., options)) instead of .pipe(options)("file", ...).'); + } + const [rawFile, rawArguments, rawOptions] = normalizeParameters(firstArgument, ...pipeArguments); + const destination = createNested(mapDestinationArguments)(rawFile, rawArguments, rawOptions); + return { destination, pipeOptions: rawOptions }; + } + if (SUBPROCESS_OPTIONS.has(firstArgument)) { + if (Object.keys(boundOptions).length > 0) { + throw new TypeError("Please use .pipe(options)`command` or .pipe($(options)`command`) instead of .pipe(options)($`command`)."); + } + return { destination: firstArgument, pipeOptions: pipeArguments[0] }; + } + throw new TypeError(`The first argument must be a template string, an options object, or an Execa subprocess: ${firstArgument}`); +}; +var mapDestinationArguments = ({ options }) => ({ options: { ...options, stdin: "pipe", piped: true } }); +var getSourceStream = (source, from) => { + try { + const sourceStream = getFromStream(source, from); + return { sourceStream }; + } catch (error) { + return { sourceError: error }; + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/pipe/throw.js +var handlePipeArgumentsError = ({ + sourceStream, + sourceError, + destinationStream, + destinationError, + fileDescriptors, + sourceOptions, + startTime +}) => { + const error = getPipeArgumentsError({ + sourceStream, + sourceError, + destinationStream, + destinationError + }); + if (error !== void 0) { + throw createNonCommandError({ + error, + fileDescriptors, + sourceOptions, + startTime + }); + } +}; +var getPipeArgumentsError = ({ sourceStream, sourceError, destinationStream, destinationError }) => { + if (sourceError !== void 0 && destinationError !== void 0) { + return destinationError; + } + if (destinationError !== void 0) { + abortSourceStream(sourceStream); + return destinationError; + } + if (sourceError !== void 0) { + endDestinationStream(destinationStream); + return sourceError; + } +}; +var createNonCommandError = ({ error, fileDescriptors, sourceOptions, startTime }) => makeEarlyError({ + error, + command: PIPE_COMMAND_MESSAGE, + escapedCommand: PIPE_COMMAND_MESSAGE, + fileDescriptors, + options: sourceOptions, + startTime, + isSync: false +}); +var PIPE_COMMAND_MESSAGE = "source.pipe(destination)"; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/pipe/sequence.js +var waitForBothSubprocesses = async (subprocessPromises) => { + const [ + { status: sourceStatus, reason: sourceReason, value: sourceResult = sourceReason }, + { status: destinationStatus, reason: destinationReason, value: destinationResult = destinationReason } + ] = await subprocessPromises; + if (!destinationResult.pipedFrom.includes(sourceResult)) { + destinationResult.pipedFrom.push(sourceResult); + } + if (destinationStatus === "rejected") { + throw destinationResult; + } + if (sourceStatus === "rejected") { + throw sourceResult; + } + return destinationResult; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/pipe/streaming.js +var import_promises8 = require("stream/promises"); +var pipeSubprocessStream = (sourceStream, destinationStream, maxListenersController) => { + const mergedStream = MERGED_STREAMS.has(destinationStream) ? pipeMoreSubprocessStream(sourceStream, destinationStream) : pipeFirstSubprocessStream(sourceStream, destinationStream); + incrementMaxListeners(sourceStream, SOURCE_LISTENERS_PER_PIPE, maxListenersController.signal); + incrementMaxListeners(destinationStream, DESTINATION_LISTENERS_PER_PIPE, maxListenersController.signal); + cleanupMergedStreamsMap(destinationStream); + return mergedStream; +}; +var pipeFirstSubprocessStream = (sourceStream, destinationStream) => { + const mergedStream = mergeStreams([sourceStream]); + pipeStreams(mergedStream, destinationStream); + MERGED_STREAMS.set(destinationStream, mergedStream); + return mergedStream; +}; +var pipeMoreSubprocessStream = (sourceStream, destinationStream) => { + const mergedStream = MERGED_STREAMS.get(destinationStream); + mergedStream.add(sourceStream); + return mergedStream; +}; +var cleanupMergedStreamsMap = async (destinationStream) => { + try { + await (0, import_promises8.finished)(destinationStream, { cleanup: true, readable: false, writable: true }); + } catch { + } + MERGED_STREAMS.delete(destinationStream); +}; +var MERGED_STREAMS = /* @__PURE__ */ new WeakMap(); +var SOURCE_LISTENERS_PER_PIPE = 2; +var DESTINATION_LISTENERS_PER_PIPE = 1; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/pipe/abort.js +var import_node_util8 = require("util"); +var unpipeOnAbort = (unpipeSignal, unpipeContext) => unpipeSignal === void 0 ? [] : [unpipeOnSignalAbort(unpipeSignal, unpipeContext)]; +var unpipeOnSignalAbort = async (unpipeSignal, { sourceStream, mergedStream, fileDescriptors, sourceOptions, startTime }) => { + await (0, import_node_util8.aborted)(unpipeSignal, sourceStream); + await mergedStream.remove(sourceStream); + const error = new Error("Pipe canceled by `unpipeSignal` option."); + throw createNonCommandError({ + error, + fileDescriptors, + sourceOptions, + startTime + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/pipe/setup.js +var pipeToSubprocess = (sourceInfo, ...pipeArguments) => { + if (isPlainObject(pipeArguments[0])) { + return pipeToSubprocess.bind(void 0, { + ...sourceInfo, + boundOptions: { ...sourceInfo.boundOptions, ...pipeArguments[0] } + }); + } + const { destination, ...normalizedInfo } = normalizePipeArguments(sourceInfo, ...pipeArguments); + const promise = handlePipePromise({ ...normalizedInfo, destination }); + promise.pipe = pipeToSubprocess.bind(void 0, { + ...sourceInfo, + source: destination, + sourcePromise: promise, + boundOptions: {} + }); + return promise; +}; +var handlePipePromise = async ({ + sourcePromise, + sourceStream, + sourceOptions, + sourceError, + destination, + destinationStream, + destinationError, + unpipeSignal, + fileDescriptors, + startTime +}) => { + const subprocessPromises = getSubprocessPromises(sourcePromise, destination); + handlePipeArgumentsError({ + sourceStream, + sourceError, + destinationStream, + destinationError, + fileDescriptors, + sourceOptions, + startTime + }); + const maxListenersController = new AbortController(); + try { + const mergedStream = pipeSubprocessStream(sourceStream, destinationStream, maxListenersController); + return await Promise.race([ + waitForBothSubprocesses(subprocessPromises), + ...unpipeOnAbort(unpipeSignal, { + sourceStream, + mergedStream, + sourceOptions, + fileDescriptors, + startTime + }) + ]); + } finally { + maxListenersController.abort(); + } +}; +var getSubprocessPromises = (sourcePromise, destination) => Promise.allSettled([sourcePromise, destination]); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/contents.js +var import_promises9 = require("timers/promises"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/iterate.js +var import_node_events12 = require("events"); +var import_node_stream5 = require("stream"); +var iterateOnSubprocessStream = ({ subprocessStdout, subprocess, binary, shouldEncode, encoding, preserveNewlines }) => { + const controller = new AbortController(); + stopReadingOnExit(subprocess, controller); + return iterateOnStream({ + stream: subprocessStdout, + controller, + binary, + shouldEncode: !subprocessStdout.readableObjectMode && shouldEncode, + encoding, + shouldSplit: !subprocessStdout.readableObjectMode, + preserveNewlines + }); +}; +var stopReadingOnExit = async (subprocess, controller) => { + try { + await subprocess; + } catch { + } finally { + controller.abort(); + } +}; +var iterateForResult = ({ stream, onStreamEnd, lines, encoding, stripFinalNewline: stripFinalNewline2, allMixed }) => { + const controller = new AbortController(); + stopReadingOnStreamEnd(onStreamEnd, controller, stream); + const objectMode = stream.readableObjectMode && !allMixed; + return iterateOnStream({ + stream, + controller, + binary: encoding === "buffer", + shouldEncode: !objectMode, + encoding, + shouldSplit: !objectMode && lines, + preserveNewlines: !stripFinalNewline2 + }); +}; +var stopReadingOnStreamEnd = async (onStreamEnd, controller, stream) => { + try { + await onStreamEnd; + } catch { + stream.destroy(); + } finally { + controller.abort(); + } +}; +var iterateOnStream = ({ stream, controller, binary, shouldEncode, encoding, shouldSplit, preserveNewlines }) => { + const onStdoutChunk = (0, import_node_events12.on)(stream, "data", { + signal: controller.signal, + highWaterMark: HIGH_WATER_MARK, + // Backward compatibility with older name for this option + // See https://github.com/nodejs/node/pull/52080#discussion_r1525227861 + // @todo Remove after removing support for Node 21 + highWatermark: HIGH_WATER_MARK + }); + return iterateOnData({ + onStdoutChunk, + controller, + binary, + shouldEncode, + encoding, + shouldSplit, + preserveNewlines + }); +}; +var DEFAULT_OBJECT_HIGH_WATER_MARK = (0, import_node_stream5.getDefaultHighWaterMark)(true); +var HIGH_WATER_MARK = DEFAULT_OBJECT_HIGH_WATER_MARK; +var iterateOnData = async function* ({ onStdoutChunk, controller, binary, shouldEncode, encoding, shouldSplit, preserveNewlines }) { + const generators = getGenerators({ + binary, + shouldEncode, + encoding, + shouldSplit, + preserveNewlines + }); + try { + for await (const [chunk] of onStdoutChunk) { + yield* transformChunkSync(chunk, generators, 0); + } + } catch (error) { + if (!controller.signal.aborted) { + throw error; + } + } finally { + yield* finalChunksSync(generators); + } +}; +var getGenerators = ({ binary, shouldEncode, encoding, shouldSplit, preserveNewlines }) => [ + getEncodingTransformGenerator(binary, encoding, !shouldEncode), + getSplitLinesGenerator(binary, preserveNewlines, !shouldSplit, {}) +].filter(Boolean); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/io/contents.js +var getStreamOutput = async ({ stream, onStreamEnd, fdNumber, encoding, buffer, maxBuffer, lines, allMixed, stripFinalNewline: stripFinalNewline2, verboseInfo, streamInfo }) => { + const logPromise = logOutputAsync({ + stream, + onStreamEnd, + fdNumber, + encoding, + allMixed, + verboseInfo, + streamInfo + }); + if (!buffer) { + await Promise.all([resumeStream(stream), logPromise]); + return; + } + const stripFinalNewlineValue = getStripFinalNewline(stripFinalNewline2, fdNumber); + const iterable = iterateForResult({ + stream, + onStreamEnd, + lines, + encoding, + stripFinalNewline: stripFinalNewlineValue, + allMixed + }); + const [output] = await Promise.all([ + getStreamContents2({ + stream, + iterable, + fdNumber, + encoding, + maxBuffer, + lines + }), + logPromise + ]); + return output; +}; +var logOutputAsync = async ({ stream, onStreamEnd, fdNumber, encoding, allMixed, verboseInfo, streamInfo: { fileDescriptors } }) => { + if (!shouldLogOutput({ + stdioItems: fileDescriptors[fdNumber]?.stdioItems, + encoding, + verboseInfo, + fdNumber + })) { + return; + } + const linesIterable = iterateForResult({ + stream, + onStreamEnd, + lines: true, + encoding, + stripFinalNewline: true, + allMixed + }); + await logLines(linesIterable, stream, fdNumber, verboseInfo); +}; +var resumeStream = async (stream) => { + await (0, import_promises9.setImmediate)(); + if (stream.readableFlowing === null) { + stream.resume(); + } +}; +var getStreamContents2 = async ({ stream, stream: { readableObjectMode }, iterable, fdNumber, encoding, maxBuffer, lines }) => { + try { + if (readableObjectMode || lines) { + return await getStreamAsArray(iterable, { maxBuffer }); + } + if (encoding === "buffer") { + return new Uint8Array(await getStreamAsArrayBuffer(iterable, { maxBuffer })); + } + return await getStreamAsString(iterable, { maxBuffer }); + } catch (error) { + return handleBufferedData(handleMaxBuffer({ + error, + stream, + readableObjectMode, + lines, + encoding, + fdNumber + })); + } +}; +var getBufferedData = async (streamPromise) => { + try { + return await streamPromise; + } catch (error) { + return handleBufferedData(error); + } +}; +var handleBufferedData = ({ bufferedData }) => isArrayBuffer(bufferedData) ? new Uint8Array(bufferedData) : bufferedData; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/wait-stream.js +var import_promises10 = require("stream/promises"); +var waitForStream = async (stream, fdNumber, streamInfo, { isSameDirection, stopOnExit = false } = {}) => { + const state = handleStdinDestroy(stream, streamInfo); + const abortController = new AbortController(); + try { + await Promise.race([ + ...stopOnExit ? [streamInfo.exitPromise] : [], + (0, import_promises10.finished)(stream, { cleanup: true, signal: abortController.signal }) + ]); + } catch (error) { + if (!state.stdinCleanedUp) { + handleStreamError(error, fdNumber, streamInfo, isSameDirection); + } + } finally { + abortController.abort(); + } +}; +var handleStdinDestroy = (stream, { originalStreams: [originalStdin], subprocess }) => { + const state = { stdinCleanedUp: false }; + if (stream === originalStdin) { + spyOnStdinDestroy(stream, subprocess, state); + } + return state; +}; +var spyOnStdinDestroy = (subprocessStdin, subprocess, state) => { + const { _destroy } = subprocessStdin; + subprocessStdin._destroy = (...destroyArguments) => { + setStdinCleanedUp(subprocess, state); + _destroy.call(subprocessStdin, ...destroyArguments); + }; +}; +var setStdinCleanedUp = ({ exitCode, signalCode }, state) => { + if (exitCode !== null || signalCode !== null) { + state.stdinCleanedUp = true; + } +}; +var handleStreamError = (error, fdNumber, streamInfo, isSameDirection) => { + if (!shouldIgnoreStreamError(error, fdNumber, streamInfo, isSameDirection)) { + throw error; + } +}; +var shouldIgnoreStreamError = (error, fdNumber, streamInfo, isSameDirection = true) => { + if (streamInfo.propagating) { + return isStreamEpipe(error) || isStreamAbort(error); + } + streamInfo.propagating = true; + return isInputFileDescriptor(streamInfo, fdNumber) === isSameDirection ? isStreamEpipe(error) : isStreamAbort(error); +}; +var isInputFileDescriptor = ({ fileDescriptors }, fdNumber) => fdNumber !== "all" && fileDescriptors[fdNumber].direction === "input"; +var isStreamAbort = (error) => error?.code === "ERR_STREAM_PREMATURE_CLOSE"; +var isStreamEpipe = (error) => error?.code === "EPIPE"; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/stdio.js +var waitForStdioStreams = ({ subprocess, encoding, buffer, maxBuffer, lines, stripFinalNewline: stripFinalNewline2, verboseInfo, streamInfo }) => subprocess.stdio.map((stream, fdNumber) => waitForSubprocessStream({ + stream, + fdNumber, + encoding, + buffer: buffer[fdNumber], + maxBuffer: maxBuffer[fdNumber], + lines: lines[fdNumber], + allMixed: false, + stripFinalNewline: stripFinalNewline2, + verboseInfo, + streamInfo +})); +var waitForSubprocessStream = async ({ stream, fdNumber, encoding, buffer, maxBuffer, lines, allMixed, stripFinalNewline: stripFinalNewline2, verboseInfo, streamInfo }) => { + if (!stream) { + return; + } + const onStreamEnd = waitForStream(stream, fdNumber, streamInfo); + if (isInputFileDescriptor(streamInfo, fdNumber)) { + await onStreamEnd; + return; + } + const [output] = await Promise.all([ + getStreamOutput({ + stream, + onStreamEnd, + fdNumber, + encoding, + buffer, + maxBuffer, + lines, + allMixed, + stripFinalNewline: stripFinalNewline2, + verboseInfo, + streamInfo + }), + onStreamEnd + ]); + return output; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/all-async.js +var makeAllStream = ({ stdout, stderr }, { all }) => all && (stdout || stderr) ? mergeStreams([stdout, stderr].filter(Boolean)) : void 0; +var waitForAllStream = ({ subprocess, encoding, buffer, maxBuffer, lines, stripFinalNewline: stripFinalNewline2, verboseInfo, streamInfo }) => waitForSubprocessStream({ + ...getAllStream(subprocess, buffer), + fdNumber: "all", + encoding, + maxBuffer: maxBuffer[1] + maxBuffer[2], + lines: lines[1] || lines[2], + allMixed: getAllMixed(subprocess), + stripFinalNewline: stripFinalNewline2, + verboseInfo, + streamInfo +}); +var getAllStream = ({ stdout, stderr, all }, [, bufferStdout, bufferStderr]) => { + const buffer = bufferStdout || bufferStderr; + if (!buffer) { + return { stream: all, buffer }; + } + if (!bufferStdout) { + return { stream: stderr, buffer }; + } + if (!bufferStderr) { + return { stream: stdout, buffer }; + } + return { stream: all, buffer }; +}; +var getAllMixed = ({ all, stdout, stderr }) => all && stdout && stderr && stdout.readableObjectMode !== stderr.readableObjectMode; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/wait-subprocess.js +var import_node_events13 = require("events"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/ipc.js +var shouldLogIpc = (verboseInfo) => isFullVerbose(verboseInfo, "ipc"); +var logIpcOutput = (message, verboseInfo) => { + const verboseMessage = serializeVerboseMessage(message); + verboseLog({ + type: "ipc", + verboseMessage, + fdNumber: "ipc", + verboseInfo + }); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/ipc/buffer-messages.js +var waitForIpcOutput = async ({ + subprocess, + buffer: bufferArray, + maxBuffer: maxBufferArray, + ipc, + ipcOutput, + verboseInfo +}) => { + if (!ipc) { + return ipcOutput; + } + const isVerbose2 = shouldLogIpc(verboseInfo); + const buffer = getFdSpecificValue(bufferArray, "ipc"); + const maxBuffer = getFdSpecificValue(maxBufferArray, "ipc"); + for await (const message of loopOnMessages({ + anyProcess: subprocess, + channel: subprocess.channel, + isSubprocess: false, + ipc, + shouldAwait: false, + reference: true + })) { + if (buffer) { + checkIpcMaxBuffer(subprocess, ipcOutput, maxBuffer); + ipcOutput.push(message); + } + if (isVerbose2) { + logIpcOutput(message, verboseInfo); + } + } + return ipcOutput; +}; +var getBufferedIpcOutput = async (ipcOutputPromise, ipcOutput) => { + await Promise.allSettled([ipcOutputPromise]); + return ipcOutput; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/resolve/wait-subprocess.js +var waitForSubprocessResult = async ({ + subprocess, + options: { + encoding, + buffer, + maxBuffer, + lines, + timeoutDuration: timeout, + cancelSignal, + gracefulCancel, + forceKillAfterDelay, + stripFinalNewline: stripFinalNewline2, + ipc, + ipcInput + }, + context, + verboseInfo, + fileDescriptors, + originalStreams, + onInternalError, + controller +}) => { + const exitPromise = waitForExit(subprocess, context); + const streamInfo = { + originalStreams, + fileDescriptors, + subprocess, + exitPromise, + propagating: false + }; + const stdioPromises = waitForStdioStreams({ + subprocess, + encoding, + buffer, + maxBuffer, + lines, + stripFinalNewline: stripFinalNewline2, + verboseInfo, + streamInfo + }); + const allPromise = waitForAllStream({ + subprocess, + encoding, + buffer, + maxBuffer, + lines, + stripFinalNewline: stripFinalNewline2, + verboseInfo, + streamInfo + }); + const ipcOutput = []; + const ipcOutputPromise = waitForIpcOutput({ + subprocess, + buffer, + maxBuffer, + ipc, + ipcOutput, + verboseInfo + }); + const originalPromises = waitForOriginalStreams(originalStreams, subprocess, streamInfo); + const customStreamsEndPromises = waitForCustomStreamsEnd(fileDescriptors, streamInfo); + try { + return await Promise.race([ + Promise.all([ + {}, + waitForSuccessfulExit(exitPromise), + Promise.all(stdioPromises), + allPromise, + ipcOutputPromise, + sendIpcInput(subprocess, ipcInput), + ...originalPromises, + ...customStreamsEndPromises + ]), + onInternalError, + throwOnSubprocessError(subprocess, controller), + ...throwOnTimeout(subprocess, timeout, context, controller), + ...throwOnCancel({ + subprocess, + cancelSignal, + gracefulCancel, + context, + controller + }), + ...throwOnGracefulCancel({ + subprocess, + cancelSignal, + gracefulCancel, + forceKillAfterDelay, + context, + controller + }) + ]); + } catch (error) { + context.terminationReason ??= "other"; + return Promise.all([ + { error }, + exitPromise, + Promise.all(stdioPromises.map((stdioPromise) => getBufferedData(stdioPromise))), + getBufferedData(allPromise), + getBufferedIpcOutput(ipcOutputPromise, ipcOutput), + Promise.allSettled(originalPromises), + Promise.allSettled(customStreamsEndPromises) + ]); + } +}; +var waitForOriginalStreams = (originalStreams, subprocess, streamInfo) => originalStreams.map((stream, fdNumber) => stream === subprocess.stdio[fdNumber] ? void 0 : waitForStream(stream, fdNumber, streamInfo)); +var waitForCustomStreamsEnd = (fileDescriptors, streamInfo) => fileDescriptors.flatMap(({ stdioItems }, fdNumber) => stdioItems.filter(({ value, stream = value }) => isStream(stream, { checkOpen: false }) && !isStandardStream(stream)).map(({ type, value, stream = value }) => waitForStream(stream, fdNumber, streamInfo, { + isSameDirection: TRANSFORM_TYPES.has(type), + stopOnExit: type === "native" +}))); +var throwOnSubprocessError = async (subprocess, { signal }) => { + const [error] = await (0, import_node_events13.once)(subprocess, "error", { signal }); + throw error; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/concurrent.js +var initializeConcurrentStreams = () => ({ + readableDestroy: /* @__PURE__ */ new WeakMap(), + writableFinal: /* @__PURE__ */ new WeakMap(), + writableDestroy: /* @__PURE__ */ new WeakMap() +}); +var addConcurrentStream = (concurrentStreams, stream, waitName) => { + const weakMap = concurrentStreams[waitName]; + if (!weakMap.has(stream)) { + weakMap.set(stream, []); + } + const promises = weakMap.get(stream); + const promise = createDeferred(); + promises.push(promise); + const resolve = promise.resolve.bind(promise); + return { resolve, promises }; +}; +var waitForConcurrentStreams = async ({ resolve, promises }, subprocess) => { + resolve(); + const [isSubprocessExit] = await Promise.race([ + Promise.allSettled([true, subprocess]), + Promise.all([false, ...promises]) + ]); + return !isSubprocessExit; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/readable.js +var import_node_stream6 = require("stream"); +var import_node_util9 = require("util"); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/shared.js +var import_promises11 = require("stream/promises"); +var safeWaitForSubprocessStdin = async (subprocessStdin) => { + if (subprocessStdin === void 0) { + return; + } + try { + await waitForSubprocessStdin(subprocessStdin); + } catch { + } +}; +var safeWaitForSubprocessStdout = async (subprocessStdout) => { + if (subprocessStdout === void 0) { + return; + } + try { + await waitForSubprocessStdout(subprocessStdout); + } catch { + } +}; +var waitForSubprocessStdin = async (subprocessStdin) => { + await (0, import_promises11.finished)(subprocessStdin, { cleanup: true, readable: false, writable: true }); +}; +var waitForSubprocessStdout = async (subprocessStdout) => { + await (0, import_promises11.finished)(subprocessStdout, { cleanup: true, readable: true, writable: false }); +}; +var waitForSubprocess = async (subprocess, error) => { + await subprocess; + if (error) { + throw error; + } +}; +var destroyOtherStream = (stream, isOpen, error) => { + if (error && !isStreamAbort(error)) { + stream.destroy(error); + } else if (isOpen) { + stream.destroy(); + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/readable.js +var createReadable = ({ subprocess, concurrentStreams, encoding }, { from, binary: binaryOption = true, preserveNewlines = true } = {}) => { + const binary = binaryOption || BINARY_ENCODINGS.has(encoding); + const { subprocessStdout, waitReadableDestroy } = getSubprocessStdout(subprocess, from, concurrentStreams); + const { readableEncoding, readableObjectMode, readableHighWaterMark } = getReadableOptions(subprocessStdout, binary); + const { read, onStdoutDataDone } = getReadableMethods({ + subprocessStdout, + subprocess, + binary, + encoding, + preserveNewlines + }); + const readable2 = new import_node_stream6.Readable({ + read, + destroy: (0, import_node_util9.callbackify)(onReadableDestroy.bind(void 0, { subprocessStdout, subprocess, waitReadableDestroy })), + highWaterMark: readableHighWaterMark, + objectMode: readableObjectMode, + encoding: readableEncoding + }); + onStdoutFinished({ + subprocessStdout, + onStdoutDataDone, + readable: readable2, + subprocess + }); + return readable2; +}; +var getSubprocessStdout = (subprocess, from, concurrentStreams) => { + const subprocessStdout = getFromStream(subprocess, from); + const waitReadableDestroy = addConcurrentStream(concurrentStreams, subprocessStdout, "readableDestroy"); + return { subprocessStdout, waitReadableDestroy }; +}; +var getReadableOptions = ({ readableEncoding, readableObjectMode, readableHighWaterMark }, binary) => binary ? { readableEncoding, readableObjectMode, readableHighWaterMark } : { readableEncoding, readableObjectMode: true, readableHighWaterMark: DEFAULT_OBJECT_HIGH_WATER_MARK }; +var getReadableMethods = ({ subprocessStdout, subprocess, binary, encoding, preserveNewlines }) => { + const onStdoutDataDone = createDeferred(); + const onStdoutData = iterateOnSubprocessStream({ + subprocessStdout, + subprocess, + binary, + shouldEncode: !binary, + encoding, + preserveNewlines + }); + return { + read() { + onRead(this, onStdoutData, onStdoutDataDone); + }, + onStdoutDataDone + }; +}; +var onRead = async (readable2, onStdoutData, onStdoutDataDone) => { + try { + const { value, done } = await onStdoutData.next(); + if (done) { + onStdoutDataDone.resolve(); + } else { + readable2.push(value); + } + } catch { + } +}; +var onStdoutFinished = async ({ subprocessStdout, onStdoutDataDone, readable: readable2, subprocess, subprocessStdin }) => { + try { + await waitForSubprocessStdout(subprocessStdout); + await subprocess; + await safeWaitForSubprocessStdin(subprocessStdin); + await onStdoutDataDone; + if (readable2.readable) { + readable2.push(null); + } + } catch (error) { + await safeWaitForSubprocessStdin(subprocessStdin); + destroyOtherReadable(readable2, error); + } +}; +var onReadableDestroy = async ({ subprocessStdout, subprocess, waitReadableDestroy }, error) => { + if (await waitForConcurrentStreams(waitReadableDestroy, subprocess)) { + destroyOtherReadable(subprocessStdout, error); + await waitForSubprocess(subprocess, error); + } +}; +var destroyOtherReadable = (stream, error) => { + destroyOtherStream(stream, stream.readable, error); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/writable.js +var import_node_stream7 = require("stream"); +var import_node_util10 = require("util"); +var createWritable = ({ subprocess, concurrentStreams }, { to } = {}) => { + const { subprocessStdin, waitWritableFinal, waitWritableDestroy } = getSubprocessStdin(subprocess, to, concurrentStreams); + const writable2 = new import_node_stream7.Writable({ + ...getWritableMethods(subprocessStdin, subprocess, waitWritableFinal), + destroy: (0, import_node_util10.callbackify)(onWritableDestroy.bind(void 0, { + subprocessStdin, + subprocess, + waitWritableFinal, + waitWritableDestroy + })), + highWaterMark: subprocessStdin.writableHighWaterMark, + objectMode: subprocessStdin.writableObjectMode + }); + onStdinFinished(subprocessStdin, writable2); + return writable2; +}; +var getSubprocessStdin = (subprocess, to, concurrentStreams) => { + const subprocessStdin = getToStream(subprocess, to); + const waitWritableFinal = addConcurrentStream(concurrentStreams, subprocessStdin, "writableFinal"); + const waitWritableDestroy = addConcurrentStream(concurrentStreams, subprocessStdin, "writableDestroy"); + return { subprocessStdin, waitWritableFinal, waitWritableDestroy }; +}; +var getWritableMethods = (subprocessStdin, subprocess, waitWritableFinal) => ({ + write: onWrite.bind(void 0, subprocessStdin), + final: (0, import_node_util10.callbackify)(onWritableFinal.bind(void 0, subprocessStdin, subprocess, waitWritableFinal)) +}); +var onWrite = (subprocessStdin, chunk, encoding, done) => { + if (subprocessStdin.write(chunk, encoding)) { + done(); + } else { + subprocessStdin.once("drain", done); + } +}; +var onWritableFinal = async (subprocessStdin, subprocess, waitWritableFinal) => { + if (await waitForConcurrentStreams(waitWritableFinal, subprocess)) { + if (subprocessStdin.writable) { + subprocessStdin.end(); + } + await subprocess; + } +}; +var onStdinFinished = async (subprocessStdin, writable2, subprocessStdout) => { + try { + await waitForSubprocessStdin(subprocessStdin); + if (writable2.writable) { + writable2.end(); + } + } catch (error) { + await safeWaitForSubprocessStdout(subprocessStdout); + destroyOtherWritable(writable2, error); + } +}; +var onWritableDestroy = async ({ subprocessStdin, subprocess, waitWritableFinal, waitWritableDestroy }, error) => { + await waitForConcurrentStreams(waitWritableFinal, subprocess); + if (await waitForConcurrentStreams(waitWritableDestroy, subprocess)) { + destroyOtherWritable(subprocessStdin, error); + await waitForSubprocess(subprocess, error); + } +}; +var destroyOtherWritable = (stream, error) => { + destroyOtherStream(stream, stream.writable, error); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/duplex.js +var import_node_stream8 = require("stream"); +var import_node_util11 = require("util"); +var createDuplex = ({ subprocess, concurrentStreams, encoding }, { from, to, binary: binaryOption = true, preserveNewlines = true } = {}) => { + const binary = binaryOption || BINARY_ENCODINGS.has(encoding); + const { subprocessStdout, waitReadableDestroy } = getSubprocessStdout(subprocess, from, concurrentStreams); + const { subprocessStdin, waitWritableFinal, waitWritableDestroy } = getSubprocessStdin(subprocess, to, concurrentStreams); + const { readableEncoding, readableObjectMode, readableHighWaterMark } = getReadableOptions(subprocessStdout, binary); + const { read, onStdoutDataDone } = getReadableMethods({ + subprocessStdout, + subprocess, + binary, + encoding, + preserveNewlines + }); + const duplex2 = new import_node_stream8.Duplex({ + read, + ...getWritableMethods(subprocessStdin, subprocess, waitWritableFinal), + destroy: (0, import_node_util11.callbackify)(onDuplexDestroy.bind(void 0, { + subprocessStdout, + subprocessStdin, + subprocess, + waitReadableDestroy, + waitWritableFinal, + waitWritableDestroy + })), + readableHighWaterMark, + writableHighWaterMark: subprocessStdin.writableHighWaterMark, + readableObjectMode, + writableObjectMode: subprocessStdin.writableObjectMode, + encoding: readableEncoding + }); + onStdoutFinished({ + subprocessStdout, + onStdoutDataDone, + readable: duplex2, + subprocess, + subprocessStdin + }); + onStdinFinished(subprocessStdin, duplex2, subprocessStdout); + return duplex2; +}; +var onDuplexDestroy = async ({ subprocessStdout, subprocessStdin, subprocess, waitReadableDestroy, waitWritableFinal, waitWritableDestroy }, error) => { + await Promise.all([ + onReadableDestroy({ subprocessStdout, subprocess, waitReadableDestroy }, error), + onWritableDestroy({ + subprocessStdin, + subprocess, + waitWritableFinal, + waitWritableDestroy + }, error) + ]); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/iterable.js +var createIterable = (subprocess, encoding, { + from, + binary: binaryOption = false, + preserveNewlines = false +} = {}) => { + const binary = binaryOption || BINARY_ENCODINGS.has(encoding); + const subprocessStdout = getFromStream(subprocess, from); + const onStdoutData = iterateOnSubprocessStream({ + subprocessStdout, + subprocess, + binary, + shouldEncode: true, + encoding, + preserveNewlines + }); + return iterateOnStdoutData(onStdoutData, subprocessStdout, subprocess); +}; +var iterateOnStdoutData = async function* (onStdoutData, subprocessStdout, subprocess) { + try { + yield* onStdoutData; + } finally { + if (subprocessStdout.readable) { + subprocessStdout.destroy(); + } + await subprocess; + } +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/convert/add.js +var addConvertedStreams = (subprocess, { encoding }) => { + const concurrentStreams = initializeConcurrentStreams(); + subprocess.readable = createReadable.bind(void 0, { subprocess, concurrentStreams, encoding }); + subprocess.writable = createWritable.bind(void 0, { subprocess, concurrentStreams }); + subprocess.duplex = createDuplex.bind(void 0, { subprocess, concurrentStreams, encoding }); + subprocess.iterable = createIterable.bind(void 0, subprocess, encoding); + subprocess[Symbol.asyncIterator] = createIterable.bind(void 0, subprocess, encoding, {}); +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/promise.js +var mergePromise = (subprocess, promise) => { + for (const [property, descriptor] of descriptors) { + const value = descriptor.value.bind(promise); + Reflect.defineProperty(subprocess, property, { ...descriptor, value }); + } +}; +var nativePromisePrototype = (async () => { +})().constructor.prototype; +var descriptors = ["then", "catch", "finally"].map((property) => [ + property, + Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property) +]); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/main-async.js +var execaCoreAsync = (rawFile, rawArguments, rawOptions, createNested) => { + const { file, commandArguments, command, escapedCommand, startTime, verboseInfo, options, fileDescriptors } = handleAsyncArguments(rawFile, rawArguments, rawOptions); + const { subprocess, promise } = spawnSubprocessAsync({ + file, + commandArguments, + options, + startTime, + verboseInfo, + command, + escapedCommand, + fileDescriptors + }); + subprocess.pipe = pipeToSubprocess.bind(void 0, { + source: subprocess, + sourcePromise: promise, + boundOptions: {}, + createNested + }); + mergePromise(subprocess, promise); + SUBPROCESS_OPTIONS.set(subprocess, { options, fileDescriptors }); + return subprocess; +}; +var handleAsyncArguments = (rawFile, rawArguments, rawOptions) => { + const { command, escapedCommand, startTime, verboseInfo } = handleCommand(rawFile, rawArguments, rawOptions); + const { file, commandArguments, options: normalizedOptions } = normalizeOptions(rawFile, rawArguments, rawOptions); + const options = handleAsyncOptions(normalizedOptions); + const fileDescriptors = handleStdioAsync(options, verboseInfo); + return { + file, + commandArguments, + command, + escapedCommand, + startTime, + verboseInfo, + options, + fileDescriptors + }; +}; +var handleAsyncOptions = ({ timeout, signal, ...options }) => { + if (signal !== void 0) { + throw new TypeError('The "signal" option has been renamed to "cancelSignal" instead.'); + } + return { ...options, timeoutDuration: timeout }; +}; +var spawnSubprocessAsync = ({ file, commandArguments, options, startTime, verboseInfo, command, escapedCommand, fileDescriptors }) => { + let subprocess; + try { + subprocess = (0, import_node_child_process5.spawn)(...concatenateShell(file, commandArguments, options)); + } catch (error) { + return handleEarlyError({ + error, + command, + escapedCommand, + fileDescriptors, + options, + startTime, + verboseInfo + }); + } + const controller = new AbortController(); + (0, import_node_events14.setMaxListeners)(Number.POSITIVE_INFINITY, controller.signal); + const originalStreams = [...subprocess.stdio]; + pipeOutputAsync(subprocess, fileDescriptors, controller); + cleanupOnExit(subprocess, options, controller); + const context = {}; + const onInternalError = createDeferred(); + subprocess.kill = subprocessKill.bind(void 0, { + kill: subprocess.kill.bind(subprocess), + options, + onInternalError, + context, + controller + }); + subprocess.all = makeAllStream(subprocess, options); + addConvertedStreams(subprocess, options); + addIpcMethods(subprocess, options); + const promise = handlePromise({ + subprocess, + options, + startTime, + verboseInfo, + fileDescriptors, + originalStreams, + command, + escapedCommand, + context, + onInternalError, + controller + }); + return { subprocess, promise }; +}; +var handlePromise = async ({ subprocess, options, startTime, verboseInfo, fileDescriptors, originalStreams, command, escapedCommand, context, onInternalError, controller }) => { + const [ + errorInfo, + [exitCode, signal], + stdioResults, + allResult, + ipcOutput + ] = await waitForSubprocessResult({ + subprocess, + options, + context, + verboseInfo, + fileDescriptors, + originalStreams, + onInternalError, + controller + }); + controller.abort(); + onInternalError.resolve(); + const stdio = stdioResults.map((stdioResult, fdNumber) => stripNewline(stdioResult, options, fdNumber)); + const all = stripNewline(allResult, options, "all"); + const result = getAsyncResult({ + errorInfo, + exitCode, + signal, + stdio, + all, + ipcOutput, + context, + options, + command, + escapedCommand, + startTime + }); + return handleResult2(result, verboseInfo, options); +}; +var getAsyncResult = ({ errorInfo, exitCode, signal, stdio, all, ipcOutput, context, options, command, escapedCommand, startTime }) => "error" in errorInfo ? makeError({ + error: errorInfo.error, + command, + escapedCommand, + timedOut: context.terminationReason === "timeout", + isCanceled: context.terminationReason === "cancel" || context.terminationReason === "gracefulCancel", + isGracefullyCanceled: context.terminationReason === "gracefulCancel", + isMaxBuffer: errorInfo.error instanceof MaxBufferError, + isForcefullyTerminated: context.isForcefullyTerminated, + exitCode, + signal, + stdio, + all, + ipcOutput, + options, + startTime, + isSync: false +}) : makeSuccessResult({ + command, + escapedCommand, + stdio, + all, + ipcOutput, + options, + startTime +}); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/bind.js +var mergeOptions = (boundOptions, options) => { + const newOptions = Object.fromEntries( + Object.entries(options).map(([optionName, optionValue]) => [ + optionName, + mergeOption(optionName, boundOptions[optionName], optionValue) + ]) + ); + return { ...boundOptions, ...newOptions }; +}; +var mergeOption = (optionName, boundOptionValue, optionValue) => { + if (DEEP_OPTIONS.has(optionName) && isPlainObject(boundOptionValue) && isPlainObject(optionValue)) { + return { ...boundOptionValue, ...optionValue }; + } + return optionValue; +}; +var DEEP_OPTIONS = /* @__PURE__ */ new Set(["env", ...FD_SPECIFIC_OPTIONS]); + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/create.js +var createExeca = (mapArguments, boundOptions, deepOptions, setBoundExeca) => { + const createNested = (mapArguments2, boundOptions2, setBoundExeca2) => createExeca(mapArguments2, boundOptions2, deepOptions, setBoundExeca2); + const boundExeca = (...execaArguments) => callBoundExeca({ + mapArguments, + deepOptions, + boundOptions, + setBoundExeca, + createNested + }, ...execaArguments); + if (setBoundExeca !== void 0) { + setBoundExeca(boundExeca, createNested, boundOptions); + } + return boundExeca; +}; +var callBoundExeca = ({ mapArguments, deepOptions = {}, boundOptions = {}, setBoundExeca, createNested }, firstArgument, ...nextArguments) => { + if (isPlainObject(firstArgument)) { + return createNested(mapArguments, mergeOptions(boundOptions, firstArgument), setBoundExeca); + } + const { file, commandArguments, options, isSync } = parseArguments({ + mapArguments, + firstArgument, + nextArguments, + deepOptions, + boundOptions + }); + return isSync ? execaCoreSync(file, commandArguments, options) : execaCoreAsync(file, commandArguments, options, createNested); +}; +var parseArguments = ({ mapArguments, firstArgument, nextArguments, deepOptions, boundOptions }) => { + const callArguments = isTemplateString(firstArgument) ? parseTemplates(firstArgument, nextArguments) : [firstArgument, ...nextArguments]; + const [initialFile, initialArguments, initialOptions] = normalizeParameters(...callArguments); + const mergedOptions = mergeOptions(mergeOptions(deepOptions, boundOptions), initialOptions); + const { + file = initialFile, + commandArguments = initialArguments, + options = mergedOptions, + isSync = false + } = mapArguments({ file: initialFile, commandArguments: initialArguments, options: mergedOptions }); + return { + file, + commandArguments, + options, + isSync + }; +}; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/command.js +var mapCommandAsync = ({ file, commandArguments }) => parseCommand(file, commandArguments); +var mapCommandSync = ({ file, commandArguments }) => ({ ...parseCommand(file, commandArguments), isSync: true }); +var parseCommand = (command, unusedArguments) => { + if (unusedArguments.length > 0) { + throw new TypeError(`The command and its arguments must be passed as a single string: ${command} ${unusedArguments}.`); + } + const [file, ...commandArguments] = parseCommandString(command); + return { file, commandArguments }; +}; +var parseCommandString = (command) => { + if (typeof command !== "string") { + throw new TypeError(`The command must be a string: ${String(command)}.`); + } + const trimmedCommand = command.trim(); + if (trimmedCommand === "") { + return []; + } + const tokens = []; + for (const token of trimmedCommand.split(SPACES_REGEXP)) { + const previousToken = tokens.at(-1); + if (previousToken && previousToken.endsWith("\\")) { + tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`; + } else { + tokens.push(token); + } + } + return tokens; +}; +var SPACES_REGEXP = / +/g; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/script.js +var setScriptSync = (boundExeca, createNested, boundOptions) => { + boundExeca.sync = createNested(mapScriptSync, boundOptions); + boundExeca.s = boundExeca.sync; +}; +var mapScriptAsync = ({ options }) => getScriptOptions(options); +var mapScriptSync = ({ options }) => ({ ...getScriptOptions(options), isSync: true }); +var getScriptOptions = (options) => ({ options: { ...getScriptStdinOption(options), ...options } }); +var getScriptStdinOption = ({ input, inputFile, stdio }) => input === void 0 && inputFile === void 0 && stdio === void 0 ? { stdin: "inherit" } : {}; +var deepScriptOptions = { preferLocal: true }; + +// ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/index.js +var execa = createExeca(() => ({})); +var execaSync = createExeca(() => ({ isSync: true })); +var execaCommand = createExeca(mapCommandAsync); +var execaCommandSync = createExeca(mapCommandSync); +var execaNode = createExeca(mapNode); +var $ = createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync); +var { + sendMessage: sendMessage2, + getOneMessage: getOneMessage2, + getEachMessage: getEachMessage2, + getCancelSignal: getCancelSignal2 +} = getIpcExport(); + +// ../../packages/drift/dist/index.js +var import_fs10 = require("fs"); +var import_path9 = __toESM(require("path"), 1); +var import_picomatch = __toESM(require_picomatch2(), 1); +var import_fs11 = require("fs"); +var import_path10 = __toESM(require("path"), 1); + +// ../../packages/runners/dist/index.js +var import_buffer = require("buffer"); +var import_fs5 = require("fs"); +var import_path4 = __toESM(require("path"), 1); +var DEFAULT_MAX_STDOUT_BYTES = 10 * 1024 * 1024; +var DEFAULT_MAX_STDERR_BYTES = 1024 * 1024; +function assertSafeToken(value, what) { + if (value.length === 0) { + throw new SpecBridgeError("INVALID_ARGUMENT", `${what} must not be empty.`); + } + if (value.includes("\0")) { + throw new SpecBridgeError("INVALID_ARGUMENT", `${what} must not contain null bytes.`); + } +} +function redactArgv(argv, redactValues = []) { + if (redactValues.length === 0) return [...argv]; + return argv.map((argument) => redactValues.includes(argument) ? "" : argument); +} +function isExecutableFile(candidate) { + try { + return (0, import_fs5.statSync)(candidate).isFile(); + } catch { + return false; + } +} +function resolveExecutable(command, cwd) { + if (command.includes("/") || command.includes("\\")) { + const resolved = import_path4.default.resolve(cwd, command); + return isExecutableFile(resolved) ? resolved : void 0; + } + const pathValue = process.env["PATH"] ?? process.env["Path"] ?? ""; + const extensions = process.platform === "win32" ? ["", ...(process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD").split(";")] : [""]; + for (const dir of pathValue.split(import_path4.default.delimiter)) { + if (dir.length === 0) continue; + for (const extension of extensions) { + const candidate = import_path4.default.join(dir, command + extension); + if (isExecutableFile(candidate)) return candidate; + } + } + return void 0; +} +async function runSafeProcess(request) { + assertSafeToken(request.executable, "executable"); + for (const argument of request.argv) { + if (argument.includes("\0")) { + throw new SpecBridgeError("INVALID_ARGUMENT", "argv must not contain null bytes."); + } + } + const maxStdout = request.maxStdoutBytes ?? DEFAULT_MAX_STDOUT_BYTES; + const maxStderr = request.maxStderrBytes ?? DEFAULT_MAX_STDERR_BYTES; + const startedAt = /* @__PURE__ */ new Date(); + if (resolveExecutable(request.executable, request.cwd) === void 0) { + const endedAt2 = /* @__PURE__ */ new Date(); + return { + status: "spawn-failed", + stdout: "", + stderr: "", + failureReason: `could not start "${request.executable}": executable not found on PATH`, + observation: { + executable: request.executable, + redactedArgv: redactArgv(request.argv, request.redactValues), + startedAt: startedAt.toISOString(), + endedAt: endedAt2.toISOString(), + durationMs: 0, + exitCode: void 0, + signal: void 0, + timedOut: false, + cancelled: false, + stdoutBytes: 0, + stderrBytes: 0, + stdoutTruncated: false, + stderrTruncated: false + } + }; + } + const result = await execa(request.executable, request.argv, { + cwd: request.cwd, + timeout: request.timeoutMs, + ...request.signal !== void 0 ? { cancelSignal: request.signal } : {}, + forceKillAfterDelay: request.forceKillAfterMs ?? 2e3, + maxBuffer: { stdout: maxStdout, stderr: maxStderr }, + reject: false, + stripFinalNewline: false, + ...request.stdin !== void 0 ? { input: request.stdin } : { stdin: "ignore" }, + // Environment: inherited from the parent process on purpose (the local + // agent CLI needs its own auth environment). It is never logged. + windowsHide: true + }); + const endedAt = /* @__PURE__ */ new Date(); + const stdout = typeof result.stdout === "string" ? result.stdout : ""; + const stderr = typeof result.stderr === "string" ? result.stderr : ""; + const spawnFailed = result.exitCode === void 0 && !result.timedOut && !result.isCanceled; + const stdoutTruncated = import_buffer.Buffer.byteLength(stdout, "utf8") >= maxStdout; + const stderrTruncated = import_buffer.Buffer.byteLength(stderr, "utf8") >= maxStderr; + const isMaxBuffer = "isMaxBuffer" in result && result.isMaxBuffer === true || stdoutTruncated || stderrTruncated; + let status; + let failureReason; + if (result.timedOut) { + status = "timeout"; + failureReason = `process exceeded the ${request.timeoutMs} ms timeout and was terminated`; + } else if (result.isCanceled) { + status = "cancelled"; + failureReason = "process was cancelled and terminated"; + } else if (isMaxBuffer) { + status = "output-limit"; + failureReason = `process output exceeded the configured limit (stdout ${maxStdout} bytes, stderr ${maxStderr} bytes) and was terminated; the truncated output was retained but will not be parsed`; + } else if (spawnFailed && result.isTerminated !== true) { + status = "spawn-failed"; + const original = "originalMessage" in result && typeof result.originalMessage === "string" ? result.originalMessage : result.shortMessage ?? "unknown spawn failure"; + failureReason = `could not start "${request.executable}": ${original}`; + } else if (result.exitCode === 0) { + status = "ok"; + } else { + status = "nonzero-exit"; + failureReason = result.exitCode !== void 0 ? `process exited with code ${result.exitCode}` : `process was terminated by signal ${result.signal ?? "unknown"}`; + } + return { + status, + stdout, + stderr, + ...failureReason !== void 0 ? { failureReason } : {}, + observation: { + executable: request.executable, + redactedArgv: redactArgv(request.argv, request.redactValues), + startedAt: startedAt.toISOString(), + endedAt: endedAt.toISOString(), + durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime()), + exitCode: result.exitCode, + signal: typeof result.signal === "string" ? result.signal : void 0, + timedOut: result.timedOut === true, + cancelled: result.isCanceled === true, + stdoutBytes: import_buffer.Buffer.byteLength(stdout, "utf8"), + stderrBytes: import_buffer.Buffer.byteLength(stderr, "utf8"), + stdoutTruncated, + stderrTruncated + } + }; +} +var claudeEnvelopeSchema = external_exports.object({ + type: external_exports.string().optional(), + subtype: external_exports.string().optional(), + is_error: external_exports.boolean().optional(), + result: external_exports.string().optional(), + session_id: external_exports.string().optional(), + structured_result: external_exports.unknown().optional(), + permission_denials: external_exports.array(external_exports.unknown()).optional() +}).passthrough(); + +// ../../packages/drift/dist/index.js +var import_fs12 = require("fs"); +var import_path11 = __toESM(require("path"), 1); + +// ../../packages/compat-kiro/dist/index.js +var import_fs6 = require("fs"); +var import_yaml = __toESM(require_dist(), 1); +var import_fs7 = require("fs"); +var import_path5 = __toESM(require("path"), 1); +var import_fs8 = require("fs"); +var BOM = "\uFEFF"; +function splitLines(text) { + const lines = []; + let start = 0; + let i2 = 0; + while (i2 < text.length) { + const code2 = text.charCodeAt(i2); + if (code2 === 10) { + lines.push({ text: text.slice(start, i2), eol: "\n" }); + i2 += 1; + start = i2; + } else if (code2 === 13) { + const eol = text.charCodeAt(i2 + 1) === 10 ? "\r\n" : "\r"; + lines.push({ text: text.slice(start, i2), eol }); + i2 += eol.length; + start = i2; + } else { + i2 += 1; + } + } + if (start < text.length) { + lines.push({ text: text.slice(start), eol: "" }); + } + return lines; +} +var FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})(.*)$/; +var HEADING = /^ {0,3}(#{1,6})(?:$|[ \t]+(.*))$/; +var MarkdownDocument = class _MarkdownDocument { + filePath; + hasBom; + /** + * True when decoding the source bytes as UTF-8 and re-encoding reproduces + * them exactly. False means the file is not valid UTF-8 and MUST NOT be + * edited through this model (reading is still fine). + */ + encodingSafe; + documentLines; + constructor(lines, hasBom, encodingSafe, filePath) { + this.documentLines = lines; + this.hasBom = hasBom; + this.encodingSafe = encodingSafe; + this.filePath = filePath; + } + static fromText(text, filePath) { + return _MarkdownDocument.create(text, true, filePath); + } + static fromBuffer(buffer, filePath) { + const text = buffer.toString("utf8"); + const encodingSafe = Buffer.from(text, "utf8").equals(buffer); + return _MarkdownDocument.create(text, encodingSafe, filePath); + } + static load(filePath) { + let buffer; + try { + buffer = (0, import_fs6.readFileSync)(filePath); + } catch (cause) { + throw ioError("read", filePath, cause); + } + return _MarkdownDocument.fromBuffer(buffer, filePath); + } + static create(text, encodingSafe, filePath) { + const hasBom = text.startsWith(BOM); + const body = hasBom ? text.slice(1) : text; + return new _MarkdownDocument(splitLines(body), hasBom, encodingSafe, filePath); + } + get lineCount() { + return this.documentLines.length; + } + get lines() { + return this.documentLines; + } + lineAt(index) { + const line = this.documentLines[index]; + if (line === void 0) { + throw new SpecBridgeError( + "INVALID_ARGUMENT", + `Line index ${index} is out of range (document has ${this.documentLines.length} lines).` + ); + } + return line; + } + /** Replace the text of one line. The line ending is preserved untouched. */ + setLineText(index, text) { + if (text.includes("\n") || text.includes("\r")) { + throw new SpecBridgeError( + "INVALID_ARGUMENT", + "setLineText received text containing a line break; surgical edits must stay on one line." + ); + } + const line = this.lineAt(index); + line.text = text; + } + /** Reconstruct the exact document text (including BOM when present). */ + serialize() { + let out = this.hasBom ? BOM : ""; + for (const line of this.documentLines) { + out += line.text + line.eol; + } + return out; + } + toBuffer() { + return Buffer.from(this.serialize(), "utf8"); + } + /** + * Per-line mask marking lines that are part of a fenced code block + * (including the fence markers themselves). Heading and checkbox detection + * must ignore masked lines. + */ + codeFenceMask() { + const mask = new Array(this.documentLines.length).fill(false); + let open = null; + for (let i2 = 0; i2 < this.documentLines.length; i2 += 1) { + const text = this.documentLines[i2]?.text ?? ""; + const match = FENCE_OPEN.exec(text); + if (open !== null) { + mask[i2] = true; + if (match !== null && match[1] !== void 0 && match[1].startsWith(open.char) && match[1].length >= open.length && (match[2] ?? "").trim() === "") { + open = null; + } + } else if (match !== null && match[1] !== void 0) { + const char = match[1].charAt(0); + const info2 = match[2] ?? ""; + if (char === "`" && info2.includes("`")) continue; + open = { char, length: match[1].length }; + mask[i2] = true; + } + } + return mask; + } + /** Info strings of opening code fences (e.g. `mermaid`, `ts`). */ + fenceInfoStrings() { + const infos = []; + let open = null; + for (const line of this.documentLines) { + const match = FENCE_OPEN.exec(line.text); + if (open !== null) { + if (match !== null && match[1] !== void 0 && match[1].startsWith(open.char) && match[1].length >= open.length && (match[2] ?? "").trim() === "") { + open = null; + } + } else if (match !== null && match[1] !== void 0) { + const char = match[1].charAt(0); + const info2 = (match[2] ?? "").trim(); + if (char === "`" && info2.includes("`")) continue; + open = { char, length: match[1].length }; + infos.push(info2); + } + } + return infos; + } + /** ATX headings outside code fences. Recomputed on demand (documents are small). */ + headings() { + const mask = this.codeFenceMask(); + const headings = []; + for (let i2 = 0; i2 < this.documentLines.length; i2 += 1) { + if (mask[i2] === true) continue; + const match = HEADING.exec(this.documentLines[i2]?.text ?? ""); + if (match === null || match[1] === void 0) continue; + let text = (match[2] ?? "").trim(); + text = text.replace(/[ \t]+#+[ \t]*$/, "").trim(); + headings.push({ line: i2, level: match[1].length, text }); + } + return headings; + } + /** + * Sections derived from headings. A section spans from its heading line to + * the next heading with the same or a higher (smaller-number) level. + */ + sections() { + const headings = this.headings(); + return headings.map((heading, index) => { + let endLine = this.documentLines.length; + for (let j = index + 1; j < headings.length; j += 1) { + const next = headings[j]; + if (next !== void 0 && next.level <= heading.level) { + endLine = next.line; + break; + } + } + return { heading, startLine: heading.line, endLine }; + }); + } + /** First section whose heading text matches (case-insensitive, trimmed). */ + findSection(matcher, options) { + const maxLevel = options?.maxLevel ?? 6; + for (const section of this.sections()) { + if (section.heading.level > maxLevel) continue; + const text = section.heading.text.trim(); + const matched = typeof matcher === "string" ? text.toLowerCase() === matcher.trim().toLowerCase() : matcher.test(text); + if (matched) return section; + } + return void 0; + } + /** Text of lines [startLine, endLine), joined with their original endings. */ + getText(startLine, endLine) { + let out = ""; + const end = Math.min(endLine, this.documentLines.length); + for (let i2 = Math.max(0, startLine); i2 < end; i2 += 1) { + const line = this.documentLines[i2]; + if (line !== void 0) out += line.text + line.eol; + } + return out; + } + /** Full body text without the BOM. */ + bodyText() { + return this.getText(0, this.documentLines.length); + } + dominantEol() { + let lf = 0; + let crlf = 0; + let cr = 0; + for (const line of this.documentLines) { + if (line.eol === "\n") lf += 1; + else if (line.eol === "\r\n") crlf += 1; + else if (line.eol === "\r") cr += 1; + } + const kinds = [lf > 0, crlf > 0, cr > 0].filter(Boolean).length; + if (kinds === 0) return "none"; + if (kinds > 1) return "mixed"; + if (lf > 0) return "lf"; + if (crlf > 0) return "crlf"; + return "cr"; + } + endsWithNewline() { + const last = this.documentLines[this.documentLines.length - 1]; + return last !== void 0 && last.eol !== ""; + } + /** First level-1 heading text, if any. Used as the document title. */ + title() { + return this.headings().find((h2) => h2.level === 1)?.text; + } +}; +function extractFrontMatter(document) { + if (document.lineCount === 0 || document.lineAt(0).text.trim() !== "---") { + return { present: false, endLine: 0 }; + } + for (let i2 = 1; i2 < document.lineCount; i2 += 1) { + const text = document.lineAt(i2).text.trim(); + if (text === "---" || text === "...") { + const raw = document.getText(1, i2); + try { + const data = (0, import_yaml.parse)(raw); + if (data === null || data === void 0) return { present: true, endLine: i2 + 1 }; + if (typeof data !== "object" || Array.isArray(data)) { + return { present: true, endLine: i2 + 1, error: "front matter is not a YAML mapping" }; + } + return { present: true, endLine: i2 + 1, data }; + } catch (cause) { + return { + present: true, + endLine: i2 + 1, + error: cause instanceof Error ? cause.message : String(cause) + }; + } + } + } + return { present: false, endLine: 0 }; +} +var KNOWN_FILE_KINDS = { + "requirements.md": "requirements", + "design.md": "design", + "tasks.md": "tasks", + "bugfix.md": "bugfix" +}; +function kindForFileName(fileName) { + return KNOWN_FILE_KINDS[fileName.toLowerCase()] ?? "other"; +} +function readSpecFolder(specsDir, name) { + const dir = import_path5.default.join(specsDir, name); + const files = []; + const extraDirs = []; + for (const entry of (0, import_fs7.readdirSync)(dir, { withFileTypes: true })) { + if (entry.isDirectory()) { + extraDirs.push(entry.name); + continue; + } + if (!entry.isFile()) continue; + const filePath = import_path5.default.join(dir, entry.name); + let sizeBytes = 0; + try { + sizeBytes = (0, import_fs7.statSync)(filePath).size; + } catch { + } + files.push({ + fileName: entry.name, + kind: kindForFileName(entry.name), + path: filePath, + sizeBytes + }); + } + files.sort((a2, b) => a2.fileName.localeCompare(b.fileName, "en")); + extraDirs.sort((a2, b) => a2.localeCompare(b, "en")); + return { name, dir, files, extraDirs }; +} +function discoverSpecs(workspace) { + if (workspace.specsDir === void 0) return []; + return (0, import_fs7.readdirSync)(workspace.specsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((a2, b) => a2.localeCompare(b, "en")).map((name) => readSpecFolder(workspace.specsDir, name)); +} +function findSpec(workspace, name) { + if (workspace.specsDir === void 0) return void 0; + const wanted = name.toLowerCase(); + return discoverSpecs(workspace).find((spec) => spec.name.toLowerCase() === wanted); +} +function requireSpec(workspace, name) { + const spec = findSpec(workspace, name); + if (spec === void 0) { + const available = discoverSpecs(workspace).map((s) => s.name); + throw new SpecBridgeError( + "SPEC_NOT_FOUND", + available.length > 0 ? `Spec "${name}" not found. Available specs: ${available.join(", ")}.` : `Spec "${name}" not found. This workspace has no specs under .kiro/specs/.` + ); + } + return spec; +} +function specFile(folder, kind) { + return folder.files.find((file) => file.kind === kind); +} +var FEATURE_REQUIRED = ["requirements", "design", "tasks"]; +var BUGFIX_REQUIRED = ["bugfix", "design", "tasks"]; +function classifySpec(folder, state) { + const diagnostics = []; + const presentKinds = [...new Set(folder.files.map((f) => f.kind))].filter( + (kind) => kind !== "other" + ); + const hasBugfix = specFile(folder, "bugfix") !== void 0; + let type; + if (hasBugfix) { + type = "bugfix"; + if (specFile(folder, "requirements") !== void 0) { + diagnostics.push({ + severity: "info", + code: "SPEC_MIXED_TYPE_FILES", + message: "Spec contains both bugfix.md and requirements.md; classified as a bugfix spec.", + file: folder.dir + }); + } + } else if (presentKinds.length > 0) { + type = "feature"; + } else { + type = "unknown"; + diagnostics.push({ + severity: "warning", + code: "SPEC_NO_KNOWN_FILES", + message: "Spec folder contains no recognized files (requirements.md, design.md, tasks.md, bugfix.md).", + file: folder.dir + }); + } + if (state !== void 0 && state.specType !== type && type !== "unknown") { + diagnostics.push({ + severity: "warning", + code: "SIDECAR_TYPE_MISMATCH", + message: `Sidecar state records type "${state.specType}" but the files look like a ${type} spec.`, + file: folder.dir + }); + } + const workflowMode = state?.workflowMode ?? "unknown"; + const required = type === "bugfix" ? BUGFIX_REQUIRED : FEATURE_REQUIRED; + const missingKinds = required.filter((kind) => !presentKinds.includes(kind)); + let completeness; + if (presentKinds.length === 0) completeness = "empty"; + else if (missingKinds.length === 0) completeness = "complete"; + else completeness = "partial"; + return { type, workflowMode, completeness, presentKinds, missingKinds, diagnostics }; +} +var REQUIREMENT_HEADING = /^requirements?[ \t]+((?:[A-Za-z]{1,4}-?)?\d[A-Za-z0-9.]*)[ \t]*[:.–—-]?[ \t]*(.*)$/i; +var REQUIREMENT_ID_HEADING = /^(R-?\d+(?:\.\d+)*)[ \t]*[:.–—-]?[ \t]*(.*)$/; +var USER_STORY = /\*\*[ \t]*user story[ \t]*:?[ \t]*\*\*[ \t]*:?[ \t]*(.*)$/i; +var ORDERED_ITEM = /^[ \t]*(\d+)[.)][ \t]+(.+)$/; +var BULLET_ITEM = /^[ \t]*[-*+][ \t]+(.+)$/; +var EARS = /\b(when|if|while|where)\b[\s\S]*\bshall\b/i; +var KNOWN_TOP_SECTIONS = /* @__PURE__ */ new Set(["introduction", "overview", "summary", "requirements"]); +function matchRequirementHeading(text) { + const trimmed = text.trim(); + const named = REQUIREMENT_HEADING.exec(trimmed); + if (named !== null && named[1] !== void 0) { + const title = (named[2] ?? "").trim(); + return { id: named[1], ...title.length > 0 ? { title } : {} }; + } + const shorthand = REQUIREMENT_ID_HEADING.exec(trimmed); + if (shorthand !== null && shorthand[1] !== void 0) { + const title = (shorthand[2] ?? "").trim(); + return { id: shorthand[1], ...title.length > 0 ? { title } : {} }; + } + return void 0; +} +function parseCriteria(document, requirementId, section, mask, diagnostics) { + const acHeading = document.headings().find( + (h2) => h2.line > section.startLine && h2.line < section.endLine && /acceptance criteria/i.test(h2.text) + ); + if (acHeading === void 0) return []; + const nextHeading = document.headings().find((h2) => h2.line > acHeading.line && h2.line < section.endLine); + const endLine = nextHeading?.line ?? section.endLine; + const criteria = []; + let unnumberedCount = 0; + for (let i2 = acHeading.line + 1; i2 < endLine; i2 += 1) { + if (mask[i2] === true) continue; + const text = document.lineAt(i2).text; + const ordered = ORDERED_ITEM.exec(text); + if (ordered !== null && ordered[1] !== void 0 && ordered[2] !== void 0) { + criteria.push({ + id: `${requirementId}.${ordered[1]}`, + number: ordered[1], + text: ordered[2].trim(), + line: i2, + ears: EARS.test(ordered[2]) + }); + continue; + } + const bullet = BULLET_ITEM.exec(text); + if (bullet !== null && bullet[1] !== void 0 && criteria.length === 0) { + unnumberedCount += 1; + criteria.push({ + id: `${requirementId}.${unnumberedCount}`, + number: String(unnumberedCount), + text: bullet[1].trim(), + line: i2, + ears: EARS.test(bullet[1]) + }); + continue; + } + if (bullet !== null && bullet[1] !== void 0 && unnumberedCount > 0) { + unnumberedCount += 1; + criteria.push({ + id: `${requirementId}.${unnumberedCount}`, + number: String(unnumberedCount), + text: bullet[1].trim(), + line: i2, + ears: EARS.test(bullet[1]) + }); + } + } + if (unnumberedCount > 0) { + diagnostics.push({ + severity: "info", + code: "REQUIREMENTS_UNNUMBERED_CRITERIA", + message: `Requirement ${requirementId} uses unnumbered acceptance criteria; SpecBridge assigned positional numbers.`, + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: acHeading.line + 1 + }); + } + return criteria; +} +function parseRequirements(document) { + const diagnostics = []; + const mask = document.codeFenceMask(); + const sections = document.sections(); + const requirements = []; + const seenIds = /* @__PURE__ */ new Map(); + const requirementSections = []; + for (const section of sections) { + if (section.heading.level < 2 || section.heading.level > 4) continue; + const match = matchRequirementHeading(section.heading.text); + if (match === void 0) continue; + requirementSections.push(section); + const previous = seenIds.get(match.id); + if (previous !== void 0) { + diagnostics.push({ + severity: "warning", + code: "REQUIREMENTS_DUPLICATE_ID", + message: `Requirement id ${match.id} appears more than once (also on line ${previous}).`, + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: section.heading.line + 1 + }); + } else { + seenIds.set(match.id, section.heading.line + 1); + } + let userStory; + for (let i2 = section.startLine + 1; i2 < section.endLine; i2 += 1) { + if (mask[i2] === true) continue; + const storyMatch = USER_STORY.exec(document.lineAt(i2).text); + if (storyMatch !== null) { + userStory = (storyMatch[1] ?? "").trim(); + if (userStory.length === 0) { + const next = i2 + 1 < section.endLine ? document.lineAt(i2 + 1).text.trim() : ""; + userStory = next.length > 0 ? next : void 0; + } + break; + } + } + const criteria = parseCriteria(document, match.id, section, mask, diagnostics); + if (criteria.length === 0) { + diagnostics.push({ + severity: "info", + code: "REQUIREMENTS_NO_CRITERIA", + message: `Requirement ${match.id} has no recognized acceptance criteria.`, + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: section.heading.line + 1 + }); + } + requirements.push({ + id: match.id, + ...match.title !== void 0 ? { title: match.title } : {}, + ...userStory !== void 0 ? { userStory } : {}, + criteria, + headingLine: section.heading.line, + startLine: section.startLine, + endLine: section.endLine + }); + } + const introductionSection = sections.find( + (s) => s.heading.level <= 2 && /^(introduction|overview|summary)$/i.test(s.heading.text.trim()) + ); + const unknownSections = []; + for (const section of sections) { + if (section.heading.level !== 2) continue; + const text = section.heading.text.trim().toLowerCase(); + if (KNOWN_TOP_SECTIONS.has(text)) continue; + if (matchRequirementHeading(section.heading.text) !== void 0) continue; + const insideRequirement = requirementSections.some( + (r) => section.heading.line > r.startLine && section.heading.line < r.endLine + ); + if (insideRequirement) continue; + unknownSections.push({ + title: section.heading.text, + line: section.heading.line, + level: section.heading.level + }); + } + if (requirements.length === 0) { + diagnostics.push({ + severity: "info", + code: "REQUIREMENTS_NONE_RECOGNIZED", + message: 'No "Requirement N" headings recognized. The file is preserved as-is; task-to-requirement linking is unavailable.', + ...document.filePath !== void 0 ? { file: document.filePath } : {} + }); + } + const title = document.title(); + return { + ...document.filePath !== void 0 ? { filePath: document.filePath } : {}, + ...title !== void 0 ? { title } : {}, + ...introductionSection !== void 0 ? { + introduction: { + startLine: introductionSection.startLine, + endLine: introductionSection.endLine + } + } : {}, + requirements, + unknownSections, + diagnostics + }; +} +var KIND_MATCHERS = [ + [/non[- ]goals?/i, "non-goals"], + [/goals?/i, "goals"], + [/root cause/i, "root-cause"], + [/proposed fix|fix approach/i, "proposed-fix"], + [/data model|data models|schema/i, "data-model"], + [/error handling|failure handling|failure modes?/i, "error-handling"], + [/components?( and interfaces?)?/i, "components"], + [/interfaces?|api/i, "interfaces"], + [/testing|test strategy|validation strategy/i, "testing"], + [/security|threat model/i, "security"], + [/observability|monitoring|telemetry/i, "observability"], + [/risks?|regression risks?/i, "risks"], + [/alternatives?|options considered/i, "alternatives"], + [/migration|rollout|deployment/i, "migration"], + [/architecture/i, "architecture"], + [/overview|introduction|summary/i, "overview"], + [/context|background/i, "context"] +]; +function classifyDesignHeading(text) { + for (const [pattern, kind] of KIND_MATCHERS) { + if (pattern.test(text)) return kind; + } + return "unknown"; +} +function parseDesign(document) { + const diagnostics = []; + const sections = []; + for (const section of document.sections()) { + if (section.heading.level < 2 || section.heading.level > 3) continue; + sections.push({ + title: section.heading.text, + kind: classifyDesignHeading(section.heading.text), + level: section.heading.level, + startLine: section.startLine, + endLine: section.endLine + }); + } + const mermaidBlockCount = document.fenceInfoStrings().filter((info2) => info2.toLowerCase().startsWith("mermaid")).length; + if (sections.length === 0) { + diagnostics.push({ + severity: "info", + code: "DESIGN_NO_SECTIONS", + message: "design.md has no level-2/3 headings; the file is preserved as-is.", + ...document.filePath !== void 0 ? { file: document.filePath } : {} + }); + } + const title = document.title(); + return { + ...document.filePath !== void 0 ? { filePath: document.filePath } : {}, + ...title !== void 0 ? { title } : {}, + sections, + mermaidBlockCount, + diagnostics + }; +} +var CHECKBOX = /^([ \t]*)([-*+])[ \t]+\[([^\]]?)\](\*)?[ \t]*(.*)$/; +var CHECKBOX_PROBE = /^[ \t]*[-*+][ \t]+\[([^\]]*)\]/; +var NUMBER_PREFIX = /^(\d+(?:\.\d+)*)[.)]?[ \t]+(.*)$/; +var REQUIREMENT_REF = /_[ \t]*requirements?[ \t]*:[ \t]*([^_]*)_/i; +function stateForChar(char) { + if (char === " " || char === "") return "open"; + if (char === "x" || char === "X") return "done"; + if (char === "-" || char === "~") return "in-progress"; + return "unknown"; +} +function indentWidth(indent) { + let width = 0; + for (const char of indent) width += char === " " ? 4 : 1; + return width; +} +function parseTasks(document) { + const diagnostics = []; + const mask = document.codeFenceMask(); + const allTasks = []; + const roots = []; + const stack = []; + const numbersSeen = /* @__PURE__ */ new Map(); + for (let i2 = 0; i2 < document.lineCount; i2 += 1) { + if (mask[i2] === true) continue; + const text = document.lineAt(i2).text; + const match = CHECKBOX.exec(text); + if (match === null) { + const probe = CHECKBOX_PROBE.exec(text); + if (probe !== null) { + const inner = probe[1] ?? ""; + const looksLikeCheckbox = inner.trim() === "" || /^[ \txX~-]+$/.test(inner); + if (looksLikeCheckbox && inner.length !== 1) { + diagnostics.push({ + severity: "warning", + code: "TASKS_MALFORMED_CHECKBOX", + message: `Unrecognized checkbox syntax "[${inner}]"; this line is preserved but not counted as a task.`, + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: i2 + 1 + }); + } + } + if (allTasks.length > 0) { + const refMatch = REQUIREMENT_REF.exec(text); + if (refMatch !== null) { + const owner = allTasks[allTasks.length - 1]; + if (owner !== void 0) { + const refs = (refMatch[1] ?? "").split(",").map((ref) => ref.trim()).filter((ref) => ref.length > 0); + owner.requirementRefs.push(...refs); + } + } + } + continue; + } + const indentText = match[1] ?? ""; + const stateChar = match[3] ?? ""; + const optionalMarker = match[4] === "*"; + const rest = (match[5] ?? "").trim(); + if (stateChar === "") { + diagnostics.push({ + severity: "warning", + code: "TASKS_MALFORMED_CHECKBOX", + message: 'Empty checkbox brackets "[]"; this line is preserved but not counted as a task.', + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: i2 + 1 + }); + continue; + } + const state = stateForChar(stateChar); + if (state === "unknown") { + diagnostics.push({ + severity: "info", + code: "TASKS_UNKNOWN_CHECKBOX_STATE", + message: `Unrecognized checkbox state "[${stateChar}]"; treated as unknown and preserved as-is.`, + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: i2 + 1 + }); + } + const numberMatch = NUMBER_PREFIX.exec(rest); + const number = numberMatch?.[1]; + const title = (numberMatch?.[2] ?? rest).trim(); + const optional = optionalMarker || /\(optional\)/i.test(rest); + const task = { + id: number ?? `line:${i2 + 1}`, + ...number !== void 0 ? { number } : {}, + title, + line: i2, + indent: indentWidth(indentText), + state, + stateChar, + optional, + requirementRefs: [], + children: [] + }; + if (number !== void 0) { + const previousLine = numbersSeen.get(number); + if (previousLine !== void 0) { + diagnostics.push({ + severity: "warning", + code: "TASKS_DUPLICATE_NUMBER", + message: `Task number ${number} appears more than once (also on line ${previousLine}).`, + ...document.filePath !== void 0 ? { file: document.filePath } : {}, + line: i2 + 1 + }); + } else { + numbersSeen.set(number, i2 + 1); + } + } + while (stack.length > 0 && (stack[stack.length - 1]?.indent ?? 0) >= task.indent) { + stack.pop(); + } + const parent = stack[stack.length - 1]?.task; + if (parent !== void 0) parent.children.push(task); + else roots.push(task); + stack.push({ indent: task.indent, task }); + allTasks.push(task); + } + const progress = { + total: 0, + completed: 0, + inProgress: 0, + optionalTotal: 0, + optionalCompleted: 0 + }; + for (const task of allTasks) { + if (task.optional) { + progress.optionalTotal += 1; + if (task.state === "done") progress.optionalCompleted += 1; + } else { + progress.total += 1; + if (task.state === "done") progress.completed += 1; + if (task.state === "in-progress") progress.inProgress += 1; + } + } + return { + ...document.filePath !== void 0 ? { filePath: document.filePath } : {}, + ...document.title() !== void 0 ? { title: document.title() } : {}, + tasks: roots, + allTasks, + progress, + diagnostics + }; +} +function normalizeHeading(text) { + return text.toLowerCase().replace(/[^a-z0-9 ]+/g, " ").replace(/\s+/g, " ").trim(); +} +var CONCEPT_MATCHERS = [ + [/^current behaviou?r$|^actual behaviou?r$/, "current-behavior"], + [/^expected behaviou?r$|^desired behaviou?r$/, "expected-behavior"], + [/^unchanged behaviou?r$|^behaviou?r to preserve$/, "unchanged-behavior"], + [/^root cause( analysis)?$/, "root-cause"], + [/^regression protection$|^regression risks?$|^regression tests?$/, "regression-protection"], + [/^reproduction( steps)?$|^steps to reproduce$|^repro( steps)?$/, "reproduction"], + [/^evidence$|^logs?$|^observed evidence$/, "evidence"], + [/^constraints?$/, "constraints"], + [/^proposed fix$|^fix$|^fix approach$/, "proposed-fix"], + [/^validation( strategy)?$|^verification( strategy)?$/, "validation-strategy"] +]; +function classifyBugfixHeading(text) { + const normalized = normalizeHeading(text); + for (const [pattern, concept] of CONCEPT_MATCHERS) { + if (pattern.test(normalized)) return concept; + } + return void 0; +} +function parseBugfix(document) { + const diagnostics = []; + const concepts = {}; + const unknownSections = []; + for (const section of document.sections()) { + if (section.heading.level < 2 || section.heading.level > 4) continue; + const ref = { + title: section.heading.text, + level: section.heading.level, + startLine: section.startLine, + endLine: section.endLine + }; + const concept = classifyBugfixHeading(section.heading.text); + if (concept === void 0) { + if (section.heading.level === 2) unknownSections.push(ref); + continue; + } + if (concepts[concept] === void 0) concepts[concept] = ref; + } + const behaviorConcepts = [ + "current-behavior", + "expected-behavior", + "unchanged-behavior" + ]; + if (behaviorConcepts.every((concept) => concepts[concept] === void 0)) { + diagnostics.push({ + severity: "info", + code: "BUGFIX_NO_BEHAVIOR_SECTIONS", + message: "bugfix.md has no recognized behavior sections (Current/Expected/Unchanged Behavior); the file is preserved as-is.", + ...document.filePath !== void 0 ? { file: document.filePath } : {} + }); + } + const title = document.title(); + return { + ...document.filePath !== void 0 ? { filePath: document.filePath } : {}, + ...title !== void 0 ? { title } : {}, + concepts, + unknownSections, + diagnostics + }; +} +function checkNoopRoundTrip(filePath) { + let original; + try { + original = (0, import_fs8.readFileSync)(filePath); + } catch (cause) { + return { + file: filePath, + identical: false, + encodingSafe: false, + byteLength: 0, + eol: "none", + hasBom: false, + lineCount: 0, + reason: `unreadable: ${cause instanceof Error ? cause.message : String(cause)}` + }; + } + const document = MarkdownDocument.fromBuffer(original, filePath); + const reserialized = document.toBuffer(); + const identical = reserialized.equals(original); + return { + file: filePath, + identical, + encodingSafe: document.encodingSafe, + byteLength: original.length, + eol: document.dominantEol(), + hasBom: document.hasBom, + lineCount: document.lineCount, + ...identical ? {} : { + reason: document.encodingSafe ? "reserialized bytes differ from the original (this is a SpecBridge bug \u2014 please report it)" : "file is not valid UTF-8" + } + }; +} +function scanForForeignMetadata(document) { + const frontMatter = extractFrontMatter(document); + if (!frontMatter.present || frontMatter.data === void 0) return false; + return Object.keys(frontMatter.data).some((key) => key.toLowerCase().includes("specbridge")); +} +function analyzeSpec(workspace, folder) { + const diagnostics = []; + const documents = {}; + const roundTrip = []; + const stateResult = readSpecState(workspace, folder.name); + diagnostics.push(...stateResult.diagnostics); + const classification = classifySpec(folder, stateResult.state); + diagnostics.push(...classification.diagnostics); + let requirements; + let design; + let tasks; + let bugfix; + for (const file of folder.files) { + if (!file.fileName.toLowerCase().endsWith(".md")) continue; + roundTrip.push(checkNoopRoundTrip(file.path)); + let document; + try { + document = MarkdownDocument.load(file.path); + } catch (cause) { + diagnostics.push({ + severity: "error", + code: "SPEC_FILE_UNREADABLE", + message: cause instanceof Error ? cause.message : String(cause), + file: file.path + }); + continue; + } + if (!document.encodingSafe) { + diagnostics.push({ + severity: "error", + code: "FILE_NOT_UTF8", + message: "File is not valid UTF-8; SpecBridge reads it best-effort but will never edit it.", + file: file.path + }); + } + if (document.dominantEol() === "mixed") { + diagnostics.push({ + severity: "warning", + code: "FILE_MIXED_LINE_ENDINGS", + message: "File mixes LF and CRLF line endings. SpecBridge preserves them exactly as-is.", + file: file.path + }); + } + if (file.sizeBytes === 0) { + diagnostics.push({ + severity: "warning", + code: "SPEC_FILE_EMPTY", + message: "File is empty.", + file: file.path + }); + } + if (scanForForeignMetadata(document)) { + diagnostics.push({ + severity: "error", + code: "FOREIGN_METADATA_IN_KIRO_FILE", + message: "Found SpecBridge-branded front matter inside a .kiro file. SpecBridge never writes metadata into .kiro; please report how this happened.", + file: file.path + }); + } + switch (file.kind) { + case "requirements": + documents.requirements = document; + requirements = parseRequirements(document); + diagnostics.push(...requirements.diagnostics); + break; + case "design": + documents.design = document; + design = parseDesign(document); + diagnostics.push(...design.diagnostics); + break; + case "tasks": + documents.tasks = document; + tasks = parseTasks(document); + diagnostics.push(...tasks.diagnostics); + break; + case "bugfix": + documents.bugfix = document; + bugfix = parseBugfix(document); + diagnostics.push(...bugfix.diagnostics); + break; + case "other": + break; + } + } + for (const missing of classification.missingKinds) { + diagnostics.push({ + severity: "info", + code: "SPEC_STAGE_MISSING", + message: `${missing}.md is not present yet (${classification.type} specs usually gain it in a later stage).`, + file: folder.dir + }); + } + return { + folder, + classification, + ...stateResult.state !== void 0 ? { state: stateResult.state } : {}, + documents, + ...requirements !== void 0 ? { requirements } : {}, + ...design !== void 0 ? { design } : {}, + ...tasks !== void 0 ? { tasks } : {}, + ...bugfix !== void 0 ? { bugfix } : {}, + taskProgress: tasks?.progress ?? EMPTY_TASK_PROGRESS, + roundTrip, + diagnostics + }; +} +var CHECKBOX_STATE_PREFIX = /^([ \t]*[-*+][ \t]+\[)([ xX~-])(\])/; +var NORMALIZED_STATE = " "; +function normalizedTaskPlanText(document) { + const mask = document.codeFenceMask(); + let out = document.hasBom ? String.fromCharCode(65279) : ""; + for (let i2 = 0; i2 < document.lineCount; i2 += 1) { + const line = document.lineAt(i2); + let text = line.text; + if (mask[i2] !== true) { + const match = CHECKBOX_STATE_PREFIX.exec(text); + if (match !== null && match[1] !== void 0 && match[3] !== void 0) { + text = `${match[1]}${NORMALIZED_STATE}${match[3]}${text.slice(match[0].length)}`; + } + } + out += text + line.eol; + } + return out; +} +function taskPlanHash(document) { + return sha256Hex(Buffer.from(normalizedTaskPlanText(document), "utf8")); +} +function tryTaskPlanHashOfFile(filePath) { + try { + return taskPlanHash(MarkdownDocument.load(filePath)); + } catch { + return void 0; + } +} +function taskFingerprint(task) { + return sha256Hex( + JSON.stringify({ + id: task.id, + title: task.title, + requirementRefs: [...task.requirementRefs] + }) + ); +} +var ID_PREFIX = /^(?:requirements?|req|r|ac|criterion)[-_. ]?(?=\d)/i; +var CANONICAL_SHAPE = /^\d+(?:[.-]\d+)*$/; +function canonicalRequirementRef(raw) { + const trimmed = raw.trim().toLowerCase(); + if (trimmed.length === 0) return void 0; + const withoutPrefix = trimmed.replace(ID_PREFIX, ""); + if (!CANONICAL_SHAPE.test(withoutPrefix)) return void 0; + return withoutPrefix.split(/[.-]/).map((segment) => segment.replace(/^0+(?=\d)/, "")).join("."); +} +var TEST_LANGUAGE = /\btest(?:s|ed|ing)?\b|\bunit[- ]tested\b|\bcovered by tests\b/i; +function mentionsTests(text) { + return TEST_LANGUAGE.test(text); +} +var ID_HEADING = /^((?:req)[-_. ]?\d+(?:[.-]\d+)*)[ \t]*[:.–—-]?[ \t]*(.*)$/i; +var EXPLICIT_AC_MARKER = /^(ac[-_. ]?\d+(?:[.-]\d+)*)[ \t]*[:.–—-][ \t]*/i; +var ORDERED_ITEM2 = /^[ \t]*(\d+)[.)][ \t]+(.+)$/; +function buildRequirementCatalog(model, document) { + const entries = []; + const byCanonical = /* @__PURE__ */ new Map(); + const add = (entry) => { + entries.push(entry); + if (!byCanonical.has(entry.canonical)) byCanonical.set(entry.canonical, entry); + }; + for (const requirement of model.requirements) { + const canonical = canonicalRequirementRef(requirement.id); + if (canonical === void 0) continue; + const requirementEntry = { + displayId: requirement.id, + canonical, + kind: "requirement", + line: requirement.headingLine, + ...requirement.title !== void 0 ? { title: requirement.title } : {}, + testRequired: requirement.title !== void 0 && mentionsTests(requirement.title) || requirement.criteria.some((criterion) => mentionsTests(criterion.text)), + requirementCanonical: canonical, + method: "requirements-parser", + confidence: "deterministic" + }; + add(requirementEntry); + for (const criterion of requirement.criteria) { + const criterionCanonical = canonicalRequirementRef(criterion.id); + if (criterionCanonical === void 0) continue; + add({ + displayId: criterion.id, + canonical: criterionCanonical, + kind: "criterion", + line: criterion.line, + testRequired: mentionsTests(criterion.text), + requirementCanonical: canonical, + method: "requirements-parser", + confidence: "deterministic" + }); + const marker = EXPLICIT_AC_MARKER.exec(criterion.text); + const markerCanonical = marker?.[1] !== void 0 ? canonicalRequirementRef(marker[1]) : void 0; + if (markerCanonical !== void 0 && markerCanonical !== criterionCanonical) { + add({ + displayId: marker[1], + canonical: markerCanonical, + kind: "criterion", + line: criterion.line, + testRequired: mentionsTests(criterion.text), + requirementCanonical: canonical, + method: "explicit-ac-marker", + confidence: "deterministic" + }); + } + } + } + if (document !== void 0) { + const knownHeadingLines = new Set(model.requirements.map((r) => r.headingLine)); + const sections = document.sections(); + const mask = document.codeFenceMask(); + for (const section of sections) { + if (section.heading.level < 2 || section.heading.level > 4) continue; + if (knownHeadingLines.has(section.heading.line)) continue; + const match = ID_HEADING.exec(section.heading.text.trim()); + if (match === null || match[1] === void 0) continue; + const canonical = canonicalRequirementRef(match[1]); + if (canonical === void 0 || byCanonical.has(canonical)) continue; + const title = (match[2] ?? "").trim(); + const sectionText = document.getText(section.startLine, section.endLine); + const entry = { + displayId: match[1], + canonical, + kind: "requirement", + line: section.heading.line, + ...title.length > 0 ? { title } : {}, + testRequired: mentionsTests(sectionText), + requirementCanonical: canonical, + method: "id-heading", + confidence: "deterministic" + }; + add(entry); + for (let i2 = section.startLine + 1; i2 < section.endLine; i2 += 1) { + if (mask[i2] === true) continue; + const item = ORDERED_ITEM2.exec(document.lineAt(i2).text); + if (item === null || item[1] === void 0 || item[2] === void 0) continue; + const criterionCanonical = `${canonical}.${item[1].replace(/^0+(?=\d)/, "")}`; + if (byCanonical.has(criterionCanonical)) continue; + add({ + displayId: `${match[1]}.${item[1]}`, + canonical: criterionCanonical, + kind: "criterion", + line: i2, + testRequired: mentionsTests(item[2]), + requirementCanonical: canonical, + method: "id-heading", + confidence: "deterministic" + }); + } + } + } + return { + entries, + requirements: entries.filter((entry) => entry.kind === "requirement"), + byCanonical + }; +} +var UNDERSCORE_REFS = /_[ \t]*requirements?[ \t]*:[ \t]*([^_]*)_/i; +var REFS_LINE = /^[ \t]*(?:[-*+][ \t]+)?requirements?[ \t]*:[ \t]*(.+)$/i; +var BRACKET_REF = /\[[ \t]*((?:req|r|ac)[-_. ]?\d+(?:[.-]\d+)*)[ \t]*\](?!\()/gi; +var KEYWORD_REF = /\b(?:supports|implements|covers|satisfies|fulfils|fulfills|addresses)[ \t]+((?:requirements?|req|r|ac)[-_. ]?\d+(?:[.-]\d+)*|\d+(?:\.\d+)+)/gi; +function splitReferenceList(list) { + return list.split(/[,;]/).map((item) => item.trim()).filter((item) => item.length > 0); +} +function ownerTaskAt(tasks, line) { + let owner; + for (const task of tasks) { + if (task.line <= line) owner = task; + else break; + } + return owner; +} +function extractTaskRequirementReferences(document, tasks) { + const references = []; + if (tasks.allTasks.length === 0) return references; + const mask = document.codeFenceMask(); + const orderedTasks = [...tasks.allTasks].sort((a2, b) => a2.line - b.line); + const firstTaskLine = orderedTasks[0]?.line ?? 0; + const seen = /* @__PURE__ */ new Set(); + const push = (task, raw, line, method, confidence) => { + const canonical = canonicalRequirementRef(raw); + const key = `${task.id} ${canonical ?? raw.toLowerCase()}`; + if (seen.has(key)) return; + seen.add(key); + references.push({ + taskId: task.id, + raw, + ...canonical !== void 0 ? { canonical } : {}, + line, + method, + confidence + }); + }; + for (let i2 = firstTaskLine; i2 < document.lineCount; i2 += 1) { + if (mask[i2] === true) continue; + const owner = ownerTaskAt(orderedTasks, i2); + if (owner === void 0) continue; + const text = document.lineAt(i2).text; + const isTaskLine = orderedTasks.some((task) => task.line === i2); + if (!isTaskLine) { + const underscore = UNDERSCORE_REFS.exec(text); + if (underscore !== null) { + for (const item of splitReferenceList(underscore[1] ?? "")) { + push(owner, item, i2, "underscore-refs", "deterministic"); + } + } else { + const refsLine = REFS_LINE.exec(text); + if (refsLine !== null) { + for (const item of splitReferenceList(refsLine[1] ?? "")) { + if (canonicalRequirementRef(item) !== void 0) { + push(owner, item, i2, "refs-line", "deterministic"); + } + } + } + } + } + for (const match of text.matchAll(BRACKET_REF)) { + if (match[1] !== void 0) push(owner, match[1], i2, "bracket-ref", "deterministic"); + } + for (const match of text.matchAll(KEYWORD_REF)) { + if (match[1] !== void 0) push(owner, match[1], i2, "keyword-ref", "heuristic"); + } + } + return references; +} +function taskMentionsTests(document, tasks, task) { + if (mentionsTests(task.title)) return true; + const orderedTasks = [...tasks.allTasks].sort((a2, b) => a2.line - b.line); + const next = orderedTasks.find((candidate) => candidate.line > task.line); + const endLine = next?.line ?? document.lineCount; + const mask = document.codeFenceMask(); + for (let i2 = task.line + 1; i2 < endLine; i2 += 1) { + if (mask[i2] === true) continue; + if (mentionsTests(document.lineAt(i2).text)) return true; + } + return false; +} +var NON_REQUIREMENT_TASK = /\b(document|documentation|docs|readme|changelog|release|publish|version bump|cleanup|clean up|chore|lint|format|typo)\b/i; +function isLikelyNonRequirementTask(task) { + return NON_REQUIREMENT_TASK.test(task.title); +} +var BACKTICK_SPAN = /`([^`\n]+)`/g; +var MARKDOWN_LINK = /\[[^\]]*\]\(([^()\s]+)\)/g; +var URL_SCHEME = /^[a-z][a-z0-9+.-]*:/i; +var GLOB_CHARS = /[*?[\]{}]/; +var CODE_TOKEN = /[(){}<>;=,]|::|=>/; +function normalizePathCandidate(raw) { + let candidate = raw.trim(); + if (candidate.length === 0 || candidate.includes("\0") || /\s/.test(candidate)) { + return void 0; + } + if (URL_SCHEME.test(candidate) || candidate.startsWith("#")) return void 0; + if (CODE_TOKEN.test(candidate)) return void 0; + candidate = candidate.split("\\").join("/"); + candidate = candidate.replace(/^\.\//, ""); + if (candidate.startsWith("/") || /^[A-Za-z]:/.test(candidate)) return void 0; + if (candidate.split("/").includes("..")) return void 0; + candidate = candidate.replace(/[#?].*$/, ""); + if (candidate.length === 0) return void 0; + if (!candidate.includes("/")) return void 0; + if (candidate.endsWith("/")) candidate = candidate.slice(0, -1); + if (candidate.length === 0) return void 0; + return candidate; +} +function extractPathReferences(document) { + const references = []; + const mask = document.codeFenceMask(); + const seen = /* @__PURE__ */ new Set(); + for (let i2 = 0; i2 < document.lineCount; i2 += 1) { + if (mask[i2] === true) continue; + const text = document.lineAt(i2).text; + for (const match of text.matchAll(BACKTICK_SPAN)) { + const raw = match[1]; + if (raw === void 0) continue; + const path53 = normalizePathCandidate(raw); + if (path53 === void 0) continue; + const key = `${path53} ${i2}`; + if (seen.has(key)) continue; + seen.add(key); + references.push({ + raw, + path: path53, + line: i2, + method: "backtick-path", + confidence: "deterministic", + isGlob: GLOB_CHARS.test(path53) + }); + } + for (const match of text.matchAll(MARKDOWN_LINK)) { + const raw = match[1]; + if (raw === void 0) continue; + const path53 = normalizePathCandidate(raw); + if (path53 === void 0) continue; + const key = `${path53} ${i2}`; + if (seen.has(key)) continue; + seen.add(key); + references.push({ + raw, + path: path53, + line: i2, + method: "markdown-link", + confidence: "deterministic", + isGlob: GLOB_CHARS.test(path53) + }); + } + } + return references; +} + +// ../../packages/evidence/dist/index.js +var import_fs9 = require("fs"); +var import_path6 = __toESM(require("path"), 1); +var import_path7 = __toESM(require("path"), 1); +var TAIL_BYTES = 8 * 1024; +function tail(text) { + return text.length > TAIL_BYTES ? text.slice(text.length - TAIL_BYTES) : text; +} +async function runVerificationCommands(workspaceRoot, commands, options = {}) { + const results = []; + const requiredFailed = []; + const optionalFailed = []; + for (const command of commands) { + options.onCommandStart?.(command); + const executable = command.argv[0]; + const rest = command.argv.slice(1); + const processResult = await runSafeProcess({ + executable, + argv: rest, + cwd: workspaceRoot, + timeoutMs: command.timeoutMs, + ...options.signal !== void 0 ? { signal: options.signal } : {}, + maxStdoutBytes: 16 * 1024 * 1024, + maxStderrBytes: 16 * 1024 * 1024 + }); + const passed = processResult.status === "ok"; + const result = { + name: command.name, + argv: [...command.argv], + required: command.required, + status: processResult.status, + exitCode: processResult.observation.exitCode, + durationMs: processResult.observation.durationMs, + timedOut: processResult.observation.timedOut, + stdoutTail: tail(processResult.stdout), + stderrTail: tail(processResult.stderr), + passed + }; + results.push(result); + options.onCommandFinished?.(result, processResult.stdout, processResult.stderr); + if (!passed) { + if (command.required) requiredFailed.push(command.name); + else optionalFailed.push(command.name); + } + } + return { + ran: true, + skipped: false, + configured: commands.length > 0, + commands: results, + requiredFailed, + optionalFailed, + passed: requiredFailed.length === 0 + }; +} +var changedFileRecordSchema = external_exports.object({ + path: external_exports.string().min(1), + changeType: external_exports.enum(["added", "modified", "deleted"]), + preExisting: external_exports.boolean(), + modifiedDuringRun: external_exports.boolean() +}); +var evidenceVerificationCommandSchema = external_exports.object({ + name: external_exports.string(), + argv: external_exports.array(external_exports.string()), + required: external_exports.boolean(), + exitCode: external_exports.number().nullable(), + durationMs: external_exports.number(), + passed: external_exports.boolean() +}); +var manualAcceptanceSchema = external_exports.object({ + actor: external_exports.literal("local-user"), + reason: external_exports.string().min(1), + acceptedAt: external_exports.string(), + referencedRunId: external_exports.string().optional() +}); +var SHA256_HEX2 = /^[0-9a-f]{64}$/; +var evidenceSpecContextSchema = external_exports.object({ + /** Approved exact-byte hash of requirements.md/bugfix.md at evidence time. */ + documentHash: external_exports.string().regex(SHA256_HEX2).optional(), + /** Approved exact-byte hash of design.md at evidence time. */ + designHash: external_exports.string().regex(SHA256_HEX2).optional(), + /** Checkbox-normalized plan hash of tasks.md at evidence time. */ + tasksPlanHash: external_exports.string().regex(SHA256_HEX2).optional(), + /** Fingerprint of the task's id, title, and requirement refs. */ + taskFingerprint: external_exports.string().regex(SHA256_HEX2).optional(), + /** Raw checkbox line text of the task at evidence time. */ + taskText: external_exports.string().optional() +}).passthrough(); +var taskEvidenceRecordSchema = external_exports.object({ + schemaVersion: external_exports.string().regex(/^\d+\.\d+\.\d+$/), + runId: external_exports.string().min(1), + parentRunId: external_exports.string().optional(), + specName: external_exports.string().min(1), + taskId: external_exports.string().min(1), + status: external_exports.enum(EVIDENCE_STATUS_VALUES), + runner: external_exports.string().min(1), + sessionId: external_exports.string().optional(), + repository: external_exports.object({ + headBefore: external_exports.string().optional(), + headAfter: external_exports.string().optional(), + branch: external_exports.string().optional(), + dirtyBefore: external_exports.boolean(), + dirtyAfter: external_exports.boolean() + }), + changedFiles: external_exports.array(changedFileRecordSchema), + verificationCommands: external_exports.array(evidenceVerificationCommandSchema), + verificationSkipped: external_exports.boolean(), + runnerClaims: external_exports.object({ + outcome: external_exports.string().optional(), + summary: external_exports.string().optional(), + changedFiles: external_exports.array(external_exports.string()), + commandsReported: external_exports.array(external_exports.string()), + testsReported: external_exports.array(external_exports.object({ name: external_exports.string(), status: external_exports.string() })) + }), + violations: external_exports.array(external_exports.string()), + warnings: external_exports.array(external_exports.string()), + evaluatedAt: external_exports.string(), + manualAcceptance: manualAcceptanceSchema.optional(), + specContext: evidenceSpecContextSchema.optional() +}).passthrough(); +function taskIdDirName(taskId) { + return taskId.replace(/[^A-Za-z0-9._-]+/g, "-"); +} +function evidenceTaskDir(workspace, specName, taskId) { + return assertInsideWorkspace( + workspace.rootDir, + import_path6.default.join(workspace.sidecarDir, "evidence", specName, taskIdDirName(taskId)) + ); +} +function listTaskEvidence(workspace, specName, taskId) { + const dir = evidenceTaskDir(workspace, specName, taskId); + if (!(0, import_fs9.existsSync)(dir)) return { records: [], diagnostics: [] }; + const records = []; + const diagnostics = []; + for (const entry of (0, import_fs9.readdirSync)(dir, { withFileTypes: true })) { + if (!entry.isFile() || !entry.name.endsWith(".json")) continue; + const filePath = import_path6.default.join(dir, entry.name); + try { + const parsed = JSON.parse((0, import_fs9.readFileSync)(filePath, "utf8")); + const result = taskEvidenceRecordSchema.safeParse(parsed); + if (result.success) { + records.push(result.data); + } else { + diagnostics.push({ + severity: "warning", + code: "EVIDENCE_INVALID_SHAPE", + message: "Evidence record does not match the expected schema; ignoring it.", + file: filePath + }); + } + } catch (cause) { + diagnostics.push({ + severity: "warning", + code: "EVIDENCE_UNREADABLE", + message: `Evidence record could not be read: ${cause instanceof Error ? cause.message : String(cause)}`, + file: filePath + }); + } + } + records.sort((a2, b) => a2.evaluatedAt.localeCompare(b.evaluatedAt, "en")); + return { records, diagnostics }; +} +var ACCEPTED_STATUSES = /* @__PURE__ */ new Set(["verified", "manually-accepted"]); +var FUTURE_SKEW_TOLERANCE_MS = 5 * 60 * 1e3; +function evidencePathEscapesRepository(recordedPath) { + if (recordedPath.includes("\0")) return true; + if (import_path7.default.isAbsolute(recordedPath) || /^[A-Za-z]:/.test(recordedPath)) return true; + return recordedPath.split(/[\\/]/).includes(".."); +} +var CHECKBOX_STATE_PREFIX2 = /^([ \t]*[-*+][ \t]+\[)([ xX~-])(\])/; +function sameTaskLineIgnoringState(a2, b) { + const normalize = (text) => { + const match = CHECKBOX_STATE_PREFIX2.exec(text); + if (match === null || match[1] === void 0 || match[3] === void 0) return text; + return `${match[1]} ${match[3]}${text.slice(match[0].length)}`; + }; + return normalize(a2) === normalize(b); +} +function parseTimestamp(value) { + const parsed = Date.parse(value); + return Number.isNaN(parsed) ? void 0 : parsed; +} +function assessEvidenceRecord(record, context) { + const reasons = []; + const notes = []; + const pathViolations = []; + const accepted = ACCEPTED_STATUSES.has(record.status); + const manual = record.status === "manually-accepted"; + if (record.specName !== context.specName) { + reasons.push({ + code: "spec-name-mismatch", + message: `the record names spec "${record.specName}" but was read for "${context.specName}"` + }); + } + for (const file of record.changedFiles) { + if (evidencePathEscapesRepository(file.path)) pathViolations.push(file.path); + } + if (pathViolations.length > 0) { + reasons.push({ + code: "paths-outside-repository", + message: `recorded changed-file paths escape the repository: ${pathViolations.join(", ")}` + }); + } + const evaluatedAtMs = parseTimestamp(record.evaluatedAt); + if (evaluatedAtMs === void 0) { + reasons.push({ + code: "timestamp-unparseable", + message: `evaluatedAt "${record.evaluatedAt}" is not a parseable timestamp` + }); + } else if (evaluatedAtMs > context.now.getTime() + FUTURE_SKEW_TOLERANCE_MS) { + notes.push("the record timestamp lies in the future relative to this machine (clock skew?)"); + } + if (manual && record.manualAcceptance === void 0) { + reasons.push({ + code: "manual-record-malformed", + message: "status is manually-accepted but no manualAcceptance block is recorded" + }); + } + if (reasons.length > 0) { + return { record, accepted, manual, validity: "invalid", reasons, notes, pathViolations }; + } + if (!accepted) { + return { record, accepted, manual, validity: "not-accepted", reasons, notes, pathViolations }; + } + const stale = []; + const currentTask = context.tasks.get(record.taskId); + if (currentTask === void 0) { + stale.push({ + code: "task-missing", + message: `task ${record.taskId} no longer exists in tasks.md` + }); + } else if (record.specContext?.taskFingerprint !== void 0) { + if (record.specContext.taskFingerprint !== currentTask.fingerprint) { + stale.push({ + code: "task-identity-changed", + message: "the task's text, numbering, or requirement references changed since the evidence was recorded" + }); + } + } else if (record.specContext?.taskText !== void 0) { + if (!sameTaskLineIgnoringState(record.specContext.taskText, currentTask.rawLineText)) { + stale.push({ + code: "task-identity-changed", + message: "the task line text changed since the evidence was recorded" + }); + } + } + const specContext = record.specContext; + if (specContext !== void 0) { + const hashChecks = [ + { + recorded: specContext.documentHash, + current: context.approved.documentHash, + code: "document-hash-changed", + what: "the approved requirements/bugfix document" + }, + { + recorded: specContext.designHash, + current: context.approved.designHash, + code: "design-hash-changed", + what: "the approved design" + }, + { + recorded: specContext.tasksPlanHash, + current: context.approved.tasksPlanHash, + code: "plan-hash-changed", + what: "the approved task plan" + } + ]; + for (const { recorded, current, code: code2, what } of hashChecks) { + if (recorded === void 0) continue; + if (current === void 0) { + stale.push({ + code: "stage-not-approved", + message: `${what} is no longer effectively approved` + }); + } else if (recorded !== current) { + stale.push({ code: code2, message: `${what} changed since the evidence was recorded` }); + } + } + } else { + const referenceMs = record.manualAcceptance !== void 0 ? parseTimestamp(record.manualAcceptance.acceptedAt) ?? evaluatedAtMs : evaluatedAtMs; + const timestampChecks = [ + [context.approvedAt.document, "requirements/bugfix"], + [context.approvedAt.design, "design"], + [context.approvedAt.tasks, "tasks"] + ]; + for (const [approvedAt, stage] of timestampChecks) { + if (approvedAt === void 0 || referenceMs === void 0) continue; + const approvedMs = parseTimestamp(approvedAt); + if (approvedMs !== void 0 && approvedMs > referenceMs) { + stale.push({ + code: "approved-after-evidence", + message: `the ${stage} stage was (re)approved after this evidence was recorded` + }); + } + } + } + const headAfter = record.repository.headAfter; + if (headAfter !== void 0 && context.ancestry !== void 0) { + const ancestry = context.ancestry.get(headAfter); + if (ancestry === "not-ancestor") { + stale.push({ + code: "history-diverged", + message: `the recorded commit ${headAfter.slice(0, 12)} is not an ancestor of the current HEAD (history diverged)` + }); + } else if (ancestry === "unknown") { + notes.push( + `the recorded commit ${headAfter.slice(0, 12)} cannot be resolved in this clone (shallow history?)` + ); + } + } + return { + record, + accepted, + manual, + validity: stale.length > 0 ? "stale" : "valid", + reasons: stale, + notes, + pathViolations + }; +} +function assessTaskEvidence(taskId, records, context) { + const all = records.map((record) => assessEvidenceRecord(record, context)); + const acceptedAssessments = all.filter((assessment) => assessment.accepted); + const best = acceptedAssessments[acceptedAssessments.length - 1]; + if (best === void 0) { + return { taskId, all, bucket: "missing" }; + } + const bucket = best.validity === "valid" ? "valid" : best.validity === "stale" ? "stale" : "invalid"; + return { taskId, best, all, bucket }; +} +var GIT_TIMEOUT_MS2 = 3e4; +var SHA_PATTERN = /^[0-9a-f]{4,64}$/i; +async function resolveCommitAncestry(workspaceRoot, shas, signal) { + const result = /* @__PURE__ */ new Map(); + for (const sha of new Set(shas)) { + if (!SHA_PATTERN.test(sha)) { + result.set(sha, "unknown"); + continue; + } + const processResult = await runSafeProcess({ + executable: "git", + argv: ["merge-base", "--is-ancestor", sha, "HEAD"], + cwd: workspaceRoot, + timeoutMs: GIT_TIMEOUT_MS2, + ...signal !== void 0 ? { signal } : {} + }); + if (processResult.status === "ok") { + result.set(sha, "ancestor"); + } else if (processResult.status === "nonzero-exit" && processResult.observation.exitCode === 1) { + result.set(sha, "not-ancestor"); + } else { + result.set(sha, "unknown"); + } + } + return result; +} +function reusableCommandPass(assessments, commandName, currentHeadSha) { + if (currentHeadSha === void 0) return void 0; + for (let i2 = assessments.length - 1; i2 >= 0; i2 -= 1) { + const assessment = assessments[i2]; + if (assessment === void 0 || assessment.validity !== "valid") continue; + const { record } = assessment; + if (record.repository.headAfter !== currentHeadSha) continue; + const command = record.verificationCommands.find( + (candidate) => candidate.name === commandName && candidate.passed + ); + if (command !== void 0) return record; + } + return void 0; +} + +// ../../packages/workflow/dist/index.js +var import_path8 = __toESM(require("path"), 1); +var WINDOWS_RESERVED = /* @__PURE__ */ new Set([ + "con", + "prn", + "aux", + "nul", + ...Array.from({ length: 9 }, (_, i2) => `com${i2 + 1}`), + ...Array.from({ length: 9 }, (_, i2) => `lpt${i2 + 1}`) +]); +var TEMPLATE_PLACEHOLDER_LINES = [ + "Design will be completed after requirements approval.", + "Requirements will be derived and validated after the initial design review.", + "Define implementation tasks after design approval.", + "Define implementation tasks after requirements and design approval." +]; +var TEMPLATE_LINES = new Set(TEMPLATE_PLACEHOLDER_LINES.map((line) => line.toLowerCase())); +var VAGUE_PHRASES = [ + "work correctly", + "works correctly", + "work properly", + "works properly", + "work as expected", + "works as expected", + "as appropriate", + "as needed", + "as necessary", + "if appropriate", + "user-friendly", + "user friendly", + "and so on", + "etc", + "handle", + "handles", + "support", + "supports", + "properly", + "appropriately", + "gracefully", + "seamlessly", + "efficiently", + "robustly", + "intuitively", + "intuitive" +]; +var VAGUE_PATTERN = new RegExp( + `\\b(?:${VAGUE_PHRASES.map((phrase) => phrase.replace(/[-\s]+/g, "[-\\s]+")).join("|")})\\b`, + "gi" +); +function documentStageFor(specType) { + return specType === "bugfix" ? "bugfix" : "requirements"; +} +function workflowShape(specType, mode) { + const documentStage = documentStageFor(specType); + switch (mode) { + case "requirements-first": + return { specType, mode, order: [documentStage, "design", "tasks"], kind: "sequential" }; + case "design-first": + return { specType, mode, order: ["design", documentStage, "tasks"], kind: "sequential" }; + case "quick": + return { specType, mode, order: [documentStage, "design", "tasks"], kind: "parallel-docs" }; + } +} +function stagePrerequisites(shape, stage) { + const index = shape.order.indexOf(stage); + if (index < 0) return []; + if (shape.kind === "sequential") { + return shape.order.slice(0, index); + } + return stage === "tasks" ? shape.order.slice(0, 2) : []; +} +function dependentStages(shape, stage) { + return shape.order.filter((candidate) => stagePrerequisites(shape, candidate).includes(stage)); +} +var DRAFT_STATUS = { + requirements: "REQUIREMENTS_DRAFT", + bugfix: "BUGFIX_DRAFT", + design: "DESIGN_DRAFT", + tasks: "TASKS_DRAFT" +}; +var APPROVED_STATUS = { + requirements: "REQUIREMENTS_APPROVED", + bugfix: "BUGFIX_APPROVED", + design: "DESIGN_APPROVED" + // tasks approved means the whole workflow is READY_FOR_IMPLEMENTATION. +}; +function deriveWorkflowStatus(shape, stages) { + const approved = (stage) => stages[stage]?.status === "approved"; + const allApproved = shape.order.every(approved); + if (allApproved) return "READY_FOR_IMPLEMENTATION"; + if (shape.kind === "parallel-docs") return "READY_FOR_REVIEW"; + for (let i2 = 0; i2 < shape.order.length; i2 += 1) { + const stage = shape.order[i2]; + if (approved(stage)) continue; + if (stages[stage]?.status === "draft") return DRAFT_STATUS[stage]; + const previous = i2 > 0 ? shape.order[i2 - 1] : void 0; + if (previous !== void 0 && approved(previous)) { + return APPROVED_STATUS[previous] ?? DRAFT_STATUS[stage]; + } + return DRAFT_STATUS[stage]; + } + return "READY_FOR_IMPLEMENTATION"; +} +function shortHash(hash) { + return hash === null || hash === void 0 ? "(none)" : `${hash.slice(0, 12)}\u2026`; +} +function resolveStageFile(workspace, stage) { + const relative = stage.file.split("/").join(import_path8.default.sep); + const resolved = import_path8.default.resolve(workspace.rootDir, relative); + const check = import_path8.default.relative(workspace.rootDir, resolved); + if (check.startsWith("..") || import_path8.default.isAbsolute(check)) { + return import_path8.default.join(workspace.rootDir, ".specbridge", "invalid-path", import_path8.default.basename(stage.file)); + } + return resolved; +} +function evaluateWorkflow(workspace, state) { + const shape = workflowShape(state.specType, state.workflowMode); + const diagnostics = []; + const staleStages = []; + const evaluations = /* @__PURE__ */ new Map(); + for (const stage of shape.order) { + const stored = stateStage(state, stage); + if (stored === void 0) continue; + const filePath = resolveStageFile(workspace, stored); + const currentHash = trySha256File(filePath); + const fileExists = currentHash !== void 0; + let effective; + let checkboxProgressOnly = false; + if (stored.status === "approved") { + if (currentHash !== void 0 && currentHash === stored.approvedHash) { + effective = "approved"; + } else if (stage === "tasks" && currentHash !== void 0 && typeof stored.approvedPlanHash === "string" && tryTaskPlanHashOfFile(filePath) === stored.approvedPlanHash) { + effective = "approved"; + checkboxProgressOnly = true; + diagnostics.push({ + severity: "info", + code: "APPROVAL_CHECKBOX_PROGRESS", + message: "tasks.md has checkbox progress since approval; the approved task plan itself is unchanged.", + file: filePath + }); + } else { + effective = "modified-after-approval"; + staleStages.push(stage); + diagnostics.push({ + severity: "warning", + code: "APPROVAL_STALE", + message: currentHash === void 0 ? `${stage} was approved but its file is missing or unreadable (approved hash ${shortHash(stored.approvedHash)}).` : `${stage} was modified after approval (approved ${shortHash(stored.approvedHash)}, current ${shortHash(currentHash)}). Review the changes and re-approve.`, + file: filePath + }); + } + } else { + effective = stored.status; + } + evaluations.set(stage, { + stage, + stored, + effective, + filePath, + fileExists, + ...stored.status === "approved" && currentHash !== void 0 ? { currentHash } : {}, + ...checkboxProgressOnly ? { checkboxProgressOnly } : {}, + prerequisites: stagePrerequisites(shape, stage) + }); + } + const invalidatedStages = []; + for (const stale of staleStages) { + for (const dependent of dependentStages(shape, stale)) { + const evaluation = evaluations.get(dependent); + if (evaluation === void 0) continue; + if (evaluation.effective === "approved") { + evaluation.effective = "stale-prerequisite"; + invalidatedStages.push(dependent); + diagnostics.push({ + severity: "warning", + code: "APPROVAL_DEPENDENT_STALE", + message: `${dependent} approval is now stale because ${stale} changed after it was approved.`, + file: evaluation.filePath + }); + } else if (evaluation.effective === "draft") { + evaluation.effective = "blocked"; + } + } + } + const stagesRecord = {}; + for (const [name, evaluation] of evaluations) stagesRecord[name] = evaluation.stored; + const storedStatus = deriveWorkflowStatus(shape, stagesRecord); + const hasStale = staleStages.length > 0 || invalidatedStages.length > 0; + return { + state, + shape, + stages: shape.order.map((stage) => evaluations.get(stage)).filter((s) => s !== void 0), + storedStatus, + effectiveStatus: hasStale ? "STALE_APPROVAL" : storedStatus, + staleStages, + invalidatedStages, + health: hasStale ? "stale" : "ok", + diagnostics + }; +} +var DEFAULT_MAX_DESCRIPTION_BYTES = 1024 * 1024; + +// ../../packages/drift/dist/index.js +var import_fs13 = require("fs"); +var import_path12 = __toESM(require("path"), 1); +var import_fs14 = require("fs"); +var import_path13 = __toESM(require("path"), 1); +var import_fs15 = require("fs"); +var import_crypto2 = require("crypto"); +var import_path14 = __toESM(require("path"), 1); +var taskEvidenceSchema = external_exports.object({ + taskId: external_exports.string().min(1), + status: external_exports.enum(["recorded", "verified", "rejected"]), + changedFiles: external_exports.array(external_exports.string()).optional(), + commands: external_exports.array( + external_exports.object({ + command: external_exports.string(), + exitCode: external_exports.number() + }) + ).optional(), + approvedBy: external_exports.string().optional(), + notes: external_exports.string().optional(), + verifiedAt: external_exports.string().optional() +}).passthrough(); +var VERIFICATION_POLICY_SCHEMA_VERSION = "1.0.0"; +var BUILT_IN_PROTECTED_PATHS = [ + ".kiro/**", + ".specbridge/state/**", + ".specbridge/config.json", + ".git/**" +]; +var IMMUTABLE_PROTECTED_PATHS = [".git/**"]; +var GLOB_MAX_LENGTH = 512; +function validateGlobPattern(pattern) { + if (pattern.length === 0) return { pattern, reason: "pattern is empty" }; + if (pattern.length > GLOB_MAX_LENGTH) { + return { pattern, reason: `pattern exceeds ${GLOB_MAX_LENGTH} characters` }; + } + if (pattern.includes("\0")) return { pattern, reason: "pattern contains a null byte" }; + if (pattern.includes("\\")) { + return { + pattern, + reason: "pattern contains a backslash; use forward slashes for repository paths" + }; + } + if (pattern.startsWith("/") || /^[A-Za-z]:/.test(pattern)) { + return { pattern, reason: "pattern must be repository-relative, not absolute" }; + } + if (pattern.split("/").includes("..")) { + return { pattern, reason: 'pattern must not contain ".." path traversal segments' }; + } + try { + (0, import_picomatch.default)(pattern); + } catch (cause) { + return { + pattern, + reason: `pattern is not a valid glob: ${cause instanceof Error ? cause.message : String(cause)}` + }; + } + return void 0; +} +var globPatternSchema = external_exports.string().superRefine((pattern, ctx) => { + const issue = validateGlobPattern(pattern); + if (issue !== void 0) { + ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: issue.reason }); + } +}); +var policyRuleOverrideSchema = external_exports.object({ + enabled: external_exports.boolean().default(true), + severity: external_exports.enum(["error", "warning", "info"]).optional() +}).passthrough(); +var verificationPolicySchema = external_exports.object({ + schemaVersion: external_exports.string().regex(/^\d+\.\d+\.\d+$/).default(VERIFICATION_POLICY_SCHEMA_VERSION), + specName: external_exports.string().min(1), + mode: external_exports.enum(["advisory", "strict"]).default("advisory"), + impactAreas: external_exports.array(globPatternSchema).default([]), + protectedPaths: external_exports.array(globPatternSchema).default([]), + /** Names of trusted commands (from `.specbridge/config.json`) that must pass. */ + requiredVerificationCommands: external_exports.array(external_exports.string().min(1)).default([]), + requireVerifiedTaskEvidence: external_exports.boolean().default(false), + requireRequirementTaskLinks: external_exports.boolean().default(false), + requireTestEvidence: external_exports.boolean().default(false), + rules: external_exports.record( + external_exports.string().regex(VERIFICATION_RULE_ID_PATTERN, "rule keys must look like SBV005"), + policyRuleOverrideSchema + ).default({}) +}).passthrough().superRefine((policy, ctx) => { + if (!policy.schemaVersion.startsWith("1.")) { + ctx.addIssue({ + code: external_exports.ZodIssueCode.custom, + path: ["schemaVersion"], + message: `schema version ${policy.schemaVersion} is not supported by this SpecBridge version` + }); + } +}); +function policyDir(workspace) { + return import_path9.default.join(workspace.sidecarDir, "policies"); +} +function policyPath(workspace, specName) { + const resolved = import_path9.default.resolve(policyDir(workspace), `${specName}.json`); + const relative = import_path9.default.relative(workspace.rootDir, resolved); + if (relative.startsWith("..") || import_path9.default.isAbsolute(relative)) { + return import_path9.default.join(policyDir(workspace), "invalid-spec-name.json"); + } + return resolved; +} +function readVerificationPolicy(workspace, specName, explicitPath) { + const filePath = explicitPath !== void 0 ? import_path9.default.resolve(workspace.rootDir, explicitPath) : policyPath(workspace, specName); + if (!(0, import_fs10.existsSync)(filePath)) { + return { path: filePath, exists: false, diagnostics: [] }; + } + let parsed; + try { + parsed = JSON.parse((0, import_fs10.readFileSync)(filePath, "utf8")); + } catch (cause) { + return { + path: filePath, + exists: true, + diagnostics: [ + { + severity: "error", + code: "POLICY_INVALID_JSON", + message: `Verification policy is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}`, + file: filePath + } + ] + }; + } + const result = verificationPolicySchema.safeParse(parsed); + if (!result.success) { + const issues = result.error.issues.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; "); + return { + path: filePath, + exists: true, + diagnostics: [ + { + severity: "error", + code: "POLICY_INVALID_SHAPE", + message: `Verification policy does not match the versioned schema: ${issues}`, + file: filePath + } + ] + }; + } + if (explicitPath === void 0 && result.data.specName !== specName) { + return { + path: filePath, + exists: true, + diagnostics: [ + { + severity: "error", + code: "POLICY_NAME_MISMATCH", + message: `Verification policy records specName "${result.data.specName}" but is stored as ${specName}.json.`, + file: filePath + } + ] + }; + } + return { path: filePath, exists: true, policy: result.data, diagnostics: [] }; +} +function resolveEffectivePolicy(workspace, specName, options = {}) { + const read = readVerificationPolicy(workspace, specName, options.explicitPolicyPath); + const policy = read.policy; + const protectedPaths = [...BUILT_IN_PROTECTED_PATHS]; + for (const pattern of options.globalProtectedPaths ?? []) { + const validated = validateGlobPattern(pattern); + if (validated !== void 0) continue; + const asGlob = /[*?[\]{}]/.test(pattern) ? pattern : `${pattern.replace(/\/+$/, "")}/**`; + if (!protectedPaths.includes(asGlob)) protectedPaths.push(asGlob); + } + for (const pattern of policy?.protectedPaths ?? []) { + if (!protectedPaths.includes(pattern)) protectedPaths.push(pattern); + } + const storedMode = policy?.mode ?? "advisory"; + const strictFromCli = options.strict === true && storedMode !== "strict"; + const mode = options.strict === true ? "strict" : storedMode; + const workspaceRelativePolicyPath = import_path9.default.relative(workspace.rootDir, read.path).split(import_path9.default.sep).join("/"); + return { + specName, + mode, + strictFromCli, + impactAreas: [...policy?.impactAreas ?? []], + protectedPaths, + requiredVerificationCommands: [...policy?.requiredVerificationCommands ?? []], + requireVerifiedTaskEvidence: policy?.requireVerifiedTaskEvidence ?? false, + requireRequirementTaskLinks: policy?.requireRequirementTaskLinks ?? false, + requireTestEvidence: policy?.requireTestEvidence ?? false, + ruleOverrides: { ...policy?.rules ?? {} }, + ...read.exists ? { policyPath: workspaceRelativePolicyPath } : {}, + policyExists: read.exists, + policyDiagnostics: read.diagnostics + }; +} +function compilePathMatchers(patterns) { + const matchers = patterns.map((pattern) => ({ + pattern, + isMatch: (0, import_picomatch.default)(pattern, { dot: true }) + })); + return (candidate) => { + const posix = candidate.split("\\").join("/"); + return matchers.filter(({ isMatch }) => isMatch(posix)).map(({ pattern }) => pattern); + }; +} +var GIT_TIMEOUT_MS = 6e4; +var GIT_MAX_STDOUT = 64 * 1024 * 1024; +async function git(cwd, argv, signal) { + const result = await runSafeProcess({ + executable: "git", + argv, + cwd, + timeoutMs: GIT_TIMEOUT_MS, + maxStdoutBytes: GIT_MAX_STDOUT, + maxStderrBytes: 1024 * 1024, + ...signal !== void 0 ? { signal } : {} + }); + return { + ok: result.status === "ok", + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.observation.exitCode + }; +} +function isSafeGitRef(ref) { + if (ref.length === 0 || ref.length > 256) return false; + if (ref.startsWith("-")) return false; + if (/[\s\0:?*[\\]/.test(ref)) return false; + return true; +} +function statusFor2(code2) { + switch (code2.charAt(0)) { + case "A": + return "added"; + case "M": + case "T": + return "modified"; + case "D": + return "deleted"; + case "R": + return "renamed"; + case "C": + return "copied"; + default: + return void 0; + } +} +function parseNameStatusZ(raw) { + const changes = []; + const tokens = raw.split("\0"); + for (let i2 = 0; i2 < tokens.length; i2 += 1) { + const code2 = tokens[i2]; + if (code2 === void 0 || code2.length === 0) continue; + const changeType = statusFor2(code2); + if (changeType === void 0) { + i2 += 1; + continue; + } + if (changeType === "renamed" || changeType === "copied") { + const oldPath = tokens[i2 + 1]; + const newPath = tokens[i2 + 2]; + i2 += 2; + if (oldPath === void 0 || newPath === void 0 || newPath.length === 0) continue; + changes.push({ + path: newPath, + oldPath, + changeType, + binary: false, + symlinkOutsideRepository: false + }); + } else { + const filePath = tokens[i2 + 1]; + i2 += 1; + if (filePath === void 0 || filePath.length === 0) continue; + changes.push({ path: filePath, changeType, binary: false, symlinkOutsideRepository: false }); + } + } + return changes; +} +function parseNumstatZ(raw) { + const stats = /* @__PURE__ */ new Map(); + const tokens = raw.split("\0"); + for (let i2 = 0; i2 < tokens.length; i2 += 1) { + const token = tokens[i2]; + if (token === void 0 || token.length === 0) continue; + const match = /^(-|\d+)\t(-|\d+)\t(.*)$/s.exec(token); + if (match === null) continue; + const insertions = match[1] === "-" ? void 0 : Number(match[1]); + const deletions = match[2] === "-" ? void 0 : Number(match[2]); + const binary = match[1] === "-" && match[2] === "-"; + let filePath = match[3] ?? ""; + if (filePath.length === 0) { + const newPath = tokens[i2 + 2]; + i2 += 2; + if (newPath === void 0) continue; + filePath = newPath; + } + stats.set(filePath, { + ...insertions !== void 0 ? { insertions } : {}, + ...deletions !== void 0 ? { deletions } : {}, + binary + }); + } + return stats; +} +function mergeNumstat(files, stats) { + for (const file of files) { + const stat = stats.get(file.path); + if (stat === void 0) continue; + if (stat.insertions !== void 0) file.insertions = stat.insertions; + if (stat.deletions !== void 0) file.deletions = stat.deletions; + file.binary = stat.binary; + } +} +function sniffBinary(absolutePath) { + let fd; + try { + fd = (0, import_fs11.openSync)(absolutePath, "r"); + const buffer = Buffer.alloc(8e3); + const bytesRead = (0, import_fs11.readSync)(fd, buffer, 0, buffer.length, 0); + return buffer.subarray(0, bytesRead).includes(0); + } catch { + return false; + } finally { + if (fd !== void 0) (0, import_fs11.closeSync)(fd); + } +} +function flagSymlinkEscapes(repoRoot, files) { + const resolvedRoot = (() => { + try { + return (0, import_fs11.realpathSync)(repoRoot); + } catch { + return import_path10.default.resolve(repoRoot); + } + })(); + for (const file of files) { + if (file.changeType === "deleted") continue; + const absolute = import_path10.default.join(repoRoot, file.path.split("/").join(import_path10.default.sep)); + try { + const stats = (0, import_fs11.lstatSync)(absolute); + if (!stats.isSymbolicLink()) continue; + const target = (0, import_fs11.realpathSync)(absolute); + const relative = import_path10.default.relative(resolvedRoot, target); + if (relative.startsWith("..") || import_path10.default.isAbsolute(relative)) { + file.symlinkOutsideRepository = true; + } + } catch { + } + } +} +function sortFiles(files) { + return files.sort((a2, b) => a2.path.localeCompare(b.path, "en")); +} +async function isShallow(repoRoot, signal) { + const result = await git(repoRoot, ["rev-parse", "--is-shallow-repository"], signal); + return result.ok && result.stdout.trim() === "true"; +} +async function resolveSha(repoRoot, ref, signal) { + const result = await git(repoRoot, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], signal); + return result.ok ? result.stdout.trim() : void 0; +} +async function resolveComparison(repoRoot, request, options = {}) { + const signal = options.signal; + const descriptor = { + mode: request.mode, + base: request.mode === "diff" ? request.base : null, + head: request.mode === "diff" ? request.head : null, + baseSha: null, + headSha: null, + label: request.mode === "diff" ? `${request.base}...${request.head}` : request.mode === "working-tree" ? "working tree vs HEAD" : "staged changes vs HEAD" + }; + const failed = (reason, message, shallow = false) => ({ + ok: false, + descriptor, + changedFiles: [], + failure: { reason, message, shallow } + }); + const inside = await git(repoRoot, ["rev-parse", "--is-inside-work-tree"], signal); + if (!inside.ok || inside.stdout.trim() !== "true") { + return failed( + "not-a-repository", + `${repoRoot} is not a usable git work tree; drift verification needs the repository history.` + ); + } + if (request.mode === "diff") { + for (const [role, ref] of [ + ["base", request.base], + ["head", request.head] + ]) { + if (!isSafeGitRef(ref)) { + return failed( + "invalid-ref", + `The ${role} ref "${ref}" is not a valid git ref (refs must not start with "-" or contain whitespace).` + ); + } + } + const baseSha = await resolveSha(repoRoot, request.base, signal); + const headSha2 = await resolveSha(repoRoot, request.head, signal); + const shallow = await isShallow(repoRoot, signal); + if (baseSha === void 0 || headSha2 === void 0) { + const missing = baseSha === void 0 ? request.base : request.head; + return failed( + "ref-not-found", + `Git ref "${missing}" cannot be resolved in this clone.` + (shallow ? " The clone is shallow \u2014 check out with full history (actions/checkout@v4 with fetch-depth: 0) or fetch the missing ref explicitly." : " Fetch it first (SpecBridge never fetches automatically)."), + shallow + ); + } + descriptor.baseSha = baseSha; + descriptor.headSha = headSha2; + const mergeBase = await git(repoRoot, ["merge-base", baseSha, headSha2], signal); + if (!mergeBase.ok) { + return failed( + "no-merge-base", + `No merge base exists between ${request.base} and ${request.head} in this clone.` + (shallow ? " The clone is shallow \u2014 check out with full history (actions/checkout@v4 with fetch-depth: 0)." : ""), + shallow + ); + } + const nameStatus2 = await git( + repoRoot, + ["diff", "--relative", "--name-status", "-z", "-M", `${baseSha}...${headSha2}`], + signal + ); + if (!nameStatus2.ok) { + return failed("ref-not-found", `git diff failed: ${nameStatus2.stderr.trim()}`); + } + const files2 = parseNameStatusZ(nameStatus2.stdout); + const numstat2 = await git( + repoRoot, + ["diff", "--relative", "--numstat", "-z", "-M", `${baseSha}...${headSha2}`], + signal + ); + if (numstat2.ok) mergeNumstat(files2, parseNumstatZ(numstat2.stdout)); + flagSymlinkEscapes(repoRoot, files2); + return { ok: true, descriptor, changedFiles: sortFiles(files2) }; + } + const headSha = await resolveSha(repoRoot, "HEAD", signal); + if (headSha === void 0) { + return failed( + "no-commits", + "The repository has no commits yet; there is nothing to compare the working tree against." + ); + } + descriptor.headSha = headSha; + descriptor.baseSha = headSha; + if (request.mode === "staged") { + const nameStatus2 = await git(repoRoot, ["diff", "--relative", "--name-status", "-z", "-M", "--cached"], signal); + if (!nameStatus2.ok) { + return failed("git-unavailable", `git diff --cached failed: ${nameStatus2.stderr.trim()}`); + } + const files2 = parseNameStatusZ(nameStatus2.stdout); + const numstat2 = await git(repoRoot, ["diff", "--relative", "--numstat", "-z", "-M", "--cached"], signal); + if (numstat2.ok) mergeNumstat(files2, parseNumstatZ(numstat2.stdout)); + flagSymlinkEscapes(repoRoot, files2); + return { ok: true, descriptor, changedFiles: sortFiles(files2) }; + } + const nameStatus = await git(repoRoot, ["diff", "--relative", "--name-status", "-z", "-M", "HEAD"], signal); + if (!nameStatus.ok) { + return failed("git-unavailable", `git diff HEAD failed: ${nameStatus.stderr.trim()}`); + } + const files = parseNameStatusZ(nameStatus.stdout); + const numstat = await git(repoRoot, ["diff", "--relative", "--numstat", "-z", "-M", "HEAD"], signal); + if (numstat.ok) mergeNumstat(files, parseNumstatZ(numstat.stdout)); + const untracked = await git( + repoRoot, + ["ls-files", "--others", "--exclude-standard", "-z"], + signal + ); + if (untracked.ok) { + const known = new Set(files.map((file) => file.path)); + for (const token of untracked.stdout.split("\0")) { + if (token.length === 0 || known.has(token)) continue; + const absolute = import_path10.default.join(repoRoot, token.split("/").join(import_path10.default.sep)); + files.push({ + path: token, + changeType: "untracked", + binary: sniffBinary(absolute), + symlinkOutsideRepository: false + }); + } + } + flagSymlinkEscapes(repoRoot, files); + return { ok: true, descriptor, changedFiles: sortFiles(files) }; +} +var GIT_TIMEOUT_MS22 = 3e4; +function createRunCaches() { + return { baseContent: /* @__PURE__ */ new Map(), ancestry: /* @__PURE__ */ new Map() }; +} +function makeBaseContentReader(workspace, comparison, caches, signal) { + return async (repoPath) => { + if (caches.baseContent.has(repoPath)) return caches.baseContent.get(repoPath); + const baseSha = comparison.descriptor.baseSha; + if (baseSha === null) { + caches.baseContent.set(repoPath, void 0); + return void 0; + } + const result = await runSafeProcess({ + executable: "git", + argv: ["show", `${baseSha}:${repoPath}`], + cwd: workspace.rootDir, + timeoutMs: GIT_TIMEOUT_MS22, + maxStdoutBytes: 16 * 1024 * 1024, + ...signal !== void 0 ? { signal } : {} + }); + const content = result.status === "ok" ? result.stdout : void 0; + caches.baseContent.set(repoPath, content); + return content; + }; +} +async function resolveAncestryCached(workspace, shas, caches, signal) { + const missing = shas.filter((sha) => !caches.ancestry.has(sha)); + if (missing.length > 0) { + const resolved = await resolveCommitAncestry(workspace.rootDir, missing, signal); + for (const [sha, ancestry] of resolved) caches.ancestry.set(sha, ancestry); + } + const view = /* @__PURE__ */ new Map(); + for (const sha of shas) { + const ancestry = caches.ancestry.get(sha); + if (ancestry !== void 0) view.set(sha, ancestry); + } + return view; +} +function specMatchReasons(specName, policy, validEvidencePaths, designPathReferences, file) { + const reasons = []; + const posixPath = file.path; + if (posixPath.startsWith(`.kiro/specs/${specName}/`)) { + reasons.push("spec files"); + } + if (posixPath === `.specbridge/state/specs/${specName}.json`) { + reasons.push("sidecar state"); + } + if (posixPath === `.specbridge/policies/${specName}.json`) { + reasons.push("verification policy"); + } + if (policy.impactAreas.length > 0) { + const matched = compilePathMatchers(policy.impactAreas)(posixPath); + for (const pattern of matched) reasons.push(`impact area ${pattern}`); + } + if (validEvidencePaths.has(posixPath)) { + reasons.push("task evidence"); + } + for (const reference of designPathReferences) { + if (!reference.isGlob && reference.path === posixPath) { + reasons.push("design reference"); + break; + } + } + return reasons; +} +function readSpecEvidenceRecords(workspace, specName) { + const byTask = /* @__PURE__ */ new Map(); + let invalidRecordCount = 0; + const specDir = import_path11.default.join(workspace.sidecarDir, "evidence", specName); + if ((0, import_fs12.existsSync)(specDir)) { + const taskDirs = (0, import_fs12.readdirSync)(specDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((a2, b) => a2.localeCompare(b, "en")); + for (const taskDir of taskDirs) { + const { records, diagnostics } = listTaskEvidence(workspace, specName, taskDir); + invalidRecordCount += diagnostics.length; + if (records.length === 0) continue; + const taskId = records[0]?.taskId ?? taskDir; + const list = byTask.get(taskId) ?? []; + list.push(...records); + byTask.set(taskId, list); + } + } + return { byTask, invalidRecordCount }; +} +async function buildSpecVerificationContext(options) { + const { workspace, folder, comparison, caches, now } = options; + const spec = analyzeSpec(workspace, folder); + const evaluation = spec.state !== void 0 ? evaluateWorkflow(workspace, spec.state) : void 0; + const policy = resolveEffectivePolicy(workspace, folder.name, { + globalProtectedPaths: options.config.execution.protectedPaths, + ...options.strict !== void 0 ? { strict: options.strict } : {}, + ...options.explicitPolicyPath !== void 0 ? { explicitPolicyPath: options.explicitPolicyPath } : {} + }); + const requirementsDocument = spec.documents.requirements; + const catalog = spec.requirements !== void 0 ? buildRequirementCatalog(spec.requirements, requirementsDocument) : { entries: [], requirements: [], byCanonical: /* @__PURE__ */ new Map() }; + const tasksDocument = spec.documents.tasks; + const references = tasksDocument !== void 0 && spec.tasks !== void 0 ? extractTaskRequirementReferences(tasksDocument, spec.tasks) : []; + const designDocument = spec.documents.design; + const designPathReferences = designDocument !== void 0 ? extractPathReferences(designDocument) : []; + const approved = {}; + const approvedAt = {}; + if (spec.state !== void 0 && evaluation !== void 0) { + const documentStageName = spec.state.specType === "bugfix" ? "bugfix" : "requirements"; + const documentStage = stateStage(spec.state, documentStageName); + const designStage = stateStage(spec.state, "design"); + const tasksStage = stateStage(spec.state, "tasks"); + if (documentStage?.approvedAt != null) approvedAt.document = documentStage.approvedAt; + if (designStage?.approvedAt != null) approvedAt.design = designStage.approvedAt; + if (tasksStage?.approvedAt != null) approvedAt.tasks = tasksStage.approvedAt; + const effective = (stage) => evaluation.stages.find((s) => s.stage === stage)?.effective === "approved"; + if (effective(documentStageName) && documentStage?.approvedHash != null) { + approved.documentHash = documentStage.approvedHash; + } + if (effective("design") && designStage?.approvedHash != null) { + approved.designHash = designStage.approvedHash; + } + if (effective("tasks") && tasksStage !== void 0) { + const planHash = typeof tasksStage.approvedPlanHash === "string" ? tasksStage.approvedPlanHash : tryTaskPlanHashOfFile( + import_path11.default.join(workspace.rootDir, tasksStage.file.split("/").join(import_path11.default.sep)) + ); + if (planHash !== void 0) approved.tasksPlanHash = planHash; + } + } + const currentTasks = /* @__PURE__ */ new Map(); + if (spec.tasks !== void 0 && tasksDocument !== void 0) { + for (const task of spec.tasks.allTasks) { + currentTasks.set(task.id, { + fingerprint: taskFingerprint(task), + title: task.title, + rawLineText: tasksDocument.lineAt(task.line).text, + state: task.state + }); + } + } + const rawEvidence = readSpecEvidenceRecords(workspace, folder.name); + const freshness = { + specName: folder.name, + approved, + approvedAt, + tasks: currentTasks, + now + }; + const recordedShas = /* @__PURE__ */ new Set(); + for (const records of rawEvidence.byTask.values()) { + for (const record of records) { + if (record.repository.headAfter !== void 0) recordedShas.add(record.repository.headAfter); + } + } + if (recordedShas.size > 0 && comparison.descriptor.headSha !== null) { + freshness.ancestry = await resolveAncestryCached( + workspace, + [...recordedShas], + caches, + options.signal + ); + } + const assessmentsByTask = /* @__PURE__ */ new Map(); + const flattened = []; + for (const [taskId, records] of rawEvidence.byTask) { + const assessment = assessTaskEvidence(taskId, records, freshness); + assessmentsByTask.set(taskId, assessment); + flattened.push(...assessment.all); + } + const evidence = { + assessmentsByTask, + flattened, + invalidRecordCount: rawEvidence.invalidRecordCount + }; + const validEvidencePaths = /* @__PURE__ */ new Set(); + for (const assessment of evidence.assessmentsByTask.values()) { + const best = assessment.best; + if (best === void 0 || best.validity !== "valid") continue; + for (const file of best.record.changedFiles) validEvidencePaths.add(file.path); + } + const specChangedFiles = comparison.changedFiles.filter( + (file) => specMatchReasons(folder.name, policy, validEvidencePaths, designPathReferences, file).length > 0 + ); + return { + workspace, + specName: folder.name, + spec, + selectionMode: options.selectionMode, + ...evaluation !== void 0 ? { evaluation } : {}, + policy, + comparison, + changedFiles: comparison.changedFiles, + specChangedFiles, + traceability: { catalog, references, designPathReferences }, + evidence, + freshness, + matchedBy: options.matchedBy ?? [], + readBaseContent: makeBaseContentReader(workspace, comparison, caches, options.signal), + now + }; +} +async function orchestrateVerificationCommands(options) { + const configured = options.config.verification.commands; + const configuredByName = new Map( + configured.map((command) => [command.name, command]) + ); + const requiringSpecs = /* @__PURE__ */ new Map(); + for (const [specName, names] of options.requiredBySpec) { + for (const name of names) { + const list = requiringSpecs.get(name) ?? []; + list.push(specName); + requiringSpecs.set(name, list); + } + } + for (const list of requiringSpecs.values()) list.sort((a2, b) => a2.localeCompare(b, "en")); + const missingRequired = [...requiringSpecs.entries()].filter(([name]) => !configuredByName.has(name)).map(([name, specs]) => ({ name, requiredBySpecs: specs })).sort((a2, b) => a2.name.localeCompare(b.name, "en")); + const mode = options.runVerification === true ? "all" : options.runVerification === false ? "none" : requiringSpecs.size > 0 ? "required-only" : "none"; + const toRun = mode === "all" ? [...configured] : mode === "required-only" ? configured.filter((command) => requiringSpecs.has(command.name)) : []; + const commands = []; + if (toRun.length > 0) { + const runResult = await runVerificationCommands(options.workspaceRoot, toRun, { + ...options.signal !== void 0 ? { signal: options.signal } : {}, + ...options.onProgress !== void 0 ? { onCommandStart: (command) => options.onProgress?.(`Running ${command.name}\u2026`) } : {}, + ...options.onCommandFinished !== void 0 ? { onCommandFinished: options.onCommandFinished } : {} + }); + for (const result of runResult.commands) { + commands.push({ + name: result.name, + argv: [...result.argv], + required: result.required, + disposition: "executed", + passed: result.passed, + timedOut: result.timedOut, + spawnFailed: result.status === "spawn-failed", + exitCode: result.exitCode ?? null, + durationMs: result.durationMs, + requiredBySpecs: requiringSpecs.get(result.name) ?? [], + result + }); + } + } + for (const [name, specs] of [...requiringSpecs.entries()].sort( + (a2, b) => a2[0].localeCompare(b[0], "en") + )) { + const configuredCommand = configuredByName.get(name); + if (configuredCommand === void 0) continue; + if (commands.some((command) => command.name === name)) continue; + let reusedFrom; + for (const specName of specs) { + const assessments = options.evidenceBySpec.get(specName) ?? []; + const record = reusableCommandPass(assessments, name, options.headSha); + if (record !== void 0) { + reusedFrom = record.runId; + break; + } + } + commands.push({ + name, + argv: [...configuredCommand.argv], + required: true, + disposition: reusedFrom !== void 0 ? "reused-evidence" : "not-run", + passed: reusedFrom !== void 0, + timedOut: false, + spawnFailed: false, + exitCode: null, + durationMs: null, + ...reusedFrom !== void 0 ? { reusedFromRunId: reusedFrom } : {}, + requiredBySpecs: specs + }); + } + commands.sort((a2, b) => a2.name.localeCompare(b.name, "en")); + return { mode, commands, missingRequired }; +} +function resolveRuleConfig(rule, policy) { + const override = policy.ruleOverrides[rule.id]; + const severity = override?.severity ?? rule.defaultSeverity[policy.mode]; + return { + enabled: override?.enabled ?? true, + severity, + overridden: override?.severity !== void 0 + }; +} +var SEVERITY_ORDER = { error: 0, warning: 1, info: 2 }; +function resolveGlobalRuleConfig(rule, policies) { + if (policies.length === 0) { + return { enabled: true, severity: rule.defaultSeverity.advisory, overridden: false }; + } + const resolved = policies.map((policy) => resolveRuleConfig(rule, policy)); + const enabled = resolved.some((config) => config.enabled); + const strictest = resolved.reduce( + (best, config) => SEVERITY_ORDER[config.severity] < SEVERITY_ORDER[best.severity] ? config : best + ); + return { enabled, severity: strictest.severity, overridden: strictest.overridden }; +} +function makeDiagnostic(input) { + const file = input.file === null || input.file === void 0 ? null : { + path: input.file.path, + line: input.file.line ?? null, + column: input.file.column ?? null + }; + return { + schemaVersion: VERIFICATION_DIAGNOSTIC_SCHEMA_VERSION, + ruleId: input.rule.id, + title: input.rule.title, + severity: input.severity, + category: input.rule.category, + message: input.message, + remediation: input.remediation ?? input.rule.resolution, + specName: input.specName ?? null, + taskId: input.taskId ?? null, + requirementId: input.requirementId ?? null, + file, + evidence: input.evidence ?? {}, + confidence: input.confidence ?? input.rule.confidence + }; +} +async function evaluateSpecRules(rules, context) { + const diagnostics = []; + const disabledRules = []; + for (const rule of rules) { + if (rule.scope !== "spec") continue; + const resolved = resolveRuleConfig(rule, context.policy); + if (!resolved.enabled) { + disabledRules.push(rule.id); + continue; + } + diagnostics.push(...await rule.evaluate(context, resolved)); + } + return { diagnostics, disabledRules }; +} +async function evaluateGlobalRules(rules, context) { + const policies = context.specContexts.map((spec) => spec.policy); + const diagnostics = []; + const disabledRules = []; + for (const rule of rules) { + if (rule.scope !== "global") continue; + const resolved = resolveGlobalRuleConfig(rule, policies); + if (!resolved.enabled) { + disabledRules.push(rule.id); + continue; + } + diagnostics.push(...await rule.evaluate(context, resolved)); + } + return { diagnostics, disabledRules }; +} +function repoRelative(workspace, absolutePath) { + return import_path12.default.relative(workspace.rootDir, absolutePath).split(import_path12.default.sep).join("/"); +} +function isSpecInfraPath(candidate) { + return candidate === ".git" || candidate.startsWith(".git/") || candidate.startsWith(".kiro/") || candidate.startsWith(".specbridge/"); +} +function doneLeafTasks(context) { + const model = context.spec.tasks; + if (model === void 0) return []; + return model.allTasks.filter((task) => task.children.length === 0 && task.state === "done"); +} +function tasksFilePath(context) { + const filePath = context.spec.documents.tasks?.filePath; + return filePath !== void 0 ? repoRelative(context.workspace, filePath) : void 0; +} +function taskFileLocation(context, task) { + const filePath = tasksFilePath(context); + return filePath !== void 0 ? { path: filePath, line: task.line + 1 } : null; +} +function ownWorkflowPaths(specName, candidate) { + return candidate.startsWith(`.kiro/specs/${specName}/`) || candidate === `.specbridge/state/specs/${specName}.json` || candidate === `.specbridge/policies/${specName}.json`; +} +var TEST_PATH_PATTERN = /(^|\/)(tests?|__tests__)(\/|$)|\.(test|spec)\.[a-z0-9]+$/i; +var TEST_COMMAND_PATTERN = /test/i; +var sbv001 = { + id: "SBV001", + title: "Required spec file missing", + category: "workspace", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A feature spec is missing requirements.md, design.md, or tasks.md, or a bugfix spec is missing bugfix.md, design.md, or tasks.md.", + resolution: "Create the missing document (specbridge spec new scaffolds Kiro-compatible files), or remove the incomplete spec folder.", + evaluate(context, resolved) { + const type = context.spec.classification.type; + if (type !== "feature" && type !== "bugfix") return []; + const required = type === "bugfix" ? ["bugfix.md", "design.md", "tasks.md"] : ["requirements.md", "design.md", "tasks.md"]; + const present = new Set(context.spec.folder.files.map((file) => file.fileName.toLowerCase())); + return required.filter((fileName) => !present.has(fileName)).map( + (fileName) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The ${type} spec "${context.specName}" is missing ${fileName}.`, + specName: context.specName, + file: { path: `.kiro/specs/${context.specName}/${fileName}` }, + evidence: { specType: type, missingFile: fileName } + }) + ); + } +}; +var sbv002 = { + id: "SBV002", + title: "Spec approval stale", + category: "approval", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "An approved stage document no longer matches its recorded approval hash. For the tasks stage, checkbox-only progress is NOT stale (hash semantics v2); any other byte change is.", + resolution: "Review the changed document and re-approve the stage (specbridge spec approve --stage ), or restore the approved content.", + evaluate(context, resolved) { + if (context.evaluation === void 0) return []; + return context.evaluation.stages.filter((stage) => stage.effective === "modified-after-approval").map( + (stage) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The approved ${stage.stage} stage of "${context.specName}" changed after approval (approved hash ${stage.stored.approvedHash?.slice(0, 12) ?? "(none)"}\u2026, current ${stage.currentHash?.slice(0, 12) ?? "missing"}\u2026).`, + specName: context.specName, + file: { path: stage.stored.file }, + evidence: { + stage: stage.stage, + approvedHash: stage.stored.approvedHash, + currentHash: stage.currentHash ?? null, + approvedAt: stage.stored.approvedAt + } + }) + ); + } +}; +var sbv003 = { + id: "SBV003", + title: "Approval prerequisite invalid", + category: "approval", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A later-stage approval depends on an earlier stage that is stale, revoked, or was never approved.", + resolution: "Re-approve the earlier stage first, then re-approve the dependent stage \u2014 approvals form a chain.", + evaluate(context, resolved) { + if (context.evaluation === void 0) return []; + const diagnostics = []; + for (const stage of context.evaluation.stages) { + if (stage.stored.status !== "approved") continue; + if (stage.effective === "stale-prerequisite") { + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The ${stage.stage} approval of "${context.specName}" is invalid because an earlier stage changed after it was approved.`, + specName: context.specName, + file: { path: stage.stored.file }, + evidence: { stage: stage.stage, prerequisites: stage.prerequisites } + }) + ); + continue; + } + const unapproved = stage.prerequisites.filter((prerequisite) => { + const evaluation = context.evaluation?.stages.find((s) => s.stage === prerequisite); + return evaluation !== void 0 && evaluation.stored.status !== "approved"; + }); + if (unapproved.length > 0) { + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The ${stage.stage} stage of "${context.specName}" is approved although ${unapproved.join(" and ")} ${unapproved.length === 1 ? "is" : "are"} not.`, + specName: context.specName, + file: { path: stage.stored.file }, + evidence: { stage: stage.stage, unapprovedPrerequisites: unapproved } + }) + ); + } + } + return diagnostics; + } +}; +var sbv004 = { + id: "SBV004", + title: "Completed task lacks verified evidence", + category: "evidence", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A task checkbox is [x] but no verified or manually accepted evidence record exists for it. Error severity when the policy sets requireVerifiedTaskEvidence.", + resolution: "Run the task through specbridge spec run (which records evidence), accept it explicitly with specbridge spec accept-task, or uncheck the box.", + evaluate(context, resolved) { + const severity = context.policy.requireVerifiedTaskEvidence ? "error" : resolved.severity; + return doneLeafTasks(context).filter((task) => { + const assessment = context.evidence.assessmentsByTask.get(task.id); + return assessment === void 0 || assessment.bucket === "missing" || assessment.bucket === "invalid"; + }).map((task) => { + const assessment = context.evidence.assessmentsByTask.get(task.id); + const invalidOnly = assessment?.bucket === "invalid"; + return makeDiagnostic({ + rule: this, + severity, + message: invalidOnly ? `Task ${task.id} ("${task.title}") is checked but its only evidence records are structurally invalid.` : `Task ${task.id} ("${task.title}") is checked but has no verified or manually accepted evidence.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { + evidenceRequired: context.policy.requireVerifiedTaskEvidence, + checkboxState: task.stateChar, + invalidRecordsOnly: invalidOnly + } + }); + }); + } +}; +var sbv005 = { + id: "SBV005", + title: "Changed file outside declared impact area", + category: "impact-area", + defaultSeverity: { advisory: "warning", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "Verifying a single named spec whose policy declares impact areas: a changed repository file matches none of them. (In --changed/--all runs, cross-spec coverage is reported by SBV014 instead.)", + resolution: "Revert the unrelated change, split it into its own change set, or extend the impact areas in the spec verification policy after review.", + evaluate(context, resolved) { + if (context.selectionMode !== "single") return []; + if (context.policy.impactAreas.length === 0) return []; + const matcher = compilePathMatchers(context.policy.impactAreas); + return context.changedFiles.filter((file) => !isSpecInfraPath(file.path)).filter((file) => matcher(file.path).length === 0).map( + (file) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${file.path} is outside the impact areas declared for ${context.specName}.`, + specName: context.specName, + file: { path: file.path }, + evidence: { + changedPath: file.path, + changeType: file.changeType, + declaredImpactAreas: context.policy.impactAreas + } + }) + ); + } +}; +var sbv006 = { + id: "SBV006", + title: "Protected path modified", + category: "protected-path", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "The comparison touches a protected path (.kiro/**, .specbridge/state/**, .specbridge/config.json, .git/**, or configured additions). The verified specs\u2019 own spec files, sidecar state, and policy are exempt \u2014 changing them is spec authoring, which the approval rules govern \u2014 and checkbox-only tasks.md progress is always exempt.", + resolution: "Remove the protected-path change from this change set, or \u2014 if this is deliberate spec authoring for a spec not under verification \u2014 verify that spec too.", + async evaluate(context, resolved) { + if (!context.comparison.ok) return []; + const selectedSpecs = context.specContexts.map((spec) => spec.specName); + const patterns = /* @__PURE__ */ new Set(); + for (const spec of context.specContexts) { + for (const pattern of spec.policy.protectedPaths) patterns.add(pattern); + } + if (patterns.size === 0) { + for (const pattern of [".kiro/**", ".specbridge/state/**", ".specbridge/config.json", ".git/**"]) { + patterns.add(pattern); + } + } + const matcher = compilePathMatchers([...patterns]); + const immutableMatcher = compilePathMatchers([...IMMUTABLE_PROTECTED_PATHS]); + const diagnostics = []; + for (const file of context.comparison.changedFiles) { + const matched = matcher(file.path); + if (matched.length === 0) continue; + const owningSpec = selectedSpecs.find((specName) => ownWorkflowPaths(specName, file.path)); + if (owningSpec !== void 0) { + let note = "spec-authoring change of a verified spec"; + if (file.path === `.kiro/specs/${owningSpec}/tasks.md` && (file.changeType === "modified" || file.changeType === "renamed")) { + const specContext = context.specContexts.find((spec) => spec.specName === owningSpec); + const checkboxOnly = specContext !== void 0 ? await isCheckboxOnlyChange(specContext, file.path) : false; + note = checkboxOnly ? "checkbox-only task progress (expected)" : "task plan edited (see SBV023)"; + } + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: "info", + message: `${file.path} changed \u2014 ${note}.`, + specName: owningSpec, + file: { path: file.path }, + evidence: { matchedPatterns: matched, exempt: true, note } + }) + ); + continue; + } + const severity = immutableMatcher(file.path).length > 0 ? "error" : resolved.severity; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity, + message: `Protected path ${file.path} was ${file.changeType === "deleted" ? "deleted" : "modified"} by this change set.`, + file: { path: file.path }, + evidence: { + matchedPatterns: matched, + changeType: file.changeType, + selectedSpecs + } + }) + ); + } + return diagnostics; + } +}; +async function isCheckboxOnlyChange(context, repoPath) { + const baseContent = await context.readBaseContent(repoPath); + if (baseContent === void 0) return false; + const currentDocument = context.spec.documents.tasks; + if (currentDocument === void 0) return false; + const baseDocument = MarkdownDocument.fromText(baseContent); + return normalizedTaskPlanText(baseDocument) === normalizedTaskPlanText(currentDocument); +} +var sbv007 = { + id: "SBV007", + title: "Requirement has no implementation task", + category: "requirements", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "An identifiable requirement ID is referenced by no task \u2014 neither directly nor through any of its acceptance criteria. Error severity when the policy sets requireRequirementTaskLinks.", + resolution: "Add an implementation task referencing the requirement (e.g. a _Requirements: 1.2_ detail line), or remove the requirement if it is obsolete.", + evaluate(context, resolved) { + const { catalog, references } = context.traceability; + if (catalog.requirements.length === 0 || context.spec.tasks === void 0) return []; + const severity = context.policy.requireRequirementTaskLinks ? "error" : resolved.severity; + const referenced = new Set( + references.map((reference) => reference.canonical).filter((canonical) => canonical !== void 0) + ); + const requirementsFile = context.spec.documents.requirements?.filePath; + const filePath = requirementsFile !== void 0 ? repoRelative(context.workspace, requirementsFile) : void 0; + return catalog.requirements.filter((requirement) => { + for (const canonical of referenced) { + if (canonical === requirement.canonical) return false; + const entry = catalog.byCanonical.get(canonical); + if (entry !== void 0 && entry.requirementCanonical === requirement.canonical) { + return false; + } + } + return true; + }).map( + (requirement) => makeDiagnostic({ + rule: this, + severity, + message: `Requirement ${requirement.displayId}${requirement.title !== void 0 ? ` ("${requirement.title}")` : ""} is not referenced by any task.`, + specName: context.specName, + requirementId: requirement.displayId, + file: filePath !== void 0 ? { path: filePath, line: requirement.line + 1 } : null, + evidence: { + canonicalId: requirement.canonical, + criteria: catalog.entries.filter( + (entry) => entry.kind === "criterion" && entry.requirementCanonical === requirement.canonical + ).map((entry) => entry.displayId) + } + }) + ); + } +}; +var sbv008 = { + id: "SBV008", + title: "Task has no requirement reference", + category: "tasks", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "heuristic", + scope: "spec", + triggeredWhen: "Requirement linking is in use in this tasks document, but a leaf implementation task carries no requirement reference. Clearly non-requirement work (documentation, release, cleanup chores) is excluded.", + resolution: "Add a _Requirements: \u2026_ detail line to the task, or leave it unlinked deliberately if it is supporting work.", + evaluate(context, resolved) { + const model = context.spec.tasks; + if (model === void 0) return []; + const { references, catalog } = context.traceability; + if (references.length === 0 || catalog.requirements.length === 0) return []; + const tasksWithReferences = new Set(references.map((reference) => reference.taskId)); + return model.allTasks.filter( + (task) => task.children.length === 0 && !tasksWithReferences.has(task.id) && !isLikelyNonRequirementTask(task) + ).map( + (task) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Task ${task.id} ("${task.title}") has no requirement reference while other tasks in this plan are linked.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { linkedTasks: tasksWithReferences.size, totalTasks: model.allTasks.length } + }) + ); + } +}; +var sbv009 = { + id: "SBV009", + title: "Task references unknown requirement", + category: "tasks", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A task references a requirement or acceptance-criterion ID that does not exist in the requirements document. References recognized only heuristically (keyword phrases) warn instead of erroring.", + resolution: "Fix the reference to point at an existing requirement ID, or add the missing requirement to requirements.md and re-approve it.", + evaluate(context, resolved) { + const { catalog, references } = context.traceability; + if (catalog.entries.length === 0) return []; + const filePath = tasksFilePath(context); + return references.filter( + (reference) => reference.canonical === void 0 || !catalog.byCanonical.has(reference.canonical) + ).map( + (reference) => makeDiagnostic({ + rule: this, + severity: reference.confidence === "heuristic" ? "warning" : resolved.severity, + message: `Task ${reference.taskId} references "${reference.raw}", which matches no requirement or acceptance criterion in requirements.md.`, + specName: context.specName, + taskId: reference.taskId, + requirementId: reference.raw, + file: filePath !== void 0 ? { path: filePath, line: reference.line + 1 } : null, + evidence: { + reference: reference.raw, + canonical: reference.canonical ?? null, + method: reference.method, + knownIds: catalog.entries.slice(0, 20).map((entry) => entry.displayId) + }, + confidence: reference.confidence + }) + ); + } +}; +var sbv010 = { + id: "SBV010", + title: "Completed parent task has incomplete child task", + category: "tasks", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A parent task checkbox is [x] while at least one of its subtasks is not.", + resolution: "Finish (or uncheck) the open subtasks, or uncheck the parent task.", + evaluate(context, resolved) { + const model = context.spec.tasks; + if (model === void 0) return []; + const diagnostics = []; + const openDescendants = (task) => { + const open = []; + for (const child of task.children) { + if (child.state !== "done") open.push(child); + open.push(...openDescendants(child)); + } + return open; + }; + for (const task of model.allTasks) { + if (task.children.length === 0 || task.state !== "done") continue; + const open = openDescendants(task); + if (open.length === 0) continue; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Parent task ${task.id} is checked but ${open.length} of its subtasks ${open.length === 1 ? "is" : "are"} not complete (${open.map((child) => child.id).join(", ")}).`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { incompleteChildren: open.map((child) => child.id) } + }) + ); + } + return diagnostics; + } +}; +var SBV011_CODES = /* @__PURE__ */ new Set([ + "task-identity-changed", + "task-missing", + "history-diverged", + "stage-not-approved" +]); +var SBV015_CODES = /* @__PURE__ */ new Set([ + "document-hash-changed", + "design-hash-changed", + "plan-hash-changed", + "approved-after-evidence" +]); +function staleEvidenceDiagnostics(rule, context, resolved, codes) { + const diagnostics = []; + for (const task of doneLeafTasks(context)) { + const assessment = context.evidence.assessmentsByTask.get(task.id); + if (assessment === void 0 || assessment.bucket !== "stale") continue; + const best = assessment.best; + if (best === void 0) continue; + const matching = best.reasons.filter((reason) => codes.has(reason.code)); + if (matching.length === 0) continue; + diagnostics.push( + makeDiagnostic({ + rule, + severity: resolved.severity, + message: `Task ${task.id} is checked but its evidence is stale: ${matching.map((reason) => reason.message).join("; ")}.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { + runId: best.record.runId, + evidenceStatus: best.record.status, + manualAcceptance: best.manual, + reasons: matching.map((reason) => ({ code: reason.code, message: reason.message })), + evaluatedAt: best.record.evaluatedAt + } + }) + ); + } + return diagnostics; +} +var sbv011 = { + id: "SBV011", + title: "Task evidence is stale", + category: "evidence", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A checked task has evidence whose recorded task identity, commit lineage, or approval linkage no longer matches the repository (the task text changed, history diverged, or a referenced stage is no longer approved).", + resolution: "Re-run the task (specbridge spec run) or re-accept it (specbridge spec accept-task) so fresh evidence is recorded, or uncheck the box.", + evaluate(context, resolved) { + return staleEvidenceDiagnostics(this, context, resolved, SBV011_CODES); + } +}; +var sbv015 = { + id: "SBV015", + title: "Spec changed after implementation evidence", + category: "evidence", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "The requirements/bugfix document, design, or task plan changed (or was re-approved) after the evidence for a checked task was recorded \u2014 the implementation was verified against an older spec.", + resolution: "Re-run or re-accept the affected tasks against the current spec so the evidence describes what is approved now.", + evaluate(context, resolved) { + return staleEvidenceDiagnostics(this, context, resolved, SBV015_CODES); + } +}; +var sbv012 = { + id: "SBV012", + title: "Required verification command failed", + category: "verification-command", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "A trusted verification command required by a spec policy failed, could not start, or did not run in this verification with no reusable passing evidence.", + resolution: "Fix the failing command locally, or run the verification with --run-verification so a current result is produced.", + evaluate(context, resolved) { + const diagnostics = []; + for (const command of context.commands.commands) { + if (!command.required || command.passed || command.timedOut) continue; + const specName = command.requiredBySpecs.length === 1 ? command.requiredBySpecs[0] ?? null : null; + const message = command.disposition === "not-run" ? `Required verification command "${command.name}" did not run in this verification and no current evidence covers it.` : command.spawnFailed ? `Required verification command "${command.name}" could not start (${command.result?.status ?? "spawn failure"}).` : `Required verification command "${command.name}" failed with exit code ${command.exitCode ?? "unknown"}.`; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message, + specName, + evidence: { + command: command.name, + argv: command.argv, + disposition: command.disposition, + exitCode: command.exitCode, + spawnFailed: command.spawnFailed, + requiredBySpecs: command.requiredBySpecs, + stderrTail: command.result?.stderrTail.slice(-2e3) ?? null + } + }) + ); + } + return diagnostics; + } +}; +var sbv013 = { + id: "SBV013", + title: "Required verification command missing", + category: "verification-command", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "A spec policy requires a verification command by name, but no command with that name is configured in .specbridge/config.json.", + resolution: "Add the command to verification.commands in .specbridge/config.json (argv array form), or remove the name from the policy.", + evaluate(context, resolved) { + return context.commands.missingRequired.map( + ({ name, requiredBySpecs }) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Verification command "${name}" is required by ${requiredBySpecs.join(", ")} but is not configured in .specbridge/config.json.`, + specName: requiredBySpecs.length === 1 ? requiredBySpecs[0] ?? null : null, + evidence: { command: name, requiredBySpecs } + }) + ); + } +}; +var sbv025 = { + id: "SBV025", + title: "Verification command timed out", + category: "verification-command", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "A trusted verification command exceeded its configured timeout. Required commands error; optional commands warn.", + resolution: "Raise the command timeout in .specbridge/config.json, or make the command faster/scoped.", + evaluate(context, resolved) { + return context.commands.commands.filter((command) => command.timedOut).map( + (command) => makeDiagnostic({ + rule: this, + severity: command.required ? resolved.severity : "warning", + message: `Verification command "${command.name}" timed out after ${command.durationMs ?? "?"} ms.`, + specName: command.requiredBySpecs.length === 1 ? command.requiredBySpecs[0] ?? null : null, + evidence: { + command: command.name, + argv: command.argv, + required: command.required, + durationMs: command.durationMs + } + }) + ); + } +}; +var sbv014 = { + id: "SBV014", + title: "Unmapped changed file", + category: "mapping", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "In --changed or --all verification, a changed source or test file maps to no spec: no spec directory, impact area, task evidence, or design reference claims it.", + resolution: "Add the path to the owning spec\u2019s impact areas, create a spec for the work, or accept unmapped changes by policy (rules.SBV014).", + evaluate(context, resolved) { + if (context.selection.mode === "single") return []; + return context.unmappedFiles.map( + (file) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${file.path} does not map to any spec (no impact area, evidence, or spec reference claims it).`, + file: { path: file.path }, + evidence: { changedPath: file.path, changeType: file.changeType } + }) + ); + } +}; +var sbv016 = { + id: "SBV016", + title: "Task marked complete before task-plan approval", + category: "approval", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "A managed spec has checked tasks while its task plan is not approved (never approved, or approval revoked). Unmanaged specs (no sidecar state) are not judged.", + resolution: "Approve the task plan first (specbridge spec approve --stage tasks), or uncheck the boxes.", + evaluate(context, resolved) { + const state = context.spec.state; + if (state === void 0 || context.spec.tasks === void 0) return []; + const tasksStage = context.evaluation?.stages.find((stage) => stage.stage === "tasks"); + if (tasksStage === void 0 || tasksStage.stored.status === "approved") return []; + return context.spec.tasks.allTasks.filter((task) => task.state === "done").map( + (task) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Task ${task.id} is checked but the task plan of "${context.specName}" has never been approved (status: ${tasksStage.stored.status}).`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { tasksStageStatus: tasksStage.stored.status } + }) + ); + } +}; +var sbv017 = { + id: "SBV017", + title: "No test evidence for test-required task", + category: "evidence", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "heuristic", + scope: "spec", + triggeredWhen: "A checked task (or its referenced requirement) explicitly mentions tests, but its valid evidence contains neither a passing test command nor changed test files. Error severity when the policy sets requireTestEvidence. Test-language detection is heuristic.", + resolution: "Run the configured test command as part of the task (spec run records it), or record a manual acceptance explaining how the tests were covered.", + evaluate(context, resolved) { + const model = context.spec.tasks; + const tasksDocument = context.spec.documents.tasks; + if (model === void 0 || tasksDocument === void 0) return []; + const severity = context.policy.requireTestEvidence ? "error" : resolved.severity; + const { catalog, references } = context.traceability; + const diagnostics = []; + for (const task of doneLeafTasks(context)) { + const assessment = context.evidence.assessmentsByTask.get(task.id); + if (assessment === void 0 || assessment.bucket !== "valid") continue; + const taskWantsTests = taskMentionsTests(tasksDocument, model, task); + const requirementWantsTests = references.some((reference) => { + if (reference.taskId !== task.id || reference.canonical === void 0) return false; + const entry = catalog.byCanonical.get(reference.canonical); + if (entry === void 0) return false; + if (entry.testRequired) return true; + const requirement = catalog.byCanonical.get(entry.requirementCanonical); + return requirement?.testRequired === true; + }); + if (!taskWantsTests && !requirementWantsTests) continue; + const record = assessment.best?.record; + if (record === void 0) continue; + const passingTestCommand = record.verificationCommands.some( + (command) => command.passed && (TEST_COMMAND_PATTERN.test(command.name) || command.argv.some((argument) => TEST_COMMAND_PATTERN.test(argument))) + ); + const testFilesChanged = record.changedFiles.some( + (file) => TEST_PATH_PATTERN.test(file.path) + ); + if (passingTestCommand || testFilesChanged) continue; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity, + message: `Task ${task.id} indicates tests (${taskWantsTests ? "task text" : "referenced requirement"}), but its evidence shows no passing test command and no changed test files.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { + taskMentionsTests: taskWantsTests, + requirementMentionsTests: requirementWantsTests, + evidenceRunId: record.runId, + recordedCommands: record.verificationCommands.map((command) => command.name), + testEvidenceRequired: context.policy.requireTestEvidence + } + }) + ); + } + return diagnostics; + } +}; +var sbv018 = { + id: "SBV018", + title: "Design path reference does not exist", + category: "design", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "design.md explicitly references a repository path (in backticks or a Markdown link) that exists neither relative to the repository root nor relative to the spec folder. Glob patterns are not checked.", + resolution: "Fix the path in design.md, or delete the reference if the file was intentionally removed (then re-approve the design).", + evaluate(context, resolved) { + const designDocument = context.spec.documents.design; + if (designDocument === void 0) return []; + const designFile = designDocument.filePath; + const designRepoPath = designFile !== void 0 ? repoRelative(context.workspace, designFile) : void 0; + const specDir = import_path12.default.join(context.workspace.rootDir, ".kiro", "specs", context.specName); + return context.traceability.designPathReferences.filter((reference) => !reference.isGlob).filter((reference) => { + const fromRoot = import_path12.default.join( + context.workspace.rootDir, + reference.path.split("/").join(import_path12.default.sep) + ); + const fromSpecDir = import_path12.default.join(specDir, reference.path.split("/").join(import_path12.default.sep)); + return !(0, import_fs13.existsSync)(fromRoot) && !(0, import_fs13.existsSync)(fromSpecDir); + }).map( + (reference) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `design.md references \`${reference.raw}\`, which does not exist in the repository.`, + specName: context.specName, + file: designRepoPath !== void 0 ? { path: designRepoPath, line: reference.line + 1 } : null, + evidence: { referencedPath: reference.path, method: reference.method } + }) + ); + } +}; +var sbv019 = { + id: "SBV019", + title: "Changed file not represented in execution evidence", + category: "evidence", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "The spec has valid task evidence, yet the comparison contains implementation files that no evidence record accounts for \u2014 work happened outside recorded task runs.", + resolution: "Run the remaining work as tasks (spec run records the files), or accept that untracked edits reduce evidence coverage.", + evaluate(context, resolved) { + const hasValidEvidence = [...context.evidence.assessmentsByTask.values()].some( + (assessment) => assessment.bucket === "valid" + ); + if (!hasValidEvidence) return []; + const evidencePaths = /* @__PURE__ */ new Set(); + for (const assessment of context.evidence.assessmentsByTask.values()) { + for (const item of assessment.all) { + if (item.validity !== "valid") continue; + for (const file of item.record.changedFiles) evidencePaths.add(file.path); + } + } + const candidates = context.selectionMode === "single" ? context.changedFiles : context.specChangedFiles; + return candidates.filter((file) => !isSpecInfraPath(file.path)).filter((file) => !evidencePaths.has(file.path)).map( + (file) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${file.path} changed but appears in no valid task evidence for ${context.specName}.`, + specName: context.specName, + file: { path: file.path }, + evidence: { changedPath: file.path, changeType: file.changeType } + }) + ); + } +}; +var sbv020 = { + id: "SBV020", + title: "Verification policy invalid", + category: "workspace", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "The spec\u2019s verification policy file exists but is not valid JSON, does not match the versioned schema, or contains rejected glob patterns. Verification then runs with secure defaults.", + resolution: "Fix the policy file (specbridge spec policy validate pinpoints the problem), or delete it to use defaults.", + evaluate(context, resolved) { + return context.policy.policyDiagnostics.map( + (diagnostic) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: diagnostic.message, + specName: context.specName, + file: context.policy.policyPath !== void 0 ? { path: context.policy.policyPath } : null, + evidence: { code: diagnostic.code } + }) + ); + } +}; +var sbv021 = { + id: "SBV021", + title: "Diff base unavailable", + category: "git", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "The requested Git comparison cannot be resolved: a ref does not exist locally, no merge base exists, the clone is shallow, or the directory is not a git work tree.", + resolution: "Fetch the missing refs yourself (SpecBridge never fetches automatically). In GitHub Actions, check out with actions/checkout@v4 and fetch-depth: 0.", + evaluate(context, resolved) { + const failure = context.comparison.failure; + if (context.comparison.ok || failure === void 0) return []; + return [ + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: failure.message, + evidence: { + reason: failure.reason, + shallowClone: failure.shallow, + comparison: context.comparison.descriptor.label + } + }) + ]; + } +}; +var sbv022 = { + id: "SBV022", + title: "Ambiguous affected-spec mapping", + category: "mapping", + defaultSeverity: { advisory: "warning", strict: "warning" }, + confidence: "deterministic", + scope: "global", + triggeredWhen: "A changed file maps to more than one spec (overlapping impact areas or evidence). Every matching spec is verified; the overlap itself is reported.", + resolution: "Narrow the overlapping impact areas so each path has one owning spec, or accept the shared ownership deliberately.", + evaluate(context, resolved) { + return context.ambiguousFiles.map( + (entry) => makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${entry.path} maps to ${entry.specs.length} specs: ${entry.specs.map((spec) => `${spec.name} (via ${spec.via.join(", ")})`).join("; ")}.`, + file: { path: entry.path }, + evidence: { specs: entry.specs } + }) + ); + } +}; +var sbv023 = { + id: "SBV023", + title: "Tasks document unexpectedly changed", + category: "tasks", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "The comparison modifies a managed spec\u2019s tasks.md beyond checkbox transitions \u2014 task text, IDs, hierarchy, or references changed relative to the comparison base.", + resolution: "If the plan change is intentional, review and re-approve the task plan; otherwise revert the tasks.md edit.", + async evaluate(context, resolved) { + if (context.spec.state === void 0) return []; + if (!context.comparison.ok) return []; + const repoPath = `.kiro/specs/${context.specName}/tasks.md`; + const changed = context.changedFiles.find( + (file) => file.path === repoPath && (file.changeType === "modified" || file.changeType === "renamed") + ); + if (changed === void 0) return []; + const currentDocument = context.spec.documents.tasks; + if (currentDocument === void 0) return []; + const baseContent = await context.readBaseContent(repoPath); + if (baseContent === void 0) return []; + const baseDocument = MarkdownDocument.fromText(baseContent); + if (normalizedTaskPlanText(baseDocument) === normalizedTaskPlanText(currentDocument)) { + return []; + } + return [ + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `tasks.md of "${context.specName}" changed beyond checkbox progress in this comparison (task text, IDs, hierarchy, or references differ from the base).`, + specName: context.specName, + file: { path: repoPath }, + evidence: { + comparison: context.comparison.descriptor.label, + changeType: changed.changeType + } + }) + ]; + } +}; +var sbv024 = { + id: "SBV024", + title: "Evidence points outside repository", + category: "evidence", + defaultSeverity: { advisory: "error", strict: "error" }, + confidence: "deterministic", + scope: "spec", + triggeredWhen: "An evidence record lists changed-file paths that escape the repository (absolute paths or .. traversal). Such records are never trusted.", + resolution: "Delete or regenerate the corrupt evidence record; evidence must only reference repository-relative paths.", + evaluate(context, resolved) { + const diagnostics = []; + for (const [taskId, assessment] of context.evidence.assessmentsByTask) { + for (const item of assessment.all) { + if (item.pathViolations.length === 0) continue; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Evidence record ${item.record.runId} for task ${taskId} references paths outside the repository: ${item.pathViolations.join(", ")}.`, + specName: context.specName, + taskId, + evidence: { runId: item.record.runId, paths: item.pathViolations } + }) + ); + } + } + return diagnostics; + } +}; +function builtInVerificationRules() { + return [ + sbv001, + sbv002, + sbv003, + sbv004, + sbv005, + sbv006, + sbv007, + sbv008, + sbv009, + sbv010, + sbv011, + sbv012, + sbv013, + sbv014, + sbv015, + sbv016, + sbv017, + sbv018, + sbv019, + sbv020, + sbv021, + sbv022, + sbv023, + sbv024, + sbv025 + ]; +} +function isInfrastructurePath(candidate) { + return candidate === ".git" || candidate.startsWith(".git/") || candidate.startsWith(".kiro/") || candidate.startsWith(".specbridge/"); +} +function loadSpecMatchingInfo(workspace, folder, options) { + const policy = resolveEffectivePolicy(workspace, folder.name, { + ...options.strict !== void 0 ? { strict: options.strict } : {} + }); + let designReferences = []; + const design = specFile(folder, "design"); + if (design !== void 0) { + try { + designReferences = extractPathReferences(MarkdownDocument.load(design.path)); + } catch { + } + } + const evidencePaths = /* @__PURE__ */ new Set(); + const evidenceDir2 = import_path13.default.join(workspace.sidecarDir, "evidence", folder.name); + if ((0, import_fs14.existsSync)(evidenceDir2)) { + for (const entry of (0, import_fs15.readdirSync)(evidenceDir2, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const { records } = listTaskEvidence(workspace, folder.name, entry.name); + for (const record of records) { + if (record.status !== "verified" && record.status !== "manually-accepted") continue; + for (const file of record.changedFiles) evidencePaths.add(file.path); + } + } + } + return { folder, policy, designReferences, evidencePaths }; +} +function resolveAffectedSpecs(workspace, changedFiles, options = {}) { + const specs = discoverSpecs(workspace).map( + (folder) => loadSpecMatchingInfo(workspace, folder, options) + ); + const affectedByName = /* @__PURE__ */ new Map(); + const claimsByFile = /* @__PURE__ */ new Map(); + for (const file of changedFiles) { + for (const spec of specs) { + const via = specMatchReasons( + spec.folder.name, + spec.policy, + spec.evidencePaths, + spec.designReferences, + file + ); + if (via.length === 0) continue; + const fileMatches = affectedByName.get(spec.folder.name) ?? /* @__PURE__ */ new Map(); + fileMatches.set(file.path, via); + affectedByName.set(spec.folder.name, fileMatches); + const claims = claimsByFile.get(file.path) ?? []; + claims.push({ name: spec.folder.name, via }); + claimsByFile.set(file.path, claims); + } + } + const affected = [...affectedByName.entries()].map(([specName, fileMatches]) => ({ + specName, + matches: [...fileMatches.entries()].map(([file, via]) => ({ file, via })).sort((a2, b) => a2.file.localeCompare(b.file, "en")) + })).sort((a2, b) => a2.specName.localeCompare(b.specName, "en")); + const unmapped = changedFiles.filter( + (file) => !isInfrastructurePath(file.path) && !claimsByFile.has(file.path) + ); + const ambiguous = [...claimsByFile.entries()].filter(([, claims]) => claims.length > 1).map(([filePath, claims]) => ({ + path: filePath, + specs: [...claims].sort((a2, b) => a2.name.localeCompare(b.name, "en")) + })).sort((a2, b) => a2.path.localeCompare(b.path, "en")); + return { affected, unmapped, ambiguous }; +} +var VERIFY_EXIT_CODES = { + passed: 0, + thresholdReached: 1, + invalidInput: 2, + comparisonUnavailable: 3, + commandFailedToStart: 4, + commandTimeout: 5 +}; +async function verifySpecs(request) { + const now = (request.clock ?? (() => /* @__PURE__ */ new Date()))(); + const verificationId = (request.idFactory ?? import_crypto2.randomUUID)(); + const workspace = request.workspace; + const configRead = readAgentConfig(workspace); + if (configRead.config === void 0) { + throw new SpecBridgeError( + "INVALID_STATE", + `Cannot verify: ${configRead.diagnostics.map((diagnostic) => diagnostic.message).join("; ")}` + ); + } + const config = configRead.config; + request.onProgress?.(`Resolving comparison (${describeComparison(request.comparison)})\u2026`); + const comparison = await resolveComparison(workspace.rootDir, request.comparison, { + ...request.signal !== void 0 ? { signal: request.signal } : {} + }); + const caches = createRunCaches(); + const selectionMode = request.selection.mode; + let affectedResult = { affected: [], unmapped: [], ambiguous: [] }; + const specContexts = []; + if (comparison.ok) { + if (selectionMode !== "single") { + affectedResult = resolveAffectedSpecs(workspace, comparison.changedFiles, { + ...request.strict !== void 0 ? { strict: request.strict } : {} + }); + } + const selectedFolders = request.selection.mode === "single" ? [requireSpec(workspace, request.selection.spec)] : request.selection.mode === "all" ? discoverSpecs(workspace) : discoverSpecs(workspace).filter( + (folder) => affectedResult.affected.some((spec) => spec.specName === folder.name) + ); + for (const folder of selectedFolders) { + request.onProgress?.(`Analyzing spec ${folder.name}\u2026`); + const matchedBy = affectedResult.affected.find((spec) => spec.specName === folder.name)?.matches.flatMap((match) => match.via.map((via) => `${via}: ${match.file}`)); + specContexts.push( + await buildSpecVerificationContext({ + workspace, + folder, + config, + comparison, + selectionMode, + caches, + ...request.strict !== void 0 ? { strict: request.strict } : {}, + ...request.explicitPolicyPath !== void 0 ? { explicitPolicyPath: request.explicitPolicyPath } : {}, + ...matchedBy !== void 0 ? { matchedBy: dedupe(matchedBy) } : {}, + now, + ...request.signal !== void 0 ? { signal: request.signal } : {} + }) + ); + } + } + let artifactsDir; + const ensureArtifactsDir = () => { + if (artifactsDir === void 0) { + const base = request.reportsDir ?? import_path14.default.join(workspace.sidecarDir, "reports"); + artifactsDir = import_path14.default.join(base, verificationId); + } + return artifactsDir; + }; + const requiredBySpec = /* @__PURE__ */ new Map(); + const evidenceBySpec = /* @__PURE__ */ new Map(); + for (const context of specContexts) { + requiredBySpec.set(context.specName, context.policy.requiredVerificationCommands); + evidenceBySpec.set(context.specName, context.evidence.flattened); + } + const commands = comparison.ok ? await orchestrateVerificationCommands({ + config, + requiredBySpec, + runVerification: request.runVerification, + workspaceRoot: workspace.rootDir, + ...comparison.descriptor.headSha !== null ? { headSha: comparison.descriptor.headSha } : {}, + evidenceBySpec, + ...request.signal !== void 0 ? { signal: request.signal } : {}, + ...request.onProgress !== void 0 ? { onProgress: request.onProgress } : {}, + onCommandFinished: (result, stdout, stderr) => { + const dir = ensureArtifactsDir(); + const safeName = result.name.replace(/[^A-Za-z0-9._-]+/g, "-"); + writeFileAtomic(import_path14.default.join(dir, "commands", `${safeName}.stdout.log`), stdout); + writeFileAtomic(import_path14.default.join(dir, "commands", `${safeName}.stderr.log`), stderr); + } + }) : { mode: "none", commands: [], missingRequired: [] }; + const rules = builtInVerificationRules(); + const diagnosticsBySpec = /* @__PURE__ */ new Map(); + for (const context of specContexts) { + const { diagnostics } = await evaluateSpecRules(rules, context); + diagnosticsBySpec.set(context.specName, diagnostics); + } + const globalContext = { + workspace, + comparison, + selection: { mode: selectionMode }, + specContexts, + unmappedFiles: affectedResult.unmapped, + ambiguousFiles: affectedResult.ambiguous, + commands, + now + }; + const globalResult = await evaluateGlobalRules(rules, globalContext); + const selectedNames = new Set(specContexts.map((context) => context.specName)); + const globalDiagnostics = []; + for (const diagnostic of globalResult.diagnostics) { + if (diagnostic.specName !== null && selectedNames.has(diagnostic.specName)) { + diagnosticsBySpec.get(diagnostic.specName)?.push(diagnostic); + } else { + globalDiagnostics.push(diagnostic); + } + } + const specResults = specContexts.map((context) => { + const diagnostics = sortVerificationDiagnostics(diagnosticsBySpec.get(context.specName) ?? []); + const counts = countDiagnostics(diagnostics); + const files = selectionMode === "single" ? context.changedFiles : context.specChangedFiles; + return { + specName: context.specName, + specType: context.spec.state?.specType ?? context.spec.classification.type, + workflowMode: context.spec.state?.workflowMode ?? "unknown", + managed: context.spec.state !== void 0, + result: reachesFailureThreshold(counts, request.failOn) ? "failed" : "passed", + policyMode: context.policy.mode, + policyPath: context.policy.policyExists ? context.policy.policyPath ?? null : null, + matchedBy: context.matchedBy, + changedFiles: files.map(toReportChangedFile), + traceability: traceabilitySummary(context), + evidence: evidenceSummary(context), + diagnostics + }; + }); + const sortedGlobal = sortVerificationDiagnostics(globalDiagnostics); + const allDiagnostics = [...sortedGlobal, ...specResults.flatMap((spec) => spec.diagnostics)]; + const totals = countDiagnostics(allDiagnostics); + const failed = reachesFailureThreshold(totals, request.failOn); + const report = { + schemaVersion: VERIFICATION_REPORT_SCHEMA_VERSION, + tool: { name: "specbridge", version: request.toolVersion }, + verificationId, + createdAt: now.toISOString(), + comparison: comparison.descriptor, + selection: { + mode: selectionMode, + specs: specContexts.map((context) => context.specName) + }, + summary: { + result: failed || !comparison.ok ? "failed" : "passed", + specsVerified: specContexts.length, + errors: totals.errors, + warnings: totals.warnings, + info: totals.info + }, + specResults, + globalDiagnostics: sortedGlobal, + verificationCommands: commands.commands.map(toCommandReport) + }; + verificationReportSchema.parse(report); + if (artifactsDir !== void 0) { + writeFileAtomic( + import_path14.default.join(artifactsDir, "report.json"), + `${JSON.stringify(report, null, 2)} +` + ); + } + return { + report, + exitCode: resolveExitCode(report, comparison, commands, request.failOn), + ...artifactsDir !== void 0 ? { artifactsDir } : {} + }; +} +function describeComparison(request) { + if (request.mode === "diff") return `${request.base}...${request.head}`; + return request.mode; +} +function dedupe(values) { + return [...new Set(values)]; +} +function toReportChangedFile(file) { + return { + path: file.path, + oldPath: file.oldPath ?? null, + changeType: file.changeType, + binary: file.binary, + insertions: file.insertions ?? null, + deletions: file.deletions ?? null + }; +} +function toCommandReport(command) { + return { + name: command.name, + argv: command.argv, + required: command.required, + disposition: command.disposition, + exitCode: command.exitCode, + durationMs: command.durationMs, + timedOut: command.timedOut, + passed: command.passed, + requiredBySpecs: command.requiredBySpecs + }; +} +function traceabilitySummary(context) { + const { catalog, references } = context.traceability; + const referenced = new Set( + references.map((reference) => reference.canonical).filter((canonical) => canonical !== void 0) + ); + let requirementsWithTasks = 0; + for (const requirement of catalog.requirements) { + let covered = false; + for (const canonical of referenced) { + if (canonical === requirement.canonical || catalog.byCanonical.get(canonical)?.requirementCanonical === requirement.canonical) { + covered = true; + break; + } + } + if (covered) requirementsWithTasks += 1; + } + const tasks = context.spec.tasks?.allTasks ?? []; + const tasksWithReferences = new Set(references.map((reference) => reference.taskId)); + return { + requirements: catalog.requirements.length, + requirementsWithTasks, + tasks: tasks.length, + tasksWithRequirements: tasks.filter((task) => tasksWithReferences.has(task.id)).length + }; +} +function evidenceSummary(context) { + const summary2 = { valid: 0, stale: 0, missing: 0, invalid: 0, manuallyAccepted: 0 }; + const model = context.spec.tasks; + if (model === void 0) return summary2; + for (const task of model.allTasks) { + if (task.children.length > 0 || task.state !== "done") continue; + const assessment = context.evidence.assessmentsByTask.get(task.id); + if (assessment === void 0 || assessment.bucket === "missing") { + summary2.missing += 1; + } else if (assessment.bucket === "valid") { + summary2.valid += 1; + if (assessment.best?.manual === true) summary2.manuallyAccepted += 1; + } else if (assessment.bucket === "stale") { + summary2.stale += 1; + } else { + summary2.invalid += 1; + } + } + summary2.invalid += context.evidence.invalidRecordCount; + return summary2; +} +function resolveExitCode(report, comparison, commands, failOn) { + if (!comparison.ok) return VERIFY_EXIT_CODES.comparisonUnavailable; + const allDiagnostics = [ + ...report.globalDiagnostics, + ...report.specResults.flatMap((spec) => spec.diagnostics) + ]; + if (allDiagnostics.some((diagnostic) => diagnostic.ruleId === "SBV020")) { + return VERIFY_EXIT_CODES.invalidInput; + } + const requiredSpawnFailed = commands.commands.some( + (command) => command.required && command.spawnFailed + ); + if (requiredSpawnFailed) return VERIFY_EXIT_CODES.commandFailedToStart; + const requiredTimedOut = commands.commands.some( + (command) => command.required && command.timedOut + ); + if (requiredTimedOut) return VERIFY_EXIT_CODES.commandTimeout; + const counts = countDiagnostics(allDiagnostics); + return reachesFailureThreshold(counts, failOn) ? VERIFY_EXIT_CODES.thresholdReached : VERIFY_EXIT_CODES.passed; +} + +// ../../packages/reporting/dist/index.js +function escapeHtml(text) { + return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'"); +} +var DEFAULT_MAX_DIAGNOSTICS = 50; +var DEFAULT_MAX_BLOCKING = 10; +function cell(text) { + return text.replaceAll("|", "\\|").replaceAll("\n", " "); +} +function code(text) { + return text.includes("`") ? `\`\`${text}\`\`` : `\`${text}\``; +} +function diagnosticLine(diagnostic) { + const location = diagnostic.file !== null ? ` \u2014 ${code(diagnostic.file.path)}${diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ""}` : ""; + const heuristic = diagnostic.confidence === "heuristic" ? " _(heuristic)_" : ""; + return `- ${code(diagnostic.ruleId)}${location}${heuristic} \u2014 ${diagnostic.message}`; +} +function severityBadge(diagnostic) { + if (diagnostic.severity === "error") return "\u{1F534} error"; + if (diagnostic.severity === "warning") return "\u{1F7E1} warning"; + return "\u{1F535} info"; +} +function specSection(spec, maxDiagnostics) { + const lines = []; + lines.push(`### ${spec.specName}`); + lines.push(""); + const policy = spec.policyPath !== null ? `${spec.policyMode} (${code(spec.policyPath)})` : `${spec.policyMode} (defaults)`; + lines.push( + `**Result:** ${spec.result === "passed" ? "Passed" : "Failed"} \xB7 **Policy:** ${policy} \xB7 **Type:** ${spec.specType}${spec.managed ? "" : " (unmanaged)"}` + ); + lines.push(""); + const t = spec.traceability; + const e = spec.evidence; + lines.push( + `Traceability: ${t.requirements} requirements (${t.requirementsWithTasks} with tasks), ${t.tasks} tasks (${t.tasksWithRequirements} linked). Evidence: ${e.valid} valid${e.manuallyAccepted > 0 ? ` (${e.manuallyAccepted} manual)` : ""}, ${e.stale} stale, ${e.missing} missing.` + ); + lines.push(""); + if (spec.diagnostics.length === 0) { + lines.push("No findings."); + lines.push(""); + return lines; + } + lines.push("| Severity | Rule | Where | Finding |"); + lines.push("|---|---|---|---|"); + const shown = spec.diagnostics.slice(0, maxDiagnostics); + for (const diagnostic of shown) { + const where = diagnostic.file !== null ? `${code(diagnostic.file.path)}${diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ""}` : diagnostic.taskId !== null ? `task ${code(diagnostic.taskId)}` : "\u2014"; + lines.push( + `| ${severityBadge(diagnostic)} | ${code(diagnostic.ruleId)} | ${cell(where)} | ${cell(diagnostic.message)} |` + ); + } + if (spec.diagnostics.length > shown.length) { + lines.push(""); + lines.push(`\u2026 and ${spec.diagnostics.length - shown.length} more findings (see the JSON report).`); + } + lines.push(""); + const remediations = shown.filter((diagnostic) => diagnostic.severity !== "info"); + if (remediations.length > 0) { + lines.push("
"); + lines.push("How to fix"); + lines.push(""); + for (const diagnostic of remediations) { + lines.push(`- ${code(diagnostic.ruleId)} \u2014 ${diagnostic.remediation}`); + } + lines.push(""); + lines.push("
"); + lines.push(""); + } + return lines; +} +function renderVerificationMarkdown(report, options = {}) { + const maxDiagnostics = options.maxDiagnosticsPerSpec ?? DEFAULT_MAX_DIAGNOSTICS; + const maxBlocking = options.maxBlockingIssues ?? DEFAULT_MAX_BLOCKING; + const lines = []; + lines.push("# SpecBridge Verification"); + lines.push(""); + lines.push(`**Result:** ${report.summary.result === "passed" ? "Passed \u2705" : "Failed \u274C"}`); + lines.push(""); + lines.push( + `Comparison: ${code(report.comparison.label)} \xB7 Selection: ${report.selection.mode} \xB7 ${report.summary.specsVerified} spec${report.summary.specsVerified === 1 ? "" : "s"} verified \xB7 ${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info` + ); + lines.push(""); + if (report.specResults.length > 0) { + lines.push("| Spec | Result | Errors | Warnings |"); + lines.push("|---|---|---:|---:|"); + for (const spec of report.specResults) { + const errors = spec.diagnostics.filter((diagnostic) => diagnostic.severity === "error").length; + const warnings = spec.diagnostics.filter( + (diagnostic) => diagnostic.severity === "warning" + ).length; + lines.push( + `| ${cell(spec.specName)} | ${spec.result === "passed" ? "Passed" : "Failed"} | ${errors} | ${warnings} |` + ); + } + lines.push(""); + } + const allDiagnostics = [ + ...report.globalDiagnostics, + ...report.specResults.flatMap((spec) => spec.diagnostics) + ]; + const blocking = allDiagnostics.filter((diagnostic) => diagnostic.severity === "error"); + if (blocking.length > 0) { + lines.push("## Blocking issues"); + lines.push(""); + for (const diagnostic of blocking.slice(0, maxBlocking)) { + lines.push(diagnosticLine(diagnostic)); + } + if (blocking.length > maxBlocking) { + lines.push(`- \u2026 and ${blocking.length - maxBlocking} more errors.`); + } + lines.push(""); + } + if (report.verificationCommands.length > 0) { + lines.push("## Verification commands"); + lines.push(""); + lines.push("| Command | Required | Outcome |"); + lines.push("|---|---|---|"); + for (const command of report.verificationCommands) { + const outcome = command.disposition === "executed" ? command.passed ? `passed (exit ${command.exitCode ?? 0})` : command.timedOut ? "timed out" : `failed (exit ${command.exitCode ?? "?"})` : command.disposition === "reused-evidence" ? "passed (reused from evidence)" : "not run"; + lines.push(`| ${code(command.name)} | ${command.required ? "yes" : "no"} | ${cell(outcome)} |`); + } + lines.push(""); + } + if (report.globalDiagnostics.length > 0) { + lines.push("## Workspace findings"); + lines.push(""); + for (const diagnostic of report.globalDiagnostics.slice(0, maxDiagnostics)) { + lines.push(diagnosticLine(diagnostic)); + } + lines.push(""); + } + for (const spec of report.specResults) { + lines.push(...specSection(spec, maxDiagnostics)); + } + const artifacts = options.artifactPaths; + if (artifacts !== void 0 && (artifacts.json ?? artifacts.markdown ?? artifacts.html) !== void 0) { + lines.push("## Reports"); + lines.push(""); + if (artifacts.json !== void 0) lines.push(`- JSON: ${code(artifacts.json)}`); + if (artifacts.markdown !== void 0) lines.push(`- Markdown: ${code(artifacts.markdown)}`); + if (artifacts.html !== void 0) lines.push(`- HTML: ${code(artifacts.html)}`); + lines.push(""); + } + lines.push( + `specbridge ${report.tool.version} \xB7 verification ${report.verificationId} \xB7 ${report.createdAt}` + ); + lines.push(""); + return lines.join("\n"); +} +function severityGlyph(severity) { + if (severity === "error") return "\u2717"; + if (severity === "warning") return "!"; + return "\xB7"; +} +function specSlug(index) { + return `spec-${index}`; +} +function renderDiagnostic2(diagnostic, specClass) { + const location = diagnostic.file !== null ? `${escapeHtml(diagnostic.file.path)}${diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ""}` : diagnostic.taskId !== null ? `task ${escapeHtml(diagnostic.taskId)}` : ""; + return [ + `
  • `, + ``, + `

    ${escapeHtml(diagnostic.ruleId)}`, + ` ${diagnostic.severity}`, + diagnostic.confidence === "heuristic" ? ' heuristic' : "", + location !== "" ? ` \u2014 ${location}` : "", + `

    ${escapeHtml(diagnostic.message)}

    `, + `

    Fix: ${escapeHtml(diagnostic.remediation)}

  • ` + ].join(""); +} +function renderSpec(spec, index) { + const cls = specSlug(index); + const t = spec.traceability; + const e = spec.evidence; + const rows = spec.changedFiles.map( + (file) => `${escapeHtml(file.changeType)}${escapeHtml(file.path)}${file.oldPath !== null ? ` from ${escapeHtml(file.oldPath)}` : ""}${file.binary ? "binary" : `+${file.insertions ?? 0} \u2212${file.deletions ?? 0}`}` + ).join("\n"); + return ` +
    +

    ${escapeHtml(spec.specName)} ${spec.result}

    +

    ${escapeHtml(spec.specType)}${spec.managed ? "" : " \xB7 unmanaged"} \xB7 policy: ${escapeHtml(spec.policyMode)}${spec.policyPath !== null ? ` (${escapeHtml(spec.policyPath)})` : " (defaults)"}

    +

    Traceability: ${t.requirements} requirements (${t.requirementsWithTasks} with tasks), ${t.tasks} tasks (${t.tasksWithRequirements} linked) \xB7 +Evidence: ${e.valid} valid${e.manuallyAccepted > 0 ? ` (${e.manuallyAccepted} manually accepted)` : ""}, ${e.stale} stale, ${e.missing} missing${e.invalid > 0 ? `, ${e.invalid} invalid` : ""}

    +${spec.changedFiles.length > 0 ? `
    ${spec.changedFiles.length} changed file${spec.changedFiles.length === 1 ? "" : "s"} + +${rows} +
    ChangePathLines
    ` : ""} +${spec.diagnostics.length > 0 ? `
      +${spec.diagnostics.map((diagnostic) => renderDiagnostic2(diagnostic, cls)).join("\n")} +
    ` : '

    No findings.

    '} +
    `; +} +function renderVerificationHtml(report) { + const specFilters = report.specResults.map( + (spec, index) => `` + ).join("\n"); + const specFilterCss = report.specResults.map( + (_, index) => `body:has(#f-${specSlug(index)}:not(:checked)) .${specSlug(index)} { display: none; }` + ).join("\n"); + const commandRows = report.verificationCommands.map((command) => { + const outcome = command.disposition === "executed" ? command.passed ? `passed (exit ${command.exitCode ?? 0})` : command.timedOut ? "timed out" : `failed (exit ${command.exitCode ?? "?"})` : command.disposition === "reused-evidence" ? "passed (reused from evidence)" : "not run"; + return `${escapeHtml(command.name)}${command.required ? "required" : "optional"}${escapeHtml(command.argv.join(" "))}${escapeHtml(outcome)}`; + }).join("\n"); + const summary2 = report.summary; + return ` + + + + +SpecBridge verification \u2014 ${escapeHtml(summary2.result)} + + + +

    SpecBridge Verification

    +

    ${summary2.result === "passed" ? "PASSED" : "FAILED"} \u2014 ${summary2.errors} errors, ${summary2.warnings} warnings, ${summary2.info} info

    +

    Comparison: ${escapeHtml(report.comparison.label)} \xB7 selection: ${escapeHtml(report.selection.mode)} \xB7 ${summary2.specsVerified} spec(s) verified

    +

    specbridge ${escapeHtml(report.tool.version)} \xB7 verification ${escapeHtml(report.verificationId)} \xB7 ${escapeHtml(report.createdAt)}

    + +
    +Filters (CSS only \u2014 content remains in the document) + + + +${specFilters} +
    + +${report.globalDiagnostics.length > 0 ? `

    Workspace findings

      +${report.globalDiagnostics.map((diagnostic) => renderDiagnostic2(diagnostic, "global")).join("\n")} +
    ` : ""} + +${report.verificationCommands.length > 0 ? `

    Verification commands

    + +${commandRows} +
    CommandKindargvOutcome
    ` : ""} + +${report.specResults.map((spec, index) => renderSpec(spec, index)).join("\n")} + +
    Generated by specbridge spec verify \u2014 deterministic, offline, no model involved.
    + + +`; +} + +// src/annotations.ts +function annotatable(diagnostic) { + if (diagnostic.file === null) return false; + const filePath = diagnostic.file.path; + if (filePath.startsWith("/") || /^[A-Za-z]:/.test(filePath)) return false; + if (filePath.split("/").includes("..")) return false; + return true; +} +function emitAnnotations(sink, report, limit) { + const all = sortVerificationDiagnostics([ + ...report.globalDiagnostics, + ...report.specResults.flatMap((spec) => spec.diagnostics) + ]).filter(annotatable); + let emitted = 0; + for (const diagnostic of all) { + if (emitted >= limit) break; + const properties = { + title: `${diagnostic.ruleId} \u2014 ${diagnostic.title}`, + ...diagnostic.file !== null ? { file: diagnostic.file.path } : {}, + ...diagnostic.file?.line != null ? { startLine: diagnostic.file.line } : {}, + ...diagnostic.file?.column != null ? { startColumn: diagnostic.file.column } : {} + }; + const message = `${diagnostic.message} Fix: ${diagnostic.remediation}`; + if (diagnostic.severity === "error") sink.error(message, properties); + else if (diagnostic.severity === "warning") sink.warning(message, properties); + else sink.notice(message, properties); + emitted += 1; + } + const suppressed = all.length - emitted; + if (suppressed > 0) { + sink.warning( + `${suppressed} further finding${suppressed === 1 ? "" : "s"} were not annotated (annotation limit ${limit}); the full report artifact contains everything.`, + { title: "SpecBridge \u2014 annotation limit reached" } + ); + } + return { emitted, suppressed }; +} + +// src/event.ts +var ZERO_SHA = /^0{40}$/; +function asRecord(value) { + return typeof value === "object" && value !== null ? value : {}; +} +function stringField(value) { + return typeof value === "string" && value.length > 0 ? value : void 0; +} +function safeDiff(base, head, source) { + for (const [role, ref] of [ + ["base", base], + ["head", head] + ]) { + if (!isSafeGitRef(ref)) { + return { ok: false, message: `The ${role} ref "${ref}" (${source}) is not a valid git ref.` }; + } + } + return { ok: true, request: { mode: "diff", base, head }, source }; +} +function resolveComparisonFromEvent(input) { + if (input.baseRef !== void 0) { + return safeDiff(input.baseRef, input.headRef ?? "HEAD", "explicit base-ref/head-ref inputs"); + } + if (input.headRef !== void 0) { + return { + ok: false, + message: 'Input "head-ref" was set without "base-ref"; a comparison needs both (head-ref defaults to HEAD).' + }; + } + const payload = asRecord(input.payload); + if (input.eventName === "pull_request" || input.eventName === "pull_request_target") { + const pullRequest = asRecord(payload["pull_request"]); + const baseSha = stringField(asRecord(pullRequest["base"])["sha"]); + const headSha = stringField(asRecord(pullRequest["head"])["sha"]); + if (baseSha === void 0 || headSha === void 0) { + return { + ok: false, + message: "The pull_request event payload has no base/head SHAs; pass base-ref and head-ref explicitly." + }; + } + return safeDiff(baseSha, headSha, `${input.eventName} event`); + } + if (input.eventName === "push") { + const before = stringField(payload["before"]); + const after = stringField(payload["after"]) ?? input.sha; + if (before === void 0 || after === void 0) { + return { + ok: false, + message: "The push event payload has no before/after SHAs; pass base-ref and head-ref explicitly." + }; + } + if (ZERO_SHA.test(before)) { + return { + ok: false, + message: 'This push created the branch, so there is no "before" commit to compare against. Pass base-ref explicitly (for example the default branch ref).' + }; + } + return safeDiff(before, after, "push event"); + } + return { + ok: false, + message: `Event "${input.eventName ?? "(unknown)"}" carries no comparison range. Set the base-ref (and optionally head-ref) inputs, e.g. base-ref: \${{ github.event.repository.default_branch }}.` + }; +} + +// src/inputs.ts +function requireEnum(name, raw, accepted, fallback) { + const value = raw.trim() === "" ? fallback : raw.trim(); + if (!accepted.includes(value)) { + throw new Error( + `Input "${name}" must be one of ${accepted.join(", ")}; got "${raw}".` + ); + } + return value; +} +function requireBoolean(name, raw, fallback) { + const value = raw.trim().toLowerCase(); + if (value === "") return fallback; + if (value === "true") return true; + if (value === "false") return false; + throw new Error(`Input "${name}" must be "true" or "false"; got "${raw}".`); +} +function parseActionInputs(getInput2) { + const mode = requireEnum("mode", getInput2("mode"), ["single", "changed", "all"], "changed"); + const spec = getInput2("spec").trim(); + if (mode === "single" && spec === "") { + throw new Error('Input "spec" is required when mode is "single".'); + } + if (mode !== "single" && spec !== "") { + throw new Error(`Input "spec" only applies when mode is "single" (mode is "${mode}").`); + } + const failOn = requireEnum("fail-on", getInput2("fail-on"), ["error", "warning", "never"], "error"); + const strict = requireBoolean("strict", getInput2("strict"), false); + const runVerification = requireBoolean("run-verification", getInput2("run-verification"), true); + const annotations = requireBoolean("annotations", getInput2("annotations"), true); + const writeStepSummary = requireBoolean( + "write-step-summary", + getInput2("write-step-summary"), + true + ); + const reportDirectoryRaw = getInput2("report-directory").trim(); + const reportDirectory = reportDirectoryRaw === "" ? ".specbridge/action-reports" : reportDirectoryRaw; + if (reportDirectory.split(/[\\/]/).includes("..")) { + throw new Error('Input "report-directory" must not contain ".." path segments.'); + } + const annotationLimitRaw = getInput2("annotation-limit").trim(); + const annotationLimit = annotationLimitRaw === "" ? 50 : Number(annotationLimitRaw); + if (!Number.isInteger(annotationLimit) || annotationLimit < 0 || annotationLimit > 1e3) { + throw new Error( + `Input "annotation-limit" must be an integer between 0 and 1000; got "${annotationLimitRaw}".` + ); + } + return { + mode, + spec: spec === "" ? void 0 : spec, + baseRef: emptyToUndefined(getInput2("base-ref")), + headRef: emptyToUndefined(getInput2("head-ref")), + failOn, + strict, + runVerification, + reportDirectory, + annotations, + writeStepSummary, + annotationLimit + }; +} +function emptyToUndefined(value) { + const trimmed = value.trim(); + return trimmed === "" ? void 0 : trimmed; +} + +// src/version.ts +var ACTION_VERSION = "0.4.0"; + +// src/main.ts +function readEventPayload(eventPath) { + if (eventPath === void 0 || eventPath === "") return void 0; + try { + return JSON.parse((0, import_node_fs6.readFileSync)(eventPath, "utf8")); + } catch { + return void 0; + } +} +function toPosixRelative(from, to) { + return import_node_path6.default.relative(from, to).split(import_node_path6.default.sep).join("/"); +} +async function run() { + const inputs = parseActionInputs((name) => core.getInput(name)); + const workspaceDir = process.env["GITHUB_WORKSPACE"] ?? process.cwd(); + const workspace = resolveWorkspace(workspaceDir); + if (workspace === void 0) { + core.setFailed( + `No .kiro directory found under ${workspaceDir}. Check out the repository containing your Kiro workspace before this step.` + ); + return; + } + const eventResolution = resolveComparisonFromEvent({ + eventName: process.env["GITHUB_EVENT_NAME"], + payload: readEventPayload(process.env["GITHUB_EVENT_PATH"]), + sha: process.env["GITHUB_SHA"], + baseRef: inputs.baseRef, + headRef: inputs.headRef + }); + if (!eventResolution.ok) { + core.setFailed(eventResolution.message); + return; + } + core.info( + `Comparison: ${eventResolution.request.mode === "diff" ? `${eventResolution.request.base}...${eventResolution.request.head}` : eventResolution.request.mode} (${eventResolution.source})` + ); + const selection = inputs.mode === "single" ? { mode: "single", spec: inputs.spec } : { mode: inputs.mode }; + const reportDirectory = import_node_path6.default.resolve(workspace.rootDir, inputs.reportDirectory); + const result = await verifySpecs({ + workspace, + selection, + comparison: eventResolution.request, + runVerification: inputs.runVerification, + strict: inputs.strict, + failOn: inputs.failOn, + toolVersion: ACTION_VERSION, + reportsDir: reportDirectory, + onProgress: (message) => core.info(message) + }); + const report = result.report; + const jsonPath = import_node_path6.default.join(reportDirectory, "report.json"); + const markdownPath = import_node_path6.default.join(reportDirectory, "report.md"); + const htmlPath = import_node_path6.default.join(reportDirectory, "report.html"); + const relative = { + json: toPosixRelative(workspace.rootDir, jsonPath), + markdown: toPosixRelative(workspace.rootDir, markdownPath), + html: toPosixRelative(workspace.rootDir, htmlPath) + }; + const markdown = renderVerificationMarkdown(report, { artifactPaths: relative }); + writeFileAtomic(jsonPath, `${JSON.stringify(report, null, 2)} +`); + writeFileAtomic(markdownPath, `${markdown} +`); + writeFileAtomic(htmlPath, renderVerificationHtml(report)); + core.setOutput("result", report.summary.result); + core.setOutput("verification-id", report.verificationId); + core.setOutput("spec-count", String(report.summary.specsVerified)); + core.setOutput("error-count", String(report.summary.errors)); + core.setOutput("warning-count", String(report.summary.warnings)); + core.setOutput("info-count", String(report.summary.info)); + core.setOutput("json-report", relative.json); + core.setOutput("markdown-report", relative.markdown); + core.setOutput("html-report", relative.html); + core.setOutput("affected-specs", JSON.stringify(report.selection.specs)); + if (inputs.annotations) { + const outcome = emitAnnotations(core, report, inputs.annotationLimit); + core.info( + `Annotations: ${outcome.emitted} emitted${outcome.suppressed > 0 ? `, ${outcome.suppressed} suppressed by the limit` : ""}.` + ); + } + if (inputs.writeStepSummary) { + await core.summary.addRaw(markdown, true).write(); + } + core.info( + `Verification ${report.summary.result}: ${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info across ${report.summary.specsVerified} spec(s).` + ); + if (result.exitCode !== 0) { + const reason = result.exitCode === 3 ? "the git comparison could not be resolved (shallow clone? use actions/checkout with fetch-depth: 0)" : result.exitCode === 2 ? "a verification policy or configuration is invalid" : result.exitCode === 4 ? "a required verification command failed to start" : result.exitCode === 5 ? "a required verification command timed out" : `the ${inputs.failOn} failure threshold was reached`; + core.setFailed(`SpecBridge verification failed: ${reason}. See the step summary and ${relative.markdown}.`); + } +} +run().catch((error) => { + core.setFailed(error instanceof Error ? error.message : String(error)); +}); +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + run +}); +/*! Bundled license information: + +undici/lib/fetch/body.js: + (*! formdata-polyfill. MIT License. Jimmy Wärting *) + +undici/lib/websocket/frame.js: + (*! ws. MIT License. Einar Otto Stangvik *) +*/ diff --git a/integrations/github-action/package.json b/integrations/github-action/package.json new file mode 100644 index 0000000..6d8088d --- /dev/null +++ b/integrations/github-action/package.json @@ -0,0 +1,23 @@ +{ + "name": "specbridge-github-action", + "version": "0.4.0", + "private": true, + "description": "GitHub Action for deterministic SpecBridge spec drift verification. No model, no API key, no network access required.", + "license": "MIT", + "scripts": { + "build": "tsup", + "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@actions/core": "^1.11.1", + "@specbridge/compat-kiro": "workspace:*", + "@specbridge/core": "workspace:*", + "@specbridge/drift": "workspace:*", + "@specbridge/reporting": "workspace:*" + }, + "devDependencies": { + "tsup": "^8.3.0", + "typescript": "^5.6.0" + } +} diff --git a/integrations/github-action/src/annotations.ts b/integrations/github-action/src/annotations.ts new file mode 100644 index 0000000..d2a7ccf --- /dev/null +++ b/integrations/github-action/src/annotations.ts @@ -0,0 +1,71 @@ +import type { VerificationDiagnostic, VerificationReport } from '@specbridge/core'; +import { sortVerificationDiagnostics } from '@specbridge/core'; + +/** + * Bounded GitHub file/line annotations. Errors get the budget first; when + * the limit is reached, one summary warning explains how many findings were + * suppressed — the full report artifact always has everything. + */ + +export interface AnnotationSink { + error(message: string, properties: AnnotationProperties): void; + warning(message: string, properties: AnnotationProperties): void; + notice(message: string, properties: AnnotationProperties): void; +} + +export interface AnnotationProperties { + title?: string; + file?: string; + startLine?: number; + startColumn?: number; +} + +function annotatable(diagnostic: VerificationDiagnostic): boolean { + if (diagnostic.file === null) return false; + const filePath = diagnostic.file.path; + // Never annotate paths outside the repository. + if (filePath.startsWith('/') || /^[A-Za-z]:/.test(filePath)) return false; + if (filePath.split('/').includes('..')) return false; + return true; +} + +export interface AnnotationOutcome { + emitted: number; + suppressed: number; +} + +export function emitAnnotations( + sink: AnnotationSink, + report: VerificationReport, + limit: number, +): AnnotationOutcome { + const all = sortVerificationDiagnostics([ + ...report.globalDiagnostics, + ...report.specResults.flatMap((spec) => spec.diagnostics), + ]).filter(annotatable); + + let emitted = 0; + for (const diagnostic of all) { + if (emitted >= limit) break; + const properties: AnnotationProperties = { + title: `${diagnostic.ruleId} — ${diagnostic.title}`, + ...(diagnostic.file !== null ? { file: diagnostic.file.path } : {}), + ...(diagnostic.file?.line != null ? { startLine: diagnostic.file.line } : {}), + ...(diagnostic.file?.column != null ? { startColumn: diagnostic.file.column } : {}), + }; + const message = `${diagnostic.message} Fix: ${diagnostic.remediation}`; + if (diagnostic.severity === 'error') sink.error(message, properties); + else if (diagnostic.severity === 'warning') sink.warning(message, properties); + else sink.notice(message, properties); + emitted += 1; + } + + const suppressed = all.length - emitted; + if (suppressed > 0) { + sink.warning( + `${suppressed} further finding${suppressed === 1 ? '' : 's'} were not annotated (annotation limit ${limit}); the full report artifact contains everything.`, + { title: 'SpecBridge — annotation limit reached' }, + ); + } + return { emitted, suppressed }; +} diff --git a/integrations/github-action/src/event.ts b/integrations/github-action/src/event.ts new file mode 100644 index 0000000..2325ec3 --- /dev/null +++ b/integrations/github-action/src/event.ts @@ -0,0 +1,107 @@ +import type { ComparisonRequest } from '@specbridge/drift'; +import { isSafeGitRef } from '@specbridge/drift'; + +/** + * GitHub event → git comparison resolution. + * + * pull_request / pull_request_target: base SHA … head SHA from the event + * push: before SHA … after SHA (GITHUB_SHA) + * workflow_dispatch and anything else: explicit base-ref/head-ref inputs, + * otherwise fail with instructions + * + * Nothing here assumes `main`, assumes the default branch exists locally, or + * fetches anything. Unresolvable SHAs are diagnosed downstream by the + * comparison resolver with the fetch-depth guidance. + */ + +const ZERO_SHA = /^0{40}$/; + +export interface EventResolutionInput { + eventName: string | undefined; + /** Parsed GITHUB_EVENT_PATH payload (undefined when absent/unreadable). */ + payload: unknown; + /** GITHUB_SHA. */ + sha: string | undefined; + baseRef: string | undefined; + headRef: string | undefined; +} + +export type EventResolution = + | { ok: true; request: ComparisonRequest; source: string } + | { ok: false; message: string }; + +function asRecord(value: unknown): Record { + return typeof value === 'object' && value !== null ? (value as Record) : {}; +} + +function stringField(value: unknown): string | undefined { + return typeof value === 'string' && value.length > 0 ? value : undefined; +} + +function safeDiff(base: string, head: string, source: string): EventResolution { + for (const [role, ref] of [ + ['base', base], + ['head', head], + ] as const) { + if (!isSafeGitRef(ref)) { + return { ok: false, message: `The ${role} ref "${ref}" (${source}) is not a valid git ref.` }; + } + } + return { ok: true, request: { mode: 'diff', base, head }, source }; +} + +export function resolveComparisonFromEvent(input: EventResolutionInput): EventResolution { + // Explicit inputs always win — they are the only way to steer dispatch runs. + if (input.baseRef !== undefined) { + return safeDiff(input.baseRef, input.headRef ?? 'HEAD', 'explicit base-ref/head-ref inputs'); + } + if (input.headRef !== undefined) { + return { + ok: false, + message: 'Input "head-ref" was set without "base-ref"; a comparison needs both (head-ref defaults to HEAD).', + }; + } + + const payload = asRecord(input.payload); + + if (input.eventName === 'pull_request' || input.eventName === 'pull_request_target') { + const pullRequest = asRecord(payload['pull_request']); + const baseSha = stringField(asRecord(pullRequest['base'])['sha']); + const headSha = stringField(asRecord(pullRequest['head'])['sha']); + if (baseSha === undefined || headSha === undefined) { + return { + ok: false, + message: + 'The pull_request event payload has no base/head SHAs; pass base-ref and head-ref explicitly.', + }; + } + return safeDiff(baseSha, headSha, `${input.eventName} event`); + } + + if (input.eventName === 'push') { + const before = stringField(payload['before']); + const after = stringField(payload['after']) ?? input.sha; + if (before === undefined || after === undefined) { + return { + ok: false, + message: 'The push event payload has no before/after SHAs; pass base-ref and head-ref explicitly.', + }; + } + if (ZERO_SHA.test(before)) { + return { + ok: false, + message: + 'This push created the branch, so there is no "before" commit to compare against. ' + + 'Pass base-ref explicitly (for example the default branch ref).', + }; + } + return safeDiff(before, after, 'push event'); + } + + return { + ok: false, + message: + `Event "${input.eventName ?? '(unknown)'}" carries no comparison range. ` + + 'Set the base-ref (and optionally head-ref) inputs, e.g. base-ref: ${{ github.event.repository.default_branch }}.', + }; +} diff --git a/integrations/github-action/src/inputs.ts b/integrations/github-action/src/inputs.ts new file mode 100644 index 0000000..c3798c8 --- /dev/null +++ b/integrations/github-action/src/inputs.ts @@ -0,0 +1,98 @@ +/** + * Action input parsing and validation. Inputs arrive as `INPUT_` + * environment variables; every enum is validated with a clear error that + * names the input, the received value, and the accepted values. + */ + +export interface ActionInputs { + mode: 'single' | 'changed' | 'all'; + spec: string | undefined; + baseRef: string | undefined; + headRef: string | undefined; + failOn: 'error' | 'warning' | 'never'; + strict: boolean; + runVerification: boolean; + reportDirectory: string; + annotations: boolean; + writeStepSummary: boolean; + annotationLimit: number; +} + +export type GetInput = (name: string) => string; + +function requireEnum( + name: string, + raw: string, + accepted: readonly T[], + fallback: T, +): T { + const value = raw.trim() === '' ? fallback : raw.trim(); + if (!(accepted as readonly string[]).includes(value)) { + throw new Error( + `Input "${name}" must be one of ${accepted.join(', ')}; got "${raw}".`, + ); + } + return value as T; +} + +function requireBoolean(name: string, raw: string, fallback: boolean): boolean { + const value = raw.trim().toLowerCase(); + if (value === '') return fallback; + if (value === 'true') return true; + if (value === 'false') return false; + throw new Error(`Input "${name}" must be "true" or "false"; got "${raw}".`); +} + +export function parseActionInputs(getInput: GetInput): ActionInputs { + const mode = requireEnum('mode', getInput('mode'), ['single', 'changed', 'all'], 'changed'); + const spec = getInput('spec').trim(); + if (mode === 'single' && spec === '') { + throw new Error('Input "spec" is required when mode is "single".'); + } + if (mode !== 'single' && spec !== '') { + throw new Error(`Input "spec" only applies when mode is "single" (mode is "${mode}").`); + } + + const failOn = requireEnum('fail-on', getInput('fail-on'), ['error', 'warning', 'never'], 'error'); + const strict = requireBoolean('strict', getInput('strict'), false); + const runVerification = requireBoolean('run-verification', getInput('run-verification'), true); + const annotations = requireBoolean('annotations', getInput('annotations'), true); + const writeStepSummary = requireBoolean( + 'write-step-summary', + getInput('write-step-summary'), + true, + ); + + const reportDirectoryRaw = getInput('report-directory').trim(); + const reportDirectory = reportDirectoryRaw === '' ? '.specbridge/action-reports' : reportDirectoryRaw; + if (reportDirectory.split(/[\\/]/).includes('..')) { + throw new Error('Input "report-directory" must not contain ".." path segments.'); + } + + const annotationLimitRaw = getInput('annotation-limit').trim(); + const annotationLimit = annotationLimitRaw === '' ? 50 : Number(annotationLimitRaw); + if (!Number.isInteger(annotationLimit) || annotationLimit < 0 || annotationLimit > 1000) { + throw new Error( + `Input "annotation-limit" must be an integer between 0 and 1000; got "${annotationLimitRaw}".`, + ); + } + + return { + mode, + spec: spec === '' ? undefined : spec, + baseRef: emptyToUndefined(getInput('base-ref')), + headRef: emptyToUndefined(getInput('head-ref')), + failOn, + strict, + runVerification, + reportDirectory, + annotations, + writeStepSummary, + annotationLimit, + }; +} + +function emptyToUndefined(value: string): string | undefined { + const trimmed = value.trim(); + return trimmed === '' ? undefined : trimmed; +} diff --git a/integrations/github-action/src/main.ts b/integrations/github-action/src/main.ts new file mode 100644 index 0000000..e6c894e --- /dev/null +++ b/integrations/github-action/src/main.ts @@ -0,0 +1,143 @@ +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import * as core from '@actions/core'; +import { resolveWorkspace, writeFileAtomic } from '@specbridge/core'; +import type { VerifySelection } from '@specbridge/drift'; +import { verifySpecs } from '@specbridge/drift'; +import { renderVerificationHtml, renderVerificationMarkdown } from '@specbridge/reporting'; +import { emitAnnotations } from './annotations.js'; +import { resolveComparisonFromEvent } from './event.js'; +import { parseActionInputs } from './inputs.js'; +import { ACTION_VERSION } from './version.js'; + +/** + * SpecBridge verification GitHub Action (node20). + * + * A thin wrapper around the shared @specbridge/drift verification engine: + * no rule logic lives here. Requires no model, no API key, no Claude Code + * installation, and performs no network access. It never modifies tracked + * project files — its only writes are the generated reports under the + * configured report directory. + */ + +function readEventPayload(eventPath: string | undefined): unknown { + if (eventPath === undefined || eventPath === '') return undefined; + try { + return JSON.parse(readFileSync(eventPath, 'utf8')); + } catch { + return undefined; + } +} + +function toPosixRelative(from: string, to: string): string { + return path.relative(from, to).split(path.sep).join('/'); +} + +export async function run(): Promise { + const inputs = parseActionInputs((name) => core.getInput(name)); + + const workspaceDir = process.env['GITHUB_WORKSPACE'] ?? process.cwd(); + const workspace = resolveWorkspace(workspaceDir); + if (workspace === undefined) { + core.setFailed( + `No .kiro directory found under ${workspaceDir}. ` + + 'Check out the repository containing your Kiro workspace before this step.', + ); + return; + } + + const eventResolution = resolveComparisonFromEvent({ + eventName: process.env['GITHUB_EVENT_NAME'], + payload: readEventPayload(process.env['GITHUB_EVENT_PATH']), + sha: process.env['GITHUB_SHA'], + baseRef: inputs.baseRef, + headRef: inputs.headRef, + }); + if (!eventResolution.ok) { + core.setFailed(eventResolution.message); + return; + } + core.info( + `Comparison: ${eventResolution.request.mode === 'diff' ? `${eventResolution.request.base}...${eventResolution.request.head}` : eventResolution.request.mode} (${eventResolution.source})`, + ); + + const selection: VerifySelection = + inputs.mode === 'single' + ? { mode: 'single', spec: inputs.spec as string } + : { mode: inputs.mode }; + + const reportDirectory = path.resolve(workspace.rootDir, inputs.reportDirectory); + const result = await verifySpecs({ + workspace, + selection, + comparison: eventResolution.request, + runVerification: inputs.runVerification, + strict: inputs.strict, + failOn: inputs.failOn, + toolVersion: ACTION_VERSION, + reportsDir: reportDirectory, + onProgress: (message) => core.info(message), + }); + const report = result.report; + + // ---- Reports -------------------------------------------------------------- + const jsonPath = path.join(reportDirectory, 'report.json'); + const markdownPath = path.join(reportDirectory, 'report.md'); + const htmlPath = path.join(reportDirectory, 'report.html'); + const relative = { + json: toPosixRelative(workspace.rootDir, jsonPath), + markdown: toPosixRelative(workspace.rootDir, markdownPath), + html: toPosixRelative(workspace.rootDir, htmlPath), + }; + const markdown = renderVerificationMarkdown(report, { artifactPaths: relative }); + writeFileAtomic(jsonPath, `${JSON.stringify(report, null, 2)}\n`); + writeFileAtomic(markdownPath, `${markdown}\n`); + writeFileAtomic(htmlPath, renderVerificationHtml(report)); + + // ---- Outputs -------------------------------------------------------------- + core.setOutput('result', report.summary.result); + core.setOutput('verification-id', report.verificationId); + core.setOutput('spec-count', String(report.summary.specsVerified)); + core.setOutput('error-count', String(report.summary.errors)); + core.setOutput('warning-count', String(report.summary.warnings)); + core.setOutput('info-count', String(report.summary.info)); + core.setOutput('json-report', relative.json); + core.setOutput('markdown-report', relative.markdown); + core.setOutput('html-report', relative.html); + core.setOutput('affected-specs', JSON.stringify(report.selection.specs)); + + // ---- Annotations and step summary ------------------------------------------ + if (inputs.annotations) { + const outcome = emitAnnotations(core, report, inputs.annotationLimit); + core.info( + `Annotations: ${outcome.emitted} emitted${outcome.suppressed > 0 ? `, ${outcome.suppressed} suppressed by the limit` : ''}.`, + ); + } + if (inputs.writeStepSummary) { + await core.summary.addRaw(markdown, true).write(); + } + + core.info( + `Verification ${report.summary.result}: ${report.summary.errors} errors, ` + + `${report.summary.warnings} warnings, ${report.summary.info} info ` + + `across ${report.summary.specsVerified} spec(s).`, + ); + + if (result.exitCode !== 0) { + const reason = + result.exitCode === 3 + ? 'the git comparison could not be resolved (shallow clone? use actions/checkout with fetch-depth: 0)' + : result.exitCode === 2 + ? 'a verification policy or configuration is invalid' + : result.exitCode === 4 + ? 'a required verification command failed to start' + : result.exitCode === 5 + ? 'a required verification command timed out' + : `the ${inputs.failOn} failure threshold was reached`; + core.setFailed(`SpecBridge verification failed: ${reason}. See the step summary and ${relative.markdown}.`); + } +} + +run().catch((error: unknown) => { + core.setFailed(error instanceof Error ? error.message : String(error)); +}); diff --git a/integrations/github-action/src/version.ts b/integrations/github-action/src/version.ts new file mode 100644 index 0000000..058a2fb --- /dev/null +++ b/integrations/github-action/src/version.ts @@ -0,0 +1,2 @@ +/** Action version, kept in sync with package.json (checked by tests). */ +export const ACTION_VERSION = '0.4.0'; diff --git a/integrations/github-action/tsconfig.json b/integrations/github-action/tsconfig.json new file mode 100644 index 0000000..883bfe4 --- /dev/null +++ b/integrations/github-action/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node"] + }, + "include": ["src/**/*.ts", "tsup.config.ts"] +} diff --git a/integrations/github-action/tsup.config.ts b/integrations/github-action/tsup.config.ts new file mode 100644 index 0000000..5799558 --- /dev/null +++ b/integrations/github-action/tsup.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'tsup'; + +/** + * Reproducible single-file bundle for the node20 GitHub Action runtime. + * + * Everything — workspace packages and npm dependencies alike — is inlined + * into dist/index.js (CommonJS), so consumers of `uses:` need no package + * manager, no pnpm, and no install step. The committed bundle is rebuilt in + * CI and diffed against the source to keep it honest. + */ +export default defineConfig({ + entry: { index: 'src/main.ts' }, + format: ['cjs'], + target: 'node20', + platform: 'node', + noExternal: [/.*/], + sourcemap: false, + minify: false, + clean: true, +}); diff --git a/package.json b/package.json index a994323..62d6ca7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "specbridge-monorepo", - "version": "0.3.0", + "version": "0.4.0", "private": true, "description": "An open, model-agnostic spec runtime for existing Kiro projects.", "license": "MIT", diff --git a/packages/cli/package.json b/packages/cli/package.json index bce141e..ba08b00 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "specbridge", - "version": "0.3.0", + "version": "0.4.0", "description": "An open, model-agnostic spec runtime for existing Kiro projects. No conversion, no duplicated specs, no lock-in.", "license": "MIT", "type": "module", @@ -28,6 +28,7 @@ "dependencies": { "@specbridge/compat-kiro": "workspace:*", "@specbridge/core": "workspace:*", + "@specbridge/drift": "workspace:*", "@specbridge/evidence": "workspace:*", "@specbridge/execution": "workspace:*", "@specbridge/reporting": "workspace:*", diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index f6e7999..92c9d6a 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -17,6 +17,9 @@ import { registerSpecStatusCommand } from './commands/spec-status.js'; import { registerSpecSyncCommand } from './commands/spec-sync.js'; import { registerSpecRunCommand } from './commands/spec-run.js'; import { registerSpecVerifyCommand } from './commands/spec-verify.js'; +import { registerSpecAffectedCommand } from './commands/spec-affected.js'; +import { registerSpecPolicyCommand } from './commands/spec-policy.js'; +import { registerVerifyRuleCommands } from './commands/verify-rules.js'; import { registerSpecExportCommand } from './commands/spec-export.js'; import { registerSpecGenerateCommand } from './commands/spec-generate.js'; import { registerSpecRefineCommand } from './commands/spec-refine.js'; @@ -73,8 +76,11 @@ honest error; nothing pretends to work before it does.`, registerSpecAcceptTaskCommand(spec, runtime); registerSpecSyncCommand(spec, runtime); registerSpecVerifyCommand(spec, runtime); + registerSpecAffectedCommand(spec, runtime); + registerSpecPolicyCommand(spec, runtime); registerSpecExportCommand(spec, runtime); + registerVerifyRuleCommands(program, runtime); registerRunnerCommands(program, runtime); registerRunCommands(program, runtime); registerCompatCheckCommand(program, runtime); diff --git a/packages/cli/src/commands/spec-accept-task.ts b/packages/cli/src/commands/spec-accept-task.ts index ad78cea..8941194 100644 --- a/packages/cli/src/commands/spec-accept-task.ts +++ b/packages/cli/src/commands/spec-accept-task.ts @@ -4,7 +4,12 @@ import { analyzeSpec, parseTasks, requireSpec } from '@specbridge/compat-kiro'; import { CLI_BIN, EXIT_CODES, SpecBridgeError, stateStage } from '@specbridge/core'; import type { TaskEvidenceRecord } from '@specbridge/evidence'; import { EVIDENCE_SCHEMA_VERSION, captureGitSnapshot, writeTaskEvidence } from '@specbridge/evidence'; -import { completeTaskCheckbox, readRunRecord, selectTask } from '@specbridge/execution'; +import { + buildEvidenceSpecContext, + completeTaskCheckbox, + readRunRecord, + selectTask, +} from '@specbridge/execution'; import { createJsonReport, dim, @@ -139,6 +144,7 @@ Example: acceptedAt, ...(referencedRunId !== undefined ? { referencedRunId } : {}), }, + specContext: buildEvidenceSpecContext(workspace, folder.name, spec.state, task), }; const evidencePath = writeTaskEvidence(workspace, record); diff --git a/packages/cli/src/commands/spec-affected.ts b/packages/cli/src/commands/spec-affected.ts new file mode 100644 index 0000000..7d83da6 --- /dev/null +++ b/packages/cli/src/commands/spec-affected.ts @@ -0,0 +1,133 @@ +import type { Command } from 'commander'; +import { CLI_BIN } from '@specbridge/core'; +import { resolveAffectedSpecs, resolveComparison } from '@specbridge/drift'; +import { + createJsonReport, + dim, + okLine, + reportTitle, + sectionTitle, + serializeJsonReport, + warnLine, +} from '@specbridge/reporting'; +import type { CliRuntime } from '../context.js'; +import type { ComparisonCliOptions } from '../verify-options.js'; +import { resolveComparisonRequest } from '../verify-options.js'; +import { VERSION } from '../version.js'; + +/** + * `specbridge spec affected` — which specs does a change set touch? + * Read-only: resolves the comparison and the deterministic spec mapping; + * runs no verification commands and writes nothing. + */ + +interface SpecAffectedOptions extends ComparisonCliOptions { + json?: boolean; +} + +export function registerSpecAffectedCommand(spec: Command, runtime: CliRuntime): void { + spec + .command('affected') + .description('Resolve which specs are affected by a git comparison (read-only)') + .option('--diff ', 'compare a git revision range, e.g. origin/main...HEAD') + .option('--base ', 'explicit base ref (with optional --head)') + .option('--head ', 'explicit head ref (defaults to HEAD)') + .option('--working-tree', 'compare working tree vs HEAD (default)') + .option('--staged', 'compare staged changes vs HEAD') + .option('--json', 'output a machine-readable JSON report') + .addHelpText( + 'after', + ` +A spec is affected when a changed file lives under .kiro/specs//, is +the spec's sidecar state or policy file, matches a declared impact area, +appears in accepted task evidence, or is explicitly referenced by design.md. + +Exit codes: 0 resolved · 2 invalid input · 3 git comparison unavailable. + +Examples: + ${CLI_BIN} spec affected --diff origin/main...HEAD + ${CLI_BIN} spec affected --working-tree --json`, + ) + .action(async (options: SpecAffectedOptions) => { + const workspace = runtime.workspace(); + const request = resolveComparisonRequest(options); + const comparison = await resolveComparison(workspace.rootDir, request); + + if (!comparison.ok) { + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.spec-affected/1', `${CLI_BIN} ${VERSION}`, { + comparison: comparison.descriptor, + ok: false, + failure: comparison.failure ?? null, + affected: [], + unmapped: [], + ambiguous: [], + }), + ), + ); + } else { + runtime.err(`Cannot resolve the comparison: ${comparison.failure?.message ?? 'unknown git failure'}`); + } + runtime.exitCode = 3; + return; + } + + const result = resolveAffectedSpecs(workspace, comparison.changedFiles); + + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.spec-affected/1', `${CLI_BIN} ${VERSION}`, { + comparison: comparison.descriptor, + ok: true, + changedFiles: comparison.changedFiles.map((file) => ({ + path: file.path, + changeType: file.changeType, + })), + affected: result.affected, + unmapped: result.unmapped.map((file) => file.path), + ambiguous: result.ambiguous, + }), + ), + ); + return; + } + + runtime.out(reportTitle('Affected specs')); + runtime.out(dim(`Comparison: ${comparison.descriptor.label}`)); + runtime.out(); + if (result.affected.length === 0) { + runtime.out(okLine('No spec is affected by this change set.')); + } + for (const affected of result.affected) { + runtime.out(`${affected.specName}`); + runtime.out(dim(' matched:')); + for (const match of affected.matches) { + runtime.out(` ${match.file}`); + runtime.out(dim(` via ${match.via.join(', ')}`)); + } + runtime.out(); + } + + if (result.ambiguous.length > 0) { + runtime.out(sectionTitle('Ambiguous mappings')); + for (const entry of result.ambiguous) { + runtime.out( + warnLine( + `${entry.path} maps to ${entry.specs.map((specMatch) => specMatch.name).join(' and ')}`, + ), + ); + } + runtime.out(); + } + + if (result.unmapped.length > 0) { + runtime.out(sectionTitle('Warnings')); + for (const file of result.unmapped) { + runtime.out(warnLine(`${file.path} does not map to any spec`)); + } + } + }); +} diff --git a/packages/cli/src/commands/spec-policy.ts b/packages/cli/src/commands/spec-policy.ts new file mode 100644 index 0000000..01ec969 --- /dev/null +++ b/packages/cli/src/commands/spec-policy.ts @@ -0,0 +1,351 @@ +import { existsSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import type { Command } from 'commander'; +import { MarkdownDocument, extractPathReferences, requireSpec, specFile } from '@specbridge/compat-kiro'; +import { CLI_BIN, SpecBridgeError, readAgentConfig, writeFileAtomic } from '@specbridge/core'; +import type { VerificationPolicy } from '@specbridge/drift'; +import { + VERIFICATION_POLICY_SCHEMA_VERSION, + policyPath, + readVerificationPolicy, + resolveEffectivePolicy, +} from '@specbridge/drift'; +import { listTaskEvidence } from '@specbridge/evidence'; +import { readdirSync } from 'node:fs'; +import { + createJsonReport, + dim, + failLine, + okLine, + reportTitle, + sectionTitle, + serializeJsonReport, + warnLine, +} from '@specbridge/reporting'; +import type { CliRuntime } from '../context.js'; +import { relPath } from '../context.js'; +import { VERSION } from '../version.js'; + +/** + * `specbridge spec policy init|show|validate` — spec-specific verification + * policy management. A policy file is plain configuration under + * `.specbridge/policies/.json`; it is never a spec stage and needs no + * approval. `init` is the only writing subcommand and never overwrites. + */ + +interface PolicyInitOptions { + mode?: string; + dryRun?: boolean; + json?: boolean; +} + +interface PolicyReadOptions { + json?: boolean; +} + +function isInfrastructurePath(candidate: string): boolean { + return ( + candidate.startsWith('.git') || + candidate.startsWith('.kiro/') || + candidate.startsWith('.specbridge/') + ); +} + +/** + * Propose impact areas from observed paths: the first two directory segments + * become a `dir/**` pattern (top-level files stay exact). Proposals are + * hints for review, never authoritative. + */ +export function proposeImpactAreas(paths: readonly string[]): string[] { + const areas = new Set(); + for (const candidate of paths) { + const posix = candidate.split('\\').join('/'); + if (posix.length === 0 || isInfrastructurePath(posix)) continue; + const segments = posix.split('/'); + if (segments.length === 1) { + areas.add(posix); + continue; + } + const depth = Math.min(2, segments.length - 1); + areas.add(`${segments.slice(0, depth).join('/')}/**`); + } + return [...areas].sort((a, b) => a.localeCompare(b, 'en')); +} + +function collectProposalSources( + runtime: CliRuntime, + specName: string, +): { paths: string[]; sources: string[] } { + const workspace = runtime.workspace(); + const folder = requireSpec(workspace, specName); + const paths: string[] = []; + const sources: string[] = []; + + const design = specFile(folder, 'design'); + if (design !== undefined) { + try { + const references = extractPathReferences(MarkdownDocument.load(design.path)); + const explicit = references.filter((reference) => !reference.isGlob); + if (explicit.length > 0) { + paths.push(...explicit.map((reference) => reference.path)); + sources.push(`design.md (${explicit.length} explicit path reference${explicit.length === 1 ? '' : 's'})`); + } + } catch { + // Unreadable design contributes nothing. + } + } + + const evidenceDir = path.join(workspace.sidecarDir, 'evidence', specName); + if (existsSync(evidenceDir)) { + let evidencePathCount = 0; + for (const entry of readdirSync(evidenceDir, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const { records } = listTaskEvidence(workspace, specName, entry.name); + for (const record of records) { + if (record.status !== 'verified' && record.status !== 'manually-accepted') continue; + for (const file of record.changedFiles) { + paths.push(file.path); + evidencePathCount += 1; + } + } + } + if (evidencePathCount > 0) { + sources.push(`task evidence (${evidencePathCount} recorded file change${evidencePathCount === 1 ? '' : 's'})`); + } + } + + return { paths, sources }; +} + +export function registerSpecPolicyCommand(spec: Command, runtime: CliRuntime): void { + const policy = spec + .command('policy') + .description('Manage spec-specific verification policies (.specbridge/policies/)'); + + policy + .command('init ') + .description('Create a starter verification policy for a spec (never overwrites)') + .option('--mode ', 'advisory or strict', 'advisory') + .option('--dry-run', 'print the proposed policy without writing it') + .option('--json', 'output a machine-readable JSON report') + .addHelpText( + 'after', + ` +Impact areas are proposed from explicit design.md path references and +recorded task evidence — they are hints, not authoritative facts. Review the +file before enforcing strict verification. + +Example: + ${CLI_BIN} spec policy init notification-preferences --mode strict`, + ) + .action((name: string, options: PolicyInitOptions) => { + const workspace = runtime.workspace(); + requireSpec(workspace, name); + const mode = options.mode ?? 'advisory'; + if (mode !== 'advisory' && mode !== 'strict') { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `--mode must be advisory or strict, got "${mode}".`, + ); + } + const filePath = policyPath(workspace, name); + if (existsSync(filePath) && options.dryRun !== true) { + throw new SpecBridgeError( + 'INVALID_STATE', + `A verification policy already exists at ${relPath(workspace, filePath)}. ` + + 'Edit it directly, or delete it first — policy init never overwrites.', + ); + } + + const { paths, sources } = collectProposalSources(runtime, name); + const impactAreas = proposeImpactAreas(paths); + const configRead = readAgentConfig(workspace); + const requiredCommands = (configRead.config?.verification.commands ?? []) + .filter((command) => command.required) + .map((command) => command.name); + + const proposal: VerificationPolicy = { + schemaVersion: VERIFICATION_POLICY_SCHEMA_VERSION, + specName: name, + mode, + impactAreas, + protectedPaths: [], + requiredVerificationCommands: requiredCommands, + requireVerifiedTaskEvidence: false, + requireRequirementTaskLinks: false, + requireTestEvidence: false, + rules: {}, + }; + const serialized = `${JSON.stringify(proposal, null, 2)}\n`; + + if (options.dryRun !== true) { + writeFileAtomic(filePath, serialized); + } + + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.policy-init/1', `${CLI_BIN} ${VERSION}`, { + specName: name, + path: relPath(workspace, filePath), + written: options.dryRun !== true, + dryRun: options.dryRun === true, + policy: proposal, + proposalSources: sources, + }), + ), + ); + return; + } + + runtime.out( + reportTitle( + options.dryRun === true + ? 'Verification policy proposal (dry run — nothing written):' + : 'Verification policy created:', + ), + ); + runtime.out(); + runtime.out(` ${relPath(workspace, filePath)}`); + runtime.out(); + runtime.out(sectionTitle('Impact areas')); + if (impactAreas.length === 0) { + runtime.out(dim(' (none proposed — no explicit design paths or evidence found)')); + } else { + for (const area of impactAreas) runtime.out(` ${area}`); + } + if (sources.length > 0) { + runtime.out(dim(` Proposed from: ${sources.join('; ')} — review before trusting.`)); + } + runtime.out(); + runtime.out(sectionTitle('Required commands')); + if (requiredCommands.length === 0) { + runtime.out(dim(' (none — configure verification.commands in .specbridge/config.json)')); + } else { + for (const command of requiredCommands) runtime.out(` ${command}`); + } + runtime.out(); + runtime.out('Review this file before enforcing strict verification.'); + if (options.dryRun === true) { + runtime.out(dim('Dry run: no file was written.')); + } + }); + + policy + .command('show ') + .description('Show the stored and effective verification policy for a spec (read-only)') + .option('--json', 'output a machine-readable JSON report') + .action((name: string, options: PolicyReadOptions) => { + const workspace = runtime.workspace(); + requireSpec(workspace, name); + const read = readVerificationPolicy(workspace, name); + const configRead = readAgentConfig(workspace); + const effective = resolveEffectivePolicy(workspace, name, { + globalProtectedPaths: configRead.config?.execution.protectedPaths ?? [], + }); + + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.policy-show/1', `${CLI_BIN} ${VERSION}`, { + specName: name, + path: relPath(workspace, read.path), + exists: read.exists, + policy: read.policy ?? null, + diagnostics: read.diagnostics, + effective, + }), + ), + ); + return; + } + + runtime.out(reportTitle(`Verification policy: ${name}`)); + runtime.out(dim(` ${relPath(workspace, read.path)}${read.exists ? '' : ' (not present — defaults apply)'}`)); + for (const diagnostic of read.diagnostics) { + runtime.out(failLine(diagnostic.message)); + } + runtime.out(); + runtime.out(sectionTitle('Effective policy')); + runtime.out(` Mode: ${effective.mode}`); + runtime.out( + ` Impact areas: ${effective.impactAreas.length > 0 ? effective.impactAreas.join(', ') : '(none declared)'}`, + ); + runtime.out(` Protected paths: ${effective.protectedPaths.join(', ')}`); + runtime.out( + ` Required commands: ${effective.requiredVerificationCommands.length > 0 ? effective.requiredVerificationCommands.join(', ') : '(none)'}`, + ); + runtime.out(` Require verified task evidence: ${effective.requireVerifiedTaskEvidence}`); + runtime.out(` Require requirement-task links: ${effective.requireRequirementTaskLinks}`); + runtime.out(` Require test evidence: ${effective.requireTestEvidence}`); + const overrides = Object.entries(effective.ruleOverrides); + if (overrides.length > 0) { + runtime.out(sectionTitle('Rule overrides')); + for (const [ruleId, override] of overrides) { + runtime.out( + ` ${ruleId}: ${override.enabled ? 'enabled' : 'disabled'}${override.severity !== undefined ? `, severity ${override.severity}` : ''}`, + ); + } + } + }); + + policy + .command('validate ') + .description('Validate a verification policy file against the versioned schema (read-only)') + .option('--json', 'output a machine-readable JSON report') + .addHelpText('after', '\nExit codes: 0 valid · 1 invalid · 2 no policy file / usage error.') + .action((name: string, options: PolicyReadOptions) => { + const workspace = runtime.workspace(); + requireSpec(workspace, name); + const read = readVerificationPolicy(workspace, name); + if (!read.exists) { + throw new SpecBridgeError( + 'INVALID_STATE', + `No verification policy exists at ${relPath(workspace, read.path)}. Create one with "${CLI_BIN} spec policy init ${name}".`, + ); + } + + const problems: string[] = read.diagnostics.map((diagnostic) => diagnostic.message); + if (read.policy !== undefined) { + // Required command names must exist in the trusted configuration. + const configRead = readAgentConfig(workspace); + const configured = new Set( + (configRead.config?.verification.commands ?? []).map((command) => command.name), + ); + for (const required of read.policy.requiredVerificationCommands) { + if (!configured.has(required)) { + problems.push( + `requiredVerificationCommands names "${required}", which is not configured in .specbridge/config.json (SBV013 would fail verification).`, + ); + } + } + } + + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.policy-validate/1', `${CLI_BIN} ${VERSION}`, { + specName: name, + path: relPath(workspace, read.path), + valid: problems.length === 0, + problems, + }), + ), + ); + runtime.exitCode = problems.length === 0 ? 0 : 1; + return; + } + + runtime.out(reportTitle(`Validate policy: ${relPath(workspace, read.path)}`)); + if (problems.length === 0) { + runtime.out(okLine('The policy is valid.')); + const raw = JSON.parse(readFileSync(read.path, 'utf8')) as { mode?: string }; + runtime.out(dim(` Mode: ${raw.mode ?? 'advisory'}`)); + } else { + for (const problem of problems) runtime.out(failLine(problem)); + runtime.out(); + runtime.out(warnLine('Fix the problems above; verification would report SBV020/SBV013.')); + runtime.exitCode = 1; + } + }); +} diff --git a/packages/cli/src/commands/spec-verify.ts b/packages/cli/src/commands/spec-verify.ts index 66b77d1..fc3021e 100644 --- a/packages/cli/src/commands/spec-verify.ts +++ b/packages/cli/src/commands/spec-verify.ts @@ -1,18 +1,208 @@ +import path from 'node:path'; import type { Command } from 'commander'; +import type { FailOnThreshold, VerificationReport } from '@specbridge/core'; +import { CLI_BIN, SpecBridgeError, writeFileAtomic } from '@specbridge/core'; +import type { VerifySelection } from '@specbridge/drift'; +import { verifySpecs } from '@specbridge/drift'; +import { + dim, + renderVerificationHtml, + renderVerificationMarkdown, + renderVerificationTerminal, + serializeJsonReport, +} from '@specbridge/reporting'; import type { CliRuntime } from '../context.js'; -import { registerPlannedCommand } from '../context.js'; +import { relPath } from '../context.js'; +import type { ComparisonCliOptions } from '../verify-options.js'; +import { resolveComparisonRequest } from '../verify-options.js'; +import { VERSION } from '../version.js'; /** - * Planned: Phase H (deterministic spec-drift verification; no LLM). - * The underlying checks already exist as a tested library in - * @specbridge/drift — this command wires them to live git repositories. + * `specbridge spec verify` — deterministic spec-to-code drift verification. + * + * Read-only by default: no spec content, approval state, task state, or + * evidence is ever modified. The only writes are report artifacts (command + * logs and report.json when trusted commands execute, plus the --output + * file when requested). No model is involved anywhere. */ + +interface SpecVerifyOptions extends ComparisonCliOptions { + changed?: boolean; + all?: boolean; + runVerification?: boolean; + policy?: string; + failOn?: string; + strict?: boolean; + json?: boolean; + format?: string; + output?: string; + verbose?: boolean; +} + +const FORMATS = ['terminal', 'json', 'markdown', 'html'] as const; +type OutputFormat = (typeof FORMATS)[number]; + +function resolveSelection(name: string | undefined, options: SpecVerifyOptions): VerifySelection { + const modes: string[] = []; + if (name !== undefined) modes.push(`spec "${name}"`); + if (options.changed === true) modes.push('--changed'); + if (options.all === true) modes.push('--all'); + if (modes.length > 1) { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `Choose one selection mode — ${modes.join(', ')} are mutually exclusive.`, + ); + } + if (name !== undefined) return { mode: 'single', spec: name }; + if (options.changed === true) return { mode: 'changed' }; + if (options.all === true) return { mode: 'all' }; + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `Select what to verify: a spec name, --changed (specs affected by the comparison), or --all.`, + ); +} + +function resolveFormat(options: SpecVerifyOptions): OutputFormat { + if (options.json === true && options.format !== undefined && options.format !== 'json') { + throw new SpecBridgeError('INVALID_ARGUMENT', '--json conflicts with --format; use one.'); + } + if (options.json === true) return 'json'; + const format = options.format ?? 'terminal'; + if (!(FORMATS as readonly string[]).includes(format)) { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `--format must be one of ${FORMATS.join(', ')}, got "${format}".`, + ); + } + return format as OutputFormat; +} + +function resolveFailOn(options: SpecVerifyOptions): FailOnThreshold { + const failOn = options.failOn ?? 'error'; + if (failOn !== 'error' && failOn !== 'warning' && failOn !== 'never') { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `--fail-on must be error, warning, or never, got "${failOn}".`, + ); + } + return failOn; +} + +function renderReport( + report: VerificationReport, + format: OutputFormat, + verbose: boolean, +): string { + switch (format) { + case 'json': + return serializeJsonReport(report); + case 'markdown': + return renderVerificationMarkdown(report); + case 'html': + return renderVerificationHtml(report); + case 'terminal': + return `${renderVerificationTerminal(report, { verbose }).join('\n')}\n`; + } +} + export function registerSpecVerifyCommand(spec: Command, runtime: CliRuntime): void { - registerPlannedCommand(spec, runtime, { - name: 'verify', - args: '[name]', - summary: 'Deterministically verify spec-to-code alignment against a git diff (CI quality gate)', - phase: 'the sync-and-drift phase (Phase H)', - workaround: 'the deterministic checks are available today as the @specbridge/drift library.', - }); + spec + .command('verify [name]') + .description('Deterministically verify spec-to-code alignment against a git comparison') + .option('--changed', 'verify every spec affected by the comparison') + .option('--all', 'verify every spec in the workspace') + .option('--diff ', 'compare a git revision range, e.g. origin/main...HEAD') + .option('--base ', 'explicit base ref (with optional --head)') + .option('--head ', 'explicit head ref (defaults to HEAD)') + .option('--working-tree', 'compare working tree (staged + unstaged + untracked) vs HEAD (default)') + .option('--staged', 'compare staged changes vs HEAD') + .option('--run-verification', 'run every trusted command from .specbridge/config.json') + .option('--no-run-verification', 'never run commands; reuse valid evidence where possible') + .option('--policy ', 'explicit verification policy file (single-spec mode)') + .option('--fail-on ', 'failure threshold: error, warning, or never', 'error') + .option('--strict', 'strict verification behavior (tightens, never loosens, the policy)') + .option('--json', 'print the JSON report to stdout (same as --format json)') + .option('--format ', 'terminal (default), json, markdown, or html') + .option('--output ', 'write the report to a file instead of stdout') + .option('--verbose', 'include info diagnostics and full file lists') + .addHelpText( + 'after', + ` +Verification is read-only: it never edits .kiro files, never marks task +checkboxes, and never changes approval state or evidence. Commands run only +from trusted .specbridge/config.json configuration — never from spec text. + +By default only commands required by a spec policy run; --run-verification +runs everything configured, --no-run-verification runs nothing and reuses +valid evidence recorded at the current HEAD where possible. + +Exit codes: + 0 passed per --fail-on · 1 threshold reached · 2 invalid input/policy/state + 3 git comparison unavailable · 4 command failed to start · 5 command timeout + +Examples: + ${CLI_BIN} spec verify notification-preferences --working-tree + ${CLI_BIN} spec verify notification-preferences --diff origin/main...HEAD --run-verification + ${CLI_BIN} spec verify --changed --diff origin/main...HEAD + ${CLI_BIN} spec verify --all --working-tree --fail-on warning`, + ) + .action(async (name: string | undefined, options: SpecVerifyOptions) => { + const workspace = runtime.workspace(); + const selection = resolveSelection(name, options); + const comparison = resolveComparisonRequest(options); + const format = resolveFormat(options); + const failOn = resolveFailOn(options); + if (options.output !== undefined && format === 'terminal') { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + '--output needs a file format: pass --format json, markdown, or html.', + ); + } + + // Progress only in interactive terminal mode; machine formats stay clean. + const interactive = + format === 'terminal' && options.output === undefined && process.stderr.isTTY === true; + + const result = await verifySpecs({ + workspace, + selection, + comparison, + ...(options.runVerification !== undefined + ? { runVerification: options.runVerification } + : {}), + ...(options.strict !== undefined ? { strict: options.strict } : {}), + failOn, + ...(options.policy !== undefined ? { explicitPolicyPath: options.policy } : {}), + toolVersion: VERSION, + reportsDir: path.join(workspace.sidecarDir, 'reports'), + clock: () => runtime.now(), + ...(interactive ? { onProgress: (message: string) => runtime.err(dim(message)) } : {}), + }); + + if (options.strict === true && format === 'terminal') { + const raised = result.report.specResults + .filter((specResult) => specResult.policyMode === 'strict') + .map((specResult) => specResult.specName); + if (raised.length > 0) { + runtime.err( + dim( + `--strict: strict-mode severities apply to ${raised.join(', ')} (the policy files themselves are unchanged).`, + ), + ); + } + } + + const rendered = renderReport(result.report, format, options.verbose === true); + if (options.output !== undefined) { + const outputPath = path.resolve(runtime.cwd, options.output); + writeFileAtomic(outputPath, rendered); + runtime.out(`Report written: ${relPath(workspace, outputPath)}`); + } else { + runtime.outRaw(rendered); + } + if (result.artifactsDir !== undefined && format === 'terminal') { + runtime.out(dim(`Artifacts: ${relPath(workspace, result.artifactsDir)}`)); + } + runtime.exitCode = result.exitCode; + }); } diff --git a/packages/cli/src/commands/verify-rules.ts b/packages/cli/src/commands/verify-rules.ts new file mode 100644 index 0000000..7ee1e28 --- /dev/null +++ b/packages/cli/src/commands/verify-rules.ts @@ -0,0 +1,112 @@ +import type { Command } from 'commander'; +import { CLI_BIN } from '@specbridge/core'; +import { builtInVerificationRules, describeDefaultSeverity, findRule } from '@specbridge/drift'; +import { + createJsonReport, + dim, + renderColumns, + reportTitle, + sectionTitle, + serializeJsonReport, +} from '@specbridge/reporting'; +import type { CliRuntime } from '../context.js'; +import { VERSION } from '../version.js'; + +/** + * `specbridge verify rules` / `specbridge verify explain ` — + * deterministic, read-only inspection of the built-in verification rules. + */ + +interface RulesOptions { + json?: boolean; +} + +export function registerVerifyRuleCommands(program: Command, runtime: CliRuntime): void { + const verify = program + .command('verify') + .description('Inspect the deterministic verification rules (read-only)'); + + verify + .command('rules') + .description('List every built-in verification rule with its stable ID') + .option('--json', 'output a machine-readable JSON report') + .action((options: RulesOptions) => { + const rules = builtInVerificationRules(); + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.verify-rules/1', `${CLI_BIN} ${VERSION}`, { + rules: rules.map((rule) => ({ + id: rule.id, + title: rule.title, + category: rule.category, + scope: rule.scope, + confidence: rule.confidence, + defaultSeverity: rule.defaultSeverity, + })), + }), + ), + ); + return; + } + runtime.out(reportTitle(`Verification rules (${rules.length})`)); + runtime.out(); + const rows = rules.map((rule) => [ + rule.id, + rule.defaultSeverity.advisory === rule.defaultSeverity.strict + ? rule.defaultSeverity.advisory + : `${rule.defaultSeverity.advisory}/${rule.defaultSeverity.strict}`, + rule.category, + rule.confidence === 'heuristic' ? `${rule.title} (heuristic)` : rule.title, + ]); + for (const line of renderColumns(rows)) runtime.out(line); + runtime.out(); + runtime.out(dim(`Severity column shows advisory/strict defaults; policies may override per rule.`)); + runtime.out(dim(`Details: ${CLI_BIN} verify explain `)); + }); + + verify + .command('explain ') + .description('Explain one verification rule: trigger, defaults, and resolution') + .option('--json', 'output a machine-readable JSON report') + .action((ruleId: string, options: RulesOptions) => { + const rule = findRule(ruleId); + if (rule === undefined) { + runtime.err( + `Unknown rule "${ruleId}". Valid IDs run SBV001–SBV025; list them with "${CLI_BIN} verify rules".`, + ); + runtime.exitCode = 2; + return; + } + if (options.json === true) { + runtime.outRaw( + serializeJsonReport( + createJsonReport('specbridge.verify-explain/1', `${CLI_BIN} ${VERSION}`, { + id: rule.id, + title: rule.title, + category: rule.category, + scope: rule.scope, + confidence: rule.confidence, + defaultSeverity: rule.defaultSeverity, + triggeredWhen: rule.triggeredWhen, + resolution: rule.resolution, + }), + ), + ); + return; + } + runtime.out(reportTitle(`${rule.id} — ${rule.title}`)); + runtime.out(); + runtime.out(sectionTitle('Default severity')); + runtime.out(` ${describeDefaultSeverity(rule)}`); + runtime.out(); + runtime.out(sectionTitle('Category')); + runtime.out(` ${rule.category} (${rule.confidence}, ${rule.scope}-scoped)`); + runtime.out(); + runtime.out(sectionTitle('Triggered when')); + runtime.out(` ${rule.triggeredWhen}`); + runtime.out(); + runtime.out(sectionTitle('Resolution')); + runtime.out(` ${rule.resolution}`); + }); +} diff --git a/packages/cli/src/verify-options.ts b/packages/cli/src/verify-options.ts new file mode 100644 index 0000000..3329e1b --- /dev/null +++ b/packages/cli/src/verify-options.ts @@ -0,0 +1,64 @@ +import type { ComparisonRequest } from '@specbridge/drift'; +import { isSafeGitRef, parseDiffRange } from '@specbridge/drift'; +import { SpecBridgeError } from '@specbridge/core'; + +/** + * Shared comparison-option parsing for `spec verify` and `spec affected`. + * Exactly one comparison mode may be selected; the default is the working + * tree (staged + unstaged + untracked changes against HEAD). + */ + +export interface ComparisonCliOptions { + diff?: string; + base?: string; + head?: string; + workingTree?: boolean; + staged?: boolean; +} + +export function resolveComparisonRequest(options: ComparisonCliOptions): ComparisonRequest { + const modes: string[] = []; + if (options.diff !== undefined) modes.push('--diff'); + if (options.base !== undefined || options.head !== undefined) modes.push('--base/--head'); + if (options.workingTree === true) modes.push('--working-tree'); + if (options.staged === true) modes.push('--staged'); + if (modes.length > 1) { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `Choose one comparison mode — ${modes.join(', ')} are mutually exclusive.`, + ); + } + + if (options.diff !== undefined) { + const range = parseDiffRange(options.diff); + if (range === undefined) { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `--diff expects "..." (e.g. origin/main...HEAD), got "${options.diff}".`, + ); + } + assertRef(range.base, 'base'); + assertRef(range.head, 'head'); + return { mode: 'diff', base: range.base, head: range.head }; + } + if (options.base !== undefined || options.head !== undefined) { + if (options.base === undefined) { + throw new SpecBridgeError('INVALID_ARGUMENT', '--head requires --base .'); + } + const head = options.head ?? 'HEAD'; + assertRef(options.base, 'base'); + assertRef(head, 'head'); + return { mode: 'diff', base: options.base, head }; + } + if (options.staged === true) return { mode: 'staged' }; + return { mode: 'working-tree' }; +} + +function assertRef(ref: string, role: string): void { + if (!isSafeGitRef(ref)) { + throw new SpecBridgeError( + 'INVALID_ARGUMENT', + `The ${role} ref "${ref}" is not a valid git ref (refs must not start with "-" or contain whitespace).`, + ); + } +} diff --git a/packages/cli/src/version.ts b/packages/cli/src/version.ts index 468ebce..5e52110 100644 --- a/packages/cli/src/version.ts +++ b/packages/cli/src/version.ts @@ -2,4 +2,4 @@ * Single source of the CLI version string. Keep in sync with * packages/cli/package.json when releasing (checked by scripts/smoke.mjs). */ -export const VERSION = '0.3.0'; +export const VERSION = '0.4.0'; diff --git a/packages/compat-kiro/package.json b/packages/compat-kiro/package.json index 9e7761b..e649089 100644 --- a/packages/compat-kiro/package.json +++ b/packages/compat-kiro/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/compat-kiro", - "version": "0.3.0", + "version": "0.4.0", "description": "Read and round-trip-safely edit existing .kiro steering and spec files without migration.", "license": "MIT", "type": "module", diff --git a/packages/compat-kiro/src/index.ts b/packages/compat-kiro/src/index.ts index 2568e5d..fbf43a6 100644 --- a/packages/compat-kiro/src/index.ts +++ b/packages/compat-kiro/src/index.ts @@ -10,3 +10,5 @@ export * from './bugfix-parser.js'; export * from './roundtrip-writer.js'; export * from './diagnostics.js'; export * from './agent-context.js'; +export * from './task-plan-hash.js'; +export * from './traceability.js'; diff --git a/packages/compat-kiro/src/task-plan-hash.ts b/packages/compat-kiro/src/task-plan-hash.ts new file mode 100644 index 0000000..2884a03 --- /dev/null +++ b/packages/compat-kiro/src/task-plan-hash.ts @@ -0,0 +1,82 @@ +import { sha256Hex } from '@specbridge/core'; +import { MarkdownDocument } from './markdown-document.js'; +import type { TaskItem } from './tasks-parser.js'; + +/** + * Normalized task-plan hashing (hash semantics version "2", see + * TASK_PLAN_HASH_SEMANTICS_VERSION in @specbridge/core). + * + * The plan hash answers one question: "is this the same task plan that was + * approved, ignoring checkbox progress?" Normalization therefore touches + * exactly one thing — the single state character between the brackets of a + * recognized checkbox line — and nothing else: + * + * - task text, numbering, indentation, and hierarchy are NOT normalized + * - requirement references and detail lines are NOT normalized + * - line endings, BOM, and trailing-newline style are NOT normalized + * - checkbox-looking lines inside fenced code blocks are content, not + * tasks, and are NOT normalized + * - unrecognized state characters (anything outside ` `, `x`, `X`, `-`, + * `~`) are NOT normalized — changing them is a content change + * + * Consequently `[ ]` → `[x]` progress keeps the plan hash stable while every + * other byte change produces a different hash. + */ + +/** Matches the checkbox prefix of a task line with a recognized state char. */ +const CHECKBOX_STATE_PREFIX = /^([ \t]*[-*+][ \t]+\[)([ xX~-])(\])/; + +/** The canonical (open) state every recognized checkbox is normalized to. */ +const NORMALIZED_STATE = ' '; + +/** + * The document text with recognized checkbox states normalized to `[ ]`. + * Every other byte — including the BOM and each line's original ending — + * is reproduced exactly. + */ +export function normalizedTaskPlanText(document: MarkdownDocument): string { + const mask = document.codeFenceMask(); + let out = document.hasBom ? String.fromCharCode(0xfeff) : ''; + for (let i = 0; i < document.lineCount; i += 1) { + const line = document.lineAt(i); + let text = line.text; + if (mask[i] !== true) { + const match = CHECKBOX_STATE_PREFIX.exec(text); + if (match !== null && match[1] !== undefined && match[3] !== undefined) { + text = `${match[1]}${NORMALIZED_STATE}${match[3]}${text.slice(match[0].length)}`; + } + } + out += text + line.eol; + } + return out; +} + +/** SHA-256 (hex) of the checkbox-normalized document text. */ +export function taskPlanHash(document: MarkdownDocument): string { + return sha256Hex(Buffer.from(normalizedTaskPlanText(document), 'utf8')); +} + +/** Plan hash of a tasks file on disk, or undefined when it cannot be read. */ +export function tryTaskPlanHashOfFile(filePath: string): string | undefined { + try { + return taskPlanHash(MarkdownDocument.load(filePath)); + } catch { + return undefined; + } +} + +/** + * Stable fingerprint of one task's plan-relevant identity: its ID, title, + * and requirement references. Checkbox state is deliberately excluded, so + * progress does not change the fingerprint while renaming, renumbering, or + * re-referencing the task does. + */ +export function taskFingerprint(task: Pick): string { + return sha256Hex( + JSON.stringify({ + id: task.id, + title: task.title, + requirementRefs: [...task.requirementRefs], + }), + ); +} diff --git a/packages/compat-kiro/src/traceability.ts b/packages/compat-kiro/src/traceability.ts new file mode 100644 index 0000000..f3c99db --- /dev/null +++ b/packages/compat-kiro/src/traceability.ts @@ -0,0 +1,470 @@ +import type { MarkdownDocument } from './markdown-document.js'; +import type { RequirementsModel } from './requirements-parser.js'; +import type { TaskItem, TasksModel } from './tasks-parser.js'; + +/** + * Traceability extraction: requirement identifiers, task-to-requirement + * references, test-required language, and explicit repository paths — all + * read from the tolerant document models without regenerating any Markdown. + * + * Every extracted relation records its source line, the extraction method, + * and whether the extraction is deterministic (explicit syntax) or heuristic + * (pattern recognition over prose). Heuristic relations must never be + * presented as proven facts downstream. + */ + +export type TraceabilityConfidence = 'deterministic' | 'heuristic'; + +/* ------------------------------------------------------------------ * + * Requirement identifier canonicalization + * ------------------------------------------------------------------ */ + +const ID_PREFIX = /^(?:requirements?|req|r|ac|criterion)[-_. ]?(?=\d)/i; +const CANONICAL_SHAPE = /^\d+(?:[.-]\d+)*$/; + +/** + * Canonical form of a requirement/criterion reference, or undefined when the + * text is not identifier-shaped. Documented normalization rules: + * + * - case-insensitive + * - optional `R`, `REQ`, `AC`, `Requirement`, `Criterion` prefix with an + * optional `-`, `_`, `.`, or space separator is stripped + * - `-` separators between numbers are treated as `.` + * - leading zeros in each numeric segment are dropped (REQ-001 ≡ REQ-1) + * + * Examples: `R1` → `1`, `REQ-001` → `1`, `Requirement 2` → `2`, + * `AC1.2` → `1.2`, `1.1` → `1.1`. Free text like `TBD` returns undefined. + */ +export function canonicalRequirementRef(raw: string): string | undefined { + const trimmed = raw.trim().toLowerCase(); + if (trimmed.length === 0) return undefined; + const withoutPrefix = trimmed.replace(ID_PREFIX, ''); + if (!CANONICAL_SHAPE.test(withoutPrefix)) return undefined; + return withoutPrefix + .split(/[.-]/) + .map((segment) => segment.replace(/^0+(?=\d)/, '')) + .join('.'); +} + +/* ------------------------------------------------------------------ * + * Requirement catalog + * ------------------------------------------------------------------ */ + +/** Heuristic recognizer for "this explicitly calls for tests" language. */ +const TEST_LANGUAGE = /\btest(?:s|ed|ing)?\b|\bunit[- ]tested\b|\bcovered by tests\b/i; + +export function mentionsTests(text: string): boolean { + return TEST_LANGUAGE.test(text); +} + +export interface RequirementCatalogEntry { + /** Identifier as written in the document (e.g. `REQ-001`, `1.2`). */ + displayId: string; + canonical: string; + kind: 'requirement' | 'criterion'; + /** 0-based source line of the heading or criterion. */ + line: number; + title?: string; + /** Heuristic: the requirement/criterion text explicitly mentions tests. */ + testRequired: boolean; + /** Canonical id of the owning requirement (itself for requirements). */ + requirementCanonical: string; + /** How the identifier was recognized. */ + method: 'requirements-parser' | 'id-heading' | 'explicit-ac-marker'; + confidence: TraceabilityConfidence; +} + +export interface RequirementCatalog { + entries: RequirementCatalogEntry[]; + /** Requirement-kind entries only, in document order. */ + requirements: RequirementCatalogEntry[]; + byCanonical: Map; +} + +/** Supplemental ID-style headings the tolerant parser does not treat as requirements. */ +const ID_HEADING = /^((?:req)[-_. ]?\d+(?:[.-]\d+)*)[ \t]*[:.–—-]?[ \t]*(.*)$/i; +const EXPLICIT_AC_MARKER = /^(ac[-_. ]?\d+(?:[.-]\d+)*)[ \t]*[:.–—-][ \t]*/i; +const ORDERED_ITEM = /^[ \t]*(\d+)[.)][ \t]+(.+)$/; + +/** + * Build the catalog of identifiable requirements and acceptance criteria. + * + * Sources, in order: + * 1. the tolerant requirements parser (`Requirement 1`, `R1` headings and + * their numbered acceptance criteria) — deterministic + * 2. supplemental `REQ-001`-style level 2–4 headings the parser does not + * recognize as requirements — deterministic + * 3. explicit `AC-1:` markers inside criterion text — deterministic aliases + */ +export function buildRequirementCatalog( + model: RequirementsModel, + document?: MarkdownDocument, +): RequirementCatalog { + const entries: RequirementCatalogEntry[] = []; + const byCanonical = new Map(); + + const add = (entry: RequirementCatalogEntry): void => { + entries.push(entry); + if (!byCanonical.has(entry.canonical)) byCanonical.set(entry.canonical, entry); + }; + + for (const requirement of model.requirements) { + const canonical = canonicalRequirementRef(requirement.id); + if (canonical === undefined) continue; + const requirementEntry: RequirementCatalogEntry = { + displayId: requirement.id, + canonical, + kind: 'requirement', + line: requirement.headingLine, + ...(requirement.title !== undefined ? { title: requirement.title } : {}), + testRequired: + (requirement.title !== undefined && mentionsTests(requirement.title)) || + requirement.criteria.some((criterion) => mentionsTests(criterion.text)), + requirementCanonical: canonical, + method: 'requirements-parser', + confidence: 'deterministic', + }; + add(requirementEntry); + + for (const criterion of requirement.criteria) { + const criterionCanonical = canonicalRequirementRef(criterion.id); + if (criterionCanonical === undefined) continue; + add({ + displayId: criterion.id, + canonical: criterionCanonical, + kind: 'criterion', + line: criterion.line, + testRequired: mentionsTests(criterion.text), + requirementCanonical: canonical, + method: 'requirements-parser', + confidence: 'deterministic', + }); + // An explicit `AC-3:` marker at the start of the criterion text is an + // alias the author expects tasks to reference. + const marker = EXPLICIT_AC_MARKER.exec(criterion.text); + const markerCanonical = + marker?.[1] !== undefined ? canonicalRequirementRef(marker[1]) : undefined; + if (markerCanonical !== undefined && markerCanonical !== criterionCanonical) { + add({ + displayId: (marker as RegExpExecArray)[1] as string, + canonical: markerCanonical, + kind: 'criterion', + line: criterion.line, + testRequired: mentionsTests(criterion.text), + requirementCanonical: canonical, + method: 'explicit-ac-marker', + confidence: 'deterministic', + }); + } + } + } + + // Supplemental REQ-### headings (level 2–4) outside recognized requirements. + if (document !== undefined) { + const knownHeadingLines = new Set(model.requirements.map((r) => r.headingLine)); + const sections = document.sections(); + const mask = document.codeFenceMask(); + for (const section of sections) { + if (section.heading.level < 2 || section.heading.level > 4) continue; + if (knownHeadingLines.has(section.heading.line)) continue; + const match = ID_HEADING.exec(section.heading.text.trim()); + if (match === null || match[1] === undefined) continue; + const canonical = canonicalRequirementRef(match[1]); + if (canonical === undefined || byCanonical.has(canonical)) continue; + const title = (match[2] ?? '').trim(); + const sectionText = document.getText(section.startLine, section.endLine); + const entry: RequirementCatalogEntry = { + displayId: match[1], + canonical, + kind: 'requirement', + line: section.heading.line, + ...(title.length > 0 ? { title } : {}), + testRequired: mentionsTests(sectionText), + requirementCanonical: canonical, + method: 'id-heading', + confidence: 'deterministic', + }; + add(entry); + // Numbered list items in the section become its criteria. + for (let i = section.startLine + 1; i < section.endLine; i += 1) { + if (mask[i] === true) continue; + const item = ORDERED_ITEM.exec(document.lineAt(i).text); + if (item === null || item[1] === undefined || item[2] === undefined) continue; + const criterionCanonical = `${canonical}.${item[1].replace(/^0+(?=\d)/, '')}`; + if (byCanonical.has(criterionCanonical)) continue; + add({ + displayId: `${match[1]}.${item[1]}`, + canonical: criterionCanonical, + kind: 'criterion', + line: i, + testRequired: mentionsTests(item[2]), + requirementCanonical: canonical, + method: 'id-heading', + confidence: 'deterministic', + }); + } + } + } + + return { + entries, + requirements: entries.filter((entry) => entry.kind === 'requirement'), + byCanonical, + }; +} + +/* ------------------------------------------------------------------ * + * Task requirement references + * ------------------------------------------------------------------ */ + +export type TaskReferenceMethod = + | 'underscore-refs' + | 'refs-line' + | 'bracket-ref' + | 'keyword-ref'; + +export interface TaskRequirementReference { + taskId: string; + /** Reference text as written (single identifier). */ + raw: string; + /** Canonical identifier, or undefined when the text is not id-shaped. */ + canonical?: string; + /** 0-based line the reference appears on. */ + line: number; + method: TaskReferenceMethod; + confidence: TraceabilityConfidence; +} + +const UNDERSCORE_REFS = /_[ \t]*requirements?[ \t]*:[ \t]*([^_]*)_/i; +const REFS_LINE = /^[ \t]*(?:[-*+][ \t]+)?requirements?[ \t]*:[ \t]*(.+)$/i; +/** `[R1]`-style bracket refs; a following `(` would make it a Markdown link. */ +const BRACKET_REF = /\[[ \t]*((?:req|r|ac)[-_. ]?\d+(?:[.-]\d+)*)[ \t]*\](?!\()/gi; +const KEYWORD_REF = + /\b(?:supports|implements|covers|satisfies|fulfils|fulfills|addresses)[ \t]+((?:requirements?|req|r|ac)[-_. ]?\d+(?:[.-]\d+)*|\d+(?:\.\d+)+)/gi; + +function splitReferenceList(list: string): string[] { + return list + .split(/[,;]/) + .map((item) => item.trim()) + .filter((item) => item.length > 0); +} + +function ownerTaskAt(tasks: readonly TaskItem[], line: number): TaskItem | undefined { + let owner: TaskItem | undefined; + for (const task of tasks) { + if (task.line <= line) owner = task; + else break; + } + return owner; +} + +/** + * Extract every task-to-requirement reference with source lines. + * + * Recognized forms (first three deterministic, keyword form heuristic): + * - `_Requirements: 1.1, 2.3_` detail lines (the documented Kiro form) + * - `Requirements: R1, R2` detail lines without underscores + * - `[R1]` / `[REQ-001]` bracket references in titles or details + * - `Supports REQ-001` / `Implements 1.2` keyword references (heuristic) + */ +export function extractTaskRequirementReferences( + document: MarkdownDocument, + tasks: TasksModel, +): TaskRequirementReference[] { + const references: TaskRequirementReference[] = []; + if (tasks.allTasks.length === 0) return references; + const mask = document.codeFenceMask(); + const orderedTasks = [...tasks.allTasks].sort((a, b) => a.line - b.line); + const firstTaskLine = orderedTasks[0]?.line ?? 0; + const seen = new Set(); + + const push = ( + task: TaskItem, + raw: string, + line: number, + method: TaskReferenceMethod, + confidence: TraceabilityConfidence, + ): void => { + const canonical = canonicalRequirementRef(raw); + const key = `${task.id} ${canonical ?? raw.toLowerCase()}`; + if (seen.has(key)) return; + seen.add(key); + references.push({ + taskId: task.id, + raw, + ...(canonical !== undefined ? { canonical } : {}), + line, + method, + confidence, + }); + }; + + for (let i = firstTaskLine; i < document.lineCount; i += 1) { + if (mask[i] === true) continue; + const owner = ownerTaskAt(orderedTasks, i); + if (owner === undefined) continue; + const text = document.lineAt(i).text; + const isTaskLine = orderedTasks.some((task) => task.line === i); + + if (!isTaskLine) { + const underscore = UNDERSCORE_REFS.exec(text); + if (underscore !== null) { + for (const item of splitReferenceList(underscore[1] ?? '')) { + push(owner, item, i, 'underscore-refs', 'deterministic'); + } + } else { + const refsLine = REFS_LINE.exec(text); + if (refsLine !== null) { + for (const item of splitReferenceList(refsLine[1] ?? '')) { + // Only id-shaped items count — `Requirements: see above` is prose. + if (canonicalRequirementRef(item) !== undefined) { + push(owner, item, i, 'refs-line', 'deterministic'); + } + } + } + } + } + + for (const match of text.matchAll(BRACKET_REF)) { + if (match[1] !== undefined) push(owner, match[1], i, 'bracket-ref', 'deterministic'); + } + for (const match of text.matchAll(KEYWORD_REF)) { + if (match[1] !== undefined) push(owner, match[1], i, 'keyword-ref', 'heuristic'); + } + } + + return references; +} + +/** Heuristic: the task's title or detail lines explicitly mention tests. */ +export function taskMentionsTests( + document: MarkdownDocument, + tasks: TasksModel, + task: TaskItem, +): boolean { + if (mentionsTests(task.title)) return true; + const orderedTasks = [...tasks.allTasks].sort((a, b) => a.line - b.line); + const next = orderedTasks.find((candidate) => candidate.line > task.line); + const endLine = next?.line ?? document.lineCount; + const mask = document.codeFenceMask(); + for (let i = task.line + 1; i < endLine; i += 1) { + if (mask[i] === true) continue; + if (mentionsTests(document.lineAt(i).text)) return true; + } + return false; +} + +/** + * Heuristic: tasks that are clearly not requirement-implementing work + * (documentation, release, cleanup, formatting chores). Used to exclude + * them from "task has no requirement reference" findings — never to excuse + * missing evidence. + */ +const NON_REQUIREMENT_TASK = + /\b(document|documentation|docs|readme|changelog|release|publish|version bump|cleanup|clean up|chore|lint|format|typo)\b/i; + +export function isLikelyNonRequirementTask(task: TaskItem): boolean { + return NON_REQUIREMENT_TASK.test(task.title); +} + +/* ------------------------------------------------------------------ * + * Explicit repository path references + * ------------------------------------------------------------------ */ + +export type PathReferenceMethod = 'backtick-path' | 'markdown-link'; + +export interface PathReference { + /** Text exactly as written (backtick content or link target). */ + raw: string; + /** Normalized repo-relative POSIX path candidate (no leading `./`). */ + path: string; + /** 0-based source line. */ + line: number; + method: PathReferenceMethod; + confidence: TraceabilityConfidence; + /** Contains glob characters — usable as an impact-area hint, not a file. */ + isGlob: boolean; +} + +const BACKTICK_SPAN = /`([^`\n]+)`/g; +const MARKDOWN_LINK = /\[[^\]]*\]\(([^()\s]+)\)/g; +const URL_SCHEME = /^[a-z][a-z0-9+.-]*:/i; +const GLOB_CHARS = /[*?[\]{}]/; +const CODE_TOKEN = /[(){}<>;=,]|::|=>/; + +function normalizePathCandidate(raw: string): string | undefined { + let candidate = raw.trim(); + if (candidate.length === 0 || candidate.includes('\0') || /\s/.test(candidate)) { + return undefined; + } + if (URL_SCHEME.test(candidate) || candidate.startsWith('#')) return undefined; + if (CODE_TOKEN.test(candidate)) return undefined; + candidate = candidate.split('\\').join('/'); + candidate = candidate.replace(/^\.\//, ''); + // Absolute paths and traversal cannot be repo-relative references. + if (candidate.startsWith('/') || /^[A-Za-z]:/.test(candidate)) return undefined; + if (candidate.split('/').includes('..')) return undefined; + // Strip anchors/queries from link targets. + candidate = candidate.replace(/[#?].*$/, ''); + if (candidate.length === 0) return undefined; + // A path needs a directory separator to be an unambiguous repository path; + // bare file names (`config.json`) could live anywhere and are skipped. + if (!candidate.includes('/')) return undefined; + if (candidate.endsWith('/')) candidate = candidate.slice(0, -1); + if (candidate.length === 0) return undefined; + return candidate; +} + +/** + * Explicit repository paths written in a document: backtick spans that look + * like paths and Markdown links to repository files. Deterministic — the + * syntax is explicit; no prose inference happens here. + */ +export function extractPathReferences(document: MarkdownDocument): PathReference[] { + const references: PathReference[] = []; + const mask = document.codeFenceMask(); + const seen = new Set(); + + for (let i = 0; i < document.lineCount; i += 1) { + if (mask[i] === true) continue; + const text = document.lineAt(i).text; + + for (const match of text.matchAll(BACKTICK_SPAN)) { + const raw = match[1]; + if (raw === undefined) continue; + const path = normalizePathCandidate(raw); + if (path === undefined) continue; + const key = `${path} ${i}`; + if (seen.has(key)) continue; + seen.add(key); + references.push({ + raw, + path, + line: i, + method: 'backtick-path', + confidence: 'deterministic', + isGlob: GLOB_CHARS.test(path), + }); + } + + for (const match of text.matchAll(MARKDOWN_LINK)) { + const raw = match[1]; + if (raw === undefined) continue; + const path = normalizePathCandidate(raw); + if (path === undefined) continue; + const key = `${path} ${i}`; + if (seen.has(key)) continue; + seen.add(key); + references.push({ + raw, + path, + line: i, + method: 'markdown-link', + confidence: 'deterministic', + isGlob: GLOB_CHARS.test(path), + }); + } + } + + return references; +} diff --git a/packages/core/package.json b/packages/core/package.json index 3134b6d..28faf3a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/core", - "version": "0.3.0", + "version": "0.4.0", "description": "Core types, errors, workspace detection, and sidecar state for SpecBridge.", "license": "MIT", "type": "module", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 58683e2..72a71af 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,4 +6,5 @@ export * from './hash.js'; export * from './spec-state.js'; export * from './run-types.js'; export * from './runner-output.js'; +export * from './verification-types.js'; export * from './agent-config.js'; diff --git a/packages/core/src/spec-state.ts b/packages/core/src/spec-state.ts index deb62b2..8fbacd9 100644 --- a/packages/core/src/spec-state.ts +++ b/packages/core/src/spec-state.ts @@ -20,6 +20,17 @@ import { assertInsideWorkspace, writeFileAtomic } from './workspace.js'; export const SPEC_STATE_SCHEMA_VERSION = '1.0.0'; +/** + * Approval-hash semantics version recorded per stage. + * + * Version "2" (v0.4) adds `approvedPlanHash` for the tasks stage: a SHA-256 + * over the tasks document with only checkbox state characters normalized, so + * `[ ]` → `[x]` progress does not invalidate an approved task plan while any + * other byte change (task text, IDs, hierarchy, references) still does. + * Requirements, bugfix, and design approvals remain exact-byte hashes only. + */ +export const TASK_PLAN_HASH_SEMANTICS_VERSION = '2'; + const SHA256_HEX = /^[0-9a-f]{64}$/; export const stageApprovalSchema = z.object({ @@ -30,6 +41,19 @@ export const stageApprovalSchema = z.object({ approvedAt: z.string().datetime({ offset: true }).nullable(), /** SHA-256 (hex) of the exact approved file bytes, or null when not approved. */ approvedHash: z.string().regex(SHA256_HEX, 'must be a lowercase sha256 hex digest').nullable(), + /** + * Tasks stage only: SHA-256 of the approved document with checkbox state + * normalized (semantics version 2). Absent on stages approved before v0.4 + * and on non-tasks stages; the exact `approvedHash` remains authoritative + * for audit either way. + */ + approvedPlanHash: z + .string() + .regex(SHA256_HEX, 'must be a lowercase sha256 hex digest') + .nullable() + .optional(), + hashAlgorithm: z.literal('sha256').optional(), + hashSemanticsVersion: z.string().optional(), }); export type StageApproval = z.infer; @@ -94,6 +118,17 @@ export const specWorkflowStateSchema = z message: 'a stage that is not approved must have null approvedAt and approvedHash', }); } + if ( + !approved && + approval.approvedPlanHash !== null && + approval.approvedPlanHash !== undefined + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ['stages', name], + message: 'a stage that is not approved must not record approvedPlanHash', + }); + } } }); diff --git a/packages/core/src/verification-types.ts b/packages/core/src/verification-types.ts new file mode 100644 index 0000000..4237193 --- /dev/null +++ b/packages/core/src/verification-types.ts @@ -0,0 +1,276 @@ +import { z } from 'zod'; + +/** + * Versioned verification vocabulary shared by the drift rule engine, the + * reporting renderers, the CLI, and the GitHub Action. + * + * Stability contract: + * - rule IDs (`SBV###`) are stable and never silently renumbered + * - diagnostic and report schemas are versioned; readers accept any 1.x + * - every report is validated with these schemas before it is written + */ + +export const VERIFICATION_DIAGNOSTIC_SCHEMA_VERSION = '1.0.0'; +export const VERIFICATION_REPORT_SCHEMA_VERSION = '1.0.0'; + +export const VERIFICATION_SEVERITIES = ['error', 'warning', 'info'] as const; +export type VerificationSeverity = (typeof VERIFICATION_SEVERITIES)[number]; + +export const VERIFICATION_CATEGORIES = [ + 'workspace', + 'approval', + 'requirements', + 'design', + 'tasks', + 'evidence', + 'impact-area', + 'verification-command', + 'protected-path', + 'mapping', + 'git', +] as const; +export type VerificationCategory = (typeof VERIFICATION_CATEGORIES)[number]; + +/** + * How a finding was produced. `deterministic` findings follow from file + * bytes, hashes, git output, and exit codes alone. `heuristic` findings come + * from pattern recognition (e.g. "this task title mentions tests") and must + * never default to `error` severity. + */ +export const VERIFICATION_CONFIDENCE_VALUES = ['deterministic', 'heuristic'] as const; +export type VerificationConfidence = (typeof VERIFICATION_CONFIDENCE_VALUES)[number]; + +export const VERIFICATION_RULE_ID_PATTERN = /^SBV\d{3}$/; + +/** Repository-relative source location (forward slashes, 1-based line/column). */ +export const verificationFileLocationSchema = z.object({ + path: z.string().min(1), + line: z.number().int().min(1).nullable(), + column: z.number().int().min(1).nullable(), +}); +export type VerificationFileLocation = z.infer; + +export const verificationDiagnosticSchema = z.object({ + schemaVersion: z.string().regex(/^\d+\.\d+\.\d+$/), + ruleId: z.string().regex(VERIFICATION_RULE_ID_PATTERN), + title: z.string().min(1), + severity: z.enum(VERIFICATION_SEVERITIES), + category: z.enum(VERIFICATION_CATEGORIES), + message: z.string().min(1), + remediation: z.string().min(1), + specName: z.string().nullable(), + taskId: z.string().nullable(), + requirementId: z.string().nullable(), + file: verificationFileLocationSchema.nullable(), + /** Structured, rule-specific supporting data (always JSON-serializable). */ + evidence: z.record(z.unknown()), + confidence: z.enum(VERIFICATION_CONFIDENCE_VALUES), +}); +export type VerificationDiagnostic = z.infer; + +export const COMPARISON_MODES = ['diff', 'working-tree', 'staged'] as const; +export type ComparisonMode = (typeof COMPARISON_MODES)[number]; + +export const comparisonDescriptorSchema = z.object({ + mode: z.enum(COMPARISON_MODES), + /** Base ref as given by the user/event; null for working-tree and staged. */ + base: z.string().nullable(), + head: z.string().nullable(), + /** Resolved commit SHAs where available. */ + baseSha: z.string().nullable(), + headSha: z.string().nullable(), + /** Human-readable label, e.g. `origin/main...HEAD` or `working tree vs HEAD`. */ + label: z.string().min(1), +}); +export type ComparisonDescriptor = z.infer; + +export const CHANGED_FILE_TYPES = [ + 'added', + 'modified', + 'deleted', + 'renamed', + 'copied', + 'untracked', +] as const; +export type ChangedFileType = (typeof CHANGED_FILE_TYPES)[number]; + +export const reportChangedFileSchema = z.object({ + /** Repository-relative path with forward slashes. */ + path: z.string().min(1), + oldPath: z.string().nullable(), + changeType: z.enum(CHANGED_FILE_TYPES), + binary: z.boolean(), + insertions: z.number().int().min(0).nullable(), + deletions: z.number().int().min(0).nullable(), +}); +export type ReportChangedFile = z.infer; + +export const VERIFICATION_COMMAND_DISPOSITIONS = [ + /** The command ran during this verification. */ + 'executed', + /** A passing result was reused from valid, fresh task evidence. */ + 'reused-evidence', + /** The command did not run (per options) and nothing could be reused. */ + 'not-run', +] as const; +export type VerificationCommandDisposition = (typeof VERIFICATION_COMMAND_DISPOSITIONS)[number]; + +export const verificationCommandReportSchema = z.object({ + name: z.string().min(1), + argv: z.array(z.string()), + required: z.boolean(), + disposition: z.enum(VERIFICATION_COMMAND_DISPOSITIONS), + exitCode: z.number().int().nullable(), + durationMs: z.number().min(0).nullable(), + timedOut: z.boolean(), + passed: z.boolean(), + /** Specs whose policy required this command by name. */ + requiredBySpecs: z.array(z.string()), +}); +export type VerificationCommandReport = z.infer; + +export const SELECTION_MODES = ['single', 'changed', 'all'] as const; +export type SelectionMode = (typeof SELECTION_MODES)[number]; + +export const VERIFICATION_RESULTS = ['passed', 'failed'] as const; +export type VerificationResult = (typeof VERIFICATION_RESULTS)[number]; + +export const POLICY_MODES = ['advisory', 'strict'] as const; +export type PolicyMode = (typeof POLICY_MODES)[number]; + +export const specTraceabilitySummarySchema = z.object({ + requirements: z.number().int().min(0), + requirementsWithTasks: z.number().int().min(0), + tasks: z.number().int().min(0), + tasksWithRequirements: z.number().int().min(0), +}); +export type SpecTraceabilitySummary = z.infer; + +export const specEvidenceSummarySchema = z.object({ + /** Completed tasks with valid, fresh verified evidence. */ + valid: z.number().int().min(0), + /** Completed tasks whose best evidence is stale. */ + stale: z.number().int().min(0), + /** Completed tasks with no accepted evidence at all. */ + missing: z.number().int().min(0), + /** Structurally invalid evidence records encountered. */ + invalid: z.number().int().min(0), + /** Completed tasks covered by valid manual acceptance (subset of valid). */ + manuallyAccepted: z.number().int().min(0), +}); +export type SpecEvidenceSummary = z.infer; + +export const specVerificationResultSchema = z.object({ + specName: z.string().min(1), + specType: z.enum(['feature', 'bugfix', 'unknown']), + workflowMode: z.enum(['requirements-first', 'design-first', 'quick', 'unknown']), + /** True when SpecBridge sidecar workflow state exists for the spec. */ + managed: z.boolean(), + result: z.enum(VERIFICATION_RESULTS), + policyMode: z.enum(POLICY_MODES), + /** Workspace-relative policy file path; null when defaults were used. */ + policyPath: z.string().nullable(), + /** Why the spec was selected (affected-spec reasons; empty for single/all). */ + matchedBy: z.array(z.string()), + changedFiles: z.array(reportChangedFileSchema), + traceability: specTraceabilitySummarySchema, + evidence: specEvidenceSummarySchema, + diagnostics: z.array(verificationDiagnosticSchema), +}); +export type SpecVerificationResult = z.infer; + +export const verificationSummarySchema = z.object({ + result: z.enum(VERIFICATION_RESULTS), + specsVerified: z.number().int().min(0), + errors: z.number().int().min(0), + warnings: z.number().int().min(0), + info: z.number().int().min(0), +}); +export type VerificationSummary = z.infer; + +export const verificationReportSchema = z.object({ + schemaVersion: z.string().regex(/^\d+\.\d+\.\d+$/), + tool: z.object({ + name: z.string().min(1), + version: z.string().min(1), + }), + verificationId: z.string().min(1), + createdAt: z.string().datetime({ offset: true }), + comparison: comparisonDescriptorSchema, + selection: z.object({ + mode: z.enum(SELECTION_MODES), + specs: z.array(z.string()), + }), + summary: verificationSummarySchema, + specResults: z.array(specVerificationResultSchema), + /** Diagnostics not attributable to a single selected spec. */ + globalDiagnostics: z.array(verificationDiagnosticSchema), + verificationCommands: z.array(verificationCommandReportSchema), +}); +export type VerificationReport = z.infer; + +const SEVERITY_RANK: Record = { + error: 0, + warning: 1, + info: 2, +}; + +export function severityRank(severity: VerificationSeverity): number { + return SEVERITY_RANK[severity]; +} + +/** + * Deterministic diagnostic ordering used by every report format: + * severity (errors first), then rule ID, file path, line, task, requirement, + * and finally the message text as a tiebreaker. + */ +export function compareVerificationDiagnostics( + a: VerificationDiagnostic, + b: VerificationDiagnostic, +): number { + const bySeverity = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity]; + if (bySeverity !== 0) return bySeverity; + const byRule = a.ruleId.localeCompare(b.ruleId, 'en'); + if (byRule !== 0) return byRule; + const byFile = (a.file?.path ?? '').localeCompare(b.file?.path ?? '', 'en'); + if (byFile !== 0) return byFile; + const byLine = (a.file?.line ?? 0) - (b.file?.line ?? 0); + if (byLine !== 0) return byLine; + const byTask = (a.taskId ?? '').localeCompare(b.taskId ?? '', 'en'); + if (byTask !== 0) return byTask; + const byRequirement = (a.requirementId ?? '').localeCompare(b.requirementId ?? '', 'en'); + if (byRequirement !== 0) return byRequirement; + return a.message.localeCompare(b.message, 'en'); +} + +export function sortVerificationDiagnostics( + diagnostics: readonly VerificationDiagnostic[], +): VerificationDiagnostic[] { + return [...diagnostics].sort(compareVerificationDiagnostics); +} + +/** Count diagnostics per severity across spec results and global diagnostics. */ +export function countDiagnostics( + diagnostics: readonly VerificationDiagnostic[], +): { errors: number; warnings: number; info: number } { + const counts = { errors: 0, warnings: 0, info: 0 }; + for (const diagnostic of diagnostics) { + if (diagnostic.severity === 'error') counts.errors += 1; + else if (diagnostic.severity === 'warning') counts.warnings += 1; + else counts.info += 1; + } + return counts; +} + +export const FAIL_ON_THRESHOLDS = ['error', 'warning', 'never'] as const; +export type FailOnThreshold = (typeof FAIL_ON_THRESHOLDS)[number]; + +/** True when the diagnostic counts reach the configured failure threshold. */ +export function reachesFailureThreshold( + counts: { errors: number; warnings: number }, + threshold: FailOnThreshold, +): boolean { + if (threshold === 'never') return false; + if (threshold === 'warning') return counts.errors > 0 || counts.warnings > 0; + return counts.errors > 0; +} diff --git a/packages/drift/package.json b/packages/drift/package.json index 7401756..a324bf8 100644 --- a/packages/drift/package.json +++ b/packages/drift/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/drift", - "version": "0.3.0", + "version": "0.4.0", "description": "Deterministic spec-to-code drift primitives for SpecBridge (no LLM required).", "license": "MIT", "type": "module", @@ -26,6 +26,9 @@ "dependencies": { "@specbridge/compat-kiro": "workspace:*", "@specbridge/core": "workspace:*", + "@specbridge/evidence": "workspace:*", + "@specbridge/runners": "workspace:*", + "@specbridge/workflow": "workspace:*", "execa": "^9.4.0", "picomatch": "^4.0.2", "zod": "^3.23.8" diff --git a/packages/drift/src/index.ts b/packages/drift/src/index.ts index c6bb9f9..c8799bc 100644 --- a/packages/drift/src/index.ts +++ b/packages/drift/src/index.ts @@ -1,11 +1,14 @@ /** - * @specbridge/drift — deterministic spec-to-code drift primitives. + * @specbridge/drift — deterministic spec-to-code drift verification. * - * v0.1 status: this package ships the pure building blocks (git diff - * parsing, impact areas, requirement/task coverage, report assembly) with - * full test coverage. The `specbridge spec verify` CLI command that wires - * them to live repositories lands in a later phase — see docs/roadmap.md. - * No function here requires an LLM. + * v0.4 ships the full verification stack under `verification/`: comparison + * resolution, spec policies, the rule engine with the stable SBV001–SBV025 + * rules, affected-spec resolution, trusted-command orchestration, and + * schema-validated report assembly. No function here requires an LLM, and + * verification never writes to `.kiro`, approval state, or evidence. + * + * The v0.1 primitives (git-diff, impact-area, coverage, drift-report) remain + * exported unchanged for library consumers. */ export * from './git-diff.js'; @@ -14,3 +17,12 @@ export * from './impact-area.js'; export * from './requirement-coverage.js'; export * from './task-coverage.js'; export * from './drift-report.js'; + +export * from './verification/policy.js'; +export * from './verification/comparison.js'; +export * from './verification/context.js'; +export * from './verification/commands.js'; +export * from './verification/rule-engine.js'; +export * from './verification/rules.js'; +export * from './verification/affected.js'; +export * from './verification/verify.js'; diff --git a/packages/drift/src/verification/affected.ts b/packages/drift/src/verification/affected.ts new file mode 100644 index 0000000..c11b570 --- /dev/null +++ b/packages/drift/src/verification/affected.ts @@ -0,0 +1,158 @@ +import { existsSync } from 'node:fs'; +import path from 'node:path'; +import { MarkdownDocument, extractPathReferences } from '@specbridge/compat-kiro'; +import type { PathReference, SpecFolder } from '@specbridge/compat-kiro'; +import { discoverSpecs, specFile } from '@specbridge/compat-kiro'; +import type { WorkspaceInfo } from '@specbridge/core'; +import { listTaskEvidence } from '@specbridge/evidence'; +import { readdirSync } from 'node:fs'; +import type { ComparisonChangedFile } from './comparison.js'; +import type { EffectivePolicy } from './policy.js'; +import { resolveEffectivePolicy } from './policy.js'; +import { specMatchReasons } from './context.js'; + +/** + * Deterministic affected-spec resolution: which specs does a change set + * touch? A spec is affected when at least one changed file + * + * 1. lives under `.kiro/specs//`, + * 2. is the spec's sidecar state file, + * 3. is the spec's verification policy file, + * 4. matches a declared impact area, + * 5. appears in accepted task evidence for the spec, or + * 6. is a file design.md explicitly references. + * + * Everything here is read-only and runs no verification commands. + */ + +export interface AffectedFileMatch { + file: string; + via: string[]; +} + +export interface AffectedSpec { + specName: string; + matches: AffectedFileMatch[]; +} + +export interface AffectedSpecsResult { + /** Affected specs sorted by name; matches sorted by file path. */ + affected: AffectedSpec[]; + /** Non-infrastructure changed files that no spec claims (SBV014). */ + unmapped: ComparisonChangedFile[]; + /** Files claimed by more than one spec (SBV022). */ + ambiguous: { path: string; specs: { name: string; via: string[] }[] }[]; +} + +function isInfrastructurePath(candidate: string): boolean { + return ( + candidate === '.git' || + candidate.startsWith('.git/') || + candidate.startsWith('.kiro/') || + candidate.startsWith('.specbridge/') + ); +} + +interface SpecMatchingInfo { + folder: SpecFolder; + policy: EffectivePolicy; + designReferences: PathReference[]; + evidencePaths: Set; +} + +function loadSpecMatchingInfo( + workspace: WorkspaceInfo, + folder: SpecFolder, + options: { strict?: boolean }, +): SpecMatchingInfo { + const policy = resolveEffectivePolicy(workspace, folder.name, { + ...(options.strict !== undefined ? { strict: options.strict } : {}), + }); + + let designReferences: PathReference[] = []; + const design = specFile(folder, 'design'); + if (design !== undefined) { + try { + designReferences = extractPathReferences(MarkdownDocument.load(design.path)); + } catch { + // Unreadable design files simply contribute no reference matches. + } + } + + // Accepted evidence records route files to the spec (routing only — the + // freshness rules judge validity separately during verification). + const evidencePaths = new Set(); + const evidenceDir = path.join(workspace.sidecarDir, 'evidence', folder.name); + if (existsSync(evidenceDir)) { + for (const entry of readdirSync(evidenceDir, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const { records } = listTaskEvidence(workspace, folder.name, entry.name); + for (const record of records) { + if (record.status !== 'verified' && record.status !== 'manually-accepted') continue; + for (const file of record.changedFiles) evidencePaths.add(file.path); + } + } + } + + return { folder, policy, designReferences, evidencePaths }; +} + +export interface ResolveAffectedSpecsOptions { + strict?: boolean; +} + +/** Resolve affected specs for a change set against every workspace spec. */ +export function resolveAffectedSpecs( + workspace: WorkspaceInfo, + changedFiles: readonly ComparisonChangedFile[], + options: ResolveAffectedSpecsOptions = {}, +): AffectedSpecsResult { + const specs = discoverSpecs(workspace).map((folder) => + loadSpecMatchingInfo(workspace, folder, options), + ); + + const affectedByName = new Map>(); + const claimsByFile = new Map(); + + for (const file of changedFiles) { + for (const spec of specs) { + const via = specMatchReasons( + spec.folder.name, + spec.policy, + spec.evidencePaths, + spec.designReferences, + file, + ); + if (via.length === 0) continue; + const fileMatches = affectedByName.get(spec.folder.name) ?? new Map(); + fileMatches.set(file.path, via); + affectedByName.set(spec.folder.name, fileMatches); + const claims = claimsByFile.get(file.path) ?? []; + claims.push({ name: spec.folder.name, via }); + claimsByFile.set(file.path, claims); + } + } + + const affected: AffectedSpec[] = [...affectedByName.entries()] + .map(([specName, fileMatches]) => ({ + specName, + matches: [...fileMatches.entries()] + .map(([file, via]) => ({ file, via })) + .sort((a, b) => a.file.localeCompare(b.file, 'en')), + })) + .sort((a, b) => a.specName.localeCompare(b.specName, 'en')); + + const unmapped = changedFiles.filter( + (file) => !isInfrastructurePath(file.path) && !claimsByFile.has(file.path), + ); + + const ambiguous = [...claimsByFile.entries()] + .filter(([, claims]) => claims.length > 1) + .map(([filePath, claims]) => ({ + path: filePath, + specs: [...claims].sort((a, b) => a.name.localeCompare(b.name, 'en')), + })) + .sort((a, b) => a.path.localeCompare(b.path, 'en')); + + return { affected, unmapped, ambiguous }; +} diff --git a/packages/drift/src/verification/commands.ts b/packages/drift/src/verification/commands.ts new file mode 100644 index 0000000..c3142a4 --- /dev/null +++ b/packages/drift/src/verification/commands.ts @@ -0,0 +1,170 @@ +import type { AgentConfig, VerificationCommand } from '@specbridge/core'; +import type { EvidenceAssessment } from '@specbridge/evidence'; +import { reusableCommandPass, runVerificationCommands } from '@specbridge/evidence'; +import type { VerificationCommandResult } from '@specbridge/evidence'; + +/** + * Trusted verification-command orchestration for `spec verify`. + * + * Commands come exclusively from `.specbridge/config.json` (argv arrays, + * validated by the config schema). Spec policies may only *name* configured + * commands — a policy can never introduce a new command line. + * + * Execution modes: + * - `all` (--run-verification): run every configured command + * - `required-only` (default when a selected policy requires commands): + * run just the policy-required commands + * - `none` (--no-run-verification, or nothing required): run + * nothing; try to reuse passing results from valid, + * fresh evidence recorded at the exact current HEAD + */ + +export type CommandRunMode = 'all' | 'required-only' | 'none'; + +export interface OrchestratedCommand { + name: string; + argv: string[]; + required: boolean; + disposition: 'executed' | 'reused-evidence' | 'not-run'; + passed: boolean; + timedOut: boolean; + spawnFailed: boolean; + exitCode: number | null; + durationMs: number | null; + /** Run id of the evidence record a passing result was reused from. */ + reusedFromRunId?: string; + /** Specs whose policy required this command by name. */ + requiredBySpecs: string[]; + /** Present when the command executed in this run. */ + result?: VerificationCommandResult; +} + +export interface OrchestratedCommands { + mode: CommandRunMode; + commands: OrchestratedCommand[]; + /** Policy-required command names that are not configured at all (SBV013). */ + missingRequired: { name: string; requiredBySpecs: string[] }[]; +} + +export interface OrchestrateCommandsOptions { + config: AgentConfig; + /** Required command names per selected spec. */ + requiredBySpec: Map; + /** CLI tri-state: true = all, false = none, undefined = auto. */ + runVerification: boolean | undefined; + workspaceRoot: string; + /** Current HEAD SHA (needed for evidence reuse). */ + headSha?: string; + /** Valid evidence assessments per spec (reuse source). */ + evidenceBySpec: Map; + signal?: AbortSignal; + onProgress?: (message: string) => void; + /** Sink for full command output (report artifacts). */ + onCommandFinished?: (result: VerificationCommandResult, stdout: string, stderr: string) => void; +} + +export async function orchestrateVerificationCommands( + options: OrchestrateCommandsOptions, +): Promise { + const configured = options.config.verification.commands; + const configuredByName = new Map( + configured.map((command) => [command.name, command]), + ); + + // name → specs that require it (sorted for deterministic output). + const requiringSpecs = new Map(); + for (const [specName, names] of options.requiredBySpec) { + for (const name of names) { + const list = requiringSpecs.get(name) ?? []; + list.push(specName); + requiringSpecs.set(name, list); + } + } + for (const list of requiringSpecs.values()) list.sort((a, b) => a.localeCompare(b, 'en')); + + const missingRequired = [...requiringSpecs.entries()] + .filter(([name]) => !configuredByName.has(name)) + .map(([name, specs]) => ({ name, requiredBySpecs: specs })) + .sort((a, b) => a.name.localeCompare(b.name, 'en')); + + const mode: CommandRunMode = + options.runVerification === true + ? 'all' + : options.runVerification === false + ? 'none' + : requiringSpecs.size > 0 + ? 'required-only' + : 'none'; + + const toRun: VerificationCommand[] = + mode === 'all' + ? [...configured] + : mode === 'required-only' + ? configured.filter((command) => requiringSpecs.has(command.name)) + : []; + + const commands: OrchestratedCommand[] = []; + + if (toRun.length > 0) { + const runResult = await runVerificationCommands(options.workspaceRoot, toRun, { + ...(options.signal !== undefined ? { signal: options.signal } : {}), + ...(options.onProgress !== undefined + ? { onCommandStart: (command) => options.onProgress?.(`Running ${command.name}…`) } + : {}), + ...(options.onCommandFinished !== undefined + ? { onCommandFinished: options.onCommandFinished } + : {}), + }); + for (const result of runResult.commands) { + commands.push({ + name: result.name, + argv: [...result.argv], + required: result.required, + disposition: 'executed', + passed: result.passed, + timedOut: result.timedOut, + spawnFailed: result.status === 'spawn-failed', + exitCode: result.exitCode ?? null, + durationMs: result.durationMs, + requiredBySpecs: requiringSpecs.get(result.name) ?? [], + result, + }); + } + } + + // Required commands that did not execute: attempt evidence reuse. + for (const [name, specs] of [...requiringSpecs.entries()].sort((a, b) => + a[0].localeCompare(b[0], 'en'), + )) { + const configuredCommand = configuredByName.get(name); + if (configuredCommand === undefined) continue; // reported via missingRequired + if (commands.some((command) => command.name === name)) continue; + + let reusedFrom: string | undefined; + for (const specName of specs) { + const assessments = options.evidenceBySpec.get(specName) ?? []; + const record = reusableCommandPass(assessments, name, options.headSha); + if (record !== undefined) { + reusedFrom = record.runId; + break; + } + } + + commands.push({ + name, + argv: [...configuredCommand.argv], + required: true, + disposition: reusedFrom !== undefined ? 'reused-evidence' : 'not-run', + passed: reusedFrom !== undefined, + timedOut: false, + spawnFailed: false, + exitCode: null, + durationMs: null, + ...(reusedFrom !== undefined ? { reusedFromRunId: reusedFrom } : {}), + requiredBySpecs: specs, + }); + } + + commands.sort((a, b) => a.name.localeCompare(b.name, 'en')); + return { mode, commands, missingRequired }; +} diff --git a/packages/drift/src/verification/comparison.ts b/packages/drift/src/verification/comparison.ts new file mode 100644 index 0000000..e479ebc --- /dev/null +++ b/packages/drift/src/verification/comparison.ts @@ -0,0 +1,433 @@ +import { lstatSync, openSync, readSync, closeSync, realpathSync } from 'node:fs'; +import path from 'node:path'; +import type { ChangedFileType, ComparisonDescriptor } from '@specbridge/core'; +import { runSafeProcess } from '@specbridge/runners'; + +/** + * Git comparison resolution: turn a requested comparison (revision range, + * working tree, or staged changes) into a normalized changed-file list. + * + * Security posture: + * - git runs as an argv array via runSafeProcess — no shell, ever + * - refs are validated before use and may never start with `-` + * - `-z` output is used throughout, so UTF-8 paths and spaces survive + * - nothing here fetches, commits, or writes anything + * + * All diffs run with `--relative` from the workspace root, so paths are + * workspace-relative and the comparison is scoped to the workspace subtree + * even when the `.kiro` workspace sits inside a larger repository. + */ + +export type ComparisonRequest = + | { mode: 'diff'; base: string; head: string } + | { mode: 'working-tree' } + | { mode: 'staged' }; + +export interface ComparisonChangedFile { + /** Repository-relative path, forward slashes. */ + path: string; + oldPath?: string; + changeType: ChangedFileType; + binary: boolean; + insertions?: number; + deletions?: number; + /** The path is a symlink whose target resolves outside the repository. */ + symlinkOutsideRepository: boolean; +} + +export type ComparisonFailureReason = + | 'git-unavailable' + | 'not-a-repository' + | 'invalid-ref' + | 'ref-not-found' + | 'no-merge-base' + | 'no-commits'; + +export interface ResolvedComparison { + ok: boolean; + descriptor: ComparisonDescriptor; + changedFiles: ComparisonChangedFile[]; + /** Present when `ok` is false. */ + failure?: { + reason: ComparisonFailureReason; + message: string; + /** True when the repository is a shallow clone (fetch-depth hint applies). */ + shallow: boolean; + }; +} + +const GIT_TIMEOUT_MS = 60_000; +const GIT_MAX_STDOUT = 64 * 1024 * 1024; + +async function git( + cwd: string, + argv: string[], + signal?: AbortSignal, +): Promise<{ ok: boolean; stdout: string; stderr: string; exitCode: number | undefined }> { + const result = await runSafeProcess({ + executable: 'git', + argv, + cwd, + timeoutMs: GIT_TIMEOUT_MS, + maxStdoutBytes: GIT_MAX_STDOUT, + maxStderrBytes: 1024 * 1024, + ...(signal !== undefined ? { signal } : {}), + }); + return { + ok: result.status === 'ok', + stdout: result.stdout, + stderr: result.stderr, + exitCode: result.observation.exitCode, + }; +} + +/** + * A ref is acceptable when it cannot be mistaken for a git option and + * contains no whitespace, control, or glob characters. `~` and `^` stay + * allowed (HEAD~1, HEAD^2). Existence is checked separately with + * `git rev-parse --verify`. + */ +export function isSafeGitRef(ref: string): boolean { + if (ref.length === 0 || ref.length > 256) return false; + if (ref.startsWith('-')) return false; + if (/[\s\0:?*[\\]/.test(ref)) return false; + return true; +} + +/** Split `base...head` (or `base..head`) into endpoints. */ +export function parseDiffRange(range: string): { base: string; head: string } | undefined { + const threeDot = range.split('...'); + if (threeDot.length === 2 && threeDot[0] !== undefined && threeDot[1] !== undefined) { + const base = threeDot[0].trim(); + const head = threeDot[1].trim() === '' ? 'HEAD' : threeDot[1].trim(); + if (base === '') return undefined; + return { base, head }; + } + const twoDot = range.split('..'); + if (twoDot.length === 2 && twoDot[0] !== undefined && twoDot[1] !== undefined) { + const base = twoDot[0].trim(); + const head = twoDot[1].trim() === '' ? 'HEAD' : twoDot[1].trim(); + if (base === '') return undefined; + return { base, head }; + } + return undefined; +} + +function statusFor(code: string): ChangedFileType | undefined { + switch (code.charAt(0)) { + case 'A': + return 'added'; + case 'M': + case 'T': + return 'modified'; + case 'D': + return 'deleted'; + case 'R': + return 'renamed'; + case 'C': + return 'copied'; + default: + return undefined; + } +} + +/** Parse `git diff --name-status -z` output (NUL-separated tokens). */ +export function parseNameStatusZ(raw: string): ComparisonChangedFile[] { + const changes: ComparisonChangedFile[] = []; + const tokens = raw.split('\0'); + for (let i = 0; i < tokens.length; i += 1) { + const code = tokens[i]; + if (code === undefined || code.length === 0) continue; + const changeType = statusFor(code); + if (changeType === undefined) { + // Unknown status letter: skip its path token defensively. + i += 1; + continue; + } + if (changeType === 'renamed' || changeType === 'copied') { + const oldPath = tokens[i + 1]; + const newPath = tokens[i + 2]; + i += 2; + if (oldPath === undefined || newPath === undefined || newPath.length === 0) continue; + changes.push({ + path: newPath, + oldPath, + changeType, + binary: false, + symlinkOutsideRepository: false, + }); + } else { + const filePath = tokens[i + 1]; + i += 1; + if (filePath === undefined || filePath.length === 0) continue; + changes.push({ path: filePath, changeType, binary: false, symlinkOutsideRepository: false }); + } + } + return changes; +} + +/** Parse `git diff --numstat -z` output into per-path line counts. */ +export function parseNumstatZ( + raw: string, +): Map { + const stats = new Map(); + // -z numstat: `ins\tdel\t\0` or, for renames, `ins\tdel\t\0old\0new\0`. + const tokens = raw.split('\0'); + for (let i = 0; i < tokens.length; i += 1) { + const token = tokens[i]; + if (token === undefined || token.length === 0) continue; + const match = /^(-|\d+)\t(-|\d+)\t(.*)$/s.exec(token); + if (match === null) continue; + const insertions = match[1] === '-' ? undefined : Number(match[1]); + const deletions = match[2] === '-' ? undefined : Number(match[2]); + const binary = match[1] === '-' && match[2] === '-'; + let filePath = match[3] ?? ''; + if (filePath.length === 0) { + // Rename form: the next two tokens are old and new path. + const newPath = tokens[i + 2]; + i += 2; + if (newPath === undefined) continue; + filePath = newPath; + } + stats.set(filePath, { + ...(insertions !== undefined ? { insertions } : {}), + ...(deletions !== undefined ? { deletions } : {}), + binary, + }); + } + return stats; +} + +function mergeNumstat( + files: ComparisonChangedFile[], + stats: Map, +): void { + for (const file of files) { + const stat = stats.get(file.path); + if (stat === undefined) continue; + if (stat.insertions !== undefined) file.insertions = stat.insertions; + if (stat.deletions !== undefined) file.deletions = stat.deletions; + file.binary = stat.binary; + } +} + +/** git-style binary sniff: a NUL byte in the first 8000 bytes. */ +function sniffBinary(absolutePath: string): boolean { + let fd: number | undefined; + try { + fd = openSync(absolutePath, 'r'); + const buffer = Buffer.alloc(8000); + const bytesRead = readSync(fd, buffer, 0, buffer.length, 0); + return buffer.subarray(0, bytesRead).includes(0); + } catch { + return false; + } finally { + if (fd !== undefined) closeSync(fd); + } +} + +/** Detect symlinks whose resolved target escapes the repository root. */ +function flagSymlinkEscapes(repoRoot: string, files: ComparisonChangedFile[]): void { + const resolvedRoot = (() => { + try { + return realpathSync(repoRoot); + } catch { + return path.resolve(repoRoot); + } + })(); + for (const file of files) { + if (file.changeType === 'deleted') continue; + const absolute = path.join(repoRoot, file.path.split('/').join(path.sep)); + try { + const stats = lstatSync(absolute); + if (!stats.isSymbolicLink()) continue; + const target = realpathSync(absolute); + const relative = path.relative(resolvedRoot, target); + if (relative.startsWith('..') || path.isAbsolute(relative)) { + file.symlinkOutsideRepository = true; + } + } catch { + // Missing/broken links cannot leak content; ignore. + } + } +} + +function sortFiles(files: ComparisonChangedFile[]): ComparisonChangedFile[] { + return files.sort((a, b) => a.path.localeCompare(b.path, 'en')); +} + +async function isShallow(repoRoot: string, signal?: AbortSignal): Promise { + const result = await git(repoRoot, ['rev-parse', '--is-shallow-repository'], signal); + return result.ok && result.stdout.trim() === 'true'; +} + +async function resolveSha( + repoRoot: string, + ref: string, + signal?: AbortSignal, +): Promise { + const result = await git(repoRoot, ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], signal); + return result.ok ? result.stdout.trim() : undefined; +} + +export interface ResolveComparisonOptions { + signal?: AbortSignal; +} + +/** + * Resolve a comparison request against a repository. Never throws for git + * or ref problems — failures come back structured so the rule engine can + * emit SBV021 with actionable remediation. + */ +export async function resolveComparison( + repoRoot: string, + request: ComparisonRequest, + options: ResolveComparisonOptions = {}, +): Promise { + const signal = options.signal; + const descriptor: ComparisonDescriptor = { + mode: request.mode, + base: request.mode === 'diff' ? request.base : null, + head: request.mode === 'diff' ? request.head : null, + baseSha: null, + headSha: null, + label: + request.mode === 'diff' + ? `${request.base}...${request.head}` + : request.mode === 'working-tree' + ? 'working tree vs HEAD' + : 'staged changes vs HEAD', + }; + + const failed = ( + reason: ComparisonFailureReason, + message: string, + shallow = false, + ): ResolvedComparison => ({ + ok: false, + descriptor, + changedFiles: [], + failure: { reason, message, shallow }, + }); + + const inside = await git(repoRoot, ['rev-parse', '--is-inside-work-tree'], signal); + if (!inside.ok || inside.stdout.trim() !== 'true') { + return failed( + 'not-a-repository', + `${repoRoot} is not a usable git work tree; drift verification needs the repository history.`, + ); + } + + if (request.mode === 'diff') { + for (const [role, ref] of [ + ['base', request.base], + ['head', request.head], + ] as const) { + if (!isSafeGitRef(ref)) { + return failed( + 'invalid-ref', + `The ${role} ref "${ref}" is not a valid git ref (refs must not start with "-" or contain whitespace).`, + ); + } + } + const baseSha = await resolveSha(repoRoot, request.base, signal); + const headSha = await resolveSha(repoRoot, request.head, signal); + const shallow = await isShallow(repoRoot, signal); + if (baseSha === undefined || headSha === undefined) { + const missing = baseSha === undefined ? request.base : request.head; + return failed( + 'ref-not-found', + `Git ref "${missing}" cannot be resolved in this clone.` + + (shallow + ? ' The clone is shallow — check out with full history (actions/checkout@v4 with fetch-depth: 0) or fetch the missing ref explicitly.' + : ' Fetch it first (SpecBridge never fetches automatically).'), + shallow, + ); + } + descriptor.baseSha = baseSha; + descriptor.headSha = headSha; + + const mergeBase = await git(repoRoot, ['merge-base', baseSha, headSha], signal); + if (!mergeBase.ok) { + return failed( + 'no-merge-base', + `No merge base exists between ${request.base} and ${request.head} in this clone.` + + (shallow + ? ' The clone is shallow — check out with full history (actions/checkout@v4 with fetch-depth: 0).' + : ''), + shallow, + ); + } + + const nameStatus = await git( + repoRoot, + ['diff', '--relative', '--name-status', '-z', '-M', `${baseSha}...${headSha}`], + signal, + ); + if (!nameStatus.ok) { + return failed('ref-not-found', `git diff failed: ${nameStatus.stderr.trim()}`); + } + const files = parseNameStatusZ(nameStatus.stdout); + const numstat = await git( + repoRoot, + ['diff', '--relative', '--numstat', '-z', '-M', `${baseSha}...${headSha}`], + signal, + ); + if (numstat.ok) mergeNumstat(files, parseNumstatZ(numstat.stdout)); + flagSymlinkEscapes(repoRoot, files); + return { ok: true, descriptor, changedFiles: sortFiles(files) }; + } + + // Working tree and staged modes need a HEAD to compare against. + const headSha = await resolveSha(repoRoot, 'HEAD', signal); + if (headSha === undefined) { + return failed( + 'no-commits', + 'The repository has no commits yet; there is nothing to compare the working tree against.', + ); + } + descriptor.headSha = headSha; + descriptor.baseSha = headSha; + + if (request.mode === 'staged') { + const nameStatus = await git(repoRoot, ['diff', '--relative', '--name-status', '-z', '-M', '--cached'], signal); + if (!nameStatus.ok) { + return failed('git-unavailable', `git diff --cached failed: ${nameStatus.stderr.trim()}`); + } + const files = parseNameStatusZ(nameStatus.stdout); + const numstat = await git(repoRoot, ['diff', '--relative', '--numstat', '-z', '-M', '--cached'], signal); + if (numstat.ok) mergeNumstat(files, parseNumstatZ(numstat.stdout)); + flagSymlinkEscapes(repoRoot, files); + return { ok: true, descriptor, changedFiles: sortFiles(files) }; + } + + // Working tree: staged + unstaged (diff against HEAD) plus untracked files. + const nameStatus = await git(repoRoot, ['diff', '--relative', '--name-status', '-z', '-M', 'HEAD'], signal); + if (!nameStatus.ok) { + return failed('git-unavailable', `git diff HEAD failed: ${nameStatus.stderr.trim()}`); + } + const files = parseNameStatusZ(nameStatus.stdout); + const numstat = await git(repoRoot, ['diff', '--relative', '--numstat', '-z', '-M', 'HEAD'], signal); + if (numstat.ok) mergeNumstat(files, parseNumstatZ(numstat.stdout)); + + const untracked = await git( + repoRoot, + ['ls-files', '--others', '--exclude-standard', '-z'], + signal, + ); + if (untracked.ok) { + const known = new Set(files.map((file) => file.path)); + for (const token of untracked.stdout.split('\0')) { + if (token.length === 0 || known.has(token)) continue; + const absolute = path.join(repoRoot, token.split('/').join(path.sep)); + files.push({ + path: token, + changeType: 'untracked', + binary: sniffBinary(absolute), + symlinkOutsideRepository: false, + }); + } + } + flagSymlinkEscapes(repoRoot, files); + return { ok: true, descriptor, changedFiles: sortFiles(files) }; +} diff --git a/packages/drift/src/verification/context.ts b/packages/drift/src/verification/context.ts new file mode 100644 index 0000000..6f65e82 --- /dev/null +++ b/packages/drift/src/verification/context.ts @@ -0,0 +1,392 @@ +import { existsSync, readdirSync } from 'node:fs'; +import path from 'node:path'; +import type { SpecAnalysis, SpecFolder } from '@specbridge/compat-kiro'; +import { + analyzeSpec, + buildRequirementCatalog, + extractPathReferences, + extractTaskRequirementReferences, + taskFingerprint, + tryTaskPlanHashOfFile, +} from '@specbridge/compat-kiro'; +import type { + RequirementCatalog, + PathReference, + TaskRequirementReference, +} from '@specbridge/compat-kiro'; +import type { AgentConfig, SelectionMode, WorkspaceInfo } from '@specbridge/core'; +import { stateStage } from '@specbridge/core'; +import type { + CommitAncestry, + EvidenceAssessment, + EvidenceFreshnessContext, + TaskEvidenceAssessment, + TaskEvidenceRecord, +} from '@specbridge/evidence'; +import { assessTaskEvidence, listTaskEvidence, resolveCommitAncestry } from '@specbridge/evidence'; +import { runSafeProcess } from '@specbridge/runners'; +import type { WorkflowEvaluation } from '@specbridge/workflow'; +import { evaluateWorkflow } from '@specbridge/workflow'; +import type { ComparisonChangedFile, ResolvedComparison } from './comparison.js'; +import type { EffectivePolicy } from './policy.js'; +import { compilePathMatchers, resolveEffectivePolicy } from './policy.js'; +import type { OrchestratedCommands } from './commands.js'; + +/** + * Verification context assembly. Each spec is parsed exactly once per run; + * evidence, traceability, and approval evaluation are computed here and + * shared read-only by every rule. + */ + +export interface SpecEvidenceView { + assessmentsByTask: Map; + /** Every assessment across tasks (for command reuse lookups). */ + flattened: EvidenceAssessment[]; + /** Structurally invalid record files encountered in the store. */ + invalidRecordCount: number; +} + +export interface SpecTraceabilityView { + catalog: RequirementCatalog; + references: TaskRequirementReference[]; + designPathReferences: PathReference[]; +} + +export interface SpecVerificationContext { + workspace: WorkspaceInfo; + specName: string; + spec: SpecAnalysis; + /** How this verification run selected specs (some rules are mode-aware). */ + selectionMode: SelectionMode; + /** Present when sidecar state exists and validates. */ + evaluation?: WorkflowEvaluation; + policy: EffectivePolicy; + comparison: ResolvedComparison; + /** Every changed file in the comparison. */ + changedFiles: readonly ComparisonChangedFile[]; + /** Changed files relevant to this spec (spec dir, sidecar, impact areas, evidence). */ + specChangedFiles: ComparisonChangedFile[]; + traceability: SpecTraceabilityView; + evidence: SpecEvidenceView; + freshness: EvidenceFreshnessContext; + /** Why the spec was selected in `--changed` mode; empty otherwise. */ + matchedBy: string[]; + /** Content of a file at the comparison base (cached; undefined if absent). */ + readBaseContent: (repoPath: string) => Promise; + now: Date; +} + +export interface GlobalVerificationContext { + workspace: WorkspaceInfo; + comparison: ResolvedComparison; + selection: { mode: SelectionMode }; + specContexts: SpecVerificationContext[]; + /** Changed files that no spec in the workspace claims (SBV014). */ + unmappedFiles: ComparisonChangedFile[]; + /** Files claimed by more than one spec, with the matching reasons (SBV022). */ + ambiguousFiles: { path: string; specs: { name: string; via: string[] }[] }[]; + commands: OrchestratedCommands; + now: Date; +} + +/* ------------------------------------------------------------------ * + * Shared caches (per verification run) + * ------------------------------------------------------------------ */ + +const GIT_TIMEOUT_MS = 30_000; + +export interface RunCaches { + /** `git show :` content cache. */ + baseContent: Map; + /** Commit ancestry cache across specs. */ + ancestry: Map; +} + +export function createRunCaches(): RunCaches { + return { baseContent: new Map(), ancestry: new Map() }; +} + +function makeBaseContentReader( + workspace: WorkspaceInfo, + comparison: ResolvedComparison, + caches: RunCaches, + signal?: AbortSignal, +): (repoPath: string) => Promise { + return async (repoPath: string): Promise => { + if (caches.baseContent.has(repoPath)) return caches.baseContent.get(repoPath); + const baseSha = comparison.descriptor.baseSha; + if (baseSha === null) { + caches.baseContent.set(repoPath, undefined); + return undefined; + } + const result = await runSafeProcess({ + executable: 'git', + argv: ['show', `${baseSha}:${repoPath}`], + cwd: workspace.rootDir, + timeoutMs: GIT_TIMEOUT_MS, + maxStdoutBytes: 16 * 1024 * 1024, + ...(signal !== undefined ? { signal } : {}), + }); + const content = result.status === 'ok' ? result.stdout : undefined; + caches.baseContent.set(repoPath, content); + return content; + }; +} + +async function resolveAncestryCached( + workspace: WorkspaceInfo, + shas: readonly string[], + caches: RunCaches, + signal?: AbortSignal, +): Promise> { + const missing = shas.filter((sha) => !caches.ancestry.has(sha)); + if (missing.length > 0) { + const resolved = await resolveCommitAncestry(workspace.rootDir, missing, signal); + for (const [sha, ancestry] of resolved) caches.ancestry.set(sha, ancestry); + } + const view = new Map(); + for (const sha of shas) { + const ancestry = caches.ancestry.get(sha); + if (ancestry !== undefined) view.set(sha, ancestry); + } + return view; +} + +/* ------------------------------------------------------------------ * + * Spec-relevance matching (shared with affected-spec resolution) + * ------------------------------------------------------------------ */ + +export interface SpecMatchReason { + file: string; + via: string; +} + +/** Deterministic "does this changed file belong to this spec?" matcher. */ +export function specMatchReasons( + specName: string, + policy: EffectivePolicy, + validEvidencePaths: ReadonlySet, + designPathReferences: readonly PathReference[], + file: ComparisonChangedFile, +): string[] { + const reasons: string[] = []; + const posixPath = file.path; + if (posixPath.startsWith(`.kiro/specs/${specName}/`)) { + reasons.push('spec files'); + } + if (posixPath === `.specbridge/state/specs/${specName}.json`) { + reasons.push('sidecar state'); + } + if (posixPath === `.specbridge/policies/${specName}.json`) { + reasons.push('verification policy'); + } + if (policy.impactAreas.length > 0) { + const matched = compilePathMatchers(policy.impactAreas)(posixPath); + for (const pattern of matched) reasons.push(`impact area ${pattern}`); + } + if (validEvidencePaths.has(posixPath)) { + reasons.push('task evidence'); + } + for (const reference of designPathReferences) { + if (!reference.isGlob && reference.path === posixPath) { + reasons.push('design reference'); + break; + } + } + return reasons; +} + +/* ------------------------------------------------------------------ * + * Evidence loading + * ------------------------------------------------------------------ */ + +interface RawSpecEvidence { + byTask: Map; + invalidRecordCount: number; +} + +/** Read every evidence record of a spec exactly once. */ +function readSpecEvidenceRecords(workspace: WorkspaceInfo, specName: string): RawSpecEvidence { + const byTask = new Map(); + let invalidRecordCount = 0; + const specDir = path.join(workspace.sidecarDir, 'evidence', specName); + if (existsSync(specDir)) { + const taskDirs = readdirSync(specDir, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort((a, b) => a.localeCompare(b, 'en')); + for (const taskDir of taskDirs) { + const { records, diagnostics } = listTaskEvidence(workspace, specName, taskDir); + invalidRecordCount += diagnostics.length; + if (records.length === 0) continue; + const taskId = records[0]?.taskId ?? taskDir; + const list = byTask.get(taskId) ?? []; + list.push(...records); + byTask.set(taskId, list); + } + } + return { byTask, invalidRecordCount }; +} + +/* ------------------------------------------------------------------ * + * Context builders + * ------------------------------------------------------------------ */ + +export interface BuildSpecContextOptions { + workspace: WorkspaceInfo; + folder: SpecFolder; + config: AgentConfig; + comparison: ResolvedComparison; + selectionMode: SelectionMode; + caches: RunCaches; + strict?: boolean; + explicitPolicyPath?: string; + matchedBy?: string[]; + now: Date; + signal?: AbortSignal; +} + +export async function buildSpecVerificationContext( + options: BuildSpecContextOptions, +): Promise { + const { workspace, folder, comparison, caches, now } = options; + const spec = analyzeSpec(workspace, folder); + const evaluation = spec.state !== undefined ? evaluateWorkflow(workspace, spec.state) : undefined; + + const policy = resolveEffectivePolicy(workspace, folder.name, { + globalProtectedPaths: options.config.execution.protectedPaths, + ...(options.strict !== undefined ? { strict: options.strict } : {}), + ...(options.explicitPolicyPath !== undefined + ? { explicitPolicyPath: options.explicitPolicyPath } + : {}), + }); + + // ---- Traceability (parsed models reused from analyzeSpec) --------------- + const requirementsDocument = spec.documents.requirements; + const catalog = + spec.requirements !== undefined + ? buildRequirementCatalog(spec.requirements, requirementsDocument) + : { entries: [], requirements: [], byCanonical: new Map() }; + const tasksDocument = spec.documents.tasks; + const references = + tasksDocument !== undefined && spec.tasks !== undefined + ? extractTaskRequirementReferences(tasksDocument, spec.tasks) + : []; + const designDocument = spec.documents.design; + const designPathReferences = + designDocument !== undefined ? extractPathReferences(designDocument) : []; + + // ---- Approval identity for evidence freshness ---------------------------- + const approved: EvidenceFreshnessContext['approved'] = {}; + const approvedAt: EvidenceFreshnessContext['approvedAt'] = {}; + if (spec.state !== undefined && evaluation !== undefined) { + const documentStageName = spec.state.specType === 'bugfix' ? 'bugfix' : 'requirements'; + const documentStage = stateStage(spec.state, documentStageName); + const designStage = stateStage(spec.state, 'design'); + const tasksStage = stateStage(spec.state, 'tasks'); + if (documentStage?.approvedAt != null) approvedAt.document = documentStage.approvedAt; + if (designStage?.approvedAt != null) approvedAt.design = designStage.approvedAt; + if (tasksStage?.approvedAt != null) approvedAt.tasks = tasksStage.approvedAt; + + const effective = (stage: string): boolean => + evaluation.stages.find((s) => s.stage === stage)?.effective === 'approved'; + if (effective(documentStageName) && documentStage?.approvedHash != null) { + approved.documentHash = documentStage.approvedHash; + } + if (effective('design') && designStage?.approvedHash != null) { + approved.designHash = designStage.approvedHash; + } + if (effective('tasks') && tasksStage !== undefined) { + const planHash = + typeof tasksStage.approvedPlanHash === 'string' + ? tasksStage.approvedPlanHash + : tryTaskPlanHashOfFile( + path.join(workspace.rootDir, tasksStage.file.split('/').join(path.sep)), + ); + if (planHash !== undefined) approved.tasksPlanHash = planHash; + } + } + + const currentTasks = new Map< + string, + { fingerprint: string; title: string; rawLineText: string; state: string } + >(); + if (spec.tasks !== undefined && tasksDocument !== undefined) { + for (const task of spec.tasks.allTasks) { + currentTasks.set(task.id, { + fingerprint: taskFingerprint(task), + title: task.title, + rawLineText: tasksDocument.lineAt(task.line).text, + state: task.state, + }); + } + } + + // Read evidence once, resolve commit ancestry (shared cache), then assess. + const rawEvidence = readSpecEvidenceRecords(workspace, folder.name); + const freshness: EvidenceFreshnessContext = { + specName: folder.name, + approved, + approvedAt, + tasks: currentTasks, + now, + }; + const recordedShas = new Set(); + for (const records of rawEvidence.byTask.values()) { + for (const record of records) { + if (record.repository.headAfter !== undefined) recordedShas.add(record.repository.headAfter); + } + } + if (recordedShas.size > 0 && comparison.descriptor.headSha !== null) { + freshness.ancestry = await resolveAncestryCached( + workspace, + [...recordedShas], + caches, + options.signal, + ); + } + + const assessmentsByTask = new Map(); + const flattened: EvidenceAssessment[] = []; + for (const [taskId, records] of rawEvidence.byTask) { + const assessment = assessTaskEvidence(taskId, records, freshness); + assessmentsByTask.set(taskId, assessment); + flattened.push(...assessment.all); + } + const evidence: SpecEvidenceView = { + assessmentsByTask, + flattened, + invalidRecordCount: rawEvidence.invalidRecordCount, + }; + + // ---- Spec-relevant changed files ----------------------------------------- + const validEvidencePaths = new Set(); + for (const assessment of evidence.assessmentsByTask.values()) { + const best = assessment.best; + if (best === undefined || best.validity !== 'valid') continue; + for (const file of best.record.changedFiles) validEvidencePaths.add(file.path); + } + const specChangedFiles = comparison.changedFiles.filter( + (file) => + specMatchReasons(folder.name, policy, validEvidencePaths, designPathReferences, file) + .length > 0, + ); + + return { + workspace, + specName: folder.name, + spec, + selectionMode: options.selectionMode, + ...(evaluation !== undefined ? { evaluation } : {}), + policy, + comparison, + changedFiles: comparison.changedFiles, + specChangedFiles, + traceability: { catalog, references, designPathReferences }, + evidence, + freshness, + matchedBy: options.matchedBy ?? [], + readBaseContent: makeBaseContentReader(workspace, comparison, caches, options.signal), + now, + }; +} diff --git a/packages/drift/src/verification/policy.ts b/packages/drift/src/verification/policy.ts new file mode 100644 index 0000000..d71c17c --- /dev/null +++ b/packages/drift/src/verification/policy.ts @@ -0,0 +1,314 @@ +import { existsSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import picomatch from 'picomatch'; +import { z } from 'zod'; +import type { Diagnostic, PolicyMode, WorkspaceInfo } from '@specbridge/core'; +import { VERIFICATION_RULE_ID_PATTERN } from '@specbridge/core'; + +/** + * Spec-specific verification policy. + * + * One JSON file per spec under `.specbridge/policies/.json` — + * plain configuration, never executable, never a spec stage, and never + * required: verification falls back to secure built-in defaults. + * + * Precedence (weakest to strongest): + * 1. secure built-in defaults (protected paths below) + * 2. global project configuration (`.specbridge/config.json`) + * 3. this per-spec policy file + * 4. explicit CLI flags (`--strict` may only tighten checks) + * + * `.git/**` protection is unconditional and cannot be configured away. + */ + +export const VERIFICATION_POLICY_SCHEMA_VERSION = '1.0.0'; + +/** + * Protected paths that are always enforced during implementation + * verification, regardless of configuration. + */ +export const BUILT_IN_PROTECTED_PATHS = [ + '.kiro/**', + '.specbridge/state/**', + '.specbridge/config.json', + '.git/**', +] as const; + +/** The one protected pattern that no configuration layer may remove. */ +export const IMMUTABLE_PROTECTED_PATHS = ['.git/**'] as const; + +const GLOB_MAX_LENGTH = 512; + +export interface GlobPatternIssue { + pattern: string; + reason: string; +} + +/** + * Validate one glob pattern for use against repository-relative paths. + * Patterns are matched with picomatch (documented in docs/verification-policy.md). + */ +export function validateGlobPattern(pattern: string): GlobPatternIssue | undefined { + if (pattern.length === 0) return { pattern, reason: 'pattern is empty' }; + if (pattern.length > GLOB_MAX_LENGTH) { + return { pattern, reason: `pattern exceeds ${GLOB_MAX_LENGTH} characters` }; + } + if (pattern.includes('\0')) return { pattern, reason: 'pattern contains a null byte' }; + if (pattern.includes('\\')) { + return { + pattern, + reason: 'pattern contains a backslash; use forward slashes for repository paths', + }; + } + if (pattern.startsWith('/') || /^[A-Za-z]:/.test(pattern)) { + return { pattern, reason: 'pattern must be repository-relative, not absolute' }; + } + if (pattern.split('/').includes('..')) { + return { pattern, reason: 'pattern must not contain ".." path traversal segments' }; + } + try { + picomatch(pattern); + } catch (cause) { + return { + pattern, + reason: `pattern is not a valid glob: ${cause instanceof Error ? cause.message : String(cause)}`, + }; + } + return undefined; +} + +const globPatternSchema = z.string().superRefine((pattern, ctx) => { + const issue = validateGlobPattern(pattern); + if (issue !== undefined) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: issue.reason }); + } +}); + +export const policyRuleOverrideSchema = z + .object({ + enabled: z.boolean().default(true), + severity: z.enum(['error', 'warning', 'info']).optional(), + }) + .passthrough(); +export type PolicyRuleOverride = z.infer; + +export const verificationPolicySchema = z + .object({ + schemaVersion: z + .string() + .regex(/^\d+\.\d+\.\d+$/) + .default(VERIFICATION_POLICY_SCHEMA_VERSION), + specName: z.string().min(1), + mode: z.enum(['advisory', 'strict']).default('advisory'), + impactAreas: z.array(globPatternSchema).default([]), + protectedPaths: z.array(globPatternSchema).default([]), + /** Names of trusted commands (from `.specbridge/config.json`) that must pass. */ + requiredVerificationCommands: z.array(z.string().min(1)).default([]), + requireVerifiedTaskEvidence: z.boolean().default(false), + requireRequirementTaskLinks: z.boolean().default(false), + requireTestEvidence: z.boolean().default(false), + rules: z + .record( + z.string().regex(VERIFICATION_RULE_ID_PATTERN, 'rule keys must look like SBV005'), + policyRuleOverrideSchema, + ) + .default({}), + }) + .passthrough() + .superRefine((policy, ctx) => { + if (!policy.schemaVersion.startsWith('1.')) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ['schemaVersion'], + message: `schema version ${policy.schemaVersion} is not supported by this SpecBridge version`, + }); + } + }); +export type VerificationPolicy = z.infer; + +export function policyDir(workspace: WorkspaceInfo): string { + return path.join(workspace.sidecarDir, 'policies'); +} + +export function policyPath(workspace: WorkspaceInfo, specName: string): string { + const resolved = path.resolve(policyDir(workspace), `${specName}.json`); + const relative = path.relative(workspace.rootDir, resolved); + if (relative.startsWith('..') || path.isAbsolute(relative)) { + // A spec name is a directory name; anything that escapes is hostile input. + return path.join(policyDir(workspace), 'invalid-spec-name.json'); + } + return resolved; +} + +export interface PolicyReadResult { + /** Absolute path that was read (or would be read). */ + path: string; + exists: boolean; + policy?: VerificationPolicy; + diagnostics: Diagnostic[]; +} + +/** + * Read one policy file. Fail-closed: an existing file that does not validate + * yields NO policy plus error diagnostics (surfaced as SBV020 by the rule + * engine) — verification then runs with secure defaults, never with a + * half-understood policy. + */ +export function readVerificationPolicy( + workspace: WorkspaceInfo, + specName: string, + explicitPath?: string, +): PolicyReadResult { + const filePath = + explicitPath !== undefined + ? path.resolve(workspace.rootDir, explicitPath) + : policyPath(workspace, specName); + if (!existsSync(filePath)) { + return { path: filePath, exists: false, diagnostics: [] }; + } + + let parsed: unknown; + try { + parsed = JSON.parse(readFileSync(filePath, 'utf8')); + } catch (cause) { + return { + path: filePath, + exists: true, + diagnostics: [ + { + severity: 'error', + code: 'POLICY_INVALID_JSON', + message: `Verification policy is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}`, + file: filePath, + }, + ], + }; + } + + const result = verificationPolicySchema.safeParse(parsed); + if (!result.success) { + const issues = result.error.issues + .map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`) + .join('; '); + return { + path: filePath, + exists: true, + diagnostics: [ + { + severity: 'error', + code: 'POLICY_INVALID_SHAPE', + message: `Verification policy does not match the versioned schema: ${issues}`, + file: filePath, + }, + ], + }; + } + + if (explicitPath === undefined && result.data.specName !== specName) { + return { + path: filePath, + exists: true, + diagnostics: [ + { + severity: 'error', + code: 'POLICY_NAME_MISMATCH', + message: `Verification policy records specName "${result.data.specName}" but is stored as ${specName}.json.`, + file: filePath, + }, + ], + }; + } + + return { path: filePath, exists: true, policy: result.data, diagnostics: [] }; +} + +/** Fully resolved policy after applying every precedence layer. */ +export interface EffectivePolicy { + specName: string; + mode: PolicyMode; + /** True when `--strict` raised the mode beyond the stored policy. */ + strictFromCli: boolean; + impactAreas: string[]; + /** Merged protected paths; always contains the built-ins. */ + protectedPaths: string[]; + requiredVerificationCommands: string[]; + requireVerifiedTaskEvidence: boolean; + requireRequirementTaskLinks: boolean; + requireTestEvidence: boolean; + ruleOverrides: Record; + /** Workspace-relative policy file path when a file was used. */ + policyPath?: string; + policyExists: boolean; + /** Error diagnostics from an unreadable/invalid policy file (SBV020). */ + policyDiagnostics: Diagnostic[]; +} + +export interface ResolveEffectivePolicyOptions { + /** Additional protected paths from global configuration. */ + globalProtectedPaths?: string[]; + /** CLI `--strict`: tighten to strict mode (never loosens). */ + strict?: boolean; + /** Explicit `--policy ` override. */ + explicitPolicyPath?: string; +} + +export function resolveEffectivePolicy( + workspace: WorkspaceInfo, + specName: string, + options: ResolveEffectivePolicyOptions = {}, +): EffectivePolicy { + const read = readVerificationPolicy(workspace, specName, options.explicitPolicyPath); + const policy = read.policy; + + const protectedPaths: string[] = [...BUILT_IN_PROTECTED_PATHS]; + for (const pattern of options.globalProtectedPaths ?? []) { + // Global config stores prefix-style protected paths; normalize a plain + // directory prefix into a glob that covers the whole subtree. + const validated = validateGlobPattern(pattern); + if (validated !== undefined) continue; + const asGlob = /[*?[\]{}]/.test(pattern) + ? pattern + : `${pattern.replace(/\/+$/, '')}/**`; + if (!protectedPaths.includes(asGlob)) protectedPaths.push(asGlob); + } + for (const pattern of policy?.protectedPaths ?? []) { + if (!protectedPaths.includes(pattern)) protectedPaths.push(pattern); + } + + const storedMode: PolicyMode = policy?.mode ?? 'advisory'; + const strictFromCli = options.strict === true && storedMode !== 'strict'; + const mode: PolicyMode = options.strict === true ? 'strict' : storedMode; + + const workspaceRelativePolicyPath = path + .relative(workspace.rootDir, read.path) + .split(path.sep) + .join('/'); + + return { + specName, + mode, + strictFromCli, + impactAreas: [...(policy?.impactAreas ?? [])], + protectedPaths, + requiredVerificationCommands: [...(policy?.requiredVerificationCommands ?? [])], + requireVerifiedTaskEvidence: policy?.requireVerifiedTaskEvidence ?? false, + requireRequirementTaskLinks: policy?.requireRequirementTaskLinks ?? false, + requireTestEvidence: policy?.requireTestEvidence ?? false, + ruleOverrides: { ...(policy?.rules ?? {}) }, + ...(read.exists ? { policyPath: workspaceRelativePolicyPath } : {}), + policyExists: read.exists, + policyDiagnostics: read.diagnostics, + }; +} + +/** Compiled matcher over repository-relative POSIX paths. */ +export function compilePathMatchers(patterns: readonly string[]): (candidate: string) => string[] { + const matchers = patterns.map((pattern) => ({ + pattern, + isMatch: picomatch(pattern, { dot: true }), + })); + return (candidate: string): string[] => { + const posix = candidate.split('\\').join('/'); + return matchers.filter(({ isMatch }) => isMatch(posix)).map(({ pattern }) => pattern); + }; +} diff --git a/packages/drift/src/verification/rule-engine.ts b/packages/drift/src/verification/rule-engine.ts new file mode 100644 index 0000000..32a9412 --- /dev/null +++ b/packages/drift/src/verification/rule-engine.ts @@ -0,0 +1,186 @@ +import type { + VerificationCategory, + VerificationConfidence, + VerificationDiagnostic, + VerificationSeverity, +} from '@specbridge/core'; +import { VERIFICATION_DIAGNOSTIC_SCHEMA_VERSION } from '@specbridge/core'; +import type { EffectivePolicy } from './policy.js'; +import type { GlobalVerificationContext, SpecVerificationContext } from './context.js'; + +/** + * Deterministic verification rule engine. + * + * Rules are pure functions over a pre-assembled context: no rule touches the + * file system for spec content (parsed once during context building), no + * rule executes anything, and no rule may write. Rule IDs are stable and + * never silently renumbered; the registry order is the documentation order. + */ + +export interface ResolvedRuleConfig { + enabled: boolean; + severity: VerificationSeverity; + /** True when the severity comes from an explicit policy override. */ + overridden: boolean; +} + +interface RuleBase { + readonly id: string; + readonly title: string; + readonly category: VerificationCategory; + /** Default severity per policy mode; heuristic rules may not default to error. */ + readonly defaultSeverity: { advisory: VerificationSeverity; strict: VerificationSeverity }; + readonly confidence: VerificationConfidence; + /** One-paragraph trigger description for `verify explain`. */ + readonly triggeredWhen: string; + /** Default remediation for `verify explain` and diagnostics. */ + readonly resolution: string; +} + +export interface SpecVerificationRule extends RuleBase { + readonly scope: 'spec'; + evaluate( + context: SpecVerificationContext, + resolved: ResolvedRuleConfig, + ): VerificationDiagnostic[] | Promise; +} + +export interface GlobalVerificationRule extends RuleBase { + readonly scope: 'global'; + evaluate( + context: GlobalVerificationContext, + resolved: ResolvedRuleConfig, + ): VerificationDiagnostic[] | Promise; +} + +export type VerificationRule = SpecVerificationRule | GlobalVerificationRule; + +/** Resolve one rule's configuration against a spec's effective policy. */ +export function resolveRuleConfig( + rule: RuleBase, + policy: Pick, +): ResolvedRuleConfig { + const override = policy.ruleOverrides[rule.id]; + const severity = override?.severity ?? rule.defaultSeverity[policy.mode]; + return { + enabled: override?.enabled ?? true, + severity, + overridden: override?.severity !== undefined, + }; +} + +const SEVERITY_ORDER: Record = { error: 0, warning: 1, info: 2 }; + +/** + * Resolve a global rule against every selected spec's policy: the rule is + * disabled only when every policy disables it, and the strictest severity + * wins (a global finding must not be weakened by one lenient spec). + */ +export function resolveGlobalRuleConfig( + rule: RuleBase, + policies: readonly Pick[], +): ResolvedRuleConfig { + if (policies.length === 0) { + return { enabled: true, severity: rule.defaultSeverity.advisory, overridden: false }; + } + const resolved = policies.map((policy) => resolveRuleConfig(rule, policy)); + const enabled = resolved.some((config) => config.enabled); + const strictest = resolved.reduce((best, config) => + SEVERITY_ORDER[config.severity] < SEVERITY_ORDER[best.severity] ? config : best, + ); + return { enabled, severity: strictest.severity, overridden: strictest.overridden }; +} + +export interface DiagnosticInput { + rule: RuleBase; + severity: VerificationSeverity; + message: string; + remediation?: string; + specName?: string | null; + taskId?: string | null; + requirementId?: string | null; + file?: { path: string; line?: number | null; column?: number | null } | null; + evidence?: Record; + /** Override the rule's predominant confidence for this one finding. */ + confidence?: VerificationConfidence; +} + +/** Build a schema-complete diagnostic from rule metadata plus specifics. */ +export function makeDiagnostic(input: DiagnosticInput): VerificationDiagnostic { + const file = + input.file === null || input.file === undefined + ? null + : { + path: input.file.path, + line: input.file.line ?? null, + column: input.file.column ?? null, + }; + return { + schemaVersion: VERIFICATION_DIAGNOSTIC_SCHEMA_VERSION, + ruleId: input.rule.id, + title: input.rule.title, + severity: input.severity, + category: input.rule.category, + message: input.message, + remediation: input.remediation ?? input.rule.resolution, + specName: input.specName ?? null, + taskId: input.taskId ?? null, + requirementId: input.requirementId ?? null, + file, + evidence: input.evidence ?? {}, + confidence: input.confidence ?? input.rule.confidence, + }; +} + +/** Human-readable default-severity description for `verify explain`. */ +export function describeDefaultSeverity(rule: RuleBase): string { + if (rule.defaultSeverity.advisory === rule.defaultSeverity.strict) { + return rule.defaultSeverity.advisory; + } + return `${rule.defaultSeverity.advisory} in advisory mode, ${rule.defaultSeverity.strict} in strict mode`; +} + +export interface RuleEngineResult { + diagnostics: VerificationDiagnostic[]; + /** Rules skipped because a policy disabled them. */ + disabledRules: string[]; +} + +/** Evaluate every enabled spec-scoped rule against one spec context. */ +export async function evaluateSpecRules( + rules: readonly VerificationRule[], + context: SpecVerificationContext, +): Promise { + const diagnostics: VerificationDiagnostic[] = []; + const disabledRules: string[] = []; + for (const rule of rules) { + if (rule.scope !== 'spec') continue; + const resolved = resolveRuleConfig(rule, context.policy); + if (!resolved.enabled) { + disabledRules.push(rule.id); + continue; + } + diagnostics.push(...(await rule.evaluate(context, resolved))); + } + return { diagnostics, disabledRules }; +} + +/** Evaluate every enabled global rule once for the whole run. */ +export async function evaluateGlobalRules( + rules: readonly VerificationRule[], + context: GlobalVerificationContext, +): Promise { + const policies = context.specContexts.map((spec) => spec.policy); + const diagnostics: VerificationDiagnostic[] = []; + const disabledRules: string[] = []; + for (const rule of rules) { + if (rule.scope !== 'global') continue; + const resolved = resolveGlobalRuleConfig(rule, policies); + if (!resolved.enabled) { + disabledRules.push(rule.id); + continue; + } + diagnostics.push(...(await rule.evaluate(context, resolved))); + } + return { diagnostics, disabledRules }; +} diff --git a/packages/drift/src/verification/rules.ts b/packages/drift/src/verification/rules.ts new file mode 100644 index 0000000..de7593c --- /dev/null +++ b/packages/drift/src/verification/rules.ts @@ -0,0 +1,1224 @@ +import { existsSync } from 'node:fs'; +import path from 'node:path'; +import { MarkdownDocument, normalizedTaskPlanText } from '@specbridge/compat-kiro'; +import type { TaskItem } from '@specbridge/compat-kiro'; +import { isLikelyNonRequirementTask, taskMentionsTests } from '@specbridge/compat-kiro'; +import type { VerificationDiagnostic, WorkspaceInfo } from '@specbridge/core'; +import type { EvidenceReasonCode } from '@specbridge/evidence'; +import type { SpecVerificationContext } from './context.js'; +import type { + GlobalVerificationRule, + ResolvedRuleConfig, + SpecVerificationRule, + VerificationRule, +} from './rule-engine.js'; +import { makeDiagnostic } from './rule-engine.js'; +import { IMMUTABLE_PROTECTED_PATHS, compilePathMatchers } from './policy.js'; + +/** + * Built-in verification rules SBV001–SBV025. + * + * The registry at the bottom of this file is the single source of truth for + * rule IDs. IDs are stable: rules are never silently renumbered, and removed + * rules would leave a documented gap rather than shifting later IDs. + */ + +/* ------------------------------------------------------------------ * + * Shared helpers + * ------------------------------------------------------------------ */ + +function repoRelative(workspace: WorkspaceInfo, absolutePath: string): string { + return path.relative(workspace.rootDir, absolutePath).split(path.sep).join('/'); +} + +/** Paths that are workflow/VCS infrastructure, never implementation. */ +function isSpecInfraPath(candidate: string): boolean { + return ( + candidate === '.git' || + candidate.startsWith('.git/') || + candidate.startsWith('.kiro/') || + candidate.startsWith('.specbridge/') + ); +} + +function doneLeafTasks(context: SpecVerificationContext): TaskItem[] { + const model = context.spec.tasks; + if (model === undefined) return []; + return model.allTasks.filter((task) => task.children.length === 0 && task.state === 'done'); +} + +function tasksFilePath(context: SpecVerificationContext): string | undefined { + const filePath = context.spec.documents.tasks?.filePath; + return filePath !== undefined ? repoRelative(context.workspace, filePath) : undefined; +} + +function taskFileLocation( + context: SpecVerificationContext, + task: Pick, +): { path: string; line: number } | null { + const filePath = tasksFilePath(context); + return filePath !== undefined ? { path: filePath, line: task.line + 1 } : null; +} + +/** The selected spec's own workflow files (exempt from SBV006 by design). */ +function ownWorkflowPaths(specName: string, candidate: string): boolean { + return ( + candidate.startsWith(`.kiro/specs/${specName}/`) || + candidate === `.specbridge/state/specs/${specName}.json` || + candidate === `.specbridge/policies/${specName}.json` + ); +} + +const TEST_PATH_PATTERN = /(^|\/)(tests?|__tests__)(\/|$)|\.(test|spec)\.[a-z0-9]+$/i; +const TEST_COMMAND_PATTERN = /test/i; + +/* ------------------------------------------------------------------ * + * SBV001 — Required spec file missing + * ------------------------------------------------------------------ */ + +const sbv001: SpecVerificationRule = { + id: 'SBV001', + title: 'Required spec file missing', + category: 'workspace', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'A feature spec is missing requirements.md, design.md, or tasks.md, or a bugfix spec is missing bugfix.md, design.md, or tasks.md.', + resolution: + 'Create the missing document (specbridge spec new scaffolds Kiro-compatible files), or remove the incomplete spec folder.', + evaluate(context, resolved) { + const type = context.spec.classification.type; + if (type !== 'feature' && type !== 'bugfix') return []; + const required = + type === 'bugfix' + ? ['bugfix.md', 'design.md', 'tasks.md'] + : ['requirements.md', 'design.md', 'tasks.md']; + const present = new Set(context.spec.folder.files.map((file) => file.fileName.toLowerCase())); + return required + .filter((fileName) => !present.has(fileName)) + .map((fileName) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The ${type} spec "${context.specName}" is missing ${fileName}.`, + specName: context.specName, + file: { path: `.kiro/specs/${context.specName}/${fileName}` }, + evidence: { specType: type, missingFile: fileName }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV002 — Spec approval stale + * ------------------------------------------------------------------ */ + +const sbv002: SpecVerificationRule = { + id: 'SBV002', + title: 'Spec approval stale', + category: 'approval', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'An approved stage document no longer matches its recorded approval hash. For the tasks stage, checkbox-only progress is NOT stale (hash semantics v2); any other byte change is.', + resolution: + 'Review the changed document and re-approve the stage (specbridge spec approve --stage ), or restore the approved content.', + evaluate(context, resolved) { + if (context.evaluation === undefined) return []; + return context.evaluation.stages + .filter((stage) => stage.effective === 'modified-after-approval') + .map((stage) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The approved ${stage.stage} stage of "${context.specName}" changed after approval (approved hash ${stage.stored.approvedHash?.slice(0, 12) ?? '(none)'}…, current ${stage.currentHash?.slice(0, 12) ?? 'missing'}…).`, + specName: context.specName, + file: { path: stage.stored.file }, + evidence: { + stage: stage.stage, + approvedHash: stage.stored.approvedHash, + currentHash: stage.currentHash ?? null, + approvedAt: stage.stored.approvedAt, + }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV003 — Approval prerequisite invalid + * ------------------------------------------------------------------ */ + +const sbv003: SpecVerificationRule = { + id: 'SBV003', + title: 'Approval prerequisite invalid', + category: 'approval', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'A later-stage approval depends on an earlier stage that is stale, revoked, or was never approved.', + resolution: + 'Re-approve the earlier stage first, then re-approve the dependent stage — approvals form a chain.', + evaluate(context, resolved) { + if (context.evaluation === undefined) return []; + const diagnostics: VerificationDiagnostic[] = []; + for (const stage of context.evaluation.stages) { + if (stage.stored.status !== 'approved') continue; + if (stage.effective === 'stale-prerequisite') { + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The ${stage.stage} approval of "${context.specName}" is invalid because an earlier stage changed after it was approved.`, + specName: context.specName, + file: { path: stage.stored.file }, + evidence: { stage: stage.stage, prerequisites: stage.prerequisites }, + }), + ); + continue; + } + const unapproved = stage.prerequisites.filter((prerequisite) => { + const evaluation = context.evaluation?.stages.find((s) => s.stage === prerequisite); + return evaluation !== undefined && evaluation.stored.status !== 'approved'; + }); + if (unapproved.length > 0) { + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `The ${stage.stage} stage of "${context.specName}" is approved although ${unapproved.join(' and ')} ${unapproved.length === 1 ? 'is' : 'are'} not.`, + specName: context.specName, + file: { path: stage.stored.file }, + evidence: { stage: stage.stage, unapprovedPrerequisites: unapproved }, + }), + ); + } + } + return diagnostics; + }, +}; + +/* ------------------------------------------------------------------ * + * SBV004 — Completed task lacks verified evidence + * ------------------------------------------------------------------ */ + +const sbv004: SpecVerificationRule = { + id: 'SBV004', + title: 'Completed task lacks verified evidence', + category: 'evidence', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'A task checkbox is [x] but no verified or manually accepted evidence record exists for it. Error severity when the policy sets requireVerifiedTaskEvidence.', + resolution: + 'Run the task through specbridge spec run (which records evidence), accept it explicitly with specbridge spec accept-task, or uncheck the box.', + evaluate(context, resolved) { + const severity = context.policy.requireVerifiedTaskEvidence ? 'error' : resolved.severity; + return doneLeafTasks(context) + .filter((task) => { + const assessment = context.evidence.assessmentsByTask.get(task.id); + // Stale evidence is reported separately (SBV011/SBV015); structurally + // invalid records are not usable evidence and count as absent here. + return ( + assessment === undefined || + assessment.bucket === 'missing' || + assessment.bucket === 'invalid' + ); + }) + .map((task) => { + const assessment = context.evidence.assessmentsByTask.get(task.id); + const invalidOnly = assessment?.bucket === 'invalid'; + return makeDiagnostic({ + rule: this, + severity, + message: invalidOnly + ? `Task ${task.id} ("${task.title}") is checked but its only evidence records are structurally invalid.` + : `Task ${task.id} ("${task.title}") is checked but has no verified or manually accepted evidence.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { + evidenceRequired: context.policy.requireVerifiedTaskEvidence, + checkboxState: task.stateChar, + invalidRecordsOnly: invalidOnly, + }, + }); + }); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV005 — Changed file outside declared impact area + * ------------------------------------------------------------------ */ + +const sbv005: SpecVerificationRule = { + id: 'SBV005', + title: 'Changed file outside declared impact area', + category: 'impact-area', + defaultSeverity: { advisory: 'warning', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'Verifying a single named spec whose policy declares impact areas: a changed repository file matches none of them. (In --changed/--all runs, cross-spec coverage is reported by SBV014 instead.)', + resolution: + 'Revert the unrelated change, split it into its own change set, or extend the impact areas in the spec verification policy after review.', + evaluate(context, resolved) { + if (context.selectionMode !== 'single') return []; + if (context.policy.impactAreas.length === 0) return []; + const matcher = compilePathMatchers(context.policy.impactAreas); + return context.changedFiles + .filter((file) => !isSpecInfraPath(file.path)) + .filter((file) => matcher(file.path).length === 0) + .map((file) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${file.path} is outside the impact areas declared for ${context.specName}.`, + specName: context.specName, + file: { path: file.path }, + evidence: { + changedPath: file.path, + changeType: file.changeType, + declaredImpactAreas: context.policy.impactAreas, + }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV006 — Protected path modified + * ------------------------------------------------------------------ */ + +const sbv006: GlobalVerificationRule = { + id: 'SBV006', + title: 'Protected path modified', + category: 'protected-path', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'The comparison touches a protected path (.kiro/**, .specbridge/state/**, .specbridge/config.json, .git/**, or configured additions). The verified specs’ own spec files, sidecar state, and policy are exempt — changing them is spec authoring, which the approval rules govern — and checkbox-only tasks.md progress is always exempt.', + resolution: + 'Remove the protected-path change from this change set, or — if this is deliberate spec authoring for a spec not under verification — verify that spec too.', + async evaluate(context, resolved) { + if (!context.comparison.ok) return []; + const selectedSpecs = context.specContexts.map((spec) => spec.specName); + const patterns = new Set(); + for (const spec of context.specContexts) { + for (const pattern of spec.policy.protectedPaths) patterns.add(pattern); + } + if (patterns.size === 0) { + for (const pattern of ['.kiro/**', '.specbridge/state/**', '.specbridge/config.json', '.git/**']) { + patterns.add(pattern); + } + } + const matcher = compilePathMatchers([...patterns]); + const immutableMatcher = compilePathMatchers([...IMMUTABLE_PROTECTED_PATHS]); + + const diagnostics: VerificationDiagnostic[] = []; + for (const file of context.comparison.changedFiles) { + const matched = matcher(file.path); + if (matched.length === 0) continue; + + const owningSpec = selectedSpecs.find((specName) => ownWorkflowPaths(specName, file.path)); + if (owningSpec !== undefined) { + // Spec authoring of a spec under verification: sanctioned, but for a + // modified tasks.md distinguish checkbox progress from plan edits + // (plan edits are separately flagged by SBV023). + let note = 'spec-authoring change of a verified spec'; + if ( + file.path === `.kiro/specs/${owningSpec}/tasks.md` && + (file.changeType === 'modified' || file.changeType === 'renamed') + ) { + const specContext = context.specContexts.find((spec) => spec.specName === owningSpec); + const checkboxOnly = + specContext !== undefined ? await isCheckboxOnlyChange(specContext, file.path) : false; + note = checkboxOnly + ? 'checkbox-only task progress (expected)' + : 'task plan edited (see SBV023)'; + } + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: 'info', + message: `${file.path} changed — ${note}.`, + specName: owningSpec, + file: { path: file.path }, + evidence: { matchedPatterns: matched, exempt: true, note }, + }), + ); + continue; + } + + const severity = immutableMatcher(file.path).length > 0 ? 'error' : resolved.severity; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity, + message: `Protected path ${file.path} was ${file.changeType === 'deleted' ? 'deleted' : 'modified'} by this change set.`, + file: { path: file.path }, + evidence: { + matchedPatterns: matched, + changeType: file.changeType, + selectedSpecs, + }, + }), + ); + } + return diagnostics; + }, +}; + +async function isCheckboxOnlyChange( + context: SpecVerificationContext, + repoPath: string, +): Promise { + const baseContent = await context.readBaseContent(repoPath); + if (baseContent === undefined) return false; + const currentDocument = context.spec.documents.tasks; + if (currentDocument === undefined) return false; + const baseDocument = MarkdownDocument.fromText(baseContent); + return normalizedTaskPlanText(baseDocument) === normalizedTaskPlanText(currentDocument); +} + +/* ------------------------------------------------------------------ * + * SBV007 — Requirement has no implementation task + * ------------------------------------------------------------------ */ + +const sbv007: SpecVerificationRule = { + id: 'SBV007', + title: 'Requirement has no implementation task', + category: 'requirements', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'An identifiable requirement ID is referenced by no task — neither directly nor through any of its acceptance criteria. Error severity when the policy sets requireRequirementTaskLinks.', + resolution: + 'Add an implementation task referencing the requirement (e.g. a _Requirements: 1.2_ detail line), or remove the requirement if it is obsolete.', + evaluate(context, resolved) { + const { catalog, references } = context.traceability; + if (catalog.requirements.length === 0 || context.spec.tasks === undefined) return []; + const severity = context.policy.requireRequirementTaskLinks ? 'error' : resolved.severity; + const referenced = new Set( + references + .map((reference) => reference.canonical) + .filter((canonical): canonical is string => canonical !== undefined), + ); + const requirementsFile = context.spec.documents.requirements?.filePath; + const filePath = + requirementsFile !== undefined ? repoRelative(context.workspace, requirementsFile) : undefined; + + return catalog.requirements + .filter((requirement) => { + for (const canonical of referenced) { + if (canonical === requirement.canonical) return false; + const entry = catalog.byCanonical.get(canonical); + if (entry !== undefined && entry.requirementCanonical === requirement.canonical) { + return false; + } + } + return true; + }) + .map((requirement) => + makeDiagnostic({ + rule: this, + severity, + message: `Requirement ${requirement.displayId}${requirement.title !== undefined ? ` ("${requirement.title}")` : ''} is not referenced by any task.`, + specName: context.specName, + requirementId: requirement.displayId, + file: filePath !== undefined ? { path: filePath, line: requirement.line + 1 } : null, + evidence: { + canonicalId: requirement.canonical, + criteria: catalog.entries + .filter( + (entry) => + entry.kind === 'criterion' && + entry.requirementCanonical === requirement.canonical, + ) + .map((entry) => entry.displayId), + }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV008 — Task has no requirement reference + * ------------------------------------------------------------------ */ + +const sbv008: SpecVerificationRule = { + id: 'SBV008', + title: 'Task has no requirement reference', + category: 'tasks', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'heuristic', + scope: 'spec', + triggeredWhen: + 'Requirement linking is in use in this tasks document, but a leaf implementation task carries no requirement reference. Clearly non-requirement work (documentation, release, cleanup chores) is excluded.', + resolution: + 'Add a _Requirements: …_ detail line to the task, or leave it unlinked deliberately if it is supporting work.', + evaluate(context, resolved) { + const model = context.spec.tasks; + if (model === undefined) return []; + const { references, catalog } = context.traceability; + if (references.length === 0 || catalog.requirements.length === 0) return []; + const tasksWithReferences = new Set(references.map((reference) => reference.taskId)); + + return model.allTasks + .filter( + (task) => + task.children.length === 0 && + !tasksWithReferences.has(task.id) && + !isLikelyNonRequirementTask(task), + ) + .map((task) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Task ${task.id} ("${task.title}") has no requirement reference while other tasks in this plan are linked.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { linkedTasks: tasksWithReferences.size, totalTasks: model.allTasks.length }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV009 — Task references unknown requirement + * ------------------------------------------------------------------ */ + +const sbv009: SpecVerificationRule = { + id: 'SBV009', + title: 'Task references unknown requirement', + category: 'tasks', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'A task references a requirement or acceptance-criterion ID that does not exist in the requirements document. References recognized only heuristically (keyword phrases) warn instead of erroring.', + resolution: + 'Fix the reference to point at an existing requirement ID, or add the missing requirement to requirements.md and re-approve it.', + evaluate(context, resolved) { + const { catalog, references } = context.traceability; + if (catalog.entries.length === 0) return []; + const filePath = tasksFilePath(context); + return references + .filter( + (reference) => + reference.canonical === undefined || !catalog.byCanonical.has(reference.canonical), + ) + .map((reference) => + makeDiagnostic({ + rule: this, + severity: reference.confidence === 'heuristic' ? 'warning' : resolved.severity, + message: `Task ${reference.taskId} references "${reference.raw}", which matches no requirement or acceptance criterion in requirements.md.`, + specName: context.specName, + taskId: reference.taskId, + requirementId: reference.raw, + file: filePath !== undefined ? { path: filePath, line: reference.line + 1 } : null, + evidence: { + reference: reference.raw, + canonical: reference.canonical ?? null, + method: reference.method, + knownIds: catalog.entries.slice(0, 20).map((entry) => entry.displayId), + }, + confidence: reference.confidence, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV010 — Completed parent task has incomplete child task + * ------------------------------------------------------------------ */ + +const sbv010: SpecVerificationRule = { + id: 'SBV010', + title: 'Completed parent task has incomplete child task', + category: 'tasks', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: 'A parent task checkbox is [x] while at least one of its subtasks is not.', + resolution: 'Finish (or uncheck) the open subtasks, or uncheck the parent task.', + evaluate(context, resolved) { + const model = context.spec.tasks; + if (model === undefined) return []; + const diagnostics: VerificationDiagnostic[] = []; + const openDescendants = (task: TaskItem): TaskItem[] => { + const open: TaskItem[] = []; + for (const child of task.children) { + if (child.state !== 'done') open.push(child); + open.push(...openDescendants(child)); + } + return open; + }; + for (const task of model.allTasks) { + if (task.children.length === 0 || task.state !== 'done') continue; + const open = openDescendants(task); + if (open.length === 0) continue; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Parent task ${task.id} is checked but ${open.length} of its subtasks ${open.length === 1 ? 'is' : 'are'} not complete (${open.map((child) => child.id).join(', ')}).`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { incompleteChildren: open.map((child) => child.id) }, + }), + ); + } + return diagnostics; + }, +}; + +/* ------------------------------------------------------------------ * + * SBV011 / SBV015 — evidence freshness rules + * ------------------------------------------------------------------ */ + +const SBV011_CODES: ReadonlySet = new Set([ + 'task-identity-changed', + 'task-missing', + 'history-diverged', + 'stage-not-approved', +]); +const SBV015_CODES: ReadonlySet = new Set([ + 'document-hash-changed', + 'design-hash-changed', + 'plan-hash-changed', + 'approved-after-evidence', +]); + +function staleEvidenceDiagnostics( + rule: SpecVerificationRule, + context: SpecVerificationContext, + resolved: ResolvedRuleConfig, + codes: ReadonlySet, +): VerificationDiagnostic[] { + const diagnostics: VerificationDiagnostic[] = []; + for (const task of doneLeafTasks(context)) { + const assessment = context.evidence.assessmentsByTask.get(task.id); + if (assessment === undefined || assessment.bucket !== 'stale') continue; + const best = assessment.best; + if (best === undefined) continue; + const matching = best.reasons.filter((reason) => codes.has(reason.code)); + if (matching.length === 0) continue; + diagnostics.push( + makeDiagnostic({ + rule, + severity: resolved.severity, + message: `Task ${task.id} is checked but its evidence is stale: ${matching.map((reason) => reason.message).join('; ')}.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { + runId: best.record.runId, + evidenceStatus: best.record.status, + manualAcceptance: best.manual, + reasons: matching.map((reason) => ({ code: reason.code, message: reason.message })), + evaluatedAt: best.record.evaluatedAt, + }, + }), + ); + } + return diagnostics; +} + +const sbv011: SpecVerificationRule = { + id: 'SBV011', + title: 'Task evidence is stale', + category: 'evidence', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'A checked task has evidence whose recorded task identity, commit lineage, or approval linkage no longer matches the repository (the task text changed, history diverged, or a referenced stage is no longer approved).', + resolution: + 'Re-run the task (specbridge spec run) or re-accept it (specbridge spec accept-task) so fresh evidence is recorded, or uncheck the box.', + evaluate(context, resolved) { + return staleEvidenceDiagnostics(this, context, resolved, SBV011_CODES); + }, +}; + +const sbv015: SpecVerificationRule = { + id: 'SBV015', + title: 'Spec changed after implementation evidence', + category: 'evidence', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'The requirements/bugfix document, design, or task plan changed (or was re-approved) after the evidence for a checked task was recorded — the implementation was verified against an older spec.', + resolution: + 'Re-run or re-accept the affected tasks against the current spec so the evidence describes what is approved now.', + evaluate(context, resolved) { + return staleEvidenceDiagnostics(this, context, resolved, SBV015_CODES); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV012 / SBV013 / SBV025 — verification command rules + * ------------------------------------------------------------------ */ + +const sbv012: GlobalVerificationRule = { + id: 'SBV012', + title: 'Required verification command failed', + category: 'verification-command', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'A trusted verification command required by a spec policy failed, could not start, or did not run in this verification with no reusable passing evidence.', + resolution: + 'Fix the failing command locally, or run the verification with --run-verification so a current result is produced.', + evaluate(context, resolved) { + const diagnostics: VerificationDiagnostic[] = []; + for (const command of context.commands.commands) { + if (!command.required || command.passed || command.timedOut) continue; + const specName = + command.requiredBySpecs.length === 1 ? (command.requiredBySpecs[0] ?? null) : null; + const message = + command.disposition === 'not-run' + ? `Required verification command "${command.name}" did not run in this verification and no current evidence covers it.` + : command.spawnFailed + ? `Required verification command "${command.name}" could not start (${command.result?.status ?? 'spawn failure'}).` + : `Required verification command "${command.name}" failed with exit code ${command.exitCode ?? 'unknown'}.`; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message, + specName, + evidence: { + command: command.name, + argv: command.argv, + disposition: command.disposition, + exitCode: command.exitCode, + spawnFailed: command.spawnFailed, + requiredBySpecs: command.requiredBySpecs, + stderrTail: command.result?.stderrTail.slice(-2000) ?? null, + }, + }), + ); + } + return diagnostics; + }, +}; + +const sbv013: GlobalVerificationRule = { + id: 'SBV013', + title: 'Required verification command missing', + category: 'verification-command', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'A spec policy requires a verification command by name, but no command with that name is configured in .specbridge/config.json.', + resolution: + 'Add the command to verification.commands in .specbridge/config.json (argv array form), or remove the name from the policy.', + evaluate(context, resolved) { + return context.commands.missingRequired.map(({ name, requiredBySpecs }) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Verification command "${name}" is required by ${requiredBySpecs.join(', ')} but is not configured in .specbridge/config.json.`, + specName: requiredBySpecs.length === 1 ? (requiredBySpecs[0] ?? null) : null, + evidence: { command: name, requiredBySpecs }, + }), + ); + }, +}; + +const sbv025: GlobalVerificationRule = { + id: 'SBV025', + title: 'Verification command timed out', + category: 'verification-command', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'A trusted verification command exceeded its configured timeout. Required commands error; optional commands warn.', + resolution: + 'Raise the command timeout in .specbridge/config.json, or make the command faster/scoped.', + evaluate(context, resolved) { + return context.commands.commands + .filter((command) => command.timedOut) + .map((command) => + makeDiagnostic({ + rule: this, + severity: command.required ? resolved.severity : 'warning', + message: `Verification command "${command.name}" timed out after ${command.durationMs ?? '?'} ms.`, + specName: + command.requiredBySpecs.length === 1 ? (command.requiredBySpecs[0] ?? null) : null, + evidence: { + command: command.name, + argv: command.argv, + required: command.required, + durationMs: command.durationMs, + }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV014 — Unmapped changed file + * ------------------------------------------------------------------ */ + +const sbv014: GlobalVerificationRule = { + id: 'SBV014', + title: 'Unmapped changed file', + category: 'mapping', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'In --changed or --all verification, a changed source or test file maps to no spec: no spec directory, impact area, task evidence, or design reference claims it.', + resolution: + 'Add the path to the owning spec’s impact areas, create a spec for the work, or accept unmapped changes by policy (rules.SBV014).', + evaluate(context, resolved) { + if (context.selection.mode === 'single') return []; + return context.unmappedFiles.map((file) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${file.path} does not map to any spec (no impact area, evidence, or spec reference claims it).`, + file: { path: file.path }, + evidence: { changedPath: file.path, changeType: file.changeType }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV016 — Task marked complete before task-plan approval + * ------------------------------------------------------------------ */ + +const sbv016: SpecVerificationRule = { + id: 'SBV016', + title: 'Task marked complete before task-plan approval', + category: 'approval', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'A managed spec has checked tasks while its task plan is not approved (never approved, or approval revoked). Unmanaged specs (no sidecar state) are not judged.', + resolution: + 'Approve the task plan first (specbridge spec approve --stage tasks), or uncheck the boxes.', + evaluate(context, resolved) { + const state = context.spec.state; + if (state === undefined || context.spec.tasks === undefined) return []; + const tasksStage = context.evaluation?.stages.find((stage) => stage.stage === 'tasks'); + if (tasksStage === undefined || tasksStage.stored.status === 'approved') return []; + return context.spec.tasks.allTasks + .filter((task) => task.state === 'done') + .map((task) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Task ${task.id} is checked but the task plan of "${context.specName}" has never been approved (status: ${tasksStage.stored.status}).`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { tasksStageStatus: tasksStage.stored.status }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV017 — No test evidence for test-required task + * ------------------------------------------------------------------ */ + +const sbv017: SpecVerificationRule = { + id: 'SBV017', + title: 'No test evidence for test-required task', + category: 'evidence', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'heuristic', + scope: 'spec', + triggeredWhen: + 'A checked task (or its referenced requirement) explicitly mentions tests, but its valid evidence contains neither a passing test command nor changed test files. Error severity when the policy sets requireTestEvidence. Test-language detection is heuristic.', + resolution: + 'Run the configured test command as part of the task (spec run records it), or record a manual acceptance explaining how the tests were covered.', + evaluate(context, resolved) { + const model = context.spec.tasks; + const tasksDocument = context.spec.documents.tasks; + if (model === undefined || tasksDocument === undefined) return []; + const severity = context.policy.requireTestEvidence ? 'error' : resolved.severity; + const { catalog, references } = context.traceability; + const diagnostics: VerificationDiagnostic[] = []; + + for (const task of doneLeafTasks(context)) { + const assessment = context.evidence.assessmentsByTask.get(task.id); + if (assessment === undefined || assessment.bucket !== 'valid') continue; // missing/stale covered elsewhere + + const taskWantsTests = taskMentionsTests(tasksDocument, model, task); + const requirementWantsTests = references.some((reference) => { + if (reference.taskId !== task.id || reference.canonical === undefined) return false; + const entry = catalog.byCanonical.get(reference.canonical); + if (entry === undefined) return false; + if (entry.testRequired) return true; + const requirement = catalog.byCanonical.get(entry.requirementCanonical); + return requirement?.testRequired === true; + }); + if (!taskWantsTests && !requirementWantsTests) continue; + + const record = assessment.best?.record; + if (record === undefined) continue; + const passingTestCommand = record.verificationCommands.some( + (command) => + command.passed && + (TEST_COMMAND_PATTERN.test(command.name) || + command.argv.some((argument) => TEST_COMMAND_PATTERN.test(argument))), + ); + const testFilesChanged = record.changedFiles.some((file) => + TEST_PATH_PATTERN.test(file.path), + ); + if (passingTestCommand || testFilesChanged) continue; + + diagnostics.push( + makeDiagnostic({ + rule: this, + severity, + message: `Task ${task.id} indicates tests (${taskWantsTests ? 'task text' : 'referenced requirement'}), but its evidence shows no passing test command and no changed test files.`, + specName: context.specName, + taskId: task.id, + file: taskFileLocation(context, task), + evidence: { + taskMentionsTests: taskWantsTests, + requirementMentionsTests: requirementWantsTests, + evidenceRunId: record.runId, + recordedCommands: record.verificationCommands.map((command) => command.name), + testEvidenceRequired: context.policy.requireTestEvidence, + }, + }), + ); + } + return diagnostics; + }, +}; + +/* ------------------------------------------------------------------ * + * SBV018 — Design path reference does not exist + * ------------------------------------------------------------------ */ + +const sbv018: SpecVerificationRule = { + id: 'SBV018', + title: 'Design path reference does not exist', + category: 'design', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'design.md explicitly references a repository path (in backticks or a Markdown link) that exists neither relative to the repository root nor relative to the spec folder. Glob patterns are not checked.', + resolution: + 'Fix the path in design.md, or delete the reference if the file was intentionally removed (then re-approve the design).', + evaluate(context, resolved) { + const designDocument = context.spec.documents.design; + if (designDocument === undefined) return []; + const designFile = designDocument.filePath; + const designRepoPath = + designFile !== undefined ? repoRelative(context.workspace, designFile) : undefined; + const specDir = path.join(context.workspace.rootDir, '.kiro', 'specs', context.specName); + + return context.traceability.designPathReferences + .filter((reference) => !reference.isGlob) + .filter((reference) => { + const fromRoot = path.join( + context.workspace.rootDir, + reference.path.split('/').join(path.sep), + ); + const fromSpecDir = path.join(specDir, reference.path.split('/').join(path.sep)); + return !existsSync(fromRoot) && !existsSync(fromSpecDir); + }) + .map((reference) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `design.md references \`${reference.raw}\`, which does not exist in the repository.`, + specName: context.specName, + file: + designRepoPath !== undefined + ? { path: designRepoPath, line: reference.line + 1 } + : null, + evidence: { referencedPath: reference.path, method: reference.method }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV019 — Changed file not represented in execution evidence + * ------------------------------------------------------------------ */ + +const sbv019: SpecVerificationRule = { + id: 'SBV019', + title: 'Changed file not represented in execution evidence', + category: 'evidence', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'The spec has valid task evidence, yet the comparison contains implementation files that no evidence record accounts for — work happened outside recorded task runs.', + resolution: + 'Run the remaining work as tasks (spec run records the files), or accept that untracked edits reduce evidence coverage.', + evaluate(context, resolved) { + const hasValidEvidence = [...context.evidence.assessmentsByTask.values()].some( + (assessment) => assessment.bucket === 'valid', + ); + if (!hasValidEvidence) return []; + + const evidencePaths = new Set(); + for (const assessment of context.evidence.assessmentsByTask.values()) { + for (const item of assessment.all) { + if (item.validity !== 'valid') continue; + for (const file of item.record.changedFiles) evidencePaths.add(file.path); + } + } + + const candidates = + context.selectionMode === 'single' ? context.changedFiles : context.specChangedFiles; + return candidates + .filter((file) => !isSpecInfraPath(file.path)) + .filter((file) => !evidencePaths.has(file.path)) + .map((file) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${file.path} changed but appears in no valid task evidence for ${context.specName}.`, + specName: context.specName, + file: { path: file.path }, + evidence: { changedPath: file.path, changeType: file.changeType }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV020 — Verification policy invalid + * ------------------------------------------------------------------ */ + +const sbv020: SpecVerificationRule = { + id: 'SBV020', + title: 'Verification policy invalid', + category: 'workspace', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'The spec’s verification policy file exists but is not valid JSON, does not match the versioned schema, or contains rejected glob patterns. Verification then runs with secure defaults.', + resolution: + 'Fix the policy file (specbridge spec policy validate pinpoints the problem), or delete it to use defaults.', + evaluate(context, resolved) { + return context.policy.policyDiagnostics.map((diagnostic) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: diagnostic.message, + specName: context.specName, + file: context.policy.policyPath !== undefined ? { path: context.policy.policyPath } : null, + evidence: { code: diagnostic.code }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV021 — Diff base unavailable + * ------------------------------------------------------------------ */ + +const sbv021: GlobalVerificationRule = { + id: 'SBV021', + title: 'Diff base unavailable', + category: 'git', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'The requested Git comparison cannot be resolved: a ref does not exist locally, no merge base exists, the clone is shallow, or the directory is not a git work tree.', + resolution: + 'Fetch the missing refs yourself (SpecBridge never fetches automatically). In GitHub Actions, check out with actions/checkout@v4 and fetch-depth: 0.', + evaluate(context, resolved) { + const failure = context.comparison.failure; + if (context.comparison.ok || failure === undefined) return []; + return [ + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: failure.message, + evidence: { + reason: failure.reason, + shallowClone: failure.shallow, + comparison: context.comparison.descriptor.label, + }, + }), + ]; + }, +}; + +/* ------------------------------------------------------------------ * + * SBV022 — Ambiguous affected-spec mapping + * ------------------------------------------------------------------ */ + +const sbv022: GlobalVerificationRule = { + id: 'SBV022', + title: 'Ambiguous affected-spec mapping', + category: 'mapping', + defaultSeverity: { advisory: 'warning', strict: 'warning' }, + confidence: 'deterministic', + scope: 'global', + triggeredWhen: + 'A changed file maps to more than one spec (overlapping impact areas or evidence). Every matching spec is verified; the overlap itself is reported.', + resolution: + 'Narrow the overlapping impact areas so each path has one owning spec, or accept the shared ownership deliberately.', + evaluate(context, resolved) { + return context.ambiguousFiles.map((entry) => + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `${entry.path} maps to ${entry.specs.length} specs: ${entry.specs + .map((spec) => `${spec.name} (via ${spec.via.join(', ')})`) + .join('; ')}.`, + file: { path: entry.path }, + evidence: { specs: entry.specs }, + }), + ); + }, +}; + +/* ------------------------------------------------------------------ * + * SBV023 — Tasks document unexpectedly changed + * ------------------------------------------------------------------ */ + +const sbv023: SpecVerificationRule = { + id: 'SBV023', + title: 'Tasks document unexpectedly changed', + category: 'tasks', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'The comparison modifies a managed spec’s tasks.md beyond checkbox transitions — task text, IDs, hierarchy, or references changed relative to the comparison base.', + resolution: + 'If the plan change is intentional, review and re-approve the task plan; otherwise revert the tasks.md edit.', + async evaluate(context, resolved) { + if (context.spec.state === undefined) return []; // unmanaged specs are not judged + if (!context.comparison.ok) return []; + const repoPath = `.kiro/specs/${context.specName}/tasks.md`; + const changed = context.changedFiles.find( + (file) => + file.path === repoPath && + (file.changeType === 'modified' || file.changeType === 'renamed'), + ); + if (changed === undefined) return []; + const currentDocument = context.spec.documents.tasks; + if (currentDocument === undefined) return []; + const baseContent = await context.readBaseContent(repoPath); + if (baseContent === undefined) return []; + const baseDocument = MarkdownDocument.fromText(baseContent); + if (normalizedTaskPlanText(baseDocument) === normalizedTaskPlanText(currentDocument)) { + return []; // checkbox-only progress — expected + } + return [ + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `tasks.md of "${context.specName}" changed beyond checkbox progress in this comparison (task text, IDs, hierarchy, or references differ from the base).`, + specName: context.specName, + file: { path: repoPath }, + evidence: { + comparison: context.comparison.descriptor.label, + changeType: changed.changeType, + }, + }), + ]; + }, +}; + +/* ------------------------------------------------------------------ * + * SBV024 — Evidence points outside repository + * ------------------------------------------------------------------ */ + +const sbv024: SpecVerificationRule = { + id: 'SBV024', + title: 'Evidence points outside repository', + category: 'evidence', + defaultSeverity: { advisory: 'error', strict: 'error' }, + confidence: 'deterministic', + scope: 'spec', + triggeredWhen: + 'An evidence record lists changed-file paths that escape the repository (absolute paths or .. traversal). Such records are never trusted.', + resolution: + 'Delete or regenerate the corrupt evidence record; evidence must only reference repository-relative paths.', + evaluate(context, resolved) { + const diagnostics: VerificationDiagnostic[] = []; + for (const [taskId, assessment] of context.evidence.assessmentsByTask) { + for (const item of assessment.all) { + if (item.pathViolations.length === 0) continue; + diagnostics.push( + makeDiagnostic({ + rule: this, + severity: resolved.severity, + message: `Evidence record ${item.record.runId} for task ${taskId} references paths outside the repository: ${item.pathViolations.join(', ')}.`, + specName: context.specName, + taskId, + evidence: { runId: item.record.runId, paths: item.pathViolations }, + }), + ); + } + } + return diagnostics; + }, +}; + +/* ------------------------------------------------------------------ * + * Registry + * ------------------------------------------------------------------ */ + +/** + * Every built-in rule in ID order. This list is the registry: tests assert + * the IDs are unique, contiguous where documented, and stable. + */ +export function builtInVerificationRules(): readonly VerificationRule[] { + return [ + sbv001, + sbv002, + sbv003, + sbv004, + sbv005, + sbv006, + sbv007, + sbv008, + sbv009, + sbv010, + sbv011, + sbv012, + sbv013, + sbv014, + sbv015, + sbv016, + sbv017, + sbv018, + sbv019, + sbv020, + sbv021, + sbv022, + sbv023, + sbv024, + sbv025, + ]; +} + +export function findRule(ruleId: string): VerificationRule | undefined { + return builtInVerificationRules().find((rule) => rule.id === ruleId.toUpperCase()); +} diff --git a/packages/drift/src/verification/verify.ts b/packages/drift/src/verification/verify.ts new file mode 100644 index 0000000..9a74ac6 --- /dev/null +++ b/packages/drift/src/verification/verify.ts @@ -0,0 +1,412 @@ +import { randomUUID } from 'node:crypto'; +import path from 'node:path'; +import { discoverSpecs, requireSpec } from '@specbridge/compat-kiro'; +import type { + FailOnThreshold, + ReportChangedFile, + SelectionMode, + SpecEvidenceSummary, + SpecTraceabilitySummary, + SpecVerificationResult, + VerificationCommandReport, + VerificationDiagnostic, + VerificationReport, + WorkspaceInfo, +} from '@specbridge/core'; +import { + SpecBridgeError, + VERIFICATION_REPORT_SCHEMA_VERSION, + countDiagnostics, + reachesFailureThreshold, + readAgentConfig, + sortVerificationDiagnostics, + verificationReportSchema, + writeFileAtomic, +} from '@specbridge/core'; +import type { EvidenceAssessment } from '@specbridge/evidence'; +import type { AffectedSpecsResult } from './affected.js'; +import { resolveAffectedSpecs } from './affected.js'; +import type { OrchestratedCommands } from './commands.js'; +import { orchestrateVerificationCommands } from './commands.js'; +import type { ComparisonChangedFile, ComparisonRequest, ResolvedComparison } from './comparison.js'; +import { resolveComparison } from './comparison.js'; +import type { GlobalVerificationContext, SpecVerificationContext } from './context.js'; +import { buildSpecVerificationContext, createRunCaches } from './context.js'; +import { evaluateGlobalRules, evaluateSpecRules } from './rule-engine.js'; +import { builtInVerificationRules } from './rules.js'; + +/** + * Verification orchestration: resolve the comparison, select specs, build + * contexts (each spec parsed once), orchestrate trusted commands, evaluate + * the rule engine, and assemble a schema-validated report. + * + * Read-only guarantee: the only writes this module ever performs are + * verification artifacts (command logs and report.json) under the caller's + * reports directory — and only when commands actually execute. Spec content, + * approval state, task state, and evidence are never touched. + */ + +export type VerifySelection = + | { mode: 'single'; spec: string } + | { mode: 'changed' } + | { mode: 'all' }; + +export interface VerifySpecsRequest { + workspace: WorkspaceInfo; + selection: VerifySelection; + comparison: ComparisonRequest; + /** CLI tri-state: true = run all configured, false = never run, undefined = auto. */ + runVerification?: boolean; + strict?: boolean; + failOn: FailOnThreshold; + explicitPolicyPath?: string; + toolVersion: string; + /** + * Absolute directory for verification artifacts. `//` + * is created only when trusted commands execute (command logs plus + * report.json); a run without command execution writes nothing. + */ + reportsDir?: string; + clock?: () => Date; + idFactory?: () => string; + signal?: AbortSignal; + onProgress?: (message: string) => void; +} + +export interface VerifySpecsResult { + report: VerificationReport; + exitCode: number; + /** Created artifacts directory, when commands executed. */ + artifactsDir?: string; +} + +/** Exit codes for `spec verify` (documented in docs/ci-quality-gates.md). */ +export const VERIFY_EXIT_CODES = { + passed: 0, + thresholdReached: 1, + invalidInput: 2, + comparisonUnavailable: 3, + commandFailedToStart: 4, + commandTimeout: 5, +} as const; + +export async function verifySpecs(request: VerifySpecsRequest): Promise { + const now = (request.clock ?? ((): Date => new Date()))(); + const verificationId = (request.idFactory ?? randomUUID)(); + const workspace = request.workspace; + + const configRead = readAgentConfig(workspace); + if (configRead.config === undefined) { + // Fail-closed: an invalid trusted-command configuration is a setup error. + throw new SpecBridgeError( + 'INVALID_STATE', + `Cannot verify: ${configRead.diagnostics.map((diagnostic) => diagnostic.message).join('; ')}`, + ); + } + const config = configRead.config; + + request.onProgress?.(`Resolving comparison (${describeComparison(request.comparison)})…`); + const comparison = await resolveComparison(workspace.rootDir, request.comparison, { + ...(request.signal !== undefined ? { signal: request.signal } : {}), + }); + + // ---- Spec selection ------------------------------------------------------- + const caches = createRunCaches(); + const selectionMode: SelectionMode = request.selection.mode; + let affectedResult: AffectedSpecsResult = { affected: [], unmapped: [], ambiguous: [] }; + const specContexts: SpecVerificationContext[] = []; + + if (comparison.ok) { + if (selectionMode !== 'single') { + affectedResult = resolveAffectedSpecs(workspace, comparison.changedFiles, { + ...(request.strict !== undefined ? { strict: request.strict } : {}), + }); + } + + const selectedFolders = + request.selection.mode === 'single' + ? [requireSpec(workspace, request.selection.spec)] + : request.selection.mode === 'all' + ? discoverSpecs(workspace) + : discoverSpecs(workspace).filter((folder) => + affectedResult.affected.some((spec) => spec.specName === folder.name), + ); + + for (const folder of selectedFolders) { + request.onProgress?.(`Analyzing spec ${folder.name}…`); + const matchedBy = affectedResult.affected + .find((spec) => spec.specName === folder.name) + ?.matches.flatMap((match) => match.via.map((via) => `${via}: ${match.file}`)); + specContexts.push( + await buildSpecVerificationContext({ + workspace, + folder, + config, + comparison, + selectionMode, + caches, + ...(request.strict !== undefined ? { strict: request.strict } : {}), + ...(request.explicitPolicyPath !== undefined + ? { explicitPolicyPath: request.explicitPolicyPath } + : {}), + ...(matchedBy !== undefined ? { matchedBy: dedupe(matchedBy) } : {}), + now, + ...(request.signal !== undefined ? { signal: request.signal } : {}), + }), + ); + } + } + + // ---- Trusted verification commands --------------------------------------- + let artifactsDir: string | undefined; + const ensureArtifactsDir = (): string => { + if (artifactsDir === undefined) { + const base = request.reportsDir ?? path.join(workspace.sidecarDir, 'reports'); + artifactsDir = path.join(base, verificationId); + } + return artifactsDir; + }; + + const requiredBySpec = new Map(); + const evidenceBySpec = new Map(); + for (const context of specContexts) { + requiredBySpec.set(context.specName, context.policy.requiredVerificationCommands); + evidenceBySpec.set(context.specName, context.evidence.flattened); + } + + const commands: OrchestratedCommands = comparison.ok + ? await orchestrateVerificationCommands({ + config, + requiredBySpec, + runVerification: request.runVerification, + workspaceRoot: workspace.rootDir, + ...(comparison.descriptor.headSha !== null + ? { headSha: comparison.descriptor.headSha } + : {}), + evidenceBySpec, + ...(request.signal !== undefined ? { signal: request.signal } : {}), + ...(request.onProgress !== undefined ? { onProgress: request.onProgress } : {}), + onCommandFinished: (result, stdout, stderr) => { + const dir = ensureArtifactsDir(); + const safeName = result.name.replace(/[^A-Za-z0-9._-]+/g, '-'); + writeFileAtomic(path.join(dir, 'commands', `${safeName}.stdout.log`), stdout); + writeFileAtomic(path.join(dir, 'commands', `${safeName}.stderr.log`), stderr); + }, + }) + : { mode: 'none', commands: [], missingRequired: [] }; + + // ---- Rule evaluation ------------------------------------------------------ + const rules = builtInVerificationRules(); + const diagnosticsBySpec = new Map(); + for (const context of specContexts) { + const { diagnostics } = await evaluateSpecRules(rules, context); + diagnosticsBySpec.set(context.specName, diagnostics); + } + + const globalContext: GlobalVerificationContext = { + workspace, + comparison, + selection: { mode: selectionMode }, + specContexts, + unmappedFiles: affectedResult.unmapped, + ambiguousFiles: affectedResult.ambiguous, + commands, + now, + }; + const globalResult = await evaluateGlobalRules(rules, globalContext); + + // Global-rule diagnostics that name a selected spec are reported with it. + const selectedNames = new Set(specContexts.map((context) => context.specName)); + const globalDiagnostics: VerificationDiagnostic[] = []; + for (const diagnostic of globalResult.diagnostics) { + if (diagnostic.specName !== null && selectedNames.has(diagnostic.specName)) { + diagnosticsBySpec.get(diagnostic.specName)?.push(diagnostic); + } else { + globalDiagnostics.push(diagnostic); + } + } + + // ---- Report assembly ------------------------------------------------------ + const specResults: SpecVerificationResult[] = specContexts.map((context) => { + const diagnostics = sortVerificationDiagnostics(diagnosticsBySpec.get(context.specName) ?? []); + const counts = countDiagnostics(diagnostics); + const files = selectionMode === 'single' ? context.changedFiles : context.specChangedFiles; + return { + specName: context.specName, + specType: context.spec.state?.specType ?? context.spec.classification.type, + workflowMode: context.spec.state?.workflowMode ?? 'unknown', + managed: context.spec.state !== undefined, + result: reachesFailureThreshold(counts, request.failOn) ? 'failed' : 'passed', + policyMode: context.policy.mode, + policyPath: context.policy.policyExists ? (context.policy.policyPath ?? null) : null, + matchedBy: context.matchedBy, + changedFiles: files.map(toReportChangedFile), + traceability: traceabilitySummary(context), + evidence: evidenceSummary(context), + diagnostics, + }; + }); + + const sortedGlobal = sortVerificationDiagnostics(globalDiagnostics); + const allDiagnostics = [...sortedGlobal, ...specResults.flatMap((spec) => spec.diagnostics)]; + const totals = countDiagnostics(allDiagnostics); + const failed = reachesFailureThreshold(totals, request.failOn); + + const report: VerificationReport = { + schemaVersion: VERIFICATION_REPORT_SCHEMA_VERSION, + tool: { name: 'specbridge', version: request.toolVersion }, + verificationId, + createdAt: now.toISOString(), + comparison: comparison.descriptor, + selection: { + mode: selectionMode, + specs: specContexts.map((context) => context.specName), + }, + summary: { + result: failed || !comparison.ok ? 'failed' : 'passed', + specsVerified: specContexts.length, + errors: totals.errors, + warnings: totals.warnings, + info: totals.info, + }, + specResults, + globalDiagnostics: sortedGlobal, + verificationCommands: commands.commands.map(toCommandReport), + }; + + // Never emit an invalid report — validate before anything leaves this module. + verificationReportSchema.parse(report); + + if (artifactsDir !== undefined) { + writeFileAtomic( + path.join(artifactsDir, 'report.json'), + `${JSON.stringify(report, null, 2)}\n`, + ); + } + + return { + report, + exitCode: resolveExitCode(report, comparison, commands, request.failOn), + ...(artifactsDir !== undefined ? { artifactsDir } : {}), + }; +} + +function describeComparison(request: ComparisonRequest): string { + if (request.mode === 'diff') return `${request.base}...${request.head}`; + return request.mode; +} + +function dedupe(values: string[]): string[] { + return [...new Set(values)]; +} + +function toReportChangedFile(file: ComparisonChangedFile): ReportChangedFile { + return { + path: file.path, + oldPath: file.oldPath ?? null, + changeType: file.changeType, + binary: file.binary, + insertions: file.insertions ?? null, + deletions: file.deletions ?? null, + }; +} + +function toCommandReport( + command: OrchestratedCommands['commands'][number], +): VerificationCommandReport { + return { + name: command.name, + argv: command.argv, + required: command.required, + disposition: command.disposition, + exitCode: command.exitCode, + durationMs: command.durationMs, + timedOut: command.timedOut, + passed: command.passed, + requiredBySpecs: command.requiredBySpecs, + }; +} + +function traceabilitySummary(context: SpecVerificationContext): SpecTraceabilitySummary { + const { catalog, references } = context.traceability; + const referenced = new Set( + references + .map((reference) => reference.canonical) + .filter((canonical): canonical is string => canonical !== undefined), + ); + let requirementsWithTasks = 0; + for (const requirement of catalog.requirements) { + let covered = false; + for (const canonical of referenced) { + if ( + canonical === requirement.canonical || + catalog.byCanonical.get(canonical)?.requirementCanonical === requirement.canonical + ) { + covered = true; + break; + } + } + if (covered) requirementsWithTasks += 1; + } + const tasks = context.spec.tasks?.allTasks ?? []; + const tasksWithReferences = new Set(references.map((reference) => reference.taskId)); + return { + requirements: catalog.requirements.length, + requirementsWithTasks, + tasks: tasks.length, + tasksWithRequirements: tasks.filter((task) => tasksWithReferences.has(task.id)).length, + }; +} + +function evidenceSummary(context: SpecVerificationContext): SpecEvidenceSummary { + const summary = { valid: 0, stale: 0, missing: 0, invalid: 0, manuallyAccepted: 0 }; + const model = context.spec.tasks; + if (model === undefined) return summary; + for (const task of model.allTasks) { + if (task.children.length > 0 || task.state !== 'done') continue; + const assessment = context.evidence.assessmentsByTask.get(task.id); + if (assessment === undefined || assessment.bucket === 'missing') { + summary.missing += 1; + } else if (assessment.bucket === 'valid') { + summary.valid += 1; + if (assessment.best?.manual === true) summary.manuallyAccepted += 1; + } else if (assessment.bucket === 'stale') { + summary.stale += 1; + } else { + summary.invalid += 1; + } + } + summary.invalid += context.evidence.invalidRecordCount; + return summary; +} + +function resolveExitCode( + report: VerificationReport, + comparison: ResolvedComparison, + commands: OrchestratedCommands, + failOn: FailOnThreshold, +): number { + if (!comparison.ok) return VERIFY_EXIT_CODES.comparisonUnavailable; + + const allDiagnostics = [ + ...report.globalDiagnostics, + ...report.specResults.flatMap((spec) => spec.diagnostics), + ]; + // An invalid policy is a setup error (exit 2), not a mere finding. + if (allDiagnostics.some((diagnostic) => diagnostic.ruleId === 'SBV020')) { + return VERIFY_EXIT_CODES.invalidInput; + } + const requiredSpawnFailed = commands.commands.some( + (command) => command.required && command.spawnFailed, + ); + if (requiredSpawnFailed) return VERIFY_EXIT_CODES.commandFailedToStart; + const requiredTimedOut = commands.commands.some( + (command) => command.required && command.timedOut, + ); + if (requiredTimedOut) return VERIFY_EXIT_CODES.commandTimeout; + + const counts = countDiagnostics(allDiagnostics); + return reachesFailureThreshold(counts, failOn) + ? VERIFY_EXIT_CODES.thresholdReached + : VERIFY_EXIT_CODES.passed; +} diff --git a/packages/evidence/package.json b/packages/evidence/package.json index e4e4da4..b6cafad 100644 --- a/packages/evidence/package.json +++ b/packages/evidence/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/evidence", - "version": "0.3.0", + "version": "0.4.0", "description": "Git snapshots, trusted verification commands, and append-only task evidence for SpecBridge.", "license": "MIT", "type": "module", diff --git a/packages/evidence/src/evidence-store.ts b/packages/evidence/src/evidence-store.ts index 9b79a04..e08a238 100644 --- a/packages/evidence/src/evidence-store.ts +++ b/packages/evidence/src/evidence-store.ts @@ -45,6 +45,31 @@ export const manualAcceptanceSchema = z.object({ referencedRunId: z.string().optional(), }); +const SHA256_HEX = /^[0-9a-f]{64}$/; + +/** + * Spec-and-task identity captured when the evidence was recorded (added in + * v0.4; optional so every v0.3 record keeps validating). Verification uses + * these fields to decide deterministically whether evidence is still fresh: + * a changed approved hash, plan hash, or task fingerprint means the evidence + * no longer describes the current spec. + */ +export const evidenceSpecContextSchema = z + .object({ + /** Approved exact-byte hash of requirements.md/bugfix.md at evidence time. */ + documentHash: z.string().regex(SHA256_HEX).optional(), + /** Approved exact-byte hash of design.md at evidence time. */ + designHash: z.string().regex(SHA256_HEX).optional(), + /** Checkbox-normalized plan hash of tasks.md at evidence time. */ + tasksPlanHash: z.string().regex(SHA256_HEX).optional(), + /** Fingerprint of the task's id, title, and requirement refs. */ + taskFingerprint: z.string().regex(SHA256_HEX).optional(), + /** Raw checkbox line text of the task at evidence time. */ + taskText: z.string().optional(), + }) + .passthrough(); +export type EvidenceSpecContext = z.infer; + export const taskEvidenceRecordSchema = z .object({ schemaVersion: z.string().regex(/^\d+\.\d+\.\d+$/), @@ -76,6 +101,7 @@ export const taskEvidenceRecordSchema = z warnings: z.array(z.string()), evaluatedAt: z.string(), manualAcceptance: manualAcceptanceSchema.optional(), + specContext: evidenceSpecContextSchema.optional(), }) .passthrough(); diff --git a/packages/evidence/src/freshness.ts b/packages/evidence/src/freshness.ts new file mode 100644 index 0000000..23f4b24 --- /dev/null +++ b/packages/evidence/src/freshness.ts @@ -0,0 +1,380 @@ +import path from 'node:path'; +import { runSafeProcess } from '@specbridge/runners'; +import type { TaskEvidenceRecord } from './evidence-store.js'; + +/** + * Evidence freshness validation. + * + * v0.3 evidence proves what happened at the moment it was recorded. Whether + * it still describes the repository *now* is decided here, deterministically: + * + * - the spec name and task identity must still match + * - recorded approved-content hashes must match the currently approved + * content (checkbox-normalized for the task plan) + * - recorded repository paths must stay inside the repository + * - for records that predate the v0.4 `specContext` fields, recorded + * approval timestamps are compared instead: a stage (re)approved after + * the evidence was evaluated invalidates it + * + * Model claims inside a record (`runnerClaims`) are never consulted — they + * are audit data, not evidence. + */ + +export type EvidenceValidity = 'valid' | 'stale' | 'invalid' | 'not-accepted'; + +/** Machine-readable causes; rules map these to stable diagnostics. */ +export type EvidenceReasonCode = + | 'spec-name-mismatch' + | 'paths-outside-repository' + | 'timestamp-unparseable' + | 'manual-record-malformed' + | 'task-missing' + | 'task-identity-changed' + | 'document-hash-changed' + | 'design-hash-changed' + | 'plan-hash-changed' + | 'stage-not-approved' + | 'approved-after-evidence' + | 'history-diverged'; + +export interface EvidenceReason { + code: EvidenceReasonCode; + message: string; +} + +export interface EvidenceAssessment { + record: TaskEvidenceRecord; + /** Whether the record's status can complete a task at all. */ + accepted: boolean; + manual: boolean; + validity: EvidenceValidity; + /** Why the record is stale or invalid (empty for valid records). */ + reasons: EvidenceReason[]; + /** Non-fatal observations (unknown commit lineage, clock skew). */ + notes: string[]; + /** Recorded changed-file paths that escape the repository (SBV024). */ + pathViolations: string[]; +} + +export interface CurrentTaskIdentity { + fingerprint: string; + title: string; + /** Raw checkbox line text as it appears in tasks.md right now. */ + rawLineText: string; + state: string; +} + +export interface EvidenceFreshnessContext { + specName: string; + /** + * Currently approved content identity. A field is undefined when the stage + * is not effectively approved right now — evidence that recorded a hash + * for it can no longer be validated and reads as stale. + */ + approved: { + documentHash?: string; + designHash?: string; + /** Plan hash of the currently approved task plan. */ + tasksPlanHash?: string; + }; + /** Recorded approval timestamps (ISO), for records without specContext. */ + approvedAt: { + document?: string; + design?: string; + tasks?: string; + }; + /** Current tasks by id. */ + tasks: Map; + /** Commit ancestry of recorded `headAfter` SHAs relative to current HEAD. */ + ancestry?: Map; + now: Date; +} + +const ACCEPTED_STATUSES = new Set(['verified', 'manually-accepted']); +const FUTURE_SKEW_TOLERANCE_MS = 5 * 60 * 1000; + +/** Repo-relative path check for recorded evidence paths. */ +export function evidencePathEscapesRepository(recordedPath: string): boolean { + if (recordedPath.includes('\0')) return true; + if (path.isAbsolute(recordedPath) || /^[A-Za-z]:/.test(recordedPath)) return true; + return recordedPath.split(/[\\/]/).includes('..'); +} + +const CHECKBOX_STATE_PREFIX = /^([ \t]*[-*+][ \t]+\[)([ xX~-])(\])/; + +/** Compare two checkbox lines ignoring only the state character. */ +function sameTaskLineIgnoringState(a: string, b: string): boolean { + const normalize = (text: string): string => { + const match = CHECKBOX_STATE_PREFIX.exec(text); + if (match === null || match[1] === undefined || match[3] === undefined) return text; + return `${match[1]} ${match[3]}${text.slice(match[0].length)}`; + }; + return normalize(a) === normalize(b); +} + +function parseTimestamp(value: string): number | undefined { + const parsed = Date.parse(value); + return Number.isNaN(parsed) ? undefined : parsed; +} + +/** Assess one evidence record against the current verification context. */ +export function assessEvidenceRecord( + record: TaskEvidenceRecord, + context: EvidenceFreshnessContext, +): EvidenceAssessment { + const reasons: EvidenceReason[] = []; + const notes: string[] = []; + const pathViolations: string[] = []; + const accepted = ACCEPTED_STATUSES.has(record.status); + const manual = record.status === 'manually-accepted'; + + // Structural identity and path safety are checked for every record. + if (record.specName !== context.specName) { + reasons.push({ + code: 'spec-name-mismatch', + message: `the record names spec "${record.specName}" but was read for "${context.specName}"`, + }); + } + for (const file of record.changedFiles) { + if (evidencePathEscapesRepository(file.path)) pathViolations.push(file.path); + } + if (pathViolations.length > 0) { + reasons.push({ + code: 'paths-outside-repository', + message: `recorded changed-file paths escape the repository: ${pathViolations.join(', ')}`, + }); + } + const evaluatedAtMs = parseTimestamp(record.evaluatedAt); + if (evaluatedAtMs === undefined) { + reasons.push({ + code: 'timestamp-unparseable', + message: `evaluatedAt "${record.evaluatedAt}" is not a parseable timestamp`, + }); + } else if (evaluatedAtMs > context.now.getTime() + FUTURE_SKEW_TOLERANCE_MS) { + notes.push('the record timestamp lies in the future relative to this machine (clock skew?)'); + } + if (manual && record.manualAcceptance === undefined) { + reasons.push({ + code: 'manual-record-malformed', + message: 'status is manually-accepted but no manualAcceptance block is recorded', + }); + } + + if (reasons.length > 0) { + return { record, accepted, manual, validity: 'invalid', reasons, notes, pathViolations }; + } + + if (!accepted) { + return { record, accepted, manual, validity: 'not-accepted', reasons, notes, pathViolations }; + } + + // ---- Freshness (only meaningful for accepted records) ------------------- + const stale: EvidenceReason[] = []; + + const currentTask = context.tasks.get(record.taskId); + if (currentTask === undefined) { + stale.push({ + code: 'task-missing', + message: `task ${record.taskId} no longer exists in tasks.md`, + }); + } else if (record.specContext?.taskFingerprint !== undefined) { + if (record.specContext.taskFingerprint !== currentTask.fingerprint) { + stale.push({ + code: 'task-identity-changed', + message: + "the task's text, numbering, or requirement references changed since the evidence was recorded", + }); + } + } else if (record.specContext?.taskText !== undefined) { + if (!sameTaskLineIgnoringState(record.specContext.taskText, currentTask.rawLineText)) { + stale.push({ + code: 'task-identity-changed', + message: 'the task line text changed since the evidence was recorded', + }); + } + } + + const specContext = record.specContext; + if (specContext !== undefined) { + const hashChecks: { + recorded: string | undefined; + current: string | undefined; + code: EvidenceReasonCode; + what: string; + }[] = [ + { + recorded: specContext.documentHash, + current: context.approved.documentHash, + code: 'document-hash-changed', + what: 'the approved requirements/bugfix document', + }, + { + recorded: specContext.designHash, + current: context.approved.designHash, + code: 'design-hash-changed', + what: 'the approved design', + }, + { + recorded: specContext.tasksPlanHash, + current: context.approved.tasksPlanHash, + code: 'plan-hash-changed', + what: 'the approved task plan', + }, + ]; + for (const { recorded, current, code, what } of hashChecks) { + if (recorded === undefined) continue; + if (current === undefined) { + stale.push({ + code: 'stage-not-approved', + message: `${what} is no longer effectively approved`, + }); + } else if (recorded !== current) { + stale.push({ code, message: `${what} changed since the evidence was recorded` }); + } + } + } else { + // Legacy record (v0.3): compare recorded approval timestamps instead. + // A stage approved AFTER the evidence was evaluated means the spec the + // evidence verified is not the spec that is approved now. + const referenceMs = + record.manualAcceptance !== undefined + ? (parseTimestamp(record.manualAcceptance.acceptedAt) ?? evaluatedAtMs) + : evaluatedAtMs; + const timestampChecks: [string | undefined, string][] = [ + [context.approvedAt.document, 'requirements/bugfix'], + [context.approvedAt.design, 'design'], + [context.approvedAt.tasks, 'tasks'], + ]; + for (const [approvedAt, stage] of timestampChecks) { + if (approvedAt === undefined || referenceMs === undefined) continue; + const approvedMs = parseTimestamp(approvedAt); + if (approvedMs !== undefined && approvedMs > referenceMs) { + stale.push({ + code: 'approved-after-evidence', + message: `the ${stage} stage was (re)approved after this evidence was recorded`, + }); + } + } + } + + const headAfter = record.repository.headAfter; + if (headAfter !== undefined && context.ancestry !== undefined) { + const ancestry = context.ancestry.get(headAfter); + if (ancestry === 'not-ancestor') { + stale.push({ + code: 'history-diverged', + message: `the recorded commit ${headAfter.slice(0, 12)} is not an ancestor of the current HEAD (history diverged)`, + }); + } else if (ancestry === 'unknown') { + notes.push( + `the recorded commit ${headAfter.slice(0, 12)} cannot be resolved in this clone (shallow history?)`, + ); + } + } + + return { + record, + accepted, + manual, + validity: stale.length > 0 ? 'stale' : 'valid', + reasons: stale, + notes, + pathViolations, + }; +} + +export interface TaskEvidenceAssessment { + taskId: string; + /** Assessment of the newest accepted record, when one exists. */ + best?: EvidenceAssessment; + all: EvidenceAssessment[]; + /** Summary bucket for reports. `valid` includes manual acceptance. */ + bucket: 'valid' | 'stale' | 'invalid' | 'missing'; +} + +/** + * Assess all records of one task (records ordered oldest-first, as returned + * by the evidence store). The newest accepted record decides the bucket. + */ +export function assessTaskEvidence( + taskId: string, + records: readonly TaskEvidenceRecord[], + context: EvidenceFreshnessContext, +): TaskEvidenceAssessment { + const all = records.map((record) => assessEvidenceRecord(record, context)); + const acceptedAssessments = all.filter((assessment) => assessment.accepted); + const best = acceptedAssessments[acceptedAssessments.length - 1]; + if (best === undefined) { + return { taskId, all, bucket: 'missing' }; + } + const bucket = + best.validity === 'valid' ? 'valid' : best.validity === 'stale' ? 'stale' : 'invalid'; + return { taskId, best, all, bucket }; +} + +export type CommitAncestry = 'ancestor' | 'not-ancestor' | 'unknown'; + +const GIT_TIMEOUT_MS = 30_000; +const SHA_PATTERN = /^[0-9a-f]{4,64}$/i; + +/** + * Resolve whether each recorded commit is an ancestor of the current HEAD. + * Read-only `git merge-base --is-ancestor` per unique SHA; unresolvable SHAs + * (shallow clones, garbage-collected history) come back as `unknown`. + */ +export async function resolveCommitAncestry( + workspaceRoot: string, + shas: readonly string[], + signal?: AbortSignal, +): Promise> { + const result = new Map(); + for (const sha of new Set(shas)) { + if (!SHA_PATTERN.test(sha)) { + result.set(sha, 'unknown'); + continue; + } + const processResult = await runSafeProcess({ + executable: 'git', + argv: ['merge-base', '--is-ancestor', sha, 'HEAD'], + cwd: workspaceRoot, + timeoutMs: GIT_TIMEOUT_MS, + ...(signal !== undefined ? { signal } : {}), + }); + if (processResult.status === 'ok') { + result.set(sha, 'ancestor'); + } else if ( + processResult.status === 'nonzero-exit' && + processResult.observation.exitCode === 1 + ) { + result.set(sha, 'not-ancestor'); + } else { + result.set(sha, 'unknown'); + } + } + return result; +} + +/** + * True when a passing result for the named trusted command can be reused + * from evidence instead of re-running it: the assessment must be valid, the + * command must have passed, and the recorded repository state must be the + * exact current HEAD (anything newer could have broken it). + */ +export function reusableCommandPass( + assessments: readonly EvidenceAssessment[], + commandName: string, + currentHeadSha: string | undefined, +): TaskEvidenceRecord | undefined { + if (currentHeadSha === undefined) return undefined; + for (let i = assessments.length - 1; i >= 0; i -= 1) { + const assessment = assessments[i]; + if (assessment === undefined || assessment.validity !== 'valid') continue; + const { record } = assessment; + if (record.repository.headAfter !== currentHeadSha) continue; + const command = record.verificationCommands.find( + (candidate) => candidate.name === commandName && candidate.passed, + ); + if (command !== undefined) return record; + } + return undefined; +} diff --git a/packages/evidence/src/index.ts b/packages/evidence/src/index.ts index 4393c80..e04cde9 100644 --- a/packages/evidence/src/index.ts +++ b/packages/evidence/src/index.ts @@ -3,3 +3,4 @@ export * from './changed-files.js'; export * from './verification.js'; export * from './evidence-store.js'; export * from './evaluate.js'; +export * from './freshness.js'; diff --git a/packages/execution/package.json b/packages/execution/package.json index b92673a..fca4286 100644 --- a/packages/execution/package.json +++ b/packages/execution/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/execution", - "version": "0.3.0", + "version": "0.4.0", "description": "Task selection, bounded task context, runner orchestration, run records, and session resume for SpecBridge.", "license": "MIT", "type": "module", diff --git a/packages/execution/src/complete-task.ts b/packages/execution/src/complete-task.ts index 2949827..91d81fc 100644 --- a/packages/execution/src/complete-task.ts +++ b/packages/execution/src/complete-task.ts @@ -1,6 +1,18 @@ -import { MarkdownDocument, applyCheckboxState, writeDocumentAtomic } from '@specbridge/compat-kiro'; +import { + MarkdownDocument, + applyCheckboxState, + taskPlanHash, + writeDocumentAtomic, +} from '@specbridge/compat-kiro'; import type { StageName, WorkspaceInfo } from '@specbridge/core'; -import { SpecBridgeError, readSpecState, sha256File, stateStage, writeSpecState } from '@specbridge/core'; +import { + SpecBridgeError, + TASK_PLAN_HASH_SEMANTICS_VERSION, + readSpecState, + sha256File, + stateStage, + writeSpecState, +} from '@specbridge/core'; import type { Clock } from '@specbridge/workflow'; import { isoNow } from '@specbridge/workflow'; import { stageDocumentPath } from './write-stage.js'; @@ -75,6 +87,9 @@ export function completeTaskCheckbox( const after = document.lineAt(expected.line).text; // Re-record the tasks approval hash for SpecBridge's own sanctioned edit. + // The checkbox-normalized plan hash (semantics v2) is recorded alongside — + // a checkbox flip cannot change it, so this also migrates pre-v0.4 state + // that only stored the exact byte hash. let approvalRehashed = false; let newHash: string | undefined; const stateRead = readSpecState(workspace, specName); @@ -82,11 +97,19 @@ export function completeTaskCheckbox( const tasksStage = stateStage(stateRead.state, 'tasks'); if (tasksStage !== undefined && tasksStage.status === 'approved') { newHash = sha256File(filePath); + const planHash = taskPlanHash(MarkdownDocument.load(filePath)); const nextState = { ...stateRead.state, stages: { ...stateRead.state.stages, - tasks: { ...tasksStage, approvedHash: newHash, approvedAt: isoNow(clock) }, + tasks: { + ...tasksStage, + approvedHash: newHash, + approvedAt: isoNow(clock), + approvedPlanHash: planHash, + hashAlgorithm: 'sha256' as const, + hashSemanticsVersion: TASK_PLAN_HASH_SEMANTICS_VERSION, + }, }, updatedAt: isoNow(clock), }; diff --git a/packages/execution/src/execute-task.ts b/packages/execution/src/execute-task.ts index fd7f4ad..02123ab 100644 --- a/packages/execution/src/execute-task.ts +++ b/packages/execution/src/execute-task.ts @@ -1,10 +1,11 @@ import { randomUUID } from 'node:crypto'; import path from 'node:path'; -import { MarkdownDocument } from '@specbridge/compat-kiro'; +import { MarkdownDocument, taskFingerprint, tryTaskPlanHashOfFile } from '@specbridge/compat-kiro'; import type { AgentConfig, EvidenceStatus, ExecutionOutcome, + SpecWorkflowState, WorkspaceInfo, } from '@specbridge/core'; import { @@ -12,6 +13,7 @@ import { TASK_RUNNER_REPORT_JSON_SCHEMA, exitCodeForOutcome, readSpecState, + stateStage, } from '@specbridge/core'; import type { RunnerRegistry, TaskExecutionResult } from '@specbridge/runners'; import { ClaudeCodeRunner, buildClaudeInvocation, probeClaude } from '@specbridge/runners'; @@ -19,6 +21,7 @@ import type { Clock } from '@specbridge/workflow'; import { evaluateWorkflow, systemClock } from '@specbridge/workflow'; import type { ChangedFileRecord, + EvidenceSpecContext, SnapshotComparison, GitSnapshot, VerificationRunResult, @@ -556,6 +559,7 @@ export async function finalizeTaskRun( } } + const specContext = buildEvidenceSpecContext(workspace, context.specName, stateNow, task); const evidenceRecord: TaskEvidenceRecord = { schemaVersion: EVIDENCE_SCHEMA_VERSION, runId, @@ -563,6 +567,7 @@ export async function finalizeTaskRun( specName: context.specName, taskId: task.id, status: evidenceStatus, + specContext, runner: context.runnerName, ...(result.sessionId !== undefined ? { sessionId: result.sessionId } : {}), repository: { @@ -643,6 +648,49 @@ export async function finalizeTaskRun( return report; } +/** + * Spec-and-task identity captured alongside evidence (v0.4). Verification + * later compares these values with the then-current approved state to decide + * deterministically whether the evidence is still fresh. + */ +export function buildEvidenceSpecContext( + workspace: WorkspaceInfo, + specName: string, + state: SpecWorkflowState | undefined, + task: Pick, +): EvidenceSpecContext { + const specContext: EvidenceSpecContext = { + taskFingerprint: taskFingerprint({ + id: task.id, + title: task.title, + requirementRefs: task.requirementRefs, + }), + taskText: task.rawLineText, + }; + if (state === undefined) return specContext; + + const documentStage = stateStage(state, state.specType === 'bugfix' ? 'bugfix' : 'requirements'); + if (documentStage?.status === 'approved' && documentStage.approvedHash !== null) { + specContext.documentHash = documentStage.approvedHash; + } + const designStage = stateStage(state, 'design'); + if (designStage?.status === 'approved' && designStage.approvedHash !== null) { + specContext.designHash = designStage.approvedHash; + } + const tasksStage = stateStage(state, 'tasks'); + if (tasksStage?.status === 'approved') { + // Prefer the recorded plan hash; fall back to hashing the current file + // (identical whenever the approval is effective, which evidence + // evaluation has already checked at this point). + const planHash = + typeof tasksStage.approvedPlanHash === 'string' + ? tasksStage.approvedPlanHash + : tryTaskPlanHashOfFile(path.join(workspace.kiroDir, 'specs', specName, 'tasks.md')); + if (planHash !== undefined) specContext.tasksPlanHash = planHash; + } + return specContext; +} + function applyConfiguredProtectedPaths(config: AgentConfig, comparison: SnapshotComparison): void { const prefixes = config.execution.protectedPaths.map((prefix) => prefix.endsWith('/') ? prefix : `${prefix}/`, diff --git a/packages/reporting/package.json b/packages/reporting/package.json index 3814df0..d56f6d7 100644 --- a/packages/reporting/package.json +++ b/packages/reporting/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/reporting", - "version": "0.3.0", + "version": "0.4.0", "description": "Terminal, JSON, and self-contained HTML report rendering for SpecBridge.", "license": "MIT", "type": "module", diff --git a/packages/reporting/src/index.ts b/packages/reporting/src/index.ts index 604247c..a6305e7 100644 --- a/packages/reporting/src/index.ts +++ b/packages/reporting/src/index.ts @@ -1,3 +1,6 @@ export * from './terminal-report.js'; export * from './json-report.js'; export * from './html-report.js'; +export * from './verification-terminal.js'; +export * from './verification-markdown.js'; +export * from './verification-html.js'; diff --git a/packages/reporting/src/verification-html.ts b/packages/reporting/src/verification-html.ts new file mode 100644 index 0000000..7e8296c --- /dev/null +++ b/packages/reporting/src/verification-html.ts @@ -0,0 +1,202 @@ +import type { + SpecVerificationResult, + VerificationDiagnostic, + VerificationReport, +} from '@specbridge/core'; +import { escapeHtml } from './html-report.js'; + +/** + * Self-contained static HTML rendering for verification reports. + * + * - no external requests of any kind (CSS is inline, no fonts, no CDN) + * - no JavaScript: severity and spec filters use CSS-only checkboxes; + * all content is fully readable with CSS disabled too + * - all dynamic content is HTML-escaped + * - works from file:// and inside artifact viewers + */ + +function severityGlyph(severity: VerificationDiagnostic['severity']): string { + if (severity === 'error') return '✗'; + if (severity === 'warning') return '!'; + return '·'; +} + +function specSlug(index: number): string { + return `spec-${index}`; +} + +function renderDiagnostic(diagnostic: VerificationDiagnostic, specClass: string): string { + const location = + diagnostic.file !== null + ? `${escapeHtml(diagnostic.file.path)}${diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ''}` + : diagnostic.taskId !== null + ? `task ${escapeHtml(diagnostic.taskId)}` + : ''; + return [ + `
  • `, + ``, + `

    ${escapeHtml(diagnostic.ruleId)}`, + ` ${diagnostic.severity}`, + diagnostic.confidence === 'heuristic' ? ' heuristic' : '', + location !== '' ? ` — ${location}` : '', + `

    ${escapeHtml(diagnostic.message)}

    `, + `

    Fix: ${escapeHtml(diagnostic.remediation)}

  • `, + ].join(''); +} + +function renderSpec(spec: SpecVerificationResult, index: number): string { + const cls = specSlug(index); + const t = spec.traceability; + const e = spec.evidence; + const rows = spec.changedFiles + .map( + (file) => + `${escapeHtml(file.changeType)}${escapeHtml(file.path)}${ + file.oldPath !== null ? ` from ${escapeHtml(file.oldPath)}` : '' + }${file.binary ? 'binary' : `+${file.insertions ?? 0} −${file.deletions ?? 0}`}`, + ) + .join('\n'); + return ` +
    +

    ${escapeHtml(spec.specName)} ${spec.result}

    +

    ${escapeHtml(spec.specType)}${spec.managed ? '' : ' · unmanaged'} · policy: ${escapeHtml(spec.policyMode)}${ + spec.policyPath !== null ? ` (${escapeHtml(spec.policyPath)})` : ' (defaults)' + }

    +

    Traceability: ${t.requirements} requirements (${t.requirementsWithTasks} with tasks), ${t.tasks} tasks (${t.tasksWithRequirements} linked) · +Evidence: ${e.valid} valid${e.manuallyAccepted > 0 ? ` (${e.manuallyAccepted} manually accepted)` : ''}, ${e.stale} stale, ${e.missing} missing${ + e.invalid > 0 ? `, ${e.invalid} invalid` : '' + }

    +${ + spec.changedFiles.length > 0 + ? `
    ${spec.changedFiles.length} changed file${spec.changedFiles.length === 1 ? '' : 's'} + +${rows} +
    ChangePathLines
    ` + : '' +} +${ + spec.diagnostics.length > 0 + ? `
      \n${spec.diagnostics.map((diagnostic) => renderDiagnostic(diagnostic, cls)).join('\n')}\n
    ` + : '

    No findings.

    ' +} +
    `; +} + +/** Render a verification report as one portable HTML document. */ +export function renderVerificationHtml(report: VerificationReport): string { + const specFilters = report.specResults + .map( + (spec, index) => + ``, + ) + .join('\n'); + const specFilterCss = report.specResults + .map( + (_, index) => + `body:has(#f-${specSlug(index)}:not(:checked)) .${specSlug(index)} { display: none; }`, + ) + .join('\n'); + + const commandRows = report.verificationCommands + .map((command) => { + const outcome = + command.disposition === 'executed' + ? command.passed + ? `passed (exit ${command.exitCode ?? 0})` + : command.timedOut + ? 'timed out' + : `failed (exit ${command.exitCode ?? '?'})` + : command.disposition === 'reused-evidence' + ? 'passed (reused from evidence)' + : 'not run'; + return `${escapeHtml(command.name)}${ + command.required ? 'required' : 'optional' + }${escapeHtml(command.argv.join(' '))}${escapeHtml(outcome)}`; + }) + .join('\n'); + + const summary = report.summary; + return ` + + + + +SpecBridge verification — ${escapeHtml(summary.result)} + + + +

    SpecBridge Verification

    +

    ${summary.result === 'passed' ? 'PASSED' : 'FAILED'} — ${summary.errors} errors, ${summary.warnings} warnings, ${summary.info} info

    +

    Comparison: ${escapeHtml(report.comparison.label)} · selection: ${escapeHtml(report.selection.mode)} · ${summary.specsVerified} spec(s) verified

    +

    specbridge ${escapeHtml(report.tool.version)} · verification ${escapeHtml(report.verificationId)} · ${escapeHtml(report.createdAt)}

    + +
    +Filters (CSS only — content remains in the document) + + + +${specFilters} +
    + +${ + report.globalDiagnostics.length > 0 + ? `

    Workspace findings

      +${report.globalDiagnostics.map((diagnostic) => renderDiagnostic(diagnostic, 'global')).join('\n')} +
    ` + : '' +} + +${ + report.verificationCommands.length > 0 + ? `

    Verification commands

    + +${commandRows} +
    CommandKindargvOutcome
    ` + : '' +} + +${report.specResults.map((spec, index) => renderSpec(spec, index)).join('\n')} + +
    Generated by specbridge spec verify — deterministic, offline, no model involved.
    + + +`; +} diff --git a/packages/reporting/src/verification-markdown.ts b/packages/reporting/src/verification-markdown.ts new file mode 100644 index 0000000..70e9576 --- /dev/null +++ b/packages/reporting/src/verification-markdown.ts @@ -0,0 +1,215 @@ +import type { + SpecVerificationResult, + VerificationDiagnostic, + VerificationReport, +} from '@specbridge/core'; + +/** + * Markdown rendering for verification reports — used for GitHub Step + * Summaries, pull-request comments, and saved artifacts. + * + * Output limits are enforced (GitHub truncates step summaries at 1 MiB); + * no raw command output or environment data ever appears here. + */ + +export interface VerificationMarkdownOptions { + /** Maximum diagnostics listed per spec before folding into a count. */ + maxDiagnosticsPerSpec?: number; + /** Maximum blocking issues in the top section. */ + maxBlockingIssues?: number; + /** Report paths to link at the bottom (workspace-relative). */ + artifactPaths?: { json?: string; markdown?: string; html?: string }; +} + +const DEFAULT_MAX_DIAGNOSTICS = 50; +const DEFAULT_MAX_BLOCKING = 10; + +/** Escape content for a Markdown table cell. */ +function cell(text: string): string { + return text.replaceAll('|', '\\|').replaceAll('\n', ' '); +} + +/** Inline code span that survives backticks in the content. */ +function code(text: string): string { + return text.includes('`') ? `\`\`${text}\`\`` : `\`${text}\``; +} + +function diagnosticLine(diagnostic: VerificationDiagnostic): string { + const location = + diagnostic.file !== null + ? ` — ${code(diagnostic.file.path)}${diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ''}` + : ''; + const heuristic = diagnostic.confidence === 'heuristic' ? ' _(heuristic)_' : ''; + return `- ${code(diagnostic.ruleId)}${location}${heuristic} — ${diagnostic.message}`; +} + +function severityBadge(diagnostic: VerificationDiagnostic): string { + if (diagnostic.severity === 'error') return '🔴 error'; + if (diagnostic.severity === 'warning') return '🟡 warning'; + return '🔵 info'; +} + +function specSection(spec: SpecVerificationResult, maxDiagnostics: number): string[] { + const lines: string[] = []; + lines.push(`### ${spec.specName}`); + lines.push(''); + const policy = + spec.policyPath !== null ? `${spec.policyMode} (${code(spec.policyPath)})` : `${spec.policyMode} (defaults)`; + lines.push( + `**Result:** ${spec.result === 'passed' ? 'Passed' : 'Failed'} · **Policy:** ${policy} · ` + + `**Type:** ${spec.specType}${spec.managed ? '' : ' (unmanaged)'}`, + ); + lines.push(''); + const t = spec.traceability; + const e = spec.evidence; + lines.push( + `Traceability: ${t.requirements} requirements (${t.requirementsWithTasks} with tasks), ` + + `${t.tasks} tasks (${t.tasksWithRequirements} linked). ` + + `Evidence: ${e.valid} valid${e.manuallyAccepted > 0 ? ` (${e.manuallyAccepted} manual)` : ''}, ` + + `${e.stale} stale, ${e.missing} missing.`, + ); + lines.push(''); + + if (spec.diagnostics.length === 0) { + lines.push('No findings.'); + lines.push(''); + return lines; + } + + lines.push('| Severity | Rule | Where | Finding |'); + lines.push('|---|---|---|---|'); + const shown = spec.diagnostics.slice(0, maxDiagnostics); + for (const diagnostic of shown) { + const where = + diagnostic.file !== null + ? `${code(diagnostic.file.path)}${diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ''}` + : diagnostic.taskId !== null + ? `task ${code(diagnostic.taskId)}` + : '—'; + lines.push( + `| ${severityBadge(diagnostic)} | ${code(diagnostic.ruleId)} | ${cell(where)} | ${cell(diagnostic.message)} |`, + ); + } + if (spec.diagnostics.length > shown.length) { + lines.push(''); + lines.push(`… and ${spec.diagnostics.length - shown.length} more findings (see the JSON report).`); + } + lines.push(''); + + const remediations = shown.filter((diagnostic) => diagnostic.severity !== 'info'); + if (remediations.length > 0) { + lines.push('
    '); + lines.push('How to fix'); + lines.push(''); + for (const diagnostic of remediations) { + lines.push(`- ${code(diagnostic.ruleId)} — ${diagnostic.remediation}`); + } + lines.push(''); + lines.push('
    '); + lines.push(''); + } + return lines; +} + +/** Render a verification report as GitHub-flavored Markdown. */ +export function renderVerificationMarkdown( + report: VerificationReport, + options: VerificationMarkdownOptions = {}, +): string { + const maxDiagnostics = options.maxDiagnosticsPerSpec ?? DEFAULT_MAX_DIAGNOSTICS; + const maxBlocking = options.maxBlockingIssues ?? DEFAULT_MAX_BLOCKING; + const lines: string[] = []; + + lines.push('# SpecBridge Verification'); + lines.push(''); + lines.push(`**Result:** ${report.summary.result === 'passed' ? 'Passed ✅' : 'Failed ❌'}`); + lines.push(''); + lines.push( + `Comparison: ${code(report.comparison.label)} · Selection: ${report.selection.mode} · ` + + `${report.summary.specsVerified} spec${report.summary.specsVerified === 1 ? '' : 's'} verified · ` + + `${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info`, + ); + lines.push(''); + + if (report.specResults.length > 0) { + lines.push('| Spec | Result | Errors | Warnings |'); + lines.push('|---|---|---:|---:|'); + for (const spec of report.specResults) { + const errors = spec.diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length; + const warnings = spec.diagnostics.filter( + (diagnostic) => diagnostic.severity === 'warning', + ).length; + lines.push( + `| ${cell(spec.specName)} | ${spec.result === 'passed' ? 'Passed' : 'Failed'} | ${errors} | ${warnings} |`, + ); + } + lines.push(''); + } + + const allDiagnostics = [ + ...report.globalDiagnostics, + ...report.specResults.flatMap((spec) => spec.diagnostics), + ]; + const blocking = allDiagnostics.filter((diagnostic) => diagnostic.severity === 'error'); + if (blocking.length > 0) { + lines.push('## Blocking issues'); + lines.push(''); + for (const diagnostic of blocking.slice(0, maxBlocking)) { + lines.push(diagnosticLine(diagnostic)); + } + if (blocking.length > maxBlocking) { + lines.push(`- … and ${blocking.length - maxBlocking} more errors.`); + } + lines.push(''); + } + + if (report.verificationCommands.length > 0) { + lines.push('## Verification commands'); + lines.push(''); + lines.push('| Command | Required | Outcome |'); + lines.push('|---|---|---|'); + for (const command of report.verificationCommands) { + const outcome = + command.disposition === 'executed' + ? command.passed + ? `passed (exit ${command.exitCode ?? 0})` + : command.timedOut + ? 'timed out' + : `failed (exit ${command.exitCode ?? '?'})` + : command.disposition === 'reused-evidence' + ? 'passed (reused from evidence)' + : 'not run'; + lines.push(`| ${code(command.name)} | ${command.required ? 'yes' : 'no'} | ${cell(outcome)} |`); + } + lines.push(''); + } + + if (report.globalDiagnostics.length > 0) { + lines.push('## Workspace findings'); + lines.push(''); + for (const diagnostic of report.globalDiagnostics.slice(0, maxDiagnostics)) { + lines.push(diagnosticLine(diagnostic)); + } + lines.push(''); + } + + for (const spec of report.specResults) { + lines.push(...specSection(spec, maxDiagnostics)); + } + + const artifacts = options.artifactPaths; + if (artifacts !== undefined && (artifacts.json ?? artifacts.markdown ?? artifacts.html) !== undefined) { + lines.push('## Reports'); + lines.push(''); + if (artifacts.json !== undefined) lines.push(`- JSON: ${code(artifacts.json)}`); + if (artifacts.markdown !== undefined) lines.push(`- Markdown: ${code(artifacts.markdown)}`); + if (artifacts.html !== undefined) lines.push(`- HTML: ${code(artifacts.html)}`); + lines.push(''); + } + + lines.push( + `specbridge ${report.tool.version} · verification ${report.verificationId} · ${report.createdAt}`, + ); + lines.push(''); + return lines.join('\n'); +} diff --git a/packages/reporting/src/verification-terminal.ts b/packages/reporting/src/verification-terminal.ts new file mode 100644 index 0000000..29d106c --- /dev/null +++ b/packages/reporting/src/verification-terminal.ts @@ -0,0 +1,171 @@ +import pc from 'picocolors'; +import type { + SpecVerificationResult, + VerificationDiagnostic, + VerificationReport, +} from '@specbridge/core'; +import { dim, failLine, infoLine, okLine, reportTitle, sectionTitle, warnLine } from './terminal-report.js'; + +/** + * Terminal rendering for verification reports. Concise but actionable: every + * diagnostic shows its stable rule ID, location, and remediation. Severity is + * always carried by a glyph (✓ ! ✗ ·), never by color alone — picocolors + * already honors NO_COLOR and non-TTY output. + */ + +export interface VerificationTerminalOptions { + verbose?: boolean; +} + +function severityGlyphLine(diagnostic: VerificationDiagnostic, text: string): string { + if (diagnostic.severity === 'error') return failLine(text); + if (diagnostic.severity === 'warning') return warnLine(text); + return infoLine(text); +} + +function diagnosticLocation(diagnostic: VerificationDiagnostic): string { + if (diagnostic.file === null) return ''; + const line = diagnostic.file.line !== null ? `:${diagnostic.file.line}` : ''; + return ` ${diagnostic.file.path}${line}`; +} + +function renderDiagnostic(lines: string[], diagnostic: VerificationDiagnostic): void { + const heuristic = diagnostic.confidence === 'heuristic' ? ' (heuristic)' : ''; + lines.push( + severityGlyphLine(diagnostic, `${pc.bold(diagnostic.ruleId)}${diagnosticLocation(diagnostic)}${heuristic}`), + ); + lines.push(` ${diagnostic.message}`); + lines.push(dim(` Fix: ${diagnostic.remediation}`)); +} + +function renderSpecResult( + lines: string[], + spec: SpecVerificationResult, + options: VerificationTerminalOptions, +): void { + lines.push(reportTitle(`Spec: ${spec.specName}`)); + const mode = spec.workflowMode !== 'unknown' ? `, ${spec.workflowMode}` : ''; + lines.push(dim(` ${spec.specType}${mode}${spec.managed ? '' : ', unmanaged'}`)); + lines.push( + ` Policy: ${spec.policyMode}${spec.policyPath !== null ? ` (${spec.policyPath})` : ' (defaults — no policy file)'}`, + ); + if (spec.matchedBy.length > 0) { + lines.push(dim(` Selected via: ${spec.matchedBy.join('; ')}`)); + } + + const t = spec.traceability; + if (t.requirements > 0 || t.tasks > 0) { + lines.push(sectionTitle(' Traceability')); + lines.push( + okLine( + `${t.requirements} requirement${t.requirements === 1 ? '' : 's'} detected, ${t.requirementsWithTasks} with tasks`, + ), + ); + lines.push(okLine(`${t.tasks} task${t.tasks === 1 ? '' : 's'}, ${t.tasksWithRequirements} with requirement references`)); + } + + const e = spec.evidence; + const completedTracked = e.valid + e.stale + e.missing; + if (completedTracked > 0 || e.invalid > 0) { + lines.push(sectionTitle(' Evidence (completed tasks)')); + if (e.valid > 0) { + const manual = e.manuallyAccepted > 0 ? ` (${e.manuallyAccepted} manually accepted)` : ''; + lines.push(okLine(`${e.valid} with valid evidence${manual}`)); + } + if (e.stale > 0) lines.push(failLine(`${e.stale} with stale evidence`)); + if (e.missing > 0) lines.push(warnLine(`${e.missing} without evidence`)); + if (e.invalid > 0) lines.push(failLine(`${e.invalid} invalid evidence record${e.invalid === 1 ? '' : 's'}`)); + } + + if (spec.changedFiles.length > 0) { + lines.push(sectionTitle(' Changed files')); + const shown = options.verbose === true ? spec.changedFiles : spec.changedFiles.slice(0, 10); + for (const file of shown) { + const rename = file.oldPath !== null ? ` (from ${file.oldPath})` : ''; + lines.push(dim(` ${file.changeType.padEnd(9)} ${file.path}${rename}`)); + } + if (shown.length < spec.changedFiles.length) { + lines.push(dim(` … and ${spec.changedFiles.length - shown.length} more (--verbose shows all)`)); + } + } + + const visible = spec.diagnostics.filter( + (diagnostic) => options.verbose === true || diagnostic.severity !== 'info', + ); + lines.push(sectionTitle(' Diagnostics')); + if (visible.length === 0) { + lines.push(okLine('none')); + } else { + for (const diagnostic of visible) renderDiagnostic(lines, diagnostic); + } + lines.push( + spec.result === 'passed' + ? okLine(pc.bold('Spec result: PASSED')) + : failLine(pc.bold('Spec result: FAILED')), + ); + lines.push(''); +} + +/** Render a full verification report as terminal lines. */ +export function renderVerificationTerminal( + report: VerificationReport, + options: VerificationTerminalOptions = {}, +): string[] { + const lines: string[] = []; + lines.push(reportTitle('Spec Drift Verification')); + lines.push(''); + lines.push(sectionTitle('Comparison')); + lines.push(` ${report.comparison.label}`); + if (report.comparison.baseSha !== null && report.comparison.mode === 'diff') { + lines.push( + dim(` ${report.comparison.baseSha.slice(0, 12)} → ${report.comparison.headSha?.slice(0, 12) ?? '?'}`), + ); + } + lines.push(''); + + if (report.selection.mode !== 'single') { + lines.push(sectionTitle(report.selection.mode === 'changed' ? 'Affected specs' : 'Specs')); + if (report.selection.specs.length === 0) { + lines.push(infoLine('none')); + } else { + for (const spec of report.selection.specs) lines.push(` ${spec}`); + } + lines.push(''); + } + + for (const spec of report.specResults) renderSpecResult(lines, spec, options); + + if (report.globalDiagnostics.length > 0) { + lines.push(sectionTitle('Workspace diagnostics')); + for (const diagnostic of report.globalDiagnostics) { + if (options.verbose !== true && diagnostic.severity === 'info') continue; + renderDiagnostic(lines, diagnostic); + } + lines.push(''); + } + + if (report.verificationCommands.length > 0) { + lines.push(sectionTitle('Verification commands')); + for (const command of report.verificationCommands) { + const detail = + command.disposition === 'executed' + ? `exit ${command.exitCode ?? '?'}${command.timedOut ? ', timed out' : ''}` + : command.disposition === 'reused-evidence' + ? 'reused from evidence' + : 'not run'; + const label = `${command.name}${command.required ? '' : ' (optional)'} — ${detail}`; + lines.push(command.passed ? okLine(label) : failLine(label)); + } + lines.push(''); + } + + const s = report.summary; + const counts = `${s.errors} error${s.errors === 1 ? '' : 's'}, ${s.warnings} warning${s.warnings === 1 ? '' : 's'}, ${s.info} info`; + lines.push(sectionTitle('Result')); + lines.push( + s.result === 'passed' + ? okLine(pc.bold(`PASSED — ${counts}`)) + : failLine(pc.bold(`FAILED — ${counts}`)), + ); + return lines; +} diff --git a/packages/runners/package.json b/packages/runners/package.json index 5b321c4..7486672 100644 --- a/packages/runners/package.json +++ b/packages/runners/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/runners", - "version": "0.3.0", + "version": "0.4.0", "description": "Model- and agent-agnostic runner adapters for SpecBridge (mock, Claude Code, Codex, stubs).", "license": "MIT", "type": "module", diff --git a/packages/workflow/package.json b/packages/workflow/package.json index ab538c1..1ae926b 100644 --- a/packages/workflow/package.json +++ b/packages/workflow/package.json @@ -1,6 +1,6 @@ { "name": "@specbridge/workflow", - "version": "0.3.0", + "version": "0.4.0", "description": "Offline spec authoring and approval workflow for SpecBridge: templates, deterministic analysis, stage approvals, and stale-approval detection.", "license": "MIT", "type": "module", diff --git a/packages/workflow/src/approval.ts b/packages/workflow/src/approval.ts index 47967d0..34a47bb 100644 --- a/packages/workflow/src/approval.ts +++ b/packages/workflow/src/approval.ts @@ -9,12 +9,14 @@ import type { } from '@specbridge/core'; import { SPEC_STATE_SCHEMA_VERSION, + TASK_PLAN_HASH_SEMANTICS_VERSION, readSpecState, sha256File, stateStage, writeSpecState, } from '@specbridge/core'; import type { SpecAnalysis } from '@specbridge/compat-kiro'; +import { tryTaskPlanHashOfFile } from '@specbridge/compat-kiro'; import type { Clock } from './clock.js'; import { isoNow, systemClock } from './clock.js'; import type { SpecAnalysisResult } from './analyzers.js'; @@ -169,6 +171,21 @@ function stageList(stages: StageName[]): string { return stages.join(', '); } +/** + * A stage approval reset to draft. Every approval artifact — including the + * v0.4 plan-hash fields — is removed so the cleared entry validates and a + * later re-approval starts from a clean slate. + */ +function clearedApproval(stage: StageApproval): StageApproval { + const { + approvedPlanHash: _plan, + hashAlgorithm: _algorithm, + hashSemanticsVersion: _semantics, + ...rest + } = stage; + return { ...rest, status: 'draft', approvedAt: null, approvedHash: null }; +} + function cloneStages(state: SpecWorkflowState): Record { const stages: Record = {}; for (const [name, value] of Object.entries(state.stages)) { @@ -360,22 +377,28 @@ export function approveStage( for (const dependent of dependentStages(shape, request.stage)) { const dependentStage = stages[dependent]; if (dependentStage !== undefined && dependentStage.status === 'approved') { - stages[dependent] = { - ...dependentStage, - status: 'draft', - approvedAt: null, - approvedHash: null, - }; + stages[dependent] = clearedApproval(dependentStage); invalidated.push(dependent); } } } + // The tasks stage additionally records a checkbox-normalized plan hash + // (semantics v2) so later `[ ]` → `[x]` progress does not read as a plan + // change. Other stages stay exact-byte only. + const planHash = request.stage === 'tasks' ? tryTaskPlanHashOfFile(filePath) : undefined; stages[request.stage] = { ...target, status: 'approved', approvedAt: isoNow(clock), approvedHash: hash, + ...(planHash !== undefined + ? { + approvedPlanHash: planHash, + hashAlgorithm: 'sha256' as const, + hashSemanticsVersion: TASK_PLAN_HASH_SEMANTICS_VERSION, + } + : {}), }; const recomputed = recomputeStages(shape, { @@ -424,17 +447,12 @@ function revoke( for (const dependent of dependentStages(shape, stage)) { const dependentStage = stages[dependent]; if (dependentStage !== undefined && dependentStage.status === 'approved') { - stages[dependent] = { - ...dependentStage, - status: 'draft', - approvedAt: null, - approvedHash: null, - }; + stages[dependent] = clearedApproval(dependentStage); invalidated.push(dependent); } } - stages[stage] = { ...target, status: 'draft', approvedAt: null, approvedHash: null }; + stages[stage] = clearedApproval(target); const recomputed = recomputeStages(shape, { ...state, diff --git a/packages/workflow/src/health.ts b/packages/workflow/src/health.ts index 518290b..ac06d63 100644 --- a/packages/workflow/src/health.ts +++ b/packages/workflow/src/health.ts @@ -8,6 +8,7 @@ import type { WorkspaceInfo, } from '@specbridge/core'; import { stateStage, trySha256File } from '@specbridge/core'; +import { tryTaskPlanHashOfFile } from '@specbridge/compat-kiro'; import type { WorkflowShape } from './state-machine.js'; import { dependentStages, @@ -42,6 +43,13 @@ export interface StageEvaluation { fileExists: boolean; /** Present for approved stages (undefined when the file is unreadable). */ currentHash?: string; + /** + * Tasks stage only: true when the exact bytes changed after approval but + * the checkbox-normalized plan hash still matches — i.e. the only changes + * since approval are `[ ]`/`[x]` progress. The stage stays effectively + * approved in that case (hash semantics v2). + */ + checkboxProgressOnly?: boolean; prerequisites: StageName[]; } @@ -97,9 +105,27 @@ export function evaluateWorkflow( const fileExists = currentHash !== undefined; let effective: EffectiveStageStatus; + let checkboxProgressOnly = false; if (stored.status === 'approved') { if (currentHash !== undefined && currentHash === stored.approvedHash) { effective = 'approved'; + } else if ( + stage === 'tasks' && + currentHash !== undefined && + typeof stored.approvedPlanHash === 'string' && + tryTaskPlanHashOfFile(filePath) === stored.approvedPlanHash + ) { + // Only checkbox state changed since approval: the plan itself is the + // one that was approved (hash semantics v2), so the approval holds. + effective = 'approved'; + checkboxProgressOnly = true; + diagnostics.push({ + severity: 'info', + code: 'APPROVAL_CHECKBOX_PROGRESS', + message: + 'tasks.md has checkbox progress since approval; the approved task plan itself is unchanged.', + file: filePath, + }); } else { effective = 'modified-after-approval'; staleStages.push(stage); @@ -124,6 +150,7 @@ export function evaluateWorkflow( filePath, fileExists, ...(stored.status === 'approved' && currentHash !== undefined ? { currentHash } : {}), + ...(checkboxProgressOnly ? { checkboxProgressOnly } : {}), prerequisites: stagePrerequisites(shape, stage), }); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb5be0c..80ea11c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,31 @@ importers: specifier: ^3.0.0 version: 3.2.7(@types/node@20.19.43)(yaml@2.9.0) + integrations/github-action: + dependencies: + '@actions/core': + specifier: ^1.11.1 + version: 1.11.1 + '@specbridge/compat-kiro': + specifier: workspace:* + version: link:../../packages/compat-kiro + '@specbridge/core': + specifier: workspace:* + version: link:../../packages/core + '@specbridge/drift': + specifier: workspace:* + version: link:../../packages/drift + '@specbridge/reporting': + specifier: workspace:* + version: link:../../packages/reporting + devDependencies: + tsup: + specifier: ^8.3.0 + version: 8.5.1(postcss@8.5.16)(typescript@5.9.3)(yaml@2.9.0) + typescript: + specifier: ^5.6.0 + version: 5.9.3 + packages/cli: dependencies: '@specbridge/compat-kiro': @@ -35,6 +60,9 @@ importers: '@specbridge/core': specifier: workspace:* version: link:../core + '@specbridge/drift': + specifier: workspace:* + version: link:../drift '@specbridge/evidence': specifier: workspace:* version: link:../evidence @@ -101,6 +129,15 @@ importers: '@specbridge/core': specifier: workspace:* version: link:../core + '@specbridge/evidence': + specifier: workspace:* + version: link:../evidence + '@specbridge/runners': + specifier: workspace:* + version: link:../runners + '@specbridge/workflow': + specifier: workspace:* + version: link:../workflow execa: specifier: ^9.4.0 version: 9.6.1 @@ -221,6 +258,18 @@ importers: packages: + '@actions/core@1.11.1': + resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} + + '@actions/exec@1.1.1': + resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} + + '@actions/http-client@2.2.3': + resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} + + '@actions/io@1.1.3': + resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} + '@esbuild/aix-ppc64@0.27.7': resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} engines: {node: '>=18'} @@ -571,6 +620,10 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} @@ -1438,6 +1491,10 @@ packages: typescript: optional: true + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -1460,6 +1517,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@5.29.0: + resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} + engines: {node: '>=14.0'} + unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -1572,6 +1633,22 @@ packages: snapshots: + '@actions/core@1.11.1': + dependencies: + '@actions/exec': 1.1.1 + '@actions/http-client': 2.2.3 + + '@actions/exec@1.1.1': + dependencies: + '@actions/io': 1.1.3 + + '@actions/http-client@2.2.3': + dependencies: + tunnel: 0.0.6 + undici: 5.29.0 + + '@actions/io@1.1.3': {} + '@esbuild/aix-ppc64@0.27.7': optional: true @@ -1774,6 +1851,8 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@fastify/busboy@2.1.1': {} + '@humanfs/core@0.19.2': dependencies: '@humanfs/types': 0.15.0 @@ -2636,6 +2715,8 @@ snapshots: - tsx - yaml + tunnel@0.0.6: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -2657,6 +2738,10 @@ snapshots: undici-types@6.21.0: {} + undici@5.29.0: + dependencies: + '@fastify/busboy': 2.1.1 + unicorn-magic@0.3.0: {} uri-js@4.4.1: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 924b55f..f6d1735 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ packages: - packages/* + - integrations/github-action diff --git a/scripts/smoke.mjs b/scripts/smoke.mjs index e36e6b0..afdc8b3 100644 --- a/scripts/smoke.mjs +++ b/scripts/smoke.mjs @@ -258,6 +258,56 @@ run('unknown spec errors helpfully', { expectStderr: ['Available specs:'], }); +// v0.4 deterministic drift verification — read-only, offline, no model. +run('verify rules lists the stable rule registry', { + cwd: kiroProject, + args: ['verify', 'rules'], + expectCode: 0, + expectStdout: ['SBV001', 'SBV025', 'Changed file outside declared impact area'], +}); + +run('verify explain describes one rule with remediation', { + cwd: kiroProject, + args: ['verify', 'explain', 'SBV011'], + expectCode: 0, + expectStdout: ['SBV011', 'Triggered when', 'Resolution'], +}); + +// The stock example deliberately ships drift: task 2 is checked while its +// subtasks 2.2/2.3 are open — verification must catch it (SBV010). +run('spec verify detects the drift shipped in the example (read-only)', { + cwd: kiroProject, + args: ['spec', 'verify', 'user-authentication', '--working-tree'], + expectCode: 1, + expectStdout: [ + 'Spec Drift Verification', + 'working tree vs HEAD', + 'SBV010', + 'FAILED', + ], +}); + +run('spec verify --json emits the versioned report schema', { + cwd: kiroProject, + args: ['spec', 'verify', 'user-authentication', '--json', '--fail-on', 'never'], + expectCode: 0, + expectStdout: ['"schemaVersion": "1.0.0"', '"ruleId": "SBV010"', '"specResults"'], +}); + +run('spec affected resolves the change mapping', { + cwd: kiroProject, + args: ['spec', 'affected', '--working-tree'], + expectCode: 0, + expectStdout: ['Affected specs'], +}); + +run('spec policy init --dry-run proposes a starter policy without writing', { + cwd: kiroProject, + args: ['spec', 'policy', 'init', 'user-authentication', '--mode', 'strict', '--dry-run'], + expectCode: 0, + expectStdout: ['dry run', 'Review this file before enforcing strict verification'], +}); + // Version consistency between package.json and the version constant. const cliPackage = JSON.parse( readFileSync(path.join(repoRoot, 'packages', 'cli', 'package.json'), 'utf8'), diff --git a/tests/action/github-action.test.ts b/tests/action/github-action.test.ts new file mode 100644 index 0000000..5417c5e --- /dev/null +++ b/tests/action/github-action.test.ts @@ -0,0 +1,365 @@ +import { execFileSync } from 'node:child_process'; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { beforeAll, describe, expect, it } from 'vitest'; +import { resolveComparisonFromEvent } from '../../integrations/github-action/src/event.js'; +import { parseActionInputs } from '../../integrations/github-action/src/inputs.js'; +import { ACTION_VERSION } from '../../integrations/github-action/src/version.js'; +import { git } from '../helpers-execution.js'; +import { setupVerifyFixture, VERIFY_SPEC } from '../helpers-verify.js'; +import { fixturePath } from '../helpers.js'; + +/** + * GitHub Action tests. + * + * Unit level: event resolution and input validation (pure functions). + * Process level: the committed node20 bundle runs against real fixture + * repositories with real GITHUB_* environment files — exactly as the runner + * would execute it, requiring no model and no network access. + */ + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..'); +const actionDir = path.join(repoRoot, 'integrations', 'github-action'); +const bundlePath = path.join(actionDir, 'dist', 'index.js'); + +beforeAll(() => { + if (!existsSync(bundlePath)) { + // Local runs may predate a build; CI builds before testing. + execFileSync('pnpm', ['--filter', 'specbridge-github-action', 'build'], { + cwd: repoRoot, + stdio: 'ignore', + shell: process.platform === 'win32', + }); + } +}, 120_000); + +describe('event resolution (unit)', () => { + const payload = (name: string): unknown => + JSON.parse(readFileSync(fixturePath('github-events', `${name}.json`), 'utf8')); + + it('pull_request events resolve base and head SHAs', () => { + const resolution = resolveComparisonFromEvent({ + eventName: 'pull_request', + payload: payload('pull_request'), + sha: 'HEAD_SHA_PLACEHOLDER', + baseRef: undefined, + headRef: undefined, + }); + expect(resolution).toEqual({ + ok: true, + request: { mode: 'diff', base: 'BASE_SHA_PLACEHOLDER', head: 'HEAD_SHA_PLACEHOLDER' }, + source: 'pull_request event', + }); + }); + + it('push events resolve before...after', () => { + const resolution = resolveComparisonFromEvent({ + eventName: 'push', + payload: payload('push'), + sha: 'HEAD_SHA_PLACEHOLDER', + baseRef: undefined, + headRef: undefined, + }); + expect(resolution.ok).toBe(true); + if (resolution.ok) { + expect(resolution.request).toEqual({ + mode: 'diff', + base: 'BASE_SHA_PLACEHOLDER', + head: 'HEAD_SHA_PLACEHOLDER', + }); + } + }); + + it('a branch-creating push (zero before-SHA) fails with guidance', () => { + const resolution = resolveComparisonFromEvent({ + eventName: 'push', + payload: { before: '0'.repeat(40), after: 'abc' }, + sha: 'abc', + baseRef: undefined, + headRef: undefined, + }); + expect(resolution.ok).toBe(false); + if (!resolution.ok) expect(resolution.message).toContain('base-ref'); + }); + + it('workflow_dispatch requires explicit refs and accepts them', () => { + const withoutRefs = resolveComparisonFromEvent({ + eventName: 'workflow_dispatch', + payload: payload('workflow_dispatch'), + sha: 'abc', + baseRef: undefined, + headRef: undefined, + }); + expect(withoutRefs.ok).toBe(false); + if (!withoutRefs.ok) expect(withoutRefs.message).toContain('base-ref'); + + const withRefs = resolveComparisonFromEvent({ + eventName: 'workflow_dispatch', + payload: payload('workflow_dispatch'), + sha: 'abc', + baseRef: 'v1.0.0', + headRef: undefined, + }); + expect(withRefs).toEqual({ + ok: true, + request: { mode: 'diff', base: 'v1.0.0', head: 'HEAD' }, + source: 'explicit base-ref/head-ref inputs', + }); + }); + + it('hostile refs from any source are rejected', () => { + const resolution = resolveComparisonFromEvent({ + eventName: 'pull_request', + payload: { pull_request: { base: { sha: '--upload-pack=evil' }, head: { sha: 'abc' } } }, + sha: 'abc', + baseRef: undefined, + headRef: undefined, + }); + expect(resolution.ok).toBe(false); + }); +}); + +describe('input validation (unit)', () => { + const inputs = (values: Record) => (name: string): string => values[name] ?? ''; + + it('applies documented defaults', () => { + const parsed = parseActionInputs(inputs({})); + expect(parsed).toMatchObject({ + mode: 'changed', + failOn: 'error', + strict: false, + runVerification: true, + reportDirectory: '.specbridge/action-reports', + annotations: true, + writeStepSummary: true, + annotationLimit: 50, + }); + }); + + it('rejects invalid enums, booleans, limits, and mode/spec combinations', () => { + expect(() => parseActionInputs(inputs({ mode: 'everything' }))).toThrow(/single, changed, all/); + expect(() => parseActionInputs(inputs({ 'fail-on': 'maybe' }))).toThrow(/error, warning, never/); + expect(() => parseActionInputs(inputs({ strict: 'yep' }))).toThrow(/true.*false/); + expect(() => parseActionInputs(inputs({ mode: 'single' }))).toThrow(/required/); + expect(() => parseActionInputs(inputs({ spec: 'x' }))).toThrow(/only applies/); + expect(() => parseActionInputs(inputs({ 'annotation-limit': '-1' }))).toThrow(/between 0 and 1000/); + expect(() => parseActionInputs(inputs({ 'report-directory': '../escape' }))).toThrow(/\.\./); + }); + + it('version constant matches the action package version', () => { + const packageJson = JSON.parse(readFileSync(path.join(actionDir, 'package.json'), 'utf8')) as { + version: string; + }; + expect(ACTION_VERSION).toBe(packageJson.version); + }); +}); + +interface ActionRun { + code: number; + stdout: string; + outputs: string; + summary: string; +} + +function runBundledAction( + workspaceRoot: string, + options: { + eventName: string; + payload: unknown; + inputs?: Record; + sha?: string; + }, +): ActionRun { + const ghDir = path.join(workspaceRoot, '.github-runtime'); + mkdirSync(ghDir, { recursive: true }); + const eventPath = path.join(ghDir, 'event.json'); + const outputPath = path.join(ghDir, 'output.txt'); + const summaryPath = path.join(ghDir, 'summary.md'); + writeFileSync(eventPath, JSON.stringify(options.payload), 'utf8'); + writeFileSync(outputPath, '', 'utf8'); + writeFileSync(summaryPath, '', 'utf8'); + + const env: Record = { + ...(process.env as Record), + GITHUB_WORKSPACE: workspaceRoot, + GITHUB_EVENT_NAME: options.eventName, + GITHUB_EVENT_PATH: eventPath, + GITHUB_OUTPUT: outputPath, + GITHUB_STEP_SUMMARY: summaryPath, + GITHUB_SHA: options.sha ?? 'unset', + }; + for (const [name, value] of Object.entries(options.inputs ?? {})) { + env[`INPUT_${name.toUpperCase()}`] = value; + } + + let stdout = ''; + let code = 0; + try { + stdout = execFileSync(process.execPath, [bundlePath], { + cwd: workspaceRoot, + env, + encoding: 'utf8', + }); + } catch (error) { + const failure = error as { status?: number; stdout?: string }; + code = failure.status ?? 1; + stdout = failure.stdout ?? ''; + } + return { + code, + stdout, + outputs: readFileSync(outputPath, 'utf8'), + summary: readFileSync(summaryPath, 'utf8'), + }; +} + +function outputValue(outputs: string, name: string): string | undefined { + // @actions/core writes os.EOL — tolerate CRLF on Windows. + const match = new RegExp(`${name}<<(ghadelimiter_[^\r\n]+)\r?\n([\\s\\S]*?)\r?\n\\1`).exec( + outputs, + ); + return match?.[2]; +} + +describe('bundled action (process level)', () => { + it('passes on a clean pull_request diff, writing outputs, reports, and the step summary', () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.commit('policy baseline'); + fixture.write('src/settings/store.ts', 'export {};\n'); + fixture.commit('implementation'); + const base = git(fixture.root, 'rev-parse', 'HEAD~1').trim(); + const head = fixture.head(); + + const run = runBundledAction(fixture.root, { + eventName: 'pull_request', + payload: { pull_request: { base: { sha: base }, head: { sha: head } } }, + sha: head, + }); + + expect(run.code).toBe(0); + expect(outputValue(run.outputs, 'result')).toBe('passed'); + expect(outputValue(run.outputs, 'spec-count')).toBe('1'); + expect(outputValue(run.outputs, 'affected-specs')).toBe(`["${VERIFY_SPEC}"]`); + expect(outputValue(run.outputs, 'json-report')).toBe('.specbridge/action-reports/report.json'); + expect(run.summary).toContain('# SpecBridge Verification'); + expect(run.summary).toContain('Passed'); + for (const file of ['report.json', 'report.md', 'report.html']) { + expect(existsSync(path.join(fixture.root, '.specbridge', 'action-reports', file))).toBe(true); + } + }); + + it('fails the step at the threshold with rule-ID annotations, without touching tracked files', () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ mode: 'strict', impactAreas: ['src/settings/**'] }); + fixture.commit('policy'); + fixture.write('src/billing/invoice.ts', 'export {};\n'); + fixture.commit('out-of-scope change'); + const base = git(fixture.root, 'rev-parse', 'HEAD~1').trim(); + const head = fixture.head(); + const statusBefore = git(fixture.root, 'status', '--porcelain'); + + const run = runBundledAction(fixture.root, { + eventName: 'pull_request', + payload: { pull_request: { base: { sha: base }, head: { sha: head } } }, + sha: head, + inputs: { mode: 'single', spec: VERIFY_SPEC }, + }); + + expect(run.code).toBe(1); + expect(outputValue(run.outputs, 'result')).toBe('failed'); + expect(Number(outputValue(run.outputs, 'error-count'))).toBeGreaterThan(0); + expect(run.stdout).toContain('::error'); + expect(run.stdout).toContain('SBV005'); + expect(run.stdout).toContain('file=src/billing/invoice.ts'); + // Tracked files stay untouched; only the report directory appears. + const statusAfter = git(fixture.root, 'status', '--porcelain') + .split(/\r?\n/) + .filter((line) => line.trim() !== '') + .filter((line) => !line.includes('.specbridge/action-reports')) + .filter((line) => !line.includes('.github-runtime')); + expect(statusAfter.join('\n')).toBe(statusBefore.trim()); + }); + + it('resolves push events (before...after)', () => { + const fixture = setupVerifyFixture(); + fixture.write('src/settings/store.ts', 'export {};\n'); + fixture.commit('pushed work'); + const before = git(fixture.root, 'rev-parse', 'HEAD~1').trim(); + const after = fixture.head(); + + const run = runBundledAction(fixture.root, { + eventName: 'push', + payload: { before, after }, + sha: after, + }); + expect(run.code).toBe(0); + expect(outputValue(run.outputs, 'result')).toBe('passed'); + }); + + it('workflow_dispatch without refs fails with actionable guidance', () => { + const fixture = setupVerifyFixture(); + const run = runBundledAction(fixture.root, { + eventName: 'workflow_dispatch', + payload: { inputs: {} }, + sha: fixture.head(), + }); + expect(run.code).toBe(1); + expect(run.stdout).toContain('base-ref'); + }); + + it('missing history yields the fetch-depth guidance', () => { + const fixture = setupVerifyFixture(); + const run = runBundledAction(fixture.root, { + eventName: 'pull_request', + payload: { + pull_request: { + base: { sha: 'f'.repeat(40) }, + head: { sha: fixture.head() }, + }, + }, + sha: fixture.head(), + }); + expect(run.code).toBe(1); + expect(`${run.stdout}${run.summary}`).toContain('fetch-depth'); + expect(outputValue(run.outputs, 'result')).toBe('failed'); + }); + + it('enforces the annotation limit with a summary warning', () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.commit('policy'); + for (let index = 0; index < 5; index += 1) { + fixture.write(`outside/file-${index}.ts`, 'export {};\n'); + } + fixture.commit('five outside files'); + const base = git(fixture.root, 'rev-parse', 'HEAD~1').trim(); + + const run = runBundledAction(fixture.root, { + eventName: 'pull_request', + payload: { pull_request: { base: { sha: base }, head: { sha: fixture.head() } } }, + sha: fixture.head(), + inputs: { mode: 'single', spec: VERIFY_SPEC, 'annotation-limit': '2', 'fail-on': 'never' }, + }); + expect(run.code).toBe(0); + const annotationLines = run.stdout + .split(/\r?\n/) + .filter((line) => line.startsWith('::warning') || line.startsWith('::error')); + const limited = annotationLines.filter((line) => line.includes('SBV005')); + expect(limited).toHaveLength(2); + expect(run.stdout).toContain('annotation limit'); + }); + + it('rejects invalid inputs with a clear failure', () => { + const fixture = setupVerifyFixture(); + const run = runBundledAction(fixture.root, { + eventName: 'pull_request', + payload: { pull_request: { base: { sha: fixture.head() }, head: { sha: fixture.head() } } }, + sha: fixture.head(), + inputs: { mode: 'nonsense' }, + }); + expect(run.code).toBe(1); + expect(run.stdout).toContain('single, changed, all'); + }); +}); diff --git a/tests/cli/cli-smoke.test.ts b/tests/cli/cli-smoke.test.ts index 28cb8c5..f139017 100644 --- a/tests/cli/cli-smoke.test.ts +++ b/tests/cli/cli-smoke.test.ts @@ -265,9 +265,9 @@ describe('specbridge compat check', () => { }); describe('planned commands are honest', () => { + // `spec verify` became a real command in v0.4; sync/export stay planned. it.each([ ['spec', 'sync', 'x'], - ['spec', 'verify', 'x'], ['spec', 'export', 'x'], ])('%s %s exits 2 with a not-implemented message', async (...argv) => { const result = await cli(standard, ...argv); @@ -275,6 +275,12 @@ describe('planned commands are honest', () => { expect(result.stderr).toContain('not implemented yet'); expect(result.stderr).toContain('planned'); }); + + it('spec verify is implemented and errors helpfully for an unknown spec', async () => { + const result = await cli(standard, 'spec', 'verify', 'x'); + expect(result.code).toBe(2); + expect(result.stderr).toContain('Spec "x" not found'); + }); }); describe('general CLI behavior', () => { diff --git a/tests/cli/cli-v04-verify.test.ts b/tests/cli/cli-v04-verify.test.ts new file mode 100644 index 0000000..5690435 --- /dev/null +++ b/tests/cli/cli-v04-verify.test.ts @@ -0,0 +1,290 @@ +import { existsSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { runCli } from '../../packages/cli/src/cli'; +import { setupVerifyFixture, VERIFY_SPEC } from '../helpers-verify.js'; +import { FIXED_NOW } from '../helpers.js'; + +/** + * End-to-end CLI tests for the v0.4 verification commands. Everything runs + * in-process against temp git fixtures. + */ + +interface CliResult { + code: number; + stdout: string; + stderr: string; +} + +async function cli(cwd: string, ...argv: string[]): Promise { + const stdout: string[] = []; + const stderr: string[] = []; + const code = await runCli(argv, { + cwd, + out: (line) => stdout.push(`${line}\n`), + outRaw: (text) => stdout.push(text), + err: (line) => stderr.push(`${line}\n`), + now: () => FIXED_NOW, + }); + return { code, stdout: stdout.join(''), stderr: stderr.join('') }; +} + +describe('spec verify — selection and comparison options', () => { + it('verifies a named spec against the working tree by default', async () => { + const fixture = setupVerifyFixture(); + const result = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC); + expect(result.code).toBe(0); + expect(result.stdout).toContain('Spec Drift Verification'); + expect(result.stdout).toContain('working tree vs HEAD'); + expect(result.stdout).toContain('PASSED'); + }); + + it('rejects combined selection modes and missing selection', async () => { + const fixture = setupVerifyFixture(); + const combined = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--all'); + expect(combined.code).toBe(2); + expect(combined.stderr).toContain('mutually exclusive'); + + const none = await cli(fixture.root, 'spec', 'verify'); + expect(none.code).toBe(2); + expect(none.stderr).toContain('--changed'); + }); + + it('rejects combined comparison modes', async () => { + const fixture = setupVerifyFixture(); + const result = await cli( + fixture.root, + 'spec', + 'verify', + VERIFY_SPEC, + '--working-tree', + '--staged', + ); + expect(result.code).toBe(2); + expect(result.stderr).toContain('mutually exclusive'); + }); + + it('supports --staged and --diff explicitly', async () => { + const fixture = setupVerifyFixture(); + fixture.write('src/staged.ts', 'export {};\n'); + const { git } = await import('../helpers-execution.js'); + git(fixture.root, 'add', 'src/staged.ts'); + + const staged = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--staged'); + expect(staged.code).toBe(0); + expect(staged.stdout).toContain('staged changes vs HEAD'); + + const diff = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--diff', 'HEAD...HEAD'); + expect(diff.code).toBe(0); + expect(diff.stdout).toContain('HEAD...HEAD'); + }); + + it('fails clearly on invalid git refs', async () => { + const fixture = setupVerifyFixture(); + const hostile = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--diff', '--evil...HEAD'); + expect(hostile.code).toBe(2); + + const missing = await cli( + fixture.root, + 'spec', + 'verify', + VERIFY_SPEC, + '--diff', + 'origin/nope...HEAD', + ); + expect(missing.code).toBe(3); + expect(missing.stdout).toContain('SBV021'); + }); + + it('--changed and --all selections work end to end', async () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.write('src/settings/store.ts', 'export {};\n'); + const changed = await cli(fixture.root, 'spec', 'verify', '--changed'); + expect(changed.code).toBe(0); + expect(changed.stdout).toContain(VERIFY_SPEC); + + const all = await cli(fixture.root, 'spec', 'verify', '--all'); + expect(all.code).toBe(0); + }); +}); + +describe('spec verify — output formats and thresholds', () => { + it('--json emits a schema-valid report on stdout with no progress noise', async () => { + const fixture = setupVerifyFixture(); + const result = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--json'); + expect(result.code).toBe(0); + const parsed = JSON.parse(result.stdout) as { schemaVersion: string; summary: { result: string } }; + expect(parsed.schemaVersion).toBe('1.0.0'); + expect(parsed.summary.result).toBe('passed'); + }); + + it('--format markdown and html write self-contained reports via --output', async () => { + const fixture = setupVerifyFixture(); + const markdown = await cli( + fixture.root, + 'spec', + 'verify', + VERIFY_SPEC, + '--format', + 'markdown', + '--output', + 'report.md', + ); + expect(markdown.code).toBe(0); + const markdownContent = readFileSync(path.join(fixture.root, 'report.md'), 'utf8'); + expect(markdownContent).toContain('# SpecBridge Verification'); + expect(markdownContent).toContain('**Result:**'); + + const html = await cli( + fixture.root, + 'spec', + 'verify', + VERIFY_SPEC, + '--format', + 'html', + '--output', + 'report.html', + ); + expect(html.code).toBe(0); + const htmlContent = readFileSync(path.join(fixture.root, 'report.html'), 'utf8'); + expect(htmlContent).toContain(''); + expect(htmlContent).not.toContain(' { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.write('elsewhere/file.ts', 'export {};\n'); // SBV005 warning + expect((await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC)).code).toBe(0); + expect( + (await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--fail-on', 'warning')).code, + ).toBe(1); + expect( + (await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--fail-on', 'never')).code, + ).toBe(0); + expect( + (await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC, '--fail-on', 'nonsense')).code, + ).toBe(2); + }); + + it('verification through the CLI is read-only for spec, state, and evidence files', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); + const watched = [ + `.kiro/specs/${VERIFY_SPEC}/requirements.md`, + `.kiro/specs/${VERIFY_SPEC}/design.md`, + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + `.specbridge/state/specs/${VERIFY_SPEC}.json`, + ]; + const before = watched.map((relative) => fixture.read(relative)); + const result = await cli(fixture.root, 'spec', 'verify', VERIFY_SPEC); + expect(result.code).toBe(0); + expect(watched.map((relative) => fixture.read(relative))).toEqual(before); + }); +}); + +describe('spec affected', () => { + it('lists affected specs with match reasons and unmapped warnings', async () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.write('src/settings/store.ts', 'export {};\n'); + fixture.write('src/common/logger.ts', 'export {};\n'); + const result = await cli(fixture.root, 'spec', 'affected', '--working-tree'); + expect(result.code).toBe(0); + expect(result.stdout).toContain(VERIFY_SPEC); + expect(result.stdout).toContain('impact area src/settings/**'); + expect(result.stdout).toContain('src/common/logger.ts does not map to any spec'); + }); + + it('--json emits machine-readable results and never runs commands', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [] } }); + fixture.commit('baseline'); // config committed + fixture.write('src/anything.ts', 'export {};\n'); + const result = await cli(fixture.root, 'spec', 'affected', '--working-tree', '--json'); + expect(result.code).toBe(0); + const parsed = JSON.parse(result.stdout) as { + schema: string; + data: { unmapped: string[]; affected: unknown[] }; + }; + expect(parsed.schema).toBe('specbridge.spec-affected/1'); + expect(parsed.data.unmapped).toContain('src/anything.ts'); + expect(existsSync(path.join(fixture.root, '.specbridge', 'reports'))).toBe(false); + }); +}); + +describe('spec policy', () => { + it('init proposes areas from design paths and evidence, and never overwrites', async () => { + const fixture = setupVerifyFixture(); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/design.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/design.md`)}\nThe store lives in \`src/settings/store.ts\`.\n`, + ); + fixture.writeVerifiedEvidence('1', { + changedFiles: [ + { path: 'tests/settings.test.ts', changeType: 'added', preExisting: false, modifiedDuringRun: true }, + ], + }); + + const dryRun = await cli(fixture.root, 'spec', 'policy', 'init', VERIFY_SPEC, '--mode', 'strict', '--dry-run'); + expect(dryRun.code).toBe(0); + expect(dryRun.stdout).toContain('dry run'); + expect(existsSync(path.join(fixture.root, '.specbridge', 'policies', `${VERIFY_SPEC}.json`))).toBe(false); + + const real = await cli(fixture.root, 'spec', 'policy', 'init', VERIFY_SPEC, '--mode', 'strict'); + expect(real.code).toBe(0); + const written = JSON.parse( + readFileSync(path.join(fixture.root, '.specbridge', 'policies', `${VERIFY_SPEC}.json`), 'utf8'), + ) as { mode: string; impactAreas: string[] }; + expect(written.mode).toBe('strict'); + expect(written.impactAreas).toContain('src/settings/**'); + expect(written.impactAreas).toContain('tests/**'); + + const again = await cli(fixture.root, 'spec', 'policy', 'init', VERIFY_SPEC); + expect(again.code).toBe(2); + expect(again.stderr).toContain('never overwrites'); + }); + + it('show and validate report the effective policy and its problems', async () => { + const fixture = setupVerifyFixture(); + const missing = await cli(fixture.root, 'spec', 'policy', 'validate', VERIFY_SPEC); + expect(missing.code).toBe(2); + + fixture.writePolicy({ mode: 'strict', impactAreas: ['src/**'], requiredVerificationCommands: ['test'] }); + const show = await cli(fixture.root, 'spec', 'policy', 'show', VERIFY_SPEC); + expect(show.code).toBe(0); + expect(show.stdout).toContain('Mode: strict'); + expect(show.stdout).toContain('.git/**'); + + // "test" is not configured — validate flags it. + const invalid = await cli(fixture.root, 'spec', 'policy', 'validate', VERIFY_SPEC); + expect(invalid.code).toBe(1); + expect(invalid.stdout).toContain('SBV013'); + + fixture.writePolicy({ mode: 'strict', impactAreas: ['src/**'] }); + const valid = await cli(fixture.root, 'spec', 'policy', 'validate', VERIFY_SPEC); + expect(valid.code).toBe(0); + expect(valid.stdout).toContain('valid'); + }); +}); + +describe('verify rules inspection', () => { + it('lists all 25 rules and explains one', async () => { + const fixture = setupVerifyFixture(); + const rules = await cli(fixture.root, 'verify', 'rules'); + expect(rules.code).toBe(0); + expect(rules.stdout).toContain('SBV001'); + expect(rules.stdout).toContain('SBV025'); + + const explain = await cli(fixture.root, 'verify', 'explain', 'SBV005'); + expect(explain.code).toBe(0); + expect(explain.stdout).toContain('warning in advisory mode, error in strict mode'); + expect(explain.stdout).toContain('Triggered when'); + + const unknown = await cli(fixture.root, 'verify', 'explain', 'SBV999'); + expect(unknown.code).toBe(2); + }); +}); diff --git a/tests/compatibility/traceability.test.ts b/tests/compatibility/traceability.test.ts new file mode 100644 index 0000000..0f83ebd --- /dev/null +++ b/tests/compatibility/traceability.test.ts @@ -0,0 +1,209 @@ +import { describe, expect, it } from 'vitest'; +import { + MarkdownDocument, + buildRequirementCatalog, + canonicalRequirementRef, + extractPathReferences, + extractTaskRequirementReferences, + isLikelyNonRequirementTask, + mentionsTests, + parseRequirements, + parseTasks, + taskMentionsTests, +} from '@specbridge/compat-kiro'; + +describe('canonicalRequirementRef', () => { + it('normalizes the documented identifier shapes', () => { + expect(canonicalRequirementRef('R1')).toBe('1'); + expect(canonicalRequirementRef('r1.1')).toBe('1.1'); + expect(canonicalRequirementRef('REQ-001')).toBe('1'); + expect(canonicalRequirementRef('Requirement 1')).toBe('1'); + expect(canonicalRequirementRef('AC-1')).toBe('1'); + expect(canonicalRequirementRef('AC1.2')).toBe('1.2'); + expect(canonicalRequirementRef('1.1')).toBe('1.1'); + expect(canonicalRequirementRef('2-3')).toBe('2.3'); + expect(canonicalRequirementRef('REQ-010.02')).toBe('10.2'); + }); + + it('rejects non-identifier text', () => { + expect(canonicalRequirementRef('TBD')).toBeUndefined(); + expect(canonicalRequirementRef('see above')).toBeUndefined(); + expect(canonicalRequirementRef('')).toBeUndefined(); + expect(canonicalRequirementRef('R')).toBeUndefined(); + }); +}); + +const REQUIREMENTS = `# Requirements Document + +## Requirements + +### Requirement 1: Persist settings + +**User Story:** As a user, I want settings saved, so that they survive restarts. + +#### Acceptance Criteria + +1. WHEN the user saves THEN the system SHALL persist it. +2. AC-9: IF persistence fails THEN the system SHALL be tested for rollback. + +### REQ-002: Export data + +The export path must be covered by integration tests. + +1. The system exports settings as JSON. +`; + +describe('buildRequirementCatalog', () => { + const document = MarkdownDocument.fromText(REQUIREMENTS, 'requirements.md'); + const model = parseRequirements(document); + const catalog = buildRequirementCatalog(model, document); + + it('extracts requirement IDs from the tolerant parser', () => { + const requirement = catalog.byCanonical.get('1'); + expect(requirement?.kind).toBe('requirement'); + expect(requirement?.displayId).toBe('1'); + expect(requirement?.line).toBeGreaterThan(0); + }); + + it('extracts acceptance criterion IDs with source lines', () => { + const criterion = catalog.byCanonical.get('1.1'); + expect(criterion?.kind).toBe('criterion'); + expect(criterion?.requirementCanonical).toBe('1'); + const documentLine = document.lineAt(criterion?.line ?? 0).text; + expect(documentLine).toContain('WHEN the user saves'); + }); + + it('recognizes supplemental REQ-### headings the parser does not treat as requirements', () => { + const supplemental = catalog.byCanonical.get('2'); + expect(supplemental?.method).toBe('id-heading'); + expect(supplemental?.displayId).toBe('REQ-002'); + expect(catalog.byCanonical.get('2.1')?.kind).toBe('criterion'); + }); + + it('records explicit AC markers as deterministic aliases', () => { + const alias = catalog.byCanonical.get('9'); + expect(alias?.method).toBe('explicit-ac-marker'); + expect(alias?.requirementCanonical).toBe('1'); + }); + + it('detects test-required language heuristically', () => { + expect(catalog.byCanonical.get('1.2')?.testRequired).toBe(true); + expect(catalog.byCanonical.get('1.1')?.testRequired).toBe(false); + expect(catalog.byCanonical.get('2')?.testRequired).toBe(true); + expect(mentionsTests('the latest value')).toBe(false); + }); +}); + +const TASKS = `# Implementation Plan + +- [ ] 1. Build the store + - _Requirements: 1.1, 1.2_ +- [ ] 2. Wire the API [R1] + - Requirements: REQ-002 +- [ ] 3. Polish integration — supports 1.2 + - Implements REQ-001 +- [ ] 4. Write unit tests for the store +- [ ] 5. Update documentation and changelog +`; + +describe('extractTaskRequirementReferences', () => { + const document = MarkdownDocument.fromText(TASKS, 'tasks.md'); + const model = parseTasks(document); + const references = extractTaskRequirementReferences(document, model); + + it('extracts the documented underscore form with line numbers', () => { + const refs = references.filter((ref) => ref.taskId === '1'); + expect(refs.map((ref) => ref.canonical).sort()).toEqual(['1.1', '1.2']); + expect(refs[0]?.method).toBe('underscore-refs'); + expect(refs[0]?.confidence).toBe('deterministic'); + expect(document.lineAt(refs[0]?.line ?? 0).text).toContain('_Requirements:'); + }); + + it('extracts bracket references and bare Requirements: lines', () => { + const refs = references.filter((ref) => ref.taskId === '2'); + const methods = new Set(refs.map((ref) => ref.method)); + expect(methods.has('bracket-ref')).toBe(true); + expect(methods.has('refs-line')).toBe(true); + expect(refs.some((ref) => ref.canonical === '1')).toBe(true); + expect(refs.some((ref) => ref.canonical === '2')).toBe(true); + }); + + it('extracts keyword references as heuristic', () => { + const refs = references.filter((ref) => ref.taskId === '3'); + expect(refs.length).toBeGreaterThanOrEqual(2); + for (const ref of refs) expect(ref.confidence).toBe('heuristic'); + expect(refs.map((ref) => ref.canonical).sort()).toEqual(['1', '1.2']); + }); + + it('leaves unlinked tasks without references', () => { + expect(references.filter((ref) => ref.taskId === '4')).toHaveLength(0); + }); + + it('detects test language on tasks and excludes chore-like tasks', () => { + const testTask = model.allTasks.find((task) => task.id === '4'); + const choreTask = model.allTasks.find((task) => task.id === '5'); + expect(taskMentionsTests(document, model, testTask!)).toBe(true); + expect(taskMentionsTests(document, model, choreTask!)).toBe(false); + expect(isLikelyNonRequirementTask(choreTask!)).toBe(true); + expect(isLikelyNonRequirementTask(testTask!)).toBe(false); + }); +}); + +describe('extractPathReferences', () => { + const DESIGN = `# Design + +The store lives in \`src/settings/store.ts\` and is covered by +[the test plan](docs/testing.md). Windows authors sometimes write +\`src\\settings\\windows.ts\`. Impact spans \`src/settings/**\`. + +Not paths: \`npm install\`, \`foo(bar)\`, [site](https://example.com), +\`config.json\`, \`../outside/escape.ts\`, [anchor](#section). +`; + const references = extractPathReferences(MarkdownDocument.fromText(DESIGN, 'design.md')); + const paths = references.map((ref) => ref.path); + + it('extracts backtick paths and markdown links with lines and methods', () => { + expect(paths).toContain('src/settings/store.ts'); + expect(paths).toContain('docs/testing.md'); + const link = references.find((ref) => ref.path === 'docs/testing.md'); + expect(link?.method).toBe('markdown-link'); + const backtick = references.find((ref) => ref.path === 'src/settings/store.ts'); + expect(backtick?.method).toBe('backtick-path'); + expect(backtick?.confidence).toBe('deterministic'); + }); + + it('normalizes Windows separators', () => { + expect(paths).toContain('src/settings/windows.ts'); + }); + + it('marks glob patterns without treating them as files', () => { + const glob = references.find((ref) => ref.path === 'src/settings/**'); + expect(glob?.isGlob).toBe(true); + }); + + it('rejects URLs, code tokens, bare filenames, anchors, and traversal', () => { + expect(paths).not.toContain('npm install'); + expect(paths.some((p) => p.includes('example.com'))).toBe(false); + expect(paths).not.toContain('config.json'); + expect(paths.some((p) => p.includes('..'))).toBe(false); + }); +}); + +describe('non-English content', () => { + it('preserves and extracts UTF-8 identifiers and titles', () => { + const document = MarkdownDocument.fromText( + `# Anforderungen + +### Requirement 1: Einstellungen dauerhaft speichern + +#### Acceptance Criteria + +1. WENN gespeichert wird, DANN SHALL das System den Wert persistieren. +`, + 'requirements.md', + ); + const catalog = buildRequirementCatalog(parseRequirements(document), document); + expect(catalog.byCanonical.get('1')?.title).toBe('Einstellungen dauerhaft speichern'); + expect(catalog.byCanonical.get('1.1')).toBeDefined(); + }); +}); diff --git a/tests/drift/comparison.test.ts b/tests/drift/comparison.test.ts new file mode 100644 index 0000000..ae32b17 --- /dev/null +++ b/tests/drift/comparison.test.ts @@ -0,0 +1,146 @@ +import { mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { + isSafeGitRef, + parseDiffRange, + parseNameStatusZ, + parseNumstatZ, + resolveComparison, +} from '@specbridge/drift'; +import { emptyTempDir } from '../helpers.js'; +import { git, initGitRepo } from '../helpers-execution.js'; + +describe('git ref safety', () => { + it('accepts normal refs and rejects option-like or hostile input', () => { + expect(isSafeGitRef('origin/main')).toBe(true); + expect(isSafeGitRef('HEAD~1')).toBe(true); + expect(isSafeGitRef('v1.0.0')).toBe(true); + expect(isSafeGitRef('feature/UTF-8-ünïcode')).toBe(true); + expect(isSafeGitRef('--upload-pack=evil')).toBe(false); + expect(isSafeGitRef('-C')).toBe(false); + expect(isSafeGitRef('main branch')).toBe(false); + expect(isSafeGitRef('a\0b')).toBe(false); + expect(isSafeGitRef('')).toBe(false); + }); + + it('parses base...head and base..head ranges', () => { + expect(parseDiffRange('origin/main...HEAD')).toEqual({ base: 'origin/main', head: 'HEAD' }); + expect(parseDiffRange('origin/main...')).toEqual({ base: 'origin/main', head: 'HEAD' }); + expect(parseDiffRange('a..b')).toEqual({ base: 'a', head: 'b' }); + expect(parseDiffRange('justoneref')).toBeUndefined(); + expect(parseDiffRange('...HEAD')).toBeUndefined(); + }); +}); + +describe('-z output parsing', () => { + it('parses name-status with renames, UTF-8 paths, and spaces', () => { + const raw = ['M', 'src/päth with space.ts', 'R100', 'old/name.ts', 'new/name.ts', 'A', 'added.md', 'D', 'gone.md', ''].join( + '\0', + ); + const files = parseNameStatusZ(raw); + expect(files).toEqual([ + { path: 'src/päth with space.ts', changeType: 'modified', binary: false, symlinkOutsideRepository: false }, + { path: 'new/name.ts', oldPath: 'old/name.ts', changeType: 'renamed', binary: false, symlinkOutsideRepository: false }, + { path: 'added.md', changeType: 'added', binary: false, symlinkOutsideRepository: false }, + { path: 'gone.md', changeType: 'deleted', binary: false, symlinkOutsideRepository: false }, + ]); + }); + + it('parses numstat including binary markers and rename form', () => { + const raw = ['3\t1\tsrc/a.ts', '-\t-\tassets/logo.png', '2\t2\t', 'old/name.ts', 'new/name.ts', ''].join('\0'); + const stats = parseNumstatZ(raw); + expect(stats.get('src/a.ts')).toEqual({ insertions: 3, deletions: 1, binary: false }); + expect(stats.get('assets/logo.png')).toEqual({ binary: true }); + expect(stats.get('new/name.ts')).toEqual({ insertions: 2, deletions: 2, binary: false }); + }); +}); + +function makeRepo(): string { + const root = emptyTempDir(); + writeFileSync(path.join(root, 'keep.txt'), 'baseline\n', 'utf8'); + mkdirSync(path.join(root, 'src'), { recursive: true }); + writeFileSync(path.join(root, 'src', 'app.ts'), 'export const app = 1;\n', 'utf8'); + writeFileSync(path.join(root, 'src', 'old-name.ts'), 'export const legacy = true;\n', 'utf8'); + initGitRepo(root); + return root; +} + +describe('resolveComparison (live git)', () => { + it('working tree covers modified, deleted, untracked, and binary files', async () => { + const root = makeRepo(); + writeFileSync(path.join(root, 'src', 'app.ts'), 'export const app = 2;\n', 'utf8'); + rmSync(path.join(root, 'keep.txt')); + writeFileSync(path.join(root, 'new-untracked.txt'), 'hello\n', 'utf8'); + writeFileSync(path.join(root, 'binary.bin'), Buffer.from([0, 1, 2, 3, 0, 255])); + + const result = await resolveComparison(root, { mode: 'working-tree' }); + expect(result.ok).toBe(true); + const byPath = new Map(result.changedFiles.map((file) => [file.path, file])); + expect(byPath.get('src/app.ts')?.changeType).toBe('modified'); + expect(byPath.get('src/app.ts')?.insertions).toBe(1); + expect(byPath.get('keep.txt')?.changeType).toBe('deleted'); + expect(byPath.get('new-untracked.txt')?.changeType).toBe('untracked'); + expect(byPath.get('binary.bin')?.changeType).toBe('untracked'); + expect(byPath.get('binary.bin')?.binary).toBe(true); + // Deterministic path ordering. + const paths = result.changedFiles.map((file) => file.path); + expect(paths).toEqual([...paths].sort((a, b) => a.localeCompare(b, 'en'))); + }); + + it('staged mode sees exactly what is staged', async () => { + const root = makeRepo(); + writeFileSync(path.join(root, 'src', 'app.ts'), 'export const app = 3;\n', 'utf8'); + writeFileSync(path.join(root, 'unstaged.txt'), 'not staged\n', 'utf8'); + git(root, 'add', 'src/app.ts'); + + const result = await resolveComparison(root, { mode: 'staged' }); + expect(result.ok).toBe(true); + expect(result.changedFiles.map((file) => file.path)).toEqual(['src/app.ts']); + }); + + it('diff mode resolves SHAs and detects renames', async () => { + const root = makeRepo(); + renameSync(path.join(root, 'src', 'old-name.ts'), path.join(root, 'src', 'new-name.ts')); + git(root, 'add', '-A'); + git(root, 'commit', '-q', '-m', 'rename'); + + const result = await resolveComparison(root, { mode: 'diff', base: 'HEAD~1', head: 'HEAD' }); + expect(result.ok).toBe(true); + expect(result.descriptor.baseSha).toMatch(/^[0-9a-f]{40}$/); + expect(result.descriptor.headSha).toMatch(/^[0-9a-f]{40}$/); + const renamed = result.changedFiles.find((file) => file.changeType === 'renamed'); + expect(renamed?.path).toBe('src/new-name.ts'); + expect(renamed?.oldPath).toBe('src/old-name.ts'); + }); + + it('unresolvable refs fail structurally with fetch guidance, never throw', async () => { + const root = makeRepo(); + const result = await resolveComparison(root, { + mode: 'diff', + base: 'origin/does-not-exist', + head: 'HEAD', + }); + expect(result.ok).toBe(false); + expect(result.failure?.reason).toBe('ref-not-found'); + expect(result.failure?.message).toContain('origin/does-not-exist'); + expect(result.failure?.message).toContain('never fetches'); + }); + + it('option-injection refs are rejected before git ever runs', async () => { + const root = makeRepo(); + const result = await resolveComparison(root, { + mode: 'diff', + base: '--upload-pack=evil', + head: 'HEAD', + }); + expect(result.ok).toBe(false); + expect(result.failure?.reason).toBe('invalid-ref'); + }); + + it('a non-repository directory fails with a clear reason', async () => { + const result = await resolveComparison(emptyTempDir(), { mode: 'working-tree' }); + expect(result.ok).toBe(false); + expect(result.failure?.reason).toBe('not-a-repository'); + }); +}); diff --git a/tests/drift/evidence-freshness.test.ts b/tests/drift/evidence-freshness.test.ts new file mode 100644 index 0000000..76c9810 --- /dev/null +++ b/tests/drift/evidence-freshness.test.ts @@ -0,0 +1,243 @@ +import { describe, expect, it } from 'vitest'; +import type { EvidenceFreshnessContext, TaskEvidenceRecord } from '@specbridge/evidence'; +import { + assessEvidenceRecord, + assessTaskEvidence, + evidencePathEscapesRepository, + reusableCommandPass, +} from '@specbridge/evidence'; + +/** + * Deterministic evidence freshness: hashes, task identity, timestamps, and + * repository paths — never model claims. + */ + +const NOW = new Date('2026-07-12T12:00:00.000Z'); +const HASH_A = 'a'.repeat(64); +const HASH_B = 'b'.repeat(64); +const FINGERPRINT = 'c'.repeat(64); + +function record(overrides: Partial = {}): TaskEvidenceRecord { + return { + schemaVersion: '1.0.0', + runId: 'run-1', + specName: 'settings-persistence', + taskId: '1', + status: 'verified', + runner: 'mock', + repository: { headBefore: 'abc123', headAfter: 'abc123', dirtyBefore: false, dirtyAfter: true }, + changedFiles: [ + { path: 'src/store.ts', changeType: 'modified', preExisting: false, modifiedDuringRun: true }, + ], + verificationCommands: [ + { name: 'test', argv: ['node', '-e', '0'], required: true, exitCode: 0, durationMs: 5, passed: true }, + ], + verificationSkipped: false, + runnerClaims: { changedFiles: [], commandsReported: [], testsReported: [] }, + violations: [], + warnings: [], + evaluatedAt: '2026-07-12T10:00:00.000Z', + specContext: { + documentHash: HASH_A, + designHash: HASH_A, + tasksPlanHash: HASH_A, + taskFingerprint: FINGERPRINT, + taskText: '- [ ] 1. Build the store', + }, + ...overrides, + }; +} + +function context(overrides: Partial = {}): EvidenceFreshnessContext { + return { + specName: 'settings-persistence', + approved: { documentHash: HASH_A, designHash: HASH_A, tasksPlanHash: HASH_A }, + approvedAt: { + document: '2026-07-12T09:00:00.000Z', + design: '2026-07-12T09:00:01.000Z', + tasks: '2026-07-12T09:00:02.000Z', + }, + tasks: new Map([ + [ + '1', + { + fingerprint: FINGERPRINT, + title: 'Build the store', + rawLineText: '- [x] 1. Build the store', + state: 'done', + }, + ], + ]), + now: NOW, + ...overrides, + }; +} + +describe('assessEvidenceRecord', () => { + it('accepts fresh verified evidence (checkbox progress does not matter)', () => { + const assessment = assessEvidenceRecord(record(), context()); + expect(assessment.validity).toBe('valid'); + expect(assessment.accepted).toBe(true); + expect(assessment.reasons).toHaveLength(0); + }); + + it('flags spec-name mismatches as invalid', () => { + const assessment = assessEvidenceRecord(record({ specName: 'other-spec' }), context()); + expect(assessment.validity).toBe('invalid'); + expect(assessment.reasons[0]?.code).toBe('spec-name-mismatch'); + }); + + it('flags evidence paths escaping the repository (SBV024 source)', () => { + for (const bad of ['../outside.ts', '/etc/passwd', 'C:/Windows/system32.dll', 'a/../../b']) { + expect(evidencePathEscapesRepository(bad)).toBe(true); + const assessment = assessEvidenceRecord( + record({ + changedFiles: [ + { path: bad, changeType: 'modified', preExisting: false, modifiedDuringRun: true }, + ], + }), + context(), + ); + expect(assessment.validity).toBe('invalid'); + expect(assessment.pathViolations).toContain(bad); + } + expect(evidencePathEscapesRepository('src/inside.ts')).toBe(false); + }); + + it('detects changed approved hashes as stale with precise codes', () => { + const cases: [Partial, string][] = [ + [{ documentHash: HASH_B, designHash: HASH_A, tasksPlanHash: HASH_A }, 'document-hash-changed'], + [{ documentHash: HASH_A, designHash: HASH_B, tasksPlanHash: HASH_A }, 'design-hash-changed'], + [{ documentHash: HASH_A, designHash: HASH_A, tasksPlanHash: HASH_B }, 'plan-hash-changed'], + ]; + for (const [approved, code] of cases) { + const assessment = assessEvidenceRecord(record(), context({ approved: approved as never })); + expect(assessment.validity).toBe('stale'); + expect(assessment.reasons.map((reason) => reason.code)).toContain(code); + } + }); + + it('treats a no-longer-approved stage as stale', () => { + const assessment = assessEvidenceRecord( + record(), + context({ approved: { designHash: HASH_A, tasksPlanHash: HASH_A } }), + ); + expect(assessment.validity).toBe('stale'); + expect(assessment.reasons.map((reason) => reason.code)).toContain('stage-not-approved'); + }); + + it('detects changed task fingerprints as stale', () => { + const changed = context(); + changed.tasks.set('1', { + fingerprint: 'd'.repeat(64), + title: 'Build the RENAMED store', + rawLineText: '- [x] 1. Build the RENAMED store', + state: 'done', + }); + const assessment = assessEvidenceRecord(record(), changed); + expect(assessment.validity).toBe('stale'); + expect(assessment.reasons.map((reason) => reason.code)).toContain('task-identity-changed'); + }); + + it('falls back to approval timestamps for legacy v0.3 records', () => { + const legacy = record(); + delete (legacy as Record)['specContext']; + // Approved before the evidence: fine. + expect(assessEvidenceRecord(legacy, context()).validity).toBe('valid'); + // Re-approved after the evidence: stale. + const reapproved = context({ + approvedAt: { document: '2026-07-12T11:00:00.000Z' }, + }); + const assessment = assessEvidenceRecord(legacy, reapproved); + expect(assessment.validity).toBe('stale'); + expect(assessment.reasons.map((reason) => reason.code)).toContain('approved-after-evidence'); + }); + + it('flags diverged commit lineage and notes unknown lineage', () => { + const diverged = assessEvidenceRecord( + record(), + context({ ancestry: new Map([['abc123', 'not-ancestor']]) }), + ); + expect(diverged.validity).toBe('stale'); + expect(diverged.reasons.map((reason) => reason.code)).toContain('history-diverged'); + + const unknown = assessEvidenceRecord( + record(), + context({ ancestry: new Map([['abc123', 'unknown']]) }), + ); + expect(unknown.validity).toBe('valid'); + expect(unknown.notes.some((note) => note.includes('shallow'))).toBe(true); + }); + + it('validates manual acceptance structurally and labels it', () => { + const manual = assessEvidenceRecord( + record({ + status: 'manually-accepted', + manualAcceptance: { + actor: 'local-user', + reason: 'verified by hand', + acceptedAt: '2026-07-12T10:30:00.000Z', + }, + }), + context(), + ); + expect(manual.validity).toBe('valid'); + expect(manual.manual).toBe(true); + + const malformed = assessEvidenceRecord(record({ status: 'manually-accepted' }), context()); + expect(malformed.validity).toBe('invalid'); + expect(malformed.reasons.map((reason) => reason.code)).toContain('manual-record-malformed'); + }); + + it('never counts model claims: non-accepted statuses are not evidence of completion', () => { + const claimed = record({ + status: 'implemented-unverified', + runnerClaims: { + outcome: 'completed', + summary: 'the model says everything works', + changedFiles: ['src/store.ts'], + commandsReported: ['pnpm test'], + testsReported: [{ name: 'all', status: 'passed' }], + }, + }); + const assessment = assessEvidenceRecord(claimed, context()); + expect(assessment.accepted).toBe(false); + expect(assessment.validity).toBe('not-accepted'); + }); +}); + +describe('assessTaskEvidence buckets', () => { + it('the newest accepted record decides the bucket', () => { + const older = record({ runId: 'run-1', evaluatedAt: '2026-07-12T09:30:00.000Z' }); + const newerStale = record({ + runId: 'run-2', + evaluatedAt: '2026-07-12T10:30:00.000Z', + specContext: { ...record().specContext, tasksPlanHash: HASH_B }, + }); + const assessment = assessTaskEvidence('1', [older, newerStale], context()); + expect(assessment.bucket).toBe('stale'); + expect(assessment.best?.record.runId).toBe('run-2'); + }); + + it('reports missing when no accepted record exists', () => { + const failed = record({ status: 'failed' }); + expect(assessTaskEvidence('1', [failed], context()).bucket).toBe('missing'); + expect(assessTaskEvidence('1', [], context()).bucket).toBe('missing'); + }); +}); + +describe('reusableCommandPass', () => { + it('reuses a passing command only from valid evidence at the exact current HEAD', () => { + const assessment = assessEvidenceRecord(record(), context()); + expect(reusableCommandPass([assessment], 'test', 'abc123')?.runId).toBe('run-1'); + expect(reusableCommandPass([assessment], 'test', 'other')).toBeUndefined(); + expect(reusableCommandPass([assessment], 'lint', 'abc123')).toBeUndefined(); + expect(reusableCommandPass([assessment], 'test', undefined)).toBeUndefined(); + + const stale = assessEvidenceRecord( + record({ specContext: { ...record().specContext, tasksPlanHash: HASH_B } }), + context(), + ); + expect(reusableCommandPass([stale], 'test', 'abc123')).toBeUndefined(); + }); +}); diff --git a/tests/drift/rule-engine.test.ts b/tests/drift/rule-engine.test.ts new file mode 100644 index 0000000..713610f --- /dev/null +++ b/tests/drift/rule-engine.test.ts @@ -0,0 +1,159 @@ +import { describe, expect, it } from 'vitest'; +import { + compareVerificationDiagnostics, + sortVerificationDiagnostics, + verificationDiagnosticSchema, +} from '@specbridge/core'; +import type { VerificationDiagnostic } from '@specbridge/core'; +import { + builtInVerificationRules, + describeDefaultSeverity, + findRule, + makeDiagnostic, + resolveGlobalRuleConfig, + resolveRuleConfig, +} from '@specbridge/drift'; + +describe('built-in rule registry', () => { + const rules = builtInVerificationRules(); + + it('contains exactly SBV001–SBV025 in order, with unique stable IDs', () => { + const ids = rules.map((rule) => rule.id); + const expected = Array.from({ length: 25 }, (_, index) => `SBV${String(index + 1).padStart(3, '0')}`); + expect(ids).toEqual(expected); + expect(new Set(ids).size).toBe(ids.length); + }); + + it('is deterministic across calls', () => { + const again = builtInVerificationRules(); + expect(again.map((rule) => rule.id)).toEqual(rules.map((rule) => rule.id)); + expect(again.map((rule) => rule.title)).toEqual(rules.map((rule) => rule.title)); + }); + + it('heuristic rules never default to error in any mode', () => { + for (const rule of rules) { + if (rule.confidence !== 'heuristic') continue; + expect(rule.defaultSeverity.advisory, rule.id).not.toBe('error'); + expect(rule.defaultSeverity.strict, rule.id).not.toBe('error'); + } + }); + + it('every rule documents its trigger and resolution for verify explain', () => { + for (const rule of rules) { + expect(rule.title.length, rule.id).toBeGreaterThan(0); + expect(rule.triggeredWhen.length, rule.id).toBeGreaterThan(20); + expect(rule.resolution.length, rule.id).toBeGreaterThan(20); + expect(describeDefaultSeverity(rule).length).toBeGreaterThan(0); + } + }); + + it('findRule resolves case-insensitively and rejects unknown ids', () => { + expect(findRule('sbv005')?.id).toBe('SBV005'); + expect(findRule('SBV999')).toBeUndefined(); + }); +}); + +describe('rule configuration resolution', () => { + const rule = findRule('SBV005')!; // advisory: warning, strict: error + + it('resolves mode-dependent defaults', () => { + expect(resolveRuleConfig(rule, { mode: 'advisory', ruleOverrides: {} }).severity).toBe('warning'); + expect(resolveRuleConfig(rule, { mode: 'strict', ruleOverrides: {} }).severity).toBe('error'); + }); + + it('applies explicit severity overrides and disabling', () => { + const overridden = resolveRuleConfig(rule, { + mode: 'advisory', + ruleOverrides: { SBV005: { enabled: true, severity: 'error' } }, + }); + expect(overridden.severity).toBe('error'); + expect(overridden.overridden).toBe(true); + + const disabled = resolveRuleConfig(rule, { + mode: 'strict', + ruleOverrides: { SBV005: { enabled: false } }, + }); + expect(disabled.enabled).toBe(false); + }); + + it('global rules take the strictest severity and stay enabled unless all disable them', () => { + const sbv014 = findRule('SBV014')!; + const strictest = resolveGlobalRuleConfig(sbv014, [ + { mode: 'advisory', ruleOverrides: {} }, + { mode: 'advisory', ruleOverrides: { SBV014: { enabled: true, severity: 'error' } } }, + ]); + expect(strictest.severity).toBe('error'); + + const oneDisables = resolveGlobalRuleConfig(sbv014, [ + { mode: 'advisory', ruleOverrides: { SBV014: { enabled: false } } }, + { mode: 'advisory', ruleOverrides: {} }, + ]); + expect(oneDisables.enabled).toBe(true); + + const allDisable = resolveGlobalRuleConfig(sbv014, [ + { mode: 'advisory', ruleOverrides: { SBV014: { enabled: false } } }, + { mode: 'strict', ruleOverrides: { SBV014: { enabled: false } } }, + ]); + expect(allDisable.enabled).toBe(false); + }); +}); + +describe('diagnostic construction and ordering', () => { + const rule = findRule('SBV005')!; + + it('makeDiagnostic produces schema-valid diagnostics with source locations', () => { + const diagnostic = makeDiagnostic({ + rule, + severity: 'error', + message: 'src/billing/BillingService.ts is outside the declared impact areas.', + specName: 'notification-preferences', + file: { path: 'src/billing/BillingService.ts', line: 12, column: 3 }, + evidence: { declaredImpactAreas: ['src/notifications/**'] }, + }); + expect(() => verificationDiagnosticSchema.parse(diagnostic)).not.toThrow(); + expect(diagnostic.file).toEqual({ path: 'src/billing/BillingService.ts', line: 12, column: 3 }); + expect(diagnostic.remediation).toBe(rule.resolution); + expect(diagnostic.taskId).toBeNull(); + expect(diagnostic.confidence).toBe('deterministic'); + }); + + it('sorts deterministically: severity, rule, file, line, task, message', () => { + const base = (overrides: Partial): VerificationDiagnostic => + verificationDiagnosticSchema.parse({ + schemaVersion: '1.0.0', + ruleId: 'SBV005', + title: 't', + severity: 'warning', + category: 'impact-area', + message: 'm', + remediation: 'r', + specName: null, + taskId: null, + requirementId: null, + file: null, + evidence: {}, + confidence: 'deterministic', + ...overrides, + }); + const diagnostics = [ + base({ severity: 'info', message: 'z' }), + base({ severity: 'error', ruleId: 'SBV009' }), + base({ severity: 'error', ruleId: 'SBV002' }), + base({ file: { path: 'b.ts', line: 2, column: null } }), + base({ file: { path: 'b.ts', line: 1, column: null } }), + base({ file: { path: 'a.ts', line: 9, column: null } }), + ]; + const sorted = sortVerificationDiagnostics(diagnostics); + expect(sorted.map((d) => `${d.severity}:${d.ruleId}:${d.file?.path ?? '-'}:${d.file?.line ?? 0}`)).toEqual([ + 'error:SBV002:-:0', + 'error:SBV009:-:0', + 'warning:SBV005:a.ts:9', + 'warning:SBV005:b.ts:1', + 'warning:SBV005:b.ts:2', + 'info:SBV005:-:0', + ]); + // Stable under re-sort. + expect(sortVerificationDiagnostics(sorted)).toEqual(sorted); + expect(compareVerificationDiagnostics(sorted[0]!, sorted[0]!)).toBe(0); + }); +}); diff --git a/tests/drift/task-plan-hash.test.ts b/tests/drift/task-plan-hash.test.ts new file mode 100644 index 0000000..aa27583 --- /dev/null +++ b/tests/drift/task-plan-hash.test.ts @@ -0,0 +1,89 @@ +import { describe, expect, it } from 'vitest'; +import { MarkdownDocument, normalizedTaskPlanText, taskFingerprint, taskPlanHash } from '@specbridge/compat-kiro'; + +/** + * Hash semantics v2: the plan hash ignores exactly one thing — recognized + * checkbox state characters. Everything else is byte-significant. + */ + +const PLAN = `# Implementation Plan + +- [ ] 1. First task + - _Requirements: 1.1_ +- [ ] 2. Parent task + - [ ] 2.1 Child task + - _Requirements: 1.2_ +- [ ]* 3. Optional task +`; + +function hashOf(text: string): string { + return taskPlanHash(MarkdownDocument.fromText(text)); +} + +describe('normalized task-plan hashing (semantics v2)', () => { + it('checkbox-only progress keeps the plan hash stable', () => { + const progressed = PLAN.replace('- [ ] 1.', '- [x] 1.').replace('- [ ] 2.1', '- [x] 2.1'); + expect(hashOf(progressed)).toBe(hashOf(PLAN)); + }); + + it('in-progress and uppercase states normalize like done', () => { + expect(hashOf(PLAN.replace('- [ ] 1.', '- [-] 1.'))).toBe(hashOf(PLAN)); + expect(hashOf(PLAN.replace('- [ ] 1.', '- [X] 1.'))).toBe(hashOf(PLAN)); + expect(hashOf(PLAN.replace('- [ ] 1.', '- [~] 1.'))).toBe(hashOf(PLAN)); + }); + + it('task text changes invalidate the plan hash', () => { + expect(hashOf(PLAN.replace('First task', 'First task renamed'))).not.toBe(hashOf(PLAN)); + }); + + it('task ID changes invalidate the plan hash', () => { + expect(hashOf(PLAN.replace('2.1 Child task', '2.9 Child task'))).not.toBe(hashOf(PLAN)); + }); + + it('hierarchy (indentation) changes invalidate the plan hash', () => { + expect(hashOf(PLAN.replace(' - [ ] 2.1', '- [ ] 2.1'))).not.toBe(hashOf(PLAN)); + }); + + it('requirement reference changes invalidate the plan hash', () => { + expect(hashOf(PLAN.replace('_Requirements: 1.1_', '_Requirements: 1.2_'))).not.toBe(hashOf(PLAN)); + }); + + it('adding or removing tasks invalidates the plan hash', () => { + expect(hashOf(`${PLAN}- [ ] 4. New task\n`)).not.toBe(hashOf(PLAN)); + }); + + it('unknown checkbox state characters are content, not progress', () => { + expect(hashOf(PLAN.replace('- [ ] 1.', '- [?] 1.'))).not.toBe(hashOf(PLAN)); + }); + + it('checkbox-looking lines inside code fences are never normalized', () => { + const fenced = `${PLAN}\n\`\`\`md\n- [ ] example inside a fence\n\`\`\`\n`; + const fencedChecked = fenced.replace('- [ ] example inside a fence', '- [x] example inside a fence'); + expect(hashOf(fencedChecked)).not.toBe(hashOf(fenced)); + }); + + it('line-ending and BOM changes stay byte-significant', () => { + const crlf = PLAN.split('\n').join('\r\n'); + expect(hashOf(crlf)).not.toBe(hashOf(PLAN)); + const withBom = String.fromCharCode(0xfeff) + PLAN; + expect(hashOf(withBom)).not.toBe(hashOf(PLAN)); + }); + + it('normalizedTaskPlanText only rewrites the state character', () => { + const progressed = PLAN.replace('- [ ] 1.', '- [x] 1.'); + expect(normalizedTaskPlanText(MarkdownDocument.fromText(progressed))).toBe( + normalizedTaskPlanText(MarkdownDocument.fromText(PLAN)), + ); + expect(normalizedTaskPlanText(MarkdownDocument.fromText(PLAN))).toBe(PLAN); + }); +}); + +describe('task fingerprints', () => { + it('are stable across checkbox progress and change with identity', () => { + const base = { id: '2.1', title: 'Child task', requirementRefs: ['1.2'] }; + expect(taskFingerprint(base)).toBe(taskFingerprint({ ...base })); + expect(taskFingerprint({ ...base, title: 'Renamed' })).not.toBe(taskFingerprint(base)); + expect(taskFingerprint({ ...base, id: '2.2' })).not.toBe(taskFingerprint(base)); + expect(taskFingerprint({ ...base, requirementRefs: ['1.1'] })).not.toBe(taskFingerprint(base)); + }); +}); diff --git a/tests/drift/verification-policy.test.ts b/tests/drift/verification-policy.test.ts new file mode 100644 index 0000000..703f55d --- /dev/null +++ b/tests/drift/verification-policy.test.ts @@ -0,0 +1,148 @@ +import { mkdirSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { resolveWorkspace } from '@specbridge/core'; +import { + BUILT_IN_PROTECTED_PATHS, + compilePathMatchers, + readVerificationPolicy, + resolveEffectivePolicy, + validateGlobPattern, + verificationPolicySchema, +} from '@specbridge/drift'; +import { copyFixtureToTemp } from '../helpers.js'; + +const SPEC = 'settings-persistence'; + +function setup(): { root: string; workspace: NonNullable> } { + const root = copyFixtureToTemp('v03-ready-feature'); + const workspace = resolveWorkspace(root); + if (workspace === undefined) throw new Error('no workspace'); + return { root, workspace }; +} + +function writePolicy(root: string, content: string): void { + const dir = path.join(root, '.specbridge', 'policies'); + mkdirSync(dir, { recursive: true }); + writeFileSync(path.join(dir, `${SPEC}.json`), content, 'utf8'); +} + +describe('glob pattern validation', () => { + it('accepts repository-relative globs', () => { + expect(validateGlobPattern('src/**')).toBeUndefined(); + expect(validateGlobPattern('tests/unit/*.test.ts')).toBeUndefined(); + }); + + it('rejects absolute paths, traversal, null bytes, backslashes, and empty patterns', () => { + expect(validateGlobPattern('/etc/**')?.reason).toContain('absolute'); + expect(validateGlobPattern('C:/temp/**')?.reason).toContain('absolute'); + expect(validateGlobPattern('../outside/**')?.reason).toContain('".."'); + expect(validateGlobPattern('src/../../x')?.reason).toContain('".."'); + expect(validateGlobPattern('src\\windows\\**')?.reason).toContain('backslash'); + expect(validateGlobPattern('bad\0null')?.reason).toContain('null byte'); + expect(validateGlobPattern('')?.reason).toContain('empty'); + }); +}); + +describe('policy schema and loader', () => { + it('parses a valid policy with defaults', () => { + const parsed = verificationPolicySchema.parse({ specName: SPEC }); + expect(parsed.mode).toBe('advisory'); + expect(parsed.impactAreas).toEqual([]); + expect(parsed.rules).toEqual({}); + }); + + it('rejects invalid rule keys, severities, and glob patterns', () => { + expect( + verificationPolicySchema.safeParse({ specName: SPEC, rules: { NOTARULE: {} } }).success, + ).toBe(false); + expect( + verificationPolicySchema.safeParse({ + specName: SPEC, + rules: { SBV005: { severity: 'fatal' } }, + }).success, + ).toBe(false); + expect( + verificationPolicySchema.safeParse({ specName: SPEC, impactAreas: ['../escape/**'] }).success, + ).toBe(false); + }); + + it('fail-closed: invalid JSON and shape yield diagnostics, never a policy', () => { + const { root, workspace } = setup(); + writePolicy(root, '{ not json'); + const invalidJson = readVerificationPolicy(workspace, SPEC); + expect(invalidJson.policy).toBeUndefined(); + expect(invalidJson.diagnostics[0]?.code).toBe('POLICY_INVALID_JSON'); + + writePolicy(root, JSON.stringify({ specName: SPEC, mode: 'draconian' })); + const invalidShape = readVerificationPolicy(workspace, SPEC); + expect(invalidShape.policy).toBeUndefined(); + expect(invalidShape.diagnostics[0]?.code).toBe('POLICY_INVALID_SHAPE'); + + writePolicy(root, JSON.stringify({ specName: 'other-name' })); + const mismatch = readVerificationPolicy(workspace, SPEC); + expect(mismatch.policy).toBeUndefined(); + expect(mismatch.diagnostics[0]?.code).toBe('POLICY_NAME_MISMATCH'); + }); +}); + +describe('effective policy precedence', () => { + it('uses secure defaults when no policy exists', () => { + const { workspace } = setup(); + const effective = resolveEffectivePolicy(workspace, SPEC); + expect(effective.mode).toBe('advisory'); + expect(effective.policyExists).toBe(false); + for (const pattern of BUILT_IN_PROTECTED_PATHS) { + expect(effective.protectedPaths).toContain(pattern); + } + }); + + it('merges global protected paths and per-spec additions on top of built-ins', () => { + const { root, workspace } = setup(); + writePolicy( + root, + JSON.stringify({ specName: SPEC, protectedPaths: ['infra/terraform/**'] }), + ); + const effective = resolveEffectivePolicy(workspace, SPEC, { + globalProtectedPaths: ['generated'], + }); + expect(effective.protectedPaths).toContain('.git/**'); + expect(effective.protectedPaths).toContain('generated/**'); + expect(effective.protectedPaths).toContain('infra/terraform/**'); + }); + + it('.git/** protection cannot be removed by any layer', () => { + const { root, workspace } = setup(); + writePolicy(root, JSON.stringify({ specName: SPEC, protectedPaths: [] })); + const effective = resolveEffectivePolicy(workspace, SPEC); + expect(effective.protectedPaths).toContain('.git/**'); + }); + + it('--strict tightens the stored mode but never loosens it', () => { + const { root, workspace } = setup(); + writePolicy(root, JSON.stringify({ specName: SPEC, mode: 'advisory' })); + const tightened = resolveEffectivePolicy(workspace, SPEC, { strict: true }); + expect(tightened.mode).toBe('strict'); + expect(tightened.strictFromCli).toBe(true); + + writePolicy(root, JSON.stringify({ specName: SPEC, mode: 'strict' })); + const unchanged = resolveEffectivePolicy(workspace, SPEC, { strict: false }); + expect(unchanged.mode).toBe('strict'); + }); +}); + +describe('compilePathMatchers', () => { + it('matches repo-relative paths, normalizing Windows separators', () => { + const matcher = compilePathMatchers(['src/settings/**', 'tests/**']); + expect(matcher('src/settings/store.ts')).toEqual(['src/settings/**']); + expect(matcher('src\\settings\\store.ts')).toEqual(['src/settings/**']); + expect(matcher('src/billing/invoice.ts')).toEqual([]); + expect(matcher('.kiro/specs/x/requirements.md')).toEqual([]); + }); + + it('matches dotfiles (protected paths depend on it)', () => { + const matcher = compilePathMatchers(['.kiro/**', '.specbridge/config.json']); + expect(matcher('.kiro/specs/a/tasks.md')).toEqual(['.kiro/**']); + expect(matcher('.specbridge/config.json')).toEqual(['.specbridge/config.json']); + }); +}); diff --git a/tests/drift/verify-encodings.test.ts b/tests/drift/verify-encodings.test.ts new file mode 100644 index 0000000..1ba15ef --- /dev/null +++ b/tests/drift/verify-encodings.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from 'vitest'; +import { resolveWorkspace } from '@specbridge/core'; +import { verifySpecs } from '@specbridge/drift'; +import { copyFixtureToTemp } from '../helpers.js'; +import { initGitRepo } from '../helpers-execution.js'; + +/** + * Verification over CRLF and non-ASCII spec content: parsing, traceability, + * and reports must work byte-safely on files SpecBridge never normalizes. + */ + +async function verifyFixture(fixtureName: string, spec: string) { + const root = copyFixtureToTemp(fixtureName); + initGitRepo(root); + const workspace = resolveWorkspace(root); + if (workspace === undefined) throw new Error('fixture has no workspace'); + return verifySpecs({ + workspace, + selection: { mode: 'single', spec }, + comparison: { mode: 'working-tree' }, + failOn: 'error', + toolVersion: '0.4.0-test', + }); +} + +describe('verification over CRLF and UTF-8 fixtures', () => { + it('CRLF spec files verify with only the expected missing-design finding', async () => { + const result = await verifyFixture('crlf-files', 'crlf-feature'); + const specResult = result.report.specResults[0]; + expect(specResult?.specName).toBe('crlf-feature'); + // The fixture genuinely lacks design.md — SBV001 is the only error. + const errors = (specResult?.diagnostics ?? []).filter((d) => d.severity === 'error'); + expect(errors.map((d) => d.ruleId)).toEqual(['SBV001']); + expect(errors[0]?.message).toContain('design.md'); + // Traceability extraction worked on CRLF content. + expect(specResult?.traceability.tasks).toBeGreaterThan(0); + expect(specResult?.traceability.requirements).toBeGreaterThan(0); + }); + + it('UTF-8 spec content verifies and preserves non-English identifiers in diagnostics', async () => { + const result = await verifyFixture('utf8-content', 'localized-feature'); + const specResult = result.report.specResults[0]; + expect(specResult?.specName).toBe('localized-feature'); + expect(specResult?.traceability.requirements).toBeGreaterThanOrEqual(0); + // Whatever diagnostics exist must round-trip through the schema (validated + // inside verifySpecs) — reaching this point proves it. + expect(result.report.schemaVersion).toBe('1.0.0'); + }); +}); diff --git a/tests/drift/verify-orchestration.test.ts b/tests/drift/verify-orchestration.test.ts new file mode 100644 index 0000000..dfb3c5f --- /dev/null +++ b/tests/drift/verify-orchestration.test.ts @@ -0,0 +1,280 @@ +import { createHash } from 'node:crypto'; +import { readFileSync, readdirSync, statSync } from 'node:fs'; +import path from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { verificationReportSchema } from '@specbridge/core'; +import { resolveAffectedSpecs, resolveComparison } from '@specbridge/drift'; +import { failingCommand, passingCommand } from '../helpers-execution.js'; +import { allDiagnostics, ruleIds, setupVerifyFixture, VERIFY_SPEC } from '../helpers-verify.js'; + +/** + * Orchestration-level behavior: trusted command execution and reuse, + * affected-spec resolution, exit codes, and the read-only guarantee. + */ + +function timeoutCommand(name = 'slow'): Record { + return { + name, + argv: [process.execPath, '-e', 'setTimeout(() => {}, 30_000)'], + timeoutMs: 1_000, + required: true, + }; +} + +function spawnFailCommand(name = 'ghost'): Record { + return { + name, + argv: ['definitely-not-a-real-executable-specbridge'], + timeoutMs: 5_000, + required: true, + }; +} + +describe('trusted verification commands', () => { + it('policy-required commands run by default and pass (SBV012 stays quiet)', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [passingCommand('test')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['test'] }); + const result = await fixture.verify(); + expect(ruleIds(result)).not.toContain('SBV012'); + const command = result.report.verificationCommands.find((c) => c.name === 'test'); + expect(command?.disposition).toBe('executed'); + expect(command?.passed).toBe(true); + expect(result.exitCode).toBe(0); + // Command logs and report.json are stored under the artifacts directory. + expect(result.artifactsDir).toBeDefined(); + const commandLogs = readdirSync(path.join(result.artifactsDir as string, 'commands')); + expect(commandLogs).toContain('test.stdout.log'); + expect(readFileSync(path.join(result.artifactsDir as string, 'report.json'), 'utf8')).toContain( + '"schemaVersion"', + ); + }); + + it('a failing required command triggers SBV012 and fails verification', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [failingCommand('test')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['test'] }); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV012'); + expect(finding?.severity).toBe('error'); + expect(result.exitCode).toBe(1); + }); + + it('a failing optional command warns without failing (--run-verification)', async () => { + const fixture = setupVerifyFixture({ + config: { verificationCommands: [passingCommand('test'), failingCommand('lint', false)] }, + }); + const result = await fixture.verify({ runVerification: true }); + expect(ruleIds(result)).not.toContain('SBV012'); + const lint = result.report.verificationCommands.find((c) => c.name === 'lint'); + expect(lint?.passed).toBe(false); + expect(lint?.required).toBe(false); + expect(result.exitCode).toBe(0); + }); + + it('a missing required command name triggers SBV013', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [passingCommand('test')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['typecheck'] }); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV013'); + expect(finding?.severity).toBe('error'); + expect(finding?.message).toContain('typecheck'); + expect(result.exitCode).toBe(1); + }); + + it('a required command timeout triggers SBV025 and exit code 5', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [timeoutCommand('slow')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['slow'] }); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV025'); + expect(finding?.severity).toBe('error'); + expect(result.exitCode).toBe(5); + }); + + it('a required command that cannot start exits with code 4', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [spawnFailCommand('ghost')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['ghost'] }); + const result = await fixture.verify(); + expect(ruleIds(result)).toContain('SBV012'); + expect(result.exitCode).toBe(4); + }); + + it('--no-run-verification reuses passing results from fresh evidence at HEAD', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [passingCommand('test')] } }); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); // records a passing "test" at current HEAD + fixture.commit('progress'); // moves HEAD → evidence no longer reusable + fixture.writeVerifiedEvidence('2.1'); // fresh evidence at the new HEAD + fixture.writePolicy({ requiredVerificationCommands: ['test'] }); + + const result = await fixture.verify({ runVerification: false }); + const command = result.report.verificationCommands.find((c) => c.name === 'test'); + expect(command?.disposition).toBe('reused-evidence'); + expect(command?.passed).toBe(true); + expect(ruleIds(result)).not.toContain('SBV012'); + }); + + it('--no-run-verification without reusable evidence fails the required command honestly', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [passingCommand('test')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['test'] }); + const result = await fixture.verify({ runVerification: false }); + const command = result.report.verificationCommands.find((c) => c.name === 'test'); + expect(command?.disposition).toBe('not-run'); + expect(command?.passed).toBe(false); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV012'); + expect(finding?.message).toContain('did not run'); + expect(result.exitCode).toBe(1); + }); +}); + +describe('affected-spec resolution', () => { + it('maps changed files through every documented signal deterministically', async () => { + const fixture = setupVerifyFixture(); + // Second spec with an impact area overlapping the first's. + fixture.write( + '.kiro/specs/email-delivery/requirements.md', + '# Requirements Document\n\n### Requirement 1: Deliver email\n\n#### Acceptance Criteria\n\n1. WHEN sending THEN the system SHALL deliver.\n', + ); + fixture.write('.kiro/specs/email-delivery/design.md', '# Design Document\n\nSee `src/shared/logger.ts`.\n'); + fixture.write('.kiro/specs/email-delivery/tasks.md', '# Implementation Plan\n\n- [ ] 1. Send email\n - _Requirements: 1.1_\n'); + fixture.write( + '.specbridge/policies/email-delivery.json', + JSON.stringify({ schemaVersion: '1.0.0', specName: 'email-delivery', impactAreas: ['src/shared/**'] }), + ); + fixture.writePolicy({ impactAreas: ['src/shared/**', 'src/settings/**'] }); + fixture.commit('two specs'); + + fixture.write('src/shared/logger.ts', 'export const log = 1;\n'); // both specs + fixture.write(`.kiro/specs/${VERIFY_SPEC}/notes.md`, 'note\n'); // spec files signal + fixture.write('src/orphan/widget.ts', 'export {};\n'); // unmapped + + const comparison = await resolveComparison(fixture.root, { mode: 'working-tree' }); + expect(comparison.ok).toBe(true); + const affected = resolveAffectedSpecs(fixture.workspace, comparison.changedFiles); + + expect(affected.affected.map((spec) => spec.specName)).toEqual([ + 'email-delivery', + VERIFY_SPEC, + ]); + const emailMatches = affected.affected[0]?.matches ?? []; + expect(emailMatches.some((match) => match.via.some((via) => via.includes('impact area')))).toBe(true); + expect( + affected.affected[1]?.matches.some((match) => match.via.includes('spec files')), + ).toBe(true); + expect(affected.unmapped.map((file) => file.path)).toEqual(['src/orphan/widget.ts']); + expect(affected.ambiguous[0]?.path).toBe('src/shared/logger.ts'); + expect(affected.ambiguous[0]?.specs.map((spec) => spec.name)).toEqual([ + 'email-delivery', + VERIFY_SPEC, + ]); + }); + + it('evidence maps changed files to their spec', async () => { + const fixture = setupVerifyFixture(); + fixture.writeVerifiedEvidence('1', { + changedFiles: [ + { path: 'src/evidence-owned.ts', changeType: 'added', preExisting: false, modifiedDuringRun: true }, + ], + }); + fixture.write('src/evidence-owned.ts', 'export {};\n'); + const comparison = await resolveComparison(fixture.root, { mode: 'working-tree' }); + const affected = resolveAffectedSpecs(fixture.workspace, comparison.changedFiles); + const spec = affected.affected.find((entry) => entry.specName === VERIFY_SPEC); + expect(spec?.matches.some((match) => match.via.includes('task evidence'))).toBe(true); + }); + + it('changed-mode verification emits SBV014 and SBV022 for unmapped and shared files', async () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.write('src/orphan/widget.ts', 'export {};\n'); + fixture.write('src/settings/store.ts', 'export {};\n'); + const result = await fixture.verify({ selection: { mode: 'changed' } }); + const unmapped = allDiagnostics(result).filter((d) => d.ruleId === 'SBV014'); + expect(unmapped.some((d) => d.file?.path === 'src/orphan/widget.ts')).toBe(true); + expect(result.report.selection.specs).toEqual([VERIFY_SPEC]); + expect(result.report.specResults[0]?.matchedBy.length).toBeGreaterThan(0); + }); + + it('--all verifies every spec with deterministic ordering', async () => { + const fixture = setupVerifyFixture(); + fixture.write( + '.kiro/specs/aaa-first/requirements.md', + '# Requirements Document\n\n### Requirement 1: Sort first\n\n#### Acceptance Criteria\n\n1. WHEN listed THEN it SHALL sort first.\n', + ); + fixture.write('.kiro/specs/aaa-first/design.md', '# Design Document\n'); + fixture.write('.kiro/specs/aaa-first/tasks.md', '# Implementation Plan\n\n- [ ] 1. Do it\n - _Requirements: 1.1_\n'); + fixture.commit('another spec'); + const result = await fixture.verify({ selection: { mode: 'all' } }); + expect(result.report.selection.specs).toEqual(['aaa-first', VERIFY_SPEC]); + }); +}); + +describe('report integrity and the read-only guarantee', () => { + it('reports validate against the versioned schema and sort diagnostics deterministically', async () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/settings/**'] }); + fixture.checkTask('1'); + fixture.write('outside/a.ts', 'export {};\n'); + fixture.write('outside/b.ts', 'export {};\n'); + const result = await fixture.verify(); + expect(() => verificationReportSchema.parse(result.report)).not.toThrow(); + const diagnostics = result.report.specResults[0]?.diagnostics ?? []; + const severityRank = { error: 0, warning: 1, info: 2 } as const; + for (let i = 1; i < diagnostics.length; i += 1) { + const previous = diagnostics[i - 1]!; + const current = diagnostics[i]!; + expect(severityRank[previous.severity]).toBeLessThanOrEqual(severityRank[current.severity]); + } + // Two identical runs produce identical diagnostics (id and timestamp injected). + const again = await fixture.verify(); + expect(JSON.stringify(again.report.specResults[0]?.diagnostics)).toBe( + JSON.stringify(result.report.specResults[0]?.diagnostics), + ); + }); + + it('verification without command runs writes nothing at all', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); + fixture.writePolicy({ impactAreas: ['src/**'] }); + + const snapshot = hashTree(fixture.root); + const result = await fixture.verify(); + expect(result.artifactsDir).toBeUndefined(); + expect(hashTree(fixture.root)).toEqual(snapshot); + }); + + it('command execution writes only under the reports directory', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [passingCommand('test')] } }); + fixture.writePolicy({ requiredVerificationCommands: ['test'] }); + const before = hashTree(fixture.root, ['.specbridge/reports']); + const result = await fixture.verify(); + expect(result.artifactsDir).toBeDefined(); + expect(path.relative(fixture.root, result.artifactsDir as string).split(path.sep)[0]).toBe( + '.specbridge', + ); + const after = hashTree(fixture.root, ['.specbridge/reports']); + expect(after).toEqual(before); + }); +}); + +/** SHA-256 of every file under root (sorted map), skipping .git and excluded prefixes. */ +function hashTree(root: string, excludePrefixes: string[] = []): Record { + const result: Record = {}; + const walk = (dir: string): void => { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const absolute = path.join(dir, entry.name); + const relative = path.relative(root, absolute).split(path.sep).join('/'); + if (relative === '.git' || relative.startsWith('.git/')) continue; + if (excludePrefixes.some((prefix) => relative === prefix || relative.startsWith(`${prefix}/`))) { + continue; + } + if (entry.isDirectory()) { + walk(absolute); + } else if (entry.isFile()) { + const stats = statSync(absolute); + result[relative] = `${stats.size}:${createHash('sha256').update(readFileSync(absolute)).digest('hex')}`; + } + } + }; + walk(root); + return result; +} diff --git a/tests/drift/verify-rules.test.ts b/tests/drift/verify-rules.test.ts new file mode 100644 index 0000000..9b0baff --- /dev/null +++ b/tests/drift/verify-rules.test.ts @@ -0,0 +1,469 @@ +import { rmSync } from 'node:fs'; +import path from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { readSpecState } from '@specbridge/core'; +import { allDiagnostics, ruleIds, setupVerifyFixture, VERIFY_SPEC } from '../helpers-verify.js'; + +/** + * End-to-end rule behavior over real git fixtures. Each scenario builds a + * fresh temp repository; verification runs the actual engine. + */ + +describe('clean verification', () => { + it('an approved, unchanged spec with a clean tree passes with no findings', async () => { + const fixture = setupVerifyFixture(); + const result = await fixture.verify(); + expect(result.exitCode).toBe(0); + expect(result.report.summary.result).toBe('passed'); + expect(allDiagnostics(result)).toHaveLength(0); + expect(result.report.specResults[0]?.managed).toBe(true); + }); +}); + +describe('SBV001 — required spec file missing', () => { + it('flags each missing document of a feature spec', async () => { + const fixture = setupVerifyFixture({ approve: false }); + rmSync(path.join(fixture.root, '.kiro', 'specs', VERIFY_SPEC, 'design.md')); + fixture.commit('remove design'); + const result = await fixture.verify(); + const findings = allDiagnostics(result).filter((d) => d.ruleId === 'SBV001'); + expect(findings).toHaveLength(1); + expect(findings[0]?.severity).toBe('error'); + expect(findings[0]?.file?.path).toBe(`.kiro/specs/${VERIFY_SPEC}/design.md`); + expect(result.exitCode).toBe(1); + }); +}); + +describe('SBV002/SBV003 — approval drift', () => { + it('detects a stale requirements approval and the invalidated dependents', async () => { + const fixture = setupVerifyFixture(); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/requirements.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/requirements.md`)}\nNew requirement paragraph.\n`, + ); + const result = await fixture.verify(); + const ids = ruleIds(result); + expect(ids).toContain('SBV002'); + expect(ids).toContain('SBV003'); // design + tasks depend on requirements + expect(result.exitCode).toBe(1); + }); + + it('detects a stale design approval', async () => { + const fixture = setupVerifyFixture(); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/design.md`, + fixture.read(`.kiro/specs/${VERIFY_SPEC}/design.md`).replace('## Overview', '## Overview (edited)'), + ); + const result = await fixture.verify(); + const sbv002 = allDiagnostics(result).filter((d) => d.ruleId === 'SBV002'); + expect(sbv002.some((d) => d.message.includes('design'))).toBe(true); + }); + + it('checkbox-only progress does NOT trip SBV002 (hash semantics v2)', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + const result = await fixture.verify(); + expect(ruleIds(result)).not.toContain('SBV002'); + // The checked task without evidence is still reported, deliberately. + expect(ruleIds(result)).toContain('SBV004'); + }); +}); + +describe('SBV004 — completed task lacks verified evidence', () => { + it('warns by default and errors when the policy requires evidence', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + const asWarning = await fixture.verify(); + const warning = allDiagnostics(asWarning).find((d) => d.ruleId === 'SBV004'); + expect(warning?.severity).toBe('warning'); + expect(warning?.taskId).toBe('1'); + expect(asWarning.exitCode).toBe(0); + + fixture.writePolicy({ requireVerifiedTaskEvidence: true }); + const asError = await fixture.verify(); + expect(allDiagnostics(asError).find((d) => d.ruleId === 'SBV004')?.severity).toBe('error'); + expect(asError.exitCode).toBe(1); + }); + + it('accepts a checked task with valid verified evidence', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); + const result = await fixture.verify(); + expect(ruleIds(result)).not.toContain('SBV004'); + expect(result.report.specResults[0]?.evidence.valid).toBe(1); + }); +}); + +describe('SBV005 — impact areas', () => { + it('matching files pass; outside files warn in advisory and fail in strict', async () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/**'] }); + fixture.write('src/inside.ts', 'export {};\n'); + const inside = await fixture.verify(); + expect(ruleIds(inside)).not.toContain('SBV005'); + + fixture.write('billing/outside.ts', 'export {};\n'); + const advisory = await fixture.verify(); + const warning = allDiagnostics(advisory).find((d) => d.ruleId === 'SBV005'); + expect(warning?.severity).toBe('warning'); + expect(warning?.file?.path).toBe('billing/outside.ts'); + expect(advisory.exitCode).toBe(0); + + const strict = await fixture.verify({ strict: true }); + expect(allDiagnostics(strict).find((d) => d.ruleId === 'SBV005')?.severity).toBe('error'); + expect(strict.exitCode).toBe(1); + }); + + it('handles renames and deletions of files outside the areas', async () => { + const fixture = setupVerifyFixture(); + fixture.writePolicy({ impactAreas: ['src/**'] }); + fixture.write('billing/legacy.ts', 'export {};\n'); + fixture.commit('add legacy'); + rmSync(path.join(fixture.root, 'billing', 'legacy.ts')); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV005'); + expect(finding?.file?.path).toBe('billing/legacy.ts'); + }); +}); + +describe('SBV006 — protected paths', () => { + it('flags config.json changes as errors', async () => { + const fixture = setupVerifyFixture({ config: { verificationCommands: [] } }); + fixture.commit('config baseline'); + fixture.write('.specbridge/config.json', '{"schemaVersion":"1.0.0","defaultRunner":"mock"}\n'); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find( + (d) => d.ruleId === 'SBV006' && d.file?.path === '.specbridge/config.json', + ); + expect(finding?.severity).toBe('error'); + expect(result.exitCode).toBe(1); + }); + + it('exempts the verified spec’s own files but flags other specs’ .kiro files', async () => { + const fixture = setupVerifyFixture(); + // Another spec's file changes while verifying settings-persistence only. + fixture.write('.kiro/specs/other-spec/requirements.md', '# Requirements Document\n'); + // The verified spec's own requirements change too (spec authoring). + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/requirements.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/requirements.md`)}\nEdited.\n`, + ); + const result = await fixture.verify(); + const findings = allDiagnostics(result).filter((d) => d.ruleId === 'SBV006'); + const otherSpec = findings.find((d) => d.file?.path.startsWith('.kiro/specs/other-spec/')); + expect(otherSpec?.severity).toBe('error'); + const ownSpec = findings.find((d) => + d.file?.path.startsWith(`.kiro/specs/${VERIFY_SPEC}/`), + ); + expect(ownSpec?.severity).toBe('info'); // sanctioned authoring; SBV002 governs it + expect(ruleIds(result)).toContain('SBV002'); + }); + + it('checkbox-only tasks.md progress is reported as expected progress', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find( + (d) => d.ruleId === 'SBV006' && d.file?.path.endsWith('tasks.md'), + ); + expect(finding?.severity).toBe('info'); + expect(finding?.message).toContain('checkbox-only'); + expect(ruleIds(result)).not.toContain('SBV023'); + }); +}); + +describe('SBV007/SBV008/SBV009/SBV010 — traceability', () => { + it('an unreferenced requirement triggers SBV007 (configurable to error)', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/requirements.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/requirements.md`)} +### Requirement 2: Unimplemented extra + +#### Acceptance Criteria + +1. WHEN nothing references this THEN verification SHALL flag it. +`, + ); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV007'); + expect(finding?.severity).toBe('warning'); + expect(finding?.requirementId).toBe('2'); + + fixture.writePolicy({ requireRequirementTaskLinks: true }); + const strict = await fixture.verify(); + expect(allDiagnostics(strict).find((d) => d.ruleId === 'SBV007')?.severity).toBe('error'); + }); + + it('a linked plan with an unlinked implementation task triggers SBV008 (heuristic warning)', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`)} +- [ ] 5. Implement the audit hook +`, + ); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV008'); + expect(finding?.taskId).toBe('5'); + expect(finding?.severity).toBe('warning'); + }); + + it('documentation-style tasks are excluded from SBV008', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`)} +- [ ] 5. Update documentation for the release +`, + ); + const result = await fixture.verify(); + expect(allDiagnostics(result).filter((d) => d.ruleId === 'SBV008')).toHaveLength(0); + }); + + it('a task referencing an unknown requirement triggers SBV009 with the source line', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + fixture + .read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`) + .replace('_Requirements: 1.2_', '_Requirements: 7.7_'), + ); + const result = await fixture.verify(); + const findings = allDiagnostics(result).filter((d) => d.ruleId === 'SBV009'); + expect(findings.length).toBeGreaterThanOrEqual(1); + expect(findings[0]?.severity).toBe('error'); + expect(findings[0]?.file?.line).toBeGreaterThan(0); + expect(result.exitCode).toBe(1); + }); + + it('a completed parent with open children triggers SBV010', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + fixture + .read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`) + .replace('- [ ] 2. Add automated tests', '- [x] 2. Add automated tests'), + ); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV010'); + expect(finding?.taskId).toBe('2'); + expect(finding?.severity).toBe('error'); + expect(finding?.message).toContain('2.1'); + }); +}); + +describe('SBV011/SBV015 — evidence freshness', () => { + it('evidence recorded against an older task plan goes stale after a plan edit (SBV015)', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); + fixture.commit('progress with evidence'); + + // Edit the plan and re-approve (sanctioned change) — the evidence now + // describes an older approved plan. + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + fixture + .read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`) + .replace('3. Verify the full workflow end to end', '3. Verify everything end to end'), + ); + const { approveAllStages } = await import('../helpers-execution.js'); + approveAllStages(fixture.workspace, VERIFY_SPEC, fixture.clock); + + const result = await fixture.verify(); + const ids = ruleIds(result); + expect(ids).toContain('SBV015'); + expect(result.report.specResults[0]?.evidence.stale).toBe(1); + expect(result.exitCode).toBe(1); + }); + + it('renaming the checked task itself makes its evidence stale (SBV011)', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + fixture + .read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`) + .replace('1. Implement the settings store', '1. Implement the storage layer'), + ); + const result = await fixture.verify(); + expect(ruleIds(result)).toContain('SBV011'); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV011'); + expect(finding?.taskId).toBe('1'); + }); +}); + +describe('SBV016 — completion before approval', () => { + it('flags checked tasks in a managed spec whose plan was never approved', async () => { + const fixture = setupVerifyFixture(); + // Revoke the tasks approval, then check a box. + const { analyzeSpec, requireSpec } = await import('@specbridge/compat-kiro'); + const { approveStage } = await import('@specbridge/workflow'); + const spec = analyzeSpec(fixture.workspace, requireSpec(fixture.workspace, VERIFY_SPEC)); + const revoked = approveStage(fixture.workspace, spec, { stage: 'tasks', revoke: true }); + expect(revoked.ok).toBe(true); + fixture.checkTask('1'); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV016'); + expect(finding?.severity).toBe('error'); + expect(finding?.taskId).toBe('1'); + }); + + it('does not judge unmanaged specs', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.checkTask('1'); + const result = await fixture.verify(); + expect(ruleIds(result)).not.toContain('SBV016'); + expect(readSpecState(fixture.workspace, VERIFY_SPEC).state).toBeUndefined(); + }); +}); + +describe('SBV017 — test-required tasks', () => { + it('warns when a test-mentioning task has valid evidence without test signals', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('2.1'); // "Test the successful save path" + fixture.writeVerifiedEvidence('2.1', { + verificationCommands: [ + { name: 'build', argv: [process.execPath, '-e', '0'], required: true, exitCode: 0, durationMs: 5, passed: true }, + ], + changedFiles: [ + { path: 'src/settings.txt', changeType: 'modified', preExisting: true, modifiedDuringRun: true }, + ], + }); + const warning = await fixture.verify(); + const finding = allDiagnostics(warning).find((d) => d.ruleId === 'SBV017'); + expect(finding?.severity).toBe('warning'); + expect(finding?.taskId).toBe('2.1'); + + fixture.writePolicy({ requireTestEvidence: true }); + const strict = await fixture.verify(); + expect(allDiagnostics(strict).find((d) => d.ruleId === 'SBV017')?.severity).toBe('error'); + }); + + it('is satisfied by a passing test command or changed test files', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('2.1'); + fixture.writeVerifiedEvidence('2.1', { + changedFiles: [ + { path: 'tests/settings.test.ts', changeType: 'added', preExisting: false, modifiedDuringRun: true }, + ], + verificationCommands: [], + }); + const result = await fixture.verify(); + expect(ruleIds(result)).not.toContain('SBV017'); + }); +}); + +describe('SBV018 — design path references', () => { + it('warns for explicitly referenced repository paths that do not exist', async () => { + const fixture = setupVerifyFixture({ approve: false }); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/design.md`, + `${fixture.read(`.kiro/specs/${VERIFY_SPEC}/design.md`)} +The store implementation lives in \`src/settings/store.ts\`. +The existing scratch file is \`src/settings.txt\`. +`, + ); + const result = await fixture.verify(); + const findings = allDiagnostics(result).filter((d) => d.ruleId === 'SBV018'); + expect(findings).toHaveLength(1); + expect(findings[0]?.message).toContain('src/settings/store.ts'); + expect(findings[0]?.severity).toBe('warning'); + expect(findings[0]?.file?.line).toBeGreaterThan(0); + }); +}); + +describe('SBV019 — changed files missing from evidence', () => { + it('warns when valid evidence exists but a changed file is not represented', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1'); // records src/settings.txt only + fixture.write('src/extra-edit.ts', 'export {};\n'); + const result = await fixture.verify(); + const findings = allDiagnostics(result).filter((d) => d.ruleId === 'SBV019'); + expect(findings.some((d) => d.file?.path === 'src/extra-edit.ts')).toBe(true); + expect(findings.every((d) => d.severity === 'warning')).toBe(true); + }); +}); + +describe('SBV020 — invalid policy', () => { + it('reports the invalid policy and exits 2 while verifying with defaults', async () => { + const fixture = setupVerifyFixture(); + fixture.write(`.specbridge/policies/${VERIFY_SPEC}.json`, '{ broken json'); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV020'); + expect(finding?.severity).toBe('error'); + expect(result.exitCode).toBe(2); + }); +}); + +describe('SBV021 — comparison unavailable', () => { + it('reports the unresolvable base with fetch guidance and exits 3', async () => { + const fixture = setupVerifyFixture(); + const result = await fixture.verify({ + comparison: { mode: 'diff', base: 'origin/missing-branch', head: 'HEAD' }, + }); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV021'); + expect(finding?.severity).toBe('error'); + expect(result.report.summary.result).toBe('failed'); + expect(result.exitCode).toBe(3); + }); +}); + +describe('SBV023 — task plan changed in the comparison', () => { + it('flags plan-text edits in the diff and accepts checkbox-only diffs', async () => { + const fixture = setupVerifyFixture(); + fixture.write( + `.kiro/specs/${VERIFY_SPEC}/tasks.md`, + fixture + .read(`.kiro/specs/${VERIFY_SPEC}/tasks.md`) + .replace('Implement the settings store', 'Implement the settings store DIFFERENTLY'), + ); + const result = await fixture.verify(); + expect(ruleIds(result)).toContain('SBV023'); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV023'); + expect(finding?.severity).toBe('error'); + }); +}); + +describe('SBV024 — evidence outside the repository', () => { + it('flags records whose changed files escape the repository', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1', { + changedFiles: [ + { path: '../outside/file.ts', changeType: 'modified', preExisting: false, modifiedDuringRun: true }, + ], + }); + const result = await fixture.verify(); + const finding = allDiagnostics(result).find((d) => d.ruleId === 'SBV024'); + expect(finding?.severity).toBe('error'); + expect(finding?.taskId).toBe('1'); + // The record is invalid, so the completed task also lacks usable evidence. + expect(ruleIds(result)).toContain('SBV004'); + }); +}); + +describe('manual acceptance', () => { + it('valid manual acceptance satisfies evidence rules and is labelled', async () => { + const fixture = setupVerifyFixture(); + fixture.checkTask('1'); + fixture.writeVerifiedEvidence('1', { + status: 'manually-accepted', + manualAcceptance: { + actor: 'local-user', + reason: 'verified by hand in the dev environment', + acceptedAt: fixture.clock().toISOString(), + }, + verificationCommands: [], + verificationSkipped: true, + }); + const result = await fixture.verify(); + expect(ruleIds(result)).not.toContain('SBV004'); + expect(result.report.specResults[0]?.evidence.manuallyAccepted).toBe(1); + expect(result.report.specResults[0]?.evidence.valid).toBe(1); + }); +}); diff --git a/tests/fixtures/github-events/pull_request.json b/tests/fixtures/github-events/pull_request.json new file mode 100644 index 0000000..3a2462c --- /dev/null +++ b/tests/fixtures/github-events/pull_request.json @@ -0,0 +1,9 @@ +{ + "action": "synchronize", + "number": 42, + "pull_request": { + "number": 42, + "base": { "ref": "main", "sha": "BASE_SHA_PLACEHOLDER" }, + "head": { "ref": "feature/settings", "sha": "HEAD_SHA_PLACEHOLDER" } + } +} diff --git a/tests/fixtures/github-events/push.json b/tests/fixtures/github-events/push.json new file mode 100644 index 0000000..fda802d --- /dev/null +++ b/tests/fixtures/github-events/push.json @@ -0,0 +1,5 @@ +{ + "ref": "refs/heads/main", + "before": "BASE_SHA_PLACEHOLDER", + "after": "HEAD_SHA_PLACEHOLDER" +} diff --git a/tests/fixtures/github-events/workflow_dispatch.json b/tests/fixtures/github-events/workflow_dispatch.json new file mode 100644 index 0000000..c0cabbf --- /dev/null +++ b/tests/fixtures/github-events/workflow_dispatch.json @@ -0,0 +1,4 @@ +{ + "inputs": {}, + "ref": "refs/heads/main" +} diff --git a/tests/helpers-verify.ts b/tests/helpers-verify.ts new file mode 100644 index 0000000..dd29302 --- /dev/null +++ b/tests/helpers-verify.ts @@ -0,0 +1,245 @@ +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import type { SpecWorkflowState, WorkspaceInfo } from '@specbridge/core'; +import { readSpecState, resolveWorkspace, stateStage } from '@specbridge/core'; +import { MarkdownDocument, parseTasks, taskFingerprint, taskPlanHash } from '@specbridge/compat-kiro'; +import type { EvidenceSpecContext, TaskEvidenceRecord } from '@specbridge/evidence'; +import { EVIDENCE_SCHEMA_VERSION, writeTaskEvidence } from '@specbridge/evidence'; +import type { VerificationPolicy, VerifySpecsRequest, VerifySpecsResult } from '@specbridge/drift'; +import { verifySpecs } from '@specbridge/drift'; +import { copyFixtureToTemp } from './helpers.js'; +import { + EXECUTION_SPEC, + approveAllStages, + git, + initGitRepo, + tickingClock, + writeFixtureConfig, +} from './helpers-execution.js'; + +/** + * Shared setup for v0.4 verification tests: a git-committed copy of the + * `v03-ready-feature` fixture with optional approvals, evidence records, + * verification policies, and file edits. Fully offline and deterministic. + */ + +export const VERIFY_SPEC = EXECUTION_SPEC; + +export interface VerifyFixtureOptions { + /** Approve all stages through the real flow (default true). */ + approve?: boolean; + /** Write a `.specbridge/config.json` (default: none — defaults apply). */ + config?: { + verificationCommands?: Record[]; + execution?: Record; + }; + /** Commit everything (including approvals/config) as the baseline. */ + commitBaseline?: boolean; +} + +export interface VerifyFixture { + root: string; + workspace: WorkspaceInfo; + specName: string; + clock: () => Date; + /** Write a workspace-relative file (creates directories). */ + write: (relative: string, content: string) => void; + /** Read a workspace-relative file. */ + read: (relative: string) => string; + /** Stage and commit everything. */ + commit: (message: string) => void; + /** Current HEAD SHA. */ + head: () => string; + /** Flip one task checkbox from `[ ]` to `[x]` by editing the raw line. */ + checkTask: (taskId: string) => void; + /** Write a verification policy for the spec. */ + writePolicy: (policy: Partial & Record) => string; + /** Persist a verified evidence record with a current specContext. */ + writeVerifiedEvidence: ( + taskId: string, + overrides?: Partial & Record, + ) => TaskEvidenceRecord; + /** Run verifySpecs with fixture defaults. */ + verify: ( + overrides?: Partial>, + ) => Promise; +} + +let evidenceCounter = 0; + +export function currentSpecContext( + workspace: WorkspaceInfo, + specName: string, + taskId: string, +): EvidenceSpecContext { + const state: SpecWorkflowState | undefined = readSpecState(workspace, specName).state; + const tasksPath = path.join(workspace.rootDir, '.kiro', 'specs', specName, 'tasks.md'); + const document = MarkdownDocument.load(tasksPath); + const model = parseTasks(document); + const task = model.allTasks.find((candidate) => candidate.id === taskId); + if (task === undefined) throw new Error(`fixture: task ${taskId} not found in tasks.md`); + + const specContext: EvidenceSpecContext = { + taskFingerprint: taskFingerprint(task), + taskText: document.lineAt(task.line).text, + }; + if (state !== undefined) { + const documentStage = stateStage(state, state.specType === 'bugfix' ? 'bugfix' : 'requirements'); + if (documentStage?.approvedHash != null) specContext.documentHash = documentStage.approvedHash; + const designStage = stateStage(state, 'design'); + if (designStage?.approvedHash != null) specContext.designHash = designStage.approvedHash; + const tasksStage = stateStage(state, 'tasks'); + if (tasksStage?.status === 'approved') { + specContext.tasksPlanHash = + typeof tasksStage.approvedPlanHash === 'string' + ? tasksStage.approvedPlanHash + : taskPlanHash(document); + } + } + return specContext; +} + +export function setupVerifyFixture(options: VerifyFixtureOptions = {}): VerifyFixture { + const root = copyFixtureToTemp('v03-ready-feature'); + initGitRepo(root); + const workspace = resolveWorkspace(root); + if (workspace === undefined) throw new Error('fixture has no .kiro workspace'); + const clock = tickingClock(); + + if (options.approve !== false) { + approveAllStages(workspace, VERIFY_SPEC, clock); + } + if (options.config !== undefined) { + writeFixtureConfig(root, { + verificationCommands: options.config.verificationCommands ?? [], + ...(options.config.execution !== undefined ? { execution: options.config.execution } : {}), + }); + } + + const write = (relative: string, content: string): void => { + const absolute = path.join(root, relative.split('/').join(path.sep)); + mkdirSync(path.dirname(absolute), { recursive: true }); + writeFileSync(absolute, content, 'utf8'); + }; + const read = (relative: string): string => + readFileSync(path.join(root, relative.split('/').join(path.sep)), 'utf8'); + const commit = (message: string): void => { + git(root, 'add', '-A'); + // Tolerate a clean tree so scenario builders can commit unconditionally. + if (git(root, 'status', '--porcelain').trim() !== '') { + git(root, 'commit', '-q', '-m', message); + } + }; + const head = (): string => git(root, 'rev-parse', 'HEAD').trim(); + + if (options.commitBaseline !== false) { + commit('verification baseline'); + } + + const checkTask = (taskId: string): void => { + const relative = `.kiro/specs/${VERIFY_SPEC}/tasks.md`; + const document = MarkdownDocument.load(path.join(root, relative.split('/').join(path.sep))); + const model = parseTasks(document); + const task = model.allTasks.find((candidate) => candidate.id === taskId); + if (task === undefined) throw new Error(`fixture: task ${taskId} not found`); + const line = document.lineAt(task.line).text; + document.setLineText(task.line, line.replace('- [ ]', '- [x]')); + write(relative, document.serialize()); + }; + + const writePolicy = ( + policy: Partial & Record, + ): string => { + const relative = `.specbridge/policies/${VERIFY_SPEC}.json`; + write( + relative, + `${JSON.stringify( + { schemaVersion: '1.0.0', specName: VERIFY_SPEC, ...policy }, + null, + 2, + )}\n`, + ); + return relative; + }; + + const writeVerifiedEvidence = ( + taskId: string, + overrides: Partial & Record = {}, + ): TaskEvidenceRecord => { + evidenceCounter += 1; + const headSha = head(); + const record: TaskEvidenceRecord = { + schemaVersion: EVIDENCE_SCHEMA_VERSION, + runId: `verify-fixture-${String(evidenceCounter).padStart(4, '0')}`, + specName: VERIFY_SPEC, + taskId, + status: 'verified', + runner: 'mock', + repository: { + headBefore: headSha, + headAfter: headSha, + branch: 'main', + dirtyBefore: false, + dirtyAfter: true, + }, + changedFiles: [ + { path: 'src/settings.txt', changeType: 'modified', preExisting: true, modifiedDuringRun: true }, + ], + verificationCommands: [ + { name: 'test', argv: [process.execPath, '-e', '0'], required: true, exitCode: 0, durationMs: 10, passed: true }, + ], + verificationSkipped: false, + runnerClaims: { changedFiles: [], commandsReported: [], testsReported: [] }, + violations: [], + warnings: [], + evaluatedAt: clock().toISOString(), + specContext: currentSpecContext(workspace, VERIFY_SPEC, taskId), + ...overrides, + }; + writeTaskEvidence(workspace, record); + return record; + }; + + const verify = async ( + overrides: Partial> = {}, + ): Promise => + verifySpecs({ + workspace, + selection: { mode: 'single', spec: VERIFY_SPEC }, + comparison: { mode: 'working-tree' }, + failOn: 'error', + toolVersion: '0.4.0-test', + clock, + idFactory: () => `verification-${VERIFY_SPEC}`, + ...overrides, + }); + + return { + root, + workspace, + specName: VERIFY_SPEC, + clock, + write, + read, + commit, + head, + checkTask, + writePolicy, + writeVerifiedEvidence, + verify, + }; +} + +/** Every diagnostic (global + per spec) of a verification result. */ +export function allDiagnostics( + result: VerifySpecsResult, +): VerifySpecsResult['report']['globalDiagnostics'] { + return [ + ...result.report.globalDiagnostics, + ...result.report.specResults.flatMap((spec) => spec.diagnostics), + ]; +} + +export function ruleIds(result: VerifySpecsResult): string[] { + return allDiagnostics(result).map((diagnostic) => diagnostic.ruleId); +} diff --git a/tests/workflow/plan-hash-approval.test.ts b/tests/workflow/plan-hash-approval.test.ts new file mode 100644 index 0000000..57c15c3 --- /dev/null +++ b/tests/workflow/plan-hash-approval.test.ts @@ -0,0 +1,155 @@ +import { readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { describe, expect, it } from 'vitest'; +import { analyzeSpec, requireSpec } from '@specbridge/compat-kiro'; +import { TASK_PLAN_HASH_SEMANTICS_VERSION, readSpecState, resolveWorkspace, stateStage, writeSpecState } from '@specbridge/core'; +import { approveStage, evaluateWorkflow } from '@specbridge/workflow'; +import { copyFixtureToTemp } from '../helpers.js'; +import { approveAllStages, tickingClock } from '../helpers-execution.js'; + +/** + * Approval semantics with the v0.4 normalized task-plan hash: + * + * - requirements/design approvals stay exact-byte (any change is stale) + * - checkbox-only tasks.md progress keeps the approval effective + * - any other tasks.md change (text, ids, hierarchy, refs) is stale + * - pre-v0.4 sidecar state (no approvedPlanHash) still validates and + * falls back to exact-byte semantics until the next sanctioned write + */ + +const SPEC = 'settings-persistence'; + +function setup(): { root: string; workspace: NonNullable> } { + const root = copyFixtureToTemp('v03-ready-feature'); + const workspace = resolveWorkspace(root); + if (workspace === undefined) throw new Error('fixture has no workspace'); + approveAllStages(workspace, SPEC, tickingClock()); + return { root, workspace }; +} + +function editFile(root: string, relative: string, edit: (content: string) => string): void { + const filePath = path.join(root, relative.split('/').join(path.sep)); + writeFileSync(filePath, edit(readFileSync(filePath, 'utf8')), 'utf8'); +} + +describe('task-plan approval hash semantics', () => { + it('approving tasks records the exact hash, the plan hash, and the semantics version', () => { + const { workspace } = setup(); + const state = readSpecState(workspace, SPEC).state; + expect(state).toBeDefined(); + const tasks = stateStage(state!, 'tasks'); + expect(tasks?.status).toBe('approved'); + expect(tasks?.approvedHash).toMatch(/^[0-9a-f]{64}$/); + expect(tasks?.approvedPlanHash).toMatch(/^[0-9a-f]{64}$/); + expect(tasks?.hashSemanticsVersion).toBe(TASK_PLAN_HASH_SEMANTICS_VERSION); + expect(tasks?.hashAlgorithm).toBe('sha256'); + // Other stages stay exact-only. + expect(stateStage(state!, 'requirements')?.approvedPlanHash).toBeUndefined(); + expect(stateStage(state!, 'design')?.approvedPlanHash).toBeUndefined(); + }); + + it('checkbox-only progress keeps the tasks approval effective (with an info diagnostic)', () => { + const { root, workspace } = setup(); + editFile(root, `.kiro/specs/${SPEC}/tasks.md`, (content) => + content.replace('- [ ] 1. Implement the settings store', '- [x] 1. Implement the settings store'), + ); + const state = readSpecState(workspace, SPEC).state!; + const evaluation = evaluateWorkflow(workspace, state); + const tasks = evaluation.stages.find((stage) => stage.stage === 'tasks'); + expect(tasks?.effective).toBe('approved'); + expect(tasks?.checkboxProgressOnly).toBe(true); + expect(evaluation.health).toBe('ok'); + expect(evaluation.diagnostics.some((d) => d.code === 'APPROVAL_CHECKBOX_PROGRESS')).toBe(true); + }); + + it('task text changes invalidate the plan approval', () => { + const { root, workspace } = setup(); + editFile(root, `.kiro/specs/${SPEC}/tasks.md`, (content) => + content.replace('Implement the settings store', 'Implement the RENAMED store'), + ); + const evaluation = evaluateWorkflow(workspace, readSpecState(workspace, SPEC).state!); + expect(evaluation.stages.find((stage) => stage.stage === 'tasks')?.effective).toBe( + 'modified-after-approval', + ); + expect(evaluation.health).toBe('stale'); + }); + + it('task ID changes invalidate the plan approval', () => { + const { root, workspace } = setup(); + editFile(root, `.kiro/specs/${SPEC}/tasks.md`, (content) => + content.replace('- [ ] 2.1 Test the successful save path', '- [ ] 2.9 Test the successful save path'), + ); + const evaluation = evaluateWorkflow(workspace, readSpecState(workspace, SPEC).state!); + expect(evaluation.stages.find((stage) => stage.stage === 'tasks')?.effective).toBe( + 'modified-after-approval', + ); + }); + + it('task hierarchy changes invalidate the plan approval', () => { + const { root, workspace } = setup(); + editFile(root, `.kiro/specs/${SPEC}/tasks.md`, (content) => + content.replace(' - [ ] 2.1 Test the successful save path', '- [ ] 2.1 Test the successful save path'), + ); + const evaluation = evaluateWorkflow(workspace, readSpecState(workspace, SPEC).state!); + expect(evaluation.stages.find((stage) => stage.stage === 'tasks')?.effective).toBe( + 'modified-after-approval', + ); + }); + + it('requirements and design approvals remain exact-byte (checkbox-like edits are still stale)', () => { + const { root, workspace } = setup(); + editFile(root, `.kiro/specs/${SPEC}/requirements.md`, (content) => `${content}\nExtra line.\n`); + editFile(root, `.kiro/specs/${SPEC}/design.md`, (content) => content.replace('Overview', 'OVERVIEW')); + const evaluation = evaluateWorkflow(workspace, readSpecState(workspace, SPEC).state!); + expect(evaluation.stages.find((stage) => stage.stage === 'requirements')?.effective).toBe( + 'modified-after-approval', + ); + expect(evaluation.stages.find((stage) => stage.stage === 'design')?.effective).toBe( + 'modified-after-approval', + ); + }); + + it('revoking the tasks approval clears the plan-hash fields', () => { + const { workspace } = setup(); + const spec = analyzeSpec(workspace, requireSpec(workspace, SPEC)); + const result = approveStage(workspace, spec, { stage: 'tasks', revoke: true }); + expect(result.ok).toBe(true); + const tasks = stateStage(readSpecState(workspace, SPEC).state!, 'tasks'); + expect(tasks?.status).toBe('draft'); + expect(tasks?.approvedPlanHash).toBeUndefined(); + expect(tasks?.hashSemanticsVersion).toBeUndefined(); + }); + + it('pre-v0.4 sidecar state without a plan hash still validates and stays exact-byte', () => { + const { root, workspace } = setup(); + // Strip the v0.4 fields, simulating state written by v0.2/v0.3. + const state = readSpecState(workspace, SPEC).state!; + const legacyStages = Object.fromEntries( + Object.entries(state.stages).map(([name, stage]) => { + const clone = { ...(stage as Record) }; + delete clone['approvedPlanHash']; + delete clone['hashAlgorithm']; + delete clone['hashSemanticsVersion']; + return [name, clone]; + }), + ); + writeSpecState(workspace, { ...state, stages: legacyStages as typeof state.stages }); + + const reread = readSpecState(workspace, SPEC); + expect(reread.state).toBeDefined(); + expect(stateStage(reread.state!, 'tasks')?.approvedPlanHash).toBeUndefined(); + + // Untouched file: approval holds. + expect(evaluateWorkflow(workspace, reread.state!).health).toBe('ok'); + + // Checkbox flip without a stored plan hash: falls back to exact-byte + // semantics — stale, exactly as v0.3 behaved. + editFile(root, `.kiro/specs/${SPEC}/tasks.md`, (content) => + content.replace('- [ ] 1. Implement the settings store', '- [x] 1. Implement the settings store'), + ); + const evaluation = evaluateWorkflow(workspace, readSpecState(workspace, SPEC).state!); + expect(evaluation.stages.find((stage) => stage.stage === 'tasks')?.effective).toBe( + 'modified-after-approval', + ); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 3908730..c792a5e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,8 @@ "include": [ "packages/*/src/**/*.ts", "packages/*/tsup.config.ts", + "integrations/github-action/src/**/*.ts", + "integrations/github-action/tsup.config.ts", "tests/**/*.ts", "vitest.config.ts" ]