diff --git a/.claude/skills/run-e2e-pixel-sweep/SKILL.md b/.claude/skills/run-e2e-pixel-sweep/SKILL.md index 3594a60..40d9b24 100644 --- a/.claude/skills/run-e2e-pixel-sweep/SKILL.md +++ b/.claude/skills/run-e2e-pixel-sweep/SKILL.md @@ -1,23 +1,24 @@ --- name: run-e2e-pixel-sweep description: >- - Run the repeatable OpenLoop 4-emulator E2E sweep (Pixel 6, Pixel 8, Pixel 10 Pro Fold, Pixel 8 - API 34) using the canonical imported test video: build once, then per device cold-boot → + Run the repeatable OpenLoop Pixel 8 E2E sweep, adding the Pixel 10 Pro Fold only for + posture/preview changes and Pixel 8 API 34 only for FGS/WorkManager changes or releases, using + the canonical imported test video: build once, then per device cold-boot → scripted import → trim → speed → all four loop directions (real reverse previews) → B&W look → save → share sheet → gallery playback, followed by a programmatic output-quality gate (per-half fps, mirror SSIM, freeze/green/black scans) and a logcat scan. Use whenever the user says - "pixel sweep", "run the 4-device e2e", "/run-e2e-pixel-sweep", "api 34 fgs regression", + "pixel sweep", "run the device e2e", "/run-e2e-pixel-sweep", "api 34 fgs regression", "samsung rtl sweep", "/samsung-rtl-sweep", "regression-test the boomerang flow on the emulators", or wants proof a media-pipeline or foreground-service change didn't break the import→save path on Google devices and Android 14. Scripts compute every gesture from uiautomator bounds, so they run unmodified on any screen size. --- -# run-e2e-pixel-sweep — the repeatable 4-emulator OpenLoop sweep +# run-e2e-pixel-sweep — the repeatable risk-based OpenLoop sweep Proven end-to-end on 2026-06-04 (fold-loop iterations 1–2 + scripted validation runs on Pixel 6 and the Fold) and 2026-06-22 (API-34 FGS fix verification on `Pixel_8_API34`). -One sweep ≈ 10 minutes/device, ~40 minutes total, fully scripted — your job is to run the +The default `Pixel_8` sweep is ≈ 10 minutes; each risk-triggered lane adds ≈ 10 minutes. Run the phases, read the PASS/FAIL lines, and apply judgment where the scripts explicitly hand it back (borderline SSIM, any FAIL, churn growth). @@ -36,9 +37,9 @@ tell the user; do not substitute another video. ## Preconditions (verify, never assume) -- AVDs `Pixel_6`, `Pixel_8`, `Pixel_10_Pro_Fold`, and **`Pixel_8_API34`** exist +- The default AVD `Pixel_8` exists (`& "$env:LOCALAPPDATA\Android\Sdk\emulator\emulator.exe" -list-avds`). - If `Pixel_8_API34` is missing, create it: + For an API-34 lane, create `Pixel_8_API34` when missing: `pwsh \scripts\create-api34-avd.ps1` (requires the `system-images;android-34;google_apis_playstore;x86_64` SDK image). - ffmpeg/ffprobe on PATH (`winget install Gyan.FFmpeg` if not). @@ -48,21 +49,24 @@ tell the user; do not substitute another video. `$LASTEXITCODE -eq 0` **and** zero `e:` lines. If you change code mid-sweep, rebuild and re-run every device that already passed — a pass on a stale APK doesn't count. -## The sweep (run for each AVD, sequentially, in this order) +## The sweep -Order: `Pixel_6` → `Pixel_8` → `Pixel_10_Pro_Fold` → **`Pixel_8_API34`**. One emulator at a -time — parallel emulators fight over host CPU/codecs and fake contention bugs. +Default: run `Pixel_8` only. It covers the complete import → trim → all directions → look → save → +share → gallery flow plus encoded-output and logcat gates. `Pixel_6` covers the same stock-Android, +standard-form-factor risk and is not a second default lane. -**Why `Pixel_8_API34` last:** it runs **Android 14 (API 34)** — the OS level where -`FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING` (8192) is *not recognized* and v1.0.23 crashed every -Loopify save with `InvalidForegroundServiceTypeException: Starting FGS with type unknown` -(Crashlytics 9663c743, Galaxy A55). The fix gates to `dataSync` on API 29–34. After the three -API-35+ emulators pass, this device is the **mandatory FGS regression gate**: a green save + -`Worker result SUCCESS` for `BoomerangRenderWorker` and **zero** `InvalidForegroundServiceTypeException` -lines in logcat. See [`docs/guides/oem-regression-testing.md`](../../../docs/guides/oem-regression-testing.md) lane 1 (API 34 FGS). +Add only the lane whose distinct risk changed: + +- `Pixel_10_Pro_Fold -Fold` for posture, preview, insets, or camera-surface changes. +- `Pixel_8_API34` for FGS, WorkManager, notification, or manifest service changes, and once per + release. The JVM suite always checks the SDK-to-FGS-type mapping; this lane proves the real API-34 + service starts and saves. + +Run selected AVDs sequentially — parallel emulators fight over host CPU/codecs and fake contention +bugs. See [`docs/guides/oem-regression-testing.md`](../../../docs/guides/oem-regression-testing.md). ```powershell -$avd = "Pixel_6" # then Pixel_8, then Pixel_10_Pro_Fold, then Pixel_8_API34 +$avd = "Pixel_8" # add only a risk-triggered lane listed above $dir = "$env:TEMP\openloop_sweep\$avd" # 1. Cold-boot + install (fresh app state) + push video + start logcat capture + launch. @@ -92,7 +96,7 @@ Not all OEM bugs reproduce on stock emulators. Use the right lane: | Lane | What it catches | How to run | Emulator? | | -------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------- | -| **API 34 FGS** | `InvalidForegroundServiceTypeException` on Android 14 saves (9663c743) | 4th device in sweep: `Pixel_8_API34` | ✅ Stock AVD | +| **API 34 FGS** | `InvalidForegroundServiceTypeException` on Android 14 saves (9663c743) | `Pixel_8_API34` for FGS/WorkManager changes and each release | ✅ Stock AVD | | **Samsung codec + preview cap** | Exynos/QC wedging, 480p preview cap, `c2.google` encoder order | **Samsung RTL sweep** (real Galaxy) | ❌ Use RTL | | **Samsung app logic (identity)** | `isSamsungDevice()` branches, preview cap, encoder ordering policy | JVM: `DeviceMediaHintsOemRobolectricTest` + `SamsungReversePreviewRegressionTest` | ✅ Robolectric | | **LG `start failed` recovery** | Hardware codec rejects `start()` → software fallback (47233ad7) | Instrumented: `VideoReverserTest.reverse_recoversFromCodecStartFailure_viaSoftwareFallback` | ✅ Any device/emulator | @@ -143,15 +147,15 @@ device-specific Crashlytics issue is fixed from emulator evidence alone). ## Reading failures — signature → meaning -| Signature | Meaning | -| ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `process died` + `ShortcutService: clearing data for package` within ~15 s of capture start, app relaunches fine | **Harness artifact, not an app bug**: `pm clear`'s data wipe is partly async and its deferred SIGKILL caught the launch. sweep-prep orders + settles to avoid this and drive-flow self-heals; if it still fires, re-run the device before filing anything. | -| `Timed out after 120` / `ensureReversed.timeout` | Reverse wedge. On a COLD-booted emulator this is real — capture `dumpsys media.codec` during the stall and check `OpenLoopReverse` for which pass stalled. On a warm-booted one, cold boot first before blaming code. | -| first-half fps ≈ 15, second ≈ 30 | Pass-1 subsampling regression (BUG-1 family) — check `reverse pass1:` log line for `skipped=` ≠ 0 on this 30 fps source. | -| Moving-region macroblock smear in reversed half, static background clean | Compressed samples dropped before the decoder (broken P-frame references). Pull the cached reversed clip from `cache/scratch/reversed/` to isolate reverser vs Transformer. | -| `MPEG4Writer … encoded 0 frames` + tiny output | Zero-frame completion (S23 family, PR #62 validator territory) — different from a timeout. | -| `InvalidForegroundServiceTypeException` / `Starting FGS with type unknown` on API 34 | **FGS type regression** — the worker is passing `mediaProcessing` (8192) on Android 14. Check `BoomerangRenderNotifications.foregroundServiceTypeForSdk` gates on `VANILLA_ICE_CREAM` (35), not `UPSIDE_DOWN_CAKE` (34). Only fires on `Pixel_8_API34`; the three API-35+ emulators won't catch it. | -| `ChooserPreview: Could not read content://…fileprovider…` ×3 | Cosmetic — the OS share-sheet preview can't query FileProvider metadata. Ignore. | +| Signature | Meaning | +| ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `process died` + `ShortcutService: clearing data for package` within ~15 s of capture start, app relaunches fine | **Harness artifact, not an app bug**: `pm clear`'s data wipe is partly async and its deferred SIGKILL caught the launch. sweep-prep orders + settles to avoid this and drive-flow self-heals; if it still fires, re-run the device before filing anything. | +| `Timed out after 120` / `ensureReversed.timeout` | Reverse wedge. On a COLD-booted emulator this is real — capture `dumpsys media.codec` during the stall and check `OpenLoopReverse` for which pass stalled. On a warm-booted one, cold boot first before blaming code. | +| first-half fps ≈ 15, second ≈ 30 | Pass-1 subsampling regression (BUG-1 family) — check `reverse pass1:` log line for `skipped=` ≠ 0 on this 30 fps source. | +| Moving-region macroblock smear in reversed half, static background clean | Compressed samples dropped before the decoder (broken P-frame references). Pull the cached reversed clip from `cache/scratch/reversed/` to isolate reverser vs Transformer. | +| `MPEG4Writer … encoded 0 frames` + tiny output | Zero-frame completion (S23 family, PR #62 validator territory) — different from a timeout. | +| `InvalidForegroundServiceTypeException` / `Starting FGS with type unknown` on API 34 | **FGS type regression** — the worker is passing `mediaProcessing` (8192) on Android 14. Check `BoomerangRenderNotifications.foregroundServiceTypeForSdk` gates on `VANILLA_ICE_CREAM` (35), not `UPSIDE_DOWN_CAKE` (34). Only fires on `Pixel_8_API34`; the default API-35+ emulator won't catch it. | +| `ChooserPreview: Could not read content://…fileprovider…` ×3 | Cosmetic — the OS share-sheet preview can't query FileProvider metadata. Ignore. | ## Field notes (each of these cost real time once — don't relearn them) @@ -191,7 +195,7 @@ device-specific Crashlytics issue is fixed from emulator evidence alone). on these emulators, but budget 130 s / 150 s before declaring a stall. 13. **Renders are deterministic** for identical trim windows — same SSIM to 6 decimal places across runs. Useful: a changed SSIM means the pipeline changed, not noise. -14. **Emulator quirks:** all three AVDs report model `sdk_gphone16k_x86_64` (verify identity +14. **Emulator quirks:** the stock AVDs report model `sdk_gphone16k_x86_64` (verify identity with `adb emu avd name`, not the model prop); adb sometimes holds a stale `localhost:NNNNN` transport — always pass `-s $serial`. 15. **API 34 Photo Picker + Download/:** `sweep-prep` pushes the fixture to `Download/` on diff --git a/.codex/skills/run-e2e-pixel-sweep/SKILL.md b/.codex/skills/run-e2e-pixel-sweep/SKILL.md index 3594a60..40d9b24 100644 --- a/.codex/skills/run-e2e-pixel-sweep/SKILL.md +++ b/.codex/skills/run-e2e-pixel-sweep/SKILL.md @@ -1,23 +1,24 @@ --- name: run-e2e-pixel-sweep description: >- - Run the repeatable OpenLoop 4-emulator E2E sweep (Pixel 6, Pixel 8, Pixel 10 Pro Fold, Pixel 8 - API 34) using the canonical imported test video: build once, then per device cold-boot → + Run the repeatable OpenLoop Pixel 8 E2E sweep, adding the Pixel 10 Pro Fold only for + posture/preview changes and Pixel 8 API 34 only for FGS/WorkManager changes or releases, using + the canonical imported test video: build once, then per device cold-boot → scripted import → trim → speed → all four loop directions (real reverse previews) → B&W look → save → share sheet → gallery playback, followed by a programmatic output-quality gate (per-half fps, mirror SSIM, freeze/green/black scans) and a logcat scan. Use whenever the user says - "pixel sweep", "run the 4-device e2e", "/run-e2e-pixel-sweep", "api 34 fgs regression", + "pixel sweep", "run the device e2e", "/run-e2e-pixel-sweep", "api 34 fgs regression", "samsung rtl sweep", "/samsung-rtl-sweep", "regression-test the boomerang flow on the emulators", or wants proof a media-pipeline or foreground-service change didn't break the import→save path on Google devices and Android 14. Scripts compute every gesture from uiautomator bounds, so they run unmodified on any screen size. --- -# run-e2e-pixel-sweep — the repeatable 4-emulator OpenLoop sweep +# run-e2e-pixel-sweep — the repeatable risk-based OpenLoop sweep Proven end-to-end on 2026-06-04 (fold-loop iterations 1–2 + scripted validation runs on Pixel 6 and the Fold) and 2026-06-22 (API-34 FGS fix verification on `Pixel_8_API34`). -One sweep ≈ 10 minutes/device, ~40 minutes total, fully scripted — your job is to run the +The default `Pixel_8` sweep is ≈ 10 minutes; each risk-triggered lane adds ≈ 10 minutes. Run the phases, read the PASS/FAIL lines, and apply judgment where the scripts explicitly hand it back (borderline SSIM, any FAIL, churn growth). @@ -36,9 +37,9 @@ tell the user; do not substitute another video. ## Preconditions (verify, never assume) -- AVDs `Pixel_6`, `Pixel_8`, `Pixel_10_Pro_Fold`, and **`Pixel_8_API34`** exist +- The default AVD `Pixel_8` exists (`& "$env:LOCALAPPDATA\Android\Sdk\emulator\emulator.exe" -list-avds`). - If `Pixel_8_API34` is missing, create it: + For an API-34 lane, create `Pixel_8_API34` when missing: `pwsh \scripts\create-api34-avd.ps1` (requires the `system-images;android-34;google_apis_playstore;x86_64` SDK image). - ffmpeg/ffprobe on PATH (`winget install Gyan.FFmpeg` if not). @@ -48,21 +49,24 @@ tell the user; do not substitute another video. `$LASTEXITCODE -eq 0` **and** zero `e:` lines. If you change code mid-sweep, rebuild and re-run every device that already passed — a pass on a stale APK doesn't count. -## The sweep (run for each AVD, sequentially, in this order) +## The sweep -Order: `Pixel_6` → `Pixel_8` → `Pixel_10_Pro_Fold` → **`Pixel_8_API34`**. One emulator at a -time — parallel emulators fight over host CPU/codecs and fake contention bugs. +Default: run `Pixel_8` only. It covers the complete import → trim → all directions → look → save → +share → gallery flow plus encoded-output and logcat gates. `Pixel_6` covers the same stock-Android, +standard-form-factor risk and is not a second default lane. -**Why `Pixel_8_API34` last:** it runs **Android 14 (API 34)** — the OS level where -`FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING` (8192) is *not recognized* and v1.0.23 crashed every -Loopify save with `InvalidForegroundServiceTypeException: Starting FGS with type unknown` -(Crashlytics 9663c743, Galaxy A55). The fix gates to `dataSync` on API 29–34. After the three -API-35+ emulators pass, this device is the **mandatory FGS regression gate**: a green save + -`Worker result SUCCESS` for `BoomerangRenderWorker` and **zero** `InvalidForegroundServiceTypeException` -lines in logcat. See [`docs/guides/oem-regression-testing.md`](../../../docs/guides/oem-regression-testing.md) lane 1 (API 34 FGS). +Add only the lane whose distinct risk changed: + +- `Pixel_10_Pro_Fold -Fold` for posture, preview, insets, or camera-surface changes. +- `Pixel_8_API34` for FGS, WorkManager, notification, or manifest service changes, and once per + release. The JVM suite always checks the SDK-to-FGS-type mapping; this lane proves the real API-34 + service starts and saves. + +Run selected AVDs sequentially — parallel emulators fight over host CPU/codecs and fake contention +bugs. See [`docs/guides/oem-regression-testing.md`](../../../docs/guides/oem-regression-testing.md). ```powershell -$avd = "Pixel_6" # then Pixel_8, then Pixel_10_Pro_Fold, then Pixel_8_API34 +$avd = "Pixel_8" # add only a risk-triggered lane listed above $dir = "$env:TEMP\openloop_sweep\$avd" # 1. Cold-boot + install (fresh app state) + push video + start logcat capture + launch. @@ -92,7 +96,7 @@ Not all OEM bugs reproduce on stock emulators. Use the right lane: | Lane | What it catches | How to run | Emulator? | | -------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------- | -| **API 34 FGS** | `InvalidForegroundServiceTypeException` on Android 14 saves (9663c743) | 4th device in sweep: `Pixel_8_API34` | ✅ Stock AVD | +| **API 34 FGS** | `InvalidForegroundServiceTypeException` on Android 14 saves (9663c743) | `Pixel_8_API34` for FGS/WorkManager changes and each release | ✅ Stock AVD | | **Samsung codec + preview cap** | Exynos/QC wedging, 480p preview cap, `c2.google` encoder order | **Samsung RTL sweep** (real Galaxy) | ❌ Use RTL | | **Samsung app logic (identity)** | `isSamsungDevice()` branches, preview cap, encoder ordering policy | JVM: `DeviceMediaHintsOemRobolectricTest` + `SamsungReversePreviewRegressionTest` | ✅ Robolectric | | **LG `start failed` recovery** | Hardware codec rejects `start()` → software fallback (47233ad7) | Instrumented: `VideoReverserTest.reverse_recoversFromCodecStartFailure_viaSoftwareFallback` | ✅ Any device/emulator | @@ -143,15 +147,15 @@ device-specific Crashlytics issue is fixed from emulator evidence alone). ## Reading failures — signature → meaning -| Signature | Meaning | -| ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `process died` + `ShortcutService: clearing data for package` within ~15 s of capture start, app relaunches fine | **Harness artifact, not an app bug**: `pm clear`'s data wipe is partly async and its deferred SIGKILL caught the launch. sweep-prep orders + settles to avoid this and drive-flow self-heals; if it still fires, re-run the device before filing anything. | -| `Timed out after 120` / `ensureReversed.timeout` | Reverse wedge. On a COLD-booted emulator this is real — capture `dumpsys media.codec` during the stall and check `OpenLoopReverse` for which pass stalled. On a warm-booted one, cold boot first before blaming code. | -| first-half fps ≈ 15, second ≈ 30 | Pass-1 subsampling regression (BUG-1 family) — check `reverse pass1:` log line for `skipped=` ≠ 0 on this 30 fps source. | -| Moving-region macroblock smear in reversed half, static background clean | Compressed samples dropped before the decoder (broken P-frame references). Pull the cached reversed clip from `cache/scratch/reversed/` to isolate reverser vs Transformer. | -| `MPEG4Writer … encoded 0 frames` + tiny output | Zero-frame completion (S23 family, PR #62 validator territory) — different from a timeout. | -| `InvalidForegroundServiceTypeException` / `Starting FGS with type unknown` on API 34 | **FGS type regression** — the worker is passing `mediaProcessing` (8192) on Android 14. Check `BoomerangRenderNotifications.foregroundServiceTypeForSdk` gates on `VANILLA_ICE_CREAM` (35), not `UPSIDE_DOWN_CAKE` (34). Only fires on `Pixel_8_API34`; the three API-35+ emulators won't catch it. | -| `ChooserPreview: Could not read content://…fileprovider…` ×3 | Cosmetic — the OS share-sheet preview can't query FileProvider metadata. Ignore. | +| Signature | Meaning | +| ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `process died` + `ShortcutService: clearing data for package` within ~15 s of capture start, app relaunches fine | **Harness artifact, not an app bug**: `pm clear`'s data wipe is partly async and its deferred SIGKILL caught the launch. sweep-prep orders + settles to avoid this and drive-flow self-heals; if it still fires, re-run the device before filing anything. | +| `Timed out after 120` / `ensureReversed.timeout` | Reverse wedge. On a COLD-booted emulator this is real — capture `dumpsys media.codec` during the stall and check `OpenLoopReverse` for which pass stalled. On a warm-booted one, cold boot first before blaming code. | +| first-half fps ≈ 15, second ≈ 30 | Pass-1 subsampling regression (BUG-1 family) — check `reverse pass1:` log line for `skipped=` ≠ 0 on this 30 fps source. | +| Moving-region macroblock smear in reversed half, static background clean | Compressed samples dropped before the decoder (broken P-frame references). Pull the cached reversed clip from `cache/scratch/reversed/` to isolate reverser vs Transformer. | +| `MPEG4Writer … encoded 0 frames` + tiny output | Zero-frame completion (S23 family, PR #62 validator territory) — different from a timeout. | +| `InvalidForegroundServiceTypeException` / `Starting FGS with type unknown` on API 34 | **FGS type regression** — the worker is passing `mediaProcessing` (8192) on Android 14. Check `BoomerangRenderNotifications.foregroundServiceTypeForSdk` gates on `VANILLA_ICE_CREAM` (35), not `UPSIDE_DOWN_CAKE` (34). Only fires on `Pixel_8_API34`; the default API-35+ emulator won't catch it. | +| `ChooserPreview: Could not read content://…fileprovider…` ×3 | Cosmetic — the OS share-sheet preview can't query FileProvider metadata. Ignore. | ## Field notes (each of these cost real time once — don't relearn them) @@ -191,7 +195,7 @@ device-specific Crashlytics issue is fixed from emulator evidence alone). on these emulators, but budget 130 s / 150 s before declaring a stall. 13. **Renders are deterministic** for identical trim windows — same SSIM to 6 decimal places across runs. Useful: a changed SSIM means the pipeline changed, not noise. -14. **Emulator quirks:** all three AVDs report model `sdk_gphone16k_x86_64` (verify identity +14. **Emulator quirks:** the stock AVDs report model `sdk_gphone16k_x86_64` (verify identity with `adb emu avd name`, not the model prop); adb sometimes holds a stale `localhost:NNNNN` transport — always pass `-s $serial`. 15. **API 34 Photo Picker + Download/:** `sweep-prep` pushes the fixture to `Download/` on diff --git a/.cursor/skills/run-e2e-pixel-sweep/SKILL.md b/.cursor/skills/run-e2e-pixel-sweep/SKILL.md index 3594a60..40d9b24 100644 --- a/.cursor/skills/run-e2e-pixel-sweep/SKILL.md +++ b/.cursor/skills/run-e2e-pixel-sweep/SKILL.md @@ -1,23 +1,24 @@ --- name: run-e2e-pixel-sweep description: >- - Run the repeatable OpenLoop 4-emulator E2E sweep (Pixel 6, Pixel 8, Pixel 10 Pro Fold, Pixel 8 - API 34) using the canonical imported test video: build once, then per device cold-boot → + Run the repeatable OpenLoop Pixel 8 E2E sweep, adding the Pixel 10 Pro Fold only for + posture/preview changes and Pixel 8 API 34 only for FGS/WorkManager changes or releases, using + the canonical imported test video: build once, then per device cold-boot → scripted import → trim → speed → all four loop directions (real reverse previews) → B&W look → save → share sheet → gallery playback, followed by a programmatic output-quality gate (per-half fps, mirror SSIM, freeze/green/black scans) and a logcat scan. Use whenever the user says - "pixel sweep", "run the 4-device e2e", "/run-e2e-pixel-sweep", "api 34 fgs regression", + "pixel sweep", "run the device e2e", "/run-e2e-pixel-sweep", "api 34 fgs regression", "samsung rtl sweep", "/samsung-rtl-sweep", "regression-test the boomerang flow on the emulators", or wants proof a media-pipeline or foreground-service change didn't break the import→save path on Google devices and Android 14. Scripts compute every gesture from uiautomator bounds, so they run unmodified on any screen size. --- -# run-e2e-pixel-sweep — the repeatable 4-emulator OpenLoop sweep +# run-e2e-pixel-sweep — the repeatable risk-based OpenLoop sweep Proven end-to-end on 2026-06-04 (fold-loop iterations 1–2 + scripted validation runs on Pixel 6 and the Fold) and 2026-06-22 (API-34 FGS fix verification on `Pixel_8_API34`). -One sweep ≈ 10 minutes/device, ~40 minutes total, fully scripted — your job is to run the +The default `Pixel_8` sweep is ≈ 10 minutes; each risk-triggered lane adds ≈ 10 minutes. Run the phases, read the PASS/FAIL lines, and apply judgment where the scripts explicitly hand it back (borderline SSIM, any FAIL, churn growth). @@ -36,9 +37,9 @@ tell the user; do not substitute another video. ## Preconditions (verify, never assume) -- AVDs `Pixel_6`, `Pixel_8`, `Pixel_10_Pro_Fold`, and **`Pixel_8_API34`** exist +- The default AVD `Pixel_8` exists (`& "$env:LOCALAPPDATA\Android\Sdk\emulator\emulator.exe" -list-avds`). - If `Pixel_8_API34` is missing, create it: + For an API-34 lane, create `Pixel_8_API34` when missing: `pwsh \scripts\create-api34-avd.ps1` (requires the `system-images;android-34;google_apis_playstore;x86_64` SDK image). - ffmpeg/ffprobe on PATH (`winget install Gyan.FFmpeg` if not). @@ -48,21 +49,24 @@ tell the user; do not substitute another video. `$LASTEXITCODE -eq 0` **and** zero `e:` lines. If you change code mid-sweep, rebuild and re-run every device that already passed — a pass on a stale APK doesn't count. -## The sweep (run for each AVD, sequentially, in this order) +## The sweep -Order: `Pixel_6` → `Pixel_8` → `Pixel_10_Pro_Fold` → **`Pixel_8_API34`**. One emulator at a -time — parallel emulators fight over host CPU/codecs and fake contention bugs. +Default: run `Pixel_8` only. It covers the complete import → trim → all directions → look → save → +share → gallery flow plus encoded-output and logcat gates. `Pixel_6` covers the same stock-Android, +standard-form-factor risk and is not a second default lane. -**Why `Pixel_8_API34` last:** it runs **Android 14 (API 34)** — the OS level where -`FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING` (8192) is *not recognized* and v1.0.23 crashed every -Loopify save with `InvalidForegroundServiceTypeException: Starting FGS with type unknown` -(Crashlytics 9663c743, Galaxy A55). The fix gates to `dataSync` on API 29–34. After the three -API-35+ emulators pass, this device is the **mandatory FGS regression gate**: a green save + -`Worker result SUCCESS` for `BoomerangRenderWorker` and **zero** `InvalidForegroundServiceTypeException` -lines in logcat. See [`docs/guides/oem-regression-testing.md`](../../../docs/guides/oem-regression-testing.md) lane 1 (API 34 FGS). +Add only the lane whose distinct risk changed: + +- `Pixel_10_Pro_Fold -Fold` for posture, preview, insets, or camera-surface changes. +- `Pixel_8_API34` for FGS, WorkManager, notification, or manifest service changes, and once per + release. The JVM suite always checks the SDK-to-FGS-type mapping; this lane proves the real API-34 + service starts and saves. + +Run selected AVDs sequentially — parallel emulators fight over host CPU/codecs and fake contention +bugs. See [`docs/guides/oem-regression-testing.md`](../../../docs/guides/oem-regression-testing.md). ```powershell -$avd = "Pixel_6" # then Pixel_8, then Pixel_10_Pro_Fold, then Pixel_8_API34 +$avd = "Pixel_8" # add only a risk-triggered lane listed above $dir = "$env:TEMP\openloop_sweep\$avd" # 1. Cold-boot + install (fresh app state) + push video + start logcat capture + launch. @@ -92,7 +96,7 @@ Not all OEM bugs reproduce on stock emulators. Use the right lane: | Lane | What it catches | How to run | Emulator? | | -------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------- | -| **API 34 FGS** | `InvalidForegroundServiceTypeException` on Android 14 saves (9663c743) | 4th device in sweep: `Pixel_8_API34` | ✅ Stock AVD | +| **API 34 FGS** | `InvalidForegroundServiceTypeException` on Android 14 saves (9663c743) | `Pixel_8_API34` for FGS/WorkManager changes and each release | ✅ Stock AVD | | **Samsung codec + preview cap** | Exynos/QC wedging, 480p preview cap, `c2.google` encoder order | **Samsung RTL sweep** (real Galaxy) | ❌ Use RTL | | **Samsung app logic (identity)** | `isSamsungDevice()` branches, preview cap, encoder ordering policy | JVM: `DeviceMediaHintsOemRobolectricTest` + `SamsungReversePreviewRegressionTest` | ✅ Robolectric | | **LG `start failed` recovery** | Hardware codec rejects `start()` → software fallback (47233ad7) | Instrumented: `VideoReverserTest.reverse_recoversFromCodecStartFailure_viaSoftwareFallback` | ✅ Any device/emulator | @@ -143,15 +147,15 @@ device-specific Crashlytics issue is fixed from emulator evidence alone). ## Reading failures — signature → meaning -| Signature | Meaning | -| ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `process died` + `ShortcutService: clearing data for package` within ~15 s of capture start, app relaunches fine | **Harness artifact, not an app bug**: `pm clear`'s data wipe is partly async and its deferred SIGKILL caught the launch. sweep-prep orders + settles to avoid this and drive-flow self-heals; if it still fires, re-run the device before filing anything. | -| `Timed out after 120` / `ensureReversed.timeout` | Reverse wedge. On a COLD-booted emulator this is real — capture `dumpsys media.codec` during the stall and check `OpenLoopReverse` for which pass stalled. On a warm-booted one, cold boot first before blaming code. | -| first-half fps ≈ 15, second ≈ 30 | Pass-1 subsampling regression (BUG-1 family) — check `reverse pass1:` log line for `skipped=` ≠ 0 on this 30 fps source. | -| Moving-region macroblock smear in reversed half, static background clean | Compressed samples dropped before the decoder (broken P-frame references). Pull the cached reversed clip from `cache/scratch/reversed/` to isolate reverser vs Transformer. | -| `MPEG4Writer … encoded 0 frames` + tiny output | Zero-frame completion (S23 family, PR #62 validator territory) — different from a timeout. | -| `InvalidForegroundServiceTypeException` / `Starting FGS with type unknown` on API 34 | **FGS type regression** — the worker is passing `mediaProcessing` (8192) on Android 14. Check `BoomerangRenderNotifications.foregroundServiceTypeForSdk` gates on `VANILLA_ICE_CREAM` (35), not `UPSIDE_DOWN_CAKE` (34). Only fires on `Pixel_8_API34`; the three API-35+ emulators won't catch it. | -| `ChooserPreview: Could not read content://…fileprovider…` ×3 | Cosmetic — the OS share-sheet preview can't query FileProvider metadata. Ignore. | +| Signature | Meaning | +| ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `process died` + `ShortcutService: clearing data for package` within ~15 s of capture start, app relaunches fine | **Harness artifact, not an app bug**: `pm clear`'s data wipe is partly async and its deferred SIGKILL caught the launch. sweep-prep orders + settles to avoid this and drive-flow self-heals; if it still fires, re-run the device before filing anything. | +| `Timed out after 120` / `ensureReversed.timeout` | Reverse wedge. On a COLD-booted emulator this is real — capture `dumpsys media.codec` during the stall and check `OpenLoopReverse` for which pass stalled. On a warm-booted one, cold boot first before blaming code. | +| first-half fps ≈ 15, second ≈ 30 | Pass-1 subsampling regression (BUG-1 family) — check `reverse pass1:` log line for `skipped=` ≠ 0 on this 30 fps source. | +| Moving-region macroblock smear in reversed half, static background clean | Compressed samples dropped before the decoder (broken P-frame references). Pull the cached reversed clip from `cache/scratch/reversed/` to isolate reverser vs Transformer. | +| `MPEG4Writer … encoded 0 frames` + tiny output | Zero-frame completion (S23 family, PR #62 validator territory) — different from a timeout. | +| `InvalidForegroundServiceTypeException` / `Starting FGS with type unknown` on API 34 | **FGS type regression** — the worker is passing `mediaProcessing` (8192) on Android 14. Check `BoomerangRenderNotifications.foregroundServiceTypeForSdk` gates on `VANILLA_ICE_CREAM` (35), not `UPSIDE_DOWN_CAKE` (34). Only fires on `Pixel_8_API34`; the default API-35+ emulator won't catch it. | +| `ChooserPreview: Could not read content://…fileprovider…` ×3 | Cosmetic — the OS share-sheet preview can't query FileProvider metadata. Ignore. | ## Field notes (each of these cost real time once — don't relearn them) @@ -191,7 +195,7 @@ device-specific Crashlytics issue is fixed from emulator evidence alone). on these emulators, but budget 130 s / 150 s before declaring a stall. 13. **Renders are deterministic** for identical trim windows — same SSIM to 6 decimal places across runs. Useful: a changed SSIM means the pipeline changed, not noise. -14. **Emulator quirks:** all three AVDs report model `sdk_gphone16k_x86_64` (verify identity +14. **Emulator quirks:** the stock AVDs report model `sdk_gphone16k_x86_64` (verify identity with `adb emu avd name`, not the model prop); adb sometimes holds a stale `localhost:NNNNN` transport — always pass `-s $serial`. 15. **API 34 Photo Picker + Download/:** `sweep-prep` pushes the fixture to `Download/` on diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 5c1888f..875d7cc 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -28,12 +28,15 @@ jobs: with: node-version: '22' - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v7 with: python-version: '3.12' + - name: Install pinned text-gate tools + run: npm ci --ignore-scripts + - name: markdownlint-cli2 (0 findings) - run: npx --yes markdownlint-cli2 $(git ls-files '*.md') + run: ./node_modules/.bin/markdownlint-cli2 $(git ls-files '*.md') - name: Table alignment (0 misaligned) run: python scripts/md-table-align.py @@ -56,7 +59,7 @@ jobs: while IFS= read -r f; do [[ -z "$f" ]] && continue count=$((count + 1)) - npx --yes markdown-link-check --config .markdown-link-check.json -q "$f" | tee -a link-check.log || dead=1 + ./node_modules/.bin/markdown-link-check --config .markdown-link-check.json -q "$f" | tee -a link-check.log || dead=1 done < link-files.txt echo "checked $count Markdown file(s); scope=$scope" exit $dead @@ -77,7 +80,7 @@ jobs: run: | git ls-files '*.md' '*.kt' '*.kts' '*.xml' '*.yml' '*.yaml' '*.ps1' '*.py' '*.mjs' '*.js' \ '*.json' '*.jsonc' '*.properties' '*.html' '*.toml' '*.pro' '*.template' '*.README' '*.txt' '*.dic' \ - | npx --yes cspell --no-progress --file-list stdin # `--file-list ` can exit 1 silently on Windows; stdin is uniform + | ./node_modules/.bin/cspell --no-progress --file-list stdin # `--file-list ` can exit 1 silently on Windows; stdin is uniform - name: JSON validity + IDE dictionary in sync run: | diff --git a/.gitignore b/.gitignore index 6032579..84bbbe7 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ google-pro-fold-video.mp4 # Cloud Functions (Firebase) — dependencies are regenerated by `npm install` and # excluded from deploy via firebase.json; never commit them. +/node_modules/ functions/node_modules/ .firebase/ firebase-debug.log diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 94fa7bb..a438f12 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -33,8 +33,8 @@ android { // move; re-evaluate then. OldTargetApi suppressed at the source per STATIC_ANALYSIS.md. //noinspection OldTargetApi targetSdk = 36 - versionCode = 50 - versionName = "1.0.50" + versionCode = 51 + versionName = "1.0.51" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/cspell.json b/cspell.json index c0d984b..accfc14 100644 --- a/cspell.json +++ b/cspell.json @@ -13,6 +13,7 @@ "**/*.svg", "**/*.ico", "**/lint-baseline.xml", + "package-lock.json", "gradle/wrapper/**", "cspell.json", ".idea/dictionaries/**", diff --git a/docs/DEFINITION_OF_DONE.md b/docs/DEFINITION_OF_DONE.md index 841e8af..1b87893 100644 --- a/docs/DEFINITION_OF_DONE.md +++ b/docs/DEFINITION_OF_DONE.md @@ -12,7 +12,7 @@ The guiding principle: **don't trust "it compiles" — prove it.** Prove it buil - "Not my change" is **not** a reason to leave a red build. If you touch a module and its tests don't compile or don't pass, you fix them as part of the work. If the fix is genuinely out of scope, you **stop and flag it to the owner and get explicit direction** — you do not open a PR on top of a known-broken baseline. - A PR must be opened only from a **fully green** state: clean debug + release build, **0 test failures**, **0 lint errors, 0 lint warnings, 0 compiler warnings, 0 Markdown/spelling/inspection findings**. A known failing test in the branch is a release blocker, full stop. -- **The pre-PR sweep is the gate, and it is mechanical.** `.\scripts\pre-pr-sweep.ps1` runs every check below and writes `build/sweep-receipt.json` only when all of them are green. A Claude Code `PreToolUse` hook (`scripts/hooks/require-sweep.mjs`, wired in `.claude/settings.json`) refuses `gh pr create` and the GitHub `create_pull_request` tool unless that receipt exists **for the current `HEAD` on a clean tree** — so the sweep is, by construction, the last thing that runs after the final commit. Humans run the same script; there is no other route to a PR. +- **The pre-PR sweep is the gate, and it is mechanical.** `.\scripts\pre-pr-sweep.ps1` runs every check below and writes `build/sweep-receipt.json` only when all of them are green. The receipt records whether `-Clean` ran and the duration of every gate. A Claude Code `PreToolUse` hook (`scripts/hooks/require-sweep.mjs`, wired in `.claude/settings.json`) refuses `gh pr create` and the GitHub `create_pull_request` tool unless that receipt exists **for the current `HEAD` on a clean tree** — so the sweep is, by construction, the last thing that runs after the final commit. Humans run the same script; there is no other route to a PR. - If you discover the breakage was already on `main`, that makes it **more** urgent, not less — a broken gate on `main` means the safety net is down for every future change. Repair it (or escalate) immediately; never build on top of it. - Capture the green proof (build verdict + exit 0 + test counts, per the gate below) in the PR. @@ -158,13 +158,15 @@ changing the script. > > ```powershell > .\scripts\pre-pr-sweep.ps1 # full sweep — emulator/device attached, Inspect Code export present +> .\scripts\pre-pr-sweep.ps1 -Clean # cold build after build-tool/dependency changes or suspected stale outputs > .\scripts\pre-pr-sweep.ps1 -SkipConnected -SkipInspectCode # what an agent without Studio/emulator can run; the PR must say so > ``` > > It reports every gate (it never stops at the first red), logs to `build/sweep.log`, and writes -> `build/sweep-receipt.json` on green. Gate **5b** (the onboarding loop) starts in the background -> after a green debug APK so it overlaps lint, JVM tests, and the text gates. The steps below are -> what it runs, kept here so a human can reproduce any one of them by hand. +> `build/sweep-receipt.json` on green. Fast text gates run first, build + Lint + JVM tests share one +> Gradle invocation, then gate **5b** (the onboarding loop) runs before instrumented tests so the two +> never contend for one emulator. The steps below are what it runs, kept here so a human can reproduce +> any one of them by hand. ### 0. Baseline — before you change anything @@ -282,7 +284,7 @@ A command finishing is **not** a passed build. Confirm all three: - [ ] M3 — instruction changes went into the shared `docs/OPERATING_INSTRUCTIONS.md` / `docs/OPENLOOP_INSTRUCTIONS.md`; root `CLAUDE.md` / `AGENTS.md` are still content-free pointers, still byte-identical - [ ] M4 — anything moved/renamed/deleted was `git grep`-ed repo-wide under BOTH names; broken anchors, false statements (allowlists, folder maps, counts, "this file") and wrong pointers fixed — link-check alone is not this check - [ ] Baseline green before changes (clean assembleDebug) -- [ ] clean assembleDebug + assembleRelease: BUILD SUCCESSFUL, exit 0, zero e: +- [ ] assembleDebug + assembleRelease: BUILD SUCCESSFUL, exit 0, zero e:; `-Clean` used after build-tool/dependency changes or suspected stale outputs - [ ] Requirement checks pass (e.g. zipalign -c -P 16 shows real (OK)) - [ ] Tracked-file hygiene + Gitleaks pass: no gitignored/generated files or secrets (API keys, tokens, passwords, signing material, or other credentials) are committed - [ ] Release bump only: Play technical quality check done (vitals Memory rows under threshold, bundle App optimization High) — numbers pasted here diff --git a/docs/STATIC_ANALYSIS.md b/docs/STATIC_ANALYSIS.md index e8a3300..9cec7c4 100644 --- a/docs/STATIC_ANALYSIS.md +++ b/docs/STATIC_ANALYSIS.md @@ -190,7 +190,7 @@ equivalent of Grazie grammar — but for the classes it covers it is the same ba no baseline.** (It used to be advisory and scoped to changed files while the docs carried ~600 legacy hits; those were cleared on 2026-08-25 and the gate went hard.) -### The tools (all run via `npx` / `python`, no committed `node_modules`) +### The tools (npm CLIs are exactly pinned; `node_modules` stays uncommitted) | Tool | Config (committed) | Approximates (Engine 2 finding) | | ---------------------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | @@ -218,10 +218,11 @@ Grazie (Tier 2) finding, and the prose is American. or by hand, whole repo: ```bash -npx --yes markdownlint-cli2 $(git ls-files '*.md') +npm ci --ignore-scripts +./node_modules/.bin/markdownlint-cli2 $(git ls-files '*.md') python scripts/md-table-align.py # add --fix to rewrite -for f in $(git ls-files '*.md'); do npx --yes markdown-link-check --config .markdown-link-check.json -q "$f"; done -git ls-files '*.md' '*.kt' '*.kts' '*.xml' '*.yml' '*.ps1' '*.py' '*.mjs' '*.json' '*.html' | npx --yes cspell --no-progress --file-list stdin +for f in $(git ls-files '*.md'); do ./node_modules/.bin/markdown-link-check --config .markdown-link-check.json -q "$f"; done +git ls-files '*.md' '*.kt' '*.kts' '*.xml' '*.yml' '*.ps1' '*.py' '*.mjs' '*.json' '*.html' | ./node_modules/.bin/cspell --no-progress --file-list stdin python scripts/sync-ide-dictionary.py --check ``` diff --git a/docs/TEST_COVERAGE.md b/docs/TEST_COVERAGE.md index 5b7d065..7cf8322 100644 --- a/docs/TEST_COVERAGE.md +++ b/docs/TEST_COVERAGE.md @@ -88,14 +88,15 @@ LG hardware codec). Stock emulators cannot spoof Samsung/LG identity or vendor c | Lane | What | Where | | -------------------------- | ----------------------------------------------------------------------------- | ---------------------------- | -| API 34 FGS | `Pixel_8_API34` AVD + save smoke; Robolectric `ForegroundInfo` tests | Emulator + `test/` | +| API 34 FGS | Robolectric every sweep; `Pixel_8_API34` save smoke for FGS changes/releases | Emulator + `test/` | | Samsung app logic | `DeviceMediaHintsOemRobolectricTest` (ShadowBuild) | `test/` | | Samsung vendor codecs | `samsung-rtl-sweep.ps1` on Samsung Remote Test Lab | Real Galaxy | | LG `start failed` recovery | `VideoReverserTest#reverse_recoversFromCodecStartFailure_viaSoftwareFallback` | `androidTest/` on any device | -The **4-emulator pixel sweep** (`Pixel_6` → `Pixel_8` → `Pixel_10_Pro_Fold` → `Pixel_8_API34`) -is documented in `.claude/skills/run-e2e-pixel-sweep/SKILL.md`. Run the full OEM matrix before -media-pipeline or FGS changes. +The default pixel sweep runs the full scripted flow and output-quality gate on `Pixel_8`. +Add `Pixel_10_Pro_Fold` for posture/preview changes and `Pixel_8_API34` for FGS/WorkManager changes +and each release. `Pixel_6` duplicated the default lane; the risk-based matrix is documented in +`.claude/skills/run-e2e-pixel-sweep/SKILL.md`. --- diff --git a/docs/guides/oem-regression-testing.md b/docs/guides/oem-regression-testing.md index 8ebb367..0f41d4f 100644 --- a/docs/guides/oem-regression-testing.md +++ b/docs/guides/oem-regression-testing.md @@ -15,7 +15,7 @@ LG phone when it isn't. | [`docs/lessons_learned/024-fgs-type-constant-api-gating.md`](../lessons_learned/024-fgs-type-constant-api-gating.md) | FGS type must gate on the API that *added* the constant | **Agent skills** (same content, runnable commands): `.claude/skills/run-e2e-pixel-sweep/SKILL.md` -(OEM lanes + 4-emulator sweep) and `.claude/skills/run-e2e/SKILL.md` (manual E2E + quick table). +(default Pixel 8 flow + risk-triggered lanes) and `.claude/skills/run-e2e/SKILL.md` (manual E2E + quick table). --- @@ -57,9 +57,11 @@ emulator -list-avds # should include Pixel_8_API34 ### How to run -**Option A — part of the 4-device pixel sweep** (import path, scripted): +**Option A — conditional pixel-sweep lane** (import path, scripted): -Order: `Pixel_6` → `Pixel_8` → `Pixel_10_Pro_Fold` → **`Pixel_8_API34`** (last = mandatory FGS gate). +Run `Pixel_8_API34` for FGS, WorkManager, notification, or manifest service changes and once per +release. The default `Pixel_8` lane covers the same end-to-end flow; the API-34 lane adds real +platform validation that the foreground service starts and saves. See `.claude/skills/run-e2e-pixel-sweep/SKILL.md` for the full sweep. @@ -213,13 +215,13 @@ Pass: `tests=1 failures=0 errors=0`. ## Quick reference — which command when? -| You're changing… | Run at minimum | -| ------------------------------------------ | ----------------------------------------------------------------------------- | -| FGS / WorkManager | API 34 unit + Robolectric FGS tests; API 34 AVD save smoke | -| `DeviceMediaHints` / Samsung encoder order | `DeviceMediaHintsOemRobolectricTest` + `SamsungReversePreviewRegressionTest` | -| `VideoReverser` / reverse pipeline | 4-emulator pixel sweep + Samsung RTL if Samsung-specific | -| Anything touching save/render | Pixel sweep includes API 34; grep logcat for FGS CRASH row | -| LG codec fallback logic | `VideoReverserTest#reverse_recoversFromCodecStartFailure_viaSoftwareFallback` | +| You're changing… | Run at minimum | +| ------------------------------------------ | ----------------------------------------------------------------------------------- | +| FGS / WorkManager | API 34 unit + Robolectric FGS tests; API 34 AVD save smoke | +| `DeviceMediaHints` / Samsung encoder order | `DeviceMediaHintsOemRobolectricTest` + `SamsungReversePreviewRegressionTest` | +| `VideoReverser` / reverse pipeline | Pixel 8 sweep + Fold when preview/posture changes + Samsung RTL if Samsung-specific | +| Anything touching save/render | Pixel 8 sweep; add API 34 for FGS/WorkManager/service-manifest changes | +| LG codec fallback logic | `VideoReverserTest#reverse_recoversFromCodecStartFailure_viaSoftwareFallback` | --- diff --git a/gradle.properties b/gradle.properties index b5ce67a..eeb1e9e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,6 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 android.useAndroidX=true android.nonTransitiveRClass=true kotlin.code.style=official -org.gradle.configuration-cache=false +org.gradle.configuration-cache=true +org.gradle.caching=true +org.gradle.parallel=true diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a5d5a92 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3400 @@ +{ + "name": "openloop-tooling", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "openloop-tooling", + "devDependencies": { + "cspell": "10.1.1", + "markdown-link-check": "3.15.0", + "markdownlint-cli2": "0.23.2" + } + }, + "node_modules/@cspell/cspell-bundled-dicts": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-10.1.1.tgz", + "integrity": "sha512-EvPFPWwEPbPn2pIAD4D6PRRFbuM5OCiYfY0GhmpQyWWteCwR4gRmRs06UOWqfSRKHYBL/rUqcr3OAfiF5ctAjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.1.1", + "@cspell/dict-al": "^1.1.1", + "@cspell/dict-aws": "^4.0.17", + "@cspell/dict-bash": "^4.2.3", + "@cspell/dict-companies": "^3.2.12", + "@cspell/dict-cpp": "^7.1.0", + "@cspell/dict-cryptocurrencies": "^5.0.5", + "@cspell/dict-csharp": "^4.0.8", + "@cspell/dict-css": "^4.1.2", + "@cspell/dict-dart": "^2.3.2", + "@cspell/dict-data-science": "^2.0.16", + "@cspell/dict-django": "^4.1.6", + "@cspell/dict-docker": "^1.1.17", + "@cspell/dict-dotnet": "^5.0.13", + "@cspell/dict-elixir": "^4.0.8", + "@cspell/dict-en_us": "^4.4.36", + "@cspell/dict-en-common-misspellings": "^2.2.0", + "@cspell/dict-en-gb-mit": "^3.1.25", + "@cspell/dict-filetypes": "^3.0.18", + "@cspell/dict-flutter": "^1.1.1", + "@cspell/dict-fonts": "^4.0.6", + "@cspell/dict-fsharp": "^1.1.1", + "@cspell/dict-fullstack": "^3.2.9", + "@cspell/dict-gaming-terms": "^1.1.2", + "@cspell/dict-git": "^3.1.0", + "@cspell/dict-golang": "^6.0.27", + "@cspell/dict-google": "^1.0.9", + "@cspell/dict-haskell": "^4.0.6", + "@cspell/dict-html": "^4.0.16", + "@cspell/dict-html-symbol-entities": "^4.0.5", + "@cspell/dict-java": "^5.0.12", + "@cspell/dict-julia": "^1.1.1", + "@cspell/dict-k8s": "^1.0.13", + "@cspell/dict-kotlin": "^1.1.1", + "@cspell/dict-latex": "^5.1.0", + "@cspell/dict-lorem-ipsum": "^4.0.5", + "@cspell/dict-lua": "^4.0.8", + "@cspell/dict-makefile": "^1.0.5", + "@cspell/dict-markdown": "^2.0.18", + "@cspell/dict-monkeyc": "^1.1.0", + "@cspell/dict-node": "^5.0.9", + "@cspell/dict-npm": "^5.2.47", + "@cspell/dict-php": "^4.1.1", + "@cspell/dict-powershell": "^5.0.15", + "@cspell/dict-public-licenses": "^2.0.16", + "@cspell/dict-python": "^4.4.0", + "@cspell/dict-r": "^2.1.1", + "@cspell/dict-ruby": "^5.1.2", + "@cspell/dict-rust": "^4.1.2", + "@cspell/dict-scala": "^5.0.9", + "@cspell/dict-shell": "^1.2.0", + "@cspell/dict-software-terms": "^5.4.1", + "@cspell/dict-sql": "^2.2.1", + "@cspell/dict-svelte": "^1.0.7", + "@cspell/dict-swift": "^2.0.6", + "@cspell/dict-terraform": "^1.1.4", + "@cspell/dict-typescript": "^3.2.3", + "@cspell/dict-vue": "^3.0.5", + "@cspell/dict-zig": "^1.0.0" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-json-reporter": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-10.1.1.tgz", + "integrity": "sha512-6makYERzgDCBGeOG7jSgZBOWxJKxBV6k0UQ60xDBZNrccACP45q8zO9YIXdHAYLmHB52l3Iz2vifeG7zhue7jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "10.1.1" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-performance-monitor": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-10.1.1.tgz", + "integrity": "sha512-M3Bq+K0jmbnAE2dWB8vG/TljagcKWuILTpcf6sIMB/jTaT7QH9FyzVp0Q6srlN3GEdSBwFBqrfWCorkjRUd0cQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-pipe": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-10.1.1.tgz", + "integrity": "sha512-WOuL9zdcl38b9P5Kpco3c1vg5v82bSWZ7LVeARbyrOmW60HxS8uP4nkbCGeU6pINvJCs0JUQxEZCRMHuEF0dfQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-resolver": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-10.1.1.tgz", + "integrity": "sha512-bbsykc5c7dDdPTDFdsY0GKwXlflDDaTUycAegziFLCcp8b/q1txQmqBxx95ok1pjpU10sWxiJztZZRayFcM5sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-directory": "^5.0.0" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-service-bus": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-10.1.1.tgz", + "integrity": "sha512-Z3BUsVllqyAoJSGXcyFp0hXtBVKEfrxVcSy3UPoSoLW9gZZjXmFwOorhga3+fMseC9VRK3L6mKSccn9YGAjsnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-types": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-10.1.1.tgz", + "integrity": "sha512-lsc+/pazJQ47Zy7qyuFiQRZzco+kBSUmAtCzbmT96pFpAVxR+b4A8qRBoTdiq4OXBRXRT+CqWMNynSiwQJWM6g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/cspell-worker": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-10.1.1.tgz", + "integrity": "sha512-X9Ehif6c/9BRIODBjWMr0paHQrY3Jw7q0FWeSdxPZrnKhgJ+cX4vtvqlSD1dGXMV2/fGh10p1HznuDhNlQ4tjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cspell-lib": "10.1.1" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/dict-ada": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.1.tgz", + "integrity": "sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-al": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.1.1.tgz", + "integrity": "sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-aws": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.17.tgz", + "integrity": "sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-bash": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.3.tgz", + "integrity": "sha512-ljUZoKHbDqw5Sx0qpL2qTUlmkmr+vhZH/sCNrNaBZKTbdgiswErSnIF1jRbGmEitJNxHRHWsuZyVgnTGfVO1Yw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-shell": "1.2.0" + } + }, + "node_modules/@cspell/dict-companies": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.2.12.tgz", + "integrity": "sha512-mjiz/N3zWOCsz5VfwMUydSl7uW0OU9H2PnbCNc3RV44Vj6Q59CSp6EYGSGZQxrXU1gpsuZUrwr6QCjNjFOOg5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-cpp": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-7.1.0.tgz", + "integrity": "sha512-rcjycobioQUd9Jm/Y1n8U+sq6ytpZ0iV8AYIo+vyEFfutC5x7g6hL6Fh3bCdh6IporGHRqfEutGK/4sfopD2ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-cryptocurrencies": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.5.tgz", + "integrity": "sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-csharp": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.8.tgz", + "integrity": "sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-css": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.2.tgz", + "integrity": "sha512-+ylGoKdwZ2sVOCOnU2Eq5wDZx+RaVX3HoKyNHGGsFvhSw6IidQ6tH/mAPKBDofViHJoWCPNlklE0lTr6MDG3QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-dart": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.3.2.tgz", + "integrity": "sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-data-science": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.16.tgz", + "integrity": "sha512-M72mxv5asuAnORurz4iXRJ+Tw9XBq6eu7D2Ne7biP0Z1RciKGNxXWu9JycA/KlVvK1hAlKj/fANlXhuEWpXKFg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-django": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.6.tgz", + "integrity": "sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-docker": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.17.tgz", + "integrity": "sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-dotnet": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.13.tgz", + "integrity": "sha512-xPp7jMnFpOri7tzmqmm/dXMolXz1t2bhNqxYkOyMqXhvs08oc7BFs+EsbDY0X7hqiISgeFZGNqn0dOCr+ncPYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-elixir": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.8.tgz", + "integrity": "sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-en_us": { + "version": "4.4.37", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.37.tgz", + "integrity": "sha512-rMKyPrk2SKmDU+Bj0U0ixsv4Du93oijwovc8XlUin0zwKOJZb0/PFG5Df4P8CrM2CrLeovpaFvhoI98DigxBLw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-en-common-misspellings": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.2.0.tgz", + "integrity": "sha512-5PmCHv+AhY0LVNo3bE1FdRKMmw1esKj83GPwLymnVPYNtlI2Jf6y27EjC0azg4zny5keWmku0GQiMf55Fi+qeA==", + "dev": true, + "license": "CC BY-SA 4.0" + }, + "node_modules/@cspell/dict-en-gb-mit": { + "version": "3.1.26", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.26.tgz", + "integrity": "sha512-F9Y/45+1oIPzfL/pyWLp4kzX+vddHPAYpIpIF+45bdc65AebeEiQHKzSmKgGGTd3qbQc3fATw2kAFdLryiQpjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-filetypes": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.18.tgz", + "integrity": "sha512-yU7RKD/x1IWmDLzWeiItMwgV+6bUcU/af23uS0+uGiFUbsY1qWV/D4rxlAAO6Z7no3J2z8aZOkYIOvUrJq0Rcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-flutter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.1.1.tgz", + "integrity": "sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fonts": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.6.tgz", + "integrity": "sha512-aR/0csY01dNb0A1tw/UmN9rKgHruUxsYsvXu6YlSBJFu60s26SKr/k1o4LavpHTQ+lznlYMqAvuxGkE4Flliqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fsharp": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.1.1.tgz", + "integrity": "sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fullstack": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.9.tgz", + "integrity": "sha512-diZX+usW5aZ4/b2T0QM/H/Wl9aNMbdODa1Jq0ReBr/jazmNeWjd+PyqeVgzd1joEaHY+SAnjrf/i9CwKd2ZtWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-gaming-terms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.2.tgz", + "integrity": "sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-git": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.1.0.tgz", + "integrity": "sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-golang": { + "version": "6.0.27", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.27.tgz", + "integrity": "sha512-rRDb2JL8EefaezHGTEclKXCs4eMOS0q/datk94Lm7KQOhlGlzS9FDVZiR1/guh0o+iJCmejQuf5NR2FQeQSWsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-google": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.9.tgz", + "integrity": "sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-haskell": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.6.tgz", + "integrity": "sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-html": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.16.tgz", + "integrity": "sha512-9B6/Cpb5YVcYgsEAlKudun1yd4ONllYS/ZibKLYea2apPR+l2vQdARnPrP9kTqa7NUNfRKl7m9Fb6k9rjimnow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-html-symbol-entities": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.5.tgz", + "integrity": "sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-java": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.12.tgz", + "integrity": "sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-julia": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.1.1.tgz", + "integrity": "sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-k8s": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.13.tgz", + "integrity": "sha512-ELGkS13k7K/NEfVimBSrxVTfqXvOF/Kvxj4I62YxRm8bvHbfoXgrGaOx28lPiNRz+dmu+yYtvuXbnURKtYbC6g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-kotlin": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-kotlin/-/dict-kotlin-1.1.1.tgz", + "integrity": "sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-latex": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-5.1.0.tgz", + "integrity": "sha512-qxT4guhysyBt0gzoliXYEBYinkAdEtR2M7goRaUH0a7ltCsoqqAeEV8aXYRIdZGcV77gYSobvu3jJL038tlPAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-lorem-ipsum": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.5.tgz", + "integrity": "sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-lua": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.8.tgz", + "integrity": "sha512-N4PkgNDMu9JVsRu7JBS/3E/dvfItRgk9w5ga2dKq+JupP2Y3lojNaAVFhXISh4Y0a6qXDn2clA6nvnavQ/jjLA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-makefile": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.5.tgz", + "integrity": "sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-markdown": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.18.tgz", + "integrity": "sha512-KLRSwVrwKDz4n7bl2XQjzvaBZbGgx5QKkP5Ok1b24xaO3TpXsLhAbAn1mItvFlI2tF6Rkt83iYjQcYppywuf5Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@cspell/dict-css": "^4.1.2", + "@cspell/dict-html": "^4.0.16", + "@cspell/dict-html-symbol-entities": "^4.0.5", + "@cspell/dict-typescript": "^3.2.3" + } + }, + "node_modules/@cspell/dict-monkeyc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.1.0.tgz", + "integrity": "sha512-mc/hgvSy/emOIYtc8kuVEaLUlnaERunfAubfJ5plUXq6s0A69bcukJzUzSt9C0UTCwS28641ILRPv80m3L9QbA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-node": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.9.tgz", + "integrity": "sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-npm": { + "version": "5.2.47", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.47.tgz", + "integrity": "sha512-r5ePbkmRtpMwiv+MHd6be1xIRLuXoEwaSLIZLu3mY+qtPVo0LUj/kVl4YeIxHONiwyef75zqS3gnT+s5UF7diQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-php": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.1.1.tgz", + "integrity": "sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-powershell": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.15.tgz", + "integrity": "sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-public-licenses": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.16.tgz", + "integrity": "sha512-EQRrPvEOmwhwWezV+W7LjXbIBjiy6y/shrET6Qcpnk3XANTzfvWflf9PnJ5kId/oKWvihFy0za0AV1JHd03pSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-python": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.5.0.tgz", + "integrity": "sha512-O1lSuFXoX8p+4hvJMbqvg3blbn0Zx8LHqdPQSNaOxFZGf7hmq6pc8sfta+98E7Q/WtDooAnU3XpBxBXcn0r94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-data-science": "^2.0.16" + } + }, + "node_modules/@cspell/dict-r": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.1.1.tgz", + "integrity": "sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-ruby": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.1.2.tgz", + "integrity": "sha512-f6Slf11N91ittf71AWlfVVG9GZPezVRBfcMPCTNTWhUsY/VEspkBRZYDhPXjV4df3jqHy5YJs8nlsFcFVF/bMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-rust": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.1.2.tgz", + "integrity": "sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-scala": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.9.tgz", + "integrity": "sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-shell": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.2.0.tgz", + "integrity": "sha512-PVctvT22lJ49niMiakO8xieY7ELCAzjSqhejWR7bAMb5AZ9F4WDEs+XdGMnoVHWeXq7K5rcepLPmEJb+37zzIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-software-terms": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.4.2.tgz", + "integrity": "sha512-C2tS1JjxqHef9TpPRm08a6n+PJCrKrD6FsmPEyXb2J6TFef4FFnKRcGOf3pFnd+a6/oyQgXZWeKiECH6lBFjQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-sql": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.2.1.tgz", + "integrity": "sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-svelte": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.7.tgz", + "integrity": "sha512-hGZsGqP0WdzKkdpeVLBivRuSNzOTvN036EBmpOwxH+FTY2DuUH7ecW+cSaMwOgmq5JFSdTcbTNFlNC8HN8lhaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-swift": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.6.tgz", + "integrity": "sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-terraform": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.4.tgz", + "integrity": "sha512-Ere42ilvMFvQA4GlcN0OKlruMPR6EsvaB+iTHzj2xc+NJGRK64V7yApUcWrOrSgTiM/vhWXPIsK3OMfiAiNdmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-typescript": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.3.tgz", + "integrity": "sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-vue": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.5.tgz", + "integrity": "sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-zig": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-zig/-/dict-zig-1.0.0.tgz", + "integrity": "sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dynamic-import": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-10.1.1.tgz", + "integrity": "sha512-bNI+Gp0Rnx/WyOvni4TksvNWeQvCfyQAhZRIGMt+9bbLyniVagnftnoahV/yoF9h3WWxU3tL2eaVZx9B5dijuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "10.1.1", + "import-meta-resolve": "^4.2.0" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/filetypes": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-10.1.1.tgz", + "integrity": "sha512-sSREdKF4roC4QM2n0qUgv10W74nUO7CUhDTCz3Sd3mHlUM46WI8QqbAIZFNTm5U4SuVaVAmXzsZvM69O/rOjvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/rpc": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/rpc/-/rpc-10.1.1.tgz", + "integrity": "sha512-sWQ++D8++6pAv8FSCfJOpc/t/yoK1r0xwcBb23SenOA9nvcmI7CwAp2FK2oByLnDTe+Bh6mQWtRRZSr3gfoGhQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/strong-weak-map": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-10.1.1.tgz", + "integrity": "sha512-s7PsRDfZO5J1dB0gtlaeNxwaibDUCYIFlbdzMawlUejR/UNrhDgDIr48OScoOt5SaUHijEVpFDkrWVyCs5R7oQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@cspell/url": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-10.1.1.tgz", + "integrity": "sha512-5O2bZ5H/zPomc4qshTpfCbIltallsdQNwlw6j/Gl+eVElrlFsgc0kzuYJdk1BMnpA0ZXPXYH7XVKCGIKzLcr2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@oozcitak/dom": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-2.0.2.tgz", + "integrity": "sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "^2.0.2", + "@oozcitak/url": "^3.0.0", + "@oozcitak/util": "^10.0.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/infra": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-2.0.2.tgz", + "integrity": "sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/util": "^10.0.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-3.0.0.tgz", + "integrity": "sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "^2.0.2", + "@oozcitak/util": "^10.0.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/util": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-10.0.0.tgz", + "integrity": "sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/katex": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", + "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", + "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-6.0.0.tgz", + "integrity": "sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.2.tgz", + "integrity": "sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/comment-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-5.0.0.tgz", + "integrity": "sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cspell": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-10.1.1.tgz", + "integrity": "sha512-imoZaB1+9gHMyFFMDBY7VbtIdDwkRJXQjs3bIfo1H+AUJnw/vMxLwXk8mnPmH7ziw2m2kyGF+rPAVUE93VEAAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-json-reporter": "10.1.1", + "@cspell/cspell-performance-monitor": "10.1.1", + "@cspell/cspell-pipe": "10.1.1", + "@cspell/cspell-types": "10.1.1", + "@cspell/cspell-worker": "10.1.1", + "@cspell/dynamic-import": "10.1.1", + "@cspell/url": "10.1.1", + "ansi-regex": "^6.3.0", + "chalk": "^6.0.0", + "chalk-template": "^1.1.2", + "commander": "^15.0.0", + "cspell-config-lib": "10.1.1", + "cspell-dictionary": "10.1.1", + "cspell-gitignore": "10.1.1", + "cspell-glob": "10.1.1", + "cspell-io": "10.1.1", + "cspell-lib": "10.1.1", + "fast-json-stable-stringify": "^2.1.0", + "flatted": "^3.4.4", + "semver": "^7.8.5", + "tinyglobby": "^0.2.17" + }, + "bin": { + "cspell": "bin.mjs", + "cspell-esm": "bin.mjs" + }, + "engines": { + "node": ">=22.18.0" + }, + "funding": { + "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" + } + }, + "node_modules/cspell-config-lib": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-10.1.1.tgz", + "integrity": "sha512-/AgOcOxO0jmAJCkShhaPQqSNrx+QUkEOncTf2uFnIx4/gRxFwiRZ0Zrv6PyHNBTC5vY82+qB6scT5Pj30n174A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "10.1.1", + "comment-json": "^5.0.0", + "smol-toml": "^1.8.0", + "yaml": "^2.9.0" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-dictionary": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-10.1.1.tgz", + "integrity": "sha512-94eW96hjAa3ASAjtmWkC1h1S7GLNHEoDftViilZ/nQzHxeYHp8kU73/0Jqjawr3tzfNvdKV0Bq/8zgeEp1LNrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-performance-monitor": "10.1.1", + "@cspell/cspell-pipe": "10.1.1", + "@cspell/cspell-types": "10.1.1", + "cspell-trie-lib": "10.1.1", + "fast-equals": "^6.0.2" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-gitignore": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-10.1.1.tgz", + "integrity": "sha512-vYQjziKDH8qQzj/gHHJPKwmAqwfQIHBvyqukR0Uf1WzY1X08Ns9jMl5JDRUL7ffcosDYsReIhLxy2KJrxRkrng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "10.1.1", + "cspell-glob": "10.1.1", + "cspell-io": "10.1.1" + }, + "bin": { + "cspell-gitignore": "bin.mjs" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-glob": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-10.1.1.tgz", + "integrity": "sha512-+xRfPD/KHU3JCMPK3Blt3AchW6KAzsyrNUdNns9mmkDRiej5Vl19kdN3eKh7B/0XoAKnX/v67tucCu/jr8MTug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "10.1.1", + "picomatch": "^4.0.5" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-grammar": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-10.1.1.tgz", + "integrity": "sha512-mOHufusJEld/q8ZfC+AhequR515QIOHC0LdD1z6PU+Mpn3GRBGJBWK56iUwHH4XX935GsUMJFIQuOoMXXcbAsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-pipe": "10.1.1", + "@cspell/cspell-types": "10.1.1" + }, + "bin": { + "cspell-grammar": "bin.mjs" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-io": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-10.1.1.tgz", + "integrity": "sha512-Gcl2B2hKOJBqi+nf1ZnZ2XZj+VWN+AZLfQZR5dxxny3Ggy51vW8AfJX8lF8Ev/c559AkC5G7KkO2jkVuZ4SVsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-service-bus": "10.1.1", + "@cspell/url": "10.1.1" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-lib": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-10.1.1.tgz", + "integrity": "sha512-jckdiCU/3pkvJ21G77R2fl93R6JjpYwP+wj8qQNUewYlTl9bdhMJi8xgLb4os7CJnHD5kA59ow8tNvh45d3zDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-bundled-dicts": "10.1.1", + "@cspell/cspell-performance-monitor": "10.1.1", + "@cspell/cspell-pipe": "10.1.1", + "@cspell/cspell-resolver": "10.1.1", + "@cspell/cspell-types": "10.1.1", + "@cspell/dynamic-import": "10.1.1", + "@cspell/filetypes": "10.1.1", + "@cspell/rpc": "10.1.1", + "@cspell/strong-weak-map": "10.1.1", + "@cspell/url": "10.1.1", + "cspell-config-lib": "10.1.1", + "cspell-dictionary": "10.1.1", + "cspell-glob": "10.1.1", + "cspell-grammar": "10.1.1", + "cspell-io": "10.1.1", + "cspell-trie-lib": "10.1.1", + "env-paths": "^4.0.0", + "gensequence": "^8.0.8", + "import-fresh": "^4.0.0", + "resolve-from": "^5.0.0", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-uri": "^3.1.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=22.18.0" + } + }, + "node_modules/cspell-trie-lib": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-10.1.1.tgz", + "integrity": "sha512-4ico1ebFl9lvP1Yr4pD+FxOYRS7Ct+ImV8v0KcEclxMixqNku4NoVP/CvmE1AyyVB3FN16fITN0vo3ZAR79PFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" + }, + "peerDependencies": { + "@cspell/cspell-types": "10.1.1" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-8.0.0.tgz", + "integrity": "sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/degenerator": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-7.0.1.tgz", + "integrity": "sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "quickjs-wasi": "^2.2.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-4.0.0.tgz", + "integrity": "sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-safe-filename": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-equals": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-6.0.2.tgz", + "integrity": "sha512-sAjhj9ZhOxYCGiNMnZLaucOqf5ZeFnHNoKoAZiD9thhJ0N8RP85qJK759/97C/3L7NzzmGVB5uiX9AUpySZmUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.2.tgz", + "integrity": "sha512-UpGiiODyCGprM8EPP6JodP6jC9Rws6TCuiDOD+nn0CJhR8guI3g/ozo4ugL0vJ+Yz1UtJuuRPqvQuybVOF1VQA==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/gensequence": { + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-8.0.8.tgz", + "integrity": "sha512-omMVniXEXpdx/vKxGnPRoO2394Otlze28TyxECbFVyoSpZ9H3EO7lemjcB12OpQJzRW4e5tt/dL1rOxry6aMHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-8.0.1.tgz", + "integrity": "sha512-/5N/P4Lrh0p/mDwlDRi7Y1+P2o/OyzZI3l6Iz1Ov6XXwwm1y3RlZLuo3gVgML99djrEDtV980bBxSuOeHLk8ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.3.1", + "data-uri-to-buffer": "8.0.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-directory": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz", + "integrity": "sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "6.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.2.tgz", + "integrity": "sha512-NLvV9ubZ6NDsJaOpKPy3cQeJpKi9DcWiyCiFUpJPA0YihRqiE6RWaLUmgNNPr8MgPpLZjnBjSmou7uZBRJv9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "is-path-inside": "^4.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-link-extractor": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-link-extractor/-/html-link-extractor-1.0.5.tgz", + "integrity": "sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio": "^1.0.0-rc.10" + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-9.1.0.tgz", + "integrity": "sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "proxy-agent-negotiate": "1.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/https-proxy-agent": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz", + "integrity": "sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "proxy-agent-negotiate": "1.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-4.0.0.tgz", + "integrity": "sha512-Fpi660c7VPDM3fPKYovStd9IP1CPOikf6v/dGxJJMmHPcwYQIMJ4W7kO1avBYEpMqkCh+Dx3Ln6H7VYqgztLjw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.15" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/ip-address": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz", + "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-relative-url": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-relative-url/-/is-relative-url-4.1.0.tgz", + "integrity": "sha512-vhIXKasjAuxS7n+sdv7pJQykEAgS+YU8VBQOENXwo/VZpOHDgBBsIbHo7zFKaWBjYWF4qxERdhbPRRtFAeJKfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-absolute-url": "^4.0.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-safe-filename": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-safe-filename/-/is-safe-filename-0.1.1.tgz", + "integrity": "sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-yaml": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.2.tgz", + "integrity": "sha512-dayzUzKkJ1MkuUtZglSebU43utNXH0OWQByK9rKOOuYIO8M5TV1y+n8ALMdG0rdzBnfNkOmZEqrURepb0ejqBw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.mjs" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/link-check": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/link-check/-/link-check-5.6.0.tgz", + "integrity": "sha512-oTHNw9+pgFvXqgTM3vWYOMkf4Pv5mywUr2L6EYkiRiVtpGrDXs8wV+kGP3bxBRwnC7gD3b9IRBu1dx/Tm1MFDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-relative-url": "^4.1.0", + "ms": "^2.1.3", + "needle": "^3.5.0", + "node-email-verifier": "^4.0.0", + "proxy-agent": "^8.0.2" + } + }, + "node_modules/linkify-it": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/markdown-it": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", + "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-link-check": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/markdown-link-check/-/markdown-link-check-3.15.0.tgz", + "integrity": "sha512-EorpVYNu1Jpldk3OLrRrH7Hx/ofp1dCSAJeYuvb8MhKR/rIt6S0tgwbQYw66EZgRPu9lPvORfT6SkIe0dwn2Ow==", + "dev": true, + "license": "ISC", + "dependencies": { + "async": "^3.2.6", + "chalk": "^6.0.0", + "commander": "^15.0.0", + "link-check": "^5.6.0", + "markdown-link-extractor": "^4.0.4", + "needle": "^3.5.0", + "progress": "^2.0.3", + "proxy-agent": "^8.0.2", + "xmlbuilder2": "^4.0.3" + }, + "bin": { + "markdown-link-check": "markdown-link-check" + } + }, + "node_modules/markdown-link-extractor": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/markdown-link-extractor/-/markdown-link-extractor-4.0.4.tgz", + "integrity": "sha512-Dw9saacqF4u1EjUm3O+f0ZTBM/o7l1IrdHS8z1KSFX2coECIcJTZbltICMKx6QwHBKlzMQXgtWYnIHX71WHZMw==", + "dev": true, + "license": "ISC", + "dependencies": { + "html-link-extractor": "^1.0.5", + "marked": "^18.0.7" + } + }, + "node_modules/markdownlint": { + "version": "0.41.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.41.1.tgz", + "integrity": "sha512-qHKeU2E1bdyNAT077go2FVTNXvYcktN5IHtF6XyeD1l0PClxzSp2tUApAV14ORI8DGX4H9bNKZEzelZp4qn8IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "4.0.2", + "micromark-core-commonmark": "2.0.3", + "micromark-extension-directive": "4.0.0", + "micromark-extension-gfm-autolink-literal": "2.1.0", + "micromark-extension-gfm-footnote": "2.1.0", + "micromark-extension-gfm-table": "2.1.1", + "micromark-extension-math": "3.1.0", + "micromark-util-types": "2.0.2", + "string-width": "8.2.1" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli2": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.23.2.tgz", + "integrity": "sha512-eUhcnkSpzURo/o4htSqc7LPDszgOOTknhU4eY/sPHvMCLxnTCYscv1gw1/js/idmaZPisv9ECVEIORcllqjTUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "16.2.2", + "js-yaml": "5.2.2", + "jsonc-parser": "3.3.1", + "jsonpointer": "5.0.1", + "markdown-it": "14.3.0", + "markdownlint": "0.41.1", + "markdownlint-cli2-formatter-default": "0.0.6", + "micromatch": "4.0.8", + "smol-toml": "1.7.0" + }, + "bin": { + "markdownlint-cli2": "markdownlint-cli2-bin.mjs" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli2-formatter-default": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.6.tgz", + "integrity": "sha512-VVDGKsq9sgzu378swJ0fcHfSicUnMxnL8gnLm/Q4J/xsNJ4e5bA6lvAz7PCzIl0/No0lHyaWdqVD2jotxOSFMQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + }, + "peerDependencies": { + "markdownlint-cli2": ">=0.0.4" + } + }, + "node_modules/markdownlint-cli2/node_modules/smol-toml": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz", + "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/marked": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.11.tgz", + "integrity": "sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/mdurl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", + "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/needle": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.5.0.tgz", + "integrity": "sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/netmask": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz", + "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-email-verifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/node-email-verifier/-/node-email-verifier-4.0.0.tgz", + "integrity": "sha512-W3ktpVPscUx43WSTm1Vf797cMQMsGwp0JO08ksRaZG8A8wcRUd/XAihL78FwYl2rfABa1m1nIsBtqOMxY9uekA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3", + "validator": "^13.15.20" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/pac-proxy-agent": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-9.1.0.tgz", + "integrity": "sha512-1aU+1mpj3DrQPfo3gh+3Gap3G5x+axnMx1P/y0ZF2ch7kb2meyOCAH8K2k9d27ROsTE7TnAerzxqF9aon2jqnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "get-uri": "8.0.1", + "http-proxy-agent": "9.1.0", + "https-proxy-agent": "9.1.0", + "pac-resolver": "9.0.1", + "quickjs-wasi": "^2.2.0", + "socks-proxy-agent": "10.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/pac-resolver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-9.0.1.tgz", + "integrity": "sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "degenerator": "7.0.1", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "quickjs-wasi": "^2.2.0" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-8.0.2.tgz", + "integrity": "sha512-idLLRewuemWd7GH/BDJzGiB0dWGfT2SQs3jy6NtZtGWU9uPTTSdeC1/cdbqLwgzhfv027daGFuXX426e2Eg20A==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "http-proxy-agent": "9.1.0", + "https-proxy-agent": "9.1.0", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "9.1.0", + "proxy-from-env": "^2.0.0", + "socks-proxy-agent": "10.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/proxy-agent-negotiate": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-agent-negotiate/-/proxy-agent-negotiate-1.1.0.tgz", + "integrity": "sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "kerberos": "^2.0.0" + }, + "peerDependenciesMeta": { + "kerberos": { + "optional": true + } + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quickjs-wasi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz", + "integrity": "sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/smol-toml": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", + "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-10.1.0.tgz", + "integrity": "sha512-WlMj/67cEJ6MDI1OcsnjuYKDNDoyPCCYZ249kuuXPiMDw9F8PXkVaQ7YWu3siTydfQ/4BEZcvGzu+aYvz7dDCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/unicorn-magic": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/validator": { + "version": "13.15.35", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", + "integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.14.tgz", + "integrity": "sha512-EQyqJMi552E4ZTf46izQ4Fj6XquqxCySR3J5ZSD1SisMf6RfpeOWHxGBE8Gr6V0/3GHIGdAzDn8F8+1nTGCnoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.2.0.tgz", + "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xmlbuilder2": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-4.0.3.tgz", + "integrity": "sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/dom": "^2.0.2", + "@oozcitak/infra": "^2.0.2", + "@oozcitak/util": "^10.0.0", + "js-yaml": "^4.1.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/xmlbuilder2/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f4ec0ee --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "openloop-tooling", + "private": true, + "devDependencies": { + "cspell": "10.1.1", + "markdown-link-check": "3.15.0", + "markdownlint-cli2": "0.23.2" + } +} diff --git a/scripts/pre-pr-sweep.ps1 b/scripts/pre-pr-sweep.ps1 index ad0596e..5426ae5 100644 --- a/scripts/pre-pr-sweep.ps1 +++ b/scripts/pre-pr-sweep.ps1 @@ -3,20 +3,24 @@ The pre-PR sweep — every class of error/warning OpenLoop knows how to detect, run to ZERO. .DESCRIPTION - Runs, in order, and reports every gate (it does not stop at the first red): - 1. Gradle: clean assembleDebug + assembleRelease — BUILD SUCCESSFUL, exit 0, zero `e:` AND zero + Runs the fast text gates first, then every build/device gate, and reports every result (it does not + stop at the first red): + 1. Gradle: assembleDebug + assembleRelease + Lint + JVM tests in one invocation — BUILD SUCCESSFUL, + exit 0, zero `e:` AND zero source-attributed `w: file:…` (Kotlin warnings are already fatal via allWarningsAsErrors; build-script deprecations are caught here; KGP's environmental daemon notices are not findings). 2. 16 KB alignment: zipalign -c -P 16 on the release APK — every .so "(OK)", none "(OK - compressed)". - 3. Android Lint (Engine 1): 0 Error/Fatal AND 0 Warning in lint-results-debug.xml. The version-freshness + 3. Android Lint (Engine 1): parse the merged run's report; 0 Error/Fatal AND 0 Warning in + lint-results-debug.xml. The version-freshness checks (GradleDependency, NewerVersionAvailable, AndroidGradlePluginVersion) are reported but never fail the gate — they flip whenever upstream publishes and a gate that goes red on somebody else's schedule is a flaky gate (docs/STATIC_ANALYSIS.md). - 4. JVM unit tests: 0 failures, 0 errors, tests > 0 (counted from the XML, never from BUILD SUCCESSFUL). + 4. JVM unit tests: parse the merged run's report; 0 failures, 0 errors, tests > 0 (counted from the + XML, never from BUILD SUCCESSFUL). 5. Instrumented tests (unless -SkipConnected): same, from the connected XML. 5b. Autonomous onboarding loop via scripts/run-verification-loops.py --changed. - Starts in the background after a green debug APK so it overlaps lint/unit/text gates. - One emulator — does not overlap connectedDebugAndroidTest. Skip with -SkipConnected. + Starts after a green merged Gradle run. One emulator — does not overlap + connectedDebugAndroidTest. Skip with -SkipConnected. 6. Markdown: markdownlint-cli2, table alignment (scripts/md-table-align.py), and relative-link checks on changed Markdown (all Markdown after any delete/rename) — all zero. 7. Spelling: cspell over every tracked text file (Markdown, Kotlin, XML, scripts, configs) — zero unknown words. @@ -27,7 +31,8 @@ to build/inspect-export/. Pass -SkipInspectCode ONLY where Studio is unavailable; the receipt then says so and the PR description must say so too. - On an all-green run it writes build/sweep-receipt.json {sha, treeClean, gates, inspectCode}. The Claude Code + On an all-green run it writes build/sweep-receipt.json {sha, treeClean, cleanBuild, gates, + durationSec, inspectCode}. The Claude Code PreToolUse hook (scripts/hooks/require-sweep.mjs) refuses `gh pr create` / GitHub create_pull_request unless a receipt exists for the CURRENT HEAD on a clean tree — so the sweep is definitionally the last thing that runs after the final commit. Design + rationale: docs/DEFINITION_OF_DONE.md, docs/STATIC_ANALYSIS.md. @@ -37,9 +42,11 @@ .PARAMETER SkipConnected Skip connectedDebugAndroidTest and the onboarding loop (no emulator/device attached). A skip means onboarding is not verified. .PARAMETER DocsOnly Text gates only (6-9). For docs-only branches — the receipt records it. +.PARAMETER Clean Prepend Gradle clean. Use after build-tool/dependency changes or suspected stale outputs. .EXAMPLE .\scripts\pre-pr-sweep.ps1 + .\scripts\pre-pr-sweep.ps1 -Clean # cold build/tooling verification .\scripts\pre-pr-sweep.ps1 -SkipConnected -SkipInspectCode # agent session without Studio or an emulator #> [CmdletBinding()] @@ -47,7 +54,8 @@ param( [string]$InspectExport = "build/inspect-export/index.html", [switch]$SkipInspectCode, [switch]$SkipConnected, - [switch]$DocsOnly + [switch]$DocsOnly, + [switch]$Clean ) $ErrorActionPreference = "Continue" @@ -60,8 +68,12 @@ $log = Join-Path $root "build/sweep.log" if (-not $env:JAVA_HOME) { $env:JAVA_HOME = "C:\Program Files\Android\Android Studio\jbr" } $sdk = if ($env:ANDROID_HOME) { $env:ANDROID_HOME } elseif ($env:ANDROID_SDK_ROOT) { $env:ANDROID_SDK_ROOT } else { "$env:LOCALAPPDATA\Android\Sdk" } +$markdownLint = Join-Path $root "node_modules/markdownlint-cli2/markdownlint-cli2-bin.mjs" +$markdownLinkCheck = Join-Path $root "node_modules/markdown-link-check/markdown-link-check" +$cspell = Join-Path $root "node_modules/cspell/bin.mjs" $results = [ordered]@{} +$timings = [ordered]@{} $loopProc = $null $loopStartError = $null $loopLog = Join-Path $root "build/verification-loops.log" @@ -70,16 +82,20 @@ function Gate([string]$name, [scriptblock]$body) { Write-Host "" Write-Host "== $name" -ForegroundColor Cyan "== $name" | Add-Content $log + $sw = [Diagnostics.Stopwatch]::StartNew() try { $verdict = & $body if ($verdict -isnot [string]) { $verdict = "PASS" } } catch { $verdict = "FAIL: $($_.Exception.Message)" } - $ok = $verdict -like "PASS*" -or $verdict -like "SKIPPED*" + $sw.Stop() $color = if ($verdict -like "PASS*") { "Green" } elseif ($verdict -like "SKIPPED*") { "Yellow" } else { "Red" } Write-Host " -> $verdict" -ForegroundColor $color " -> $verdict" | Add-Content $log + Write-Host (" [{0:N1}s]" -f $sw.Elapsed.TotalSeconds) -ForegroundColor DarkGray + (" [{0:N1}s]" -f $sw.Elapsed.TotalSeconds) | Add-Content $log + $script:timings[$name] = [math]::Round($sw.Elapsed.TotalSeconds, 1) $script:results[$name] = $verdict } @@ -108,23 +124,41 @@ function Sum-JUnit([string]$dir) { return @{ Tests = $t; Failures = $f; Errors = $e } } -# ---------------------------------------------------------------------------- build gates +# ---------------------------------------------------------------------------- build gates (invoked after text gates) +$buildGates = { if (-not $DocsOnly) { - Gate "1. clean assembleDebug assembleRelease (0 e:, 0 w:)" { - $r = Run-Gradle @("clean", "assembleDebug", "assembleRelease") + $buildGateName = "1. assembleDebug assembleRelease + lint + JVM tests (0 e:, 0 w:)" + $unitResultsDir = Join-Path $root "app/build/test-results/testDebugUnitTest" + $lintResults = Join-Path $root "app/build/reports/lint-results-debug.xml" + Gate $buildGateName { + # Dropping `clean` preserves Gradle's cache, but stale reports must never count as this run. + if (Test-Path -LiteralPath $unitResultsDir) { + Remove-Item -LiteralPath $unitResultsDir -Recurse -Force + } + if (Test-Path -LiteralPath $lintResults) { Remove-Item -LiteralPath $lintResults -Force } + $tasks = @( + "assembleDebug", + "assembleRelease", + ":app:lintDebug", + ":app:testDebugUnitTest", + "--parallel", + "--build-cache", + "--continue" + ) + if ($Clean) { $tasks = [string[]]"clean" + $tasks } + $r = Run-Gradle $tasks $errs = @($r.Lines | Where-Object { $_ -match '^e: ' }) # Source-attributed warnings only (`w: file:///…:line:col`): Kotlin compiler + build-script # deprecations. KGP also prints environmental `w:` notices ("Detected multiple Kotlin daemon # sessions") that no code change can clear — those are not findings. $warns = @($r.Lines | Where-Object { $_ -match '^w: file:' }) $ok = ($r.Code -eq 0) -and ($r.Lines -match 'BUILD SUCCESSFUL') -and $errs.Count -eq 0 -and $warns.Count -eq 0 - if ($ok) { return "PASS (exit 0, BUILD SUCCESSFUL, 0 e:, 0 w:)" } + if ($ok) { return "PASS (exit 0, BUILD SUCCESSFUL, 0 e:, 0 w:; clean=$([bool]$Clean))" } return "FAIL: exit=$($r.Code) e:=$($errs.Count) w:=$($warns.Count) — first: $(($errs + $warns | Select-Object -First 1))" } - # Start the onboarding proof as soon as the debug APK exists. Connected tests wait - # until it finishes because both drive the same emulator. - if (-not $SkipConnected -and ($results["1. clean assembleDebug assembleRelease (0 e:, 0 w:)"] -like "PASS*")) { + # Connected tests wait until the onboarding proof finishes because both drive the same emulator. + if (-not $SkipConnected -and ($results[$buildGateName] -like "PASS*")) { try { if (Test-Path $loopLog) { Remove-Item $loopLog -Force } if (Test-Path $loopErr) { Remove-Item $loopErr -Force } @@ -154,9 +188,8 @@ if (-not $DocsOnly) { } Gate "3. Android Lint — 0 errors, 0 warnings (freshness checks advisory)" { - $r = Run-Gradle @(":app:lintDebug") $xml = "app/build/reports/lint-results-debug.xml" - if ($r.Code -ne 0 -or -not (Test-Path $xml)) { return "FAIL: lint exit=$($r.Code), report=$(Test-Path $xml)" } + if (-not (Test-Path $xml)) { return "FAIL: no lint report (merged Gradle run did not reach lintDebug)" } [xml]$doc = Get-Content $xml -Raw $advisory = @("GradleDependency", "NewerVersionAvailable", "AndroidGradlePluginVersion") $issues = @($doc.issues.issue) @@ -167,12 +200,12 @@ if (-not $DocsOnly) { } Gate "4. JVM unit tests — 0 failures" { - $r = Run-Gradle @(":app:testDebugUnitTest") $s = Sum-JUnit "app/build/test-results/testDebugUnitTest" - if ($r.Code -eq 0 -and $s.Tests -gt 0 -and $s.Failures -eq 0 -and $s.Errors -eq 0) { return "PASS ($($s.Tests) tests, 0 failures, 0 errors)" } - return "FAIL: exit=$($r.Code) tests=$($s.Tests) failures=$($s.Failures) errors=$($s.Errors)" + if ($s.Tests -gt 0 -and $s.Failures -eq 0 -and $s.Errors -eq 0) { return "PASS ($($s.Tests) tests, 0 failures, 0 errors)" } + return "FAIL: tests=$($s.Tests) failures=$($s.Failures) errors=$($s.Errors)" } } +} # ---------------------------------------------------------------------------- text gates $md = Tracked @("*.md") @@ -183,25 +216,14 @@ $listFile = Join-Path $root "build/sweep-files.txt" $text | Set-Content $listFile -Encoding utf8 Gate "6a. markdownlint-cli2 — 0 findings" { - # Windows rejects one command line containing every tracked Markdown path. - $failed = $false - $summary = @() - $linted = 0 - for ($i = 0; $i -lt $md.Count; $i += 40) { - $last = [Math]::Min($i + 39, $md.Count - 1) - $batch = @($md[$i..$last] | ForEach-Object { ":$_" }) - $out = & npx --yes markdownlint-cli2 @batch 2>&1 - $out | Add-Content $log - foreach ($line in $out) { - if ($line -match '^Linting: (\d+) files?$') { $linted += [int]$Matches[1] } - } - if ($LASTEXITCODE -ne 0) { - $failed = $true - $summary += @($out | Where-Object { $_ -match 'Summary:' }) - } - } - if (-not $failed -and $linted -eq $md.Count) { return "PASS ($linted files)" } - return "FAIL: linted=$linted expected=$($md.Count) $($summary -join ' ')" + if (-not (Test-Path -LiteralPath $markdownLint)) { return "FAIL: pinned npm tools missing (run npm ci --ignore-scripts)" } + # Invoke Node directly: one tracked-file-scoped process without cmd.exe's 8,191-character limit. + $out = & node $markdownLint @($md | ForEach-Object { ":$_" }) 2>&1 + $code = $LASTEXITCODE + $out | Add-Content $log + $linted = @($out | ForEach-Object { if ($_ -match '^Linting: (\d+) files?$') { [int]$Matches[1] } } | Measure-Object -Sum).Sum + if ($code -eq 0 -and $linted -eq $md.Count) { return "PASS ($linted files)" } + return "FAIL: exit=$code linted=$linted expected=$($md.Count) $(($out | Where-Object { $_ -match 'Summary:' }) -join ' ')" } Gate "6b. Markdown table alignment (IDE-faithful) — 0 misaligned" { @@ -223,15 +245,18 @@ $linkMd = if ($removedOrRenamed.Count -gt 0) { Gate "6c. markdown-link-check — changed docs (all after delete/rename)" { if (-not $linkBase) { return "FAIL: cannot find merge-base with origin/main" } + if ($linkMd.Count -gt 0 -and -not (Test-Path -LiteralPath $markdownLinkCheck)) { return "FAIL: pinned npm tools missing (run npm ci --ignore-scripts)" } $dead = 0 + $toolFailed = $false foreach ($f in $linkMd) { - $out = & npx --yes markdown-link-check --config .markdown-link-check.json -q $f 2>&1 + $out = & node $markdownLinkCheck --config .markdown-link-check.json -q $f 2>&1 + if ($LASTEXITCODE -ne 0) { $toolFailed = $true } $out | Add-Content $log $dead += @($out | Where-Object { $_ -match '\[✖\]|\[x\]|ERROR:' }).Count } $scope = if ($removedOrRenamed.Count -gt 0) { "all; delete/rename detected" } else { "changed" } - if ($dead -eq 0) { return "PASS ($($linkMd.Count) files; $scope)" } - return "FAIL: $dead dead link(s) — see build/sweep.log" + if (-not $toolFailed -and $dead -eq 0) { return "PASS ($($linkMd.Count) files; $scope)" } + return "FAIL: tool-failed=$toolFailed dead-links=$dead — see build/sweep.log" } Gate "6d. Harness skill trees byte-identical (.claude/.cursor/.codex)" { @@ -256,7 +281,8 @@ Gate "6e. Script self-checks (scripts/test-*.py) — all green" { Gate "7. cspell over every tracked text file — 0 unknown words" { # `--file-list ` exits 1 silently on Windows; feeding the list on stdin works everywhere. - $out = Get-Content $listFile | npx --yes cspell --no-progress --file-list stdin 2>&1 + if (-not (Test-Path -LiteralPath $cspell)) { return "FAIL: pinned npm tools missing (run npm ci --ignore-scripts)" } + $out = Get-Content $listFile | node $cspell --no-progress --file-list stdin 2>&1 $out | Add-Content $log if ($LASTEXITCODE -eq 0) { return "PASS ($($text.Count) files)" } return "FAIL: $(($out | Where-Object { $_ -match 'Issues found' }) -join ' ') — add legit terms to cspell.json words" @@ -267,7 +293,7 @@ Gate "8a. JSON validity" { foreach ($f in (Tracked @("*.json"))) { $raw = Get-Content $f -Raw if ($f -eq "cspell.json") { $raw = [regex]::Replace($raw, '(?m)^\s*//.*$', '') } - try { $null = $raw | ConvertFrom-Json } catch { $bad += $f } + try { [System.Text.Json.JsonDocument]::Parse($raw).Dispose() } catch { $bad += $f } } if ($bad.Count -eq 0) { return "PASS" } return "FAIL: $($bad -join ', ')" @@ -317,6 +343,8 @@ Gate "9. Inspect Code export (Engine 2) — 0 hard findings in tracked files" { return "FAIL: no export at $InspectExport. Android Studio → Code → Inspect Code → scope 'OpenLoop Tracked' → Export → HTML → build/inspect-export/" } +& $buildGates + Gate "5b. Onboarding loop — autonomous first-run + returning-user proof" { if ($DocsOnly) { return "SKIPPED (docs-only)" } if ($SkipConnected) { return "SKIPPED (-SkipConnected; onboarding is not verified)" } @@ -371,10 +399,12 @@ $receipt = [ordered]@{ at = (Get-Date -Format o) treeClean = ($dirty.Count -eq 0) docsOnly = [bool]$DocsOnly + cleanBuild = [bool]$Clean inspectCode = $inspect connected = (-not $SkipConnected) -and (-not $DocsOnly) onboardingLoop = if ($loopVerdict -like "PASS*") { "passed" } elseif ($loopVerdict -like "SKIPPED*") { "skipped" } else { "failed" } gates = $results + durationSec = $timings } $receiptPath = Join-Path $root "build/sweep-receipt.json" if ($failed.Count -gt 0) { diff --git a/scripts/test-pre-pr-sweep.py b/scripts/test-pre-pr-sweep.py new file mode 100644 index 0000000..7dc7c71 --- /dev/null +++ b/scripts/test-pre-pr-sweep.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Cheap contract checks for the pre-PR sweep's orchestration.""" +from pathlib import Path + + +SWEEP = Path(__file__).resolve().parent / "pre-pr-sweep.ps1" + + +def section(source, start, end): + return source[source.index(start):source.index(end)] + + +def main(): + source = SWEEP.read_text(encoding="utf-8") + + # Frequent text failures must surface before Gradle; device users must wait for the build. + assert source.index('Gate "6a.') < source.index("& $buildGates") + assert source.index("& $buildGates") < source.index('Gate "5b.') < source.index('Gate "5.') + + build = section(source, "$buildGates = {", "# ---------------------------------------------------------------------------- text gates") + for task in ("assembleDebug", "assembleRelease", ":app:lintDebug", ":app:testDebugUnitTest"): + assert task in build + assert build.count("Run-Gradle") == 1 + assert '"--continue"' in build + assert "Remove-Item -LiteralPath $unitResultsDir -Recurse -Force" in build + assert "Run-Gradle" not in section(build, 'Gate "3.', 'Gate "4.') + assert "Run-Gradle" not in section(build, 'Gate "4.', "}\n}\n}") + + # A green receipt must say whether the run was cold and carry every gate's measured time. + assert "cleanBuild = [bool]$Clean" in source + assert "durationSec = $timings" in source + + print("pre-pr sweep contract PASS") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())