diff --git a/.codacy.yaml b/.codacy.yaml index c1a7d158..b411b307 100644 --- a/.codacy.yaml +++ b/.codacy.yaml @@ -8,7 +8,7 @@ # the same reason). Workflows + composite actions are already linted by actionlint, zizmor, action-validator, the # ast-grep gha rules, and the gha* conftest policies; since Codacy cannot disable an individual pattern in-repo, # excluding these trees is the only way to silence its pin rule globally. -# - CLAUDE.md: Codacy's prose rules (undefined-acronym, absolute-rule-without-escape-hatch) fight this +# - AGENTS.md: Codacy's prose rules (undefined-acronym, absolute-rule-without-escape-hatch) fight this # agent-instructions doc, which is imperative and full of deliberate absolutes ("NEVER ...", "ALWAYS ...") by # design; dprint + typos + editorconfig already lint it, so Codacy adds only false positives here. # - services/ws-web-runner/mingw-shim/msvc_crt_alloc.c: MISRA-21.3-unavoidable heap-allocation code Codacy cannot @@ -42,7 +42,7 @@ exclude_paths: - ".github/actions/**" - ".github/workflows/**" - - "CLAUDE.md" + - "AGENTS.md" - "config/semgrep/**" - "services/ws-modules/dotnet-data1/Program.cs" - "libs/wasi-guest/src/coverage.rs" diff --git a/.dockerignore b/.dockerignore index 8090f9b2..39b5a8bf 100644 --- a/.dockerignore +++ b/.dockerignore @@ -59,6 +59,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/.github/actions/free-disk-space/action.yaml b/.github/actions/free-disk-space/action.yaml index 30b285dc..a1ab1c2f 100644 --- a/.github/actions/free-disk-space/action.yaml +++ b/.github/actions/free-disk-space/action.yaml @@ -18,8 +18,8 @@ runs: # is killed outright on exhaustion, reporting a shutdown signal rather than any build error. Root has the room: # it shows 119G free on the arm runner once the step above has run. - name: Add swap - uses: ./.github/actions/add-swap + uses: $/.github/actions/add-swap - name: Free disk space on Windows if: runner.os == 'Windows' - uses: ./.github/actions/free-disk-space-windows + uses: $/.github/actions/free-disk-space-windows diff --git a/.github/actions/install-mise-tools/action.yaml b/.github/actions/install-mise-tools/action.yaml index d113d331..92b25a5a 100644 --- a/.github/actions/install-mise-tools/action.yaml +++ b/.github/actions/install-mise-tools/action.yaml @@ -41,7 +41,7 @@ runs: steps: # Reclaim runner disk before anything is installed into it. - name: Free disk space - uses: ./.github/actions/free-disk-space + uses: $/.github/actions/free-disk-space # No cargo: tool installs on the Windows lane right now -- cargo-binstall fails to execute there (os error 193). # open-o2's opener isn't needed in CI, so skip cargo:open rather than let the install fail. @@ -51,7 +51,7 @@ runs: run: echo "MISE_DISABLE_TOOLS=cargo:open" >> "$GITHUB_ENV" - name: Install mise binary - uses: ./.github/actions/install-mise + uses: $/.github/actions/install-mise with: install-action-tools: ${{ inputs.install-action-tools }} @@ -121,7 +121,7 @@ runs: # died on a frippery.org (http:busybox) connect timeout. - name: Remove mise shim before the retry if: steps.install-mise-tools.outcome == 'failure' - uses: ./.github/actions/remove-mise-shim + uses: $/.github/actions/remove-mise-shim - name: Install mise tools (retry) if: steps.install-mise-tools.outcome == 'failure' @@ -133,4 +133,4 @@ runs: mise install - name: Remove mise shim - uses: ./.github/actions/remove-mise-shim + uses: $/.github/actions/remove-mise-shim diff --git a/.github/actions/install-mise/action.yaml b/.github/actions/install-mise/action.yaml index 136c8e81..2522594f 100644 --- a/.github/actions/install-mise/action.yaml +++ b/.github/actions/install-mise/action.yaml @@ -22,7 +22,7 @@ runs: - name: Install mise uses: taiki-e/install-action@v2 with: - tool: cargo-binstall,mise@2026.9.0 + tool: cargo-binstall,mise@2026.9.17 - name: Install extra tools via install-action if: inputs.install-action-tools != '' diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 7f6c07e1..930d46a2 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -35,7 +35,7 @@ jobs: - os: ubuntu-latest timeout: 40 - os: macos-latest - timeout: 45 + timeout: 75 - os: windows-latest timeout: 120 # Windows runs the checkers under busybox-w32 ash, same as test.yaml's Windows lane. @@ -59,7 +59,7 @@ jobs: persist-credentials: false - name: Install mise + tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 60 - name: Prefetch Rust dependencies diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 542ade12..9801abf1 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -73,7 +73,7 @@ jobs: - name: Install mise + tools if: matrix.language == 'rust' - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 60 - name: Prefetch Rust dependencies diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 1c9c99c9..1013a4cd 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -65,10 +65,10 @@ jobs: - name: Install Mesa Vulkan drivers (lavapipe) if: runner.os == 'Linux' - uses: ./.github/actions/install-lavapipe + uses: $/.github/actions/install-lavapipe - name: Install mise + coverage tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 20 with: install-action-tools: cargo-llvm-cov,deepsource diff --git a/.github/workflows/dependencies.yaml b/.github/workflows/dependencies.yaml index b83ead26..8eb807a9 100644 --- a/.github/workflows/dependencies.yaml +++ b/.github/workflows/dependencies.yaml @@ -48,7 +48,7 @@ jobs: persist-credentials: false - name: Install mise + dependency-scan tools - uses: ./.github/actions/install-mise + uses: $/.github/actions/install-mise with: install-action-tools: cargo-deny,cargo-unmaintained,coreutils,jaq,osv-scanner,ripgrep diff --git a/.github/workflows/docker-windows.yaml b/.github/workflows/docker-windows.yaml index 2bef3935..44c4f9ad 100644 --- a/.github/workflows/docker-windows.yaml +++ b/.github/workflows/docker-windows.yaml @@ -50,7 +50,7 @@ jobs: # The classic Windows builder on windows-2022 can't substitute build-args into the Dockerfile's RUN, and # mise's prebuilt "latest" zip is stale (2026.3.0, too old for the config). 2026.7.1 is required: the config # templates use Tera v2 syntax, which mise switched to in 2026.7.1 (older mise fails to parse them). - MISE_VERSION: "2026.9.0" + MISE_VERSION: "2026.9.17" steps: - name: Checkout uses: actions/checkout@v4 @@ -75,7 +75,7 @@ jobs: # does -- it only runs `docker build` and `docker run`. check.yaml and test.yaml share this action and # leave both off, because test.yaml's `override (msvc)` lane does link natively against them. - name: Free disk space on Windows runner - uses: ./.github/actions/free-disk-space-windows + uses: $/.github/actions/free-disk-space-windows with: keep-image: mcr.microsoft.com/windows/${{ matrix.base }}:${{ matrix.windows_version }} visual-studio: "true" diff --git a/.github/workflows/k3s.yaml b/.github/workflows/k3s.yaml index 99279530..09bc38c4 100644 --- a/.github/workflows/k3s.yaml +++ b/.github/workflows/k3s.yaml @@ -74,7 +74,7 @@ jobs: run: echo "MISE_ENV=$MISE_ENV" - name: Install mise + tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 60 with: github-token: ${{ github.token }} @@ -142,7 +142,7 @@ jobs: persist-credentials: false - name: Install mise + tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 60 with: github-token: ${{ github.token }} @@ -181,7 +181,7 @@ jobs: persist-credentials: false - name: Install mise + tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 60 with: github-token: ${{ github.token }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ccee98b6..e3c1fb7d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -120,7 +120,7 @@ jobs: - name: Install Mesa Vulkan drivers (lavapipe) if: runner.os == 'Linux' - uses: ./.github/actions/install-lavapipe + uses: $/.github/actions/install-lavapipe # Windows tools source-build under mise 2026.7.1, so this step runs long (bumped from 20). # The per-tool msvc `install_env` override no longer reaches cargo-binstall there, so cargo tools like @@ -137,7 +137,7 @@ jobs: # on commit https://github.com/edge-toolkit/core/commit/5d7dfaa10c0d10e980aa7a4a785476be059699fb at # https://github.com/edge-toolkit/core/actions/runs/36812561314/job/110210608554. - name: Install mise + tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: ${{ matrix.install_timeout || 60 }} env: ET_LINK_WITH_MOLD: "false" @@ -216,7 +216,7 @@ jobs: persist-credentials: false - name: Install mise + tools - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools timeout-minutes: 60 - name: Prefetch dependencies @@ -299,7 +299,7 @@ jobs: # reason for one) -- busybox-w32 is an x64 exe, and this job's single task chain is far too short for the # Git Bash cygheap pathology that override exists to dodge. - name: Install mise - uses: ./.github/actions/install-mise + uses: $/.github/actions/install-mise # Both toolchains the Windows [[tools.rust]] entries name, resolved at the arm64 host triple. # python is here because a workspace build reaches et-ws-pyo3-runner, whose pyo3-ffi build script runs @@ -347,7 +347,7 @@ jobs: # install-mise-tools ends with this, but this job deliberately does not use it, so it clears its own. - name: Remove mise shim - uses: ./.github/actions/remove-mise-shim + uses: $/.github/actions/remove-mise-shim # A build, not a check: codegen and linking are where a new host triple actually fails. # The ceiling allows for the macos-26-intel runners' pace, which swings by more than two to one between diff --git a/.github/workflows/upstream-cache.yaml b/.github/workflows/upstream-cache.yaml index a5081e8f..304779e7 100644 --- a/.github/workflows/upstream-cache.yaml +++ b/.github/workflows/upstream-cache.yaml @@ -153,7 +153,7 @@ jobs: if: |- steps.rp_check.outputs.work == 'yes' && github.event.pull_request.head.repo.fork != true - uses: ./.github/actions/install-mise-tools + uses: $/.github/actions/install-mise-tools with: github-token: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 263c0089..187f2475 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/.mise/config.coverage.toml b/.mise/config.coverage.toml index f09979b0..e5412f31 100644 --- a/.mise/config.coverage.toml +++ b/.mise/config.coverage.toml @@ -397,12 +397,12 @@ description = "Combined Python coverage (pytest + web-runner Pyodide runs) -> Co # schema that records each test's file, which Codecov's test analytics reads. run = """ pycov=target/pycov -mkdir -p "$pycov" +coreutils mkdir -p "$pycov" for module in pyface1 pydemo1 pyeye1 pyspeech1; do dir="services/ws-modules/$module" junit="$PWD/$pycov/junit-$module.xml" uv run --directory "$dir" pytest --cov="$module" --cov-report= --junitxml="$junit" -o junit_family=legacy - cp "$dir/.coverage" "$pycov/.coverage.${module}_pytest" + coreutils cp "$dir/.coverage" "$pycov/.coverage.${module}_pytest" done pyface=services/ws-modules/pyface1 uv run --project "$pyface" coverage combine "$pycov" diff --git a/.mise/config.dart.toml b/.mise/config.dart.toml index 5434349b..c9b2967d 100644 --- a/.mise/config.dart.toml +++ b/.mise/config.dart.toml @@ -26,7 +26,8 @@ version_expr = ''' fromJSON(body).prefixes | filter({ # matches "^channels/stable/release/(\\d+\\.\\d+\\.\\d+)/$" }) | map({split(#, "/")[3]}) -| sortVersions()''' +| sortVersions() +''' version_list_url = "{{ vars.dart_bucket }}?prefix=channels/stable/release/&delimiter=/" [tasks.dart-pub-get] @@ -102,7 +103,7 @@ shell = "{{ vars.task_shell }}" depends = ["gen:ws-spec"] description = "Emit the Dart sealed-class WS client via dart-typegen (consumes generated/specs/ws.kdl from gen:ws-spec)" run = """ -mkdir -p generated/dart-ws/lib +coreutils mkdir -p generated/dart-ws/lib dart-typegen generate -i generated/specs/ws.kdl -o generated/dart-ws/lib/ws_messages.dart dart format generated/dart-ws/lib/ws_messages.dart """ @@ -130,7 +131,7 @@ dart pub get coreutils rm -rf lib dart run swagger_parser s=../../target/scratch -mkdir -p "$s" +coreutils mkdir -p "$s" goawk 'BEGIN { q = sprintf("%c", 39) } /^import / && /dart:io/ { print "import " q "dart:typed_data" q ";"; io++; next } /^ Future getFile\\(\\{$/ { diff --git a/.mise/config.dotnet.toml b/.mise/config.dotnet.toml index e9c439d0..9f35f601 100644 --- a/.mise/config.dotnet.toml +++ b/.mise/config.dotnet.toml @@ -48,7 +48,7 @@ fi dotnet publish -c Release $$publish_args PUBLISH=bin/Release/net10.0/publish/wwwroot/_framework -cp "$$PUBLISH"/*.js "$$PUBLISH"/*.wasm "$$PUBLISH"/*.dat pkg/ +coreutils cp "$$PUBLISH"/*.js "$$PUBLISH"/*.wasm "$$PUBLISH"/*.dat pkg/ ''' [tasks.dotnet-fmt] diff --git a/.mise/config.java.toml b/.mise/config.java.toml index a6f08a4a..c2a532d0 100644 --- a/.mise/config.java.toml +++ b/.mise/config.java.toml @@ -36,7 +36,8 @@ java_home = '''{% if os() == "windows" and env?.MISE_INSTALLS_DIR -%} {%- else -%} {{- env?.MISE_DATA_DIR or (env.HOME ~ "/.local/share/mise") -}} /installs/java/26.0.1 -{%- endif %}''' +{%- endif -%} +''' [env] # JAVA_HOME must be set in the env because mvn.cmd requires it. @@ -65,7 +66,8 @@ MVN = '''{% if os() == "windows" -%} {{- vars.maven_bin -}}\mvn.cmd {%- else -%} mvn -{%- endif %}''' +{%- endif -%} +''' [tasks.build-ws-java-data1-module] description = "Build the java-data1 workflow module" diff --git a/.mise/config.js.toml b/.mise/config.js.toml index 4cd443a6..cd94f9d7 100644 --- a/.mise/config.js.toml +++ b/.mise/config.js.toml @@ -26,7 +26,7 @@ # release assets, distributing per-platform binaries via `@oxlint-tsgolint/` optional deps, so every OS # is covered without os-scoping. "npm:oxlint-tsgolint" = "0.24.0" -"npm:pnpm" = { version = "latest", os = ["macos/x64"] } +"npm:pnpm" = { version = "11", os = ["macos/x64"] } # oxlint + oxfmt are the Rust-native JS/TS linter + formatter from the oxc-project. # They are pulled directly from the shared `apps_v` GitHub release. Aqua's registry entry trips mise's @@ -50,24 +50,25 @@ url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/ox url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/oxlint-x86_64-pc-windows-msvc.zip" # oxfmt is pinned independently of oxlint. -# Both ship from per-version `apps_v` tags but track separate semver. oxfmt stays on apps_v1.69.0 / 0.54.0: its -# output is tuned against dprint (config/oxfmtrc.jsonc + config/dprint.jsonc) at that version, and a bump risks -# reformatting churn that fights dprint. oxlint above rode ahead to 1.73.0 for the `--type-aware` engine. Re-pin -# oxfmt here only after re-validating the oxfmt <-> dprint agreement at the new version. +# Both ship from per-version `apps_v` tags but track separate semver, and `version` names the tag, as mise holds +# it to the version in the URL. oxfmt stays on apps_v1.69.0, which ships oxfmt 0.54.0: its output is tuned against +# dprint (config/oxfmtrc.jsonc + config/dprint.jsonc) at that version, and a bump risks reformatting churn that +# fights dprint. oxlint above rode ahead to 1.73.0 for the `--type-aware` engine. Re-pin oxfmt here only after +# re-validating the oxfmt <-> dprint agreement at the new version. [tools."http:oxfmt"] bin = "oxfmt" rename_exe = "oxfmt" -version = "0.54.0" +version = "1.69.0" [tools."http:oxfmt".platforms.linux-arm64] -url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-aarch64-unknown-linux-gnu.tar.gz" +url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/oxfmt-aarch64-unknown-linux-gnu.tar.gz" [tools."http:oxfmt".platforms.linux-x64] -url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-x86_64-unknown-linux-gnu.tar.gz" +url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/oxfmt-x86_64-unknown-linux-gnu.tar.gz" [tools."http:oxfmt".platforms.macos-arm64] -url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-aarch64-apple-darwin.tar.gz" +url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/oxfmt-aarch64-apple-darwin.tar.gz" [tools."http:oxfmt".platforms.macos-x64] -url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-x86_64-apple-darwin.tar.gz" +url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/oxfmt-x86_64-apple-darwin.tar.gz" [tools."http:oxfmt".platforms.windows-x64] -url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-x86_64-pc-windows-msvc.zip" +url = "https://github.com/oxc-project/oxc/releases/download/apps_v{{version}}/oxfmt-x86_64-pc-windows-msvc.zip" [tasks.build-ws-har1-module] depends = ["build-et-cli", "build-wasm-cov-wrapper"] diff --git a/.mise/config.kotlin.toml b/.mise/config.kotlin.toml index 1ed1c0f4..26d301b6 100644 --- a/.mise/config.kotlin.toml +++ b/.mise/config.kotlin.toml @@ -23,7 +23,8 @@ GRADLE = '''{% if os() == "windows" -%} {{- vars.gradle_bin -}}\gradle.bat {%- else -%} gradle -{%- endif %}''' +{%- endif -%} +''' [tasks.build-ws-kotlin-data1-module] description = "Build the kotlin-data1 workflow module (Kotlin/Wasm -> WasmGC)" diff --git a/.mise/config.linux.toml b/.mise/config.linux.toml index 92c67048..e04606de 100644 --- a/.mise/config.linux.toml +++ b/.mise/config.linux.toml @@ -8,7 +8,7 @@ # has libclang-cpp (the C++ API), not the C one. "conda:clangxx" = "latest" # gpg for mise's gpg_verify signature checks; _setup_all installs it up front. -"conda:gnupg" = "latest" +"conda:gnupg" = { version = "latest", os = ["linux"] } # mold, the linker a Linux lane that sets ET_LINK_WITH_MOLD links Rust with. "aqua:rui314/mold" = "latest" @@ -56,7 +56,7 @@ # mise can't render. a_conda_arch: conda's target-triple dir (x86_64/aarch64 vs mise's x64/arm64). a_conda_arch = "{% if arch() == 'arm64' %}aarch64{% else %}x86_64{% endif %}" a_conda_clangxx = "{{ env.HOME }}/.local/share/mise/installs/conda-clangxx/latest" -b_clang_resource = "{{ vars.a_conda_clangxx }}/lib/clang/22" +b_clang_resource = "{{ vars.a_conda_clangxx }}/lib/clang/23" b_clang_sysroot = "{{ vars.a_conda_clangxx }}/{{ vars.a_conda_arch }}-conda-linux-gnu/sysroot" # Link through mold rather than the system linker, for a lane that sets ET_LINK_WITH_MOLD=true. # On aarch64 the system linker is GNU ld -- rustc only defaults to its bundled lld on x86_64 -- and linking the @@ -108,7 +108,7 @@ description = "Preinstall: shared base + verify system build prerequisites" run = """ # Some third-party install scripts hard-code bare `awk`. # dotnet-install.sh notably, invoked by the `dotnet` mise tool below, does this. Repo policy is goawk-only -# (CLAUDE.md "Don't depend on host tools"); fedora/ubuntu/debian base images happen to ship awk pre-installed +# (AGENTS.md "Don't depend on host tools"); fedora/ubuntu/debian base images happen to ship awk pre-installed # so this is a no-op there, but Azure Linux's base/core is more minimal and ships without awk. Provide one as # a symlink to mise's goawk so policy holds (the only awk binary on the system IS goawk) and the third-party # script finds something on PATH. goawk is installed in `_setup_all` (config.toml) before this task body diff --git a/.mise/config.macos.toml b/.mise/config.macos.toml index 244ec7b1..d4c0c060 100644 --- a/.mise/config.macos.toml +++ b/.mise/config.macos.toml @@ -4,7 +4,7 @@ [tools] # gpg for mise's gpg_verify signature checks; _setup_all installs it up front. -"conda:gnupg" = "latest" +"conda:gnupg" = { version = "latest", os = ["macos"] } [vars] # Xcode's libclang (the lib dir beside `xcrun`'s clang). diff --git a/.mise/config.maint.toml b/.mise/config.maint.toml index 0e69e417..623c0e32 100644 --- a/.mise/config.maint.toml +++ b/.mise/config.maint.toml @@ -28,7 +28,7 @@ [tools] # Rust-native HTTP client replacing the host `curl`. -# See CLAUDE.md "Don't depend on host tools in mise tasks". Behaves like HTTPie on the CLI; `--follow` is +# See AGENTS.md "Don't depend on host tools in mise tasks". Behaves like HTTPie on the CLI; `--follow` is # needed because xh doesn't follow redirects by default like curl -L does. "aqua:ducaale/xh" = "latest" # 7-zip CLI as a standalone `7zz` binary. diff --git a/.mise/config.python.toml b/.mise/config.python.toml index ff40812b..1c7829e4 100644 --- a/.mise/config.python.toml +++ b/.mise/config.python.toml @@ -226,7 +226,7 @@ dir = "services/ws-modules/wasi-graphics-info" # image, so the guest fetches it via the `wasi:keyvalue/store` host import from the ws-server at runtime. # componentize-py 0.23's `bindings` subcommand refuses to overwrite an existing output dir, so we wipe it first. run = """ -rm -rf wit_world +coreutils rm -rf wit_world componentize-py -d {{ vars.wit_dir }} -w module bindings . componentize-py -d {{ vars.wit_dir }} -w module componentize wasi_graphics_info -o pkg/et_ws_wasi_graphics_info.wasm {{ vars.et_cli }} module-package-json @@ -256,7 +256,7 @@ shell = "{{ vars.task_shell }}" depends = ["gen:ws-spec"] description = "Emit the typed Python REST client via openapi-python-client (consumes generated/specs/rest.yaml)" run = """ -mkdir -p generated/python-rest/et_rest_client +coreutils mkdir -p generated/python-rest/et_rest_client # None of these args move into config/openapi-python-client.yaml. # path / meta / overwrite / output-path are CLI-only `generate` options. Build # them up in a shell var (split over two lines) so neither line needs a backslash @@ -268,7 +268,7 @@ args="$args --meta none --overwrite --output-path generated/python-rest/et_rest_ openapi-python-client generate $args # Remove the .ruff_cache that openapi-python-client / our follow-up ruff drop. # It lands next to the generated source; we don't want that committed. -rm -rf generated/python-rest/et_rest_client/.ruff_cache +coreutils rm -rf generated/python-rest/et_rest_client/.ruff_cache # Run both ruff passes ourselves from the workspace's `ruff` install. # openapi-python-client's built-in post-hooks (`ruff check --fix-only` + `ruff format`) are disabled via # config/openapi-python-client.yaml because they emit "ruff is not in PATH" on Windows where ruff doesn't sit @@ -287,7 +287,7 @@ description = "Emit Pydantic models for the WS protocol via datamodel-code-gener # style flags); only the input/output paths are passed on the CLI. dir = "generated/python-ws" run = """ -mkdir -p et_ws +coreutils mkdir -p et_ws datamodel-codegen --input ../../target/int-gen/ws.schema.json --output et_ws/messages.py # Drop the 2-line header that custom-file-header = "#" emits, so the file starts cleanly. # That header is a lone `#` + the blank after it. tail, not sed: datamodel-codegen always emits exactly those diff --git a/.mise/config.rust.toml b/.mise/config.rust.toml index b7548d3d..09870eb0 100644 --- a/.mise/config.rust.toml +++ b/.mise/config.rust.toml @@ -113,8 +113,9 @@ description = "Build the Rust WASI data1 module as a WASI Preview 2 component" # copied into the module's pkg/ for et-modules-service to serve. run = """ {{ vars.wasm_cov }} cargo build --release -p et-ws-wasi-data1 --target wasm32-wasip2{{ vars.wasi_cov_feat }} -mkdir -p services/ws-modules/wasi-data1/pkg -cp target/wasm32-wasip2/release/et_ws_wasi_data1.wasm services/ws-modules/wasi-data1/pkg/et_ws_wasi_data1.wasm +coreutils mkdir -p services/ws-modules/wasi-data1/pkg +wasm=et_ws_wasi_data1.wasm +coreutils cp "target/wasm32-wasip2/release/$wasm" "services/ws-modules/wasi-data1/pkg/$wasm" {{ vars.et_cli }} module-package-json --module-dir services/ws-modules/wasi-data1 """ shell = "{{ vars.task_shell }}" @@ -124,8 +125,9 @@ depends = ["build-et-cli"] description = "Build the Rust WASI math1 module as a WASI Preview 2 component" run = """ {{ vars.wasm_cov }} cargo build --release -p et-ws-wasi-math1 --target wasm32-wasip2{{ vars.wasi_cov_feat }} -mkdir -p services/ws-modules/wasi-math1/pkg -cp target/wasm32-wasip2/release/et_ws_wasi_math1.wasm services/ws-modules/wasi-math1/pkg/et_ws_wasi_math1.wasm +coreutils mkdir -p services/ws-modules/wasi-math1/pkg +wasm=et_ws_wasi_math1.wasm +coreutils cp "target/wasm32-wasip2/release/$wasm" "services/ws-modules/wasi-math1/pkg/$wasm" {{ vars.et_cli }} module-package-json --module-dir services/ws-modules/wasi-math1 """ shell = "{{ vars.task_shell }}" @@ -135,9 +137,9 @@ depends = ["build-et-cli"] description = "Build the Rust WASI math1-sender module as a WASI Preview 2 component" run = """ {{ vars.wasm_cov }} cargo build --release -p et-ws-wasi-math1-sender --target wasm32-wasip2{{ vars.wasi_cov_feat }} -mkdir -p services/ws-modules/wasi-math1-sender/pkg +coreutils mkdir -p services/ws-modules/wasi-math1-sender/pkg sender=et_ws_wasi_math1_sender.wasm -cp "target/wasm32-wasip2/release/$sender" "services/ws-modules/wasi-math1-sender/pkg/$sender" +coreutils cp "target/wasm32-wasip2/release/$sender" "services/ws-modules/wasi-math1-sender/pkg/$sender" {{ vars.et_cli }} module-package-json --module-dir services/ws-modules/wasi-math1-sender """ shell = "{{ vars.task_shell }}" @@ -147,8 +149,9 @@ depends = ["build-et-cli"] description = "Build the Rust WASI comm1 module as a WASI Preview 2 component" run = """ {{ vars.wasm_cov }} cargo build --release -p et-ws-wasi-comm1 --target wasm32-wasip2{{ vars.wasi_cov_feat }} -mkdir -p services/ws-modules/wasi-comm1/pkg -cp target/wasm32-wasip2/release/et_ws_wasi_comm1.wasm services/ws-modules/wasi-comm1/pkg/et_ws_wasi_comm1.wasm +coreutils mkdir -p services/ws-modules/wasi-comm1/pkg +wasm=et_ws_wasi_comm1.wasm +coreutils cp "target/wasm32-wasip2/release/$wasm" "services/ws-modules/wasi-comm1/pkg/$wasm" {{ vars.et_cli }} module-package-json --module-dir services/ws-modules/wasi-comm1 """ shell = "{{ vars.task_shell }}" diff --git a/.mise/config.toml b/.mise/config.toml index eaa84522..6d648e77 100644 --- a/.mise/config.toml +++ b/.mise/config.toml @@ -16,7 +16,7 @@ # installs node ahead of any npm: tool, install-mise-tools stops restoring the GHCR store, and every task # declares a `shell` that routes its body through a wrapper script. A warm checkout needs `mise install` re-run # once -- a tool this mise cannot resolve still reports as installed, so nothing refetches it on its own. -min_version = "2026.9.0" +min_version = "2026.9.17" [settings] # Disable mise's two auto-install paths so tasks fail fast on a missing tool. @@ -99,25 +99,11 @@ conftest = "latest" # aqua records `provenance = "github-attestations"` instead, which is what every other pinned tool here uses. # This is the compose implementation only -- a docker daemon still has to come from the host. "aqua:docker/compose" = "latest" +dprint = "latest" +editorconfig-checker = "latest" "github:nextest-rs/nextest" = { version = "latest", version_prefix = "cargo-nextest-" } taplo = "latest" watchexec = "latest" -# uutils coreutils: the Rust multicall binary, invoked as `coreutils ` in tasks. -# Pinned to 0.6.0 (NOT the latest 0.9.0) because uutils 0.7.0+ ships the Windows release as 85 per-utility -# .exes with no multicall coreutils.exe (see uutils/coreutils#11268). 0.6.0 keeps the multicall layout -# uniform across Linux/macOS/Windows, so tasks can keep using `coreutils ` everywhere. Bump cautiously: -# confirm the Windows zip layout hasn't reverted before raising the pin. -coreutils = "0.6.0" -dprint = "latest" -# Held at the last release whose assets aqua's registry entry still names. -# v4.0.0 renamed every asset from `ec--` to `editorconfig-checker--`, and aqua's manifest -# was not updated, so `latest` resolves to a version whose download it cannot find: -# aqua:editorconfig-checker/editorconfig-checker@latest: no asset found: ec-windows-amd64.zip -# on commit https://github.com/edge-toolkit/core/commit/02d645a30b89850b5d27711e0dd8f61780dcdcb3 at -# https://github.com/edge-toolkit/core/actions/runs/33945730231/job/101251329874. The rename is not -# Windows-specific -- every platform's asset moved -- so this holds every lane, not just that one. Drop the pin -# once the aqua registry ships a version_overrides entry for 4.x. -editorconfig-checker = "3.11.3" # ripgrep (rg): the Rust grep that tasks use in place of the host's grep. ripgrep = "latest" # uutils findutils (find + xargs), pinned to 0.8.0 (0.9.0 ships no binaries). @@ -176,8 +162,12 @@ go = "latest" "go:github.com/noperator/jqfmt/cmd/jqfmt" = "0.1.0" hadolint = "latest" ls-lint = "latest" -lychee = "latest" -mprocs = "latest" +# dekit, mprocs under its new name: `dekit mprocs` runs the repo-root mprocs.yaml. +# The github backend rather than the registry's `aqua:pvolok/dekit`, whose manifest still names the pre-rename +# assets, so every platform fails with +# aqua:pvolok/dekit@0.10.0: no asset found: mprocs-0.10.0-darwin-aarch64.tar.gz, mprocs-0.10.0-darwin-universal.tar.gz +# on mise 2026.9.18. Return to the registry name once its aqua entry knows the `dekit-` assets. +"github:pvolok/dekit" = "latest" node = "22" osv-scanner = "latest" # Aqua has no pipx build for windows/amd64. @@ -191,8 +181,22 @@ gh = "latest" "pipx:cowsay" = "latest" "pipx:semgrep" = "latest" # Aqua has no pnpm darwin/amd64 prebuilt. -# The `npm:pnpm` fallback for macos/x64 lives in the `js` env (config.js.toml). -pnpm = { version = "latest", os = ["linux", "macos/arm64", "windows"] } +# The `npm:pnpm` fallback for macos/x64 lives in the `js` env (config.js.toml), held to the same major. +# +# Held at pnpm 11 because pnpm 12 cannot install on Nano Server. pnpm 12 resolves its store operation lock directory +# only through `SHGetKnownFolderPath(FOLDERID_LocalAppData)`, with no setting or variable to override it, and Nano's +# shell32 lacks that entry point, so every install there aborts before resolving a single package: +# +# Error: ERR_PNPM_STORE_DIR_OPEN_OPERATION_LOCK +# x installing dependencies +# `-> Failed to open the store operation lock at "pnpm-store-operation-locks": +# failed to resolve the local application data directory: HRESULT 0x80004005 +# +# Seen in `prefetch:node` on the `build (windows-2022, nanoserver)` lane at commit +# https://github.com/edge-toolkit/core/commit/4daebb043af06dfd3b0f81ef301f5b0ead6d50b0, +# https://github.com/edge-toolkit/core/actions/runs/36950377535/job/110661783062. pnpm 11 runs on node and never +# calls the API. Held everywhere rather than on Nano alone so every lane installs the workspace with one pnpm. +pnpm = { version = "11", os = ["linux", "macos/arm64", "windows"] } protoc = "latest" # Full version triple, not a minor pin. # mise installs python under a per-tool dir named after the request and only symlinks the `3.x` minor alias @@ -271,6 +275,31 @@ crate = "rustfs" os = ["macos/x64"] version = "tag:1.0.0-beta.12" +# uutils coreutils: the Rust multicall binary, invoked as `coreutils ` in tasks. +# Pinned to 0.6.0 (NOT the latest 0.9.0) because uutils 0.7.0+ ships the Windows release as 85 per-utility +# .exes with no multicall coreutils.exe (see uutils/coreutils#11268). 0.6.0 keeps the multicall layout +# uniform across Linux/macOS/Windows, so tasks can keep using `coreutils ` everywhere. Bump cautiously: +# confirm the Windows zip layout hasn't reverted before raising the pin. +# +# On Linux it takes the musl build. The gnu one needs GLIBC_2.39, so on the ubuntu:22.04 (2.35) and +# debian:bookworm (2.36) image bases it cannot start, and every `coreutils` call there fails -- first the preinstall +# libicu probe, as `preinstall: missing required build prerequisite: the versioned libicu runtime` on the +# `build (debian:bookworm)` and `build (ubuntu:22.04)` lanes of +# https://github.com/edge-toolkit/core/actions/runs/36933521606. mise picks the gnu build for a glibc platform +# unless told otherwise, and the aqua registry entry offers no way to tell it, hence the github backend. +# +# The pattern is one template for every platform rather than a per-platform `asset_pattern`: mise keys a lock +# entry on its options, so per-platform patterns become separate entries that an install on any other platform +# prunes, and `mise-lock-check` then reports the lockfile as drifted. +[tools."github:uutils/coreutils"] +asset_pattern = "{{ vars.musl_pattern }}" +version = "0.6.0" + +# lychee takes its musl build on Linux for the same reason as coreutils above: the gnu one needs GLIBC_2.39. +[tools."github:lycheeverse/lychee"] +asset_pattern = "{{ vars.musl_pattern }}" +version = "latest" + # Native rustpython binary built from upstream RustPython main. # Built with `freeze-stdlib` (so the binary embeds the Python stdlib and doesn't need a RUSTPYTHONPATH dance) # + the upstream pip audit-hook fix (RustPython#7956). Per-platform url + checksum, os-scoped to only those @@ -458,6 +487,11 @@ rust_nightly = "nightly-2026-08-05" # and its own `[vars]` are therefore absent from the context. Declaring it there failed every `mise upgrade` # that had work to do, with `Field win_rust_host is not defined`; this file is active everywhere. win_rust_host = "{% if arch() == 'arm64' %}aarch64-pc-windows-msvc{% else %}x86_64-pc-windows-gnullvm{% endif %}" +# The github-backend `asset_pattern` that takes a Rust-triple release's musl build on Linux. +# `raw` keeps the config's own render from evaluating it, so the backend renders it per target platform and the +# lock records the one template rather than a host-specific string. The pattern is anchored and the shortest match +# wins, which is what the trailing `*` leans on to take `.tar.gz` / `.zip` over their `.sha256` sidecars. +musl_pattern = '{% raw %}*-{{ x86_64_arch }}-*{{ os(linux="musl.t", macos="darwin.t", windows="msvc.z") }}*{% endraw %}' # Tier-`a_` prefix marks leaf values referenced by later vars. # a_* vars are referenced by later vars (face1_src), and mise renders [vars] in alphabetical order; `a_` sorts # before every non-prefixed var name so the reference resolves. Shared GitHub release tag for the HF-asset @@ -479,7 +513,8 @@ a_home = '''{% if os() == "windows" -%} {{- (env?.USERPROFILE or "") | replace(from="\\", to="/") -}} {%- else -%} {{- env.HOME -}} -{%- endif %}''' +{%- endif -%} +''' # augeas asset filenames, one per supported platform. # Each matches an `[asset.""]` row in config/upstream-cache/data.toml so the checksums.rego policy # can enforce the cross-reference. All five tarballs are uploaded to the augeas-v1 release by the @@ -676,6 +711,14 @@ a_rp_wasm_short = "08a1d6f" # normalizer (`cp: The system cannot find the path specified. (os error 3)`). # Extra actionlint flags for actionlint-check; empty everywhere except the config.windows.toml override. actionlint_args = "" +# The one actionlint error actionlint-check ignores: a local action written in GitHub's self-repository syntax. +# That syntax (`uses: $/.github/actions/`) arrived in July 2026, and actionlint 1.7.12, the latest release, +# predates it, so it reports every such ref as +# specifying action "$/.github/actions/install-mise" in invalid format because ref is missing. +# available formats are "{owner}/{repo}@{ref}" or "{owner}/{repo}/{path}@{ref}" [action] +# The pattern matches only that message for a `$/.github/actions/` ref, so a malformed remote ref is still caught. +# Drop it once an actionlint release understands `$/`. +actionlint_ignore = "-ignore 'specifying action ..[/][.]github/actions/[^ ]+ in invalid format because ref is missing'" gh_http = "--http-url https://github.com --progress --ignore-existing" # Shared shfmt flags for the shfmt-mise-check / shfmt-mise-fmt pair. # `-ln bash` because a split-out body carries no shebang for shfmt to sniff, `-i 2` to match the indent_size @@ -688,6 +731,11 @@ shfmt_args = "-ln bash -i 2 -ci" # body does. Double-quoted so a checkout path containing a space still arrives as one operand -- mise splits a # `shell` string on whitespace, honouring double quotes but not single. task_shell = 'bash -euo pipefail "{{ config_root }}/.mise/task-shell.sh"' +# The TOML files the taplo tasks act on, NUL-separated: every tracked or new-but-not-ignored `*.toml`. +# Named explicitly because taplo's own discovery walks the tree following links before it applies `exclude`, and pnpm +# links an optional package it skips on the host to `../../../../..`, the repo root -- so `taplo lint` and +# `taplo format --check` recursed through the repo inside node_modules forever instead of failing. +toml_files = "git ls-files -z --cached --others --exclude-standard '*.toml'" # `set -x` variant, for a body whose every command should be traced. task_shell_trace = 'bash -xeuo pipefail "{{ config_root }}/.mise/task-shell.sh"' # Unguarded variant, for a body that checks its own exit codes and must not abort on the first failure. @@ -708,7 +756,8 @@ rp_wasm_dir = '''{% if os() == "windows" and env?.MISE_INSTALLS_DIR -%} {{- base -}}/mise/installs/http-rp-wasm/{{- vars.a_rp_wasm_short -}} {%- else -%} {{- vars.mise_data_dir -}}/installs/http-rp-wasm/{{- vars.a_rp_wasm_short -}} -{%- endif %}''' +{%- endif -%} +''' [env] # Comma-separated list of every language env (one per .mise/config..toml). @@ -756,8 +805,8 @@ ORT_LIB_LOCATION = "{% if os() == 'windows' %}{{ vars.ort_loc_win }}{% else %}{{ ORT_SKIP_DOWNLOAD = "1" [tasks] -ec = "ec" -editorconfig-check = "ec" +ec = "editorconfig-checker" +editorconfig-check = "editorconfig-checker" [tasks.dprint-check] env = { DPRINT_CACHE_DIR = "{{ config_root }}/target/dprint-cache" } @@ -809,6 +858,7 @@ depends = [ "cargo-clippy-check", "cargo-doc-check", "cargo-fmt-check", + "checks-md-check", "conftest-check", "dockerignore-check", "dprint-check", @@ -867,7 +917,7 @@ description = "Validate GitHub Actions workflow + composite-action YAML" run = "action-validator .github/workflows/*.yaml .github/actions/*/action.yaml" [tasks.agent-lint-check] -description = "Lint this repository's Claude configuration (CLAUDE.md, .claude/) with agent-lint" +description = "Lint this repository's agent configuration (AGENTS.md, .claude/) with agent-lint" # Skips where upstream ships no binary rather than failing on a missing one. # That is the one case this repo treats a missing tool as expected: the `[tools]` entry is os-scoped to the # targets the release actually carries, so on any other platform there is nothing to install and nothing this @@ -891,7 +941,7 @@ description = "Lint GitHub Actions workflows (actionlint): local-action input va # warns). actionlint lints workflows only, so it does NOT see composite-action -> action calls; the gha_uses # conftest rule covers that direction. Intentional word-splitting sites carry an inline # `# shellcheck disable=SC2086` directive in the run script, as the mise-task bodies do. -run = "actionlint {{ vars.actionlint_args }} .github/workflows/*.yaml" +run = "actionlint {{ vars.actionlint_args }} {{ vars.actionlint_ignore }} .github/workflows/*.yaml" [tasks.zizmor-check] description = "Audit GitHub Actions workflows + composite actions for security issues (zizmor)" @@ -1104,11 +1154,11 @@ run = "cargo clippy --fix --allow-dirty --allow-staged --keep-going --workspace [tasks.taplo-fmt] alias = "toml-fmt" -run = "taplo format" +run = "{{ vars.toml_files }} | xargs -0 taplo format" [tasks.taplo-fmt-check] alias = "toml-fmt-check" -run = "taplo format --check" +run = "{{ vars.toml_files }} | xargs -0 taplo format --check" [tasks.conftest-check] depends = ["conftest-check-*"] @@ -1123,14 +1173,14 @@ description = "Run conftest OPA/Rego policies over the TOML config + lock files" # namespaces are listed explicitly, so the per-file `gha` (YAML) namespace is never evaluated against this # combined TOML input. run = """ -ns_list="cross cargo mise pyproject no_trailing_backslash checksums advisories" +ns_list="cross cargo mise mise_lock pyproject no_trailing_backslash checksums advisories" named="Cargo.lock config/upstream-cache/data.toml config/deny.toml" # Both lists rely on word-splitting when they expand. # $ns expands to repeated `--namespace ` pairs; $named is a space-separated path list. # shellcheck disable=SC2086 ns=$(for n in $ns_list; do echo -n " --namespace $n"; done) # shellcheck disable=SC2086 -git ls-files '*Cargo.toml' '.mise/config*.toml' '*pyproject.toml' $named | +git ls-files '*Cargo.toml' '.mise/config*.toml' '.mise/mise*.lock' '*pyproject.toml' $named | xargs conftest test --combine --parser toml $ns -p config/conftest/policy """ shell = "{{ vars.task_shell }}" @@ -1283,7 +1333,7 @@ description = "Check that every multi-line bash mise task body is shfmt-formatte # The `-d` pass is what makes a failure actionable -- shfmt prints the offending body's own diff -- while the # hash compare additionally catches whatever the merge pass would rewrite outside shfmt's view (the TOML # escape normalisation .mise/shfmt-mise.awk performs on a `"""` body). -run = ''' +run = """ work="{{ vars.config_root_fwd }}/target/scratch/shfmt-mise-check" coreutils rm -rf "$work" status=0 @@ -1305,7 +1355,7 @@ for cfg in .mise/config*.toml; do fi done exit $status -''' +""" shell = "{{ vars.task_shell }}" [tasks.shfmt-mise-fmt] @@ -1313,7 +1363,7 @@ description = "Format every multi-line bash mise task body with shfmt" # Split each config's task bodies into scratch scripts, shfmt them, then merge them back over the config. # .mise/shfmt-mise.awk owns both halves of that trip; the two loops here are split around one shfmt call so # the glob always has something to match (config.java.toml carries no multi-line body of its own). -run = ''' +run = """ work="{{ vars.config_root_fwd }}/target/scratch/shfmt-mise-fmt" coreutils rm -rf "$work" for cfg in .mise/config*.toml; do @@ -1327,7 +1377,7 @@ for cfg in .mise/config*.toml; do goawk -N raw -v mode=merge -v dir="$d" -f .mise/shfmt-mise.awk "$cfg" >"$d/merged.toml" coreutils cp "$d/merged.toml" "$cfg" done -''' +""" shell = "{{ vars.task_shell }}" # taplo-fmt rewrites every .mise/config*.toml in full, and so does this task. # fmt:rust runs its dependencies as parallel siblings, so with no ordering edge between the two the second @@ -1343,7 +1393,7 @@ alias = "toml-check" # rule alone). We work around it by applying each schema explicitly with `taplo lint --schema file://...`. # conftest-check-toml (config/conftest/policy) intentionally duplicates these lints; running both is fine. run = """ -taplo lint +{{ vars.toml_files }} | xargs -0 taplo lint # The --schema lints need a file:// URL, built cross-platform as file:///${PWD#/}. # taplo rejects a bare path. On Linux $PWD is /abs, so the form yields file:///abs; on Windows $PWD is C:/dir @@ -1497,14 +1547,25 @@ mise trust "$out/mise.toml" >/dev/null # gitignored, so nothing downstream depends on it surviving. coreutils rm -f "$out/mise.lock" -# The npm registry config is exported here rather than left to the deployment's own `[env]`. +# The npm registry config is exported here, for every mise call below, rather than left to the deployment's `[env]`. # mise computes that entry but does not apply it to its own tool resolution, so the embedded npm client reads # no `NPM_CONFIG_USERCONFIG`, falls back to registry.npmjs.org, and answers `package not found` for a scoped # package that only GitHub Packages holds. Exported into the process, the same file resolves against # npm.pkg.github.com and installs. Measured both ways on one cold cache: the deployment's `[env]` alone # fetched https://registry.npmjs.org/@edge-toolkit%2Fet-ws-math1 and installed nothing. -npmrc="$PWD/$out/npmrc" -(cd "$out" && NPM_CONFIG_USERCONFIG="$npmrc" mise install) +export NPM_CONFIG_USERCONFIG="$PWD/$out/npmrc" +(cd "$out" && mise install) +# `mise lock` after the install records each npm module's dependency graph, which the install alone leaves out. +# mise files an npm install under a directory named for that graph (`~aube~`), but a fresh +# `mise install` writes the module's lock entry with no graph, and `mise ls --current` then names the bare +# `` directory that was never created. The hub finds its modules through that listing, so it served +# nothing and each runner's request for its module's `package.json` was a 404. Reproduced with any `latest` npm tool +# on the mise `min_version` names and on its next release: the install lands in `~aube~` while the +# listing names ``, until `mise lock` adds the graph. Seen as +# `GET /modules/@edge-toolkit/et-ws-math1/package.json` 404s at +# https://github.com/edge-toolkit/core/commit/b19fbf4790a38c77000dd888d513ff27b0f35d16, job +# https://github.com/edge-toolkit/core/actions/runs/36968983438/job/110718777886. +(cd "$out" && mise lock) (cd "$out" && mise run generated-scenario) & scenario_pid=$! @@ -1525,6 +1586,20 @@ done if [ -z "$stored" ]; then echo "published-verify: no math1-output.json appeared under $storage" >&2 echo "published-verify: check whether the crates and module packages this scenario names are published yet" >&2 + # Print where the hub was told each module is installed, beside what is actually there. + # The hub serves each npm module from the install path `mise ls --current --json` names, and is silent when that + # path is missing, so a module it never found shows up only as a runner's 404 -- this makes a listing that names a + # directory the install never created visible. + listing=$(cd "$out" && mise ls --current --json) || listing="{}" + printf '%s' "$listing" | + jaq -r 'to_entries[] | select(.key | startswith("npm:@edge-toolkit/")) | "\\(.key) \\(.value[0].install_path)"' | + while read -r tool path; do + echo "published-verify: $tool is listed at $path" >&2 + coreutils ls -la "$(coreutils dirname "$path")" >&2 || true + done + # A module whose lock entry has no `aube` graph is listed at the bare version, so show which entries carry one. + echo "published-verify: aube graphs recorded in $out/mise.lock:" >&2 + rg -n -A6 '^\\[\\[tools\\."npm:@edge-toolkit/' "$out/mise.lock" >&2 || true exit 1 fi @@ -1619,8 +1694,10 @@ kubectl rollout status deploy/ws-server -n "$ns" --timeout="$manifest_wait" # concatenated JSON documents rather than one. The sibling mise and compose test reads the first match for the # same reason. stored="" -# The glob and `$1` are for the pod's shell to expand, so they must reach it unexpanded. +# The glob, `$1` and the `cat` are all for the pod's shell, so they must reach it unexpanded. +# That shell runs in the hub image, where no mise-managed coreutils exists. # shellcheck disable=SC2016 +# nosemgrep: config.semgrep.mise-task-coreutils-prefix read_model='set -- /app/storage/*/math1-output.json; cat "$1"' for _ in $(coreutils seq 1 60); do stored=$(kubectl exec -n "$ns" deploy/ws-server -- sh -c "$read_model" 2>/dev/null || true) @@ -1725,7 +1802,7 @@ mise install gh mise install cargo-binstall mise install node mise install conda:openssl -mise install coreutils +mise install github:uutils/coreutils mise install ripgrep # goawk lands here in _setup_all so it's available to every later step. # Steps that may need `awk` -- third-party scripts (dotnet-install.sh on Linux, others) hard-code bare @@ -1836,7 +1913,7 @@ run = ''' echo "# like .gitignore. Edit .gitignore and regenerate." echo { - cat .gitignore + coreutils cat .gitignore printf '%s\n' '.git/' 'Dockerfile*' '/README.md' } | goawk ' /^[[:space:]]*#/ { print; next } @@ -1957,32 +2034,27 @@ depends = ["regenerate-verification"] description = "Fail if generated scenario output files are stale" run = "git diff --exit-code -- verification/" -# HELP.md for each clap-using utility under utilities/. -# Each crate has an optional `markdown-help` feature that gates a hidden `--markdown-help` flag; -# `cargo run --features markdown-help -p -- --markdown-help` prints a full clap-tree markdown -# rendering. gen-help-all regenerates every HELP.md; gen-help-check diffs the committed files against -# fresh output. The pattern mirrors pep257-rs's HELP.md flow. It must run after regenerate-verification -# as they use different features, and they can race, invoking the wrong binary, without the required -# feature. [tasks.gen-help-all] -depends = ["cargo-check", "cargo-clippy-check", "cargo-doc-check", "regenerate-verification"] description = "Regenerate HELP.md for every clap-using utility under utilities/" -run = """ -s=target/scratch/gen-help -mkdir -p "$s" -for crate in et-cli et-int-gen et-onnx; do - helpmd="utilities/${crate#et-}/HELP.md" - echo "[gen-help-all] $crate -> $helpmd" - cargo run --features markdown-help -q -p "$crate" -- --markdown-help | dprint fmt --stdin md >"$s/$crate.md" - coreutils mv "$s/$crate.md" "$helpmd" -done -""" -shell = "{{ vars.task_shell }}" +run = "cargo run -q -p et-int-gen --bin et-int-gen -- help-md" + +[tasks."gen:checks"] +description = "Regenerate CHECKS.md, the catalogue of every check across every MISE_ENV" +run = "cargo run -q -p et-int-gen --bin et-int-gen -- checks" + +[tasks.checks-md-check] +# Ordered after the workspace builds so its `cargo run` reuses their artifacts. +# Run beside them it is a fourth concurrent build, which doubled every cargo task's time on the three-core macOS +# runner and took the macOS check lane past its budget. +depends = ["cargo-check", "cargo-clippy-check", "cargo-doc-check", "regenerate-verification"] +description = "Fail if CHECKS.md is stale vs the mise task tables and rule files (run `mise run gen:checks`)" +run = "cargo run -q -p et-int-gen --bin et-int-gen -- checks --check" [tasks.gen-help-check] -depends = ["gen-help-all"] -description = "Fail if any utility's checked-in HELP.md is stale vs the clap tree" -run = "git diff --exit-code -- utilities/*/HELP.md" +# After checks-md-check, whose et-int-gen build it reuses. +depends = ["checks-md-check"] +description = "Fail if any utility's checked-in HELP.md is stale vs the clap tree (run `mise run gen-help-all`)" +run = "cargo run -q -p et-int-gen --bin et-int-gen -- help-md --check" [tasks.fetch-wit-deps] description = "Fetch upstream WASI WIT packages into generated/specs/wit/ at pinned versions (run by hand on bumps)" @@ -2122,7 +2194,7 @@ shell = "{{ vars.task_shell }}" # https://github.com/edge-toolkit/core/actions/runs/31773896309/job/94685231006. [tasks._setup-store-tools] description = "Install the tools the mise-tools store tasks depend on (cold-checkout helper)" -run = "mise install coreutils crane gh aqua:01mf02/jaq" +run = "mise install github:uutils/coreutils crane gh aqua:01mf02/jaq" # Build the OCI layout for a mise-tools store, carrying only relocatable tools. # Shared by every push-mise-tools* task (native and docker) so all platforms' stores hold the same set of @@ -2417,9 +2489,9 @@ otelcol-contrib --config config/otelcol-winperf.yaml shell = "{{ vars.task_shell }}" # Note: bare `yq` / `coreutils` would fail inside the nanoserver docker build. -# There mise's shims aren't on PATH for busybox-w32 ash (see the CLAUDE.md "Nano Server exception"). +# There mise's shims aren't on PATH for busybox-w32 ash (see the AGENTS.md "Nano Server exception"). # `mise exec --` is the documented escape hatch; works the same on every host. yq stays bare because it -# already runs cleanly on every other lane and the nanoserver-shim TODO (CLAUDE.md) plans to put all +# already runs cleanly on every other lane and the nanoserver-shim TODO (AGENTS.md) plans to put all # shims on PATH there too. [tasks.fetch-face1-rclone] run = """ diff --git a/.mise/config.windows.toml b/.mise/config.windows.toml index 6ed05641..105fb092 100644 --- a/.mise/config.windows.toml +++ b/.mise/config.windows.toml @@ -124,7 +124,8 @@ a_mise_installs_fwd = '''{% if env?.MISE_INSTALLS_DIR -%} {{- env.MISE_INSTALLS_DIR | replace(from="\\", to="/") -}} {%- else -%} {{- (env?.LOCALAPPDATA or "") | replace(from="\\", to="/") -}}/mise/installs -{%- endif %}''' +{%- endif -%} +''' # clang-tidy's builtin-header resource dir (config.linux.toml solves the same gap with conda's clang). # llvm-mingw ships the clang resource headers (stddef.h/stdint.h -- everything the zig-data1 C needs), # and conda's clang-tidy is the same LLVM 22 major. The trailing `22` is clang's major version, not the @@ -149,7 +150,8 @@ mise_installs = '''{% if env?.MISE_INSTALLS_DIR -%} {{- env.MISE_INSTALLS_DIR -}} {%- else -%} {{- env?.LOCALAPPDATA or "" -}}\mise\installs -{%- endif %}''' +{%- endif -%} +''' # busybox `ash` install path for MISE_BASH_PATH. # Keyed by the pinned http:busybox version above -- keep in sync. winsh = '{{ vars.mise_installs }}\http-busybox\1.37.0\ash.exe' @@ -188,7 +190,8 @@ cargo_bin = '''{% if env?.CARGO_HOME -%} {{- env.CARGO_HOME -}}\bin {%- else -%} {{- env?.USERPROFILE or "" -}}\.cargo\bin -{%- endif %}''' +{%- endif -%} +''' # Pinned to the [tools] version so the [env] _.path entry resolves; bump both together. m2_gnupg_bin = '{{ vars.mise_installs }}\conda-m2-gnupg\2.2.41.1\Library\usr\bin' # msys2's make.exe dir, on the same terms as m2_gnupg_bin above. diff --git a/.mise/mise.coverage.lock b/.mise/mise.coverage.lock index e2cfa5cb..ae36e19d 100644 --- a/.mise/mise.coverage.lock +++ b/.mise/mise.coverage.lock @@ -12,93 +12,97 @@ checksum = "sha256:548d128bc257badd2d9dbdff8173eb693fcbec84ceeb0fa74cbfed141ed42 url = "https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_102.conda" checksum = "sha256:eebe159bf600943552e4319ff4ce27b6a2dadf0dcc5443e76dcee9259a408e11" -[conda-packages.linux-arm64."clang-22-22.1.7-default_h2a92e99_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-22-22.1.7-default_h2a92e99_1.conda" -checksum = "sha256:9e7c0ada4d29cce433d2a006f80521000a2112049b005bbd8078483324aa0823" +[conda-packages.linux-arm64."clang-23-23.1.2-default_h473506b_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-23-23.1.2-default_h473506b_0.conda" +checksum = "sha256:408ffc3dec7d6ac5ef17a11fdb925a94f178f9d0414c4412884c6394b1a89ab1" -[conda-packages.linux-arm64."clang_impl_linux-aarch64-22.1.7-default_h1168dbd_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang_impl_linux-aarch64-22.1.7-default_h1168dbd_1.conda" -checksum = "sha256:4e8522e436ee8c7238e553701ce0d11b07b96e9448c1ca9a95c590e791c63260" +[conda-packages.linux-arm64."clang_impl_linux-aarch64-23.1.2-default_hb71c922_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang_impl_linux-aarch64-23.1.2-default_hb71c922_0.conda" +checksum = "sha256:fd4dcb2b8f1098faf65dd2a78fff0b06bd3e732363232a2c1daff476a11ca40b" -[conda-packages.linux-arm64."compiler-rt-22.1.7-h8af1aa0_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt-22.1.7-h8af1aa0_0.conda" -checksum = "sha256:73e562aaf4d28cc20016fd2dcddeedbbd6a471a2c93066921aebcf56211e91a5" +[conda-packages.linux-arm64."compiler-rt-23.1.2-h8af1aa0_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt-23.1.2-h8af1aa0_0.conda" +checksum = "sha256:7919c447020a962c20e5350e578469db002748fad3069cc59cfb2e1da9dc6555" -[conda-packages.linux-arm64."compiler-rt22-22.1.7-hfefdfc9_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt22-22.1.7-hfefdfc9_0.conda" -checksum = "sha256:89dc80694e4b8f89329b99c09528db8a11a8193fcf128e3616a9dd7bb0d9f5af" +[conda-packages.linux-arm64."compiler-rt23-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt23-23.1.2-hde6636f_0.conda" +checksum = "sha256:3219dd61acef3620ff7ceaa490ef4576e88401b48aee68d57dc225ffb1fe0470" -[conda-packages.linux-arm64."compiler-rt22_linux-aarch64-22.1.7-hfefdfc9_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_linux-aarch64-22.1.7-hfefdfc9_0.conda" -checksum = "sha256:324fb1c2f8832337e14b5b69af566d97de2535a9de7ca0dcabd0850aee5c2583" +[conda-packages.linux-arm64."compiler-rt23_linux-aarch64-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-aarch64-23.1.2-hde6636f_0.conda" +checksum = "sha256:95cae6c25dcd67d76a909841859ba95ebf7c51087d84be6e8c962ba372756c47" -[conda-packages.linux-arm64."compiler-rt_linux-aarch64-22.1.7-h8af1aa0_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-aarch64-22.1.7-h8af1aa0_0.conda" -checksum = "sha256:9b7edee12b8df41ca8edb25822208ad16a1045d7cb80812e16f69d131665f203" +[conda-packages.linux-arm64."compiler-rt_linux-aarch64-23.1.2-h8af1aa0_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-aarch64-23.1.2-h8af1aa0_0.conda" +checksum = "sha256:0a8f2f4993e5566bbba883db2f51f5f0a5c750fe2ae42cd1177582efe7b4544d" -[conda-packages.linux-arm64."kernel-headers_linux-aarch64-6.12.0-h05a177a_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-6.12.0-h05a177a_6.conda" -checksum = "sha256:2251f81ccc1d3bb38873cbcdcf43c15f424a057714a7c7a4756e3c68440ad0e9" +[conda-packages.linux-arm64."icu-78.3-py311h3512406_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda" +checksum = "sha256:54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e" + +[conda-packages.linux-arm64."kernel-headers_linux-aarch64-4.18.0-h05a177a_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda" +checksum = "sha256:5d224bf4df9bac24e69de41897c53756108c5271a0e5d2d2f66fd4e2fbc1d84b" [conda-packages.linux-arm64."ld_impl_linux-aarch64-2.46.1-default_h1979696_102"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda" checksum = "sha256:2c4901f4227b0850328ed0c69f958b30ad2cd18982f7a31c7c1f911827004d08" -[conda-packages.linux-arm64."libclang-cpp22.1-22.1.7-default_h2a92e99_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.7-default_h2a92e99_1.conda" -checksum = "sha256:ff9e0d7dbe8abc4192cdbeb8f6339084250937fc68693ad4875782768aa5974b" +[conda-packages.linux-arm64."libclang-cpp23.1-23.1.2-default_h01b09c7_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp23.1-23.1.2-default_h01b09c7_0.conda" +checksum = "sha256:9b0ced8d10de3dd1cc8271779dd1603b6168ee2384b0fa79ac7743a1ea0ae47c" -[conda-packages.linux-arm64."libcompiler-rt-22.1.7-hfefdfc9_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libcompiler-rt-22.1.7-hfefdfc9_0.conda" -checksum = "sha256:18c469676375208f447efdf3cfd424193da2f252ffe6abf779cfe4f97867abf6" +[conda-packages.linux-arm64."libcompiler-rt-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libcompiler-rt-23.1.2-hde6636f_0.conda" +checksum = "sha256:bb301a736fcd1a018ee4865c37b407d820b90ac27dc0fbc33fee2dc7b047e8ae" -[conda-packages.linux-arm64."libgcc-16.1.0-h205dda4_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.1.0-h205dda4_1.conda" -checksum = "sha256:88a3d400c678df034c9d498f32503779977d5ea826063687c663e42c945abed5" +[conda-packages.linux-arm64."libgcc-16.2.0-h205dda4_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda" +checksum = "sha256:eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1" -[conda-packages.linux-arm64."libgcc-devel_linux-aarch64-16.1.0-hd673532_101"] -url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-16.1.0-hd673532_101.conda" -checksum = "sha256:885f0d8a47f7ea50d7b33d07a240f2301935602b9d2a39a35b5018b13e934100" +[conda-packages.linux-arm64."libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107"] +url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107.conda" +checksum = "sha256:3a0fc46d9ffe0bc98e825bfcc0409564435e74ae0ac094b484a89a296ed777ee" -[conda-packages.linux-arm64."libgomp-16.1.0-h8acb6b2_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.1.0-h8acb6b2_1.conda" -checksum = "sha256:1c609a4a72597350317b92c4d9dfb85d21740219048e2b1d458925a6ccfa3d7a" +[conda-packages.linux-arm64."libgomp-16.2.0-h8acb6b2_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda" +checksum = "sha256:4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494" -[conda-packages.linux-arm64."libiconv-1.18-h90929bb_2"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda" -checksum = "sha256:1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9" +[conda-packages.linux-arm64."libiconv-1.18-h1ea5142_3"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h1ea5142_3.conda" +checksum = "sha256:d22c666eb887afd2119aac2110e23a0e817e9391bda99293421f7c46dab1564c" -[conda-packages.linux-arm64."libllvm22-22.1.8-hfd2ba90_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda" -checksum = "sha256:dc943f1730a27f5fb36682c9852f7196f671c3a9df4a0a7a8f7ba665637c9151" +[conda-packages.linux-arm64."libllvm23-23.1.2-h680871c_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm23-23.1.2-h680871c_0.conda" +checksum = "sha256:9b7820c041aeebea33d738a917c185ae554b6b89e2491e83e64f9a2fe675f88c" [conda-packages.linux-arm64."liblzma-5.8.3-he30d5cf_1"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda" checksum = "sha256:f760669fd1cea27f689f411c0d5488e26ce50e382c9b63e4ad348f959850124a" -[conda-packages.linux-arm64."libstdcxx-16.1.0-hef695bb_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.1.0-hef695bb_1.conda" -checksum = "sha256:81ef9a10a0e01ffc7e03d429ed048410153411b2d8bbf95c334bdf3dcf175ab0" +[conda-packages.linux-arm64."libstdcxx-16.2.0-hef695bb_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda" +checksum = "sha256:b241a3acfa9cdb1359112864a1241225533c92642de3000d52ae65ef5d3a9786" -[conda-packages.linux-arm64."libxml2-16-2.15.3-h064b767_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.3-h064b767_0.conda" -checksum = "sha256:96e9bd642c013ce3407c23b3819204ea8a591567d62b49baa4bafb2f1487326c" +[conda-packages.linux-arm64."libxml2-16-2.15.4-h2e5089f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.4-h2e5089f_0.conda" +checksum = "sha256:58bf7fcf64bae7f624a5e2aed860ddea614a8ec13c8c43fe150420a275b8bdb5" -[conda-packages.linux-arm64."libxml2-2.15.3-h9ba8346_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.3-h9ba8346_0.conda" -checksum = "sha256:74aa3c62e0ec4491343b95ce4ca8812ad2f9bb015369e29cb3b4b9b4302d8cb0" +[conda-packages.linux-arm64."libxml2-2.15.4-h92b9305_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.4-h92b9305_0.conda" +checksum = "sha256:3345c88fa9ebb373bcf4069ede898950005fa2d1707e56a13a1ac6339919492f" [conda-packages.linux-arm64."libzlib-1.3.2-hdc9db2a_3"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda" checksum = "sha256:76efa6cc9d7e6f5ee3bbca0939f64054af2bdfb3c3632531f8e633cf6c2ea41e" -[conda-packages.linux-arm64."llvm-openmp-22.1.8-he40846f_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/llvm-openmp-22.1.8-he40846f_0.conda" -checksum = "sha256:30bbb0ce4ae7cebbeb9801af5bbd2a29f8627237a38d08fc5d8d800e79c817aa" +[conda-packages.linux-arm64."llvm-openmp-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/llvm-openmp-23.1.2-hde6636f_0.conda" +checksum = "sha256:75a5cba29fd370cf20c6922587bbf4034858e2a46815b2cc45144f009b596df7" -[conda-packages.linux-arm64."sysroot_linux-aarch64-2.39-h934ec21_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.39-h934ec21_6.conda" -checksum = "sha256:bf817fbdb9953dda8f4b0d3c5bdf23a072c6baf6d39cb80e067f274a9d6feaf2" +[conda-packages.linux-arm64."sysroot_linux-aarch64-2.28-h585391f_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda" +checksum = "sha256:1bd2db6b2e451247bab103e4a0128cf6c7595dd72cb26d70f7fadd9edd1d1bc3" [conda-packages.linux-arm64.tzdata-2026c-h151e31d_0] url = "https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda" @@ -120,97 +124,93 @@ checksum = "sha256:659c367ef49df7741749a2ad240b007d7df51b4f210505a78543deafb001e url = "https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.46.1-default_hfdba357_102.conda" checksum = "sha256:fb7bf36984a37ce7e4714d1d1da0bd0e3bfc679520f5cdc184afc676fd4b5da2" -[conda-packages.linux-x64."clang-22-22.1.7-default_h99862b1_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-22-22.1.7-default_h99862b1_1.conda" -checksum = "sha256:38c0c7bae81c823ae6415efb148bb725649daa21d8ec86ad68edf96515752ea5" - -[conda-packages.linux-x64."clang_impl_linux-64-22.1.7-default_h0a60c25_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-22.1.7-default_h0a60c25_1.conda" -checksum = "sha256:a21fa9532a6a5b6b71344ded3254e22d05e30089e674b690636de20a0a31b86e" +[conda-packages.linux-x64."clang-23-23.1.2-default_hfab3205_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-23-23.1.2-default_hfab3205_0.conda" +checksum = "sha256:86a6c2e8d77a1c07905623c4decaa2304a27a55ea7fa39a2ce338f911104f799" -[conda-packages.linux-x64."compiler-rt-22.1.7-ha770c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-22.1.7-ha770c72_0.conda" -checksum = "sha256:5c3fd5b891f1899dd2850f6df69a9796728e0dcc0491106bd34bc8309c743159" +[conda-packages.linux-x64."clang_impl_linux-64-23.1.2-default_he0f7a93_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-23.1.2-default_he0f7a93_0.conda" +checksum = "sha256:c88b4669209d93a93738ba7a1c59518a2cbefd9498dbfc873e9f5ce2fbc7991a" -[conda-packages.linux-x64."compiler-rt22-22.1.7-hb700be7_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt22-22.1.7-hb700be7_0.conda" -checksum = "sha256:69dcd7ebbda0395092a250f7a6a6849e136ef83e50fb011b7bccbaff8387ab18" +[conda-packages.linux-x64."compiler-rt-23.1.2-ha770c72_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-23.1.2-ha770c72_0.conda" +checksum = "sha256:11b5fcbfdc088c370c5120ac758593905aca71ac2b511912fc60d9e6595bb709" -[conda-packages.linux-x64."compiler-rt22_linux-64-22.1.7-hffcefe0_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_linux-64-22.1.7-hffcefe0_0.conda" -checksum = "sha256:0184dc333e3dc0c1973f6d354015cd3533625571bf2ad97dfa287a18a1ac2945" +[conda-packages.linux-x64."compiler-rt23-23.1.2-h7148c6a_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt23-23.1.2-h7148c6a_0.conda" +checksum = "sha256:3b59755649409e7d61a92233ba1be11880c1d7071796ef8713f4f8be2f3aa645" -[conda-packages.linux-x64."compiler-rt_linux-64-22.1.7-ha770c72_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-22.1.7-ha770c72_0.conda" -checksum = "sha256:e86ef4ebeafa37917cc2a8d63381dfb397a285d9c4aa61a8da21d2812c2f805f" +[conda-packages.linux-x64."compiler-rt23_linux-64-23.1.2-h0e38de2_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-64-23.1.2-h0e38de2_0.conda" +checksum = "sha256:8ab3d19a6d833a9d98a559d40a2e9f07eea353d5501c2610417f53102391bf8c" -[conda-packages.linux-x64."icu-78.3-py310h44b86e0_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda" -checksum = "sha256:9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432" +[conda-packages.linux-x64."compiler-rt_linux-64-23.1.2-ha770c72_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-23.1.2-ha770c72_0.conda" +checksum = "sha256:1365a5fff5c9463b09586ed4cd0b03864083fde070bbbe5320d4ddf70d648ebe" -[conda-packages.linux-x64."kernel-headers_linux-64-6.12.0-he073ed8_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-6.12.0-he073ed8_6.conda" -checksum = "sha256:73b11f31db6c9ebe63d900334fa4f46859aa1ddd8f37cfa5f25a043e0a59253c" +[conda-packages.linux-x64."kernel-headers_linux-64-4.18.0-he073ed8_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda" +checksum = "sha256:41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a" [conda-packages.linux-x64."ld_impl_linux-64-2.46.1-default_hbd61a6d_102"] url = "https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda" checksum = "sha256:27d83f1188cd19bcb7754a078b3fa7f4cfb8527f8eb2fde54dd01fc529d1adec" -[conda-packages.linux-x64."libclang-cpp22.1-22.1.7-default_h99862b1_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.7-default_h99862b1_1.conda" -checksum = "sha256:e638accaebe12402ce1c80ac2ba04be8114bbaa71d4012fbe8f2661fa76ea841" +[conda-packages.linux-x64."libclang-cpp23.1-23.1.2-default_h0acdd01_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp23.1-23.1.2-default_h0acdd01_0.conda" +checksum = "sha256:49156155d4f0ab4f479bc96d24db2c48c0b6bdb5659135c194f03c289ae2c523" -[conda-packages.linux-x64."libcompiler-rt-22.1.7-hb700be7_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-22.1.7-hb700be7_0.conda" -checksum = "sha256:0a88373df59c14af4b28d517362d499b635ff4c3fafda489909e27fb0cbe359c" +[conda-packages.linux-x64."libcompiler-rt-23.1.2-h7148c6a_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-23.1.2-h7148c6a_0.conda" +checksum = "sha256:2b0e6b377b1a429db6a86cad50a07e856a2c6ef748d740a3d59722677376eefd" -[conda-packages.linux-x64."libgcc-16.1.0-ha9f2e26_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda" -checksum = "sha256:d5cb8475131c31680f8fd30512c418f373064e272e452063276a8fb14c9fa42f" +[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda" +checksum = "sha256:e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea" -[conda-packages.linux-x64."libgcc-devel_linux-64-16.1.0-h59071f9_101"] -url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.1.0-h59071f9_101.conda" -checksum = "sha256:b314251d957b16c71ec241119ac09b9530c5c4ce140026ec98d297f55d6c5e08" +[conda-packages.linux-x64."libgcc-devel_linux-64-16.2.0-he3ce08f_107"] +url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.2.0-he3ce08f_107.conda" +checksum = "sha256:f1e7465f6b53f89b325e441c30ad7b19407b051eca556b6d0386ec05513b8e76" -[conda-packages.linux-x64."libgomp-16.1.0-he0feb66_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda" -checksum = "sha256:62cb599ad0539d99386515326d9d5e8f51f75a60c69c2131b21df76edf35bd89" +[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda" +checksum = "sha256:92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758" -[conda-packages.linux-x64."libiconv-1.18-h3b78370_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda" -checksum = "sha256:c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f" +[conda-packages.linux-x64."libiconv-1.18-h0cb94f2_3"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda" +checksum = "sha256:f943117edb9cd4d9c61cc972eee5a34291dc55ea7a6e9e38da104995841cbcb6" -[conda-packages.linux-x64."libllvm22-22.1.8-hf7376ad_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda" -checksum = "sha256:e9b5f301d6b001a9b8ce782157f56b75c92c4fbc9eba95dc6345c1139251d13b" +[conda-packages.linux-x64."libllvm23-23.1.2-h474f4eb_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm23-23.1.2-h474f4eb_0.conda" +checksum = "sha256:253a11a58756a3584c72c625752fb6ccf0a8885815f3e911f05731cfc24ea0ed" [conda-packages.linux-x64."liblzma-5.8.3-hb03c661_1"] url = "https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda" checksum = "sha256:9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab" -[conda-packages.linux-x64."libstdcxx-16.1.0-h934c35e_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.1.0-h934c35e_1.conda" -checksum = "sha256:79721dd08aeb0ab9e773f1f9ef41cf4e6c17477e3d72319147619045bce05a09" +[conda-packages.linux-x64."libstdcxx-16.2.0-h934c35e_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda" +checksum = "sha256:fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745" -[conda-packages.linux-x64."libxml2-16-2.15.3-hca6bf5a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_0.conda" -checksum = "sha256:3d44f737c5ae52d5af32682cc1530df433f401f8e58a7533926536244127572a" +[conda-packages.linux-x64."libxml2-16-2.15.4-hbdfff7e_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hbdfff7e_0.conda" +checksum = "sha256:b6f96287c408269f5067bb4f7a61693ff5c856152902362964d9807152b9c146" -[conda-packages.linux-x64."libxml2-2.15.3-h49c6c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_0.conda" -checksum = "sha256:3bc5551720c58591f6ea1146f7d1539c734ed1c40e7b9f5cb8cb7e900c509aba" +[conda-packages.linux-x64."libxml2-2.15.4-ha7a5771_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-ha7a5771_0.conda" +checksum = "sha256:db52c038430a508656530fc7b5650ae3e2629875693a6a256cc48dec203f8bfe" [conda-packages.linux-x64."libzlib-1.3.2-h25fd6f3_3"] url = "https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda" checksum = "sha256:eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc736" -[conda-packages.linux-x64."llvm-openmp-22.1.8-h4922eb0_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda" -checksum = "sha256:a37aba21b85800af1e7c5b04ba76abab96b6e591eedf99dc6e4df83b0fefd7a5" +[conda-packages.linux-x64."llvm-openmp-23.1.2-h7148c6a_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-23.1.2-h7148c6a_0.conda" +checksum = "sha256:292606e3a17fcf98db940d3ee6e723f84f4c6fb0104a6a69cd95043a7794eef0" -[conda-packages.linux-x64."sysroot_linux-64-2.39-hc4b9eeb_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.39-hc4b9eeb_6.conda" -checksum = "sha256:7d235e4337f122f3439d0196e1c1c6e715a5b88fcbf24f944510186c84168e45" +[conda-packages.linux-x64."sysroot_linux-64-2.28-h4ee821c_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda" +checksum = "sha256:c47299fe37aebb0fcf674b3be588e67e4afb86225be4b0d452c7eb75c086b851" [conda-packages.linux-x64.tzdata-2026c-h151e31d_0] url = "https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda" @@ -224,65 +224,69 @@ checksum = "sha256:47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fb url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" checksum = "sha256:0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6" -[conda-packages.macos-arm64."cctools-1030.6.3-llvm22_1_hbe26303_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm22_1_hbe26303_4.conda" -checksum = "sha256:a8d8f9a6ae4c149d2174f8f52c61da079cc793b87e2f76441a43daf7f394631f" +[conda-packages.macos-arm64."cctools-1030.6.3-llvm23_1_h54b4f4b_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm23_1_h54b4f4b_6.conda" +checksum = "sha256:5d3b24d769c70de6a8d2169936b50794008b8a8aacced77e954f694c2b37343e" -[conda-packages.macos-arm64."cctools_impl_osx-arm64-1030.6.3-llvm22_1_hb5e89dc_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm22_1_hb5e89dc_4.conda" -checksum = "sha256:97075a1afeac8a7a4dca258ac10efb70638e3c734cbf5a6328ca1e0718e09c41" +[conda-packages.macos-arm64."cctools_impl_osx-arm64-1030.6.3-llvm23_1_hf5e010b_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm23_1_hf5e010b_6.conda" +checksum = "sha256:e917665c2f89249598c12562c81b6536e40ac30563b2bfbe1f4a9f506bffc967" -[conda-packages.macos-arm64."clang-22-22.1.7-default_hd632d02_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-22-22.1.7-default_hd632d02_1.conda" -checksum = "sha256:3a438c7a27c86ef14a41c991b8688ef53efe92ad1db8ae930f27fce410ca843a" +[conda-packages.macos-arm64."clang-23-23.1.2-default_h8f9c3af_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-23-23.1.2-default_h8f9c3af_0.conda" +checksum = "sha256:b48232891a6df9c7f0e05a058a660ecf830e3bd11a3e3640d2b452ffb25414b9" -[conda-packages.macos-arm64."clang_impl_osx-arm64-22.1.7-default_h17d1ed9_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-22.1.7-default_h17d1ed9_1.conda" -checksum = "sha256:09a6fa56849653389f4db79e548832dda874fa9255740a292adec0941a6b8902" +[conda-packages.macos-arm64."clang_impl_osx-arm64-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:d814ce43960d9e1144e50162c25a3610dddc8ae2963375d6f0ab7dcccaaa57d8" -[conda-packages.macos-arm64."compiler-rt-22.1.7-hce30654_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-22.1.7-hce30654_0.conda" -checksum = "sha256:721b702d79bf70de4e938e552dbae794ff60590ceb4594bd5dadcaf77fa90c8b" +[conda-packages.macos-arm64."compiler-rt-23.1.2-hce30654_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-23.1.2-hce30654_0.conda" +checksum = "sha256:7a5a154f6794e35fc4e2b53d997b262f1c1949e5b983fbbf724587467adef20b" -[conda-packages.macos-arm64."compiler-rt22-22.1.7-hd34ed20_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt22-22.1.7-hd34ed20_0.conda" -checksum = "sha256:cfe6a196223f735b49b093586359615e059d9944b3cf049101a20ce135a94300" +[conda-packages.macos-arm64."compiler-rt23-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt23-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:7791feae7141a9d807e2d000677a1f027dfee206898dcebfc985ae933102a1d3" -[conda-packages.macos-arm64."compiler-rt22_osx-arm64-22.1.7-h7e67a1e_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_osx-arm64-22.1.7-h7e67a1e_0.conda" -checksum = "sha256:f3d32eba79cd7815b20277c5a0dc0b265d7f5ca0eabad9daa6fd68be87fb8af7" +[conda-packages.macos-arm64."compiler-rt23_osx-arm64-23.1.2-hb8825d9_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_osx-arm64-23.1.2-hb8825d9_0.conda" +checksum = "sha256:a3f20ea42e1c99dfb4188c39c464d709280b7dfde181f5d8bc949ced6806fc5e" -[conda-packages.macos-arm64."compiler-rt_osx-arm64-22.1.7-hce30654_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-22.1.7-hce30654_0.conda" -checksum = "sha256:fc9f7f6322088f2efc014dac83219cd00e42583dc6502c7314c98183b6554c3d" +[conda-packages.macos-arm64."compiler-rt_osx-arm64-23.1.2-hce30654_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-23.1.2-hce30654_0.conda" +checksum = "sha256:164fd5db9accf2c630f9bebe2c1b4ecb411080e5b0702e6b1b485dbed7560487" -[conda-packages.macos-arm64."ld64-956.6-llvm22_1_h5b97f1b_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm22_1_h5b97f1b_4.conda" -checksum = "sha256:405f08540aedb58fa070b097143b3fe0fcb2b92e3b4aca723780e2f3d754803b" +[conda-packages.macos-arm64."icu-78.3-py310h579977c_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda" +checksum = "sha256:6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43" -[conda-packages.macos-arm64."ld64_osx-arm64-956.6-llvm22_1_h692d5aa_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm22_1_h692d5aa_4.conda" -checksum = "sha256:e4ae2ef85672c094aa3467d466f932ccdc1dda9bd4adac64f4252cc796149091" +[conda-packages.macos-arm64."ld64-956.6-llvm23_1_hd841b0c_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm23_1_hd841b0c_6.conda" +checksum = "sha256:aa34de810767f7d92721aeab004479672853f2fb9235a3e9c350db41c0c86112" -[conda-packages.macos-arm64."libclang-cpp22.1-22.1.7-default_h8e162e0_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp22.1-22.1.7-default_h8e162e0_1.conda" -checksum = "sha256:27fe54bb8da8a80793bbd9346324cfbc9609cee498b79d6ae8cbd89e09c197be" +[conda-packages.macos-arm64."ld64_osx-arm64-956.6-llvm23_1_hc8058f9_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm23_1_hc8058f9_6.conda" +checksum = "sha256:857ab8bf793d29a4d94af0c9eb536d1bb5a56ab9c4b5fb7a4100b24c35e96446" -[conda-packages.macos-arm64."libcompiler-rt-22.1.7-hd34ed20_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-22.1.7-hd34ed20_0.conda" -checksum = "sha256:35f6b1f2a1e61e043eb17aab49cccf65234d7cb137f26ed87ea7163f6937ab6b" +[conda-packages.macos-arm64."libclang-cpp23.1-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:7a176b6dda75f39184cc96b548fa436581451547bb185c610627a9b6dca05ca8" -[conda-packages.macos-arm64."libcxx-22.1.8-h55c6f16_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda" -checksum = "sha256:a2e7abab5add9750fab064c024394de48e49f97631c605ad5db5c8ac3fc769ef" +[conda-packages.macos-arm64."libcompiler-rt-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:5bce0c59f2744e16bb106126d9c0d5b976d3bc6527b13003c35e7fc88781c0ff" + +[conda-packages.macos-arm64."libcxx-23.1.2-h55c6f16_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.2-h55c6f16_0.conda" +checksum = "sha256:087a610bacee7901d259ef72c6f060d795ab26831bd7541ba75ced786a5a63f9" [conda-packages.macos-arm64."libiconv-1.18-he4c29f2_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda" checksum = "sha256:689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f" -[conda-packages.macos-arm64."libllvm22-22.1.7-h89af1be_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.7-h89af1be_0.conda" -checksum = "sha256:533929d04a94ee43431c6f7f0916b0f5a387f6b02b5339f06301bbfa9e180c84" +[conda-packages.macos-arm64."libllvm23-23.1.2-h759d1ac_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.2-h759d1ac_0.conda" +checksum = "sha256:9717b7ae514600cebeb43ea89bf008bef6e96fbbefa1dda40843c394f2b6a46e" [conda-packages.macos-arm64."liblzma-5.8.3-h8088a28_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda" @@ -292,45 +296,45 @@ checksum = "sha256:23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4 url = "https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda" checksum = "sha256:fcfa03afe31f40dfabf011629d99836adbebbc3ed1b38c7e9eee9ffc7581975b" -[conda-packages.macos-arm64."libxml2-16-2.15.3-h6967ea9_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h6967ea9_0.conda" -checksum = "sha256:43895a7517c055b8893531290f9dc48bd751eb04be04f14bbce3b6c71b052be6" +[conda-packages.macos-arm64."libxml2-16-2.15.4-heb56d2d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda" +checksum = "sha256:8a26f7c94ab849c1930da36c298f4b82e892382b70ae865cd7274188d9d783e2" -[conda-packages.macos-arm64."libxml2-2.15.3-heed7d32_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.3-heed7d32_0.conda" -checksum = "sha256:4d9c117b2dd222cf891710d5f6a570ebb275479979843a1477ac54ed50907b40" +[conda-packages.macos-arm64."libxml2-2.15.4-h550178d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda" +checksum = "sha256:81217fcd4d4abdc69ee63cdb9cdb22e05a20b9ba7a76f596579914a838fe5960" [conda-packages.macos-arm64."libzlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda" checksum = "sha256:a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef9d7" -[conda-packages.macos-arm64."llvm-openmp-22.1.8-hc7d1edf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.8-hc7d1edf_0.conda" -checksum = "sha256:ccbaad6bbc88f135ab849bc36af5fa6eda36a9ed18ce6f58e3dde3d11784c156" +[conda-packages.macos-arm64."llvm-openmp-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:f9aea67117079c00b9663ee0bbca7e5409dbe94625c34e68881ce2c97c3d47c9" -[conda-packages.macos-arm64."llvm-tools-22-22.1.7-hb545844_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22-22.1.7-hb545844_0.conda" -checksum = "sha256:fd44ba14755380db3d89b75485c2e9a9982fefe54e7853d9a91a250948b2c48c" +[conda-packages.macos-arm64."llvm-tools-23-23.1.2-h79441dc_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-23-23.1.2-h79441dc_0.conda" +checksum = "sha256:52f1824ca1de2d034764225c275928e38ca61094d8080d7407175ab06ac408e2" -[conda-packages.macos-arm64."llvm-tools-22.1.7-hd34ed20_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22.1.7-hd34ed20_0.conda" -checksum = "sha256:eafdac4500c69bed1e5964efc8f6a024a4a70f57a91e5c5e099bc9ed5ff4695b" +[conda-packages.macos-arm64."llvm-tools-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:2911fe5dad062b513f572d317fbc7ef1e94f177cac63db01bbb1d4278e707996" [conda-packages.macos-arm64."ncurses-6.6-he64c551_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda" checksum = "sha256:7024a48c8c0d0114ed4ab53c76bf9275d50e91ba7cea367a9aead638d3c29c68" -[conda-packages.macos-arm64."openssl-3.6.3-hd24854e_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda" -checksum = "sha256:66be2283b5b37dcda1332b5e74c1782a8cb14fd2e62e0d38017c2d35bf73c119" +[conda-packages.macos-arm64."openssl-3.6.4-h55eecbc_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.4-h55eecbc_0.conda" +checksum = "sha256:f23239eacd75c4c50705e68fae1aa3292da473e6a3a4abe2330f1e6afa680704" [conda-packages.macos-arm64."sigtool-codesign-0.1.3-h98dc951_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda" checksum = "sha256:7efd6d7d18bf9cc5788bfe1c1e1620d9dbbe00a81c646814929a82ff31944cf3" -[conda-packages.macos-arm64."tapi-1600.0.11.8-hb561403_3"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_3.conda" -checksum = "sha256:9f1cc109e6e57861110e9de6e03beca7fd2b7fbdb46124cccc07990b0844d88a" +[conda-packages.macos-arm64."tapi-1600.0.11.8-hb561403_4"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda" +checksum = "sha256:6effea9587f049e702c838e8e57d98ac92b89ca1f3f1edd51c78dd252d24e83b" [conda-packages.macos-arm64."zstd-1.5.7-hf451053_7"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda" @@ -340,65 +344,65 @@ checksum = "sha256:da867f5092eb0cb746d353694f0098031fd9817a4ce7d5743121209ae0f40 url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" checksum = "sha256:0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6" -[conda-packages.macos-x64."cctools-1030.6.3-llvm22_1_h0a1bb1c_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm22_1_h0a1bb1c_4.conda" -checksum = "sha256:e0b732ed52bcfa98f90fe61ef87fc47cb39222351ab2e730c05f262d29621b51" +[conda-packages.macos-x64."cctools-1030.6.3-llvm23_1_h254e556_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm23_1_h254e556_6.conda" +checksum = "sha256:386336eab60ff2cbd2dbd510c015400b7d9f6263411c0297860e508261c68ed6" -[conda-packages.macos-x64."cctools_impl_osx-64-1030.6.3-llvm22_1_h8fe25a2_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm22_1_h8fe25a2_4.conda" -checksum = "sha256:9e003c254b6c1880e6c8f2d777b20d837db2b7aff161454d857693692fd862dd" +[conda-packages.macos-x64."cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6.conda" +checksum = "sha256:318a4ce9253a4808283b35dd09e1db36e07751a1a4ce1dc00312b00ae932e3c8" -[conda-packages.macos-x64."clang-22-22.1.7-default_h3b8fe2e_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-22-22.1.7-default_h3b8fe2e_1.conda" -checksum = "sha256:8acd160b174fe02c61efd926b574d0bce11fc800ab1b8882817461f7940b2561" +[conda-packages.macos-x64."clang-23-23.1.2-default_h3065a3b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-23-23.1.2-default_h3065a3b_0.conda" +checksum = "sha256:b845ff3a9f3725face10ccf56582405fe5d4e97d4679f33bcc2892f4e4c55930" -[conda-packages.macos-x64."clang_impl_osx-64-22.1.7-default_he9bf3b8_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-22.1.7-default_he9bf3b8_1.conda" -checksum = "sha256:eacf23606165a106141ca0adae56f37b2de3f2557a8eec3554259f62e15bb3eb" +[conda-packages.macos-x64."clang_impl_osx-64-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:c55b59c17a59de3bfd0eddacf2c6179940b882a47bafbdc9d42cdab473f10584" -[conda-packages.macos-x64."compiler-rt-22.1.7-h694c41f_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-22.1.7-h694c41f_0.conda" -checksum = "sha256:057879f1f517b25a2394639fcedfc04005f6bbf63ab003182bc479e641db2b2c" +[conda-packages.macos-x64."compiler-rt-23.1.2-h694c41f_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-23.1.2-h694c41f_0.conda" +checksum = "sha256:be8fe7a2c142b10f4bb88b01f6e8b8691069c297a13ac34f14113ad7f94efaf7" -[conda-packages.macos-x64."compiler-rt22-22.1.7-h1637cdf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt22-22.1.7-h1637cdf_0.conda" -checksum = "sha256:f67af723c48fa4c789d1b3cdcde618d7479622fd410cb51f9457f0b70dc8c13d" +[conda-packages.macos-x64."compiler-rt23-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt23-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:c05f82f29f66254a3f3f391d8d73beed669e22932358065939700b070fd07de7" -[conda-packages.macos-x64."compiler-rt22_osx-64-22.1.7-hcf80936_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_osx-64-22.1.7-hcf80936_0.conda" -checksum = "sha256:87c48a861f8c06c2be4f8ad7e7b774e2c6d4891e617dc6461d9c670bae17b790" +[conda-packages.macos-x64."compiler-rt23_osx-64-23.1.2-h8d5f570_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_osx-64-23.1.2-h8d5f570_0.conda" +checksum = "sha256:a3ca596feee730ef98015a6c9d6f55749e8634c01c17e7eb2acef8b13b7af483" -[conda-packages.macos-x64."compiler-rt_osx-64-22.1.7-h694c41f_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-22.1.7-h694c41f_0.conda" -checksum = "sha256:a5118bf285946d0a04e0d5bf989b729340d72b317a6b115d6c41e8dfe959081e" +[conda-packages.macos-x64."compiler-rt_osx-64-23.1.2-h694c41f_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-23.1.2-h694c41f_0.conda" +checksum = "sha256:101d620216e883738286ffd860764cf688161bfce223495d5e9387838a279b70" -[conda-packages.macos-x64."ld64-956.6-llvm22_1_hc399b6d_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm22_1_hc399b6d_4.conda" -checksum = "sha256:a4ac125329e14d407ecb2c074412a0af6f78256989db82d83c4a02e93912c88e" +[conda-packages.macos-x64."ld64-956.6-llvm23_1_h0b736ef_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm23_1_h0b736ef_6.conda" +checksum = "sha256:11a6c36fd6207683a57d5e91533d3ce1756c1fc7e2a30504de8686ac867a8f0b" -[conda-packages.macos-x64."ld64_osx-64-956.6-llvm22_1_h163eae7_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm22_1_h163eae7_4.conda" -checksum = "sha256:e49272192003e0e30edd6877197db3c220bb374a78d5b255d18c7a029cd33c1e" +[conda-packages.macos-x64."ld64_osx-64-956.6-llvm23_1_h484b24f_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm23_1_h484b24f_6.conda" +checksum = "sha256:36c603caf2a7f65ae9f0ce4acbf7afde49357bdcea65b28ca7aefd9cf46c1f5a" -[conda-packages.macos-x64."libclang-cpp22.1-22.1.7-default_h9399c5b_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp22.1-22.1.7-default_h9399c5b_1.conda" -checksum = "sha256:f354e26f811a31427ff4cc4695a6773187bb2ac9ad9197eebf41da470e637968" +[conda-packages.macos-x64."libclang-cpp23.1-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:491c85fac38f91060802761e59e3a1505ee738ed2849504e8d0f3ecf0c520537" -[conda-packages.macos-x64."libcompiler-rt-22.1.7-h1637cdf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-22.1.7-h1637cdf_0.conda" -checksum = "sha256:d0ef06b0c7d1312e572f3726b867f81e22eed158e6255b66e58448ede7647b49" +[conda-packages.macos-x64."libcompiler-rt-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:ff0e2bc0217a46aba323edb4b61dcd29ea333ab344735a93de5f9bf140a34fa8" -[conda-packages.macos-x64."libcxx-22.1.8-h19cb2f5_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.8-h19cb2f5_0.conda" -checksum = "sha256:57ee997f1f800cf38abc743c0f0a9ddfe6a101c697c35510452ce6f4ddf96361" +[conda-packages.macos-x64."libcxx-23.1.2-h19cb2f5_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.2-h19cb2f5_0.conda" +checksum = "sha256:0ad8c788c3681674f100820cf5e76fcc8ec88502e7aa64f4776581985009a7be" [conda-packages.macos-x64."libiconv-1.18-h4ae439b_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda" checksum = "sha256:2389e03a58ed0f5e8f2469eb4d4ba80d0af378b38854ae5eee65e5b641244082" -[conda-packages.macos-x64."libllvm22-22.1.7-hab754da_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm22-22.1.7-hab754da_0.conda" -checksum = "sha256:9ef76e7c6a078cbead8a462af85cfae4f8fe2a9480ec0ee483f00332703a02ca" +[conda-packages.macos-x64."libllvm23-23.1.2-hd11396f_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.2-hd11396f_0.conda" +checksum = "sha256:f6174a6f25f900bbcebaa6461ad7152937ff5769e6dbec500a385c321e5adbc2" [conda-packages.macos-x64."liblzma-5.8.3-hbb4bfdb_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda" @@ -408,69 +412,89 @@ checksum = "sha256:7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa url = "https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda" checksum = "sha256:c3d76ff04ebed64d00a7ff5106297a55af20082a3d3df0ea7dfb235f94ba31c3" -[conda-packages.macos-x64."libxml2-16-2.15.3-h0d7f165_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h0d7f165_0.conda" -checksum = "sha256:daa69a1dd887b2dbac44327bc5af73a4d41fa63bc6dc609782fdda9aec187895" +[conda-packages.macos-x64."libxml2-16-2.15.4-h341e563_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h341e563_0.conda" +checksum = "sha256:bc284057b85e4a0ecc158598d81c3081fa58e9111969a05d3056ab7a8442c837" -[conda-packages.macos-x64."libxml2-2.15.3-h0712280_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.3-h0712280_0.conda" -checksum = "sha256:caf6e73fa53c3dec3227ea67de231b0f7009544252684e816c6f2f414aeb55c9" +[conda-packages.macos-x64."libxml2-2.15.4-h3668fe6_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-h3668fe6_0.conda" +checksum = "sha256:9cf91223637981568c8fbd5c4dbbc1e6137592e919828554ae436bf259aa91d0" [conda-packages.macos-x64."libzlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda" checksum = "sha256:b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c18e1" -[conda-packages.macos-x64."llvm-openmp-22.1.8-h0d3cbff_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.8-h0d3cbff_0.conda" -checksum = "sha256:7e8dcf03c2ef5491405d6d86eb892d14e99902f50f4eeb250db0cbdc58dd5818" +[conda-packages.macos-x64."llvm-openmp-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:3c17127e2a94d60a8babef57c66d643374c5b08c896ec5f0987a62ecfb81c8ee" -[conda-packages.macos-x64."llvm-tools-22-22.1.7-hc181bea_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-22-22.1.7-hc181bea_0.conda" -checksum = "sha256:86158dd6e99018e83c4ecd0d504511efd284d242d891723b6fc7edab1fd41b44" +[conda-packages.macos-x64."llvm-tools-23-23.1.2-h36529c3_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23-23.1.2-h36529c3_0.conda" +checksum = "sha256:5c12ec6e2f59444aa38ed1ab778ae3533a9d09b5c9c7c5e97e482dca81e9e08d" -[conda-packages.macos-x64."llvm-tools-22.1.7-h1637cdf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-22.1.7-h1637cdf_0.conda" -checksum = "sha256:432f04a68a18e487f4339d89bf8cea1054850fb92d0e3397605c219382892666" +[conda-packages.macos-x64."llvm-tools-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:bbf730a23807a089f2c2e9f1d460d03d49919291f97895b3aeb9593f6f0d6309" [conda-packages.macos-x64."ncurses-6.6-hcc0dc9a_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda" checksum = "sha256:12c1d676b9a0e8109b576672519312c5428308f3f3d7706f8717e2f536d5d9e7" -[conda-packages.macos-x64."openssl-3.6.3-hc881268_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.3-hc881268_1.conda" -checksum = "sha256:d43abd09a455847108fc821e81cf4e36dba31755263a1313b6f1b538ac218998" +[conda-packages.macos-x64."openssl-3.6.4-h332eb6d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.4-h332eb6d_0.conda" +checksum = "sha256:73d648d24f0994fd8641972848d74bd57b8d80888a64600643e3fe88a1b50545" [conda-packages.macos-x64."sigtool-codesign-0.1.3-h8c25ef7_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda" checksum = "sha256:37aac42f05e21b48a3b61b28ae624ed5a3d2acfcbaabf2cd10ef7762c4fb4c45" -[conda-packages.macos-x64."tapi-1600.0.11.8-h44950e2_3"] -url = "https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_3.conda" -checksum = "sha256:ec381e40cf1caf8496265bbf14ca0d2cb947495cd3e9069947e2fa75f7de7b3b" +[conda-packages.macos-x64."tapi-1600.0.11.8-h44950e2_4"] +url = "https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda" +checksum = "sha256:045e62838ec78ad75974552ebeeccbee5a4a843272da47c7a67e99fd9cc25d8d" [conda-packages.macos-x64."zstd-1.5.7-hbc1a06c_7"] url = "https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda" checksum = "sha256:5277886d9704a624dc9b79ac985861e1e431bdb39a57c082507ab577a138ec6c" -[conda-packages.windows-x64."clang-22-22.1.7-default_hac490eb_1"] -url = "https://conda.anaconda.org/conda-forge/win-64/clang-22-22.1.7-default_hac490eb_1.conda" -checksum = "sha256:5fb98251c0547e128ef108f1f120b3bb7ac2200139732b8b42efb71e5c664279" +[conda-packages.windows-x64."clang-23-23.1.2-default_hacd6ee9_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/clang-23-23.1.2-default_hacd6ee9_0.conda" +checksum = "sha256:656a751d20af0b1007fee20c19138deae20f9eeb8c5d0c9610df1bcf1c4cca47" + +[conda-packages.windows-x64."compiler-rt23-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/compiler-rt23-23.1.2-h49e36cd_0.conda" +checksum = "sha256:c35bfe3bf40dc8b28ae9f1c0e23e7ca1302746a03d909547c81745a38aa5d3be" + +[conda-packages.windows-x64."compiler-rt23_win-64-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_win-64-23.1.2-h49e36cd_0.conda" +checksum = "sha256:41059149e766110b8bbe792a81bfad41f259e4e554cc585f1de3d2dd3095737d" + +[conda-packages.windows-x64."icu-78.3-h5112557_2"] +url = "https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda" +checksum = "sha256:75c549b55b673e15de8785a8e5dd85bca7eb612eee0ff4dc8d7bdaa15eacbdbb" + +[conda-packages.windows-x64."libiconv-1.18-hc1393d2_3"] +url = "https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda" +checksum = "sha256:35e04e3ddac7720fc7c550a1c9f998604299d6a7bd1f3ec9b2825d825061daa2" + +[conda-packages.windows-x64."liblzma-5.8.3-hfd05255_1"] +url = "https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda" +checksum = "sha256:d36c4a1e1f80fd08e18a407e03622ff2f34dfdd022da6488ad19603dea19e6d5" -[conda-packages.windows-x64."compiler-rt22-22.1.7-h49e36cd_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/compiler-rt22-22.1.7-h49e36cd_0.conda" -checksum = "sha256:0254a8b7fed783b81eebbaafb6940e7a064289bab8aeda86672b9fb2d568af9e" +[conda-packages.windows-x64."libxml2-16-2.15.4-h3cfd58e_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda" +checksum = "sha256:9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac" -[conda-packages.windows-x64."compiler-rt22_win-64-22.1.7-h49e36cd_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_win-64-22.1.7-h49e36cd_0.conda" -checksum = "sha256:75e6dd239778206bc8690401be65ca5672b8c9fc7213decfe51733e101d985b8" +[conda-packages.windows-x64."libxml2-2.15.4-he095d88_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda" +checksum = "sha256:a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88" [conda-packages.windows-x64."libzlib-1.3.2-hfd05255_3"] url = "https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda" checksum = "sha256:0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527" -[conda-packages.windows-x64."llvm-openmp-22.1.8-h4fa8253_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.8-h4fa8253_0.conda" -checksum = "sha256:50c02902bb516eeb56680358f052be38b5bf74b40e78ea4b2a675e84957e7307" +[conda-packages.windows-x64."llvm-openmp-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda" +checksum = "sha256:8b462c021d6bf3f956749d305bd3f52deb82ae2901047c0c7061a21c3550e48f" [conda-packages.windows-x64."ucrt-10.0.26100.0-h57928b3_0"] url = "https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda" @@ -493,33 +517,33 @@ url = "https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda checksum = "sha256:ca7daae4f218a11fab82cc2857f0ea518ec3f46acec60490485347a4c22c6b3e" [[tools."aqua:boyter/scc"]] -version = "3.7.0" +version = "4.1.0" backend = "aqua:boyter/scc" [tools."aqua:boyter/scc"."platforms.linux-arm64"] -checksum = "sha256:dcb05c6e993bb2d8d2da4765ff018f2e752325dd205a41698929c55e4123575d" -url = "https://github.com/boyter/scc/releases/download/v3.7.0/scc_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/boyter/scc/releases/assets/367071880" +checksum = "sha256:6e0d2a1f8d3540ba7df185477dec40bb7340f1b214bfd303147de5cad2bd7b8b" +url = "https://github.com/boyter/scc/releases/download/v4.1.0/scc_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/boyter/scc/releases/assets/549478881" [tools."aqua:boyter/scc"."platforms.linux-x64"] -checksum = "sha256:3d9d65b00ca874c2b29151abe7e1480736f5229edc3ce8e4b2791460cdfabf5a" -url = "https://github.com/boyter/scc/releases/download/v3.7.0/scc_Linux_x86_64.tar.gz" -url_api = "https://api.github.com/repos/boyter/scc/releases/assets/367071881" +checksum = "sha256:c7328436d3027f4357d3d7853f7dc3ac2bbcb4ca08f1adad91a27c593884079b" +url = "https://github.com/boyter/scc/releases/download/v4.1.0/scc_Linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/boyter/scc/releases/assets/549478876" [tools."aqua:boyter/scc"."platforms.macos-arm64"] -checksum = "sha256:376cbae670be59ee64f398de20e0694ec434bf8a9b842642952b0ab0be5f3961" -url = "https://github.com/boyter/scc/releases/download/v3.7.0/scc_Darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/boyter/scc/releases/assets/367071904" +checksum = "sha256:7201c7aa4aace058d43308462cba72adb18f6094c08c0741727455976d0a0747" +url = "https://github.com/boyter/scc/releases/download/v4.1.0/scc_Darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/boyter/scc/releases/assets/549478883" [tools."aqua:boyter/scc"."platforms.macos-x64"] -checksum = "sha256:c3f7457856b9169ccb3c1dd14198e67f730bee065f24d9051bf52cdc2a719ecc" -url = "https://github.com/boyter/scc/releases/download/v3.7.0/scc_Darwin_x86_64.tar.gz" -url_api = "https://api.github.com/repos/boyter/scc/releases/assets/367071885" +checksum = "sha256:7f705031228add7e55edded409179a60de6b538d41f153ba2922dee95adda50d" +url = "https://github.com/boyter/scc/releases/download/v4.1.0/scc_Darwin_x86_64.tar.gz" +url_api = "https://api.github.com/repos/boyter/scc/releases/assets/549478879" [tools."aqua:boyter/scc"."platforms.windows-x64"] -checksum = "sha256:97abf9d55d4b79d3310536d576ccbdf5017aeb425780e850336120b6e67622e1" -url = "https://github.com/boyter/scc/releases/download/v3.7.0/scc_Windows_x86_64.zip" -url_api = "https://api.github.com/repos/boyter/scc/releases/assets/367071884" +checksum = "sha256:4a433984f45ff29c94eeb3af6db5b511c58f5bf74063dccedafcbf473cb8ff31" +url = "https://github.com/boyter/scc/releases/download/v4.1.0/scc_Windows_x86_64.zip" +url_api = "https://api.github.com/repos/boyter/scc/releases/assets/549478880" [[tools."aqua:hhatto/gocloc"]] version = "0.7.0" @@ -551,161 +575,167 @@ url = "https://github.com/hhatto/gocloc/releases/download/v0.7.0/gocloc_Windows_ url_api = "https://api.github.com/repos/hhatto/gocloc/releases/assets/240320597" [[tools."conda:clang"]] -version = "22.1.7" +version = "23.1.2" backend = "conda:clang" [tools."conda:clang".options] channel = "conda-forge" [tools."conda:clang"."platforms.linux-arm64"] -checksum = "sha256:e0672f305242539d1325bdd0b1b80a9efdcf1542c25b2eaa70f05a89aac7861a" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-22.1.7-default_cfg_h99ebb92_1.conda" +checksum = "sha256:a4296ee7ba32a24cda0eb766f46dfb0adb22d9f889bfd14bc835cd4e415beaf9" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-23.1.2-default_cfg_h1a548ed_0.conda" conda_deps = [ - "clang_impl_linux-aarch64-22.1.7-default_h1168dbd_1", - "clang-22-22.1.7-default_h2a92e99_1", - "compiler-rt-22.1.7-h8af1aa0_0", - "libclang-cpp22.1-22.1.7-default_h2a92e99_1", - "compiler-rt22-22.1.7-hfefdfc9_0", - "libcompiler-rt-22.1.7-hfefdfc9_0", - "compiler-rt22_linux-aarch64-22.1.7-hfefdfc9_0", - "compiler-rt_linux-aarch64-22.1.7-h8af1aa0_0", + "clang_impl_linux-aarch64-23.1.2-default_hb71c922_0", + "llvm-openmp-23.1.2-hde6636f_0", + "clang-23-23.1.2-default_h473506b_0", + "compiler-rt-23.1.2-h8af1aa0_0", + "compiler-rt_linux-aarch64-23.1.2-h8af1aa0_0", + "libclang-cpp23.1-23.1.2-default_h01b09c7_0", + "libllvm23-23.1.2-h680871c_0", + "compiler-rt23-23.1.2-hde6636f_0", + "libcompiler-rt-23.1.2-hde6636f_0", + "compiler-rt23_linux-aarch64-23.1.2-hde6636f_0", "binutils-2.46.1-default_hf1166c9_102", - "llvm-openmp-22.1.8-he40846f_0", - "libgcc-devel_linux-aarch64-16.1.0-hd673532_101", - "sysroot_linux-aarch64-2.39-h934ec21_6", - "kernel-headers_linux-aarch64-6.12.0-h05a177a_6", + "libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107", + "sysroot_linux-aarch64-2.28-h585391f_9", + "kernel-headers_linux-aarch64-4.18.0-h05a177a_9", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", + "libzlib-1.3.2-hdc9db2a_3", + "libxml2-16-2.15.4-h2e5089f_0", + "libxml2-2.15.4-h92b9305_0", + "zstd-1.5.7-h9d15635_7", "binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_102", "ld_impl_linux-aarch64-2.46.1-default_h1979696_102", - "libllvm22-22.1.8-hfd2ba90_1", - "libgcc-16.1.0-h205dda4_1", - "libstdcxx-16.1.0-hef695bb_1", "tzdata-2026c-h151e31d_0", - "zstd-1.5.7-h9d15635_7", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libxml2-2.15.3-h9ba8346_0", - "libxml2-16-2.15.3-h064b767_0", - "libzlib-1.3.2-hdc9db2a_3", - "libiconv-1.18-h90929bb_2", + "libgomp-16.2.0-h8acb6b2_7", + "icu-78.3-py311h3512406_2", + "libiconv-1.18-h1ea5142_3", "liblzma-5.8.3-he30d5cf_1", ] [tools."conda:clang"."platforms.linux-x64"] -checksum = "sha256:5fb0aa5d906cf26edd713227b25e65aa9aa1864ee25bb90333dc13f1eeb1dfef" -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-22.1.7-default_cfg_hcbb2b3e_1.conda" +checksum = "sha256:ebf8acd24c828fffb3cd66580e534abdd62894a596c60c9f4cbcfb8f899f8627" +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-23.1.2-default_cfg_hc1abcf6_0.conda" conda_deps = [ - "clang_impl_linux-64-22.1.7-default_h0a60c25_1", - "clang-22-22.1.7-default_h99862b1_1", - "compiler-rt-22.1.7-ha770c72_0", - "libclang-cpp22.1-22.1.7-default_h99862b1_1", - "compiler-rt22-22.1.7-hb700be7_0", - "libcompiler-rt-22.1.7-hb700be7_0", - "compiler-rt22_linux-64-22.1.7-hffcefe0_0", - "compiler-rt_linux-64-22.1.7-ha770c72_0", + "clang_impl_linux-64-23.1.2-default_he0f7a93_0", + "llvm-openmp-23.1.2-h7148c6a_0", + "clang-23-23.1.2-default_hfab3205_0", + "compiler-rt-23.1.2-ha770c72_0", + "compiler-rt_linux-64-23.1.2-ha770c72_0", + "libllvm23-23.1.2-h474f4eb_0", + "libclang-cpp23.1-23.1.2-default_h0acdd01_0", + "compiler-rt23-23.1.2-h7148c6a_0", + "libcompiler-rt-23.1.2-h7148c6a_0", + "compiler-rt23_linux-64-23.1.2-h0e38de2_0", "binutils-2.46.1-default_h4852527_102", - "llvm-openmp-22.1.8-h4922eb0_0", - "libgcc-devel_linux-64-16.1.0-h59071f9_101", - "sysroot_linux-64-2.39-hc4b9eeb_6", - "kernel-headers_linux-64-6.12.0-he073ed8_6", + "libgcc-devel_linux-64-16.2.0-he3ce08f_107", + "sysroot_linux-64-2.28-h4ee821c_9", + "kernel-headers_linux-64-4.18.0-he073ed8_9", + "libstdcxx-16.2.0-h934c35e_7", + "libgcc-16.2.0-ha9f2e26_7", + "libzlib-1.3.2-h25fd6f3_3", + "libxml2-16-2.15.4-hbdfff7e_0", + "libxml2-2.15.4-ha7a5771_0", + "zstd-1.5.7-hb78ec9c_7", "binutils_impl_linux-64-2.46.1-default_hfdba357_102", "ld_impl_linux-64-2.46.1-default_hbd61a6d_102", - "libllvm22-22.1.8-hf7376ad_1", - "libgcc-16.1.0-ha9f2e26_1", - "libstdcxx-16.1.0-h934c35e_1", "tzdata-2026c-h151e31d_0", - "zstd-1.5.7-hb78ec9c_7", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", - "libzlib-1.3.2-h25fd6f3_3", - "libxml2-2.15.3-h49c6c72_0", - "libxml2-16-2.15.3-hca6bf5a_0", - "libiconv-1.18-h3b78370_2", + "libgomp-16.2.0-he0feb66_7", "liblzma-5.8.3-hb03c661_1", - "icu-78.3-py310h44b86e0_2", + "libiconv-1.18-h0cb94f2_3", ] [tools."conda:clang"."platforms.macos-arm64"] -checksum = "sha256:57178d90dc21db8301fc026ffa1bb8df88e66c43c1453a7cef0a611b583e2ae4" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-22.1.7-default_cfg_hb78b91e_1.conda" +checksum = "sha256:a5676921e47783b3ce47e9fe8a98f4516c3d46c84072bc2ff87af82e05f92159" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-23.1.2-default_cfg_h870b8d9_0.conda" conda_deps = [ - "llvm-tools-22.1.7-hd34ed20_0", - "clang_impl_osx-arm64-22.1.7-default_h17d1ed9_1", - "clang-22-22.1.7-default_hd632d02_1", - "llvm-tools-22-22.1.7-hb545844_0", - "libllvm22-22.1.7-h89af1be_0", - "compiler-rt-22.1.7-hce30654_0", - "libclang-cpp22.1-22.1.7-default_h8e162e0_1", - "compiler-rt22-22.1.7-hd34ed20_0", - "libcompiler-rt-22.1.7-hd34ed20_0", - "compiler-rt22_osx-arm64-22.1.7-h7e67a1e_0", - "compiler-rt_osx-arm64-22.1.7-hce30654_0", - "cctools_impl_osx-arm64-1030.6.3-llvm22_1_hb5e89dc_4", - "ld64_osx-arm64-956.6-llvm22_1_h692d5aa_4", - "cctools-1030.6.3-llvm22_1_hbe26303_4", - "ld64-956.6-llvm22_1_h5b97f1b_4", - "llvm-openmp-22.1.8-hc7d1edf_0", - "libcxx-22.1.8-h55c6f16_0", - "tapi-1600.0.11.8-hb561403_3", + "llvm-tools-23.1.2-hdb3d66b_0", + "ld64_osx-arm64-956.6-llvm23_1_hc8058f9_6", + "clang_impl_osx-arm64-23.1.2-default_h79071a4_0", + "llvm-openmp-23.1.2-hdb3d66b_0", + "clang-23-23.1.2-default_h8f9c3af_0", + "llvm-tools-23-23.1.2-h79441dc_0", + "libllvm23-23.1.2-h759d1ac_0", + "compiler-rt-23.1.2-hce30654_0", + "compiler-rt_osx-arm64-23.1.2-hce30654_0", + "libclang-cpp23.1-23.1.2-default_h79071a4_0", + "libcxx-23.1.2-h55c6f16_0", + "compiler-rt23-23.1.2-hdb3d66b_0", + "cctools_impl_osx-arm64-1030.6.3-llvm23_1_hf5e010b_6", + "libcompiler-rt-23.1.2-hdb3d66b_0", + "compiler-rt23_osx-arm64-23.1.2-hb8825d9_0", + "ld64-956.6-llvm23_1_hd841b0c_6", + "cctools-1030.6.3-llvm23_1_h54b4f4b_6", + "libzlib-1.3.2-h8088a28_3", + "libxml2-16-2.15.4-heb56d2d_0", + "libxml2-2.15.4-h550178d_0", + "zstd-1.5.7-hf451053_7", "sigtool-codesign-0.1.3-h98dc951_1", "libsigtool-0.1.3-h98dc951_1", - "libxml2-2.15.3-heed7d32_0", - "libxml2-16-2.15.3-h6967ea9_0", - "zstd-1.5.7-hf451053_7", - "libzlib-1.3.2-h8088a28_3", - "openssl-3.6.3-hd24854e_1", - "ncurses-6.6-he64c551_1", + "tapi-1600.0.11.8-hb561403_4", "liblzma-5.8.3-h8088a28_1", + "icu-78.3-py310h579977c_2", "libiconv-1.18-he4c29f2_3", + "openssl-3.6.4-h55eecbc_0", + "ncurses-6.6-he64c551_1", "ca-certificates-2026.7.22-hbd8a1cb_0", ] [tools."conda:clang"."platforms.macos-x64"] -checksum = "sha256:bb92c990e445ddd7dd0e533e7e2b61a4640e9dfb13e3081396093f4f52fa4377" -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-22.1.7-default_cfg_h93fe8ef_1.conda" +checksum = "sha256:02e2cf73af313219166452f98befa873c6109555a21856af18e056955a4e5df9" +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-23.1.2-default_cfg_hcbdff81_0.conda" conda_deps = [ - "llvm-tools-22.1.7-h1637cdf_0", - "clang_impl_osx-64-22.1.7-default_he9bf3b8_1", - "clang-22-22.1.7-default_h3b8fe2e_1", - "llvm-tools-22-22.1.7-hc181bea_0", - "libllvm22-22.1.7-hab754da_0", - "compiler-rt-22.1.7-h694c41f_0", - "libclang-cpp22.1-22.1.7-default_h9399c5b_1", - "compiler-rt22-22.1.7-h1637cdf_0", - "libcompiler-rt-22.1.7-h1637cdf_0", - "compiler-rt22_osx-64-22.1.7-hcf80936_0", - "compiler-rt_osx-64-22.1.7-h694c41f_0", - "cctools_impl_osx-64-1030.6.3-llvm22_1_h8fe25a2_4", - "ld64_osx-64-956.6-llvm22_1_h163eae7_4", - "ld64-956.6-llvm22_1_hc399b6d_4", - "cctools-1030.6.3-llvm22_1_h0a1bb1c_4", - "llvm-openmp-22.1.8-h0d3cbff_0", - "libcxx-22.1.8-h19cb2f5_0", - "tapi-1600.0.11.8-h44950e2_3", - "sigtool-codesign-0.1.3-h8c25ef7_1", - "libsigtool-0.1.3-h8c25ef7_1", - "libxml2-2.15.3-h0712280_0", - "libxml2-16-2.15.3-h0d7f165_0", + "llvm-tools-23.1.2-h8c1e6b9_0", + "ld64_osx-64-956.6-llvm23_1_h484b24f_6", + "clang_impl_osx-64-23.1.2-default_h6e863b9_0", + "llvm-openmp-23.1.2-h8c1e6b9_0", + "clang-23-23.1.2-default_h3065a3b_0", + "llvm-tools-23-23.1.2-h36529c3_0", + "libllvm23-23.1.2-hd11396f_0", + "compiler-rt-23.1.2-h694c41f_0", + "compiler-rt_osx-64-23.1.2-h694c41f_0", + "libclang-cpp23.1-23.1.2-default_h6e863b9_0", + "libcxx-23.1.2-h19cb2f5_0", + "compiler-rt23-23.1.2-h8c1e6b9_0", + "cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6", + "libcompiler-rt-23.1.2-h8c1e6b9_0", + "compiler-rt23_osx-64-23.1.2-h8d5f570_0", + "ld64-956.6-llvm23_1_h0b736ef_6", + "cctools-1030.6.3-llvm23_1_h254e556_6", + "libxml2-16-2.15.4-h341e563_0", + "libxml2-2.15.4-h3668fe6_0", "libzlib-1.3.2-hbb4bfdb_3", "zstd-1.5.7-hbc1a06c_7", - "openssl-3.6.3-hc881268_1", - "ncurses-6.6-hcc0dc9a_1", + "sigtool-codesign-0.1.3-h8c25ef7_1", + "libsigtool-0.1.3-h8c25ef7_1", + "tapi-1600.0.11.8-h44950e2_4", "liblzma-5.8.3-hbb4bfdb_1", "libiconv-1.18-h4ae439b_3", + "openssl-3.6.4-h332eb6d_0", + "ncurses-6.6-hcc0dc9a_1", "ca-certificates-2026.7.22-hbd8a1cb_0", ] [tools."conda:clang"."platforms.windows-x64"] -checksum = "sha256:5a5b0772bf1d62acb8b4999c02c1ffdc332a7be5cc3f8c3697fce1ef81e109f1" -url = "https://conda.anaconda.org/conda-forge/win-64/clang-22.1.7-default_nocfg_hbb9487a_1.conda" +checksum = "sha256:5cc2e7f6e90e682af16c67caa3e8dc98da484d1e118deaea1644dd8061819c55" +url = "https://conda.anaconda.org/conda-forge/win-64/clang-23.1.2-default_nocfg_h59757e6_0.conda" conda_deps = [ - "clang-22-22.1.7-default_hac490eb_1", - "compiler-rt22-22.1.7-h49e36cd_0", - "compiler-rt22_win-64-22.1.7-h49e36cd_0", + "llvm-openmp-23.1.2-h49e36cd_0", + "clang-23-23.1.2-default_hacd6ee9_0", + "compiler-rt23-23.1.2-h49e36cd_0", + "compiler-rt23_win-64-23.1.2-h49e36cd_0", "libzlib-1.3.2-hfd05255_3", - "llvm-openmp-22.1.8-h4fa8253_0", - "ucrt-10.0.26100.0-h57928b3_0", "vc-14.5-ha367084_41", "vc14_runtime-14.51.36247-habf1de7_41", "vcomp14-14.51.36247-habf1de7_41", + "ucrt-10.0.26100.0-h57928b3_0", "zstd-1.5.7-h534d264_7", + "libxml2-16-2.15.4-h3cfd58e_0", + "libxml2-2.15.4-he095d88_0", + "icu-78.3-h5112557_2", + "libiconv-1.18-hc1393d2_3", + "liblzma-5.8.3-hfd05255_1", ] diff --git a/.mise/mise.dart.lock b/.mise/mise.dart.lock index b09f8e1e..954d28c2 100644 --- a/.mise/mise.dart.lock +++ b/.mise/mise.dart.lock @@ -5,28 +5,28 @@ version = "0.1.14" backend = "cargo:dart-typegen" [[tools.dart]] -version = "3.12.1" +version = "3.13.5" backend = "http:dart" [tools.dart.options] strip_components = "1" [tools.dart."platforms.linux-arm64"] -checksum = "sha256:b44087930108f6d7f56bf580a02d5d2a97ff94519c5a288339982202e1b4c481" -url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.12.1/sdk/dartsdk-linux-arm64-release.zip" +checksum = "sha256:19a731647c3ed55058ee46dde00330150e6a8729bb6121b4a31e86084c8a3e6d" +url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.13.5/sdk/dartsdk-linux-arm64-release.zip" [tools.dart."platforms.linux-x64"] -checksum = "sha256:6a2bbf64a133c9c86a62a532dbd3e0b4db4ac365abd456e9f9d1c5df61fcdbf8" -url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.12.1/sdk/dartsdk-linux-x64-release.zip" +checksum = "sha256:ea864bc64df30a6b8bdf30b2e32550f7717d9a890de8f40293aeabb924fe232b" +url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.13.5/sdk/dartsdk-linux-x64-release.zip" [tools.dart."platforms.macos-arm64"] -checksum = "sha256:eaff3823d5a0c5cdcb65b38adf204e5f35290fcd560d48cb47c2fac7e1547b97" -url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.12.1/sdk/dartsdk-macos-arm64-release.zip" +checksum = "sha256:9dfe7d6f2558816c2a978aff6c80e8a4509c6cb726c0702a616c64d286f60e88" +url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.13.5/sdk/dartsdk-macos-arm64-release.zip" [tools.dart."platforms.macos-x64"] -checksum = "sha256:c56b322cdbc15e0d7c373970c2e2be53bfb438458bd67c1828703e744acb7916" -url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.12.1/sdk/dartsdk-macos-x64-release.zip" +checksum = "sha256:15aaffcc5c6aebcf5e907f721671a9f03cdc5e0b95affa59a9d8291fb2972421" +url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.13.5/sdk/dartsdk-macos-x64-release.zip" [tools.dart."platforms.windows-x64"] -checksum = "sha256:c7af2bfc518ee1c429d5c4c5914588d35efa3aae16650b0b10b5805dc9f22269" -url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.12.1/sdk/dartsdk-windows-x64-release.zip" +checksum = "sha256:aed8e4a8932ce8fa18ea32f990e43b4a1c9390a4c73777ab6fdf77fc9f4524d1" +url = "https://storage.googleapis.com/dart-archive/channels/stable/release/3.13.5/sdk/dartsdk-windows-x64-release.zip" diff --git a/.mise/mise.dotnet.lock b/.mise/mise.dotnet.lock index 8934c722..035cd446 100644 --- a/.mise/mise.dotnet.lock +++ b/.mise/mise.dotnet.lock @@ -5,5 +5,5 @@ version = "10.0.300" backend = "core:dotnet" [[tools."dotnet:roslynator.dotnet.cli"]] -version = "0.12.0" +version = "1.0.0" backend = "dotnet:roslynator.dotnet.cli" diff --git a/.mise/mise.js.lock b/.mise/mise.js.lock index 82ec33e0..d0dcd225 100644 --- a/.mise/mise.js.lock +++ b/.mise/mise.js.lock @@ -1,7 +1,7 @@ # @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html [[tools."http:oxfmt"]] -version = "0.54.0" +version = "1.69.0" backend = "http:oxfmt" [tools."http:oxfmt".options] @@ -16,6 +16,7 @@ checksum = "blake3:81f1adca5230c938968d88e06bc9d9ae6d9d34ee0c849d1e4b43d07562605 url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-x86_64-unknown-linux-gnu.tar.gz" [tools."http:oxfmt"."platforms.macos-arm64"] +checksum = "blake3:2f2414bd00332f5fbe3b50ef84e3dde7f3ee35c9fa29ad3ca449710e4b17196d" url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.69.0/oxfmt-aarch64-apple-darwin.tar.gz" [tools."http:oxfmt"."platforms.macos-x64"] @@ -53,11 +54,11 @@ version = "4.3.0" backend = "npm:@huggingface/transformers" [[tools."npm:@mediapipe/tasks-vision"]] -version = "1.0.0" +version = "1.0.1" backend = "npm:@mediapipe/tasks-vision" [[tools."npm:onnxruntime-web"]] -version = "1.27.0" +version = "1.30.0" backend = "npm:onnxruntime-web" [[tools."npm:oxlint-tsgolint"]] @@ -65,7 +66,7 @@ version = "0.24.0" backend = "npm:oxlint-tsgolint" [[tools."npm:pnpm"]] -version = "11.21.0" +version = "11.28.3" backend = "npm:pnpm" [[tools."npm:stats-gl"]] diff --git a/.mise/mise.linux.lock b/.mise/mise.linux.lock index 027efb35..6d0b8c80 100644 --- a/.mise/mise.linux.lock +++ b/.mise/mise.linux.lock @@ -16,45 +16,49 @@ checksum = "sha256:eebe159bf600943552e4319ff4ce27b6a2dadf0dcc5443e76dcee9259a408 url = "https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda" checksum = "sha256:24eacc8a20fd7c4616566178562bef7f9344eb4a8700cfc3180fa75a6ff9d39f" -[conda-packages.linux-arm64."clang-22-22.1.6-default_h2a92e99_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-22-22.1.6-default_h2a92e99_1.conda" -checksum = "sha256:8387978801602fe514577103c99a207ba11535f4bb8b7d66c0e81613d20fd0ef" +[conda-packages.linux-arm64."clang-23-23.1.2-default_h473506b_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-23-23.1.2-default_h473506b_0.conda" +checksum = "sha256:408ffc3dec7d6ac5ef17a11fdb925a94f178f9d0414c4412884c6394b1a89ab1" -[conda-packages.linux-arm64."clang-22.1.6-default_cfg_h99ebb92_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-22.1.6-default_cfg_h99ebb92_1.conda" -checksum = "sha256:5640b47945a66b24f4db6d1b9f428039c0e6f11204b05f3cdde5f381c8c3fe71" +[conda-packages.linux-arm64."clang-23.1.2-default_cfg_h1a548ed_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-23.1.2-default_cfg_h1a548ed_0.conda" +checksum = "sha256:a4296ee7ba32a24cda0eb766f46dfb0adb22d9f889bfd14bc835cd4e415beaf9" -[conda-packages.linux-arm64."clang-scan-deps-22.1.6-default_h2a92e99_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-scan-deps-22.1.6-default_h2a92e99_1.conda" -checksum = "sha256:b340f665fb90a44a0b6e6624e749509a5507a2456c05b7eccae3fc2bda94da01" +[conda-packages.linux-arm64."clang-scan-deps-23.1.2-default_h01b09c7_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-scan-deps-23.1.2-default_h01b09c7_0.conda" +checksum = "sha256:2321952cd5d77a2e03b5d3f429a26805885379bbc7a1f1151a0d08e208ba1d22" -[conda-packages.linux-arm64."clang_impl_linux-aarch64-22.1.6-default_h1168dbd_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang_impl_linux-aarch64-22.1.6-default_h1168dbd_1.conda" -checksum = "sha256:738c6066605b14b4a98d9cffcaaea1087bab8e59f803d781597af5ad8a9cacc0" +[conda-packages.linux-arm64."clang_impl_linux-aarch64-23.1.2-default_hb71c922_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang_impl_linux-aarch64-23.1.2-default_hb71c922_0.conda" +checksum = "sha256:fd4dcb2b8f1098faf65dd2a78fff0b06bd3e732363232a2c1daff476a11ca40b" -[conda-packages.linux-arm64."clangxx_impl_linux-aarch64-22.1.6-default_h1168dbd_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clangxx_impl_linux-aarch64-22.1.6-default_h1168dbd_1.conda" -checksum = "sha256:b6e47b0241952cde7541a405de84ac3f20fdf4836fbb0a2360615bd9b388bae0" +[conda-packages.linux-arm64."clangxx_impl_linux-aarch64-23.1.2-default_h99e0da6_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clangxx_impl_linux-aarch64-23.1.2-default_h99e0da6_0.conda" +checksum = "sha256:8df7edc76137b331cf264b3443bf5514313e9cfdd0f35c6402737e48ac0b8f79" -[conda-packages.linux-arm64."compiler-rt-22.1.6-h8af1aa0_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt-22.1.6-h8af1aa0_0.conda" -checksum = "sha256:7a51cf211eb1f2f85e476bcebf4ac17a3f37ad08093f0cfb92010f4d65aeb74c" +[conda-packages.linux-arm64."compiler-rt-23.1.2-h8af1aa0_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt-23.1.2-h8af1aa0_0.conda" +checksum = "sha256:7919c447020a962c20e5350e578469db002748fad3069cc59cfb2e1da9dc6555" -[conda-packages.linux-arm64."compiler-rt22-22.1.6-hfefdfc9_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt22-22.1.6-hfefdfc9_0.conda" -checksum = "sha256:392494883c7ef15c8292a246c40332041c6c692baf11e1a0a58e90bd00e7a5b3" +[conda-packages.linux-arm64."compiler-rt23-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/compiler-rt23-23.1.2-hde6636f_0.conda" +checksum = "sha256:3219dd61acef3620ff7ceaa490ef4576e88401b48aee68d57dc225ffb1fe0470" -[conda-packages.linux-arm64."compiler-rt22_linux-aarch64-22.1.6-hfefdfc9_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_linux-aarch64-22.1.6-hfefdfc9_0.conda" -checksum = "sha256:633d744bf08ffe7717908c794dc4398989a2bb97e382fdbc7dd46e10e11af381" +[conda-packages.linux-arm64."compiler-rt23_linux-aarch64-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-aarch64-23.1.2-hde6636f_0.conda" +checksum = "sha256:95cae6c25dcd67d76a909841859ba95ebf7c51087d84be6e8c962ba372756c47" -[conda-packages.linux-arm64."compiler-rt_linux-aarch64-22.1.6-h8af1aa0_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-aarch64-22.1.6-h8af1aa0_0.conda" -checksum = "sha256:94626803f1a8be6e9389e0d67e7d3721fb4ddeae5468e453d123d0edfd5274a7" +[conda-packages.linux-arm64."compiler-rt_linux-aarch64-23.1.2-h8af1aa0_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-aarch64-23.1.2-h8af1aa0_0.conda" +checksum = "sha256:0a8f2f4993e5566bbba883db2f51f5f0a5c750fe2ae42cd1177582efe7b4544d" -[conda-packages.linux-arm64."kernel-headers_linux-aarch64-6.12.0-h05a177a_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-6.12.0-h05a177a_6.conda" -checksum = "sha256:2251f81ccc1d3bb38873cbcdcf43c15f424a057714a7c7a4756e3c68440ad0e9" +[conda-packages.linux-arm64."icu-78.3-py311h3512406_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda" +checksum = "sha256:54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e" + +[conda-packages.linux-arm64."kernel-headers_linux-aarch64-4.18.0-h05a177a_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h05a177a_9.conda" +checksum = "sha256:5d224bf4df9bac24e69de41897c53756108c5271a0e5d2d2f66fd4e2fbc1d84b" [conda-packages.linux-arm64."ld_impl_linux-aarch64-2.46.1-default_h1979696_102"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.46.1-default_h1979696_102.conda" @@ -64,101 +68,101 @@ checksum = "sha256:2c4901f4227b0850328ed0c69f958b30ad2cd18982f7a31c7c1f911827004 url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libassuan-3.0.2-h5ad3122_0.conda" checksum = "sha256:042843a7760a9be3e7642528a2667b644f8eda009e1846658726fdca610afb73" -[conda-packages.linux-arm64."libclang-cpp22.1-22.1.6-default_h2a92e99_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.6-default_h2a92e99_1.conda" -checksum = "sha256:663ac1fa15bdec186050a86274aae28fd337efca55b86ba0503a6792b3b80e48" +[conda-packages.linux-arm64."libclang-cpp23.1-23.1.2-default_h01b09c7_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp23.1-23.1.2-default_h01b09c7_0.conda" +checksum = "sha256:9b0ced8d10de3dd1cc8271779dd1603b6168ee2384b0fa79ac7743a1ea0ae47c" -[conda-packages.linux-arm64."libclang13-22.1.8-default_h3185f35_2"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_h3185f35_2.conda" -checksum = "sha256:50653a48c55627feb149ca80d05d6112747e396e92a80f6094234e95e483cc6e" +[conda-packages.linux-arm64."libclang13-23.1.2-default_h473506b_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-23.1.2-default_h473506b_0.conda" +checksum = "sha256:17bbfe80fd9c58e614e5de34bb3fb5d12158cbbccc789a3e8fecb110db607223" -[conda-packages.linux-arm64."libcompiler-rt-22.1.6-hfefdfc9_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libcompiler-rt-22.1.6-hfefdfc9_0.conda" -checksum = "sha256:57e9730185d018b2c226a8b7e309ead9e17aeaa7687d27c43d4968d2a3bce1e8" +[conda-packages.linux-arm64."libcompiler-rt-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libcompiler-rt-23.1.2-hde6636f_0.conda" +checksum = "sha256:bb301a736fcd1a018ee4865c37b407d820b90ac27dc0fbc33fee2dc7b047e8ae" -[conda-packages.linux-arm64."libgcc-16.1.0-h205dda4_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.1.0-h205dda4_1.conda" -checksum = "sha256:88a3d400c678df034c9d498f32503779977d5ea826063687c663e42c945abed5" +[conda-packages.linux-arm64."libgcc-16.2.0-h205dda4_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda" +checksum = "sha256:eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1" -[conda-packages.linux-arm64."libgcc-devel_linux-aarch64-16.1.0-hd673532_101"] -url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-16.1.0-hd673532_101.conda" -checksum = "sha256:885f0d8a47f7ea50d7b33d07a240f2301935602b9d2a39a35b5018b13e934100" +[conda-packages.linux-arm64."libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107"] +url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107.conda" +checksum = "sha256:3a0fc46d9ffe0bc98e825bfcc0409564435e74ae0ac094b484a89a296ed777ee" -[conda-packages.linux-arm64."libgcc-ng-16.1.0-he9431aa_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-16.1.0-he9431aa_1.conda" -checksum = "sha256:e0456b4b49e8f9f9ffc04b1b412101ea2c38476eaceb9a0e4e16792d7cfdd929" +[conda-packages.linux-arm64."libgcc-ng-16.2.0-he9431aa_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-16.2.0-he9431aa_7.conda" +checksum = "sha256:d7502682cfce6f51aabd40bba63cd6b46db3d3e4b67abdb00f54ae72332523db" -[conda-packages.linux-arm64."libgcrypt-1.12.2-h8af1aa0_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-1.12.2-h8af1aa0_0.conda" -checksum = "sha256:842adfd194494490e8c4771dfa1d536ab71a9f3f09b41b3ee4c1b49553326bbb" +[conda-packages.linux-arm64."libgcrypt-1.12.2-h8af1aa0_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-1.12.2-h8af1aa0_2.conda" +checksum = "sha256:327d2239319829def075ca2580b810060bc956036819d771d727352029cf6735" -[conda-packages.linux-arm64."libgcrypt-devel-1.12.2-he30d5cf_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-devel-1.12.2-he30d5cf_0.conda" -checksum = "sha256:8a27549cf1a903f21bbb97f10e3e3b32b23d3b0eda611329760541a1720cc69e" +[conda-packages.linux-arm64."libgcrypt-devel-1.12.2-h5bc82ec_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-devel-1.12.2-h5bc82ec_2.conda" +checksum = "sha256:2dc2ab9e7a58bb9b774e30a4b5a178113f0adbf76c5298e43b1cf0e2f272e8f5" -[conda-packages.linux-arm64."libgcrypt-lib-1.12.2-he30d5cf_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-lib-1.12.2-he30d5cf_0.conda" -checksum = "sha256:5c1fa4dfe58fedf2077a0cc831565f32fe3fede70503fa91bcaf0b0a7ee6a5d9" +[conda-packages.linux-arm64."libgcrypt-lib-1.12.2-h5bc82ec_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-lib-1.12.2-h5bc82ec_2.conda" +checksum = "sha256:26f2981255e575a47c1fb4bcd0f869d0fadfa3ab44a0ab005fe3887f75e7a154" -[conda-packages.linux-arm64."libgcrypt-tools-1.12.2-he30d5cf_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-tools-1.12.2-he30d5cf_0.conda" -checksum = "sha256:580a0806d8048e3fd936e170455bc1993f53c01923a6361115e4280cf43c820a" +[conda-packages.linux-arm64."libgcrypt-tools-1.12.2-h5bc82ec_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-tools-1.12.2-h5bc82ec_2.conda" +checksum = "sha256:3d566ba1641653f7ec835ee1401397e296c77d47c7b979bc6725c33883fe377a" -[conda-packages.linux-arm64."libgomp-16.1.0-h8acb6b2_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.1.0-h8acb6b2_1.conda" -checksum = "sha256:1c609a4a72597350317b92c4d9dfb85d21740219048e2b1d458925a6ccfa3d7a" +[conda-packages.linux-arm64."libgomp-16.2.0-h8acb6b2_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda" +checksum = "sha256:4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494" [conda-packages.linux-arm64."libgpg-error-1.61-h7ac5ae9_2"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgpg-error-1.61-h7ac5ae9_2.conda" checksum = "sha256:df4c43ae4003100feea4d96000fcfff57f05832b2aa5b9385bba05cb33fa776f" -[conda-packages.linux-arm64."libiconv-1.18-h90929bb_2"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda" -checksum = "sha256:1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9" +[conda-packages.linux-arm64."libiconv-1.18-h1ea5142_3"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h1ea5142_3.conda" +checksum = "sha256:d22c666eb887afd2119aac2110e23a0e817e9391bda99293421f7c46dab1564c" [conda-packages.linux-arm64."libksba-1.6.7-h0a1ffab_0"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libksba-1.6.7-h0a1ffab_0.conda" checksum = "sha256:6bd8c23157e3afa89d56ff876993232d94dc796e1ad190f3cd56148815c7004f" -[conda-packages.linux-arm64."libllvm22-22.1.8-hfd2ba90_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda" -checksum = "sha256:dc943f1730a27f5fb36682c9852f7196f671c3a9df4a0a7a8f7ba665637c9151" +[conda-packages.linux-arm64."libllvm23-23.1.2-h680871c_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm23-23.1.2-h680871c_0.conda" +checksum = "sha256:9b7820c041aeebea33d738a917c185ae554b6b89e2491e83e64f9a2fe675f88c" [conda-packages.linux-arm64."liblzma-5.8.3-he30d5cf_1"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda" checksum = "sha256:f760669fd1cea27f689f411c0d5488e26ce50e382c9b63e4ad348f959850124a" -[conda-packages.linux-arm64."libsqlite-3.53.4-h022381a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.4-h022381a_0.conda" -checksum = "sha256:da46b52f6815e9771f4e21e3332c423c88644e91ac96b0534e85158adc88a8b4" +[conda-packages.linux-arm64."libsqlite-3.53.4-h399dd60_1"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.4-h399dd60_1.conda" +checksum = "sha256:fae75e68e9dbc3c90dcf93d4bae6315f1330c95aaf1404a721e8468266c23475" -[conda-packages.linux-arm64."libstdcxx-16.1.0-hef695bb_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.1.0-hef695bb_1.conda" -checksum = "sha256:81ef9a10a0e01ffc7e03d429ed048410153411b2d8bbf95c334bdf3dcf175ab0" +[conda-packages.linux-arm64."libstdcxx-16.2.0-hef695bb_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda" +checksum = "sha256:b241a3acfa9cdb1359112864a1241225533c92642de3000d52ae65ef5d3a9786" -[conda-packages.linux-arm64."libstdcxx-devel_linux-aarch64-16.1.0-h2445e1f_101"] -url = "https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-16.1.0-h2445e1f_101.conda" -checksum = "sha256:926d2c2dedfca7334804d5c8a0727a3746ef580be8763f51ccc2ece24c7be56c" +[conda-packages.linux-arm64."libstdcxx-devel_linux-aarch64-16.2.0-h082e5f6_107"] +url = "https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-16.2.0-h082e5f6_107.conda" +checksum = "sha256:c46e0efb196a24e9192f160c124f8a1d927c7d191595a1dc993f30dc93a52497" -[conda-packages.linux-arm64."libstdcxx-ng-16.1.0-hdbbeba8_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-16.1.0-hdbbeba8_1.conda" -checksum = "sha256:cb88eb500022e01f835209e771d455d2296e10a18a749f518c257dfcab7d46ba" +[conda-packages.linux-arm64."libstdcxx-ng-16.2.0-hdbbeba8_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-16.2.0-hdbbeba8_7.conda" +checksum = "sha256:cfe644e4cf78302e605f7dc1cfa23ee4edabf5b72f84c92436f5f51c3003542c" -[conda-packages.linux-arm64."libxml2-16-2.15.3-h064b767_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.3-h064b767_0.conda" -checksum = "sha256:96e9bd642c013ce3407c23b3819204ea8a591567d62b49baa4bafb2f1487326c" +[conda-packages.linux-arm64."libxml2-16-2.15.4-h2e5089f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.4-h2e5089f_0.conda" +checksum = "sha256:58bf7fcf64bae7f624a5e2aed860ddea614a8ec13c8c43fe150420a275b8bdb5" -[conda-packages.linux-arm64."libxml2-2.15.3-h9ba8346_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.3-h9ba8346_0.conda" -checksum = "sha256:74aa3c62e0ec4491343b95ce4ca8812ad2f9bb015369e29cb3b4b9b4302d8cb0" +[conda-packages.linux-arm64."libxml2-2.15.4-h92b9305_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.4-h92b9305_0.conda" +checksum = "sha256:3345c88fa9ebb373bcf4069ede898950005fa2d1707e56a13a1ac6339919492f" [conda-packages.linux-arm64."libzlib-1.3.2-hdc9db2a_3"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda" checksum = "sha256:76efa6cc9d7e6f5ee3bbca0939f64054af2bdfb3c3632531f8e633cf6c2ea41e" -[conda-packages.linux-arm64."llvm-openmp-22.1.8-he40846f_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/llvm-openmp-22.1.8-he40846f_0.conda" -checksum = "sha256:30bbb0ce4ae7cebbeb9801af5bbd2a29f8627237a38d08fc5d8d800e79c817aa" +[conda-packages.linux-arm64."llvm-openmp-23.1.2-hde6636f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/llvm-openmp-23.1.2-hde6636f_0.conda" +checksum = "sha256:75a5cba29fd370cf20c6922587bbf4034858e2a46815b2cc45144f009b596df7" [conda-packages.linux-arm64."ncurses-6.6-h2b6f883_1"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-h2b6f883_1.conda" @@ -172,17 +176,17 @@ checksum = "sha256:1fcbc982059bc5ed7a544ae43a8be6d9ee8d0d4c3fe8fb30eb9185db0aa6e url = "https://conda.anaconda.org/conda-forge/linux-aarch64/ntbtls-0.3.2-hd84c7bf_0.conda" checksum = "sha256:d9af7c17e6c452312a9d623eeff588f427242986fcc39ea65a0ef030dbe8cbe1" -[conda-packages.linux-arm64."readline-8.3-hb682ff5_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda" -checksum = "sha256:fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216" +[conda-packages.linux-arm64."readline-8.3-ha7194a6_1"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda" +checksum = "sha256:80167dcf73a96b6d0c1bb2298d7b8b9bc21b27cc5bf56979f9c548b49a4d1722" -[conda-packages.linux-arm64."sqlite-3.53.4-he8854b5_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.4-he8854b5_0.conda" -checksum = "sha256:70bc70e05ec16173ad15e13624d051588dcd2c2f01ef12171234ab04d4c7d888" +[conda-packages.linux-arm64."sqlite-3.53.4-h6ce2f9a_1"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.4-h6ce2f9a_1.conda" +checksum = "sha256:551c79a5cf720c1302bc201f8633c27954a5daeb67be3719023a24ac8fd9f818" -[conda-packages.linux-arm64."sysroot_linux-aarch64-2.39-h934ec21_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.39-h934ec21_6.conda" -checksum = "sha256:bf817fbdb9953dda8f4b0d3c5bdf23a072c6baf6d39cb80e067f274a9d6feaf2" +[conda-packages.linux-arm64."sysroot_linux-aarch64-2.28-h585391f_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.28-h585391f_9.conda" +checksum = "sha256:1bd2db6b2e451247bab103e4a0128cf6c7595dd72cb26d70f7fadd9edd1d1bc3" [conda-packages.linux-arm64.tzdata-2026c-h151e31d_0] url = "https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda" @@ -212,49 +216,49 @@ checksum = "sha256:fb7bf36984a37ce7e4714d1d1da0bd0e3bfc679520f5cdc184afc676fd4b5 url = "https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda" checksum = "sha256:1a0d382c515ebf55f8ee1f38c8b81bc95af5c2acc42ad53b66bc5df932032f96" -[conda-packages.linux-x64."clang-22-22.1.6-default_h99862b1_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-22-22.1.6-default_h99862b1_1.conda" -checksum = "sha256:c0a92dc4a8b0502ae3526e8912ab69df3eb42a5baae3f5860f85490fb62e8e7c" +[conda-packages.linux-x64."clang-23-23.1.2-default_hfab3205_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-23-23.1.2-default_hfab3205_0.conda" +checksum = "sha256:86a6c2e8d77a1c07905623c4decaa2304a27a55ea7fa39a2ce338f911104f799" -[conda-packages.linux-x64."clang-22.1.6-default_cfg_hcbb2b3e_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-22.1.6-default_cfg_hcbb2b3e_1.conda" -checksum = "sha256:1b91011b467438ec1e1130d9d1b1e1f2d512f0fec0a465612b7cb6cc4da962a6" +[conda-packages.linux-x64."clang-23.1.2-default_cfg_hc1abcf6_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-23.1.2-default_cfg_hc1abcf6_0.conda" +checksum = "sha256:ebf8acd24c828fffb3cd66580e534abdd62894a596c60c9f4cbcfb8f899f8627" -[conda-packages.linux-x64."clang-scan-deps-22.1.6-default_h99862b1_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-22.1.6-default_h99862b1_1.conda" -checksum = "sha256:f65fc181adba282f4b5d5891194c222f618f828c0142c61c90a6334120ba1350" +[conda-packages.linux-x64."clang-scan-deps-23.1.2-default_h0acdd01_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-23.1.2-default_h0acdd01_0.conda" +checksum = "sha256:7c8a8382a7ab32f731302d1af010e73329cdac9ad29fa2d77c3a5048307c9308" -[conda-packages.linux-x64."clang_impl_linux-64-22.1.6-default_h0a60c25_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-22.1.6-default_h0a60c25_1.conda" -checksum = "sha256:97af437913c9d551e6fa2ff4254d1d05a07c0023c2b269b4ad5a5340533b5114" +[conda-packages.linux-x64."clang_impl_linux-64-23.1.2-default_he0f7a93_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang_impl_linux-64-23.1.2-default_he0f7a93_0.conda" +checksum = "sha256:c88b4669209d93a93738ba7a1c59518a2cbefd9498dbfc873e9f5ce2fbc7991a" -[conda-packages.linux-x64."clangxx_impl_linux-64-22.1.6-default_h0a60c25_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clangxx_impl_linux-64-22.1.6-default_h0a60c25_1.conda" -checksum = "sha256:92c68f4dfc02893e6417f40e5183eead8e7021cee64d8d7885e2ec1500bbdf00" +[conda-packages.linux-x64."clangxx_impl_linux-64-23.1.2-default_h165e814_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clangxx_impl_linux-64-23.1.2-default_h165e814_0.conda" +checksum = "sha256:878904b19bfa0ae7ffeccac551336609af19adf1ce8f74feb7f0e965fec9bde3" -[conda-packages.linux-x64."compiler-rt-22.1.6-ha770c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-22.1.6-ha770c72_0.conda" -checksum = "sha256:42d60a29aa92a64826b970b3e2a02e5d67b473549683487aeb50fbf3a7bde120" +[conda-packages.linux-x64."compiler-rt-23.1.2-ha770c72_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt-23.1.2-ha770c72_0.conda" +checksum = "sha256:11b5fcbfdc088c370c5120ac758593905aca71ac2b511912fc60d9e6595bb709" -[conda-packages.linux-x64."compiler-rt22-22.1.6-hb700be7_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt22-22.1.6-hb700be7_0.conda" -checksum = "sha256:fc510b7380f29bfc5940d5b4752a96d8b319e0bcea0a6c70010088c609507585" +[conda-packages.linux-x64."compiler-rt23-23.1.2-h7148c6a_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/compiler-rt23-23.1.2-h7148c6a_0.conda" +checksum = "sha256:3b59755649409e7d61a92233ba1be11880c1d7071796ef8713f4f8be2f3aa645" -[conda-packages.linux-x64."compiler-rt22_linux-64-22.1.6-hffcefe0_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_linux-64-22.1.6-hffcefe0_0.conda" -checksum = "sha256:c3440ca1569ea0c9735df3267de18ebc8af3390ff57ae59bad429f56e41de2c6" +[conda-packages.linux-x64."compiler-rt23_linux-64-23.1.2-h0e38de2_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_linux-64-23.1.2-h0e38de2_0.conda" +checksum = "sha256:8ab3d19a6d833a9d98a559d40a2e9f07eea353d5501c2610417f53102391bf8c" -[conda-packages.linux-x64."compiler-rt_linux-64-22.1.6-ha770c72_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-22.1.6-ha770c72_0.conda" -checksum = "sha256:edfca3825c48fdc7b4e6e4386ff62ffbabe8dcc4a30b529b09cdb38de497c90b" +[conda-packages.linux-x64."compiler-rt_linux-64-23.1.2-ha770c72_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_linux-64-23.1.2-ha770c72_0.conda" +checksum = "sha256:1365a5fff5c9463b09586ed4cd0b03864083fde070bbbe5320d4ddf70d648ebe" [conda-packages.linux-x64."icu-78.3-py310h44b86e0_2"] url = "https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda" checksum = "sha256:9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432" -[conda-packages.linux-x64."kernel-headers_linux-64-6.12.0-he073ed8_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-6.12.0-he073ed8_6.conda" -checksum = "sha256:73b11f31db6c9ebe63d900334fa4f46859aa1ddd8f37cfa5f25a043e0a59253c" +[conda-packages.linux-x64."kernel-headers_linux-64-4.18.0-he073ed8_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda" +checksum = "sha256:41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a" [conda-packages.linux-x64."ld_impl_linux-64-2.46.1-default_hbd61a6d_102"] url = "https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_102.conda" @@ -264,101 +268,101 @@ checksum = "sha256:27d83f1188cd19bcb7754a078b3fa7f4cfb8527f8eb2fde54dd01fc529d1a url = "https://conda.anaconda.org/conda-forge/linux-64/libassuan-3.0.2-h5888daf_0.conda" checksum = "sha256:a89ee880e951cc9399606545cb9e6377c8f260fa40942b8486d82d64d3d34491" -[conda-packages.linux-x64."libclang-cpp22.1-22.1.6-default_h99862b1_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.6-default_h99862b1_1.conda" -checksum = "sha256:0567c126b7b1f8a198a70e5aa97aa05886cf87c2eb325299fbed7fcbad5142e8" +[conda-packages.linux-x64."libclang-cpp23.1-23.1.2-default_h0acdd01_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp23.1-23.1.2-default_h0acdd01_0.conda" +checksum = "sha256:49156155d4f0ab4f479bc96d24db2c48c0b6bdb5659135c194f03c289ae2c523" -[conda-packages.linux-x64."libclang13-22.1.8-default_h746c552_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h746c552_2.conda" -checksum = "sha256:1eb59e923b08200403a98078f37463b314fd84cda15191d2519f82bb129765af" +[conda-packages.linux-x64."libclang13-23.1.2-default_hfab3205_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang13-23.1.2-default_hfab3205_0.conda" +checksum = "sha256:6009280c06f52fcce68f4c95c19e23a13aaf3edc99c4ae1e574c4c5f09eccac3" -[conda-packages.linux-x64."libcompiler-rt-22.1.6-hb700be7_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-22.1.6-hb700be7_0.conda" -checksum = "sha256:2b89a8c95b71509d6241cee16be682a38657c9e15e09c63c3c1ea9d315476c8e" +[conda-packages.linux-x64."libcompiler-rt-23.1.2-h7148c6a_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libcompiler-rt-23.1.2-h7148c6a_0.conda" +checksum = "sha256:2b0e6b377b1a429db6a86cad50a07e856a2c6ef748d740a3d59722677376eefd" -[conda-packages.linux-x64."libgcc-16.1.0-ha9f2e26_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda" -checksum = "sha256:d5cb8475131c31680f8fd30512c418f373064e272e452063276a8fb14c9fa42f" +[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda" +checksum = "sha256:e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea" -[conda-packages.linux-x64."libgcc-devel_linux-64-16.1.0-h59071f9_101"] -url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.1.0-h59071f9_101.conda" -checksum = "sha256:b314251d957b16c71ec241119ac09b9530c5c4ce140026ec98d297f55d6c5e08" +[conda-packages.linux-x64."libgcc-devel_linux-64-16.2.0-he3ce08f_107"] +url = "https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-16.2.0-he3ce08f_107.conda" +checksum = "sha256:f1e7465f6b53f89b325e441c30ad7b19407b051eca556b6d0386ec05513b8e76" -[conda-packages.linux-x64."libgcc-ng-16.1.0-h69a702a_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.1.0-h69a702a_1.conda" -checksum = "sha256:225275c562337a1cd61705da0ee4235dde7bba7504de1c34b74c894adb2b0eee" +[conda-packages.linux-x64."libgcc-ng-16.2.0-h69a702a_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_7.conda" +checksum = "sha256:03b54d7008de080a17cc2174b0e4acd6d06e1c981b2eb19846f46d8f59966034" -[conda-packages.linux-x64."libgcrypt-1.12.2-ha770c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-1.12.2-ha770c72_0.conda" -checksum = "sha256:a98425d866a1aa56042d24ff453d2df0ff0b0bb1ef9a77e54dcc82f6f8e0510b" +[conda-packages.linux-x64."libgcrypt-1.12.2-ha770c72_2"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-1.12.2-ha770c72_2.conda" +checksum = "sha256:831898d269b74439ef904d5ae237ed08a1c886a3a4f29fd6973eb09d22e59aa6" -[conda-packages.linux-x64."libgcrypt-devel-1.12.2-hb03c661_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-devel-1.12.2-hb03c661_0.conda" -checksum = "sha256:7128f96ebc18fb1ca51b0ef55a18570eb5fff28bb24c0b20a8eb09f95f212aeb" +[conda-packages.linux-x64."libgcrypt-devel-1.12.2-h7cc23a3_2"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-devel-1.12.2-h7cc23a3_2.conda" +checksum = "sha256:ba6a30372f94eab139a4df5967cfb685e0a1bd6cb2d4d464698594e29c5f2de2" -[conda-packages.linux-x64."libgcrypt-lib-1.12.2-hb03c661_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-lib-1.12.2-hb03c661_0.conda" -checksum = "sha256:9779af09721826ebd0217f507e03dfa09df899483d8f129116ae38b374c6788b" +[conda-packages.linux-x64."libgcrypt-lib-1.12.2-h7cc23a3_2"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-lib-1.12.2-h7cc23a3_2.conda" +checksum = "sha256:a67e7b569f08459fbd62619cbbc14a0e2da9d9e519feb11ee035bb31c653d1a9" -[conda-packages.linux-x64."libgcrypt-tools-1.12.2-hb03c661_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-tools-1.12.2-hb03c661_0.conda" -checksum = "sha256:9c7deb5e609dfb6ebf1eb327081c31b5bad7ab380176910759a46951c64c9c5d" +[conda-packages.linux-x64."libgcrypt-tools-1.12.2-h7cc23a3_2"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-tools-1.12.2-h7cc23a3_2.conda" +checksum = "sha256:781063cd902514ad5c27f30f512d7175f5c51013a1fecb1aa602ca04b583a8f2" -[conda-packages.linux-x64."libgomp-16.1.0-he0feb66_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda" -checksum = "sha256:62cb599ad0539d99386515326d9d5e8f51f75a60c69c2131b21df76edf35bd89" +[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda" +checksum = "sha256:92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758" [conda-packages.linux-x64."libgpg-error-1.61-h54a6638_2"] url = "https://conda.anaconda.org/conda-forge/linux-64/libgpg-error-1.61-h54a6638_2.conda" checksum = "sha256:b69606451dfce168990dd40324e52daf981472511788d412ce78664760d3889f" -[conda-packages.linux-x64."libiconv-1.18-h3b78370_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda" -checksum = "sha256:c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f" +[conda-packages.linux-x64."libiconv-1.18-h0cb94f2_3"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda" +checksum = "sha256:f943117edb9cd4d9c61cc972eee5a34291dc55ea7a6e9e38da104995841cbcb6" [conda-packages.linux-x64."libksba-1.6.7-hac33072_0"] url = "https://conda.anaconda.org/conda-forge/linux-64/libksba-1.6.7-hac33072_0.conda" checksum = "sha256:289d4f2bf33134c4f5565f772829cb66c996485723bd9c299a21f73ff8aed77a" -[conda-packages.linux-x64."libllvm22-22.1.8-hf7376ad_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda" -checksum = "sha256:e9b5f301d6b001a9b8ce782157f56b75c92c4fbc9eba95dc6345c1139251d13b" +[conda-packages.linux-x64."libllvm23-23.1.2-h474f4eb_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm23-23.1.2-h474f4eb_0.conda" +checksum = "sha256:253a11a58756a3584c72c625752fb6ccf0a8885815f3e911f05731cfc24ea0ed" [conda-packages.linux-x64."liblzma-5.8.3-hb03c661_1"] url = "https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda" checksum = "sha256:9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab" -[conda-packages.linux-x64."libsqlite-3.53.4-hf4e2dac_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-hf4e2dac_0.conda" -checksum = "sha256:72023efc207fe681e26b65fc9d668062cf0b4f0eacf3431e6eb099b95c1f2efd" +[conda-packages.linux-x64."libsqlite-3.53.4-h13e7031_1"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h13e7031_1.conda" +checksum = "sha256:f20d70da54e5b31dd4a51fb1efeaafafd5ab6dd8d7ac9d1438eaa2526ac4ed3d" -[conda-packages.linux-x64."libstdcxx-16.1.0-h934c35e_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.1.0-h934c35e_1.conda" -checksum = "sha256:79721dd08aeb0ab9e773f1f9ef41cf4e6c17477e3d72319147619045bce05a09" +[conda-packages.linux-x64."libstdcxx-16.2.0-h934c35e_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda" +checksum = "sha256:fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745" -[conda-packages.linux-x64."libstdcxx-devel_linux-64-16.1.0-h41cdd0d_101"] -url = "https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-16.1.0-h41cdd0d_101.conda" -checksum = "sha256:c1521172f2fdf5510d79b621ea835064209fe3131518e0d8b2b43362a75e7b4c" +[conda-packages.linux-x64."libstdcxx-devel_linux-64-16.2.0-h86e191b_107"] +url = "https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-16.2.0-h86e191b_107.conda" +checksum = "sha256:ebbad84bdebd8a9964020d74dcce0f211f1431878c66326f6115dcb59e4c3469" -[conda-packages.linux-x64."libstdcxx-ng-16.1.0-hdf11a46_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.1.0-hdf11a46_1.conda" -checksum = "sha256:2876ca4463d1b394eb969ce4a84d1620aa63fb8202a6397837d1e45ec76c1208" +[conda-packages.linux-x64."libstdcxx-ng-16.2.0-hdf11a46_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_7.conda" +checksum = "sha256:337f481db36cc357884f05f404ccd1b3a7e0fc1ee48ec5c884e4281d213bc863" -[conda-packages.linux-x64."libxml2-16-2.15.3-hca6bf5a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_0.conda" -checksum = "sha256:3d44f737c5ae52d5af32682cc1530df433f401f8e58a7533926536244127572a" +[conda-packages.linux-x64."libxml2-16-2.15.4-hbdfff7e_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hbdfff7e_0.conda" +checksum = "sha256:b6f96287c408269f5067bb4f7a61693ff5c856152902362964d9807152b9c146" -[conda-packages.linux-x64."libxml2-2.15.3-h49c6c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_0.conda" -checksum = "sha256:3bc5551720c58591f6ea1146f7d1539c734ed1c40e7b9f5cb8cb7e900c509aba" +[conda-packages.linux-x64."libxml2-2.15.4-ha7a5771_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-ha7a5771_0.conda" +checksum = "sha256:db52c038430a508656530fc7b5650ae3e2629875693a6a256cc48dec203f8bfe" [conda-packages.linux-x64."libzlib-1.3.2-h25fd6f3_3"] url = "https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda" checksum = "sha256:eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc736" -[conda-packages.linux-x64."llvm-openmp-22.1.8-h4922eb0_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda" -checksum = "sha256:a37aba21b85800af1e7c5b04ba76abab96b6e591eedf99dc6e4df83b0fefd7a5" +[conda-packages.linux-x64."llvm-openmp-23.1.2-h7148c6a_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-23.1.2-h7148c6a_0.conda" +checksum = "sha256:292606e3a17fcf98db940d3ee6e723f84f4c6fb0104a6a69cd95043a7794eef0" [conda-packages.linux-x64."ncurses-6.6-hdb14827_1"] url = "https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda" @@ -372,17 +376,17 @@ checksum = "sha256:da3af9708bbf0d459360f7c706d2550859560262c232a5b41a0715806ad7d url = "https://conda.anaconda.org/conda-forge/linux-64/ntbtls-0.3.2-hfc55251_0.conda" checksum = "sha256:63184386e34caad02ff05ee9ea84428197131c63ae9b424c8247e2488c0b5673" -[conda-packages.linux-x64."readline-8.3-h853b02a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda" -checksum = "sha256:12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002" +[conda-packages.linux-x64."readline-8.3-hd6e31c0_1"] +url = "https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-hd6e31c0_1.conda" +checksum = "sha256:01b3fe073a66e321970d09e04b388708f8cbdca5cdfbfcb7c9eeb470ad10383d" -[conda-packages.linux-x64."sqlite-3.53.4-h04a0ce9_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.4-h04a0ce9_0.conda" -checksum = "sha256:1f6c9638d64c51a35769219cc895e49af5cd0615aef896604c5472bc79b980f7" +[conda-packages.linux-x64."sqlite-3.53.4-h9ffa6c4_1"] +url = "https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.4-h9ffa6c4_1.conda" +checksum = "sha256:b01812eff4e950a73933cb3dc14647a97ee377c7fab4858495b80a749ebfbf8b" -[conda-packages.linux-x64."sysroot_linux-64-2.39-hc4b9eeb_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.39-hc4b9eeb_6.conda" -checksum = "sha256:7d235e4337f122f3439d0196e1c1c6e715a5b88fcbf24f944510186c84168e45" +[conda-packages.linux-x64."sysroot_linux-64-2.28-h4ee821c_9"] +url = "https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda" +checksum = "sha256:c47299fe37aebb0fcf674b3be588e67e4afb86225be4b0d452c7eb75c086b851" [conda-packages.linux-x64.tzdata-2026c-h151e31d_0] url = "https://conda.anaconda.org/conda-forge/noarch/tzdata-2026c-h151e31d_0.conda" @@ -404,125 +408,125 @@ checksum = "sha256:8ec22f0ba25cbfc2e64d70cf29459eccd7ffdf6436f6a6ff15bbfef799f7d url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" checksum = "sha256:0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6" -[conda-packages.macos-arm64."cctools-1030.6.3-llvm22_1_hbe26303_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm22_1_hbe26303_4.conda" -checksum = "sha256:a8d8f9a6ae4c149d2174f8f52c61da079cc793b87e2f76441a43daf7f394631f" +[conda-packages.macos-arm64."cctools-1030.6.3-llvm23_1_h54b4f4b_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools-1030.6.3-llvm23_1_h54b4f4b_6.conda" +checksum = "sha256:5d3b24d769c70de6a8d2169936b50794008b8a8aacced77e954f694c2b37343e" -[conda-packages.macos-arm64."cctools_impl_osx-arm64-1030.6.3-llvm22_1_hb5e89dc_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm22_1_hb5e89dc_4.conda" -checksum = "sha256:97075a1afeac8a7a4dca258ac10efb70638e3c734cbf5a6328ca1e0718e09c41" +[conda-packages.macos-arm64."cctools_impl_osx-arm64-1030.6.3-llvm23_1_hf5e010b_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/cctools_impl_osx-arm64-1030.6.3-llvm23_1_hf5e010b_6.conda" +checksum = "sha256:e917665c2f89249598c12562c81b6536e40ac30563b2bfbe1f4a9f506bffc967" -[conda-packages.macos-arm64."clang-22-22.1.6-default_hd632d02_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-22-22.1.6-default_hd632d02_1.conda" -checksum = "sha256:95784fe69f588cf8be808fc26149e8b0c5b63c078ba6dad10ef91425bcf5db5f" +[conda-packages.macos-arm64."clang-23-23.1.2-default_h8f9c3af_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-23-23.1.2-default_h8f9c3af_0.conda" +checksum = "sha256:b48232891a6df9c7f0e05a058a660ecf830e3bd11a3e3640d2b452ffb25414b9" -[conda-packages.macos-arm64."clang-22.1.6-default_cfg_hb78b91e_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-22.1.6-default_cfg_hb78b91e_1.conda" -checksum = "sha256:2b0ffddcad6016e6356e5f0cf6e1f9fe280dfc7dd144e541ce4d1d313ea973bc" +[conda-packages.macos-arm64."clang-23.1.2-default_cfg_h870b8d9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-23.1.2-default_cfg_h870b8d9_0.conda" +checksum = "sha256:a5676921e47783b3ce47e9fe8a98f4516c3d46c84072bc2ff87af82e05f92159" -[conda-packages.macos-arm64."clang-scan-deps-22.1.6-default_h8e162e0_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-22.1.6-default_h8e162e0_1.conda" -checksum = "sha256:1c39e8e92c9f73432c172433449580ac897e30d06f3625354ae2519017da798a" +[conda-packages.macos-arm64."clang-scan-deps-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:99a684bc5eb5348de9b78dd57af40dd6d91e85ec241f6e753611dcea1762ba32" -[conda-packages.macos-arm64."clang_impl_osx-arm64-22.1.6-default_h17d1ed9_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-22.1.6-default_h17d1ed9_1.conda" -checksum = "sha256:6e3147a8836b4a65979efdede46e649ea3db1f68a08fac58cb8fbff24c4f1b17" +[conda-packages.macos-arm64."clang_impl_osx-arm64-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang_impl_osx-arm64-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:d814ce43960d9e1144e50162c25a3610dddc8ae2963375d6f0ab7dcccaaa57d8" -[conda-packages.macos-arm64."clangxx_impl_osx-arm64-22.1.6-default_h17d1ed9_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-22.1.6-default_h17d1ed9_1.conda" -checksum = "sha256:94748f8d36c364e765e5d85fc5bbb34819f9cc455113d22ff7989a0d8c59eae1" +[conda-packages.macos-arm64."clangxx_impl_osx-arm64-23.1.2-default_hdadafb6_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-23.1.2-default_hdadafb6_0.conda" +checksum = "sha256:2f060fb6442b53a4b8f0b04993e6b4e5e2b32ae9ea7a79e828104b5243961b27" -[conda-packages.macos-arm64."compiler-rt-22.1.6-hce30654_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-22.1.6-hce30654_0.conda" -checksum = "sha256:149e12bebeab294788e9315b7c28af2588cfe885901deb35a948c147b62dbb61" +[conda-packages.macos-arm64."compiler-rt-23.1.2-hce30654_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-23.1.2-hce30654_0.conda" +checksum = "sha256:7a5a154f6794e35fc4e2b53d997b262f1c1949e5b983fbbf724587467adef20b" -[conda-packages.macos-arm64."compiler-rt22-22.1.6-hd34ed20_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt22-22.1.6-hd34ed20_0.conda" -checksum = "sha256:1156047c7d6145aad7532935346a13985d2496ca0b280702d9fb2d5614d4a551" +[conda-packages.macos-arm64."compiler-rt23-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt23-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:7791feae7141a9d807e2d000677a1f027dfee206898dcebfc985ae933102a1d3" -[conda-packages.macos-arm64."compiler-rt22_osx-arm64-22.1.6-h7e67a1e_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_osx-arm64-22.1.6-h7e67a1e_0.conda" -checksum = "sha256:49dd3a39f82703d308421cdd5e7896e87cf39f7bdfd8bf1fa43abc31e047fcaf" +[conda-packages.macos-arm64."compiler-rt23_osx-arm64-23.1.2-hb8825d9_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_osx-arm64-23.1.2-hb8825d9_0.conda" +checksum = "sha256:a3f20ea42e1c99dfb4188c39c464d709280b7dfde181f5d8bc949ced6806fc5e" -[conda-packages.macos-arm64."compiler-rt_osx-arm64-22.1.6-hce30654_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-22.1.6-hce30654_0.conda" -checksum = "sha256:11b1934e9c8d685a2b2ff0d83a02e9a24a741551bd7c25a7b3a14a3cc87bf185" +[conda-packages.macos-arm64."compiler-rt_osx-arm64-23.1.2-hce30654_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-23.1.2-hce30654_0.conda" +checksum = "sha256:164fd5db9accf2c630f9bebe2c1b4ecb411080e5b0702e6b1b485dbed7560487" [conda-packages.macos-arm64."icu-78.3-py310h579977c_2"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda" checksum = "sha256:6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43" -[conda-packages.macos-arm64."ld64-956.6-llvm22_1_h5b97f1b_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm22_1_h5b97f1b_4.conda" -checksum = "sha256:405f08540aedb58fa070b097143b3fe0fcb2b92e3b4aca723780e2f3d754803b" +[conda-packages.macos-arm64."ld64-956.6-llvm23_1_hd841b0c_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64-956.6-llvm23_1_hd841b0c_6.conda" +checksum = "sha256:aa34de810767f7d92721aeab004479672853f2fb9235a3e9c350db41c0c86112" -[conda-packages.macos-arm64."ld64_osx-arm64-956.6-llvm22_1_h692d5aa_4"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm22_1_h692d5aa_4.conda" -checksum = "sha256:e4ae2ef85672c094aa3467d466f932ccdc1dda9bd4adac64f4252cc796149091" +[conda-packages.macos-arm64."ld64_osx-arm64-956.6-llvm23_1_hc8058f9_6"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-956.6-llvm23_1_hc8058f9_6.conda" +checksum = "sha256:857ab8bf793d29a4d94af0c9eb536d1bb5a56ab9c4b5fb7a4100b24c35e96446" [conda-packages.macos-arm64."libassuan-3.0.2-h286801f_0"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libassuan-3.0.2-h286801f_0.conda" checksum = "sha256:0d8ec81850417d106df2cd4d4cb21e1597c8ce9a930bc86857ea504eb8e08dd4" -[conda-packages.macos-arm64."libclang-cpp22.1-22.1.6-default_h8e162e0_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp22.1-22.1.6-default_h8e162e0_1.conda" -checksum = "sha256:bfd6801f6b347f7a7d27f13d7cd8377520eb488399ce9a808f970afa041da3b5" +[conda-packages.macos-arm64."libclang-cpp23.1-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:7a176b6dda75f39184cc96b548fa436581451547bb185c610627a9b6dca05ca8" -[conda-packages.macos-arm64."libclang13-22.1.6-default_h6dd9417_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-22.1.6-default_h6dd9417_1.conda" -checksum = "sha256:94ba07bf83a5fbc561dc8afa8dbefc4bc0ce2499b71d78473ad55de65cc21586" +[conda-packages.macos-arm64."libclang13-23.1.2-default_h8f9c3af_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda" +checksum = "sha256:8fd0a585f9f4701a991ddf311aeb315c402783aa5b21c24b14b4034eb8cc3f20" -[conda-packages.macos-arm64."libcompiler-rt-22.1.6-hd34ed20_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-22.1.6-hd34ed20_0.conda" -checksum = "sha256:f626060e2a9e75845f5894fd9f4e5d21910dc9eab59f3ea6e427c7b8e305e9d6" +[conda-packages.macos-arm64."libcompiler-rt-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcompiler-rt-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:5bce0c59f2744e16bb106126d9c0d5b976d3bc6527b13003c35e7fc88781c0ff" -[conda-packages.macos-arm64."libcxx-22.1.8-h55c6f16_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda" -checksum = "sha256:a2e7abab5add9750fab064c024394de48e49f97631c605ad5db5c8ac3fc769ef" +[conda-packages.macos-arm64."libcxx-23.1.2-h55c6f16_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.2-h55c6f16_0.conda" +checksum = "sha256:087a610bacee7901d259ef72c6f060d795ab26831bd7541ba75ced786a5a63f9" -[conda-packages.macos-arm64."libcxx-devel-22.1.8-h6dc3340_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-22.1.8-h6dc3340_0.conda" -checksum = "sha256:e734ac1ed426d09363d242674a286dc004f041ad1167e73912e11d3634cee09d" +[conda-packages.macos-arm64."libcxx-devel-23.1.2-h6dc3340_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-devel-23.1.2-h6dc3340_0.conda" +checksum = "sha256:4b125b5cd6e93b96e6dfd4901da800298ce9297d9fbd7d3bd864c76865818f03" -[conda-packages.macos-arm64."libcxx-headers-22.1.8-h707e725_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-22.1.8-h707e725_0.conda" -checksum = "sha256:0b9853ca0d29729488519ab5c61401b1ade22b15841dae8bf299e6980fe1c964" +[conda-packages.macos-arm64."libcxx-headers-23.1.2-h707e725_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-23.1.2-h707e725_0.conda" +checksum = "sha256:8f2231b686519f3779b639cc1de0c9a9f4926265056a3c356767bb605c0437a2" -[conda-packages.macos-arm64."libgcrypt-1.12.2-hce30654_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-1.12.2-hce30654_0.conda" -checksum = "sha256:07eeb66304ef142b988a7e7f4b3d474fe17aff12fddc65ff311c8e64202380f2" +[conda-packages.macos-arm64."libgcrypt-1.12.2-hce30654_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-1.12.2-hce30654_2.conda" +checksum = "sha256:2512a5201146cbe4abccc6e7a7a46bd98424013b5c19363d8204e91c11b0e39a" -[conda-packages.macos-arm64."libgcrypt-devel-1.12.2-h84a0fba_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-devel-1.12.2-h84a0fba_0.conda" -checksum = "sha256:fe42892cea60e4d3e691ea6a4ba9912e545cccd9fedf1c7ae47811b5ac38838b" +[conda-packages.macos-arm64."libgcrypt-devel-1.12.2-hb001647_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-devel-1.12.2-hb001647_2.conda" +checksum = "sha256:2fe60bf669bac3f2d36ea70d78418f71b45afe6ba5d5bb3b4a50b6f2e42e97b4" -[conda-packages.macos-arm64."libgcrypt-lib-1.12.2-h84a0fba_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-lib-1.12.2-h84a0fba_0.conda" -checksum = "sha256:19d7ba7fc7556996ae2f549233110123f0c24408568d7aa89871deeea0835294" +[conda-packages.macos-arm64."libgcrypt-lib-1.12.2-hb001647_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-lib-1.12.2-hb001647_2.conda" +checksum = "sha256:45b1b91ff0b7dcfb2d31ffcdc156be2cb93998d80764f9a1f4bbd6a51e5a318a" -[conda-packages.macos-arm64."libgcrypt-tools-1.12.2-h84a0fba_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-tools-1.12.2-h84a0fba_0.conda" -checksum = "sha256:60c30e25e10f259b7565ff9b6c925ca1933284c307fde8ac666b11fa347a8614" +[conda-packages.macos-arm64."libgcrypt-tools-1.12.2-hb001647_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-tools-1.12.2-hb001647_2.conda" +checksum = "sha256:6e972ad2159b0f0f8bfec35814b5b736cbf8aec32c666346074d8eb9f7cca8a5" [conda-packages.macos-arm64."libgpg-error-1.61-h784d473_2"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgpg-error-1.61-h784d473_2.conda" checksum = "sha256:eb84229d2ac791a4241044dc3ad172389beb4a730cc4a2afb1ddbe51e8233d11" -[conda-packages.macos-arm64."libiconv-1.18-h23cfdf5_2"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda" -checksum = "sha256:de0336e800b2af9a40bdd694b03870ac4a848161b35c8a2325704f123f185f03" +[conda-packages.macos-arm64."libiconv-1.18-he4c29f2_3"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda" +checksum = "sha256:689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f" -[conda-packages.macos-arm64."libintl-0.25.1-h493aca8_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda" -checksum = "sha256:99d2cebcd8f84961b86784451b010f5f0a795ed1c08f1e7c76fbb3c22abf021a" +[conda-packages.macos-arm64."libintl-0.25.1-hae62183_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-hae62183_2.conda" +checksum = "sha256:b43c6645e668f86d04d5c06d6dc17efe921bbd9244be4b77946d56fb950a3fcc" [conda-packages.macos-arm64."libksba-1.6.7-h00cdb27_0"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libksba-1.6.7-h00cdb27_0.conda" checksum = "sha256:1fb2da81dd151baf940bfb90b9bfe8b14a57ab75d28b95fd5adde89e14b8b288" -[conda-packages.macos-arm64."libllvm22-22.1.6-h89af1be_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.6-h89af1be_0.conda" -checksum = "sha256:e1ca362a1ee853c54547e609459a900d098781ba74651639577375d2e95fe225" +[conda-packages.macos-arm64."libllvm23-23.1.2-h759d1ac_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.2-h759d1ac_0.conda" +checksum = "sha256:9717b7ae514600cebeb43ea89bf008bef6e96fbbefa1dda40843c394f2b6a46e" [conda-packages.macos-arm64."liblzma-5.8.3-h8088a28_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda" @@ -532,33 +536,33 @@ checksum = "sha256:23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4 url = "https://conda.anaconda.org/conda-forge/osx-arm64/libsigtool-0.1.3-h98dc951_1.conda" checksum = "sha256:fcfa03afe31f40dfabf011629d99836adbebbc3ed1b38c7e9eee9ffc7581975b" -[conda-packages.macos-arm64."libsqlite-3.53.4-h1ae2325_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h1ae2325_0.conda" -checksum = "sha256:745662565e103f290e9dc4263bbd88285082f8cf699854fe2d5f1e35a4a0d326" +[conda-packages.macos-arm64."libsqlite-3.53.4-hca69786_1"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-hca69786_1.conda" +checksum = "sha256:839b31d4830e896b4d315b551d27f2bb08026bc946df04bcc360d8627c3ba2cd" -[conda-packages.macos-arm64."libxml2-16-2.15.3-h6967ea9_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h6967ea9_0.conda" -checksum = "sha256:43895a7517c055b8893531290f9dc48bd751eb04be04f14bbce3b6c71b052be6" +[conda-packages.macos-arm64."libxml2-16-2.15.4-heb56d2d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda" +checksum = "sha256:8a26f7c94ab849c1930da36c298f4b82e892382b70ae865cd7274188d9d783e2" -[conda-packages.macos-arm64."libxml2-2.15.3-heed7d32_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.3-heed7d32_0.conda" -checksum = "sha256:4d9c117b2dd222cf891710d5f6a570ebb275479979843a1477ac54ed50907b40" +[conda-packages.macos-arm64."libxml2-2.15.4-h550178d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda" +checksum = "sha256:81217fcd4d4abdc69ee63cdb9cdb22e05a20b9ba7a76f596579914a838fe5960" [conda-packages.macos-arm64."libzlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda" checksum = "sha256:a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef9d7" -[conda-packages.macos-arm64."llvm-openmp-22.1.8-hc7d1edf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-22.1.8-hc7d1edf_0.conda" -checksum = "sha256:ccbaad6bbc88f135ab849bc36af5fa6eda36a9ed18ce6f58e3dde3d11784c156" +[conda-packages.macos-arm64."llvm-openmp-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:f9aea67117079c00b9663ee0bbca7e5409dbe94625c34e68881ce2c97c3d47c9" -[conda-packages.macos-arm64."llvm-tools-22-22.1.6-hb545844_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22-22.1.6-hb545844_0.conda" -checksum = "sha256:c779d3da14aa39091afeb7444489a69b4e843807284af9bcdff571376319b941" +[conda-packages.macos-arm64."llvm-tools-23-23.1.2-h79441dc_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-23-23.1.2-h79441dc_0.conda" +checksum = "sha256:52f1824ca1de2d034764225c275928e38ca61094d8080d7407175ab06ac408e2" -[conda-packages.macos-arm64."llvm-tools-22.1.6-hd34ed20_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-22.1.6-hd34ed20_0.conda" -checksum = "sha256:06e88f1fb0385642c2ae6bf7faf442dfe8edffe8d5a04747cc230ed1183bedbb" +[conda-packages.macos-arm64."llvm-tools-23.1.2-hdb3d66b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-23.1.2-hdb3d66b_0.conda" +checksum = "sha256:2911fe5dad062b513f572d317fbc7ef1e94f177cac63db01bbb1d4278e707996" [conda-packages.macos-arm64."ncurses-6.6-he64c551_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-he64c551_1.conda" @@ -572,25 +576,25 @@ checksum = "sha256:e6f12cee635860a2f70dc40ad28d20d80cdabf566dfab2db1ca0489b1fb89 url = "https://conda.anaconda.org/conda-forge/osx-arm64/ntbtls-0.3.2-h1059232_0.conda" checksum = "sha256:3b2343fb4120dd864ceb050123a84943c4cce3f65c0d010d82950af873d6e3f0" -[conda-packages.macos-arm64."openssl-3.6.3-hd24854e_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.3-hd24854e_1.conda" -checksum = "sha256:66be2283b5b37dcda1332b5e74c1782a8cb14fd2e62e0d38017c2d35bf73c119" +[conda-packages.macos-arm64."openssl-3.6.4-h55eecbc_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.4-h55eecbc_0.conda" +checksum = "sha256:f23239eacd75c4c50705e68fae1aa3292da473e6a3a4abe2330f1e6afa680704" -[conda-packages.macos-arm64."readline-8.3-h46df422_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda" -checksum = "sha256:a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477" +[conda-packages.macos-arm64."readline-8.3-h8b90a29_1"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda" +checksum = "sha256:d6782b430e6dce4fe8c7ac118cd988d5a193eb4a7f60741edfaede58016b6110" [conda-packages.macos-arm64."sigtool-codesign-0.1.3-h98dc951_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-codesign-0.1.3-h98dc951_1.conda" checksum = "sha256:7efd6d7d18bf9cc5788bfe1c1e1620d9dbbe00a81c646814929a82ff31944cf3" -[conda-packages.macos-arm64."sqlite-3.53.4-h77b7338_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/sqlite-3.53.4-h77b7338_0.conda" -checksum = "sha256:fffebc6bbe45dd4462d3a701a0426c224ad75f8d8bcd174860d7f1b277d4ef45" +[conda-packages.macos-arm64."sqlite-3.53.4-ha9f7ffe_1"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/sqlite-3.53.4-ha9f7ffe_1.conda" +checksum = "sha256:4e0c8704a29b6c265e7bdb6508e1d4180570adcc6e031daf182578d3777fb8b1" -[conda-packages.macos-arm64."tapi-1600.0.11.8-hb561403_3"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_3.conda" -checksum = "sha256:9f1cc109e6e57861110e9de6e03beca7fd2b7fbdb46124cccc07990b0844d88a" +[conda-packages.macos-arm64."tapi-1600.0.11.8-hb561403_4"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1600.0.11.8-hb561403_4.conda" +checksum = "sha256:6effea9587f049e702c838e8e57d98ac92b89ca1f3f1edd51c78dd252d24e83b" [conda-packages.macos-arm64."zlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda" @@ -608,121 +612,121 @@ checksum = "sha256:4ed83961876dc8844a6f0df49c07b408efbaea275ffb0b37133e24c006990 url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" checksum = "sha256:0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6" -[conda-packages.macos-x64."cctools-1030.6.3-llvm22_1_h0a1bb1c_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm22_1_h0a1bb1c_4.conda" -checksum = "sha256:e0b732ed52bcfa98f90fe61ef87fc47cb39222351ab2e730c05f262d29621b51" +[conda-packages.macos-x64."cctools-1030.6.3-llvm23_1_h254e556_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/cctools-1030.6.3-llvm23_1_h254e556_6.conda" +checksum = "sha256:386336eab60ff2cbd2dbd510c015400b7d9f6263411c0297860e508261c68ed6" -[conda-packages.macos-x64."cctools_impl_osx-64-1030.6.3-llvm22_1_h8fe25a2_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm22_1_h8fe25a2_4.conda" -checksum = "sha256:9e003c254b6c1880e6c8f2d777b20d837db2b7aff161454d857693692fd862dd" +[conda-packages.macos-x64."cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6.conda" +checksum = "sha256:318a4ce9253a4808283b35dd09e1db36e07751a1a4ce1dc00312b00ae932e3c8" -[conda-packages.macos-x64."clang-22-22.1.6-default_h3b8fe2e_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-22-22.1.6-default_h3b8fe2e_1.conda" -checksum = "sha256:fe40246c1af697249af19b5b25e93d37fed118f2aebdcf7542e3a79a976f9f22" +[conda-packages.macos-x64."clang-23-23.1.2-default_h3065a3b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-23-23.1.2-default_h3065a3b_0.conda" +checksum = "sha256:b845ff3a9f3725face10ccf56582405fe5d4e97d4679f33bcc2892f4e4c55930" -[conda-packages.macos-x64."clang-22.1.6-default_cfg_h93fe8ef_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-22.1.6-default_cfg_h93fe8ef_1.conda" -checksum = "sha256:3e9f34a8f118169fe3c0a0236cc86baf15cdb574e7a3a3972e63618f09062a32" +[conda-packages.macos-x64."clang-23.1.2-default_cfg_hcbdff81_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-23.1.2-default_cfg_hcbdff81_0.conda" +checksum = "sha256:02e2cf73af313219166452f98befa873c6109555a21856af18e056955a4e5df9" -[conda-packages.macos-x64."clang-scan-deps-22.1.6-default_h9399c5b_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-22.1.6-default_h9399c5b_1.conda" -checksum = "sha256:ce83de90eef2cf62f8895774456a0ab68b6e358e6515b12dd1787d8117bd9c8c" +[conda-packages.macos-x64."clang-scan-deps-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:a587f276042f1ca56da7fd6f7e13db7d4da22d5b6c05d8bf7f38301c91971e4b" -[conda-packages.macos-x64."clang_impl_osx-64-22.1.6-default_he9bf3b8_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-22.1.6-default_he9bf3b8_1.conda" -checksum = "sha256:14e1a84bb3a345f51e18b626159c6e8114837642f45255b81653591694334510" +[conda-packages.macos-x64."clang_impl_osx-64-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang_impl_osx-64-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:c55b59c17a59de3bfd0eddacf2c6179940b882a47bafbdc9d42cdab473f10584" -[conda-packages.macos-x64."clangxx_impl_osx-64-22.1.6-default_he9bf3b8_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-22.1.6-default_he9bf3b8_1.conda" -checksum = "sha256:bbd449dc3392dc379e1aa6f083bf6304b3b37947534cad786f609341eb6a216b" +[conda-packages.macos-x64."clangxx_impl_osx-64-23.1.2-default_hf9996f3_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-23.1.2-default_hf9996f3_0.conda" +checksum = "sha256:a48098c2e05b661efbd3293f3c46962aa518cce4738d7e55f3fe22deecc510a6" -[conda-packages.macos-x64."compiler-rt-22.1.6-h694c41f_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-22.1.6-h694c41f_0.conda" -checksum = "sha256:af268e3ce7ec453da3fd8d872d47526dce1f294302c7b0a9f0c48c9a4b421613" +[conda-packages.macos-x64."compiler-rt-23.1.2-h694c41f_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-23.1.2-h694c41f_0.conda" +checksum = "sha256:be8fe7a2c142b10f4bb88b01f6e8b8691069c297a13ac34f14113ad7f94efaf7" -[conda-packages.macos-x64."compiler-rt22-22.1.6-h1637cdf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt22-22.1.6-h1637cdf_0.conda" -checksum = "sha256:dbb939a84124dfc70f68f1daf5c064bb21f4c6b3c76bd90d8bda2de5870e5194" +[conda-packages.macos-x64."compiler-rt23-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/compiler-rt23-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:c05f82f29f66254a3f3f391d8d73beed669e22932358065939700b070fd07de7" -[conda-packages.macos-x64."compiler-rt22_osx-64-22.1.6-hcf80936_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_osx-64-22.1.6-hcf80936_0.conda" -checksum = "sha256:286e3cc2a812a5559701b659fc80ffc6ddc65a9f1e720a35ab8adb27bbb7ebd1" +[conda-packages.macos-x64."compiler-rt23_osx-64-23.1.2-h8d5f570_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_osx-64-23.1.2-h8d5f570_0.conda" +checksum = "sha256:a3ca596feee730ef98015a6c9d6f55749e8634c01c17e7eb2acef8b13b7af483" -[conda-packages.macos-x64."compiler-rt_osx-64-22.1.6-h694c41f_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-22.1.6-h694c41f_0.conda" -checksum = "sha256:0a3e8b4e26f172a1abb1ede7030ed9c7f89bf9a3b891abd0f6d8fc90ed21d2df" +[conda-packages.macos-x64."compiler-rt_osx-64-23.1.2-h694c41f_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-23.1.2-h694c41f_0.conda" +checksum = "sha256:101d620216e883738286ffd860764cf688161bfce223495d5e9387838a279b70" -[conda-packages.macos-x64."ld64-956.6-llvm22_1_hc399b6d_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm22_1_hc399b6d_4.conda" -checksum = "sha256:a4ac125329e14d407ecb2c074412a0af6f78256989db82d83c4a02e93912c88e" +[conda-packages.macos-x64."ld64-956.6-llvm23_1_h0b736ef_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/ld64-956.6-llvm23_1_h0b736ef_6.conda" +checksum = "sha256:11a6c36fd6207683a57d5e91533d3ce1756c1fc7e2a30504de8686ac867a8f0b" -[conda-packages.macos-x64."ld64_osx-64-956.6-llvm22_1_h163eae7_4"] -url = "https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm22_1_h163eae7_4.conda" -checksum = "sha256:e49272192003e0e30edd6877197db3c220bb374a78d5b255d18c7a029cd33c1e" +[conda-packages.macos-x64."ld64_osx-64-956.6-llvm23_1_h484b24f_6"] +url = "https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-956.6-llvm23_1_h484b24f_6.conda" +checksum = "sha256:36c603caf2a7f65ae9f0ce4acbf7afde49357bdcea65b28ca7aefd9cf46c1f5a" [conda-packages.macos-x64."libassuan-3.0.2-h240833e_0"] url = "https://conda.anaconda.org/conda-forge/osx-64/libassuan-3.0.2-h240833e_0.conda" checksum = "sha256:90af38135168c54a1fd4a3adbb0b0d7fd36d53cf575e263ff5227adeca423011" -[conda-packages.macos-x64."libclang-cpp22.1-22.1.6-default_h9399c5b_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp22.1-22.1.6-default_h9399c5b_1.conda" -checksum = "sha256:776d49dc3e0da85461fdffa69e3a06691148f6cdcf2eb17062dadf9503535d83" +[conda-packages.macos-x64."libclang-cpp23.1-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:491c85fac38f91060802761e59e3a1505ee738ed2849504e8d0f3ecf0c520537" -[conda-packages.macos-x64."libclang13-22.1.6-default_h2429e1b_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libclang13-22.1.6-default_h2429e1b_1.conda" -checksum = "sha256:08c80e3ab908d4310c4dcc3274d48ffee7036d6a02787f52d9d1cf07d977b96f" +[conda-packages.macos-x64."libclang13-23.1.2-default_h3065a3b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda" +checksum = "sha256:0dfe44aa4d56eae2ac5832a611ce1167d44ff17181c85596de01e149c04af01c" -[conda-packages.macos-x64."libcompiler-rt-22.1.6-h1637cdf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-22.1.6-h1637cdf_0.conda" -checksum = "sha256:e0aac5f20751e06480899382fe7d1bbd858309669085aacf59bf32faccae5a33" +[conda-packages.macos-x64."libcompiler-rt-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcompiler-rt-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:ff0e2bc0217a46aba323edb4b61dcd29ea333ab344735a93de5f9bf140a34fa8" -[conda-packages.macos-x64."libcxx-22.1.8-h19cb2f5_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.8-h19cb2f5_0.conda" -checksum = "sha256:57ee997f1f800cf38abc743c0f0a9ddfe6a101c697c35510452ce6f4ddf96361" +[conda-packages.macos-x64."libcxx-23.1.2-h19cb2f5_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.2-h19cb2f5_0.conda" +checksum = "sha256:0ad8c788c3681674f100820cf5e76fcc8ec88502e7aa64f4776581985009a7be" -[conda-packages.macos-x64."libcxx-devel-22.1.8-h7c275be_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-22.1.8-h7c275be_0.conda" -checksum = "sha256:34367b5060d38e842e53e7bcb2efe96b0e578593e59842ddfb4453302f6cd899" +[conda-packages.macos-x64."libcxx-devel-23.1.2-h7c275be_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-devel-23.1.2-h7c275be_0.conda" +checksum = "sha256:5e8c3c2ec418e83291d1bc52d055af682f5c66599cbbe222b6b38f2f7d6cb642" -[conda-packages.macos-x64."libcxx-headers-22.1.8-h707e725_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-22.1.8-h707e725_0.conda" -checksum = "sha256:0b9853ca0d29729488519ab5c61401b1ade22b15841dae8bf299e6980fe1c964" +[conda-packages.macos-x64."libcxx-headers-23.1.2-h707e725_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/libcxx-headers-23.1.2-h707e725_0.conda" +checksum = "sha256:8f2231b686519f3779b639cc1de0c9a9f4926265056a3c356767bb605c0437a2" -[conda-packages.macos-x64."libgcrypt-1.12.2-h694c41f_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-1.12.2-h694c41f_0.conda" -checksum = "sha256:266547a3d4af566e7b24fc39eb4bd4cb2d6074d79247b3ed4c2f4c34aebf8629" +[conda-packages.macos-x64."libgcrypt-1.12.2-h694c41f_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-1.12.2-h694c41f_2.conda" +checksum = "sha256:09c2c02626323c23e6245bafc53cf2b3a8774397f7a7f49e5b615a43993ae6f3" -[conda-packages.macos-x64."libgcrypt-devel-1.12.2-ha1e9b39_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-devel-1.12.2-ha1e9b39_0.conda" -checksum = "sha256:8f571edfa5edbcef92860c81da82e9b1a0324fe5986ca3d3581a1fc36e03bddf" +[conda-packages.macos-x64."libgcrypt-devel-1.12.2-hd115831_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-devel-1.12.2-hd115831_2.conda" +checksum = "sha256:55d86f0eb92b21310e5619f1397ef3d24a851181d29fafcaaaabf2aa38a74307" -[conda-packages.macos-x64."libgcrypt-lib-1.12.2-ha1e9b39_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-lib-1.12.2-ha1e9b39_0.conda" -checksum = "sha256:9573ae8561367da50b95c014fddaa10b0f12b3c1206fc971c606a350ed154a86" +[conda-packages.macos-x64."libgcrypt-lib-1.12.2-hd115831_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-lib-1.12.2-hd115831_2.conda" +checksum = "sha256:234e85de6d138ce426133ac36fbfb220448d7c6b688f3f20504ce1c3c24618ab" -[conda-packages.macos-x64."libgcrypt-tools-1.12.2-ha1e9b39_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-tools-1.12.2-ha1e9b39_0.conda" -checksum = "sha256:fa4bd339b58fc0b5d7f992abcde6f13aeabbf55d0fc72a2ada6b6bc761aa57b8" +[conda-packages.macos-x64."libgcrypt-tools-1.12.2-hd115831_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-tools-1.12.2-hd115831_2.conda" +checksum = "sha256:0128042f831879b66cbc3a1a34a78603c3a9eee8198c6c64bae01114720dd476" [conda-packages.macos-x64."libgpg-error-1.61-h2fb4741_2"] url = "https://conda.anaconda.org/conda-forge/osx-64/libgpg-error-1.61-h2fb4741_2.conda" checksum = "sha256:bb0352e979fa32a15233382cdfac5d933b7884e74a9487fe82d1b76aa2b4b4c4" -[conda-packages.macos-x64."libiconv-1.18-h57a12c2_2"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda" -checksum = "sha256:a1c8cecdf9966921e13f0ae921309a1f415dfbd2b791f2117cf7e8f5e61a48b6" +[conda-packages.macos-x64."libiconv-1.18-h4ae439b_3"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda" +checksum = "sha256:2389e03a58ed0f5e8f2469eb4d4ba80d0af378b38854ae5eee65e5b641244082" -[conda-packages.macos-x64."libintl-0.25.1-h3184127_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda" -checksum = "sha256:8c352744517bc62d24539d1ecc813b9fdc8a785c780197c5f0b84ec5b0dfe122" +[conda-packages.macos-x64."libintl-0.25.1-h98e67c8_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h98e67c8_2.conda" +checksum = "sha256:1fad645b88742ad51dbaf9a6709fa9663edd663a4fed6b27c9c4cbc42fa9c514" [conda-packages.macos-x64."libksba-1.6.7-hf036a51_0"] url = "https://conda.anaconda.org/conda-forge/osx-64/libksba-1.6.7-hf036a51_0.conda" checksum = "sha256:cbeb2ae0d4b6e3f2abfcb1ae13c92e84e3cdd87caaad7a7e99e6a80edd35deb1" -[conda-packages.macos-x64."libllvm22-22.1.6-hab754da_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm22-22.1.6-hab754da_0.conda" -checksum = "sha256:b2a76e1c5a2b1d033e4dc554c7c7b0221ce9dad11f25800cbbac87d7e50f2925" +[conda-packages.macos-x64."libllvm23-23.1.2-hd11396f_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.2-hd11396f_0.conda" +checksum = "sha256:f6174a6f25f900bbcebaa6461ad7152937ff5769e6dbec500a385c321e5adbc2" [conda-packages.macos-x64."liblzma-5.8.3-hbb4bfdb_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda" @@ -732,33 +736,33 @@ checksum = "sha256:7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa url = "https://conda.anaconda.org/conda-forge/osx-64/libsigtool-0.1.3-h8c25ef7_1.conda" checksum = "sha256:c3d76ff04ebed64d00a7ff5106297a55af20082a3d3df0ea7dfb235f94ba31c3" -[conda-packages.macos-x64."libsqlite-3.53.4-h77d7759_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-h77d7759_0.conda" -checksum = "sha256:5725d44a17d196adba9798a5fd9f692b7039a827cd6145556a072a80e1931c49" +[conda-packages.macos-x64."libsqlite-3.53.4-ha5db789_1"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_1.conda" +checksum = "sha256:78afe0bf88da66d7df62d39632aa69cb73eb32d923cd1175230ce2978618d9c8" -[conda-packages.macos-x64."libxml2-16-2.15.3-h0d7f165_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h0d7f165_0.conda" -checksum = "sha256:daa69a1dd887b2dbac44327bc5af73a4d41fa63bc6dc609782fdda9aec187895" +[conda-packages.macos-x64."libxml2-16-2.15.4-h341e563_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h341e563_0.conda" +checksum = "sha256:bc284057b85e4a0ecc158598d81c3081fa58e9111969a05d3056ab7a8442c837" -[conda-packages.macos-x64."libxml2-2.15.3-h0712280_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.3-h0712280_0.conda" -checksum = "sha256:caf6e73fa53c3dec3227ea67de231b0f7009544252684e816c6f2f414aeb55c9" +[conda-packages.macos-x64."libxml2-2.15.4-h3668fe6_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-h3668fe6_0.conda" +checksum = "sha256:9cf91223637981568c8fbd5c4dbbc1e6137592e919828554ae436bf259aa91d0" [conda-packages.macos-x64."libzlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda" checksum = "sha256:b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c18e1" -[conda-packages.macos-x64."llvm-openmp-22.1.8-h0d3cbff_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-22.1.8-h0d3cbff_0.conda" -checksum = "sha256:7e8dcf03c2ef5491405d6d86eb892d14e99902f50f4eeb250db0cbdc58dd5818" +[conda-packages.macos-x64."llvm-openmp-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:3c17127e2a94d60a8babef57c66d643374c5b08c896ec5f0987a62ecfb81c8ee" -[conda-packages.macos-x64."llvm-tools-22-22.1.6-hc181bea_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-22-22.1.6-hc181bea_0.conda" -checksum = "sha256:8b5255399c5172ebcb69e3fa3e39697e56cec5039fc604be86f0bfebed43cc7e" +[conda-packages.macos-x64."llvm-tools-23-23.1.2-h36529c3_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23-23.1.2-h36529c3_0.conda" +checksum = "sha256:5c12ec6e2f59444aa38ed1ab778ae3533a9d09b5c9c7c5e97e482dca81e9e08d" -[conda-packages.macos-x64."llvm-tools-22.1.6-h1637cdf_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-22.1.6-h1637cdf_0.conda" -checksum = "sha256:efd2689c68b381794fcbfb1a9e8fda937b27c2d55be1fecac70461ba3da84472" +[conda-packages.macos-x64."llvm-tools-23.1.2-h8c1e6b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-23.1.2-h8c1e6b9_0.conda" +checksum = "sha256:bbf730a23807a089f2c2e9f1d460d03d49919291f97895b3aeb9593f6f0d6309" [conda-packages.macos-x64."ncurses-6.6-hcc0dc9a_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.6-hcc0dc9a_1.conda" @@ -772,25 +776,25 @@ checksum = "sha256:d12c2c6d5e6c4447478a451781f8f3da74844873f7ce4d435a22ff95a93ac url = "https://conda.anaconda.org/conda-forge/osx-64/ntbtls-0.3.2-h2d185b6_0.conda" checksum = "sha256:81e664250100203f32a5b74ad8dd41b906b13d8c0e0efbd8aa6c876c4d962fc2" -[conda-packages.macos-x64."openssl-3.6.3-hc881268_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.3-hc881268_1.conda" -checksum = "sha256:d43abd09a455847108fc821e81cf4e36dba31755263a1313b6f1b538ac218998" +[conda-packages.macos-x64."openssl-3.6.4-h332eb6d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.4-h332eb6d_0.conda" +checksum = "sha256:73d648d24f0994fd8641972848d74bd57b8d80888a64600643e3fe88a1b50545" -[conda-packages.macos-x64."readline-8.3-h68b038d_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda" -checksum = "sha256:4614af680aa0920e82b953fece85a03007e0719c3399f13d7de64176874b80d5" +[conda-packages.macos-x64."readline-8.3-h000c2f7_1"] +url = "https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda" +checksum = "sha256:feb9248a062b7a0738e56339d8c9e87bc9adf8e8c76549fb55b0b2456bec3a57" [conda-packages.macos-x64."sigtool-codesign-0.1.3-h8c25ef7_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/sigtool-codesign-0.1.3-h8c25ef7_1.conda" checksum = "sha256:37aac42f05e21b48a3b61b28ae624ed5a3d2acfcbaabf2cd10ef7762c4fb4c45" -[conda-packages.macos-x64."sqlite-3.53.4-hd4d344e_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.53.4-hd4d344e_0.conda" -checksum = "sha256:f791a0485dc7ed05e1ba7230149d2922427777370c74e98df6384b0f73216582" +[conda-packages.macos-x64."sqlite-3.53.4-hdea7a7b_1"] +url = "https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.53.4-hdea7a7b_1.conda" +checksum = "sha256:eada66c9946b1feaff5c50b63902305836f09532a71ccf6461e73dc75b28018e" -[conda-packages.macos-x64."tapi-1600.0.11.8-h44950e2_3"] -url = "https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_3.conda" -checksum = "sha256:ec381e40cf1caf8496265bbf14ca0d2cb947495cd3e9069947e2fa75f7de7b3b" +[conda-packages.macos-x64."tapi-1600.0.11.8-h44950e2_4"] +url = "https://conda.anaconda.org/conda-forge/osx-64/tapi-1600.0.11.8-h44950e2_4.conda" +checksum = "sha256:045e62838ec78ad75974552ebeeccbee5a4a843272da47c7a67e99fd9cc25d8d" [conda-packages.macos-x64."zlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda" @@ -800,29 +804,49 @@ checksum = "sha256:d46ba65a5ebcb4f682f9f0f21943c427eb56e7f9d15aeab8b823294c787db url = "https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda" checksum = "sha256:5277886d9704a624dc9b79ac985861e1e431bdb39a57c082507ab577a138ec6c" -[conda-packages.windows-x64."clang-22-22.1.6-default_hac490eb_1"] -url = "https://conda.anaconda.org/conda-forge/win-64/clang-22-22.1.6-default_hac490eb_1.conda" -checksum = "sha256:9848469fd46e5ecfb3966006a7a47c8383b3799c1385c58a562d3038625ac0e5" +[conda-packages.windows-x64."clang-23-23.1.2-default_hacd6ee9_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/clang-23-23.1.2-default_hacd6ee9_0.conda" +checksum = "sha256:656a751d20af0b1007fee20c19138deae20f9eeb8c5d0c9610df1bcf1c4cca47" + +[conda-packages.windows-x64."clang-23.1.2-default_nocfg_h59757e6_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/clang-23.1.2-default_nocfg_h59757e6_0.conda" +checksum = "sha256:5cc2e7f6e90e682af16c67caa3e8dc98da484d1e118deaea1644dd8061819c55" + +[conda-packages.windows-x64."compiler-rt23-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/compiler-rt23-23.1.2-h49e36cd_0.conda" +checksum = "sha256:c35bfe3bf40dc8b28ae9f1c0e23e7ca1302746a03d909547c81745a38aa5d3be" + +[conda-packages.windows-x64."compiler-rt23_win-64-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt23_win-64-23.1.2-h49e36cd_0.conda" +checksum = "sha256:41059149e766110b8bbe792a81bfad41f259e4e554cc585f1de3d2dd3095737d" -[conda-packages.windows-x64."clang-22.1.6-default_nocfg_hbb9487a_1"] -url = "https://conda.anaconda.org/conda-forge/win-64/clang-22.1.6-default_nocfg_hbb9487a_1.conda" -checksum = "sha256:b9c053ee84d2ec9cfc36923b48af06e145d906378575d0156edfeb02e4ef3d81" +[conda-packages.windows-x64."icu-78.3-h5112557_2"] +url = "https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda" +checksum = "sha256:75c549b55b673e15de8785a8e5dd85bca7eb612eee0ff4dc8d7bdaa15eacbdbb" -[conda-packages.windows-x64."compiler-rt22-22.1.6-h49e36cd_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/compiler-rt22-22.1.6-h49e36cd_0.conda" -checksum = "sha256:bb1cfb3ce4317c468154b69321864be5994961f479c8d9655618f6acd4a14941" +[conda-packages.windows-x64."libiconv-1.18-hc1393d2_3"] +url = "https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda" +checksum = "sha256:35e04e3ddac7720fc7c550a1c9f998604299d6a7bd1f3ec9b2825d825061daa2" -[conda-packages.windows-x64."compiler-rt22_win-64-22.1.6-h49e36cd_0"] -url = "https://conda.anaconda.org/conda-forge/noarch/compiler-rt22_win-64-22.1.6-h49e36cd_0.conda" -checksum = "sha256:fdc6fe0b23b396f33b478b8e890cef0b624cc2c6f96e1ac26ad2289dea4eeb12" +[conda-packages.windows-x64."liblzma-5.8.3-hfd05255_1"] +url = "https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda" +checksum = "sha256:d36c4a1e1f80fd08e18a407e03622ff2f34dfdd022da6488ad19603dea19e6d5" + +[conda-packages.windows-x64."libxml2-16-2.15.4-h3cfd58e_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda" +checksum = "sha256:9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac" + +[conda-packages.windows-x64."libxml2-2.15.4-he095d88_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda" +checksum = "sha256:a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88" [conda-packages.windows-x64."libzlib-1.3.2-hfd05255_3"] url = "https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda" checksum = "sha256:0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527" -[conda-packages.windows-x64."llvm-openmp-22.1.8-h4fa8253_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.8-h4fa8253_0.conda" -checksum = "sha256:50c02902bb516eeb56680358f052be38b5bf74b40e78ea4b2a675e84957e7307" +[conda-packages.windows-x64."llvm-openmp-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda" +checksum = "sha256:8b462c021d6bf3f956749d305bd3f52deb82ae2901047c0c7061a21c3550e48f" [conda-packages.windows-x64."ucrt-10.0.26100.0-h57928b3_0"] url = "https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda" @@ -858,302 +882,314 @@ checksum = "sha256:6ff270c9bf07d2bec5c98aa324eb7c4daf6a1a4d815c05ff1708049616047 url = "https://github.com/rui314/mold/releases/download/v2.42.1/mold-2.42.1-x86_64-linux.tar.gz" url_api = "https://api.github.com/repos/rui314/mold/releases/assets/557036001" +[tools."aqua:rui314/mold"."platforms.windows-x64"] +checksum = "sha256:ce38c5d5d6a5169e05883d598592b367976a9575abfafcdc49889fcc788b51c0" +url = "https://github.com/rui314/mold/releases/download/v2.42.1/mold-2.42.1-x86_64-windows.zip" +url_api = "https://api.github.com/repos/rui314/mold/releases/assets/557036000" + [[tools."conda:clangxx"]] -version = "22.1.6" +version = "23.1.2" backend = "conda:clangxx" [tools."conda:clangxx".options] channel = "conda-forge" [tools."conda:clangxx"."platforms.linux-arm64"] -checksum = "sha256:be625f0270932aff83beda275bb5a6f537ffee6a671598118c8653edb17c7c32" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clangxx-22.1.6-default_cfg_he76a859_1.conda" +checksum = "sha256:6788990a67026d5e705c004ec5b1519383fbaed0b2ea99f3ee90eb3561e836d4" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clangxx-23.1.2-default_cfg_ha4cb187_0.conda" conda_deps = [ - "clangxx_impl_linux-aarch64-22.1.6-default_h1168dbd_1", - "clang-22.1.6-default_cfg_h99ebb92_1", - "clang_impl_linux-aarch64-22.1.6-default_h1168dbd_1", - "clang-scan-deps-22.1.6-default_h2a92e99_1", - "clang-22-22.1.6-default_h2a92e99_1", - "compiler-rt-22.1.6-h8af1aa0_0", - "libclang-cpp22.1-22.1.6-default_h2a92e99_1", - "compiler-rt22-22.1.6-hfefdfc9_0", - "libcompiler-rt-22.1.6-hfefdfc9_0", - "compiler-rt22_linux-aarch64-22.1.6-hfefdfc9_0", - "compiler-rt_linux-aarch64-22.1.6-h8af1aa0_0", - "libstdcxx-devel_linux-aarch64-16.1.0-h2445e1f_101", + "clangxx_impl_linux-aarch64-23.1.2-default_h99e0da6_0", + "clang-23.1.2-default_cfg_h1a548ed_0", + "clang-scan-deps-23.1.2-default_h01b09c7_0", + "clang_impl_linux-aarch64-23.1.2-default_hb71c922_0", + "clang-23-23.1.2-default_h473506b_0", + "llvm-openmp-23.1.2-hde6636f_0", + "libllvm23-23.1.2-h680871c_0", + "libclang-cpp23.1-23.1.2-default_h01b09c7_0", + "libclang13-23.1.2-default_h473506b_0", + "compiler-rt-23.1.2-h8af1aa0_0", + "compiler-rt_linux-aarch64-23.1.2-h8af1aa0_0", + "compiler-rt23-23.1.2-hde6636f_0", + "libcompiler-rt-23.1.2-hde6636f_0", + "compiler-rt23_linux-aarch64-23.1.2-hde6636f_0", + "libzlib-1.3.2-hdc9db2a_3", + "libxml2-16-2.15.4-h2e5089f_0", + "libxml2-2.15.4-h92b9305_0", + "libstdcxx-devel_linux-aarch64-16.2.0-h082e5f6_107", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", + "zstd-1.5.7-h9d15635_7", "binutils-2.46.1-default_hf1166c9_102", - "libgcc-devel_linux-aarch64-16.1.0-hd673532_101", - "llvm-openmp-22.1.8-he40846f_0", - "sysroot_linux-aarch64-2.39-h934ec21_6", - "kernel-headers_linux-aarch64-6.12.0-h05a177a_6", + "libgcc-devel_linux-aarch64-16.2.0-hc0c2482_107", + "sysroot_linux-aarch64-2.28-h585391f_9", + "kernel-headers_linux-aarch64-4.18.0-h05a177a_9", + "_openmp_mutex-4.5-20_gnu", + "libgomp-16.2.0-h8acb6b2_7", + "icu-78.3-py311h3512406_2", + "libiconv-1.18-h1ea5142_3", + "liblzma-5.8.3-he30d5cf_1", "binutils_impl_linux-aarch64-2.46.1-default_h5f4c503_102", "ld_impl_linux-aarch64-2.46.1-default_h1979696_102", - "libgcc-16.1.0-h205dda4_1", - "libstdcxx-16.1.0-hef695bb_1", - "libllvm22-22.1.8-hfd2ba90_1", "tzdata-2026c-h151e31d_0", - "libclang13-22.1.8-default_h3185f35_2", - "zstd-1.5.7-h9d15635_7", - "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libxml2-2.15.3-h9ba8346_0", - "libxml2-16-2.15.3-h064b767_0", - "libzlib-1.3.2-hdc9db2a_3", - "libiconv-1.18-h90929bb_2", - "liblzma-5.8.3-he30d5cf_1", ] [tools."conda:clangxx"."platforms.linux-x64"] -checksum = "sha256:63525a97a2c26fe35e06f63f15b4bd8d988e504826eb427608398052a58d53e6" -url = "https://conda.anaconda.org/conda-forge/linux-64/clangxx-22.1.6-default_cfg_h9f82b57_1.conda" +checksum = "sha256:ed8eb86f603e9d7283f0afd680239f492ca5677a46e9f05d4d3506351e505707" +url = "https://conda.anaconda.org/conda-forge/linux-64/clangxx-23.1.2-default_cfg_hbe11dda_0.conda" conda_deps = [ - "clangxx_impl_linux-64-22.1.6-default_h0a60c25_1", - "clang-22.1.6-default_cfg_hcbb2b3e_1", - "clang_impl_linux-64-22.1.6-default_h0a60c25_1", - "clang-scan-deps-22.1.6-default_h99862b1_1", - "clang-22-22.1.6-default_h99862b1_1", - "compiler-rt-22.1.6-ha770c72_0", - "libclang-cpp22.1-22.1.6-default_h99862b1_1", - "compiler-rt22-22.1.6-hb700be7_0", - "libcompiler-rt-22.1.6-hb700be7_0", - "compiler-rt22_linux-64-22.1.6-hffcefe0_0", - "compiler-rt_linux-64-22.1.6-ha770c72_0", - "libstdcxx-devel_linux-64-16.1.0-h41cdd0d_101", + "clangxx_impl_linux-64-23.1.2-default_h165e814_0", + "clang-23.1.2-default_cfg_hc1abcf6_0", + "clang-scan-deps-23.1.2-default_h0acdd01_0", + "clang_impl_linux-64-23.1.2-default_he0f7a93_0", + "clang-23-23.1.2-default_hfab3205_0", + "llvm-openmp-23.1.2-h7148c6a_0", + "libllvm23-23.1.2-h474f4eb_0", + "libclang-cpp23.1-23.1.2-default_h0acdd01_0", + "libclang13-23.1.2-default_hfab3205_0", + "compiler-rt-23.1.2-ha770c72_0", + "compiler-rt_linux-64-23.1.2-ha770c72_0", + "compiler-rt23-23.1.2-h7148c6a_0", + "libcompiler-rt-23.1.2-h7148c6a_0", + "compiler-rt23_linux-64-23.1.2-h0e38de2_0", + "libzlib-1.3.2-h25fd6f3_3", + "libxml2-16-2.15.4-hbdfff7e_0", + "libxml2-2.15.4-ha7a5771_0", + "libstdcxx-devel_linux-64-16.2.0-h86e191b_107", + "libstdcxx-16.2.0-h934c35e_7", + "libgcc-16.2.0-ha9f2e26_7", + "zstd-1.5.7-hb78ec9c_7", "binutils-2.46.1-default_h4852527_102", - "libgcc-devel_linux-64-16.1.0-h59071f9_101", - "llvm-openmp-22.1.8-h4922eb0_0", - "sysroot_linux-64-2.39-hc4b9eeb_6", - "kernel-headers_linux-64-6.12.0-he073ed8_6", + "libgcc-devel_linux-64-16.2.0-he3ce08f_107", + "sysroot_linux-64-2.28-h4ee821c_9", + "kernel-headers_linux-64-4.18.0-he073ed8_9", + "_openmp_mutex-4.5-20_gnu", + "libgomp-16.2.0-he0feb66_7", + "liblzma-5.8.3-hb03c661_1", + "libiconv-1.18-h0cb94f2_3", "binutils_impl_linux-64-2.46.1-default_hfdba357_102", "ld_impl_linux-64-2.46.1-default_hbd61a6d_102", - "libgcc-16.1.0-ha9f2e26_1", - "libstdcxx-16.1.0-h934c35e_1", - "libllvm22-22.1.8-hf7376ad_1", "tzdata-2026c-h151e31d_0", - "libclang13-22.1.8-default_h746c552_2", - "zstd-1.5.7-hb78ec9c_7", - "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", - "libzlib-1.3.2-h25fd6f3_3", - "libxml2-2.15.3-h49c6c72_0", - "libxml2-16-2.15.3-hca6bf5a_0", - "libiconv-1.18-h3b78370_2", - "liblzma-5.8.3-hb03c661_1", - "icu-78.3-py310h44b86e0_2", ] [tools."conda:clangxx"."platforms.macos-arm64"] -checksum = "sha256:50f3c7dfab21a4c0dee66cdf59436168790da4b1f75b5f1421fa7a3981201f2e" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-22.1.6-default_cfg_h76039ee_1.conda" +checksum = "sha256:d09bf988868ae2dc8b85aa8cea15d7c02a1947b8be84593c2e1451fbf1bb88af" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-23.1.2-default_cfg_h1399648_0.conda" conda_deps = [ - "clangxx_impl_osx-arm64-22.1.6-default_h17d1ed9_1", - "clang-22.1.6-default_cfg_hb78b91e_1", - "clang_impl_osx-arm64-22.1.6-default_h17d1ed9_1", - "clang-scan-deps-22.1.6-default_h8e162e0_1", - "clang-22-22.1.6-default_hd632d02_1", - "llvm-tools-22.1.6-hd34ed20_0", - "compiler-rt-22.1.6-hce30654_0", - "libclang-cpp22.1-22.1.6-default_h8e162e0_1", - "compiler-rt22-22.1.6-hd34ed20_0", - "llvm-tools-22-22.1.6-hb545844_0", - "libllvm22-22.1.6-h89af1be_0", - "libcompiler-rt-22.1.6-hd34ed20_0", - "compiler-rt22_osx-arm64-22.1.6-h7e67a1e_0", - "compiler-rt_osx-arm64-22.1.6-hce30654_0", - "cctools_impl_osx-arm64-1030.6.3-llvm22_1_hb5e89dc_4", - "ld64_osx-arm64-956.6-llvm22_1_h692d5aa_4", - "cctools-1030.6.3-llvm22_1_hbe26303_4", - "ld64-956.6-llvm22_1_h5b97f1b_4", - "libcxx-devel-22.1.8-h6dc3340_0", - "libcxx-headers-22.1.8-h707e725_0", - "libcxx-22.1.8-h55c6f16_0", - "llvm-openmp-22.1.8-hc7d1edf_0", - "tapi-1600.0.11.8-hb561403_3", + "clangxx_impl_osx-arm64-23.1.2-default_hdadafb6_0", + "clang-23.1.2-default_cfg_h870b8d9_0", + "clang-scan-deps-23.1.2-default_h79071a4_0", + "clang_impl_osx-arm64-23.1.2-default_h79071a4_0", + "clang-23-23.1.2-default_h8f9c3af_0", + "llvm-tools-23.1.2-hdb3d66b_0", + "ld64_osx-arm64-956.6-llvm23_1_hc8058f9_6", + "llvm-openmp-23.1.2-hdb3d66b_0", + "libllvm23-23.1.2-h759d1ac_0", + "libcxx-23.1.2-h55c6f16_0", + "libclang-cpp23.1-23.1.2-default_h79071a4_0", + "libclang13-23.1.2-default_h8f9c3af_0", + "compiler-rt-23.1.2-hce30654_0", + "compiler-rt_osx-arm64-23.1.2-hce30654_0", + "compiler-rt23-23.1.2-hdb3d66b_0", + "llvm-tools-23-23.1.2-h79441dc_0", + "cctools_impl_osx-arm64-1030.6.3-llvm23_1_hf5e010b_6", + "libcompiler-rt-23.1.2-hdb3d66b_0", + "compiler-rt23_osx-arm64-23.1.2-hb8825d9_0", + "ld64-956.6-llvm23_1_hd841b0c_6", + "cctools-1030.6.3-llvm23_1_h54b4f4b_6", + "libcxx-devel-23.1.2-h6dc3340_0", + "libcxx-headers-23.1.2-h707e725_0", + "libzlib-1.3.2-h8088a28_3", + "libxml2-16-2.15.4-heb56d2d_0", + "libxml2-2.15.4-h550178d_0", + "zstd-1.5.7-hf451053_7", + "liblzma-5.8.3-h8088a28_1", + "icu-78.3-py310h579977c_2", + "libiconv-1.18-he4c29f2_3", "sigtool-codesign-0.1.3-h98dc951_1", "libsigtool-0.1.3-h98dc951_1", - "libclang13-22.1.6-default_h6dd9417_1", - "libxml2-2.15.3-heed7d32_0", - "libxml2-16-2.15.3-h6967ea9_0", - "zstd-1.5.7-hf451053_7", - "libzlib-1.3.2-h8088a28_3", - "openssl-3.6.3-hd24854e_1", + "tapi-1600.0.11.8-hb561403_4", + "openssl-3.6.4-h55eecbc_0", "ncurses-6.6-he64c551_1", - "libiconv-1.18-h23cfdf5_2", - "liblzma-5.8.3-h8088a28_1", "ca-certificates-2026.7.22-hbd8a1cb_0", ] [tools."conda:clangxx"."platforms.macos-x64"] -checksum = "sha256:12a02ab446e464600569a26e76f955b175524eb6b15daba09e2c772c300f31f0" -url = "https://conda.anaconda.org/conda-forge/osx-64/clangxx-22.1.6-default_cfg_hbf36760_1.conda" +checksum = "sha256:f4c903ab46a89051c1d014b95a1c649e41c5bdb608155b172fcd23f1c9ee3cf9" +url = "https://conda.anaconda.org/conda-forge/osx-64/clangxx-23.1.2-default_cfg_h2b485f0_0.conda" conda_deps = [ - "clangxx_impl_osx-64-22.1.6-default_he9bf3b8_1", - "clang-22.1.6-default_cfg_h93fe8ef_1", - "clang_impl_osx-64-22.1.6-default_he9bf3b8_1", - "clang-scan-deps-22.1.6-default_h9399c5b_1", - "clang-22-22.1.6-default_h3b8fe2e_1", - "llvm-tools-22.1.6-h1637cdf_0", - "compiler-rt-22.1.6-h694c41f_0", - "libclang-cpp22.1-22.1.6-default_h9399c5b_1", - "compiler-rt22-22.1.6-h1637cdf_0", - "llvm-tools-22-22.1.6-hc181bea_0", - "libllvm22-22.1.6-hab754da_0", - "libcompiler-rt-22.1.6-h1637cdf_0", - "compiler-rt22_osx-64-22.1.6-hcf80936_0", - "compiler-rt_osx-64-22.1.6-h694c41f_0", - "cctools_impl_osx-64-1030.6.3-llvm22_1_h8fe25a2_4", - "ld64_osx-64-956.6-llvm22_1_h163eae7_4", - "ld64-956.6-llvm22_1_hc399b6d_4", - "cctools-1030.6.3-llvm22_1_h0a1bb1c_4", - "libcxx-devel-22.1.8-h7c275be_0", - "libcxx-headers-22.1.8-h707e725_0", - "libcxx-22.1.8-h19cb2f5_0", - "llvm-openmp-22.1.8-h0d3cbff_0", - "tapi-1600.0.11.8-h44950e2_3", - "sigtool-codesign-0.1.3-h8c25ef7_1", - "libsigtool-0.1.3-h8c25ef7_1", - "libclang13-22.1.6-default_h2429e1b_1", - "libxml2-2.15.3-h0712280_0", - "libxml2-16-2.15.3-h0d7f165_0", + "clangxx_impl_osx-64-23.1.2-default_hf9996f3_0", + "clang-23.1.2-default_cfg_hcbdff81_0", + "clang-scan-deps-23.1.2-default_h6e863b9_0", + "clang_impl_osx-64-23.1.2-default_h6e863b9_0", + "clang-23-23.1.2-default_h3065a3b_0", + "llvm-tools-23.1.2-h8c1e6b9_0", + "ld64_osx-64-956.6-llvm23_1_h484b24f_6", + "llvm-openmp-23.1.2-h8c1e6b9_0", + "libllvm23-23.1.2-hd11396f_0", + "libcxx-23.1.2-h19cb2f5_0", + "libclang-cpp23.1-23.1.2-default_h6e863b9_0", + "libclang13-23.1.2-default_h3065a3b_0", + "compiler-rt-23.1.2-h694c41f_0", + "compiler-rt_osx-64-23.1.2-h694c41f_0", + "compiler-rt23-23.1.2-h8c1e6b9_0", + "llvm-tools-23-23.1.2-h36529c3_0", + "cctools_impl_osx-64-1030.6.3-llvm23_1_h3bd330e_6", + "libcompiler-rt-23.1.2-h8c1e6b9_0", + "compiler-rt23_osx-64-23.1.2-h8d5f570_0", + "ld64-956.6-llvm23_1_h0b736ef_6", + "cctools-1030.6.3-llvm23_1_h254e556_6", + "libcxx-devel-23.1.2-h7c275be_0", + "libcxx-headers-23.1.2-h707e725_0", + "libxml2-16-2.15.4-h341e563_0", + "libxml2-2.15.4-h3668fe6_0", "libzlib-1.3.2-hbb4bfdb_3", "zstd-1.5.7-hbc1a06c_7", - "openssl-3.6.3-hc881268_1", - "ncurses-6.6-hcc0dc9a_1", - "libiconv-1.18-h57a12c2_2", "liblzma-5.8.3-hbb4bfdb_1", + "libiconv-1.18-h4ae439b_3", + "sigtool-codesign-0.1.3-h8c25ef7_1", + "libsigtool-0.1.3-h8c25ef7_1", + "tapi-1600.0.11.8-h44950e2_4", + "openssl-3.6.4-h332eb6d_0", + "ncurses-6.6-hcc0dc9a_1", "ca-certificates-2026.7.22-hbd8a1cb_0", ] [tools."conda:clangxx"."platforms.windows-x64"] -checksum = "sha256:862037d82f1c86d6066ceedb05850339e40971e22739dc986858bf7b76376915" -url = "https://conda.anaconda.org/conda-forge/win-64/clangxx-22.1.6-default_nocfg_hbb9487a_1.conda" +checksum = "sha256:f4d3a146cc1ef1251d917471ad1e958676e7017bbd3ae1421f48d65aa574f205" +url = "https://conda.anaconda.org/conda-forge/win-64/clangxx-23.1.2-default_nocfg_he26721c_0.conda" conda_deps = [ - "clang-22.1.6-default_nocfg_hbb9487a_1", - "clang-22-22.1.6-default_hac490eb_1", - "compiler-rt22-22.1.6-h49e36cd_0", - "compiler-rt22_win-64-22.1.6-h49e36cd_0", + "llvm-openmp-23.1.2-h49e36cd_0", + "clang-23.1.2-default_nocfg_h59757e6_0", + "clang-23-23.1.2-default_hacd6ee9_0", + "compiler-rt23-23.1.2-h49e36cd_0", + "compiler-rt23_win-64-23.1.2-h49e36cd_0", + "libxml2-16-2.15.4-h3cfd58e_0", + "libxml2-2.15.4-he095d88_0", "libzlib-1.3.2-hfd05255_3", - "ucrt-10.0.26100.0-h57928b3_0", "vc-14.5-ha367084_41", "vc14_runtime-14.51.36247-habf1de7_41", "vcomp14-14.51.36247-habf1de7_41", + "ucrt-10.0.26100.0-h57928b3_0", "zstd-1.5.7-h534d264_7", - "llvm-openmp-22.1.8-h4fa8253_0", + "icu-78.3-h5112557_2", + "libiconv-1.18-hc1393d2_3", + "liblzma-5.8.3-hfd05255_1", ] [[tools."conda:gnupg"]] -version = "2.5.21" +version = "2.5.24" backend = "conda:gnupg" [tools."conda:gnupg".options] channel = "conda-forge" [tools."conda:gnupg"."platforms.linux-arm64"] -checksum = "sha256:dcd1e425a8ccdc781f55a63773a8d7040a498bbcacc04100f14dc89ad2472cb1" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/gnupg-2.5.21-hacc8eee_0.conda" +checksum = "sha256:5317940ba41018dd9e8adbaf81386f670430db3c78b100c16d24bf3f5e46dfc3" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/gnupg-2.5.24-hf476e02_0.conda" conda_deps = [ - "ntbtls-0.3.2-hd84c7bf_0", "npth-1.8-h5ad3122_0", - "libgcrypt-lib-1.12.2-he30d5cf_0", - "libassuan-3.0.2-h5ad3122_0", "libksba-1.6.7-h0a1ffab_0", - "readline-8.3-hb682ff5_0", + "libassuan-3.0.2-h5ad3122_0", + "ntbtls-0.3.2-hd84c7bf_0", "bzip2-1.0.8-h4777abc_10", - "libiconv-1.18-h90929bb_2", - "sqlite-3.53.4-he8854b5_0", - "libsqlite-3.53.4-h022381a_0", - "libgcc-16.1.0-h205dda4_1", - "libgcc-ng-16.1.0-he9431aa_1", - "libstdcxx-16.1.0-hef695bb_1", - "libstdcxx-ng-16.1.0-hdbbeba8_1", + "readline-8.3-ha7194a6_1", + "libiconv-1.18-h1ea5142_3", + "sqlite-3.53.4-h6ce2f9a_1", + "libsqlite-3.53.4-h399dd60_1", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", + "libstdcxx-ng-16.2.0-hdbbeba8_7", + "libgcc-ng-16.2.0-he9431aa_7", + "libgcrypt-lib-1.12.2-h5bc82ec_2", "libgpg-error-1.61-h7ac5ae9_2", "ncurses-6.6-h2b6f883_1", + "icu-78.3-py311h3512406_2", "libzlib-1.3.2-hdc9db2a_3", "zlib-1.3.2-hdc9db2a_3", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libgcrypt-1.12.2-h8af1aa0_0", - "libgcrypt-tools-1.12.2-he30d5cf_0", - "libgcrypt-devel-1.12.2-he30d5cf_0", + "libgomp-16.2.0-h8acb6b2_7", + "libgcrypt-1.12.2-h8af1aa0_2", + "libgcrypt-tools-1.12.2-h5bc82ec_2", + "libgcrypt-devel-1.12.2-h5bc82ec_2", ] [tools."conda:gnupg"."platforms.linux-x64"] -checksum = "sha256:648153e11b926bf78ef4d9bea6d9966cfb8728a9f322dd13df6b35aca66149ad" -url = "https://conda.anaconda.org/conda-forge/linux-64/gnupg-2.5.21-hb3df253_0.conda" +checksum = "sha256:2e6965580eac0911e9ec0630b623e2a3ad30d7c98a3f3dfc05a7dae3d0707e7f" +url = "https://conda.anaconda.org/conda-forge/linux-64/gnupg-2.5.24-h4362557_0.conda" conda_deps = [ "libassuan-3.0.2-h5888daf_0", - "ntbtls-0.3.2-hfc55251_0", "libksba-1.6.7-hac33072_0", - "libgcrypt-lib-1.12.2-hb03c661_0", "npth-1.8-h5888daf_0", - "readline-8.3-h853b02a_0", + "ntbtls-0.3.2-hfc55251_0", "bzip2-1.0.8-hda65f42_10", - "libiconv-1.18-h3b78370_2", - "sqlite-3.53.4-h04a0ce9_0", - "libsqlite-3.53.4-hf4e2dac_0", + "readline-8.3-hd6e31c0_1", + "libiconv-1.18-h0cb94f2_3", + "sqlite-3.53.4-h9ffa6c4_1", + "libsqlite-3.53.4-h13e7031_1", + "libgcc-16.2.0-ha9f2e26_7", + "libgcc-ng-16.2.0-h69a702a_7", + "libstdcxx-16.2.0-h934c35e_7", + "libstdcxx-ng-16.2.0-hdf11a46_7", + "libgcrypt-lib-1.12.2-h7cc23a3_2", "libgpg-error-1.61-h54a6638_2", - "libgcc-16.1.0-ha9f2e26_1", - "libgcc-ng-16.1.0-h69a702a_1", - "libstdcxx-16.1.0-h934c35e_1", - "libstdcxx-ng-16.1.0-hdf11a46_1", "ncurses-6.6-hdb14827_1", "libzlib-1.3.2-h25fd6f3_3", "zlib-1.3.2-h25fd6f3_3", "icu-78.3-py310h44b86e0_2", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", - "libgcrypt-1.12.2-ha770c72_0", - "libgcrypt-tools-1.12.2-hb03c661_0", - "libgcrypt-devel-1.12.2-hb03c661_0", + "libgomp-16.2.0-he0feb66_7", + "libgcrypt-1.12.2-ha770c72_2", + "libgcrypt-tools-1.12.2-h7cc23a3_2", + "libgcrypt-devel-1.12.2-h7cc23a3_2", ] [tools."conda:gnupg"."platforms.macos-arm64"] -checksum = "sha256:4051f5f3b07b7e18fafda28decc3f6c8438609920122f6967d7e348d6f2ccd48" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/gnupg-2.5.21-hb8d65fb_0.conda" +checksum = "sha256:3e1b9115df3d4213b19b1fe10022b0584cbf3134348e60335346c7ee5359438d" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/gnupg-2.5.24-h1775f82_0.conda" conda_deps = [ - "ntbtls-0.3.2-h1059232_0", "npth-1.8-h286801f_0", - "libksba-1.6.7-h00cdb27_0", - "libgcrypt-lib-1.12.2-h84a0fba_0", - "readline-8.3-h46df422_0", "libassuan-3.0.2-h286801f_0", + "libksba-1.6.7-h00cdb27_0", + "ntbtls-0.3.2-h1059232_0", "bzip2-1.0.8-h4e30115_10", - "libiconv-1.18-h23cfdf5_2", - "sqlite-3.53.4-h77b7338_0", - "libsqlite-3.53.4-h1ae2325_0", + "readline-8.3-h8b90a29_1", + "libiconv-1.18-he4c29f2_3", + "sqlite-3.53.4-ha9f7ffe_1", + "libsqlite-3.53.4-hca69786_1", "libgpg-error-1.61-h784d473_2", - "libintl-0.25.1-h493aca8_0", - "libcxx-22.1.8-h55c6f16_0", + "libgcrypt-lib-1.12.2-hb001647_2", + "libcxx-23.1.2-h55c6f16_0", "ncurses-6.6-he64c551_1", "libzlib-1.3.2-h8088a28_3", "zlib-1.3.2-h8088a28_3", "icu-78.3-py310h579977c_2", - "libgcrypt-1.12.2-hce30654_0", - "libgcrypt-tools-1.12.2-h84a0fba_0", - "libgcrypt-devel-1.12.2-h84a0fba_0", + "libgcrypt-1.12.2-hce30654_2", + "libgcrypt-tools-1.12.2-hb001647_2", + "libgcrypt-devel-1.12.2-hb001647_2", + "libintl-0.25.1-hae62183_2", ] [tools."conda:gnupg"."platforms.macos-x64"] -checksum = "sha256:3dcc1c2ea91de1a7b8aceef988b7a20631bb3cf6eb0606c164488979b7371ac2" -url = "https://conda.anaconda.org/conda-forge/osx-64/gnupg-2.5.21-he74e0c7_0.conda" +checksum = "sha256:26faef1a7427846709eeffa6a03e639695d3c13999b873b94b2e073b665f5d15" +url = "https://conda.anaconda.org/conda-forge/osx-64/gnupg-2.5.24-h4ccb0c0_0.conda" conda_deps = [ "npth-1.8-h240833e_0", - "libgcrypt-lib-1.12.2-ha1e9b39_0", + "ntbtls-0.3.2-h2d185b6_0", "libksba-1.6.7-hf036a51_0", - "readline-8.3-h68b038d_0", "libassuan-3.0.2-h240833e_0", - "ntbtls-0.3.2-h2d185b6_0", "bzip2-1.0.8-h374f1ed_10", - "libiconv-1.18-h57a12c2_2", - "sqlite-3.53.4-hd4d344e_0", - "libsqlite-3.53.4-h77d7759_0", - "libcxx-22.1.8-h19cb2f5_0", + "readline-8.3-h000c2f7_1", + "libiconv-1.18-h4ae439b_3", + "sqlite-3.53.4-hdea7a7b_1", + "libsqlite-3.53.4-ha5db789_1", + "libcxx-23.1.2-h19cb2f5_0", "libgpg-error-1.61-h2fb4741_2", + "libgcrypt-lib-1.12.2-hd115831_2", "ncurses-6.6-hcc0dc9a_1", "libzlib-1.3.2-hbb4bfdb_3", "zlib-1.3.2-hbb4bfdb_3", - "libgcrypt-1.12.2-h694c41f_0", - "libgcrypt-tools-1.12.2-ha1e9b39_0", - "libgcrypt-devel-1.12.2-ha1e9b39_0", - "libintl-0.25.1-h3184127_1", + "libintl-0.25.1-h98e67c8_2", + "libgcrypt-1.12.2-h694c41f_2", + "libgcrypt-tools-1.12.2-hd115831_2", + "libgcrypt-devel-1.12.2-hd115831_2", ] diff --git a/.mise/mise.lock b/.mise/mise.lock index 6ded6e21..3a44068a 100644 --- a/.mise/mise.lock +++ b/.mise/mise.lock @@ -8,13 +8,13 @@ checksum = "sha256:a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1 url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" checksum = "sha256:0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6" -[conda-packages.linux-arm64."libgcc-16.1.0-h205dda4_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.1.0-h205dda4_1.conda" -checksum = "sha256:88a3d400c678df034c9d498f32503779977d5ea826063687c663e42c945abed5" +[conda-packages.linux-arm64."libgcc-16.2.0-h205dda4_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda" +checksum = "sha256:eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1" -[conda-packages.linux-arm64."libgomp-16.1.0-h8acb6b2_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.1.0-h8acb6b2_1.conda" -checksum = "sha256:1c609a4a72597350317b92c4d9dfb85d21740219048e2b1d458925a6ccfa3d7a" +[conda-packages.linux-arm64."libgomp-16.2.0-h8acb6b2_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda" +checksum = "sha256:4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494" [conda-packages.linux-x64."_openmp_mutex-4.5-20_gnu"] url = "https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda" @@ -24,13 +24,13 @@ checksum = "sha256:1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" checksum = "sha256:0a0544cf95f64394fe4959286f5c71f5444ad58feb0602e53becb27448d24da6" -[conda-packages.linux-x64."libgcc-16.1.0-ha9f2e26_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda" -checksum = "sha256:d5cb8475131c31680f8fd30512c418f373064e272e452063276a8fb14c9fa42f" +[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda" +checksum = "sha256:e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea" -[conda-packages.linux-x64."libgomp-16.1.0-he0feb66_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda" -checksum = "sha256:62cb599ad0539d99386515326d9d5e8f51f75a60c69c2131b21df76edf35bd89" +[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda" +checksum = "sha256:92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758" [conda-packages.macos-arm64."ca-certificates-2026.7.22-hbd8a1cb_0"] url = "https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.7.22-hbd8a1cb_0.conda" @@ -94,9 +94,9 @@ url = "https://github.com/01mf02/jaq/releases/download/v3.1.1/jaq-aarch64-unknow url_api = "https://api.github.com/repos/01mf02/jaq/releases/assets/502327954" [tools."aqua:01mf02/jaq"."platforms.linux-x64"] -checksum = "sha256:b9a07a6f10f0305d96d333ea7db69d60704eb4d4e71c98094157e3cc9fe08110" -url = "https://github.com/01mf02/jaq/releases/download/v3.1.1/jaq-x86_64-unknown-linux-musl" -url_api = "https://api.github.com/repos/01mf02/jaq/releases/assets/502327739" +checksum = "sha256:5922c7b67d9bd6841d6676d1f954410c6bf04b47203dcb661c4f052dfef7f454" +url = "https://github.com/01mf02/jaq/releases/download/v3.1.1/jaq-x86_64-unknown-linux-gnu" +url_api = "https://api.github.com/repos/01mf02/jaq/releases/assets/502327122" [tools."aqua:01mf02/jaq"."platforms.macos-arm64"] checksum = "sha256:b1a2e63384e156d90bbf61a1142302aa59bfebd8c89e24dfc9b5747618880fcd" @@ -143,33 +143,33 @@ url = "https://github.com/EmbarkStudios/cargo-deny/releases/download/0.20.2/carg url_api = "https://api.github.com/repos/EmbarkStudios/cargo-deny/releases/assets/471599057" [[tools."aqua:StyraInc/regal"]] -version = "0.41.1" +version = "0.43.0" backend = "aqua:StyraInc/regal" [tools."aqua:StyraInc/regal"."platforms.linux-arm64"] -checksum = "sha256:225ddfa49fad51d923a4ea2dd53a94557d610b2fb55ae76f6203ca8c0f26b061" -url = "https://github.com/open-policy-agent/regal/releases/download/v0.41.1/regal_Linux_arm64" -url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/436462512" +checksum = "sha256:d4fd44a191d5b12a5ab980f56d7eddfed0718129c43d1ede5e8dbc9d217fdcb8" +url = "https://github.com/open-policy-agent/regal/releases/download/v0.43.0/regal_Linux_arm64" +url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/598403605" [tools."aqua:StyraInc/regal"."platforms.linux-x64"] -checksum = "sha256:6769dcd8e88bc5ba5ff4fac500e4a99d55b3eec3d1d0842833d84f6820a2a80f" -url = "https://github.com/open-policy-agent/regal/releases/download/v0.41.1/regal_Linux_x86_64" -url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/436462515" +checksum = "sha256:5e7d030064e307d54e6ffa3d85b8d9052d3d40b7afa10262c86c886f8a76559d" +url = "https://github.com/open-policy-agent/regal/releases/download/v0.43.0/regal_Linux_x86_64" +url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/598403603" [tools."aqua:StyraInc/regal"."platforms.macos-arm64"] -checksum = "sha256:3657a4637de8c304f7463e30e312ec8800d581485fa6f8d716c3f9cd58a4ec2b" -url = "https://github.com/open-policy-agent/regal/releases/download/v0.41.1/regal_Darwin_arm64" -url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/436462514" +checksum = "sha256:23a6e4ef62f288c53e65d770e9325e6d8a9c35ca3f33f6ffb5943c1f381ef540" +url = "https://github.com/open-policy-agent/regal/releases/download/v0.43.0/regal_Darwin_arm64" +url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/598403601" [tools."aqua:StyraInc/regal"."platforms.macos-x64"] -checksum = "sha256:ed57cff7569e0118e9f47d7e38ed9308c85c0e675d4e973294a3438ca0ff7932" -url = "https://github.com/open-policy-agent/regal/releases/download/v0.41.1/regal_Darwin_x86_64" -url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/436462543" +checksum = "sha256:f33fc0ac70b6a5783b92c324123c314f7ff127bb970cf1e3dde807925cd821b7" +url = "https://github.com/open-policy-agent/regal/releases/download/v0.43.0/regal_Darwin_x86_64" +url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/598403604" [tools."aqua:StyraInc/regal"."platforms.windows-x64"] -checksum = "sha256:8c1a9597a7188d539536ef8ce30526373476c3e6e4e9a148d8c918f9142a7ffa" -url = "https://github.com/open-policy-agent/regal/releases/download/v0.41.1/regal_Windows_x86_64.exe" -url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/436462513" +checksum = "sha256:7239b548b0298fd4538b2555cce9b09a359e4d77e12d31e4210b94f154c75215" +url = "https://github.com/open-policy-agent/regal/releases/download/v0.43.0/regal_Windows_x86_64.exe" +url_api = "https://api.github.com/repos/open-policy-agent/regal/releases/assets/598403697" [[tools."aqua:aquasecurity/trivy"]] version = "0.74.0" @@ -327,57 +327,57 @@ url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellche url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056944" [[tools."aqua:kubernetes/kubernetes/kubectl"]] -version = "1.37.0" +version = "1.37.1" backend = "aqua:kubernetes/kubernetes/kubectl" [tools."aqua:kubernetes/kubernetes/kubectl"."platforms.linux-arm64"] -checksum = "sha256:922df28df248cc00a9e025f947704f1d1482de64ece54cfe57e61f19eaf1eef3" -url = "https://dl.k8s.io/v1.37.0/bin/linux/arm64/kubectl" +checksum = "sha256:ff749f4b78d9c4f1ec87307df9b50119ed819e2094aa9810cb9acffc3286c8c7" +url = "https://dl.k8s.io/v1.37.1/bin/linux/arm64/kubectl" [tools."aqua:kubernetes/kubernetes/kubectl"."platforms.linux-x64"] -checksum = "sha256:6129359f4e1f3848a5572ccb0b26cf28b8ca08cef38c95a765b2f64a2c961a2f" -url = "https://dl.k8s.io/v1.37.0/bin/linux/amd64/kubectl" +checksum = "sha256:65691ff77eb6fa44c908b77a1082c9f092c3b9733b5cefabec0d1104890e21a8" +url = "https://dl.k8s.io/v1.37.1/bin/linux/amd64/kubectl" [tools."aqua:kubernetes/kubernetes/kubectl"."platforms.macos-arm64"] -checksum = "sha256:583beedaebe422e71d3f1a96acef8b1fef86ea2f09a45ad01aa6c9ce287c1380" -url = "https://dl.k8s.io/v1.37.0/bin/darwin/arm64/kubectl" +checksum = "sha256:fd65982c97ddad3106754b69ffa196d0e543aa591930ae52aed1adfb92f8c77f" +url = "https://dl.k8s.io/v1.37.1/bin/darwin/arm64/kubectl" [tools."aqua:kubernetes/kubernetes/kubectl"."platforms.macos-x64"] -checksum = "sha256:d5276c0f4fde77fc446070290f345944a7f1fda153df6b960e5fde93b7a9bccd" -url = "https://dl.k8s.io/v1.37.0/bin/darwin/amd64/kubectl" +checksum = "sha256:6851381c486ff6edd691623e3d65c87cb9a5b02887ff8fbbb38d8a031b748387" +url = "https://dl.k8s.io/v1.37.1/bin/darwin/amd64/kubectl" [tools."aqua:kubernetes/kubernetes/kubectl"."platforms.windows-x64"] -checksum = "sha256:4721b614a67bb4932a0369e61f4a323d8c6ca00943d3a2ff14837c124da06f0e" -url = "https://dl.k8s.io/v1.37.0/bin/windows/amd64/kubectl.exe" +checksum = "sha256:14b93c4916a6f37a06fbc1f46b0a1d2404c4f9741be09f00d6caf8af3b05f1d3" +url = "https://dl.k8s.io/v1.37.1/bin/windows/amd64/kubectl.exe" [[tools."aqua:mvdan/sh"]] -version = "3.13.1" +version = "3.14.1" backend = "aqua:mvdan/sh" [tools."aqua:mvdan/sh"."platforms.linux-arm64"] -checksum = "sha256:32d92acaa5cd8abb29fc49dac123dc412442d5713967819d8af2c29f1b3857c7" -url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_linux_arm64" -url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/390322859" +checksum = "sha256:5f2db09dae91fca848f7adbdd014632e921a383863a2ad7e0450ad3aba0c6489" +url = "https://github.com/mvdan/sh/releases/download/v3.14.1/shfmt_v3.14.1_linux_arm64" +url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/547320869" [tools."aqua:mvdan/sh"."platforms.linux-x64"] -checksum = "sha256:fb096c5d1ac6beabbdbaa2874d025badb03ee07929f0c9ff67563ce8c75398b1" -url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_linux_amd64" -url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/390322866" +checksum = "sha256:76e77641faa025814b77f153b29796b8e6fa2fca03e0c76a691608b86c7ea7bf" +url = "https://github.com/mvdan/sh/releases/download/v3.14.1/shfmt_v3.14.1_linux_amd64" +url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/547320883" [tools."aqua:mvdan/sh"."platforms.macos-arm64"] -checksum = "sha256:9680526be4a66ea1ffe988ed08af58e1400fe1e4f4aef5bd88b20bb9b3da33f8" -url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_darwin_arm64" -url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/390322881" +checksum = "sha256:b7c872db63553ccffc7253aba3ed7d4885a27d83f1ba567b1138c6315a5847e5" +url = "https://github.com/mvdan/sh/releases/download/v3.14.1/shfmt_v3.14.1_darwin_arm64" +url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/547320930" [tools."aqua:mvdan/sh"."platforms.macos-x64"] -checksum = "sha256:6feedafc72915794163114f512348e2437d080d0047ef8b8fa2ec63b575f12af" -url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_darwin_amd64" -url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/390322886" +checksum = "sha256:d33eee0da0f92835b3562e9767a05cee7e4eaeef47daa03bfd09da17b4b590a6" +url = "https://github.com/mvdan/sh/releases/download/v3.14.1/shfmt_v3.14.1_darwin_amd64" +url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/547320946" [tools."aqua:mvdan/sh"."platforms.windows-x64"] -checksum = "sha256:60cd368533d0ad73fa86d93d5bbf95ef40587245ce684ed138c1b31557b5fe97" -url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_windows_amd64.exe" -url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/390322844" +checksum = "sha256:13629ce28442ca80b6b5a819f7574ab39e1c28c6e26734ca816c9714e04851df" +url = "https://github.com/mvdan/sh/releases/download/v3.14.1/shfmt_v3.14.1_windows_amd64.exe" +url_api = "https://api.github.com/repos/mvdan/sh/releases/assets/547320827" [[tools."aqua:rhysd/actionlint"]] version = "1.7.12" @@ -447,14 +447,14 @@ version = "0.56.0" backend = "aqua:vectordotdev/vector" [tools."aqua:vectordotdev/vector"."platforms.linux-arm64"] -checksum = "sha256:afa383a264e7ab373dac68281cd86fb808f8447bb3813c08b5b0baaae0314a05" -url = "https://github.com/vectordotdev/vector/releases/download/v0.56.0/vector-0.56.0-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/vectordotdev/vector/releases/assets/437387431" +checksum = "sha256:695cbab7a128e080b380cf29b3b40f3b0688b14280e891ed9129b3d34f4d5847" +url = "https://github.com/vectordotdev/vector/releases/download/v0.56.0/vector-0.56.0-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/vectordotdev/vector/releases/assets/437387424" [tools."aqua:vectordotdev/vector"."platforms.linux-x64"] -checksum = "sha256:8c114c5e9fd9646516f014d5d837690447cf0d4f43ba4a3746713bc0612b039b" -url = "https://github.com/vectordotdev/vector/releases/download/v0.56.0/vector-0.56.0-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/vectordotdev/vector/releases/assets/437387490" +checksum = "sha256:7139f412c9d1c5fdff4b59d566c6dbad8a2ef8bb5aa3db82c81e78e4cd919019" +url = "https://github.com/vectordotdev/vector/releases/download/v0.56.0/vector-0.56.0-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/vectordotdev/vector/releases/assets/437387487" [tools."aqua:vectordotdev/vector"."platforms.macos-arm64"] checksum = "sha256:9aa8b6772d7c887734d38c84eb721d3a067e08a4aa4dc0dcc809365da242ec16" @@ -496,70 +496,70 @@ url = "https://github.com/yannh/kubeconform/releases/download/v0.8.0/kubeconform url_api = "https://api.github.com/repos/yannh/kubeconform/releases/assets/438612665" [[tools.ast-grep]] -version = "0.43.0" +version = "0.45.3" backend = "aqua:ast-grep/ast-grep" [tools.ast-grep."platforms.linux-arm64"] -checksum = "sha256:e706846148493967f3ab8011334817edd86ce5acbec10718b2a7b40799c640ff" -url = "https://github.com/ast-grep/ast-grep/releases/download/0.43.0/app-aarch64-unknown-linux-gnu.zip" -url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/429542920" +checksum = "sha256:b39cfbc58da4b869a88b8a4bc57bd5deb0d24541e704cf7c257da7b53ec81c8f" +url = "https://github.com/ast-grep/ast-grep/releases/download/0.45.3/app-aarch64-unknown-linux-gnu.zip" +url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/537333400" [tools.ast-grep."platforms.linux-x64"] -checksum = "sha256:a26253a9c821d935f7e383e40f0de7c2ca62a4121de1f73a6d81ec32eae631e0" -url = "https://github.com/ast-grep/ast-grep/releases/download/0.43.0/app-x86_64-unknown-linux-gnu.zip" -url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/429542387" +checksum = "sha256:f8ac830881339d1edee6b2652f54798c0f4da5a827f2db38a08ee31117783ce8" +url = "https://github.com/ast-grep/ast-grep/releases/download/0.45.3/app-x86_64-unknown-linux-gnu.zip" +url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/537332692" [tools.ast-grep."platforms.macos-arm64"] -checksum = "sha256:8c847d0a29aa4b3101b3361e0b3ee7fb53c7e497adc9ed1afc9615538cd40782" -url = "https://github.com/ast-grep/ast-grep/releases/download/0.43.0/app-aarch64-apple-darwin.zip" -url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/429542766" +checksum = "sha256:6d2279dea5bea2ad79c66ea93f5fe54ba926e398a8a26de76c56db68fe59eac6" +url = "https://github.com/ast-grep/ast-grep/releases/download/0.45.3/app-aarch64-apple-darwin.zip" +url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/537332514" [tools.ast-grep."platforms.macos-x64"] -checksum = "sha256:6d703090b106747b2f56086b6ccc7e798fe78bcae70257aa20519b220153555b" -url = "https://github.com/ast-grep/ast-grep/releases/download/0.43.0/app-x86_64-apple-darwin.zip" -url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/429542599" +checksum = "sha256:b2ffd26f42810340326a9e8a084bdc3647a8795c1a3f21fc06bd7bef3c7c5b2c" +url = "https://github.com/ast-grep/ast-grep/releases/download/0.45.3/app-x86_64-apple-darwin.zip" +url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/537333391" [tools.ast-grep."platforms.windows-x64"] -checksum = "sha256:a4febbc8c48671e5729d85e29e4ebe5a051b7250d19545bca18e725ccf40ef61" -url = "https://github.com/ast-grep/ast-grep/releases/download/0.43.0/app-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/429546361" +checksum = "sha256:3751b7d6be7fd39a80df1180ffe7e053903dcf92d3190e5a8336ff1746af9059" +url = "https://github.com/ast-grep/ast-grep/releases/download/0.45.3/app-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/ast-grep/ast-grep/releases/assets/537334241" [[tools.cargo-binstall]] -version = "1.21.1" +version = "1.24.0" backend = "aqua:cargo-bins/cargo-binstall" [tools.cargo-binstall."platforms.linux-arm64"] -checksum = "sha256:1dc2979f3c83aade9a1b4344589d14fafa63459b759222528d11419f5cca9cc2" -url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.21.1/cargo-binstall-aarch64-unknown-linux-musl.tgz" -url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/489425352" +checksum = "sha256:fa5d4362758d13c38c6630260528c895b535e96afeed08ed7003caf722524ab9" +url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.24.0/cargo-binstall-aarch64-unknown-linux-gnu.tgz" +url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/590639427" provenance = "github-attestations" [tools.cargo-binstall."platforms.linux-x64"] -checksum = "sha256:630c8f8803a686aa6779497f0f0fb51d49822fb5fc3c514d8ced33b34e338e6e" -url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.21.1/cargo-binstall-x86_64-unknown-linux-musl.tgz" -url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/489425174" +checksum = "sha256:ab139b59b86ce14baf9a8da0592dd4c73fdc8b8a7d74a9746881bd68d411f4d8" +url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.24.0/cargo-binstall-x86_64-unknown-linux-gnu.tgz" +url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/590638764" provenance = "github-attestations" [tools.cargo-binstall."platforms.macos-arm64"] -checksum = "sha256:bd03935f1a6d652647f6d42a2cd39396a55094ffddc65bed0debebfe32feea43" -url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.21.1/cargo-binstall-aarch64-apple-darwin.zip" -url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/489425460" +checksum = "sha256:aa3ad3ba751c6fad85d83bf4aa7a114e4e04372de439a62cd7cad3c4025bdbbe" +url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.24.0/cargo-binstall-aarch64-apple-darwin.zip" +url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/590639619" provenance = "github-attestations" [tools.cargo-binstall."platforms.macos-x64"] -checksum = "sha256:73894951a5c5343476e703b9f2ccea9e829396147ee33bded6a5e94c09298d81" -url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.21.1/cargo-binstall-x86_64-apple-darwin.zip" -url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/489425224" +checksum = "sha256:082b204980c8c3f1f3dc109a9c937c6e0604c2f754b50059cc5cc912e80a39c2" +url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.24.0/cargo-binstall-x86_64-apple-darwin.zip" +url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/590638908" provenance = "github-attestations" [tools.cargo-binstall."platforms.windows-x64"] -checksum = "sha256:27aee4e73cd8b1d479730cb9cdbd89b1114453a135689d4ee1a7e7f913f0ffe1" -url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.21.1/cargo-binstall-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/489425215" +checksum = "sha256:d03e0b721aa770228210e6b65ed66d2c3fa9dbfb096160906ebd4b82e7bfa1fa" +url = "https://github.com/cargo-bins/cargo-binstall/releases/download/v1.24.0/cargo-binstall-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/cargo-bins/cargo-binstall/releases/assets/590638843" provenance = "github-attestations" [[tools."cargo:cargo-expand"]] -version = "1.0.122" +version = "1.0.126" backend = "cargo:cargo-expand" [[tools."cargo:findutils"]] @@ -567,7 +567,7 @@ version = "0.8.0" backend = "cargo:findutils" [[tools."cargo:open"]] -version = "5.3.6" +version = "5.4.4" backend = "cargo:open" [[tools."cargo:rustfs/rustfs"]] @@ -578,7 +578,7 @@ backend = "cargo:rustfs/rustfs" crate = "rustfs" [[tools."cargo:ryl"]] -version = "0.21.0" +version = "0.22.0" backend = "cargo:ryl" [[tools."cargo:vectordotdev/vector"]] @@ -593,74 +593,74 @@ version = "0.116.1" backend = "cargo:wasm-opt" [[tools.cmake]] -version = "4.3.3" +version = "4.4.3" backend = "aqua:Kitware/CMake" [tools.cmake."platforms.linux-arm64"] -checksum = "sha256:9ea38356dbd3e32e51029a3e09a0f2f8e117ef4fbcaad7a21ffb36409bbd5cb4" -url = "https://github.com/Kitware/CMake/releases/download/v4.3.3/cmake-4.3.3-linux-aarch64.tar.gz" -url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/426406946" +checksum = "sha256:2efc974dbd63b4444c0e8494b92f2e80c2d7e635b4b80eac2916985ddd8f72a6" +url = "https://github.com/Kitware/CMake/releases/download/v4.4.3/cmake-4.4.3-linux-aarch64.tar.gz" +url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/529577299" [tools.cmake."platforms.linux-x64"] -checksum = "sha256:927b2368a946c37269c3a66225ab00544e756459cdd0b5d0da438694fb9ff802" -url = "https://github.com/Kitware/CMake/releases/download/v4.3.3/cmake-4.3.3-linux-x86_64.tar.gz" -url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/426407023" +checksum = "sha256:d6c83076c575bc00b823522ac974bda66d0af05d6ddc30e739c12385cf32c6cc" +url = "https://github.com/Kitware/CMake/releases/download/v4.4.3/cmake-4.4.3-linux-x86_64.tar.gz" +url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/529577408" [tools.cmake."platforms.macos-arm64"] -checksum = "sha256:5221a13450c7a0219a2a0d1b6c9085eb06489721fafd8488ccebc1584175d2fb" -url = "https://github.com/Kitware/CMake/releases/download/v4.3.3/cmake-4.3.3-macos-universal.tar.gz" -url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/426407094" +checksum = "sha256:0c5d65251c14cc884bfa16bdbed3c263ce5bffe2e21c0d0d00962cb0610464fa" +url = "https://github.com/Kitware/CMake/releases/download/v4.4.3/cmake-4.4.3-macos-universal.tar.gz" +url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/529577557" [tools.cmake."platforms.macos-x64"] -checksum = "sha256:5221a13450c7a0219a2a0d1b6c9085eb06489721fafd8488ccebc1584175d2fb" -url = "https://github.com/Kitware/CMake/releases/download/v4.3.3/cmake-4.3.3-macos-universal.tar.gz" -url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/426407094" +checksum = "sha256:0c5d65251c14cc884bfa16bdbed3c263ce5bffe2e21c0d0d00962cb0610464fa" +url = "https://github.com/Kitware/CMake/releases/download/v4.4.3/cmake-4.4.3-macos-universal.tar.gz" +url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/529577557" [tools.cmake."platforms.windows-x64"] -checksum = "sha256:935ade9e5e8723583c07f44c5592cea2a1c8f65c56ca7e07b34c025c880e0bd6" -url = "https://github.com/Kitware/CMake/releases/download/v4.3.3/cmake-4.3.3-windows-x86_64.zip" -url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/426407532" +checksum = "sha256:4d52ebab7193a698651639ed80d8d04fd903358843572cf44c7fd234cb7c26ab" +url = "https://github.com/Kitware/CMake/releases/download/v4.4.3/cmake-4.4.3-windows-x86_64.zip" +url_api = "https://api.github.com/repos/Kitware/CMake/releases/assets/529578311" [[tools."conda:openssl"]] -version = "3.6.2" +version = "3.6.4" backend = "conda:openssl" [tools."conda:openssl".options] channel = "conda-forge" [tools."conda:openssl"."platforms.linux-arm64"] -checksum = "sha256:348cb74c1530ac241215d047ef65d134cf797af935c97a68655319362b7e6a01" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda" +checksum = "sha256:a70c05a9baba9b1ce17c7e8b9479029372069b3bf402dbf200bc03696c531bed" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.4-he6ad1d5_0.conda" conda_deps = [ "ca-certificates-2026.7.22-hbd8a1cb_0", - "libgcc-16.1.0-h205dda4_1", + "libgcc-16.2.0-h205dda4_7", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", + "libgomp-16.2.0-h8acb6b2_7", ] [tools."conda:openssl"."platforms.linux-x64"] -checksum = "sha256:c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb" -url = "https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda" +checksum = "sha256:4747b2d6a8336f52343bceb8a1ebf41a9e6e665b9d2e3f989972de53a310599e" +url = "https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.4-h781a0a9_0.conda" conda_deps = [ "ca-certificates-2026.7.22-hbd8a1cb_0", - "libgcc-16.1.0-ha9f2e26_1", + "libgcc-16.2.0-ha9f2e26_7", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", + "libgomp-16.2.0-he0feb66_7", ] [tools."conda:openssl"."platforms.macos-arm64"] -checksum = "sha256:c91bf510c130a1ea1b6ff023e28bac0ccaef869446acd805e2016f69ebdc49ea" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda" +checksum = "sha256:f23239eacd75c4c50705e68fae1aa3292da473e6a3a4abe2330f1e6afa680704" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.4-h55eecbc_0.conda" conda_deps = ["ca-certificates-2026.7.22-hbd8a1cb_0"] [tools."conda:openssl"."platforms.macos-x64"] -checksum = "sha256:334fd49ea31b99114f5afb1ec44555dc8c90640648302a4f8f838ee345d1ec50" -url = "https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.2-hc881268_0.conda" +checksum = "sha256:73d648d24f0994fd8641972848d74bd57b8d80888a64600643e3fe88a1b50545" +url = "https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.4-h332eb6d_0.conda" conda_deps = ["ca-certificates-2026.7.22-hbd8a1cb_0"] [tools."conda:openssl"."platforms.windows-x64"] -checksum = "sha256:feb5815125c60f2be4a411e532db1ed1cd2d7261a6a43c54cb6ae90724e2e154" -url = "https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda" +checksum = "sha256:9dddb559ba49744d5d94092d8d13cb0567f5c3b3f439f3acf28433d1f4256acc" +url = "https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.4-hf411b9b_0.conda" conda_deps = [ "ca-certificates-2026.7.22-h4c7d964_0", "ucrt-10.0.26100.0-h57928b3_0", @@ -670,212 +670,198 @@ conda_deps = [ ] [[tools.conftest]] -version = "0.68.2" +version = "0.71.0" backend = "aqua:open-policy-agent/conftest" [tools.conftest."platforms.linux-arm64"] -checksum = "sha256:4005441089655ded475384cb87d57762ae08ebef78305bada49c70530d2f4184" -url = "https://github.com/open-policy-agent/conftest/releases/download/v0.68.2/conftest_0.68.2_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/396775404" +checksum = "sha256:542f255081cfab9919cba327d3c4014fd46d6ee3f0441c634b14b1465e9469d9" +url = "https://github.com/open-policy-agent/conftest/releases/download/v0.71.0/conftest_0.71.0_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/599706184" +provenance = "github-attestations" [tools.conftest."platforms.linux-x64"] -checksum = "sha256:e8144c6d6d2ae0260b869caa60c7c262a1f95ac63ec1e5d2fb19be452d606347" -url = "https://github.com/open-policy-agent/conftest/releases/download/v0.68.2/conftest_0.68.2_Linux_x86_64.tar.gz" -url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/396775369" +checksum = "sha256:765dfefdf0730693d7541ea0147e10d530a54ed257bbfec055ff34c837ffdf72" +url = "https://github.com/open-policy-agent/conftest/releases/download/v0.71.0/conftest_0.71.0_Linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/599706185" +provenance = "github-attestations" [tools.conftest."platforms.macos-arm64"] -checksum = "sha256:cdb5445179e0cc42906e2b0233694900f272a501878d416a9c875b1f7bdfd34c" -url = "https://github.com/open-policy-agent/conftest/releases/download/v0.68.2/conftest_0.68.2_Darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/396775371" +checksum = "sha256:78051b6ef0422082ba237f0df10a636737878941927880a68893469663b9e724" +url = "https://github.com/open-policy-agent/conftest/releases/download/v0.71.0/conftest_0.71.0_Darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/599706112" +provenance = "github-attestations" [tools.conftest."platforms.macos-x64"] -checksum = "sha256:7682c54243d2c16579589f55aac47c51389d26f103f828902880288ba7f0605e" -url = "https://github.com/open-policy-agent/conftest/releases/download/v0.68.2/conftest_0.68.2_Darwin_x86_64.tar.gz" -url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/396775370" +checksum = "sha256:97a49726a9de43e5c56072b49c4ae3fa449d7a75a80a32c4b27c1467fa42c812" +url = "https://github.com/open-policy-agent/conftest/releases/download/v0.71.0/conftest_0.71.0_Darwin_x86_64.tar.gz" +url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/599706110" +provenance = "github-attestations" [tools.conftest."platforms.windows-x64"] -checksum = "sha256:66a88d02e6c03a714e9f0751c3d86ee9c5591739c367ca1b79c4f9f2f90ac4cb" -url = "https://github.com/open-policy-agent/conftest/releases/download/v0.68.2/conftest_0.68.2_Windows_x86_64.zip" -url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/396775403" - -[[tools.coreutils]] -version = "0.6.0" -backend = "aqua:uutils/coreutils" - -[tools.coreutils."platforms.linux-arm64"] -checksum = "sha256:47a14a2ed2f64b2341731e0e15f916806b3f50cce0b6ffa2cae9ed531c0c9d33" -url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349507043" - -[tools.coreutils."platforms.linux-x64"] -checksum = "sha256:6ddc463115e501a3edd368af601be9b32613f1af3b910e63679b7b273882b304" -url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349508975" - -[tools.coreutils."platforms.macos-arm64"] -checksum = "sha256:70319bbe063c015c8be25fd384478013f6f211fc7507282b6ed12f85eedb99dc" -url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349511606" - -[tools.coreutils."platforms.macos-x64"] -checksum = "sha256:ffb6b57a6640f32895eaec7a5e31f2191860b036dce27769ddcd3fd2786f2865" -url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349510965" - -[tools.coreutils."platforms.windows-x64"] -checksum = "sha256:f223058a51e8a2a4b92d9f1a1b2954f7a02b6d0f42e4a7e0413fcdb93be2e287" -url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349509944" +checksum = "sha256:a9228097e6f827dac7fee48f5cf0baa42ebd88454560de26bbb531d65ae0f448" +url = "https://github.com/open-policy-agent/conftest/releases/download/v0.71.0/conftest_0.71.0_Windows_x86_64.zip" +url_api = "https://api.github.com/repos/open-policy-agent/conftest/releases/assets/599706111" +provenance = "github-attestations" [[tools.crane]] -version = "0.21.9" +version = "0.22.1" backend = "aqua:google/go-containerregistry" [tools.crane."platforms.linux-arm64"] -checksum = "sha256:1f4c647b7bb260ab5435661df5b526cf59950ebf95201790db7183ac189cbcbd" -url = "https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/503108017" +checksum = "sha256:898c0cff975f898a33e8c4580bdafb0e7c02c7faa33374e946762f97c4ab7110" +url = "https://github.com/google/go-containerregistry/releases/download/v0.22.1/go-containerregistry_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/543544372" [tools.crane."platforms.linux-x64"] -checksum = "sha256:5c16d8ddb971cb1d5e6ed8b1e743da8224414eeba2c2762d8f1a61b2f095699e" -url = "https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Linux_x86_64.tar.gz" -url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/503108053" +checksum = "sha256:0ab7a1d6932a213aed964ce97666c3077fe691c8606413674a8b3e0b9ec4cda0" +url = "https://github.com/google/go-containerregistry/releases/download/v0.22.1/go-containerregistry_Linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/543544389" [tools.crane."platforms.macos-arm64"] -checksum = "sha256:11cc3640e53473eb0d8c501068573e52a259f4d82177e6dd11b7bacb8955459e" -url = "https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/503108022" +checksum = "sha256:2231fc8df8806d20d680ff1225db44e095a55dd6ac1ae8eced4faf4b278b78fb" +url = "https://github.com/google/go-containerregistry/releases/download/v0.22.1/go-containerregistry_Darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/543544436" [tools.crane."platforms.macos-x64"] -checksum = "sha256:f31075b3375f79b406a600e090d5c4778b3c6598a01c817dc7898c05c7c00a56" -url = "https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Darwin_x86_64.tar.gz" -url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/503108009" +checksum = "sha256:6fedd06a648c11335f0e8b9547e4783002c30e9336047fec292942cd518bb799" +url = "https://github.com/google/go-containerregistry/releases/download/v0.22.1/go-containerregistry_Darwin_x86_64.tar.gz" +url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/543544434" [tools.crane."platforms.windows-x64"] -checksum = "sha256:2309f41ce9a31b6096fd590a57b00b0fd1d6dc41d315dc820795f64be070fe03" -url = "https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Windows_x86_64.tar.gz" -url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/503108006" +checksum = "sha256:0e073ea8192c3b8442ec8aaf44d53c1050a09084669fae3a6ceb0f2026cf8b21" +url = "https://github.com/google/go-containerregistry/releases/download/v0.22.1/go-containerregistry_Windows_x86_64.tar.gz" +url_api = "https://api.github.com/repos/google/go-containerregistry/releases/assets/543544437" [[tools.dprint]] -version = "0.54.0" +version = "0.58.0" backend = "aqua:dprint/dprint" [tools.dprint."platforms.linux-arm64"] -checksum = "sha256:9a66b5931ca30402a3dd2933c432c6b6316eedd08037ab0aeb8d24cd17b2a301" -url = "https://github.com/dprint/dprint/releases/download/0.54.0/dprint-aarch64-unknown-linux-musl.zip" -url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/391792286" +checksum = "sha256:f161161399b5ef62b3b68570ea1df24d16687adfbb88c125c8c4355e5780c407" +url = "https://github.com/dprint/dprint/releases/download/0.58.0/dprint-aarch64-unknown-linux-gnu.zip" +url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/598660523" +provenance = "github-attestations" [tools.dprint."platforms.linux-x64"] -checksum = "sha256:859ae94e596105201faa59a3fb4bedc8316e226e3e154ae410f9373461e1e41c" -url = "https://github.com/dprint/dprint/releases/download/0.54.0/dprint-x86_64-unknown-linux-musl.zip" -url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/391792288" +checksum = "sha256:3047dcabe684fe32868d1959f7fad4ccbc2996a393d639bbb6634668fa08dc49" +url = "https://github.com/dprint/dprint/releases/download/0.58.0/dprint-x86_64-unknown-linux-gnu.zip" +url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/598660522" +provenance = "github-attestations" [tools.dprint."platforms.macos-arm64"] -checksum = "sha256:1d6a8fb14d66cba0f049738edd4ab3b1afc1de6d936cd32e483e33284cfd1ade" -url = "https://github.com/dprint/dprint/releases/download/0.54.0/dprint-aarch64-apple-darwin.zip" -url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/391792290" +checksum = "sha256:06a7ea017e4d7da296f8a44fabb2f3d6ffafa91bbd5fddd4830bdc418bacb46d" +url = "https://github.com/dprint/dprint/releases/download/0.58.0/dprint-aarch64-apple-darwin.zip" +url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/598660526" +provenance = "github-attestations" [tools.dprint."platforms.macos-x64"] -checksum = "sha256:fdbffa16cf0890ca30e958ffdabe7748e733867651a438ede1501f0e1a7b5e91" -url = "https://github.com/dprint/dprint/releases/download/0.54.0/dprint-x86_64-apple-darwin.zip" -url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/391792280" +checksum = "sha256:47e0c48127c9ac306bc66c4af0c3146ef41bd008c5eccc956691c09e2661f077" +url = "https://github.com/dprint/dprint/releases/download/0.58.0/dprint-x86_64-apple-darwin.zip" +url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/598660515" +provenance = "github-attestations" [tools.dprint."platforms.windows-x64"] -checksum = "sha256:3fd881acaf7fd4fbc5d07c3030ce79b965a4cb7128fe0eb1ebe725188ccd2715" -url = "https://github.com/dprint/dprint/releases/download/0.54.0/dprint-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/391792284" +checksum = "sha256:6ab827fba525918670ff666edb5fc50917157c803c9abdc463131f75b5df0840" +url = "https://github.com/dprint/dprint/releases/download/0.58.0/dprint-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/dprint/dprint/releases/assets/598660521" +provenance = "github-attestations" [[tools.editorconfig-checker]] -version = "3.11.3" -backend = "aqua:editorconfig-checker/editorconfig-checker" +version = "4.0.2" +backend = "github:editorconfig-checker/editorconfig-checker" [tools.editorconfig-checker."platforms.linux-arm64"] -checksum = "sha256:6d333917ad3c21cf0a23c191ec660549de381e6df56ee5e76ace0c513da2b7b4" -url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v3.11.3/ec-linux-arm64.tar.gz" -url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/543324052" +checksum = "sha256:abad76da8c9950fdc2a314bcd66969172aa823e9c595fa7e3a389a91e34d025e" +url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v4.0.2/editorconfig-checker-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/574675779" +provenance = "github-attestations" [tools.editorconfig-checker."platforms.linux-x64"] -checksum = "sha256:6a73858f8906e466910fb3b3b525c206b27dacdad138910b0b0513f021ab32c4" -url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v3.11.3/ec-linux-amd64.tar.gz" -url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/543324059" +checksum = "sha256:44efaef3ed14c6ab52eb87481d78e5e5c204796dccf26e2f4598a61ba17f8003" +url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v4.0.2/editorconfig-checker-linux-amd64.tar.gz" +url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/574675771" +provenance = "github-attestations" [tools.editorconfig-checker."platforms.macos-arm64"] -checksum = "sha256:eeb0e5d1db4a913277da781bc40802542eb42c4f3f43b7c87c000714dd905faf" -url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v3.11.3/ec-darwin-arm64.tar.gz" -url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/543324096" +checksum = "sha256:ff59f57717d95fc62b8e372c8051dbbb766f7d660942409a85d027b0feb2422c" +url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v4.0.2/editorconfig-checker-darwin-all.tar.gz" +url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/574675773" +provenance = "github-attestations" [tools.editorconfig-checker."platforms.macos-x64"] -checksum = "sha256:126c8fa83500389078f6b2072a04170f063787ec9905e5d1ab69a5a62ee5b10d" -url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v3.11.3/ec-darwin-amd64.tar.gz" -url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/543324099" +checksum = "sha256:ff59f57717d95fc62b8e372c8051dbbb766f7d660942409a85d027b0feb2422c" +url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v4.0.2/editorconfig-checker-darwin-all.tar.gz" +url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/574675773" +provenance = "github-attestations" [tools.editorconfig-checker."platforms.windows-x64"] -checksum = "sha256:0d6739507ac0b57099f0339fce1de0856584c71dd878c89cbc07845884f42ab5" -url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v3.11.3/ec-windows-amd64.zip" -url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/543324056" +checksum = "sha256:857f8f74dfc259d73dac93573e37cf3ce01150787d7b139bf839549cc6b5beb9" +url = "https://github.com/editorconfig-checker/editorconfig-checker/releases/download/v4.0.2/editorconfig-checker-windows-amd64.zip" +url_api = "https://api.github.com/repos/editorconfig-checker/editorconfig-checker/releases/assets/574675794" +provenance = "github-attestations" [[tools.gh]] -version = "2.97.0" +version = "2.102.0" backend = "aqua:cli/cli" [tools.gh."platforms.linux-arm64"] -checksum = "sha256:73ea440ecad9c9e284429997ee6f93577bc6f7bc6fba357ef62c53ad8fb641a5" -url = "https://github.com/cli/cli/releases/download/v2.97.0/gh_2.97.0_linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/cli/cli/releases/assets/496108278" +checksum = "sha256:7862c86c72f43df3a2d93ddde6f473285b4e2af61b494849846827e513ef6484" +url = "https://github.com/cli/cli/releases/download/v2.102.0/gh_2.102.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/599854680" provenance = "github-attestations" [tools.gh."platforms.linux-x64"] -checksum = "sha256:a2c9b8497e1f85b1ad0dfcb78b5a622e098801b8e461e459e88e1ee12f018112" -url = "https://github.com/cli/cli/releases/download/v2.97.0/gh_2.97.0_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/cli/cli/releases/assets/496108269" +checksum = "sha256:bb766f710eef8ede859c18578c72c327597cd4c8a85b06001b1f3843c6019386" +url = "https://github.com/cli/cli/releases/download/v2.102.0/gh_2.102.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/599854672" provenance = "github-attestations" [tools.gh."platforms.macos-arm64"] -checksum = "sha256:a58b8fd77b417a38f47a0b54d1370c59b0fcdb324ccc9ca002b0998f7c4c999e" -url = "https://github.com/cli/cli/releases/download/v2.97.0/gh_2.97.0_macOS_arm64.zip" -url_api = "https://api.github.com/repos/cli/cli/releases/assets/496108298" +checksum = "sha256:da922c20d1792e5b2cbf375593d7a658acf034c12c84e007e71c76ef959c337e" +url = "https://github.com/cli/cli/releases/download/v2.102.0/gh_2.102.0_macOS_arm64.zip" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/599854720" provenance = "github-attestations" [tools.gh."platforms.macos-x64"] -checksum = "sha256:63298c998cc2a924c9e254c6af6a1caad6ece281122687a91f079bc0a462700e" -url = "https://github.com/cli/cli/releases/download/v2.97.0/gh_2.97.0_macOS_amd64.zip" -url_api = "https://api.github.com/repos/cli/cli/releases/assets/496108300" +checksum = "sha256:b245f24eb2bf5f75b426b4c26da3651a107f8d5b6f4fddfbfccc5679041378b3" +url = "https://github.com/cli/cli/releases/download/v2.102.0/gh_2.102.0_macOS_amd64.zip" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/599854716" provenance = "github-attestations" [tools.gh."platforms.windows-x64"] -checksum = "sha256:35d7fe05c4dd1411ffda1e73dfc7c6f44b75c936ca51fa6595c657fdc0350cec" -url = "https://github.com/cli/cli/releases/download/v2.97.0/gh_2.97.0_windows_amd64.zip" -url_api = "https://api.github.com/repos/cli/cli/releases/assets/496108319" +checksum = "sha256:ae64e556ecc240b200f7eba60d550e4bb60d78e860e69dd88c449405b86067f4" +url = "https://github.com/cli/cli/releases/download/v2.102.0/gh_2.102.0_windows_amd64.zip" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/599854760" provenance = "github-attestations" [[tools."github:benhoyt/goawk"]] -version = "1.31.0" +version = "1.32.0" backend = "github:benhoyt/goawk" [tools."github:benhoyt/goawk"."platforms.linux-arm64"] -checksum = "sha256:e744a944e9dcdd1e4fd7c0f51f6aefcba201dd5cf2038a91540efa0d0236ec31" -url = "https://github.com/benhoyt/goawk/releases/download/v1.31.0/goawk_v1.31.0_linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/332035596" +checksum = "sha256:dad03aa7f07c49770bf6ffb2244716c05b21bfbc2f2d453170d3c1173a43dd5a" +url = "https://github.com/benhoyt/goawk/releases/download/v1.32.0/goawk_v1.32.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/565012007" [tools."github:benhoyt/goawk"."platforms.linux-x64"] -checksum = "sha256:0b4a84798bb24479f2acd16dfb6e809046ca8d2572be52d621db59e3faba3bee" -url = "https://github.com/benhoyt/goawk/releases/download/v1.31.0/goawk_v1.31.0_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/332035590" +checksum = "sha256:eda07f45b623ea9a82e9578e69632f79dd52321f2af7ff3b43935be7b805d675" +url = "https://github.com/benhoyt/goawk/releases/download/v1.32.0/goawk_v1.32.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/565011857" [tools."github:benhoyt/goawk"."platforms.macos-arm64"] -checksum = "sha256:21ae23ad87652abe2f7e8ca4473570e4098f8e2906975a12db235f2e60a2dce9" -url = "https://github.com/benhoyt/goawk/releases/download/v1.31.0/goawk_v1.31.0_darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/332035579" +checksum = "sha256:ca430af69900f20b6efb34471d31bea3fc16e301d05eab5ba2e97a4385fc5329" +url = "https://github.com/benhoyt/goawk/releases/download/v1.32.0/goawk_v1.32.0_darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/565011159" [tools."github:benhoyt/goawk"."platforms.macos-x64"] -checksum = "sha256:3a55975e6c21e3c863f0c2a25d194b592c487d59865236a716ae68d8afb2ad7c" -url = "https://github.com/benhoyt/goawk/releases/download/v1.31.0/goawk_v1.31.0_darwin_amd64.tar.gz" -url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/332035573" +checksum = "sha256:8b0d0d58db755266916b24f6c4257cdef018fe2d7d337e0c1afa3d1036e5c09e" +url = "https://github.com/benhoyt/goawk/releases/download/v1.32.0/goawk_v1.32.0_darwin_amd64.tar.gz" +url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/565010960" [tools."github:benhoyt/goawk"."platforms.windows-x64"] -checksum = "sha256:8c59523cf56d47621a9b84124a9fc15f580048103195caacf4f8964dfe632e78" -url = "https://github.com/benhoyt/goawk/releases/download/v1.31.0/goawk_v1.31.0_windows_amd64.zip" -url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/332035610" +checksum = "sha256:2cebd8d64a8eaf84b2787edec8c0274760166e077bc2bdbb69d41537b56cf32c" +url = "https://github.com/benhoyt/goawk/releases/download/v1.32.0/goawk_v1.32.0_windows_amd64.zip" +url_api = "https://api.github.com/repos/benhoyt/goawk/releases/assets/565012345" [[tools."github:caldempsey/parfit"]] version = "0.4.4" @@ -978,6 +964,38 @@ url = "https://github.com/kucherenko/jscpd/releases/download/v5.1.1/jscpd-window url_api = "https://api.github.com/repos/kucherenko/jscpd/releases/assets/538185436" provenance = "github-attestations" +[[tools."github:lycheeverse/lychee"]] +version = "lychee-v0.24.2" +backend = "github:lycheeverse/lychee" + +[tools."github:lycheeverse/lychee".options] +asset_pattern = '*-{{ x86_64_arch }}-*{{ os(linux="musl.t", macos="darwin.t", windows="msvc.z") }}*' + +[tools."github:lycheeverse/lychee"."platforms.linux-arm64"] +checksum = "sha256:5d0b0e3aeab240f41920c633a6eaf97599be6eedda034b36e858ede7dba5e535" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409958602" + +[tools."github:lycheeverse/lychee"."platforms.linux-x64"] +checksum = "sha256:73657a111819a30c47c08352896796f23d64e4eb2b3ed39b6d32149241566fc5" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409959271" + +[tools."github:lycheeverse/lychee"."platforms.macos-arm64"] +checksum = "sha256:c9d3740ea2d891854d37116c9fba840f37b6e7c89d330e7db84ac333631c4977" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409957951" + +[tools."github:lycheeverse/lychee"."platforms.macos-x64"] +checksum = "sha256:887503a9cff667d322b8d0892b40bf49976eb9507af8483220a3706cdad55978" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409957687" + +[tools."github:lycheeverse/lychee"."platforms.windows-x64"] +checksum = "sha256:32975d1493ee1a975d6bb41e4fb56fe419cb442ded628bb772ba2e614acfacad" +url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409959491" + [[tools."github:microsoft/onnxruntime"]] version = "1.22.0" backend = "github:microsoft/onnxruntime" @@ -1004,43 +1022,40 @@ url = "https://github.com/microsoft/onnxruntime/releases/download/v1.22.0/onnxru url_api = "https://api.github.com/repos/microsoft/onnxruntime/releases/assets/253300435" [[tools."github:nextest-rs/nextest"]] -version = "cargo-nextest-0.9.140" +version = "0.9.146" backend = "github:nextest-rs/nextest" [tools."github:nextest-rs/nextest".options] version_prefix = "cargo-nextest-" [tools."github:nextest-rs/nextest"."platforms.linux-arm64"] -checksum = "sha256:8b3f4d4560b6b0f83774fecc6be07e47716dbad0eb0bb6c3890f478f4affe4b6" -url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.140/cargo-nextest-0.9.140-aarch64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/467464894" +checksum = "sha256:b2e33d7c72de7ade0ff7b3a948ac37516b24f8a836b7a8870c1f634a94be9de9" +url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.146/cargo-nextest-0.9.146-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/579608024" provenance = "github-attestations" -provenance_verified = true [tools."github:nextest-rs/nextest"."platforms.linux-x64"] -checksum = "sha256:4ee9aaa0d0171a985a5d0eb735b87355894c1c455972e9674fb9fdbd1387c9a3" -url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.140/cargo-nextest-0.9.140-x86_64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/467470185" +checksum = "sha256:682c21b777c333e96fd532e114d3a5a894e0729ab88d94c0a9f20f8419695428" +url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.146/cargo-nextest-0.9.146-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/579609342" provenance = "github-attestations" -provenance_verified = true [tools."github:nextest-rs/nextest"."platforms.macos-arm64"] -checksum = "sha256:58e0a722f9444078fab447783f322acf15a2a771ba785b3fbbe8bacda31c3df9" -url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.140/cargo-nextest-0.9.140-universal-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/467468113" +checksum = "sha256:39785160b3c2f6ed9a765049cf4fa79f3b39aa02eb7598a5a0e2a1a0b9ffb9a8" +url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.146/cargo-nextest-0.9.146-universal-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/579630774" provenance = "github-attestations" -provenance_verified = true [tools."github:nextest-rs/nextest"."platforms.macos-x64"] -checksum = "sha256:58e0a722f9444078fab447783f322acf15a2a771ba785b3fbbe8bacda31c3df9" -url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.140/cargo-nextest-0.9.140-universal-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/467468113" +checksum = "sha256:39785160b3c2f6ed9a765049cf4fa79f3b39aa02eb7598a5a0e2a1a0b9ffb9a8" +url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.146/cargo-nextest-0.9.146-universal-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/579630774" provenance = "github-attestations" [tools."github:nextest-rs/nextest"."platforms.windows-x64"] -checksum = "sha256:ec39698dfe5bcfffb7d5da037f226bc1670584ba247123f4e684a0f224fe828d" -url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.140/cargo-nextest-0.9.140-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/467472279" +checksum = "sha256:0fa689815c8157e4633225b6b173184b3d546eb6ffb754c3d0e6ea5973284a20" +url = "https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-0.9.146/cargo-nextest-0.9.146-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/nextest-rs/nextest/releases/assets/579617054" provenance = "github-attestations" [[tools."github:open-telemetry/opentelemetry-collector-releases"]] @@ -1073,36 +1088,32 @@ url = "https://github.com/open-telemetry/opentelemetry-collector-releases/releas url_api = "https://api.github.com/repos/open-telemetry/opentelemetry-collector-releases/releases/assets/469251256" [[tools."github:owenlamont/ryl"]] -version = "0.19.1" +version = "0.22.0" backend = "github:owenlamont/ryl" [tools."github:owenlamont/ryl"."platforms.linux-arm64"] -checksum = "sha256:519797a066436e7ccbbf6acd01820c2ceda781e95ccf7e828d66b12b1c2c592b" -url = "https://github.com/owenlamont/ryl/releases/download/v0.19.1/ryl-aarch64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/451334890" +checksum = "sha256:1045ea5807ae274c0812f63f73469018b58f822c8987e22b71f9995be971a6dd" +url = "https://github.com/owenlamont/ryl/releases/download/v0.22.0/ryl-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/547221094" provenance = "github-attestations" -provenance_verified = true [tools."github:owenlamont/ryl"."platforms.linux-x64"] -checksum = "sha256:38dd3f408b08dec2fc33957af74a307273c36d2c35e55bed64fbdcaecae66f32" -url = "https://github.com/owenlamont/ryl/releases/download/v0.19.1/ryl-x86_64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/451334911" +checksum = "sha256:e51be237168ff44c8e28caca87db35c15ac5c943bba5edba0e72465b51add524" +url = "https://github.com/owenlamont/ryl/releases/download/v0.22.0/ryl-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/547221116" provenance = "github-attestations" -provenance_verified = true [tools."github:owenlamont/ryl"."platforms.macos-arm64"] -checksum = "sha256:0d9a3d56c773404405489b6bc3dd6aa8ccb2935c08df8e337e7883c008b04329" -url = "https://github.com/owenlamont/ryl/releases/download/v0.19.1/ryl-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/451334892" +checksum = "sha256:512051556cc92b3bfcb21c434072dcb3de7088af4982439ff0cce7888819f501" +url = "https://github.com/owenlamont/ryl/releases/download/v0.22.0/ryl-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/547221097" provenance = "github-attestations" -provenance_verified = true [tools."github:owenlamont/ryl"."platforms.windows-x64"] -checksum = "sha256:c6faa02823d9ad2c99d0d377a778daa925e7ad2ef9beb96a180236fd2f551e31" -url = "https://github.com/owenlamont/ryl/releases/download/v0.19.1/ryl-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/451334907" +checksum = "sha256:c0b3c8520b0d749d5df974e9638110a7169cde1d8febd6a4e68e802c5de7a70d" +url = "https://github.com/owenlamont/ryl/releases/download/v0.22.0/ryl-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/owenlamont/ryl/releases/assets/547221108" provenance = "github-attestations" -provenance_verified = true [[tools."github:prometheus-community/windows_exporter"]] version = "0.31.7" @@ -1113,6 +1124,35 @@ checksum = "sha256:288252baf470da41494420250e68b5358992701298f77a36d821992b589ec url = "https://github.com/prometheus-community/windows_exporter/releases/download/v0.31.7/windows_exporter-0.31.7-amd64.exe" url_api = "https://api.github.com/repos/prometheus-community/windows_exporter/releases/assets/420179563" +[[tools."github:pvolok/dekit"]] +version = "0.10.0" +backend = "github:pvolok/dekit" + +[tools."github:pvolok/dekit"."platforms.linux-arm64"] +checksum = "sha256:35b2ae81a23a1b67c3f2fb95f993b26257af23270f651cc44cc1f64eba23d5fe" +url = "https://github.com/pvolok/dekit/releases/download/v0.10.0/dekit-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/596466883" + +[tools."github:pvolok/dekit"."platforms.linux-x64"] +checksum = "sha256:330753d26feb9f96b79a388e730f8bd4414564520257f37bfc997c626b450f44" +url = "https://github.com/pvolok/dekit/releases/download/v0.10.0/dekit-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/596466904" + +[tools."github:pvolok/dekit"."platforms.macos-arm64"] +checksum = "sha256:abdcdf7c1d42139da3a3fc40b95f8000bb9245fa793565f3c18108150cfb645b" +url = "https://github.com/pvolok/dekit/releases/download/v0.10.0/dekit-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/596466890" + +[tools."github:pvolok/dekit"."platforms.macos-x64"] +checksum = "sha256:f88f44751969b4e58ef650c845f905ccf4647d0027bc2f837ab50cdc78259e80" +url = "https://github.com/pvolok/dekit/releases/download/v0.10.0/dekit-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/596466880" + +[tools."github:pvolok/dekit"."platforms.windows-x64"] +checksum = "sha256:9eb6e86513f5dff7b9712ceb62ff2127b8dba057a61d9b600491572a27a2ba62" +url = "https://github.com/pvolok/dekit/releases/download/v0.10.0/dekit-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/596466888" + [[tools."github:utkuozdemir/nvidia_gpu_exporter"]] version = "1.10.0" backend = "github:utkuozdemir/nvidia_gpu_exporter" @@ -1137,6 +1177,38 @@ checksum = "sha256:1fe9ecf3513ef7eaf9fdeb84cfdbb9bd4fa31f4c54271183a68c0075457d6 url = "https://github.com/utkuozdemir/nvidia_gpu_exporter/releases/download/v1.10.0/nvidia_gpu_exporter_1.10.0_windows_x86_64.zip" url_api = "https://api.github.com/repos/utkuozdemir/nvidia_gpu_exporter/releases/assets/467484916" +[[tools."github:uutils/coreutils"]] +version = "0.6.0" +backend = "github:uutils/coreutils" + +[tools."github:uutils/coreutils".options] +asset_pattern = '*-{{ x86_64_arch }}-*{{ os(linux="musl.t", macos="darwin.t", windows="msvc.z") }}*' + +[tools."github:uutils/coreutils"."platforms.linux-arm64"] +checksum = "sha256:47a14a2ed2f64b2341731e0e15f916806b3f50cce0b6ffa2cae9ed531c0c9d33" +url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349507043" + +[tools."github:uutils/coreutils"."platforms.linux-x64"] +checksum = "sha256:6ddc463115e501a3edd368af601be9b32613f1af3b910e63679b7b273882b304" +url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349508975" + +[tools."github:uutils/coreutils"."platforms.macos-arm64"] +checksum = "sha256:70319bbe063c015c8be25fd384478013f6f211fc7507282b6ed12f85eedb99dc" +url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349511606" + +[tools."github:uutils/coreutils"."platforms.macos-x64"] +checksum = "sha256:ffb6b57a6640f32895eaec7a5e31f2191860b036dce27769ddcd3fd2786f2865" +url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349510965" + +[tools."github:uutils/coreutils"."platforms.windows-x64"] +checksum = "sha256:f223058a51e8a2a4b92d9f1a1b2954f7a02b6d0f42e4a7e0413fcdb93be2e287" +url = "https://github.com/uutils/coreutils/releases/download/0.6.0/coreutils-0.6.0-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/uutils/coreutils/releases/assets/349509944" + [[tools."github:uutils/findutils"]] version = "0.8.0" backend = "github:uutils/findutils" @@ -1251,28 +1323,28 @@ url = "https://github.com/zhupanov/agent-lint/releases/download/v4.0.3/agent-lin url_api = "https://api.github.com/repos/zhupanov/agent-lint/releases/assets/487601239" [[tools.go]] -version = "1.26.4" +version = "1.27.1" backend = "core:go" [tools.go."platforms.linux-arm64"] -checksum = "sha256:ef758ae7c6cf9267c9c0ef080b8965f453d89ab2d25d9eb22de4405925238768" -url = "https://dl.google.com/go/go1.26.4.linux-arm64.tar.gz" +checksum = "sha256:3450b45a3f9ee8568792736a5c5e70a1f2e9b36c35a8f74958c03e51d7d92bec" +url = "https://dl.google.com/go/go1.27.1.linux-arm64.tar.gz" [tools.go."platforms.linux-x64"] -checksum = "sha256:1153d3d50e0ac764b447adfe05c2bcf08e889d42a02e0fe0259bd47f6733ad7f" -url = "https://dl.google.com/go/go1.26.4.linux-amd64.tar.gz" +checksum = "sha256:63d339f0da5ab53635a56f2490a7984dfe12dfcff22ad749f63edaf590168445" +url = "https://dl.google.com/go/go1.27.1.linux-amd64.tar.gz" [tools.go."platforms.macos-arm64"] -checksum = "sha256:b62ad2b6d7d2464f12a5bcad7ff47f19d08325773b5efd21610e445a05a9bf53" -url = "https://dl.google.com/go/go1.26.4.darwin-arm64.tar.gz" +checksum = "sha256:ee215d57e0ec269c60cc9ceca68e6bda321ba9ee5afe24f4b0988703c2d87d12" +url = "https://dl.google.com/go/go1.27.1.darwin-arm64.tar.gz" [tools.go."platforms.macos-x64"] -checksum = "sha256:05dc9b5f9997744520aaebb3d5deaa7c755371aebbfb7f97c2511a9f3367538d" -url = "https://dl.google.com/go/go1.26.4.darwin-amd64.tar.gz" +checksum = "sha256:8f8f52c6649542cf027bbc9b9c68d1ec042f9f34808a40413f0b8b3f66f3caa4" +url = "https://dl.google.com/go/go1.27.1.darwin-amd64.tar.gz" [tools.go."platforms.windows-x64"] -checksum = "sha256:3ca8fb4630b07c419cbdd51f754e31363cfcfb83b3a5354d9e895c90be2cc345" -url = "https://dl.google.com/go/go1.26.4.windows-amd64.zip" +checksum = "sha256:a3911b5e0e1b1053f25ed0675f4c1c6aad1e2bfcf253df2b9be4caabd2edd95d" +url = "https://dl.google.com/go/go1.27.1.windows-amd64.zip" [[tools."go:github.com/noperator/jqfmt/cmd/jqfmt"]] version = "0.1.0" @@ -1468,220 +1540,147 @@ checksum = "sha256:94e5cfb9468e597cb513fb7a8bf26499c9315ebd505d960c74e2d4849167b url = "https://github.com/loeffel-io/ls-lint/releases/download/v2.3.1/ls-lint-windows-amd64.exe" url_api = "https://api.github.com/repos/loeffel-io/ls-lint/releases/assets/260857557" -[[tools.lychee]] -version = "0.24.2" -backend = "aqua:lycheeverse/lychee" - -[tools.lychee."platforms.linux-arm64"] -checksum = "sha256:5d0b0e3aeab240f41920c633a6eaf97599be6eedda034b36e858ede7dba5e535" -url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409958602" - -[tools.lychee."platforms.linux-x64"] -checksum = "sha256:73657a111819a30c47c08352896796f23d64e4eb2b3ed39b6d32149241566fc5" -url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409959271" - -[tools.lychee."platforms.macos-arm64"] -checksum = "sha256:c9d3740ea2d891854d37116c9fba840f37b6e7c89d330e7db84ac333631c4977" -url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409957951" - -[tools.lychee."platforms.macos-x64"] -checksum = "sha256:887503a9cff667d322b8d0892b40bf49976eb9507af8483220a3706cdad55978" -url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409957687" - -[tools.lychee."platforms.windows-x64"] -checksum = "sha256:32975d1493ee1a975d6bb41e4fb56fe419cb442ded628bb772ba2e614acfacad" -url = "https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/lycheeverse/lychee/releases/assets/409959491" - -[[tools.mprocs]] -version = "0.9.5" -backend = "aqua:pvolok/mprocs" - -[tools.mprocs."platforms.linux-arm64"] -checksum = "sha256:f4295f1b080ea405e4b607d466b20ca469466e7708e7c6c7b451557e033b2449" -url = "https://github.com/pvolok/dekit/releases/download/v0.9.5/mprocs-0.9.5-linux-aarch64-musl.tar.gz" -url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/434731931" - -[tools.mprocs."platforms.linux-x64"] -checksum = "sha256:12d741fa1fae8f27d4d33c2f8abb2740f83ce71efa9c50f0a107383c5d9fa5fd" -url = "https://github.com/pvolok/dekit/releases/download/v0.9.5/mprocs-0.9.5-linux-x86_64-musl.tar.gz" -url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/434731976" - -[tools.mprocs."platforms.macos-arm64"] -checksum = "sha256:18dff745b3bce0606b1ba90ae75a0eb7979cb61b22b04b5bc5fdf4aea1003b8f" -url = "https://github.com/pvolok/dekit/releases/download/v0.9.5/mprocs-0.9.5-darwin-aarch64.tar.gz" -url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/434731865" - -[tools.mprocs."platforms.macos-x64"] -checksum = "sha256:04ce337c6c1975cd6336ddc63c3c70b08bd080270fde8fa79d17cd14739ceecb" -url = "https://github.com/pvolok/dekit/releases/download/v0.9.5/mprocs-0.9.5-darwin-x86_64.tar.gz" -url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/434731873" - -[tools.mprocs."platforms.windows-x64"] -checksum = "sha256:52be8a524f6616793734f06b6d1146e9b874a2c9742d2327998703b9d3d8cd99" -url = "https://github.com/pvolok/dekit/releases/download/v0.9.5/mprocs-0.9.5-windows-x86_64.zip" -url_api = "https://api.github.com/repos/pvolok/dekit/releases/assets/434732413" - [[tools.node]] -version = "22.22.3" +version = "22.23.3" backend = "core:node" [tools.node."platforms.linux-arm64"] -checksum = "sha256:cc8bc82b2dd0b595c3b95a4c3c9c8c350907cff011afbdee3d1379e812e1e3e3" -url = "https://nodejs.org/dist/v22.22.3/node-v22.22.3-linux-arm64.tar.gz" +checksum = "sha256:5ced2d48d1d7198739b7f86804de0171aefb6823b684b12341d3321afc3cb0b2" +url = "https://nodejs.org/dist/v22.23.3/node-v22.23.3-linux-arm64.tar.gz" [tools.node."platforms.linux-x64"] -checksum = "sha256:c7a10d6816da8eaaa7534dd73c71c6e2b2c391dbbf845e364902d156615dd1b8" -url = "https://nodejs.org/dist/v22.22.3/node-v22.22.3-linux-x64.tar.gz" +checksum = "sha256:1084aa36196bba4c3a5e69a1ee388a6e4ff729dad09445fbcd434b28fe3c24af" +url = "https://nodejs.org/dist/v22.23.3/node-v22.23.3-linux-x64.tar.gz" [tools.node."platforms.macos-arm64"] -checksum = "sha256:0da7ff74ef8611328c8212f17943368713a2ad953fb7d89a8c8a0eae87c23207" -url = "https://nodejs.org/dist/v22.22.3/node-v22.22.3-darwin-arm64.tar.gz" +checksum = "sha256:23b25245dcfb9af7262f8ff142e9e2e0af025368117329e7a7458a51e5922f53" +url = "https://nodejs.org/dist/v22.23.3/node-v22.23.3-darwin-arm64.tar.gz" [tools.node."platforms.macos-x64"] -checksum = "sha256:45830ba752fa0d892c6dcd640946669801293cac820a33591ded40ac075198ec" -url = "https://nodejs.org/dist/v22.22.3/node-v22.22.3-darwin-x64.tar.gz" +checksum = "sha256:8a677b0219178efd6eb0e475457c4afb452b521a92f6e67845a73bd85727f2a8" +url = "https://nodejs.org/dist/v22.23.3/node-v22.23.3-darwin-x64.tar.gz" [tools.node."platforms.windows-x64"] -checksum = "sha256:6c8d54f635feff4df76c2ca80f45332eb2ff57d25226edce36592e51a177ee33" -url = "https://nodejs.org/dist/v22.22.3/node-v22.22.3-win-x64.zip" +checksum = "sha256:2b0ff57b049cda1bbcea2240eec20467018713c1efe1f7360c2681859b90ed71" +url = "https://nodejs.org/dist/v22.23.3/node-v22.23.3-win-x64.zip" [[tools.osv-scanner]] -version = "2.3.8" +version = "2.6.0" backend = "aqua:google/osv-scanner" [tools.osv-scanner."platforms.linux-arm64"] -checksum = "sha256:8158b18edd2d03b1a30d905ca91b032bc62262167be8f206c27114f08823e27c" -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_linux_arm64" -url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/415003008" - -[tools.osv-scanner."platforms.linux-arm64".provenance.slsa] -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/multiple.intoto.jsonl" +checksum = "sha256:2c71403eb443d05891c4f268c3ad771cf4f16e5443463fd7851ef8f454d3c7e4" +url = "https://github.com/google/osv-scanner/releases/download/v2.6.0/osv-scanner_linux_arm64" +url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/562414650" [tools.osv-scanner."platforms.linux-x64"] -checksum = "sha256:bc98e15319ed0d515e3f9235287ba53cdc5535d576d24fd573978ecfe9ab92dc" -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_linux_amd64" -url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/415003010" - -[tools.osv-scanner."platforms.linux-x64".provenance.slsa] -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/multiple.intoto.jsonl" +checksum = "sha256:ca69b3d3cd08f889a49dc0a383122f71cc528b83803671df5fd874d97485b108" +url = "https://github.com/google/osv-scanner/releases/download/v2.6.0/osv-scanner_linux_amd64" +url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/562414718" [tools.osv-scanner."platforms.macos-arm64"] -checksum = "sha256:a8cd6507b06239f463a7642430cfd2d154882f150f6e30cdc0653e28dfc34216" -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_darwin_arm64" -url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/415003041" - -[tools.osv-scanner."platforms.macos-arm64".provenance.slsa] -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/multiple.intoto.jsonl" +checksum = "sha256:98c460dcd37de25819babd757d04542045b6243113e209edcd4d89fedb0256b4" +url = "https://github.com/google/osv-scanner/releases/download/v2.6.0/osv-scanner_darwin_arm64" +url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/562414648" [tools.osv-scanner."platforms.macos-x64"] -checksum = "sha256:b8a80a9f14ca4c0cd0fc2d351b28f740da9e6a5b18385ac9f9d083360b5b504e" -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_darwin_amd64" -url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/415003009" - -[tools.osv-scanner."platforms.macos-x64".provenance.slsa] -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/multiple.intoto.jsonl" +checksum = "sha256:60c5296637e977b28eeda5c7f13573e447659a632922737f94d11fa7e30ad6ca" +url = "https://github.com/google/osv-scanner/releases/download/v2.6.0/osv-scanner_darwin_amd64" +url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/562414712" [tools.osv-scanner."platforms.windows-x64"] -checksum = "sha256:cb04e79dd9698a7bc821bbfdddec916a416d1409fda79c927c509d37d00c9716" -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/osv-scanner_windows_amd64.exe" -url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/415003040" - -[tools.osv-scanner."platforms.windows-x64".provenance.slsa] -url = "https://github.com/google/osv-scanner/releases/download/v2.3.8/multiple.intoto.jsonl" +checksum = "sha256:e0ed7644118b717b028c249ee9d3515024e55e8510747ca08906eb96765354d6" +url = "https://github.com/google/osv-scanner/releases/download/v2.6.0/osv-scanner_windows_amd64.exe" +url_api = "https://api.github.com/repos/google/osv-scanner/releases/assets/562414649" [[tools.pipx]] -version = "1.13.0" +version = "1.17.8" backend = "aqua:pypa/pipx" [tools.pipx."platforms.linux-arm64"] -checksum = "sha256:621ba9b76481d44494a797f8fb25146a3b47d8ba9ddcfb815e821131f1a4f178" -url = "https://github.com/pypa/pipx/releases/download/1.13.0/pipx.pyz" -url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/433441849" +checksum = "sha256:a5827798e78767c7f83c7261400e3521a68c18cae9f6635ad7fe739290cb3e87" +url = "https://github.com/pypa/pipx/releases/download/1.17.8/pipx.pyz" +url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/598951216" [tools.pipx."platforms.linux-x64"] -checksum = "sha256:621ba9b76481d44494a797f8fb25146a3b47d8ba9ddcfb815e821131f1a4f178" -url = "https://github.com/pypa/pipx/releases/download/1.13.0/pipx.pyz" -url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/433441849" +checksum = "sha256:a5827798e78767c7f83c7261400e3521a68c18cae9f6635ad7fe739290cb3e87" +url = "https://github.com/pypa/pipx/releases/download/1.17.8/pipx.pyz" +url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/598951216" [tools.pipx."platforms.macos-arm64"] -checksum = "sha256:621ba9b76481d44494a797f8fb25146a3b47d8ba9ddcfb815e821131f1a4f178" -url = "https://github.com/pypa/pipx/releases/download/1.13.0/pipx.pyz" -url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/433441849" +checksum = "sha256:a5827798e78767c7f83c7261400e3521a68c18cae9f6635ad7fe739290cb3e87" +url = "https://github.com/pypa/pipx/releases/download/1.17.8/pipx.pyz" +url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/598951216" [tools.pipx."platforms.macos-x64"] -checksum = "sha256:621ba9b76481d44494a797f8fb25146a3b47d8ba9ddcfb815e821131f1a4f178" -url = "https://github.com/pypa/pipx/releases/download/1.13.0/pipx.pyz" -url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/433441849" +checksum = "sha256:a5827798e78767c7f83c7261400e3521a68c18cae9f6635ad7fe739290cb3e87" +url = "https://github.com/pypa/pipx/releases/download/1.17.8/pipx.pyz" +url_api = "https://api.github.com/repos/pypa/pipx/releases/assets/598951216" [[tools."pipx:cowsay"]] version = "6.1" backend = "pipx:cowsay" [[tools."pipx:semgrep"]] -version = "1.165.0" +version = "1.178.0" backend = "pipx:semgrep" [[tools.pnpm]] -version = "11.5.1" +version = "11.28.3" backend = "aqua:pnpm/pnpm" [tools.pnpm."platforms.linux-arm64"] -checksum = "sha256:6f1e9d36d12a84aafddbbd024f9e98104aa701c888f05f7df5f4149e2fe87479" -url = "https://github.com/pnpm/pnpm/releases/download/v11.5.1/pnpm-linux-arm64.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/436040142" +checksum = "sha256:f41d5272bdc1d07139daa31412d24bd5394476a4b8b6eb72c269d3bd52e95d4a" +url = "https://github.com/pnpm/pnpm/releases/download/v11.28.3/pnpm-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/601208890" provenance = "github-attestations" [tools.pnpm."platforms.linux-x64"] -checksum = "sha256:5cebc2fa002cabc2008075148427e1aa7baaa7df17dd9f5226e2b1b401e83583" -url = "https://github.com/pnpm/pnpm/releases/download/v11.5.1/pnpm-linux-x64.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/436040141" +checksum = "sha256:b0c9673be13d4b914b8045a56986418c55c446bb8d113b65ec65bf7cb7bec35f" +url = "https://github.com/pnpm/pnpm/releases/download/v11.28.3/pnpm-linux-x64.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/601208877" provenance = "github-attestations" [tools.pnpm."platforms.macos-arm64"] -checksum = "sha256:6533dc62f42eafc1965ef3170fb0bf750ae5c3064d0fd9bcc50bc72c5b95e4c2" -url = "https://github.com/pnpm/pnpm/releases/download/v11.5.1/pnpm-darwin-arm64.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/436040144" +checksum = "sha256:694046ba22f01cfe3cac02930d38a426acc91bb779c70d59cc0f675b36a6bf06" +url = "https://github.com/pnpm/pnpm/releases/download/v11.28.3/pnpm-darwin-arm64.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/601208870" provenance = "github-attestations" [tools.pnpm."platforms.windows-x64"] -checksum = "sha256:776efb770783a262d3de71ee0001460845e8b0ccb9c1a6ceba005fa47dc2d90b" -url = "https://github.com/pnpm/pnpm/releases/download/v11.5.1/pnpm-win32-x64.zip" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/436040143" +checksum = "sha256:adc2abf308ce6ad6301ff573f6dc3c10ab027d47a6004699b36bc2a63314b3be" +url = "https://github.com/pnpm/pnpm/releases/download/v11.28.3/pnpm-win32-x64.zip" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/601208873" provenance = "github-attestations" [[tools.protoc]] -version = "35.0" +version = "36.2" backend = "aqua:protocolbuffers/protobuf/protoc" [tools.protoc."platforms.linux-arm64"] -checksum = "sha256:36b518ac14d90351cc6598228ed2bbe5afe4e357b1af470b07e0ec1609875de2" -url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.0/protoc-35.0-linux-aarch_64.zip" -url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/424567208" +checksum = "sha256:8b8f18bd2b30346efbc698dd5a73dd7c805f3ef8380f6dfc95c768f3f1852f6a" +url = "https://github.com/protocolbuffers/protobuf/releases/download/v36.2/protoc-36.2-linux-aarch_64.zip" +url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/570742403" [tools.protoc."platforms.linux-x64"] -checksum = "sha256:a45cda0989c17dd950db55f6fbe1e5814c50fda08e87aa422980ac1f89dddbbc" -url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.0/protoc-35.0-linux-x86_64.zip" -url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/424567229" +checksum = "sha256:121f6c7afe1d4d0e3ea6aab9432038599250134cbf4474cb1167d2c7decd4278" +url = "https://github.com/protocolbuffers/protobuf/releases/download/v36.2/protoc-36.2-linux-x86_64.zip" +url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/570742434" [tools.protoc."platforms.macos-arm64"] -checksum = "sha256:45444963204757fd3e2fbe304bc1fdadfb488d8556ff099c4cc06575eab88976" -url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.0/protoc-35.0-osx-aarch_64.zip" -url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/424567230" +checksum = "sha256:9cd98a532c5c5e0c4161314de0225de27e4c8a323917b6ea7b1b714d3ae23466" +url = "https://github.com/protocolbuffers/protobuf/releases/download/v36.2/protoc-36.2-osx-aarch_64.zip" +url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/570742436" [tools.protoc."platforms.macos-x64"] -checksum = "sha256:3580c2d115fccb5b0239960c8f70f8da14787b1973a46b2f39c315ad71c11e01" -url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.0/protoc-35.0-osx-x86_64.zip" -url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/424567239" +checksum = "sha256:228cc7add4616cc14ca5e80dee83209d44449a7aee95a914ae748fa374efb078" +url = "https://github.com/protocolbuffers/protobuf/releases/download/v36.2/protoc-36.2-osx-x86_64.zip" +url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/570742448" [tools.protoc."platforms.windows-x64"] -checksum = "sha256:d1cede9e308cc3eb072392af1c02ccae4bdd3d2f374ec2970dbd8cdfdaa91363" -url = "https://github.com/protocolbuffers/protobuf/releases/download/v35.0/protoc-35.0-win64.zip" -url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/424567244" +checksum = "sha256:f0c128dc0d8492eceece83bb459a4c0e316764b929ffbf1aa416357fd644edd3" +url = "https://github.com/protocolbuffers/protobuf/releases/download/v36.2/protoc-36.2-win64.zip" +url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/570742465" [[tools.python]] version = "3.13.14" @@ -1713,62 +1712,62 @@ url = "https://github.com/astral-sh/python-build-standalone/releases/download/20 provenance = "github-attestations" [[tools.rclone]] -version = "1.74.2" +version = "1.75.1" backend = "aqua:rclone/rclone" [tools.rclone."platforms.linux-arm64"] -checksum = "sha256:bc2b2eb8269b743ed7bcea869f3782cfb4931e41efa53fc8befc6dc8308b7a50" -url = "https://github.com/rclone/rclone/releases/download/v1.74.2/rclone-v1.74.2-linux-arm64.zip" -url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/427801689" +checksum = "sha256:03f2504174034b6d004152ed7369251c9a9ec1f7e0836eda420f5c7a5ec0dff9" +url = "https://github.com/rclone/rclone/releases/download/v1.75.1/rclone-v1.75.1-linux-arm64.zip" +url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/544639310" [tools.rclone."platforms.linux-x64"] -checksum = "sha256:72a806370072015ccbe4d81bcd348cc5eaf3beca6c65ba693fd43fb31fcca5b1" -url = "https://github.com/rclone/rclone/releases/download/v1.74.2/rclone-v1.74.2-linux-amd64.zip" -url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/427801449" +checksum = "sha256:982b5aa772841168f8e380f139e9e787b2a105403e32b94da8676a0e1c0a13ab" +url = "https://github.com/rclone/rclone/releases/download/v1.75.1/rclone-v1.75.1-linux-amd64.zip" +url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/544638482" [tools.rclone."platforms.macos-arm64"] -checksum = "sha256:e170fc4f225cbe3685695c4761259fe5883115a2b022a2f39b7298f946b8d898" -url = "https://github.com/rclone/rclone/releases/download/v1.74.2/rclone-v1.74.2-osx-arm64.zip" -url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/427803998" +checksum = "sha256:c61d7a371c62bcbbe882c3423aa4b8bf63485c248dd0f692997b8f0c3f6d0c6f" +url = "https://github.com/rclone/rclone/releases/download/v1.75.1/rclone-v1.75.1-osx-arm64.zip" +url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/544645575" [tools.rclone."platforms.macos-x64"] -checksum = "sha256:fc24831eefa3918c278c4a10be4de78288422426e2f7e64509205167f845874d" -url = "https://github.com/rclone/rclone/releases/download/v1.74.2/rclone-v1.74.2-osx-amd64.zip" -url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/427803849" +checksum = "sha256:29253d0288b8fbbac46baad6e5f6add6cb01d462c79f10805bbd4631c4cdf82c" +url = "https://github.com/rclone/rclone/releases/download/v1.75.1/rclone-v1.75.1-osx-amd64.zip" +url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/544645299" [tools.rclone."platforms.windows-x64"] -checksum = "sha256:71f376f47428bd467bf92e8bfe7fb36f4c108a4fc4edd3df30fc74dd409c7eef" -url = "https://github.com/rclone/rclone/releases/download/v1.74.2/rclone-v1.74.2-windows-amd64.zip" -url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/427804820" +checksum = "sha256:200eb602c126d82aa38b51e0f6b9ae837473ff99b51278d3f6f837574c494d6e" +url = "https://github.com/rclone/rclone/releases/download/v1.75.1/rclone-v1.75.1-windows-amd64.zip" +url_api = "https://api.github.com/repos/rclone/rclone/releases/assets/544647178" [[tools.ripgrep]] -version = "15.1.0" +version = "15.2.0" backend = "aqua:BurntSushi/ripgrep" [tools.ripgrep."platforms.linux-arm64"] -checksum = "sha256:2b661c6ef508e902f388e9098d9c4c5aca72c87b55922d94abdba830b4dc885e" -url = "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-aarch64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/307306472" +checksum = "sha256:a740b91c82eaf9914cfedd353572f2791cbe0162c84101ee0951058f4dcbc90d" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478119579" [tools.ripgrep."platforms.linux-x64"] -checksum = "sha256:1c9297be4a084eea7ecaedf93eb03d058d6faae29bbc57ecdaf5063921491599" -url = "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/307306614" +checksum = "sha256:33e15bcf1624b25cdd2a55813a47a2f95dbe126268203e76aa6a585d1e7b149c" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478120097" [tools.ripgrep."platforms.macos-arm64"] -checksum = "sha256:378e973289176ca0c6054054ee7f631a065874a352bf43f0fa60ef079b6ba715" -url = "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/307305438" +checksum = "sha256:3750b2e93f37e0c692657da574d7019a101c0084da05a790c83fd335bad973e4" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478118851" [tools.ripgrep."platforms.macos-x64"] -checksum = "sha256:64811cb24e77cac3057d6c40b63ac9becf9082eedd54ca411b475b755d334882" -url = "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/307305422" +checksum = "sha256:af7825fcc69a2afc7a7aea55fc9af90e26421d8f20fe59df32e233c0b8a231c1" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478119585" [tools.ripgrep."platforms.windows-x64"] -checksum = "sha256:124510b94b6baa3380d051fdf4650eaa80a302c876d611e9dba0b2e18d87493a" -url = "https://github.com/BurntSushi/ripgrep/releases/download/15.1.0/ripgrep-15.1.0-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/307305871" +checksum = "sha256:71b2fef860abe467217a538ff31de02f5258807c0129f771846f87bd029aafc5" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478119643" [[tools.rust]] version = "nightly-2026-08-05" @@ -1814,48 +1813,48 @@ url = "https://github.com/tamasfe/taplo/releases/download/0.10.0/taplo-windows-x url_api = "https://api.github.com/repos/tamasfe/taplo/releases/assets/257323062" [[tools.typos]] -version = "1.47.0" +version = "1.50.3" backend = "aqua:crate-ci/typos" [tools.typos."platforms.linux-arm64"] -checksum = "sha256:0349ec65605216136b57c3ea6f1a02034e7e8bc128788474b635396997015d54" -url = "https://github.com/crate-ci/typos/releases/download/v1.47.0/typos-v1.47.0-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/432597221" +checksum = "sha256:456f9fe7aa6e7c1597879f5e951d7de2fab261a9ca05f16f324f896c806c55db" +url = "https://github.com/crate-ci/typos/releases/download/v1.50.3/typos-v1.50.3-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/588999780" [tools.typos."platforms.linux-x64"] -checksum = "sha256:6f8a935cea6c60b060082b862a7e777bfd92d939a4fd4194d8085b086dfe24e4" -url = "https://github.com/crate-ci/typos/releases/download/v1.47.0/typos-v1.47.0-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/432596994" +checksum = "sha256:aca6b5d546307092b8d0a8e0a89dd80f9da51f2f7617c5e45c5607c1684ffbf2" +url = "https://github.com/crate-ci/typos/releases/download/v1.50.3/typos-v1.50.3-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/589000924" [tools.typos."platforms.macos-arm64"] -checksum = "sha256:9baa4690960c82cdc3d28bc4744c6ca84df24d99cc1f709869cc14fa8717601a" -url = "https://github.com/crate-ci/typos/releases/download/v1.47.0/typos-v1.47.0-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/432598293" +checksum = "sha256:844d4121fb47a95604aa5566843bb9e3d6078040b3c8f22367709f563038f2c5" +url = "https://github.com/crate-ci/typos/releases/download/v1.50.3/typos-v1.50.3-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/589002568" [tools.typos."platforms.macos-x64"] -checksum = "sha256:aae88e65ed25c091dd4c4a9767b2d36f7913d08f76b38c1bb8ccd189284870d7" -url = "https://github.com/crate-ci/typos/releases/download/v1.47.0/typos-v1.47.0-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/432597671" +checksum = "sha256:7cc75e42fff1e3b66928de325b3ea1ec7e23ce35ffaa3561fdb0ede8e7275f6f" +url = "https://github.com/crate-ci/typos/releases/download/v1.50.3/typos-v1.50.3-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/589006772" [tools.typos."platforms.windows-x64"] -checksum = "sha256:8773b1b3029b1e149b7bd676785b065b236173a7509bc9ab19fa64e638ae989a" -url = "https://github.com/crate-ci/typos/releases/download/v1.47.0/typos-v1.47.0-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/432598600" +checksum = "sha256:b59f149d84e86aab535d52db029fa8d3ac5ecba9ae5c7f19cf07acb5aa0caaaf" +url = "https://github.com/crate-ci/typos/releases/download/v1.50.3/typos-v1.50.3-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/crate-ci/typos/releases/assets/589001623" [[tools.uv]] version = "0.11.8" backend = "aqua:astral-sh/uv" [tools.uv."platforms.linux-arm64"] -checksum = "sha256:29418befb64f926a2dba3473e8e69acd00b36fb845d85344ef11321a993ad8f5" -url = "https://github.com/astral-sh/uv/releases/download/0.11.8/uv-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/406601428" +checksum = "sha256:eee8dd658d20e5ac85fec9c2326b6cbc9d83a1eef09ef07433e58698ac849591" +url = "https://github.com/astral-sh/uv/releases/download/0.11.8/uv-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/406601426" provenance = "github-attestations" [tools.uv."platforms.linux-x64"] -checksum = "sha256:de82507d12e31cfc86c1c776238f7c248e48e40d996dedc812d64fdd31c6ed12" -url = "https://github.com/astral-sh/uv/releases/download/0.11.8/uv-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/406601501" +checksum = "sha256:56dd1b66701ecb62fe896abb919444e4b83c5e8645cca953e6ddd496ff8a0feb" +url = "https://github.com/astral-sh/uv/releases/download/0.11.8/uv-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/406601497" provenance = "github-attestations" [tools.uv."platforms.macos-arm64"] @@ -1877,132 +1876,132 @@ url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/406601496" provenance = "github-attestations" [[tools.wasm-tools]] -version = "1.251.0" +version = "1.260.0" backend = "aqua:bytecodealliance/wasm-tools" [tools.wasm-tools."platforms.linux-arm64"] -checksum = "sha256:9d5cbab8810ffa43b1ad4c57efdd0092c5be6e905d3bd330d7daba5ad7aaa31d" -url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.251.0/wasm-tools-1.251.0-aarch64-linux.tar.gz" -url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/432488906" +checksum = "sha256:804390ca5955c953e0c6a1eb81e2ef15efc7e3747617b363c3ace3caa9b74474" +url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.260.0/wasm-tools-1.260.0-aarch64-linux.tar.gz" +url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/601521114" provenance = "github-attestations" [tools.wasm-tools."platforms.linux-x64"] -checksum = "sha256:08d523676ec71d9afbae05aa4255041ce91bf2d325d87b7e722d190d558be689" -url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.251.0/wasm-tools-1.251.0-x86_64-linux.tar.gz" -url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/432488916" +checksum = "sha256:2112785b5cf397dc348002988ce65c4db48fea728543eb18e4df21f674c7fcdc" +url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.260.0/wasm-tools-1.260.0-x86_64-linux.tar.gz" +url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/601521147" provenance = "github-attestations" [tools.wasm-tools."platforms.macos-arm64"] -checksum = "sha256:ed0fdbdaa80a5c7ef434ac583e1d8df0b8e45d718b08edf28ec27a74e4029897" -url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.251.0/wasm-tools-1.251.0-aarch64-macos.tar.gz" -url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/432488904" +checksum = "sha256:489b726d31f0e30b8a89b30abc797fc2f59fdd8eda9bb87b317cfe6ea9cf9017" +url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.260.0/wasm-tools-1.260.0-aarch64-macos.tar.gz" +url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/601521111" provenance = "github-attestations" [tools.wasm-tools."platforms.macos-x64"] -checksum = "sha256:a0684bfeb104450bec824b9364bbc16aa8a5e6dfe7319024d0990b0d96bc8904" -url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.251.0/wasm-tools-1.251.0-x86_64-macos.tar.gz" -url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/432488918" +checksum = "sha256:de0d4cf1e5386496ee9e33663ef56c0de62280f3884a51ca27beb8324d02cddc" +url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.260.0/wasm-tools-1.260.0-x86_64-macos.tar.gz" +url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/601521152" provenance = "github-attestations" [tools.wasm-tools."platforms.windows-x64"] -checksum = "sha256:3961d881285cad7aaa58e49e8c12667045768ac901cd882dc8311a6c92e634a3" -url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.251.0/wasm-tools-1.251.0-x86_64-windows.zip" -url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/432488922" +checksum = "sha256:2be5f4c662209307e03c8e75521e3f1e03f3a2cef3f35ef30e03d10600942bda" +url = "https://github.com/bytecodealliance/wasm-tools/releases/download/v1.260.0/wasm-tools-1.260.0-x86_64-windows.zip" +url_api = "https://api.github.com/repos/bytecodealliance/wasm-tools/releases/assets/601521168" provenance = "github-attestations" [[tools.watchexec]] -version = "2.5.1" +version = "2.7.3" backend = "aqua:watchexec/watchexec" [tools.watchexec."platforms.linux-arm64"] -checksum = "sha256:c073887583d502fa0b393a8b847bb4460a111b3b0a199d1f70dafd5d89e71a2f" -url = "https://github.com/watchexec/watchexec/releases/download/v2.5.1/watchexec-2.5.1-aarch64-unknown-linux-musl.tar.xz" -url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/384489962" +checksum = "sha256:02b3e2beddf96fef5fb2b88849902e3cf9e96da87968bdfb7a488700d64142cc" +url = "https://github.com/watchexec/watchexec/releases/download/v2.7.3/watchexec-2.7.3-aarch64-unknown-linux-gnu.tar.xz" +url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/565495662" [tools.watchexec."platforms.linux-x64"] -checksum = "sha256:9efabd08de720c1ee7e57b487fe11904f0966828e76146e2b5ea5deee90626be" -url = "https://github.com/watchexec/watchexec/releases/download/v2.5.1/watchexec-2.5.1-x86_64-unknown-linux-musl.tar.xz" -url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/384489936" +checksum = "sha256:8ace3a1d2e752d189f28b6766311d58f155ab977fae66aba60b111ec8aec2f64" +url = "https://github.com/watchexec/watchexec/releases/download/v2.7.3/watchexec-2.7.3-x86_64-unknown-linux-gnu.tar.xz" +url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/565495660" [tools.watchexec."platforms.macos-arm64"] -checksum = "sha256:c5e405dd1109940b2510398d2182990c1be59063b94e11d7ace9c7b435cb1df1" -url = "https://github.com/watchexec/watchexec/releases/download/v2.5.1/watchexec-2.5.1-aarch64-apple-darwin.tar.xz" -url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/384489930" +checksum = "sha256:bb2a3acc02de5c64f87779fc0226274d47d79026c6df969c8c1034a110b2efad" +url = "https://github.com/watchexec/watchexec/releases/download/v2.7.3/watchexec-2.7.3-aarch64-apple-darwin.tar.xz" +url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/565495664" [tools.watchexec."platforms.macos-x64"] -checksum = "sha256:bb74bf33286ff7f31dd8e763e017fbc0418360d88baefd35bc57d662d28394e2" -url = "https://github.com/watchexec/watchexec/releases/download/v2.5.1/watchexec-2.5.1-x86_64-apple-darwin.tar.xz" -url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/384489931" +checksum = "sha256:ddca28bbd6b219a14ffec4893d56dad2e29cfc8b3e47f49e275706c9af20b4c2" +url = "https://github.com/watchexec/watchexec/releases/download/v2.7.3/watchexec-2.7.3-x86_64-apple-darwin.tar.xz" +url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/565495778" [tools.watchexec."platforms.windows-x64"] -checksum = "sha256:aa448c2704ca1a37ce0f1fc75381d9a411946dd293cf6236293f549426a577f7" -url = "https://github.com/watchexec/watchexec/releases/download/v2.5.1/watchexec-2.5.1-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/384489949" +checksum = "sha256:c20d195ffe0a9f90bc3067db2cc0d991c33aaf1591b20531f4aa8999a20bce67" +url = "https://github.com/watchexec/watchexec/releases/download/v2.7.3/watchexec-2.7.3-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/watchexec/watchexec/releases/assets/565495696" [[tools.yq]] -version = "4.53.2" +version = "4.54.1" backend = "aqua:mikefarah/yq" [tools.yq."platforms.linux-arm64"] -checksum = "sha256:03061b2a50c7a498de2bbb92d7cb078ce433011f085a4994117c2726be4106ea" -url = "https://github.com/mikefarah/yq/releases/download/v4.53.2/yq_linux_arm64" -url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/398368442" +checksum = "sha256:189088da0c6429ec5178dfaab1a114805f6cab0b61b165ab236efedf1d57a71b" +url = "https://github.com/mikefarah/yq/releases/download/v4.54.1/yq_linux_arm64" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/597222603" provenance = "cosign" [tools.yq."platforms.linux-x64"] -checksum = "sha256:d56bf5c6819e8e696340c312bd70f849dc1678a7cda9c2ad63eebd906371d56b" -url = "https://github.com/mikefarah/yq/releases/download/v4.53.2/yq_linux_amd64" -url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/398368450" +checksum = "sha256:8e34fc298390875de416e6a4afcb8cabeceb25d9aa8506c1a2f9353cf702ea5f" +url = "https://github.com/mikefarah/yq/releases/download/v4.54.1/yq_linux_amd64" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/597222595" provenance = "cosign" [tools.yq."platforms.macos-arm64"] -checksum = "sha256:541ba2287560df70f561955e2d7f7e1cd00cf2a15a884f6b5c87a4bfa887bc07" -url = "https://github.com/mikefarah/yq/releases/download/v4.53.2/yq_darwin_arm64" -url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/398368449" +checksum = "sha256:fee511a181bd8b3e6b7da98842b41973bfac8cd3bcd341ed29a584620b5b2844" +url = "https://github.com/mikefarah/yq/releases/download/v4.54.1/yq_darwin_arm64" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/597222609" provenance = "cosign" [tools.yq."platforms.macos-x64"] -checksum = "sha256:616b0a0f6a5b79d746f05a169c2b9bb40dee00c605ef165b9a1c1681bba738ac" -url = "https://github.com/mikefarah/yq/releases/download/v4.53.2/yq_darwin_amd64" -url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/398368453" +checksum = "sha256:3a812fce205a4d67014fb71b7fa297092210e580df3d8f52dddc2cf3a599c22b" +url = "https://github.com/mikefarah/yq/releases/download/v4.54.1/yq_darwin_amd64" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/597222619" provenance = "cosign" [tools.yq."platforms.windows-x64"] -checksum = "sha256:2aee32f1de46a20672f48c25df3018839798bd509143f2ce05fdab1550ff5592" -url = "https://github.com/mikefarah/yq/releases/download/v4.53.2/yq_windows_amd64.exe" -url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/398368402" +checksum = "sha256:b645f47ebb3a0d2fbab52998550bbd0a1706f23b5ca5f5b48e638c580bb70928" +url = "https://github.com/mikefarah/yq/releases/download/v4.54.1/yq_windows_amd64.exe" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/597222575" provenance = "cosign" [[tools.zizmor]] -version = "1.25.2" +version = "1.30.1" backend = "aqua:zizmorcore/zizmor" [tools.zizmor."platforms.linux-arm64"] -checksum = "sha256:4b4b9491112c2a09b318101c0d3349b73af1c4f532e097dd6d0164f2abda760d" -url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-aarch64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/421630939" +checksum = "sha256:7ff1dce33bdd18fd2a4affe63bdd47efcccca97b2cec1c1863ec26e9e2647540" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.30.1/zizmor-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/552067643" provenance = "github-attestations" [tools.zizmor."platforms.linux-x64"] -checksum = "sha256:aa1facd105f0d83fe5c55b1adcd9d7417de5d83aa27471f91dc0b66cf3803577" -url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-x86_64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/421630940" +checksum = "sha256:e65324f4430c2717591937edcec90ccbefaf14c174f8ec9415e03ca875b46e1a" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.30.1/zizmor-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/552067642" provenance = "github-attestations" [tools.zizmor."platforms.macos-arm64"] -checksum = "sha256:624ef0e09521aecd862126be0f6d7754669af2646750d68ac48a114be33c3146" -url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/421630938" +checksum = "sha256:e28d22b087f9ebb8d99da6e740d348c930f559961c7c3f12badda54f882195a2" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.30.1/zizmor-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/552067640" provenance = "github-attestations" [tools.zizmor."platforms.macos-x64"] -checksum = "sha256:353271b9ec301dd4ba158af481323c831c6e9b494d5ac3f5aa58cf4b207699cc" -url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/421630941" +checksum = "sha256:10e6b18b11ea07e515a16f0f0518c7b07527bc9977c1fd5698181ce7f3554202" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.30.1/zizmor-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/552067641" provenance = "github-attestations" [tools.zizmor."platforms.windows-x64"] -checksum = "sha256:65d46a8144f701200621b580f632076d80d082d60856de9f88793a95fb5882d7" -url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/421630942" +checksum = "sha256:b183b1e996eddfab9659f1e9b46e059f1ef1cf984a1f14e5da09f7876a4b3a1c" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.30.1/zizmor-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/zizmorcore/zizmor/releases/assets/552067645" provenance = "github-attestations" diff --git a/.mise/mise.macos.lock b/.mise/mise.macos.lock index f2174192..0fc891dc 100644 --- a/.mise/mise.macos.lock +++ b/.mise/mise.macos.lock @@ -8,61 +8,65 @@ checksum = "sha256:a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1 url = "https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_10.conda" checksum = "sha256:24eacc8a20fd7c4616566178562bef7f9344eb4a8700cfc3180fa75a6ff9d39f" +[conda-packages.linux-arm64."icu-78.3-py311h3512406_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda" +checksum = "sha256:54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e" + [conda-packages.linux-arm64."libassuan-3.0.2-h5ad3122_0"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libassuan-3.0.2-h5ad3122_0.conda" checksum = "sha256:042843a7760a9be3e7642528a2667b644f8eda009e1846658726fdca610afb73" -[conda-packages.linux-arm64."libgcc-16.1.0-h205dda4_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.1.0-h205dda4_1.conda" -checksum = "sha256:88a3d400c678df034c9d498f32503779977d5ea826063687c663e42c945abed5" +[conda-packages.linux-arm64."libgcc-16.2.0-h205dda4_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda" +checksum = "sha256:eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1" -[conda-packages.linux-arm64."libgcc-ng-16.1.0-he9431aa_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-16.1.0-he9431aa_1.conda" -checksum = "sha256:e0456b4b49e8f9f9ffc04b1b412101ea2c38476eaceb9a0e4e16792d7cfdd929" +[conda-packages.linux-arm64."libgcc-ng-16.2.0-he9431aa_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-16.2.0-he9431aa_7.conda" +checksum = "sha256:d7502682cfce6f51aabd40bba63cd6b46db3d3e4b67abdb00f54ae72332523db" -[conda-packages.linux-arm64."libgcrypt-1.12.2-h8af1aa0_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-1.12.2-h8af1aa0_0.conda" -checksum = "sha256:842adfd194494490e8c4771dfa1d536ab71a9f3f09b41b3ee4c1b49553326bbb" +[conda-packages.linux-arm64."libgcrypt-1.12.2-h8af1aa0_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-1.12.2-h8af1aa0_2.conda" +checksum = "sha256:327d2239319829def075ca2580b810060bc956036819d771d727352029cf6735" -[conda-packages.linux-arm64."libgcrypt-devel-1.12.2-he30d5cf_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-devel-1.12.2-he30d5cf_0.conda" -checksum = "sha256:8a27549cf1a903f21bbb97f10e3e3b32b23d3b0eda611329760541a1720cc69e" +[conda-packages.linux-arm64."libgcrypt-devel-1.12.2-h5bc82ec_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-devel-1.12.2-h5bc82ec_2.conda" +checksum = "sha256:2dc2ab9e7a58bb9b774e30a4b5a178113f0adbf76c5298e43b1cf0e2f272e8f5" -[conda-packages.linux-arm64."libgcrypt-lib-1.12.2-he30d5cf_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-lib-1.12.2-he30d5cf_0.conda" -checksum = "sha256:5c1fa4dfe58fedf2077a0cc831565f32fe3fede70503fa91bcaf0b0a7ee6a5d9" +[conda-packages.linux-arm64."libgcrypt-lib-1.12.2-h5bc82ec_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-lib-1.12.2-h5bc82ec_2.conda" +checksum = "sha256:26f2981255e575a47c1fb4bcd0f869d0fadfa3ab44a0ab005fe3887f75e7a154" -[conda-packages.linux-arm64."libgcrypt-tools-1.12.2-he30d5cf_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-tools-1.12.2-he30d5cf_0.conda" -checksum = "sha256:580a0806d8048e3fd936e170455bc1993f53c01923a6361115e4280cf43c820a" +[conda-packages.linux-arm64."libgcrypt-tools-1.12.2-h5bc82ec_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcrypt-tools-1.12.2-h5bc82ec_2.conda" +checksum = "sha256:3d566ba1641653f7ec835ee1401397e296c77d47c7b979bc6725c33883fe377a" -[conda-packages.linux-arm64."libgomp-16.1.0-h8acb6b2_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.1.0-h8acb6b2_1.conda" -checksum = "sha256:1c609a4a72597350317b92c4d9dfb85d21740219048e2b1d458925a6ccfa3d7a" +[conda-packages.linux-arm64."libgomp-16.2.0-h8acb6b2_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda" +checksum = "sha256:4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494" [conda-packages.linux-arm64."libgpg-error-1.61-h7ac5ae9_2"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgpg-error-1.61-h7ac5ae9_2.conda" checksum = "sha256:df4c43ae4003100feea4d96000fcfff57f05832b2aa5b9385bba05cb33fa776f" -[conda-packages.linux-arm64."libiconv-1.18-h90929bb_2"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda" -checksum = "sha256:1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9" +[conda-packages.linux-arm64."libiconv-1.18-h1ea5142_3"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h1ea5142_3.conda" +checksum = "sha256:d22c666eb887afd2119aac2110e23a0e817e9391bda99293421f7c46dab1564c" [conda-packages.linux-arm64."libksba-1.6.7-h0a1ffab_0"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libksba-1.6.7-h0a1ffab_0.conda" checksum = "sha256:6bd8c23157e3afa89d56ff876993232d94dc796e1ad190f3cd56148815c7004f" -[conda-packages.linux-arm64."libsqlite-3.53.4-h022381a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.4-h022381a_0.conda" -checksum = "sha256:da46b52f6815e9771f4e21e3332c423c88644e91ac96b0534e85158adc88a8b4" +[conda-packages.linux-arm64."libsqlite-3.53.4-h399dd60_1"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.4-h399dd60_1.conda" +checksum = "sha256:fae75e68e9dbc3c90dcf93d4bae6315f1330c95aaf1404a721e8468266c23475" -[conda-packages.linux-arm64."libstdcxx-16.1.0-hef695bb_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.1.0-hef695bb_1.conda" -checksum = "sha256:81ef9a10a0e01ffc7e03d429ed048410153411b2d8bbf95c334bdf3dcf175ab0" +[conda-packages.linux-arm64."libstdcxx-16.2.0-hef695bb_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda" +checksum = "sha256:b241a3acfa9cdb1359112864a1241225533c92642de3000d52ae65ef5d3a9786" -[conda-packages.linux-arm64."libstdcxx-ng-16.1.0-hdbbeba8_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-16.1.0-hdbbeba8_1.conda" -checksum = "sha256:cb88eb500022e01f835209e771d455d2296e10a18a749f518c257dfcab7d46ba" +[conda-packages.linux-arm64."libstdcxx-ng-16.2.0-hdbbeba8_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-16.2.0-hdbbeba8_7.conda" +checksum = "sha256:cfe644e4cf78302e605f7dc1cfa23ee4edabf5b72f84c92436f5f51c3003542c" [conda-packages.linux-arm64."libzlib-1.3.2-hdc9db2a_3"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda" @@ -80,13 +84,13 @@ checksum = "sha256:1fcbc982059bc5ed7a544ae43a8be6d9ee8d0d4c3fe8fb30eb9185db0aa6e url = "https://conda.anaconda.org/conda-forge/linux-aarch64/ntbtls-0.3.2-hd84c7bf_0.conda" checksum = "sha256:d9af7c17e6c452312a9d623eeff588f427242986fcc39ea65a0ef030dbe8cbe1" -[conda-packages.linux-arm64."readline-8.3-hb682ff5_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda" -checksum = "sha256:fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216" +[conda-packages.linux-arm64."readline-8.3-ha7194a6_1"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-ha7194a6_1.conda" +checksum = "sha256:80167dcf73a96b6d0c1bb2298d7b8b9bc21b27cc5bf56979f9c548b49a4d1722" -[conda-packages.linux-arm64."sqlite-3.53.4-he8854b5_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.4-he8854b5_0.conda" -checksum = "sha256:70bc70e05ec16173ad15e13624d051588dcd2c2f01ef12171234ab04d4c7d888" +[conda-packages.linux-arm64."sqlite-3.53.4-h6ce2f9a_1"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.4-h6ce2f9a_1.conda" +checksum = "sha256:551c79a5cf720c1302bc201f8633c27954a5daeb67be3719023a24ac8fd9f818" [conda-packages.linux-arm64."zlib-1.3.2-hdc9db2a_3"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.3.2-hdc9db2a_3.conda" @@ -108,13 +112,13 @@ checksum = "sha256:9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae url = "https://conda.anaconda.org/conda-forge/linux-64/libassuan-3.0.2-h5888daf_0.conda" checksum = "sha256:a89ee880e951cc9399606545cb9e6377c8f260fa40942b8486d82d64d3d34491" -[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_4"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_4.conda" -checksum = "sha256:24090e675d34403b4ee1cd4372d8f6c0937da7ecfd66a19a57cac2ed0f4ea793" +[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda" +checksum = "sha256:e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea" -[conda-packages.linux-x64."libgcc-ng-16.2.0-h69a702a_4"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_4.conda" -checksum = "sha256:d8e66c14e23f2b3c70410cff5979d9d357e6edfb990b28d8e630852f4d395629" +[conda-packages.linux-x64."libgcc-ng-16.2.0-h69a702a_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-16.2.0-h69a702a_7.conda" +checksum = "sha256:03b54d7008de080a17cc2174b0e4acd6d06e1c981b2eb19846f46d8f59966034" [conda-packages.linux-x64."libgcrypt-1.12.2-ha770c72_2"] url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-1.12.2-ha770c72_2.conda" @@ -132,9 +136,9 @@ checksum = "sha256:a67e7b569f08459fbd62619cbbc14a0e2da9d9e519feb11ee035bb31c653d url = "https://conda.anaconda.org/conda-forge/linux-64/libgcrypt-tools-1.12.2-h7cc23a3_2.conda" checksum = "sha256:781063cd902514ad5c27f30f512d7175f5c51013a1fecb1aa602ca04b583a8f2" -[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_4"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_4.conda" -checksum = "sha256:0fe5cb8e0752241ab55e11656ed1b9726248b522d23b929fe7c95b83eb55b9bb" +[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda" +checksum = "sha256:92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758" [conda-packages.linux-x64."libgpg-error-1.61-h54a6638_2"] url = "https://conda.anaconda.org/conda-forge/linux-64/libgpg-error-1.61-h54a6638_2.conda" @@ -152,13 +156,13 @@ checksum = "sha256:289d4f2bf33134c4f5565f772829cb66c996485723bd9c299a21f73ff8aed url = "https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.4-h13e7031_1.conda" checksum = "sha256:f20d70da54e5b31dd4a51fb1efeaafafd5ab6dd8d7ac9d1438eaa2526ac4ed3d" -[conda-packages.linux-x64."libstdcxx-16.2.0-h934c35e_4"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_4.conda" -checksum = "sha256:40b792b0186c1e8859280a1f6f19a54fc50a11b32724fc7b637009c1a9bd302b" +[conda-packages.linux-x64."libstdcxx-16.2.0-h934c35e_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda" +checksum = "sha256:fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745" -[conda-packages.linux-x64."libstdcxx-ng-16.2.0-hdf11a46_4"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_4.conda" -checksum = "sha256:4cdebd87b76cf53a58a08ebd6d15336daa79c5f0aa34d83a895ac503c0203632" +[conda-packages.linux-x64."libstdcxx-ng-16.2.0-hdf11a46_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-16.2.0-hdf11a46_7.conda" +checksum = "sha256:337f481db36cc357884f05f404ccd1b3a7e0fc1ee48ec5c884e4281d213bc863" [conda-packages.linux-x64."libzlib-1.3.2-h25fd6f3_3"] url = "https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda" @@ -200,45 +204,45 @@ checksum = "sha256:6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416 url = "https://conda.anaconda.org/conda-forge/osx-arm64/libassuan-3.0.2-h286801f_0.conda" checksum = "sha256:0d8ec81850417d106df2cd4d4cb21e1597c8ce9a930bc86857ea504eb8e08dd4" -[conda-packages.macos-arm64."libcxx-22.1.8-h55c6f16_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda" -checksum = "sha256:a2e7abab5add9750fab064c024394de48e49f97631c605ad5db5c8ac3fc769ef" +[conda-packages.macos-arm64."libcxx-23.1.2-h55c6f16_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.2-h55c6f16_0.conda" +checksum = "sha256:087a610bacee7901d259ef72c6f060d795ab26831bd7541ba75ced786a5a63f9" -[conda-packages.macos-arm64."libgcrypt-1.12.2-hce30654_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-1.12.2-hce30654_0.conda" -checksum = "sha256:07eeb66304ef142b988a7e7f4b3d474fe17aff12fddc65ff311c8e64202380f2" +[conda-packages.macos-arm64."libgcrypt-1.12.2-hce30654_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-1.12.2-hce30654_2.conda" +checksum = "sha256:2512a5201146cbe4abccc6e7a7a46bd98424013b5c19363d8204e91c11b0e39a" -[conda-packages.macos-arm64."libgcrypt-devel-1.12.2-h84a0fba_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-devel-1.12.2-h84a0fba_0.conda" -checksum = "sha256:fe42892cea60e4d3e691ea6a4ba9912e545cccd9fedf1c7ae47811b5ac38838b" +[conda-packages.macos-arm64."libgcrypt-devel-1.12.2-hb001647_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-devel-1.12.2-hb001647_2.conda" +checksum = "sha256:2fe60bf669bac3f2d36ea70d78418f71b45afe6ba5d5bb3b4a50b6f2e42e97b4" -[conda-packages.macos-arm64."libgcrypt-lib-1.12.2-h84a0fba_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-lib-1.12.2-h84a0fba_0.conda" -checksum = "sha256:19d7ba7fc7556996ae2f549233110123f0c24408568d7aa89871deeea0835294" +[conda-packages.macos-arm64."libgcrypt-lib-1.12.2-hb001647_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-lib-1.12.2-hb001647_2.conda" +checksum = "sha256:45b1b91ff0b7dcfb2d31ffcdc156be2cb93998d80764f9a1f4bbd6a51e5a318a" -[conda-packages.macos-arm64."libgcrypt-tools-1.12.2-h84a0fba_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-tools-1.12.2-h84a0fba_0.conda" -checksum = "sha256:60c30e25e10f259b7565ff9b6c925ca1933284c307fde8ac666b11fa347a8614" +[conda-packages.macos-arm64."libgcrypt-tools-1.12.2-hb001647_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgcrypt-tools-1.12.2-hb001647_2.conda" +checksum = "sha256:6e972ad2159b0f0f8bfec35814b5b736cbf8aec32c666346074d8eb9f7cca8a5" [conda-packages.macos-arm64."libgpg-error-1.61-h784d473_2"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libgpg-error-1.61-h784d473_2.conda" checksum = "sha256:eb84229d2ac791a4241044dc3ad172389beb4a730cc4a2afb1ddbe51e8233d11" -[conda-packages.macos-arm64."libiconv-1.18-h23cfdf5_2"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda" -checksum = "sha256:de0336e800b2af9a40bdd694b03870ac4a848161b35c8a2325704f123f185f03" +[conda-packages.macos-arm64."libiconv-1.18-he4c29f2_3"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda" +checksum = "sha256:689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f" -[conda-packages.macos-arm64."libintl-0.25.1-h493aca8_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-h493aca8_0.conda" -checksum = "sha256:99d2cebcd8f84961b86784451b010f5f0a795ed1c08f1e7c76fbb3c22abf021a" +[conda-packages.macos-arm64."libintl-0.25.1-hae62183_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libintl-0.25.1-hae62183_2.conda" +checksum = "sha256:b43c6645e668f86d04d5c06d6dc17efe921bbd9244be4b77946d56fb950a3fcc" [conda-packages.macos-arm64."libksba-1.6.7-h00cdb27_0"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libksba-1.6.7-h00cdb27_0.conda" checksum = "sha256:1fb2da81dd151baf940bfb90b9bfe8b14a57ab75d28b95fd5adde89e14b8b288" -[conda-packages.macos-arm64."libsqlite-3.53.4-h1ae2325_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-h1ae2325_0.conda" -checksum = "sha256:745662565e103f290e9dc4263bbd88285082f8cf699854fe2d5f1e35a4a0d326" +[conda-packages.macos-arm64."libsqlite-3.53.4-hca69786_1"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.4-hca69786_1.conda" +checksum = "sha256:839b31d4830e896b4d315b551d27f2bb08026bc946df04bcc360d8627c3ba2cd" [conda-packages.macos-arm64."libzlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda" @@ -256,13 +260,13 @@ checksum = "sha256:e6f12cee635860a2f70dc40ad28d20d80cdabf566dfab2db1ca0489b1fb89 url = "https://conda.anaconda.org/conda-forge/osx-arm64/ntbtls-0.3.2-h1059232_0.conda" checksum = "sha256:3b2343fb4120dd864ceb050123a84943c4cce3f65c0d010d82950af873d6e3f0" -[conda-packages.macos-arm64."readline-8.3-h46df422_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda" -checksum = "sha256:a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477" +[conda-packages.macos-arm64."readline-8.3-h8b90a29_1"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h8b90a29_1.conda" +checksum = "sha256:d6782b430e6dce4fe8c7ac118cd988d5a193eb4a7f60741edfaede58016b6110" -[conda-packages.macos-arm64."sqlite-3.53.4-h77b7338_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/sqlite-3.53.4-h77b7338_0.conda" -checksum = "sha256:fffebc6bbe45dd4462d3a701a0426c224ad75f8d8bcd174860d7f1b277d4ef45" +[conda-packages.macos-arm64."sqlite-3.53.4-ha9f7ffe_1"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/sqlite-3.53.4-ha9f7ffe_1.conda" +checksum = "sha256:4e0c8704a29b6c265e7bdb6508e1d4180570adcc6e031daf182578d3777fb8b1" [conda-packages.macos-arm64."zlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.3.2-h8088a28_3.conda" @@ -276,45 +280,45 @@ checksum = "sha256:4ed83961876dc8844a6f0df49c07b408efbaea275ffb0b37133e24c006990 url = "https://conda.anaconda.org/conda-forge/osx-64/libassuan-3.0.2-h240833e_0.conda" checksum = "sha256:90af38135168c54a1fd4a3adbb0b0d7fd36d53cf575e263ff5227adeca423011" -[conda-packages.macos-x64."libcxx-22.1.8-h19cb2f5_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.8-h19cb2f5_0.conda" -checksum = "sha256:57ee997f1f800cf38abc743c0f0a9ddfe6a101c697c35510452ce6f4ddf96361" +[conda-packages.macos-x64."libcxx-23.1.2-h19cb2f5_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.2-h19cb2f5_0.conda" +checksum = "sha256:0ad8c788c3681674f100820cf5e76fcc8ec88502e7aa64f4776581985009a7be" -[conda-packages.macos-x64."libgcrypt-1.12.2-h694c41f_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-1.12.2-h694c41f_0.conda" -checksum = "sha256:266547a3d4af566e7b24fc39eb4bd4cb2d6074d79247b3ed4c2f4c34aebf8629" +[conda-packages.macos-x64."libgcrypt-1.12.2-h694c41f_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-1.12.2-h694c41f_2.conda" +checksum = "sha256:09c2c02626323c23e6245bafc53cf2b3a8774397f7a7f49e5b615a43993ae6f3" -[conda-packages.macos-x64."libgcrypt-devel-1.12.2-ha1e9b39_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-devel-1.12.2-ha1e9b39_0.conda" -checksum = "sha256:8f571edfa5edbcef92860c81da82e9b1a0324fe5986ca3d3581a1fc36e03bddf" +[conda-packages.macos-x64."libgcrypt-devel-1.12.2-hd115831_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-devel-1.12.2-hd115831_2.conda" +checksum = "sha256:55d86f0eb92b21310e5619f1397ef3d24a851181d29fafcaaaabf2aa38a74307" -[conda-packages.macos-x64."libgcrypt-lib-1.12.2-ha1e9b39_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-lib-1.12.2-ha1e9b39_0.conda" -checksum = "sha256:9573ae8561367da50b95c014fddaa10b0f12b3c1206fc971c606a350ed154a86" +[conda-packages.macos-x64."libgcrypt-lib-1.12.2-hd115831_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-lib-1.12.2-hd115831_2.conda" +checksum = "sha256:234e85de6d138ce426133ac36fbfb220448d7c6b688f3f20504ce1c3c24618ab" -[conda-packages.macos-x64."libgcrypt-tools-1.12.2-ha1e9b39_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-tools-1.12.2-ha1e9b39_0.conda" -checksum = "sha256:fa4bd339b58fc0b5d7f992abcde6f13aeabbf55d0fc72a2ada6b6bc761aa57b8" +[conda-packages.macos-x64."libgcrypt-tools-1.12.2-hd115831_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libgcrypt-tools-1.12.2-hd115831_2.conda" +checksum = "sha256:0128042f831879b66cbc3a1a34a78603c3a9eee8198c6c64bae01114720dd476" [conda-packages.macos-x64."libgpg-error-1.61-h2fb4741_2"] url = "https://conda.anaconda.org/conda-forge/osx-64/libgpg-error-1.61-h2fb4741_2.conda" checksum = "sha256:bb0352e979fa32a15233382cdfac5d933b7884e74a9487fe82d1b76aa2b4b4c4" -[conda-packages.macos-x64."libiconv-1.18-h57a12c2_2"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda" -checksum = "sha256:a1c8cecdf9966921e13f0ae921309a1f415dfbd2b791f2117cf7e8f5e61a48b6" +[conda-packages.macos-x64."libiconv-1.18-h4ae439b_3"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda" +checksum = "sha256:2389e03a58ed0f5e8f2469eb4d4ba80d0af378b38854ae5eee65e5b641244082" -[conda-packages.macos-x64."libintl-0.25.1-h3184127_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h3184127_1.conda" -checksum = "sha256:8c352744517bc62d24539d1ecc813b9fdc8a785c780197c5f0b84ec5b0dfe122" +[conda-packages.macos-x64."libintl-0.25.1-h98e67c8_2"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libintl-0.25.1-h98e67c8_2.conda" +checksum = "sha256:1fad645b88742ad51dbaf9a6709fa9663edd663a4fed6b27c9c4cbc42fa9c514" [conda-packages.macos-x64."libksba-1.6.7-hf036a51_0"] url = "https://conda.anaconda.org/conda-forge/osx-64/libksba-1.6.7-hf036a51_0.conda" checksum = "sha256:cbeb2ae0d4b6e3f2abfcb1ae13c92e84e3cdd87caaad7a7e99e6a80edd35deb1" -[conda-packages.macos-x64."libsqlite-3.53.4-h77d7759_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-h77d7759_0.conda" -checksum = "sha256:5725d44a17d196adba9798a5fd9f692b7039a827cd6145556a072a80e1931c49" +[conda-packages.macos-x64."libsqlite-3.53.4-ha5db789_1"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.53.4-ha5db789_1.conda" +checksum = "sha256:78afe0bf88da66d7df62d39632aa69cb73eb32d923cd1175230ce2978618d9c8" [conda-packages.macos-x64."libzlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda" @@ -332,131 +336,132 @@ checksum = "sha256:d12c2c6d5e6c4447478a451781f8f3da74844873f7ce4d435a22ff95a93ac url = "https://conda.anaconda.org/conda-forge/osx-64/ntbtls-0.3.2-h2d185b6_0.conda" checksum = "sha256:81e664250100203f32a5b74ad8dd41b906b13d8c0e0efbd8aa6c876c4d962fc2" -[conda-packages.macos-x64."readline-8.3-h68b038d_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda" -checksum = "sha256:4614af680aa0920e82b953fece85a03007e0719c3399f13d7de64176874b80d5" +[conda-packages.macos-x64."readline-8.3-h000c2f7_1"] +url = "https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h000c2f7_1.conda" +checksum = "sha256:feb9248a062b7a0738e56339d8c9e87bc9adf8e8c76549fb55b0b2456bec3a57" -[conda-packages.macos-x64."sqlite-3.53.4-hd4d344e_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.53.4-hd4d344e_0.conda" -checksum = "sha256:f791a0485dc7ed05e1ba7230149d2922427777370c74e98df6384b0f73216582" +[conda-packages.macos-x64."sqlite-3.53.4-hdea7a7b_1"] +url = "https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.53.4-hdea7a7b_1.conda" +checksum = "sha256:eada66c9946b1feaff5c50b63902305836f09532a71ccf6461e73dc75b28018e" [conda-packages.macos-x64."zlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/zlib-1.3.2-hbb4bfdb_3.conda" checksum = "sha256:d46ba65a5ebcb4f682f9f0f21943c427eb56e7f9d15aeab8b823294c787dbb0b" [[tools."conda:gnupg"]] -version = "2.5.20" +version = "2.5.24" backend = "conda:gnupg" [tools."conda:gnupg".options] channel = "conda-forge" [tools."conda:gnupg"."platforms.linux-arm64"] -checksum = "sha256:e2517110e56426c60a0f727181af39521f0371630787d281728b1c4920e4bcdb" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/gnupg-2.5.20-hacc8eee_0.conda" +checksum = "sha256:5317940ba41018dd9e8adbaf81386f670430db3c78b100c16d24bf3f5e46dfc3" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/gnupg-2.5.24-hf476e02_0.conda" conda_deps = [ + "npth-1.8-h5ad3122_0", "libksba-1.6.7-h0a1ffab_0", - "readline-8.3-hb682ff5_0", "libassuan-3.0.2-h5ad3122_0", - "npth-1.8-h5ad3122_0", "ntbtls-0.3.2-hd84c7bf_0", "bzip2-1.0.8-h4777abc_10", - "libiconv-1.18-h90929bb_2", - "sqlite-3.53.4-he8854b5_0", - "libsqlite-3.53.4-h022381a_0", - "libstdcxx-16.1.0-hef695bb_1", - "libgcc-16.1.0-h205dda4_1", - "libstdcxx-ng-16.1.0-hdbbeba8_1", - "libgcc-ng-16.1.0-he9431aa_1", - "libgcrypt-lib-1.12.2-he30d5cf_0", + "readline-8.3-ha7194a6_1", + "libiconv-1.18-h1ea5142_3", + "sqlite-3.53.4-h6ce2f9a_1", + "libsqlite-3.53.4-h399dd60_1", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", + "libstdcxx-ng-16.2.0-hdbbeba8_7", + "libgcc-ng-16.2.0-he9431aa_7", + "libgcrypt-lib-1.12.2-h5bc82ec_2", "libgpg-error-1.61-h7ac5ae9_2", "ncurses-6.6-h2b6f883_1", + "icu-78.3-py311h3512406_2", "libzlib-1.3.2-hdc9db2a_3", "zlib-1.3.2-hdc9db2a_3", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libgcrypt-1.12.2-h8af1aa0_0", - "libgcrypt-tools-1.12.2-he30d5cf_0", - "libgcrypt-devel-1.12.2-he30d5cf_0", + "libgomp-16.2.0-h8acb6b2_7", + "libgcrypt-1.12.2-h8af1aa0_2", + "libgcrypt-tools-1.12.2-h5bc82ec_2", + "libgcrypt-devel-1.12.2-h5bc82ec_2", ] [tools."conda:gnupg"."platforms.linux-x64"] -checksum = "sha256:e830077da6c363321320a02a5baa2a9d79f9282bd13b0d7ae867cee94dc2f62a" -url = "https://conda.anaconda.org/conda-forge/linux-64/gnupg-2.5.20-hb3df253_0.conda" +checksum = "sha256:2e6965580eac0911e9ec0630b623e2a3ad30d7c98a3f3dfc05a7dae3d0707e7f" +url = "https://conda.anaconda.org/conda-forge/linux-64/gnupg-2.5.24-h4362557_0.conda" conda_deps = [ + "libassuan-3.0.2-h5888daf_0", "libksba-1.6.7-hac33072_0", "npth-1.8-h5888daf_0", - "libassuan-3.0.2-h5888daf_0", "ntbtls-0.3.2-hfc55251_0", "bzip2-1.0.8-hda65f42_10", "readline-8.3-hd6e31c0_1", "libiconv-1.18-h0cb94f2_3", "sqlite-3.53.4-h9ffa6c4_1", "libsqlite-3.53.4-h13e7031_1", - "libgcc-16.2.0-ha9f2e26_4", - "libgcc-ng-16.2.0-h69a702a_4", - "libstdcxx-16.2.0-h934c35e_4", - "libstdcxx-ng-16.2.0-hdf11a46_4", - "libgpg-error-1.61-h54a6638_2", + "libgcc-16.2.0-ha9f2e26_7", + "libgcc-ng-16.2.0-h69a702a_7", + "libstdcxx-16.2.0-h934c35e_7", + "libstdcxx-ng-16.2.0-hdf11a46_7", "libgcrypt-lib-1.12.2-h7cc23a3_2", + "libgpg-error-1.61-h54a6638_2", "ncurses-6.6-hdb14827_1", "libzlib-1.3.2-h25fd6f3_3", "zlib-1.3.2-h25fd6f3_3", "icu-78.3-py310h44b86e0_2", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.2.0-he0feb66_4", + "libgomp-16.2.0-he0feb66_7", "libgcrypt-1.12.2-ha770c72_2", "libgcrypt-tools-1.12.2-h7cc23a3_2", "libgcrypt-devel-1.12.2-h7cc23a3_2", ] [tools."conda:gnupg"."platforms.macos-arm64"] -checksum = "sha256:a6421d5c29378c503095925ca9636ba89c78f120c1206bd9a12f7bf092b1ce78" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/gnupg-2.5.20-hb8d65fb_0.conda" +checksum = "sha256:3e1b9115df3d4213b19b1fe10022b0584cbf3134348e60335346c7ee5359438d" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/gnupg-2.5.24-h1775f82_0.conda" conda_deps = [ - "ntbtls-0.3.2-h1059232_0", + "npth-1.8-h286801f_0", "libassuan-3.0.2-h286801f_0", "libksba-1.6.7-h00cdb27_0", - "npth-1.8-h286801f_0", - "readline-8.3-h46df422_0", + "ntbtls-0.3.2-h1059232_0", "bzip2-1.0.8-h4e30115_10", - "libiconv-1.18-h23cfdf5_2", - "sqlite-3.53.4-h77b7338_0", - "libsqlite-3.53.4-h1ae2325_0", + "readline-8.3-h8b90a29_1", + "libiconv-1.18-he4c29f2_3", + "sqlite-3.53.4-ha9f7ffe_1", + "libsqlite-3.53.4-hca69786_1", "libgpg-error-1.61-h784d473_2", - "libintl-0.25.1-h493aca8_0", - "libgcrypt-lib-1.12.2-h84a0fba_0", - "libcxx-22.1.8-h55c6f16_0", + "libgcrypt-lib-1.12.2-hb001647_2", + "libcxx-23.1.2-h55c6f16_0", "ncurses-6.6-he64c551_1", "libzlib-1.3.2-h8088a28_3", "zlib-1.3.2-h8088a28_3", "icu-78.3-py310h579977c_2", - "libgcrypt-1.12.2-hce30654_0", - "libgcrypt-tools-1.12.2-h84a0fba_0", - "libgcrypt-devel-1.12.2-h84a0fba_0", + "libgcrypt-1.12.2-hce30654_2", + "libgcrypt-tools-1.12.2-hb001647_2", + "libgcrypt-devel-1.12.2-hb001647_2", + "libintl-0.25.1-hae62183_2", ] [tools."conda:gnupg"."platforms.macos-x64"] -checksum = "sha256:fb71226342ff294a1dac084e4c1bffa9735ee8e32669ece6968c5472452e14d5" -url = "https://conda.anaconda.org/conda-forge/osx-64/gnupg-2.5.20-he74e0c7_0.conda" +checksum = "sha256:26faef1a7427846709eeffa6a03e639695d3c13999b873b94b2e073b665f5d15" +url = "https://conda.anaconda.org/conda-forge/osx-64/gnupg-2.5.24-h4ccb0c0_0.conda" conda_deps = [ - "libassuan-3.0.2-h240833e_0", - "ntbtls-0.3.2-h2d185b6_0", "npth-1.8-h240833e_0", - "readline-8.3-h68b038d_0", + "ntbtls-0.3.2-h2d185b6_0", "libksba-1.6.7-hf036a51_0", + "libassuan-3.0.2-h240833e_0", "bzip2-1.0.8-h374f1ed_10", - "libiconv-1.18-h57a12c2_2", - "sqlite-3.53.4-hd4d344e_0", - "libsqlite-3.53.4-h77d7759_0", - "libcxx-22.1.8-h19cb2f5_0", - "libgcrypt-lib-1.12.2-ha1e9b39_0", + "readline-8.3-h000c2f7_1", + "libiconv-1.18-h4ae439b_3", + "sqlite-3.53.4-hdea7a7b_1", + "libsqlite-3.53.4-ha5db789_1", + "libcxx-23.1.2-h19cb2f5_0", "libgpg-error-1.61-h2fb4741_2", + "libgcrypt-lib-1.12.2-hd115831_2", "ncurses-6.6-hcc0dc9a_1", "libzlib-1.3.2-hbb4bfdb_3", "zlib-1.3.2-hbb4bfdb_3", - "libintl-0.25.1-h3184127_1", - "libgcrypt-1.12.2-h694c41f_0", - "libgcrypt-tools-1.12.2-ha1e9b39_0", - "libgcrypt-devel-1.12.2-ha1e9b39_0", + "libintl-0.25.1-h98e67c8_2", + "libgcrypt-1.12.2-h694c41f_2", + "libgcrypt-tools-1.12.2-hd115831_2", + "libgcrypt-devel-1.12.2-hd115831_2", ] diff --git a/.mise/mise.maint.lock b/.mise/mise.maint.lock index a8a0f5d9..0add90c6 100644 --- a/.mise/mise.maint.lock +++ b/.mise/mise.maint.lock @@ -30,65 +30,64 @@ url = "https://github.com/ducaale/xh/releases/download/v0.26.2/xh-v0.26.2-x86_64 url_api = "https://api.github.com/repos/ducaale/xh/releases/assets/490411898" [[tools."aqua:ip7z/7zip"]] -version = "26.02" +version = "26.03" backend = "aqua:ip7z/7zip" [tools."aqua:ip7z/7zip"."platforms.linux-arm64"] -checksum = "sha256:70ea6cc737ae1495ea2d7eb20ef3120fe579bd3f1a83a9d2362b62ec5bde2bba" -url = "https://github.com/ip7z/7zip/releases/download/26.02/7z2602-linux-arm64.tar.xz" -url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/458363897" +checksum = "sha256:2389ba20e4d8295e8709c20b6263b69bd1ec4972fe38a04ad7a1badbf595b996" +url = "https://github.com/ip7z/7zip/releases/download/26.03/7z2603-linux-arm64.tar.xz" +url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/543966135" [tools."aqua:ip7z/7zip"."platforms.linux-x64"] -checksum = "sha256:41aaba7b1235304ab5aa0624530c67ae829496cd29e875925271efdccc28c03e" -url = "https://github.com/ip7z/7zip/releases/download/26.02/7z2602-linux-x64.tar.xz" -url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/458363910" +checksum = "sha256:dc99eff5008f1ab79bd7084c68513701547a808a89502bf4133683535ab3c695" +url = "https://github.com/ip7z/7zip/releases/download/26.03/7z2603-linux-x64.tar.xz" +url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/543966173" [tools."aqua:ip7z/7zip"."platforms.macos-arm64"] -checksum = "sha256:1cf6760579502f87e591ff5c73a005ec50b3e4d6f507e8b038382d563c3175b9" -url = "https://github.com/ip7z/7zip/releases/download/26.02/7z2602-mac.tar.xz" -url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/458364002" +checksum = "sha256:5ca87677072c59f5602e5c49baa27d4694bacd2259b4e507f0094249d4281480" +url = "https://github.com/ip7z/7zip/releases/download/26.03/7z2603-mac.tar.xz" +url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/543966195" [tools."aqua:ip7z/7zip"."platforms.macos-x64"] -checksum = "sha256:1cf6760579502f87e591ff5c73a005ec50b3e4d6f507e8b038382d563c3175b9" -url = "https://github.com/ip7z/7zip/releases/download/26.02/7z2602-mac.tar.xz" -url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/458364002" +checksum = "sha256:5ca87677072c59f5602e5c49baa27d4694bacd2259b4e507f0094249d4281480" +url = "https://github.com/ip7z/7zip/releases/download/26.03/7z2603-mac.tar.xz" +url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/543966195" [tools."aqua:ip7z/7zip"."platforms.windows-x64"] -checksum = "sha256:081df9e9311dfd9c9e0e98c1c80180b99bb51e4cb24156b5f3057fe3c259d70a" -url = "https://github.com/ip7z/7zip/releases/download/26.02/7z2602-extra.7z" -url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/458363818" +checksum = "sha256:191894e6acb3647ffb69ce630479ff318523b2e2b9890aa7f05c1127c2e59b8f" +url = "https://github.com/ip7z/7zip/releases/download/26.03/7z2603-extra.7z" +url_api = "https://api.github.com/repos/ip7z/7zip/releases/assets/543966125" [[tools.cargo-release]] -version = "1.1.5" +version = "1.1.6" backend = "github:crate-ci/cargo-release" [tools.cargo-release."platforms.linux-arm64"] -checksum = "sha256:d21b6b274b5ec369b465af4882cc31ff1f9c589b5569ea6eb4eac61882b27f9e" -url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.5/cargo-release-v1.1.5-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/510346210" +checksum = "sha256:a74a3dc62204ed1c10e3da644fa6b5dc0abead13d1936e1a21f0decfaf26b983" +url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.6/cargo-release-v1.1.6-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/568871846" provenance = "github-attestations" [tools.cargo-release."platforms.linux-x64"] -checksum = "sha256:229b9979a5dce8ea0baa65a8f91c913bac4f3f6e4c6d925fc0674aeebb1370f3" -url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.5/cargo-release-v1.1.5-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/510346479" +checksum = "sha256:d82672b9f26b9a11f1b080eedeb74ffa3dd02d96ae9fb3cbc180e4a10d5417db" +url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.6/cargo-release-v1.1.6-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/568873165" provenance = "github-attestations" [tools.cargo-release."platforms.macos-arm64"] -checksum = "sha256:85bfeffd63a8d8dd260032e6b5088954ac4c9514db8aef3a7afc76082bc89813" -url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.5/cargo-release-v1.1.5-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/510347358" +checksum = "sha256:2f41e0d9f9538108f943f498af9f923cd6efd7e3ecdd69c7f78516bb29f32c53" +url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.6/cargo-release-v1.1.6-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/568874942" provenance = "github-attestations" -provenance_verified = true [tools.cargo-release."platforms.macos-x64"] -checksum = "sha256:ebfdb4ec6d5aaf625edda0b79c903405e2f1871b490ae772f819d8f4c1386706" -url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.5/cargo-release-v1.1.5-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/510347751" +checksum = "sha256:f1a5544f7b9464bc308caac45ed0a10d4839b6a38d7f83af27cfb72e68efe501" +url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.6/cargo-release-v1.1.6-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/568875686" provenance = "github-attestations" [tools.cargo-release."platforms.windows-x64"] -checksum = "sha256:c77962b37da29549cb3f87364930f3f5cc68d625a776359be48e7fa7ce0dfa4c" -url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.5/cargo-release-v1.1.5-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/510347954" +checksum = "sha256:511ac6eb265f137cf78c74f6488bcdad750e669b5dd63324cc5582ea5a59ab5e" +url = "https://github.com/crate-ci/cargo-release/releases/download/v1.1.6/cargo-release-v1.1.6-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/crate-ci/cargo-release/releases/assets/568875956" provenance = "github-attestations" diff --git a/.mise/mise.python.lock b/.mise/mise.python.lock index f8dc52be..b2ce6ba2 100644 --- a/.mise/mise.python.lock +++ b/.mise/mise.python.lock @@ -28,11 +28,11 @@ version = "0.29.3" backend = "npm:pyodide" [[tools."pipx:componentize-py"]] -version = "0.23.0" +version = "0.25.1" backend = "pipx:componentize-py" [[tools."pipx:datamodel-code-generator"]] -version = "0.61.0" +version = "0.83.0" backend = "pipx:datamodel-code-generator" [tools."pipx:datamodel-code-generator".options] @@ -43,47 +43,47 @@ version = "0.29.0" backend = "pipx:openapi-python-client" [[tools."pipx:pyrefly"]] -version = "1.1.1" +version = "1.3.2" backend = "pipx:pyrefly" [[tools."pipx:pytest"]] -version = "9.0.3" +version = "9.1.1" backend = "pipx:pytest" [[tools."pipx:torch"]] -version = "2.12.1" +version = "2.14.1" backend = "pipx:torch" [[tools.ruff]] -version = "0.16.1" +version = "0.16.9" backend = "aqua:astral-sh/ruff" [tools.ruff."platforms.linux-arm64"] -checksum = "sha256:5929d9f37fc518a3825f33a76ad8092c0555ca045ca1dbf5e680038a402c840c" -url = "https://github.com/astral-sh/ruff/releases/download/0.16.1/ruff-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/495779006" +checksum = "sha256:a13061e8f471b49c9d2aa284c32dd54a0e5534d702d1a44e1d7f4c875569586d" +url = "https://github.com/astral-sh/ruff/releases/download/0.16.9/ruff-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/586787931" provenance = "github-attestations" [tools.ruff."platforms.linux-x64"] -checksum = "sha256:23469683052cd2db1589f15032dd1751b2a3f212062e9fc901b0776d25fb36bc" -url = "https://github.com/astral-sh/ruff/releases/download/0.16.1/ruff-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/495779139" +checksum = "sha256:1bfbb819b5d4f9af501748862276b60e412d336034d99387691a4d4bce7a6f13" +url = "https://github.com/astral-sh/ruff/releases/download/0.16.9/ruff-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/586788051" provenance = "github-attestations" [tools.ruff."platforms.macos-arm64"] -checksum = "sha256:a8df4e8e9f22e3b0ae0b9f165ddaafb7e34df692197a6c1a361e7426f90681d5" -url = "https://github.com/astral-sh/ruff/releases/download/0.16.1/ruff-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/495778992" +checksum = "sha256:33d35394499094cf6eb90f730dc82f11c0fab05d176378ae4f67de985ecc4146" +url = "https://github.com/astral-sh/ruff/releases/download/0.16.9/ruff-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/586787913" provenance = "github-attestations" [tools.ruff."platforms.macos-x64"] -checksum = "sha256:00396fb9db4cb04e07ad277e6b10d845e6767f0a2aae67e1a57aa65fa01334f0" -url = "https://github.com/astral-sh/ruff/releases/download/0.16.1/ruff-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/495779121" +checksum = "sha256:e98ea259a021c87d3a1f8bf18639d2e32dcd45cb2ef1afcb41b13e295de1e2b3" +url = "https://github.com/astral-sh/ruff/releases/download/0.16.9/ruff-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/586788039" provenance = "github-attestations" [tools.ruff."platforms.windows-x64"] -checksum = "sha256:f37898d133acba7df8cbd130abc3b58b98243d7f3ab751087193dde8887955c4" -url = "https://github.com/astral-sh/ruff/releases/download/0.16.1/ruff-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/495779128" +checksum = "sha256:fe5eb06b2f185b0d8035e17df9df0c831e59b3c98f11170206500650218a0b76" +url = "https://github.com/astral-sh/ruff/releases/download/0.16.9/ruff-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/astral-sh/ruff/releases/assets/586788044" provenance = "github-attestations" diff --git a/.mise/mise.windows.lock b/.mise/mise.windows.lock index d39a4061..5b2a5f7e 100644 --- a/.mise/mise.windows.lock +++ b/.mise/mise.windows.lock @@ -4,45 +4,49 @@ url = "https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda" checksum = "sha256:a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068" -[conda-packages.linux-arm64."libclang-cpp22.1-22.1.8-default_h9c9fc99_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.8-default_h9c9fc99_6.conda" -checksum = "sha256:c2340ee1cfe1e2aa146d8cdfe9f4dccc18bef55286b14bbd6aef5db7a93c602c" +[conda-packages.linux-arm64."icu-78.3-py311h3512406_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda" +checksum = "sha256:54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e" -[conda-packages.linux-arm64."libclang13-22.1.8-default_h1f00bc2_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_h1f00bc2_6.conda" -checksum = "sha256:4423fc1f50d4294faa275442e2c2af6824a592bafa97892f452ae307298073b9" +[conda-packages.linux-arm64."libclang-cpp22.1-22.1.8-default_h01b09c7_10"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.8-default_h01b09c7_10.conda" +checksum = "sha256:f6ba66ea249bf4e695f162ceae4594ca05ec61c7849161026a3e757bd70d4770" -[conda-packages.linux-arm64."libgcc-16.1.0-h205dda4_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.1.0-h205dda4_1.conda" -checksum = "sha256:88a3d400c678df034c9d498f32503779977d5ea826063687c663e42c945abed5" +[conda-packages.linux-arm64."libclang13-22.1.8-default_h78195ec_10"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_h78195ec_10.conda" +checksum = "sha256:d0f6c7b90478769c62a579f9bd146153bf0d4738dc96dd59ffe03bf36f988d5a" -[conda-packages.linux-arm64."libgomp-16.1.0-h8acb6b2_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.1.0-h8acb6b2_1.conda" -checksum = "sha256:1c609a4a72597350317b92c4d9dfb85d21740219048e2b1d458925a6ccfa3d7a" +[conda-packages.linux-arm64."libgcc-16.2.0-h205dda4_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda" +checksum = "sha256:eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1" -[conda-packages.linux-arm64."libiconv-1.18-h90929bb_2"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda" -checksum = "sha256:1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9" +[conda-packages.linux-arm64."libgomp-16.2.0-h8acb6b2_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda" +checksum = "sha256:4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494" -[conda-packages.linux-arm64."libllvm22-22.1.8-hfd2ba90_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda" -checksum = "sha256:dc943f1730a27f5fb36682c9852f7196f671c3a9df4a0a7a8f7ba665637c9151" +[conda-packages.linux-arm64."libiconv-1.18-h1ea5142_3"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h1ea5142_3.conda" +checksum = "sha256:d22c666eb887afd2119aac2110e23a0e817e9391bda99293421f7c46dab1564c" + +[conda-packages.linux-arm64."libllvm22-22.1.8-h680871c_3"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-h680871c_3.conda" +checksum = "sha256:ce3b3adf238db44eb054e70f7f82f5959598542b2c31161bb89fb537d15084c9" [conda-packages.linux-arm64."liblzma-5.8.3-he30d5cf_1"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda" checksum = "sha256:f760669fd1cea27f689f411c0d5488e26ce50e382c9b63e4ad348f959850124a" -[conda-packages.linux-arm64."libstdcxx-16.1.0-hef695bb_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.1.0-hef695bb_1.conda" -checksum = "sha256:81ef9a10a0e01ffc7e03d429ed048410153411b2d8bbf95c334bdf3dcf175ab0" +[conda-packages.linux-arm64."libstdcxx-16.2.0-hef695bb_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda" +checksum = "sha256:b241a3acfa9cdb1359112864a1241225533c92642de3000d52ae65ef5d3a9786" -[conda-packages.linux-arm64."libxml2-16-2.15.3-h064b767_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.3-h064b767_0.conda" -checksum = "sha256:96e9bd642c013ce3407c23b3819204ea8a591567d62b49baa4bafb2f1487326c" +[conda-packages.linux-arm64."libxml2-16-2.15.4-h2e5089f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.4-h2e5089f_0.conda" +checksum = "sha256:58bf7fcf64bae7f624a5e2aed860ddea614a8ec13c8c43fe150420a275b8bdb5" -[conda-packages.linux-arm64."libxml2-2.15.3-h9ba8346_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.3-h9ba8346_0.conda" -checksum = "sha256:74aa3c62e0ec4491343b95ce4ca8812ad2f9bb015369e29cb3b4b9b4302d8cb0" +[conda-packages.linux-arm64."libxml2-2.15.4-h92b9305_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.4-h92b9305_0.conda" +checksum = "sha256:3345c88fa9ebb373bcf4069ede898950005fa2d1707e56a13a1ac6339919492f" [conda-packages.linux-arm64."libzlib-1.3.2-hdc9db2a_3"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda" @@ -56,49 +60,45 @@ checksum = "sha256:427fd14bcb3b8659796fecc682716617409350fb5a98e5b7b47558a10d1a2 url = "https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda" checksum = "sha256:1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9" -[conda-packages.linux-x64."icu-78.3-py310h44b86e0_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda" -checksum = "sha256:9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432" - -[conda-packages.linux-x64."libclang-cpp22.1-22.1.8-default_h08c5240_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h08c5240_6.conda" -checksum = "sha256:fc2981a8e45dd232ae88cf2580f7e75c258f4dccdc96f879b68ef0a9b45c9a2b" +[conda-packages.linux-x64."libclang-cpp22.1-22.1.8-default_h0acdd01_10"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h0acdd01_10.conda" +checksum = "sha256:44ed5220e286dbb2886225b4ca2ea8eaac2769ac039e933440bea6ced3dadf95" -[conda-packages.linux-x64."libclang13-22.1.8-default_hd70ba2e_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_hd70ba2e_6.conda" -checksum = "sha256:8475136d3be6c2d16bdb801dcaf8769cb2ba372cad239c89ebd6a58912e14465" +[conda-packages.linux-x64."libclang13-22.1.8-default_h90b978e_10"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_h90b978e_10.conda" +checksum = "sha256:7791cac0802a649d36e44262ec686731e3d712a7b39e24a29e4bb6b4975db27b" -[conda-packages.linux-x64."libgcc-16.1.0-ha9f2e26_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda" -checksum = "sha256:d5cb8475131c31680f8fd30512c418f373064e272e452063276a8fb14c9fa42f" +[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda" +checksum = "sha256:e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea" -[conda-packages.linux-x64."libgomp-16.1.0-he0feb66_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda" -checksum = "sha256:62cb599ad0539d99386515326d9d5e8f51f75a60c69c2131b21df76edf35bd89" +[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda" +checksum = "sha256:92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758" -[conda-packages.linux-x64."libiconv-1.18-h3b78370_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda" -checksum = "sha256:c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f" +[conda-packages.linux-x64."libiconv-1.18-h0cb94f2_3"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda" +checksum = "sha256:f943117edb9cd4d9c61cc972eee5a34291dc55ea7a6e9e38da104995841cbcb6" -[conda-packages.linux-x64."libllvm22-22.1.8-hf7376ad_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda" -checksum = "sha256:e9b5f301d6b001a9b8ce782157f56b75c92c4fbc9eba95dc6345c1139251d13b" +[conda-packages.linux-x64."libllvm22-22.1.8-h474f4eb_3"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-h474f4eb_3.conda" +checksum = "sha256:135b8b9bfed6a20cdbda657ddb4584d483203eb0e4c29e448a60d4bcc762f391" [conda-packages.linux-x64."liblzma-5.8.3-hb03c661_1"] url = "https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda" checksum = "sha256:9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab" -[conda-packages.linux-x64."libstdcxx-16.1.0-h934c35e_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.1.0-h934c35e_1.conda" -checksum = "sha256:79721dd08aeb0ab9e773f1f9ef41cf4e6c17477e3d72319147619045bce05a09" +[conda-packages.linux-x64."libstdcxx-16.2.0-h934c35e_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda" +checksum = "sha256:fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745" -[conda-packages.linux-x64."libxml2-16-2.15.3-hca6bf5a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_0.conda" -checksum = "sha256:3d44f737c5ae52d5af32682cc1530df433f401f8e58a7533926536244127572a" +[conda-packages.linux-x64."libxml2-16-2.15.4-hbdfff7e_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hbdfff7e_0.conda" +checksum = "sha256:b6f96287c408269f5067bb4f7a61693ff5c856152902362964d9807152b9c146" -[conda-packages.linux-x64."libxml2-2.15.3-h49c6c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_0.conda" -checksum = "sha256:3bc5551720c58591f6ea1146f7d1539c734ed1c40e7b9f5cb8cb7e900c509aba" +[conda-packages.linux-x64."libxml2-2.15.4-ha7a5771_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-ha7a5771_0.conda" +checksum = "sha256:db52c038430a508656530fc7b5650ae3e2629875693a6a256cc48dec203f8bfe" [conda-packages.linux-x64."libzlib-1.3.2-h25fd6f3_3"] url = "https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda" @@ -108,6 +108,10 @@ checksum = "sha256:eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc url = "https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda" checksum = "sha256:47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fbc60" +[conda-packages.macos-arm64."icu-78.3-py310h579977c_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda" +checksum = "sha256:6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43" + [conda-packages.macos-arm64."libclang-cpp22.1-22.1.8-default_h79071a4_10"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp22.1-22.1.8-default_h79071a4_10.conda" checksum = "sha256:ec2ee8724deb386a3c6f88a9361565d0a2b1784fa908184c96ad73994c501dcd" @@ -116,29 +120,29 @@ checksum = "sha256:ec2ee8724deb386a3c6f88a9361565d0a2b1784fa908184c96ad73994c501 url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-22.1.8-default_ha685127_10.conda" checksum = "sha256:6439870848c47a21155673cccb2946a92749c0fb9be086a6554394cb94917486" -[conda-packages.macos-arm64."libcxx-23.1.0-h55c6f16_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.0-h55c6f16_0.conda" -checksum = "sha256:d3e5f0b767964af25ef81edffc002f8e822b1a5c55330da1ae3a857f70c4e4ee" +[conda-packages.macos-arm64."libcxx-23.1.2-h55c6f16_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.2-h55c6f16_0.conda" +checksum = "sha256:087a610bacee7901d259ef72c6f060d795ab26831bd7541ba75ced786a5a63f9" [conda-packages.macos-arm64."libiconv-1.18-he4c29f2_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda" checksum = "sha256:689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f" -[conda-packages.macos-arm64."libllvm22-22.1.8-h759d1ac_2"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.8-h759d1ac_2.conda" -checksum = "sha256:0d9f5b0d13e3b6b94132ebe5ce79edbd7790e089249852ce3e061888f1b0a0c5" +[conda-packages.macos-arm64."libllvm22-22.1.8-h759d1ac_3"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.8-h759d1ac_3.conda" +checksum = "sha256:70d7bbba65233fec41fb2294e81351d81b8d7e21206113135604fed4dd7fdcf6" [conda-packages.macos-arm64."liblzma-5.8.3-h8088a28_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda" checksum = "sha256:23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4311" -[conda-packages.macos-arm64."libxml2-16-2.15.3-h6967ea9_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h6967ea9_1.conda" -checksum = "sha256:cda10a8831d2dd908bea43c8d9d32850d8668ba8349f40bc5f59b6bc260f409d" +[conda-packages.macos-arm64."libxml2-16-2.15.4-heb56d2d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda" +checksum = "sha256:8a26f7c94ab849c1930da36c298f4b82e892382b70ae865cd7274188d9d783e2" -[conda-packages.macos-arm64."libxml2-2.15.3-heed7d32_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.3-heed7d32_1.conda" -checksum = "sha256:f438037bd8388b794aca7cdfb4718b2256982926531a6df2f18d0e5315b220ed" +[conda-packages.macos-arm64."libxml2-2.15.4-h550178d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda" +checksum = "sha256:81217fcd4d4abdc69ee63cdb9cdb22e05a20b9ba7a76f596579914a838fe5960" [conda-packages.macos-arm64."libzlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda" @@ -156,29 +160,29 @@ checksum = "sha256:26c70b7c30e12a6e0516de8412e7a0b57f9bfafae5f91bf33051e40bab5b1 url = "https://conda.anaconda.org/conda-forge/osx-64/libclang13-22.1.8-default_hf8c3748_10.conda" checksum = "sha256:724d6a7466beb37e01db20eeeda050580dded77eb780c1811afe69c5272e7a61" -[conda-packages.macos-x64."libcxx-23.1.0-h19cb2f5_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.0-h19cb2f5_0.conda" -checksum = "sha256:da5b60cbdaf8d931e2534f3b17a0d9b5432ebc855509d36618d61a61f1f2909d" +[conda-packages.macos-x64."libcxx-23.1.2-h19cb2f5_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.2-h19cb2f5_0.conda" +checksum = "sha256:0ad8c788c3681674f100820cf5e76fcc8ec88502e7aa64f4776581985009a7be" [conda-packages.macos-x64."libiconv-1.18-h4ae439b_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda" checksum = "sha256:2389e03a58ed0f5e8f2469eb4d4ba80d0af378b38854ae5eee65e5b641244082" -[conda-packages.macos-x64."libllvm22-22.1.8-hd11396f_2"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm22-22.1.8-hd11396f_2.conda" -checksum = "sha256:f74d914951ce3dbbe551003eefad9aaf091f02b9e36ec1e6a7ff299304eb40a4" +[conda-packages.macos-x64."libllvm22-22.1.8-hd11396f_3"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm22-22.1.8-hd11396f_3.conda" +checksum = "sha256:ad09d02257ad9e4d3cf9b4e446a1541019169bf334d3fe2e3e6d702a86901d49" [conda-packages.macos-x64."liblzma-5.8.3-hbb4bfdb_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda" checksum = "sha256:7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa739" -[conda-packages.macos-x64."libxml2-16-2.15.3-h0d7f165_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h0d7f165_1.conda" -checksum = "sha256:83d3723bf7996ba5214daab05502c044bde633ad5e4432d7da8b6609b46926bf" +[conda-packages.macos-x64."libxml2-16-2.15.4-h341e563_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h341e563_0.conda" +checksum = "sha256:bc284057b85e4a0ecc158598d81c3081fa58e9111969a05d3056ab7a8442c837" -[conda-packages.macos-x64."libxml2-2.15.3-h0712280_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.3-h0712280_1.conda" -checksum = "sha256:7e45202bd6344b3f4a6092297d4613df3a2ef8607920d64db932f0886c80c5f9" +[conda-packages.macos-x64."libxml2-2.15.4-h3668fe6_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-h3668fe6_0.conda" +checksum = "sha256:9cf91223637981568c8fbd5c4dbbc1e6137592e919828554ae436bf259aa91d0" [conda-packages.macos-x64."libzlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda" @@ -188,33 +192,37 @@ checksum = "sha256:b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c1 url = "https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda" checksum = "sha256:5277886d9704a624dc9b79ac985861e1e431bdb39a57c082507ab577a138ec6c" -[conda-packages.windows-x64."libclang13-22.1.8-default_h2778606_6"] -url = "https://conda.anaconda.org/conda-forge/win-64/libclang13-22.1.8-default_h2778606_6.conda" -checksum = "sha256:ddab96250fe45da60cf3d94df81d9d0988db157e5feffa29f8e15aea53b50b16" +[conda-packages.windows-x64."icu-78.3-h5112557_2"] +url = "https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda" +checksum = "sha256:75c549b55b673e15de8785a8e5dd85bca7eb612eee0ff4dc8d7bdaa15eacbdbb" -[conda-packages.windows-x64."libiconv-1.18-hc1393d2_2"] -url = "https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda" -checksum = "sha256:0dcdb1a5f01863ac4e8ba006a8b0dc1a02d2221ec3319b5915a1863254d7efa7" +[conda-packages.windows-x64."libclang13-22.1.8-default_hacd6ee9_10"] +url = "https://conda.anaconda.org/conda-forge/win-64/libclang13-22.1.8-default_hacd6ee9_10.conda" +checksum = "sha256:ea5b06187d703c979a75f07f185d60ee0501fdd8d0f9ff5e44c1844d6af0e379" + +[conda-packages.windows-x64."libiconv-1.18-hc1393d2_3"] +url = "https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda" +checksum = "sha256:35e04e3ddac7720fc7c550a1c9f998604299d6a7bd1f3ec9b2825d825061daa2" [conda-packages.windows-x64."liblzma-5.8.3-hfd05255_1"] url = "https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda" checksum = "sha256:d36c4a1e1f80fd08e18a407e03622ff2f34dfdd022da6488ad19603dea19e6d5" -[conda-packages.windows-x64."libxml2-16-2.15.3-h692994f_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda" -checksum = "sha256:8038084c60eda2006d0122d05e3364fe8db0a18935ca6ed0168b5ba5aa33f904" +[conda-packages.windows-x64."libxml2-16-2.15.4-h3cfd58e_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda" +checksum = "sha256:9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac" -[conda-packages.windows-x64."libxml2-2.15.3-hbc0d294_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_0.conda" -checksum = "sha256:da68af9d9d28d65a6916db1bef68f8a25c64c4fdcf759f32a2d2f2f143220adf" +[conda-packages.windows-x64."libxml2-2.15.4-he095d88_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda" +checksum = "sha256:a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88" [conda-packages.windows-x64."libzlib-1.3.2-hfd05255_3"] url = "https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda" checksum = "sha256:0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527" -[conda-packages.windows-x64."llvm-openmp-22.1.8-h4fa8253_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.8-h4fa8253_0.conda" -checksum = "sha256:50c02902bb516eeb56680358f052be38b5bf74b40e78ea4b2a675e84957e7307" +[conda-packages.windows-x64."llvm-openmp-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda" +checksum = "sha256:8b462c021d6bf3f956749d305bd3f52deb82ae2901047c0c7061a21c3550e48f" [conda-packages.windows-x64."m2-bash-5.2.015.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-bash-5.2.015.1-hd8ed1ab_4.conda" @@ -228,10 +236,6 @@ checksum = "sha256:b2b243cd336e58d0c241bb9eb799e30713b8a40806b14d242fadd96804ff8 url = "https://conda.anaconda.org/conda-forge/noarch/m2-brotli-1.1.0.1-hd8ed1ab_4.conda" checksum = "sha256:0d7aeecaff5e2bfd5722937c5532e0f5aa19a2111cfcdda187d3ce71b19e8dd1" -[conda-packages.windows-x64."m2-brotli-1.1.0.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-brotli-1.1.0.2-hc364b38_6.conda" -checksum = "sha256:05060931602ab730640f343c425671a1474ed150cbc52e1d11691ea5916504d6" - [conda-packages.windows-x64."m2-bzip2-1.0.8.4-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-bzip2-1.0.8.4-hd8ed1ab_4.conda" checksum = "sha256:411ea8400b79d4503bd68538250a6d813f996a12127453bacd085b0d174062e5" @@ -240,10 +244,6 @@ checksum = "sha256:411ea8400b79d4503bd68538250a6d813f996a12127453bacd085b0d17406 url = "https://conda.anaconda.org/conda-forge/noarch/m2-ca-certificates-20230311.1-hd8ed1ab_4.conda" checksum = "sha256:f5a25d7e069780632a188043ab4529e99978a1d2e83d4e94976f9c81ce81a2a1" -[conda-packages.windows-x64."m2-ca-certificates-20241223.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-ca-certificates-20241223.1-hc364b38_6.conda" -checksum = "sha256:e5c6636cff5675f0a10870c223117ef3fe4b6fa663af8f453c390779e51b3ae6" - [conda-packages.windows-x64.m2-conda-epoch-20230914-0_x86_64] url = "https://conda.anaconda.org/conda-forge/win-64/m2-conda-epoch-20230914-0_x86_64.conda" checksum = "sha256:5514efb349d06a8dfe7966b64a3076efad461934e35da9e84c0693a36097fe77" @@ -252,26 +252,10 @@ checksum = "sha256:5514efb349d06a8dfe7966b64a3076efad461934e35da9e84c0693a36097f url = "https://conda.anaconda.org/conda-forge/win-64/m2-conda-epoch-20250515-0_x86_64.conda" checksum = "sha256:51e9214548f177db9c3fe70424e3774c95bf19cd69e0e56e83abe2e393228ba1" -[conda-packages.windows-x64."m2-coreutils-8.32.5-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-coreutils-8.32.5-hc364b38_6.conda" -checksum = "sha256:05626edabfe076bd3b1f7f83cd830ed2acc043c48a15450d88a79091f5b718eb" - [conda-packages.windows-x64."m2-coreutils-8.32.5-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-coreutils-8.32.5-hd8ed1ab_4.conda" checksum = "sha256:e55624270e998cffdd45b85859db3376c6f4cb48804425a7fb1c9ead12084c4c" -[conda-packages.windows-x64."m2-curl-8.9.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-curl-8.9.1.1-hc364b38_6.conda" -checksum = "sha256:cb9bb9fbf4007052cb93e81b2f94e6aa27b16960425f13df54f5b1f5f4b84b21" - -[conda-packages.windows-x64."m2-db-6.2.32.5-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-db-6.2.32.5-hc364b38_6.conda" -checksum = "sha256:7b133edebb0ec6d272dc768fe86bce698771cf67c82a10602e013aaa07d68319" - -[conda-packages.windows-x64."m2-file-5.46.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-file-5.46.2-hc364b38_6.conda" -checksum = "sha256:1be9407ff87b399c116debfb14f4d9c9d6053f44313b5a5d52e8ddfc6174b6ed" - [conda-packages.windows-x64."m2-filesystem-2023.02.07.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-filesystem-2023.02.07.1-hd8ed1ab_4.conda" checksum = "sha256:ceee00fe76c4af625640fae7af916afe0f81681eafbd31a4c7134a09c2e1eff5" @@ -280,10 +264,6 @@ checksum = "sha256:ceee00fe76c4af625640fae7af916afe0f81681eafbd31a4c7134a09c2e1e url = "https://conda.anaconda.org/conda-forge/noarch/m2-filesystem-2025.02.23.1-hc364b38_10.conda" checksum = "sha256:762dd93e1d21ce3d8e5350f167aaeb0c7109edb74b8d972bdb8dbc62b7677488" -[conda-packages.windows-x64."m2-findutils-4.9.0.3-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-findutils-4.9.0.3-hc364b38_6.conda" -checksum = "sha256:a80400fd8028465c14623cb67a472bcaa13e6d4782fc3d18f1911ed64343acb9" - [conda-packages.windows-x64."m2-findutils-4.9.0.3-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-findutils-4.9.0.3-hd8ed1ab_4.conda" checksum = "sha256:dbe6545757b0cf9c6791576309db73572af86191f140047a202a1979441e8dbc" @@ -296,18 +276,10 @@ checksum = "sha256:9e13635fd59f1c6a47d745f3480f8b8a27056bcf05074f45efe59f047c42e url = "https://conda.anaconda.org/conda-forge/noarch/m2-gcc-libs-13.3.0.1-hc364b38_6.conda" checksum = "sha256:9d86cd1a0953bfe103375513f6ad4f82ad6392c9a78e12f0d5dc332be10d0569" -[conda-packages.windows-x64."m2-gdbm-1.25.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-gdbm-1.25.1-hc364b38_6.conda" -checksum = "sha256:fc76b0d3b534315c35dfc4134909f363fd26469f68bba0dc9f9bd05b727fa73a" - [conda-packages.windows-x64."m2-gettext-0.22.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-gettext-0.22.1-hd8ed1ab_4.conda" checksum = "sha256:d032c63d4af9366377c29591d95c2f96f8eee311168103d38140231770f8826a" -[conda-packages.windows-x64."m2-gmp-6.3.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-gmp-6.3.0.1-hc364b38_6.conda" -checksum = "sha256:87cd2260241dde076ec802b423a70a4a10d883e753044c3237ca2dc951271069" - [conda-packages.windows-x64."m2-gmp-6.3.0.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-gmp-6.3.0.1-hd8ed1ab_4.conda" checksum = "sha256:468f8ffa090987d5429f5daee6cd17f69fe54c049b3386ca18de016c05e9daeb" @@ -316,38 +288,18 @@ checksum = "sha256:468f8ffa090987d5429f5daee6cd17f69fe54c049b3386ca18de016c05e9d url = "https://conda.anaconda.org/conda-forge/noarch/m2-gzip-1.13.1-hd8ed1ab_4.conda" checksum = "sha256:1f1bf3b50aa363ccc2b0471244d0d2680a85c106709c551d3e5b07b106cf7e0c" -[conda-packages.windows-x64."m2-gzip-1.14.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-gzip-1.14.1-hc364b38_6.conda" -checksum = "sha256:9c33bb370a7dafbc9a5d6a4429c89d258527d3841aa1a4226a0413058e3f922d" - -[conda-packages.windows-x64."m2-heimdal-7.8.0.5-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-heimdal-7.8.0.5-hc364b38_6.conda" -checksum = "sha256:6d4f747b065fc2b3c21c824a38942b7af9ec18e22cfeea549d3be3a177598ab4" - [conda-packages.windows-x64."m2-heimdal-libs-7.8.0.4-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-heimdal-libs-7.8.0.4-hd8ed1ab_4.conda" checksum = "sha256:abb9cd7673e1e6bc019e82b030d4c31744d93160fcc4de99bd3f2163923d97e8" -[conda-packages.windows-x64."m2-heimdal-libs-7.8.0.5-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-heimdal-libs-7.8.0.5-hc364b38_6.conda" -checksum = "sha256:805ca9f957a3c7d15de58c257921184f3a2c9d99e7cc1f3ab0d52dca6ec77f11" - [conda-packages.windows-x64."m2-info-7.0.3.3-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-info-7.0.3.3-hd8ed1ab_4.conda" checksum = "sha256:da5824758f262f26bd4bb434fa0e6508ad3a13ef3452575aa442040759f9b4e8" -[conda-packages.windows-x64."m2-info-7.2.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-info-7.2.1-hc364b38_6.conda" -checksum = "sha256:95264c799ba1e06dd66d63f8d81cb98073dc32007ccceef4500d5503cffe27e4" - [conda-packages.windows-x64."m2-less-643.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-less-643.1-hd8ed1ab_4.conda" checksum = "sha256:758bda01d7867ccb9f98913d33bc3dbed0480d6c0c40bcb903fbd2b0bfe0263c" -[conda-packages.windows-x64."m2-less-668.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-less-668.1-hc364b38_6.conda" -checksum = "sha256:c7cc658de59006e1f0785400d77fff768e0f552b60ffcd07724e713178c297ad" - [conda-packages.windows-x64."m2-libasprintf-0.22.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libasprintf-0.22.1-hd8ed1ab_4.conda" checksum = "sha256:91b16a5470c77fe597c240625a741488fb20d5485ede3fc1d112398f070da45c" @@ -356,66 +308,30 @@ checksum = "sha256:91b16a5470c77fe597c240625a741488fb20d5485ede3fc1d112398f070da url = "https://conda.anaconda.org/conda-forge/noarch/m2-libassuan-2.5.6.1-hd8ed1ab_4.conda" checksum = "sha256:4f21a0d7b4ff280c3a1717cc5131036d47f6015ea32bab8e8bd6d733ffc262be" -[conda-packages.windows-x64."m2-libbz2-1.0.8.4-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libbz2-1.0.8.4-hc364b38_6.conda" -checksum = "sha256:9ab80c267ab97e6ffa483204589c27715fbcb3a1047ba43390aa9810e0e55491" - [conda-packages.windows-x64."m2-libbz2-1.0.8.4-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libbz2-1.0.8.4-hd8ed1ab_4.conda" checksum = "sha256:e522f67925fb2483dfa723e85f6a7f44504aca76061f203d9bba7fcd7cbeeeb5" -[conda-packages.windows-x64."m2-libcbor-0.12.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libcbor-0.12.0.1-hc364b38_6.conda" -checksum = "sha256:e8786387f836269b2077ce1a29e1c7dbd475015a560ba9f64eb083ce633050d8" - [conda-packages.windows-x64."m2-libcurl-8.2.1.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libcurl-8.2.1.1-hd8ed1ab_4.conda" checksum = "sha256:e3b9983c9743896c260eb0c57f6b4c758523590f9ed6924be4c2813404770e3c" -[conda-packages.windows-x64."m2-libcurl-8.9.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libcurl-8.9.1.1-hc364b38_6.conda" -checksum = "sha256:73a303d640e23f8251ce9e479b784713cd369ba36ea16b53cce3a1cbfa702ba1" - [conda-packages.windows-x64."m2-libdb-5.3.28.4-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libdb-5.3.28.4-hd8ed1ab_4.conda" checksum = "sha256:8d649be2aa1724330c7ed1b5d87079a0ee07a8a06f2158b6fe995b2fcce40841" -[conda-packages.windows-x64."m2-libdb-6.2.32.5-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libdb-6.2.32.5-hc364b38_6.conda" -checksum = "sha256:e9e6c3924e232373b7dca0176a13f4aa8113efa4fd38f57c86e963adc93874d0" - [conda-packages.windows-x64."m2-libedit-20221030_3.1.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libedit-20221030_3.1.1-hd8ed1ab_4.conda" checksum = "sha256:d3c88e28eb8210392c4ac12f8140e31cf9af321255da74b576b77405c84f055e" -[conda-packages.windows-x64."m2-libedit-20240808_3.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libedit-20240808_3.1.1-hc364b38_6.conda" -checksum = "sha256:dc03626274c22505811796442c7d8ffb39fced9c32e4a73c6c7c9a7ae2075176" - -[conda-packages.windows-x64."m2-libexpat-2.7.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libexpat-2.7.1.1-hc364b38_6.conda" -checksum = "sha256:41486991d5fdfc0f608627d78417a6ed1ef13a5d6f1ef55a8f6be81a648c1940" - [conda-packages.windows-x64."m2-libffi-3.4.4.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libffi-3.4.4.1-hd8ed1ab_4.conda" checksum = "sha256:127e6de929619953c3cf26cb531ecf196510029ea0434d49022239812304e771" -[conda-packages.windows-x64."m2-libffi-3.4.8.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libffi-3.4.8.1-hc364b38_6.conda" -checksum = "sha256:55ba85ce234efd94e4d934479b624c21ca365545a35093b7e50beaaf544729fd" - -[conda-packages.windows-x64."m2-libfido2-1.16.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libfido2-1.16.0.1-hc364b38_6.conda" -checksum = "sha256:ff084004d3846da8eb52cc31c6875b51105fa891ef5335f759afb173dce1d567" - [conda-packages.windows-x64."m2-libgcrypt-1.9.4.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libgcrypt-1.9.4.1-hd8ed1ab_4.conda" checksum = "sha256:aeaf81e63381273263b752d3ed600d7a8d09390e7bdbf5a27ef3e859b476e1e9" -[conda-packages.windows-x64."m2-libgdbm-1.25.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libgdbm-1.25.1-hc364b38_6.conda" -checksum = "sha256:a563e82bb59732f1e6f6e150af34dd022a877725657dfc91805b98b8d93eaa96" - [conda-packages.windows-x64."m2-libgettextpo-0.22.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libgettextpo-0.22.1-hd8ed1ab_4.conda" checksum = "sha256:9a2c00a37881136509f16efa133e0b9b0db0b8405af63180b84fd47a8a267439" @@ -444,10 +360,6 @@ checksum = "sha256:5eca3afbd2bf2e5253dac18b3880197f7084081571a1e92b20477fdec5a93 url = "https://conda.anaconda.org/conda-forge/noarch/m2-libidn2-2.3.4.2-hd8ed1ab_4.conda" checksum = "sha256:764e550d61876748b04d65e63d2426997cd8d7c9141a2f04c066e202748e511b" -[conda-packages.windows-x64."m2-libidn2-2.3.8.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libidn2-2.3.8.1-hc364b38_6.conda" -checksum = "sha256:b4ea0e94a2ebdf5ef3f07b0f0d162619fa01a9d2229fd4a087bc69da90a994f1" - [conda-packages.windows-x64."m2-libintl-0.22.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libintl-0.22.1-hd8ed1ab_4.conda" checksum = "sha256:e02146ea83aa2242deb8cabe30086e60a82b1573fb404f81d022723f90fce0f6" @@ -464,10 +376,6 @@ checksum = "sha256:fc93ac52b67e924d28ca150ce82e07f42bf65a1d1289089d2f522ce104558 url = "https://conda.anaconda.org/conda-forge/noarch/m2-liblzma-5.4.4.1-hd8ed1ab_4.conda" checksum = "sha256:567376f9f00048f9a226fb3c284020d424edd9fa5347376a1e1e7f7672dbf9e5" -[conda-packages.windows-x64."m2-liblzma-5.8.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-liblzma-5.8.1.1-hc364b38_6.conda" -checksum = "sha256:420d865c1b77d5e4c6c5834d49fa2e3b0c674354eb243cd93d46f1822e089230" - [conda-packages.windows-x64."m2-libnettle-3.9.1.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libnettle-3.9.1.1-hd8ed1ab_4.conda" checksum = "sha256:7b9d0edfb46a1cafe9902abd7c15b79f0e089a14718d3f62eb3016da4749dbd1" @@ -476,10 +384,6 @@ checksum = "sha256:7b9d0edfb46a1cafe9902abd7c15b79f0e089a14718d3f62eb3016da4749d url = "https://conda.anaconda.org/conda-forge/noarch/m2-libnghttp2-1.56.0.1-hd8ed1ab_4.conda" checksum = "sha256:7328aa8f24931075e374e37d4de62088fbf9dfe3d09b31b4379b842328466179" -[conda-packages.windows-x64."m2-libnghttp2-1.65.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libnghttp2-1.65.0.1-hc364b38_6.conda" -checksum = "sha256:a9c046f63f61f34058d3bbd9ef8c80e328442d9289d6abbb2b7654c85604af86" - [conda-packages.windows-x64."m2-libnpth-1.6.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libnpth-1.6.1-hd8ed1ab_4.conda" checksum = "sha256:bae5d4658da526d6e8a7bcd81c6b4817d316b4639ec46d137ee154bdbb9bdb9f" @@ -488,82 +392,42 @@ checksum = "sha256:bae5d4658da526d6e8a7bcd81c6b4817d316b4639ec46d137ee154bdbb9bd url = "https://conda.anaconda.org/conda-forge/noarch/m2-libopenssl-3.1.2.1-hd8ed1ab_4.conda" checksum = "sha256:79990ae22a43a7a362a700ade5cc160bfcecc2610cab91679dd48c6885e69e96" -[conda-packages.windows-x64."m2-libopenssl-3.5.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libopenssl-3.5.0.1-hc364b38_6.conda" -checksum = "sha256:fe7c9a1617056474fbac35a354efdce366a9b7f8447f5a6b714a0406c2601219" - [conda-packages.windows-x64."m2-libp11-kit-0.25.0.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libp11-kit-0.25.0.1-hd8ed1ab_4.conda" checksum = "sha256:73e5dedeb2b2edc276077e560753277b98cf56351c50e00aaccaf69ea2082403" -[conda-packages.windows-x64."m2-libp11-kit-0.25.5.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libp11-kit-0.25.5.2-hc364b38_6.conda" -checksum = "sha256:03d0b5f1f85a934fc18ec4d33bc81c0a8593d90801f9813c663ceb7546b62187" - [conda-packages.windows-x64."m2-libpcre2_8-10.42.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libpcre2_8-10.42.1-hd8ed1ab_4.conda" checksum = "sha256:95868715fb1f7dc9c6f42c68929e6c71e37825e3edf67fca0bc853aaccec3f71" -[conda-packages.windows-x64."m2-libpcre2_8-10.45.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libpcre2_8-10.45.1-hc364b38_6.conda" -checksum = "sha256:5cbaa07cf910cffaab1e0a54c56db67ae0774d04af2ac4408bf10698927d40bf" - [conda-packages.windows-x64."m2-libpsl-0.21.2.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libpsl-0.21.2.1-hd8ed1ab_4.conda" checksum = "sha256:cc652f130ba892adcef3e999e760609440f2f130258afd6f2b9bdc39d6446f75" -[conda-packages.windows-x64."m2-libpsl-0.21.5.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libpsl-0.21.5.2-hc364b38_6.conda" -checksum = "sha256:4bccf2f17d6c6060fa2b84bf0f119911cb1e94db8fbad9f564bbfd9977d9fcc8" - [conda-packages.windows-x64."m2-libreadline-8.2.001.3-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libreadline-8.2.001.3-hd8ed1ab_4.conda" checksum = "sha256:e5482a21ae766583aadac6eb33f46bc5495d46ccba5117a73d2f51bb51ab64d0" -[conda-packages.windows-x64."m2-libreadline-8.2.013.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libreadline-8.2.013.1-hc364b38_6.conda" -checksum = "sha256:f6882fac00b0b132752fa21cc85d0dcbaf384269761dbd92d22cd8cb293e5c87" - [conda-packages.windows-x64."m2-libsqlite-3.42.0.2-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libsqlite-3.42.0.2-hd8ed1ab_4.conda" checksum = "sha256:27afe1095ff49bcff721f03e698dcea2f1156cefc2f6e5bbe662c4defe2ea052" -[conda-packages.windows-x64."m2-libsqlite-3.49.1.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libsqlite-3.49.1.2-hc364b38_6.conda" -checksum = "sha256:92bca185f0c6b3e011c162f2c132219fb3fda4f52210193a244fe39db601e7f3" - [conda-packages.windows-x64."m2-libssh2-1.11.0.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libssh2-1.11.0.1-hd8ed1ab_4.conda" checksum = "sha256:10f24ebc0a6ff1d4fce3be7f153cc416f17483bee01d9adceec882c0c90418d4" -[conda-packages.windows-x64."m2-libssh2-1.11.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libssh2-1.11.1.1-hc364b38_6.conda" -checksum = "sha256:abc9a001a4b5fae3c60e36059677d8013d7ebd9c3a665e18fa3979f1f8d2cf07" - [conda-packages.windows-x64."m2-libtasn1-4.19.0.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libtasn1-4.19.0.1-hd8ed1ab_4.conda" checksum = "sha256:f2134769bc4a0826b850f77027e28e15567124dce6cea8a4ac1b0b1717df80d0" -[conda-packages.windows-x64."m2-libtasn1-4.20.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libtasn1-4.20.0.1-hc364b38_6.conda" -checksum = "sha256:175aa1043a91ab1b784307e50f9796f145dba4dd1484c8955207610709a213df" - [conda-packages.windows-x64."m2-libunistring-1.1.2-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libunistring-1.1.2-hd8ed1ab_4.conda" checksum = "sha256:3e478ef749831ff432ab56e72c6e6b56ddc248361d7fb83a96a17b7a412583f4" -[conda-packages.windows-x64."m2-libunistring-1.3.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libunistring-1.3.1-hc364b38_6.conda" -checksum = "sha256:25f150ca39a1cb120d1911ec1319bdd1794866cc30e4be809535ca96d063157a" - [conda-packages.windows-x64."m2-libxcrypt-4.4.36.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libxcrypt-4.4.36.1-hd8ed1ab_4.conda" checksum = "sha256:3bba99133e838da4986c82cefd1b298275d62a8e7de28fc25909629982815a90" -[conda-packages.windows-x64."m2-libxcrypt-4.4.38.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libxcrypt-4.4.38.1-hc364b38_6.conda" -checksum = "sha256:ed74c3679d61cf0547f667064f9d9a59f620009ca42caa82d1ac89cbd5770168" - [conda-packages.windows-x64."m2-libxml2-2.9.14.5-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-libxml2-2.9.14.5-hd8ed1ab_4.conda" checksum = "sha256:f0876a9109a4f6eff8d9ba464266fb61b9299dc5ad8a34bbcd762ac697aef10a" @@ -576,10 +440,6 @@ checksum = "sha256:52ce758c064548f369f45033b2ec355a20b01385ed4174aec4ad6da774934 url = "https://conda.anaconda.org/conda-forge/noarch/m2-libzstd-1.5.5.1-hd8ed1ab_4.conda" checksum = "sha256:98716894e920de6ddb29f5a9d53cf34ef862a4a10b7efc9dfdb885bd3d17f623" -[conda-packages.windows-x64."m2-libzstd-1.5.7.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-libzstd-1.5.7.1-hc364b38_6.conda" -checksum = "sha256:3dc33acb9d0c484fc58c27c83b1368d966e8cce682337959909a0f2445148a73" - [conda-packages.windows-x64."m2-msys2-runtime-3.4.9.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-msys2-runtime-3.4.9.1-hd8ed1ab_4.conda" checksum = "sha256:e505bf056171089c761b600d21dee062ad1c962b892ca8a7bc852211e3fd3273" @@ -588,174 +448,26 @@ checksum = "sha256:e505bf056171089c761b600d21dee062ad1c962b892ca8a7bc852211e3fd3 url = "https://conda.anaconda.org/conda-forge/noarch/m2-msys2-runtime-3.6.1.4-hc364b38_6.conda" checksum = "sha256:1f797d055ad856def2399d5c1c21d7a479fa68159ce5448f07b7c6cf4b9641d7" -[conda-packages.windows-x64."m2-nano-8.4.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-nano-8.4.1-hc364b38_6.conda" -checksum = "sha256:7fa7127739f8e6165ed348e31249281ea848ddc18fd87aa150ea5bec46ce3503" - [conda-packages.windows-x64."m2-ncurses-6.4.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-ncurses-6.4.1-hd8ed1ab_4.conda" checksum = "sha256:b0411fdfb34fa196445b32f42e46013cb289f8a446760dc8a5acdf3bce095f2d" -[conda-packages.windows-x64."m2-ncurses-6.5.20240831.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-ncurses-6.5.20240831.2-hc364b38_6.conda" -checksum = "sha256:d794dc2cdebc7a6a3e4628afd48492c7fb968cc0a507156e0a7eda270f7b346a" - [conda-packages.windows-x64."m2-nettle-3.9.1.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-nettle-3.9.1.1-hd8ed1ab_4.conda" checksum = "sha256:1eca10294457b5b82b9a0bcb3fc3b6bd7981a1428fdb162ad01dd0ee5efa5470" -[conda-packages.windows-x64."m2-openssh-9.9p2.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-openssh-9.9p2.1-hc364b38_6.conda" -checksum = "sha256:201a47aea8aabc98af5e7f1ca0e74731ba83c3f21014cbc4e5063645743828f2" - [conda-packages.windows-x64."m2-openssl-3.1.2.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-openssl-3.1.2.1-hd8ed1ab_4.conda" checksum = "sha256:e2e87b4c4b6061103e258025a137710e5cb16519476b6bec02f907c86cc4dd24" -[conda-packages.windows-x64."m2-openssl-3.5.0.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-openssl-3.5.0.1-hc364b38_6.conda" -checksum = "sha256:55f037f1147904415235951ac13d9cdf7caeb3bf11fb2556c88709fb9b7e3df2" - [conda-packages.windows-x64."m2-p11-kit-0.25.0.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-p11-kit-0.25.0.1-hd8ed1ab_4.conda" checksum = "sha256:6a839cee1536f6280cd971347856ecbb46e3ce8faa06ac5f41cf6cbfd7c5b905" -[conda-packages.windows-x64."m2-p11-kit-0.25.5.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-p11-kit-0.25.5.2-hc364b38_6.conda" -checksum = "sha256:469ac7a680c9923338706025159fb88417c005f31a00ae9ee7a0c087afa04434" - -[conda-packages.windows-x64."m2-perl-5.38.4.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-5.38.4.2-hc364b38_6.conda" -checksum = "sha256:44615b241d35cf5399ca95f9499158952c7202743c429c91ef86b07c5fe65077" - -[conda-packages.windows-x64."m2-perl-authen-sasl-2.1800.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-authen-sasl-2.1800.1-hc364b38_6.conda" -checksum = "sha256:c0d4426071bd7f3826bee21250bc469acb707edda5d206c1a78ccb07f5e6e0dc" - -[conda-packages.windows-x64."m2-perl-clone-0.47.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-clone-0.47.1-hc364b38_6.conda" -checksum = "sha256:436a79eb844ad340ab2e29d504506c823e5e470a1ae9515e6d85ccc07129251d" - -[conda-packages.windows-x64."m2-perl-convert-binhex-1.125.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-convert-binhex-1.125.2-hc364b38_6.conda" -checksum = "sha256:e75b21d152016de544bfbf02058238dcab4566edb12125172a7ed8d7cc05af40" - -[conda-packages.windows-x64."m2-perl-encode-locale-1.05.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-encode-locale-1.05.2-hc364b38_6.conda" -checksum = "sha256:9f95d61dab4fe0530407016797d8e56c40af930f071066b7baea189d11c6f636" - -[conda-packages.windows-x64."m2-perl-error-0.17030.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-error-0.17030.1-hc364b38_6.conda" -checksum = "sha256:ff5aec00adb471919a8c93074ac7bd5b2a58bf53f6adb23501ab2d2dfaf32331" - -[conda-packages.windows-x64."m2-perl-file-listing-6.16.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-file-listing-6.16.1-hc364b38_6.conda" -checksum = "sha256:126021f9cf8a0efc1e305c51dc1af4a6068a74577fc7da5015144618060617f2" - -[conda-packages.windows-x64."m2-perl-html-parser-3.83.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-html-parser-3.83.1-hc364b38_6.conda" -checksum = "sha256:790cdedea3db6c17f13879f510bd563c7172d23310c9cdeb903140a6fa6300fc" - -[conda-packages.windows-x64."m2-perl-html-tagset-3.24.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-html-tagset-3.24.1-hc364b38_6.conda" -checksum = "sha256:ce1782d6f4559033df89fb6cce2959b2a3f227f811c76d469c3ba86ec8d1bfa1" - -[conda-packages.windows-x64."m2-perl-http-cookiejar-0.014.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-http-cookiejar-0.014.1-hc364b38_6.conda" -checksum = "sha256:c744089b4032b4547afa3b5c16528637aef2dc6708339a443f1a746717949b04" - -[conda-packages.windows-x64."m2-perl-http-cookies-6.11.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-http-cookies-6.11.1-hc364b38_6.conda" -checksum = "sha256:32980a09af1f8c666cbfe8dd8bdcc6af0bb7da6c73c14f78950b8a67ba469481" - -[conda-packages.windows-x64."m2-perl-http-daemon-6.16.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-http-daemon-6.16.1-hc364b38_6.conda" -checksum = "sha256:92a3c360bf6f06e0c3eb044571db6df125d92682b5b8c16ac5b3d895448e98cf" - -[conda-packages.windows-x64."m2-perl-http-date-6.06.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-http-date-6.06.1-hc364b38_6.conda" -checksum = "sha256:964658dc59241be1ee9c2696662e2b1b17a9087cc64587246a60e7aea2ac9467" - -[conda-packages.windows-x64."m2-perl-http-message-7.00.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-http-message-7.00.1-hc364b38_6.conda" -checksum = "sha256:d66932679fff43f55e2714a1cbc2fea9d657332fc22a3a99ce0eed6cd50f6ffd" - -[conda-packages.windows-x64."m2-perl-http-negotiate-6.01.3-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-http-negotiate-6.01.3-hc364b38_6.conda" -checksum = "sha256:6fb4616e6d0acc823d7d1b1055dc4ff430a5cbe4069778f05137083b3c53d3a3" - -[conda-packages.windows-x64."m2-perl-io-html-1.004.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-io-html-1.004.2-hc364b38_6.conda" -checksum = "sha256:1a474819b7f0dbdd6387fa2e2c8858f617576b45318366c87708c3970cfedcde" - -[conda-packages.windows-x64."m2-perl-io-socket-ip-0.41.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-io-socket-ip-0.41.2-hc364b38_6.conda" -checksum = "sha256:3cc7f4c7f46f8f31ba126fe10667842c56f05865770ebc154f9dd2aadb99f8f9" - -[conda-packages.windows-x64."m2-perl-io-socket-ssl-2.089.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-io-socket-ssl-2.089.1-hc364b38_6.conda" -checksum = "sha256:80198485f9ab7a285576d52c725e0969a6408b0f78a93a235fb556b6e9f4b0e1" - -[conda-packages.windows-x64."m2-perl-io-stringy-2.113.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-io-stringy-2.113.2-hc364b38_6.conda" -checksum = "sha256:9075e4eb3657787b3674f4c10c0559fdc58e6b915ecc09dc03190130358fe463" - -[conda-packages.windows-x64."m2-perl-libwww-6.78.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-libwww-6.78.1-hc364b38_6.conda" -checksum = "sha256:a34a50a8300a7baec1e3aec25e296311ce3a20928a7a80b6358607789def2e42" - -[conda-packages.windows-x64."m2-perl-lwp-mediatypes-6.04.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-lwp-mediatypes-6.04.2-hc364b38_6.conda" -checksum = "sha256:c0034a2ef921ad9b3565b25f71d1daa7ec00b136750bfae0c2090b74f08a0a01" - -[conda-packages.windows-x64."m2-perl-mailtools-2.22.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-mailtools-2.22.1-hc364b38_6.conda" -checksum = "sha256:92d6d1890cd254821f6c46eef66dd821f1316d8ac170dd74e293b81daa388ec3" - -[conda-packages.windows-x64."m2-perl-mime-tools-5.515.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-mime-tools-5.515.1-hc364b38_6.conda" -checksum = "sha256:a0997a33f61a9e58d2d502d019ae80ac78738ab3fd9eca96cbae7c99b747b5da" - -[conda-packages.windows-x64."m2-perl-net-http-6.23.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-net-http-6.23.1-hc364b38_6.conda" -checksum = "sha256:6b8289727a217997cbbc55b13e201605f617544af5cd5a9a63e27d20de445845" - -[conda-packages.windows-x64."m2-perl-net-smtp-ssl-1.04.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-net-smtp-ssl-1.04.2-hc364b38_6.conda" -checksum = "sha256:dae3795e7bcb4d7b165e7f0d9c2c5896970b86317d56d95e3e56d7b7e5a8c534" - -[conda-packages.windows-x64."m2-perl-net-ssleay-1.94.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-net-ssleay-1.94.2-hc364b38_6.conda" -checksum = "sha256:de814e91914e23544e0264b4739a45cbad50b374e7d40c8b1ec71145b9661fda" - -[conda-packages.windows-x64."m2-perl-termreadkey-2.38.6-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-termreadkey-2.38.6-hc364b38_6.conda" -checksum = "sha256:006e03b2ccfccb4e56910378359d7cecad5d633f23373c289b25b6bacd473272" - -[conda-packages.windows-x64."m2-perl-timedate-2.33.2-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-timedate-2.33.2-hc364b38_6.conda" -checksum = "sha256:f4124360522dbd8bd5edad11854fa89ac3efa3c2130dafe321fd7283a8943149" - -[conda-packages.windows-x64."m2-perl-try-tiny-0.32.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-try-tiny-0.32.1-hc364b38_6.conda" -checksum = "sha256:ca8126c411c2821e746ec083b8d0e38e5c130b005c4a3db1abefb02399dd51b6" - -[conda-packages.windows-x64."m2-perl-uri-5.31.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-uri-5.31.1-hc364b38_6.conda" -checksum = "sha256:59193376eb2ded21d5195be1aac831e076f1e003febc0562aec4c2555ebc8d13" - -[conda-packages.windows-x64."m2-perl-www-robotrules-6.02.3-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-perl-www-robotrules-6.02.3-hc364b38_6.conda" -checksum = "sha256:8bae4069d3faa7337e6a7707afcf07c24bd7d1b6b7f0c121865ce3dd7ce29567" - [conda-packages.windows-x64."m2-pinentry-1.2.1.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-pinentry-1.2.1.1-hd8ed1ab_4.conda" checksum = "sha256:076982ca19005ca5f8cb1dccee8985c7fb50cba49eb04632b590d82acd4e3b6e" -[conda-packages.windows-x64."m2-sed-4.9.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-sed-4.9.1-hc364b38_6.conda" -checksum = "sha256:5c3ca07ba6bd47e56484f6a1a37bf143c5759340a425fee3043c214d8c5fd322" - [conda-packages.windows-x64."m2-sed-4.9.1-hd8ed1ab_4"] url = "https://conda.anaconda.org/conda-forge/noarch/m2-sed-4.9.1-hd8ed1ab_4.conda" checksum = "sha256:9c133530cb1640f0b8071c8925593db9567ba41db58d07de96535419a58d69a2" @@ -764,10 +476,6 @@ checksum = "sha256:9c133530cb1640f0b8071c8925593db9567ba41db58d07de96535419a58d6 url = "https://conda.anaconda.org/conda-forge/noarch/m2-zlib-1.3.1-hd8ed1ab_4.conda" checksum = "sha256:070fda848e750b96e3b36760b05fbae9399a715bde3f7ad25f997c61efe927fa" -[conda-packages.windows-x64."m2-zlib-1.3.1.1-hc364b38_6"] -url = "https://conda.anaconda.org/conda-forge/noarch/m2-zlib-1.3.1.1-hc364b38_6.conda" -checksum = "sha256:a0bca113400c9c1b856a3cb65abb4b824cddfc88644803cde4da293e5da52fc4" - [conda-packages.windows-x64."ucrt-10.0.26100.0-h57928b3_0"] url = "https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda" checksum = "sha256:3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5" @@ -789,28 +497,28 @@ url = "https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda checksum = "sha256:ca7daae4f218a11fab82cc2857f0ea518ec3f46acec60490485347a4c22c6b3e" [[tools."aqua:WebAssembly/binaryen"]] -version = "131" +version = "133" backend = "aqua:WebAssembly/binaryen" [tools."aqua:WebAssembly/binaryen"."platforms.linux-x64"] -checksum = "sha256:b5bf1f0eaf17c63ee588ff7a5954dc8f6ce2c26989051c66f24dfe9ece3e46db" -url = "https://github.com/WebAssembly/binaryen/releases/download/version_131/binaryen-version_131-x86_64-linux.tar.gz" -url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/478310450" +checksum = "sha256:2dc9c7813f5375db93d96ead4b78222fcc3e2677bbb832297af4797782a37489" +url = "https://github.com/WebAssembly/binaryen/releases/download/version_133/binaryen-version_133-x86_64-linux.tar.gz" +url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/580050094" [tools."aqua:WebAssembly/binaryen"."platforms.macos-arm64"] -checksum = "sha256:e441b48dc22163d209b4f05e44dc7210909b01237642b6c9ae48fd710a3ef83e" -url = "https://github.com/WebAssembly/binaryen/releases/download/version_131/binaryen-version_131-arm64-macos.tar.gz" -url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/478294685" +checksum = "sha256:ad66da82ac13f163e424b1643f16c6dfcccc98b5966296b43e52d3cab04f84a8" +url = "https://github.com/WebAssembly/binaryen/releases/download/version_133/binaryen-version_133-arm64-macos.tar.gz" +url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/580039733" [tools."aqua:WebAssembly/binaryen"."platforms.macos-x64"] -checksum = "sha256:d209fadd8a894bdaf3bd3612a23c32a0af184d2f4a979b8c789e6e4f6a4de883" -url = "https://github.com/WebAssembly/binaryen/releases/download/version_131/binaryen-version_131-x86_64-macos.tar.gz" -url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/478294684" +checksum = "sha256:13a9b90be775c6389ce3d1f879cb8627bea56708ba8c122983941d53a8199b95" +url = "https://github.com/WebAssembly/binaryen/releases/download/version_133/binaryen-version_133-x86_64-macos.tar.gz" +url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/580039734" [tools."aqua:WebAssembly/binaryen"."platforms.windows-x64"] -checksum = "sha256:2f4edac1703a2f695254d6ff52ede03481e67db1f094915763d863158c17d9bc" -url = "https://github.com/WebAssembly/binaryen/releases/download/version_131/binaryen-version_131-x86_64-windows.tar.gz" -url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/478305109" +checksum = "sha256:17a2cbeac6b5693c5fbafab3838d3c65fd9c1eb38b05f5baec6c657e8c84995b" +url = "https://github.com/WebAssembly/binaryen/releases/download/version_133/binaryen-version_133-x86_64-windows.tar.gz" +url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/580050907" [[tools."conda:libclang"]] version = "22.1.8" @@ -820,42 +528,42 @@ backend = "conda:libclang" channel = "conda-forge" [tools."conda:libclang"."platforms.linux-arm64"] -checksum = "sha256:687833e27337baeb60c126931c033a98205b588d7e5435d6bbf0ae59dccfc288" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-22.1.8-default_h4c58ca7_6.conda" +checksum = "sha256:e6e474afa5f3d2e4c53c16ba7c11dfbf67ad920ace61b6b7a61b14a78b28795c" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-22.1.8-default_h95c6a0e_10.conda" conda_deps = [ - "libclang13-22.1.8-default_h1f00bc2_6", - "libclang-cpp22.1-22.1.8-default_h9c9fc99_6", + "libclang13-22.1.8-default_h78195ec_10", + "libclang-cpp22.1-22.1.8-default_h01b09c7_10", "libzlib-1.3.2-hdc9db2a_3", - "libllvm22-22.1.8-hfd2ba90_1", - "libstdcxx-16.1.0-hef695bb_1", - "libgcc-16.1.0-h205dda4_1", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", "zstd-1.5.7-h9d15635_7", - "libxml2-2.15.3-h9ba8346_0", - "libxml2-16-2.15.3-h064b767_0", + "libxml2-2.15.4-h92b9305_0", + "libxml2-16-2.15.4-h2e5089f_0", + "libllvm22-22.1.8-h680871c_3", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libiconv-1.18-h90929bb_2", + "libgomp-16.2.0-h8acb6b2_7", + "icu-78.3-py311h3512406_2", + "libiconv-1.18-h1ea5142_3", "liblzma-5.8.3-he30d5cf_1", ] [tools."conda:libclang"."platforms.linux-x64"] -checksum = "sha256:049f89c9ded7971d20eb3863ac596453ee69f6aa1cdc9cfaa4b39af9653021bf" -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-22.1.8-default_h9d0c7ec_6.conda" +checksum = "sha256:3ab26b095e11e5f48090660a7f90ae3115312a6f561bb6ffced66bc864222346" +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-22.1.8-default_hd5f4932_10.conda" conda_deps = [ - "libclang13-22.1.8-default_hd70ba2e_6", - "libclang-cpp22.1-22.1.8-default_h08c5240_6", + "libclang13-22.1.8-default_h90b978e_10", + "libclang-cpp22.1-22.1.8-default_h0acdd01_10", "libzlib-1.3.2-h25fd6f3_3", - "libllvm22-22.1.8-hf7376ad_1", - "libstdcxx-16.1.0-h934c35e_1", - "libgcc-16.1.0-ha9f2e26_1", + "libstdcxx-16.2.0-h934c35e_7", + "libgcc-16.2.0-ha9f2e26_7", + "libxml2-2.15.4-ha7a5771_0", + "libxml2-16-2.15.4-hbdfff7e_0", "zstd-1.5.7-hb78ec9c_7", - "libxml2-2.15.3-h49c6c72_0", - "libxml2-16-2.15.3-hca6bf5a_0", + "libllvm22-22.1.8-h474f4eb_3", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", - "libiconv-1.18-h3b78370_2", + "libgomp-16.2.0-he0feb66_7", "liblzma-5.8.3-hb03c661_1", - "icu-78.3-py310h44b86e0_2", + "libiconv-1.18-h0cb94f2_3", ] [tools."conda:libclang"."platforms.macos-arm64"] @@ -864,13 +572,14 @@ url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-22.1.8-default_ conda_deps = [ "libclang13-22.1.8-default_ha685127_10", "libclang-cpp22.1-22.1.8-default_h79071a4_10", - "libcxx-23.1.0-h55c6f16_0", "libzlib-1.3.2-h8088a28_3", - "libllvm22-22.1.8-h759d1ac_2", - "libxml2-2.15.3-heed7d32_1", - "libxml2-16-2.15.3-h6967ea9_1", + "libcxx-23.1.2-h55c6f16_0", + "libxml2-2.15.4-h550178d_0", + "libxml2-16-2.15.4-heb56d2d_0", "zstd-1.5.7-hf451053_7", + "libllvm22-22.1.8-h759d1ac_3", "liblzma-5.8.3-h8088a28_1", + "icu-78.3-py310h579977c_2", "libiconv-1.18-he4c29f2_3", ] @@ -880,129 +589,35 @@ url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-22.1.8-default_h56 conda_deps = [ "libclang13-22.1.8-default_hf8c3748_10", "libclang-cpp22.1-22.1.8-default_h6e863b9_10", - "libcxx-23.1.0-h19cb2f5_0", "libzlib-1.3.2-hbb4bfdb_3", - "libllvm22-22.1.8-hd11396f_2", - "libxml2-2.15.3-h0712280_1", - "libxml2-16-2.15.3-h0d7f165_1", + "libcxx-23.1.2-h19cb2f5_0", + "libxml2-2.15.4-h3668fe6_0", + "libxml2-16-2.15.4-h341e563_0", "zstd-1.5.7-hbc1a06c_7", + "libllvm22-22.1.8-hd11396f_3", "liblzma-5.8.3-hbb4bfdb_1", "libiconv-1.18-h4ae439b_3", ] [tools."conda:libclang"."platforms.windows-x64"] -checksum = "sha256:a9af9e0d90a5965a1772c993a6b11399215be766f45805d6fc72878a385b2761" -url = "https://conda.anaconda.org/conda-forge/win-64/libclang-22.1.8-default_hffeb870_6.conda" +checksum = "sha256:9c2c67c378a947dd88a426e76f9180ee64e55807fe27849da7dd23be778ddc7a" +url = "https://conda.anaconda.org/conda-forge/win-64/libclang-22.1.8-default_h6cea73f_10.conda" conda_deps = [ - "llvm-openmp-22.1.8-h4fa8253_0", - "libclang13-22.1.8-default_h2778606_6", + "libclang13-22.1.8-default_hacd6ee9_10", "libzlib-1.3.2-hfd05255_3", "vc-14.5-ha367084_41", "vc14_runtime-14.51.36247-habf1de7_41", "vcomp14-14.51.36247-habf1de7_41", "ucrt-10.0.26100.0-h57928b3_0", - "libxml2-2.15.3-hbc0d294_0", - "libxml2-16-2.15.3-h692994f_0", + "llvm-openmp-23.1.2-h49e36cd_0", "zstd-1.5.7-h534d264_7", - "libiconv-1.18-hc1393d2_2", + "libxml2-2.15.4-he095d88_0", + "libxml2-16-2.15.4-h3cfd58e_0", + "icu-78.3-h5112557_2", + "libiconv-1.18-hc1393d2_3", "liblzma-5.8.3-hfd05255_1", ] -[[tools."conda:m2-git"]] -version = "2.49.0.1" -backend = "conda:m2-git" - -[tools."conda:m2-git".options] -channel = "conda-forge" - -[tools."conda:m2-git"."platforms.windows-x64"] -checksum = "sha256:93f8db405159b1de6b3f5eff0ca7fcb99cdb1fb13c6a8a243373a426abe26cf9" -url = "https://conda.anaconda.org/conda-forge/noarch/m2-git-2.49.0.1-hc364b38_6.conda" -conda_deps = [ - "m2-conda-epoch-20250515-0_x86_64", - "m2-msys2-runtime-3.6.1.4-hc364b38_6", - "m2-perl-termreadkey-2.38.6-hc364b38_6", - "m2-perl-net-smtp-ssl-1.04.2-hc364b38_6", - "m2-perl-mime-tools-5.515.1-hc364b38_6", - "m2-perl-libwww-6.78.1-hc364b38_6", - "m2-perl-authen-sasl-2.1800.1-hc364b38_6", - "m2-perl-5.38.4.2-hc364b38_6", - "m2-perl-error-0.17030.1-hc364b38_6", - "m2-openssl-3.5.0.1-hc364b38_6", - "m2-openssh-9.9p2.1-hc364b38_6", - "m2-nano-8.4.1-hc364b38_6", - "m2-libintl-0.22.5.1-hc364b38_6", - "m2-libexpat-2.7.1.1-hc364b38_6", - "m2-libpcre2_8-10.45.1-hc364b38_6", - "m2-curl-8.9.1.1-hc364b38_6", - "m2-perl-http-cookiejar-0.014.1-hc364b38_6", - "m2-perl-io-socket-ssl-2.089.1-hc364b38_6", - "m2-perl-convert-binhex-1.125.2-hc364b38_6", - "m2-perl-io-stringy-2.113.2-hc364b38_6", - "m2-perl-mailtools-2.22.1-hc364b38_6", - "m2-perl-try-tiny-0.32.1-hc364b38_6", - "m2-perl-http-message-7.00.1-hc364b38_6", - "m2-perl-www-robotrules-6.02.3-hc364b38_6", - "m2-perl-uri-5.31.1-hc364b38_6", - "m2-perl-net-http-6.23.1-hc364b38_6", - "m2-perl-lwp-mediatypes-6.04.2-hc364b38_6", - "m2-perl-http-negotiate-6.01.3-hc364b38_6", - "m2-perl-http-date-6.06.1-hc364b38_6", - "m2-perl-http-daemon-6.16.1-hc364b38_6", - "m2-perl-http-cookies-6.11.1-hc364b38_6", - "m2-perl-html-parser-3.83.1-hc364b38_6", - "m2-perl-file-listing-6.16.1-hc364b38_6", - "m2-perl-encode-locale-1.05.2-hc364b38_6", - "m2-bash-5.2.037.2-hc364b38_6", - "m2-coreutils-8.32.5-hc364b38_6", - "m2-libxcrypt-4.4.38.1-hc364b38_6", - "m2-gdbm-1.25.1-hc364b38_6", - "m2-db-6.2.32.5-hc364b38_6", - "m2-libopenssl-3.5.0.1-hc364b38_6", - "m2-libfido2-1.16.0.1-hc364b38_6", - "m2-libedit-20240808_3.1.1-hc364b38_6", - "m2-heimdal-7.8.0.5-hc364b38_6", - "m2-ncurses-6.5.20240831.2-hc364b38_6", - "m2-file-5.46.2-hc364b38_6", - "m2-libiconv-1.18.1-hc364b38_6", - "m2-gcc-libs-13.3.0.1-hc364b38_6", - "m2-zlib-1.3.1.1-hc364b38_6", - "m2-libpsl-0.21.5.2-hc364b38_6", - "m2-libnghttp2-1.65.0.1-hc364b38_6", - "m2-libunistring-1.3.1-hc364b38_6", - "m2-libcurl-8.9.1.1-hc364b38_6", - "m2-ca-certificates-20241223.1-hc364b38_6", - "m2-libgdbm-1.25.1-hc364b38_6", - "m2-libdb-6.2.32.5-hc364b38_6", - "m2-perl-net-ssleay-1.94.2-hc364b38_6", - "m2-perl-timedate-2.33.2-hc364b38_6", - "m2-perl-io-html-1.004.2-hc364b38_6", - "m2-perl-clone-0.47.1-hc364b38_6", - "m2-perl-io-socket-ip-0.41.2-hc364b38_6", - "m2-perl-html-tagset-3.24.1-hc364b38_6", - "m2-gmp-6.3.0.1-hc364b38_6", - "m2-libcbor-0.12.0.1-hc364b38_6", - "m2-heimdal-libs-7.8.0.5-hc364b38_6", - "m2-libzstd-1.5.7.1-hc364b38_6", - "m2-liblzma-5.8.1.1-hc364b38_6", - "m2-libbz2-1.0.8.4-hc364b38_6", - "m2-libidn2-2.3.8.1-hc364b38_6", - "m2-libssh2-1.11.1.1-hc364b38_6", - "m2-brotli-1.1.0.2-hc364b38_6", - "m2-p11-kit-0.25.5.2-hc364b38_6", - "m2-sed-4.9.1-hc364b38_6", - "m2-findutils-4.9.0.3-hc364b38_6", - "m2-libreadline-8.2.013.1-hc364b38_6", - "m2-libsqlite-3.49.1.2-hc364b38_6", - "m2-libp11-kit-0.25.5.2-hc364b38_6", - "m2-libtasn1-4.20.0.1-hc364b38_6", - "m2-libffi-3.4.8.1-hc364b38_6", - "m2-info-7.2.1-hc364b38_6", - "m2-gzip-1.14.1-hc364b38_6", - "m2-less-668.1-hc364b38_6", - "m2-filesystem-2025.02.23.1-hc364b38_10", -] - [[tools."conda:m2-gnupg"]] version = "2.2.41.1" backend = "conda:m2-gnupg" @@ -1120,23 +735,23 @@ backend = "http:busybox" [tools."http:busybox"."platforms.linux-arm64"] checksum = "sha256:6e263d154d8548d1eb936f65d1d8312c80df31c45974e48d6335e4dcc0f4f34c" -url = "https://frippery.org/files/busybox/busybox64u.exe" +url = "https://github.com/edge-toolkit/core/releases/download/busybox-w32-v1/busybox64u.exe" [tools."http:busybox"."platforms.linux-x64"] checksum = "sha256:6e263d154d8548d1eb936f65d1d8312c80df31c45974e48d6335e4dcc0f4f34c" -url = "https://frippery.org/files/busybox/busybox64u.exe" +url = "https://github.com/edge-toolkit/core/releases/download/busybox-w32-v1/busybox64u.exe" [tools."http:busybox"."platforms.macos-arm64"] checksum = "sha256:6e263d154d8548d1eb936f65d1d8312c80df31c45974e48d6335e4dcc0f4f34c" -url = "https://frippery.org/files/busybox/busybox64u.exe" +url = "https://github.com/edge-toolkit/core/releases/download/busybox-w32-v1/busybox64u.exe" [tools."http:busybox"."platforms.macos-x64"] checksum = "sha256:6e263d154d8548d1eb936f65d1d8312c80df31c45974e48d6335e4dcc0f4f34c" -url = "https://frippery.org/files/busybox/busybox64u.exe" +url = "https://github.com/edge-toolkit/core/releases/download/busybox-w32-v1/busybox64u.exe" [tools."http:busybox"."platforms.windows-x64"] checksum = "sha256:6e263d154d8548d1eb936f65d1d8312c80df31c45974e48d6335e4dcc0f4f34c" -url = "https://frippery.org/files/busybox/busybox64u.exe" +url = "https://github.com/edge-toolkit/core/releases/download/busybox-w32-v1/busybox64u.exe" [[tools."http:dart-typegen"]] version = "0.1.13" diff --git a/.mise/mise.zig.lock b/.mise/mise.zig.lock index b3888b22..3b586446 100644 --- a/.mise/mise.zig.lock +++ b/.mise/mise.zig.lock @@ -4,57 +4,61 @@ url = "https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda" checksum = "sha256:a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068" -[conda-packages.linux-arm64."clang-format-22-22.1.8-default_h9c9fc99_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-22-22.1.8-default_h9c9fc99_6.conda" -checksum = "sha256:d6200432d9ff21eb6c7c8fb3bc46284f734b0fcbb5012c5ee229cf021843c007" +[conda-packages.linux-arm64."clang-format-23-23.1.2-default_h01b09c7_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-23-23.1.2-default_h01b09c7_0.conda" +checksum = "sha256:16c6f21ae3de358156afb9290130485809c252ffd5b7bfd9b236a7bbade69244" -[conda-packages.linux-arm64."clang-format-22.1.8-default_h7c587c8_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-22.1.8-default_h7c587c8_6.conda" -checksum = "sha256:f872e60a7ce3079e370650c1722d66148d41f36def051b89afd46eff7ab192f9" +[conda-packages.linux-arm64."clang-format-23.1.2-default_h9f22059_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-23.1.2-default_h9f22059_0.conda" +checksum = "sha256:7841a0b232fc0c324ef4680f8cb76f448ece36a97c6f6bd4e9563cba4727dc5d" -[conda-packages.linux-arm64."clang-scan-deps-22.1.8-default_h9c9fc99_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-scan-deps-22.1.8-default_h9c9fc99_6.conda" -checksum = "sha256:8cb79c11cd584f078442173cf6ef8c0cef1d70c4dfcd113464920781acdefd7d" +[conda-packages.linux-arm64."clang-scan-deps-23.1.2-default_h01b09c7_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-scan-deps-23.1.2-default_h01b09c7_0.conda" +checksum = "sha256:2321952cd5d77a2e03b5d3f429a26805885379bbc7a1f1151a0d08e208ba1d22" -[conda-packages.linux-arm64."libclang-cpp22.1-22.1.8-default_h9c9fc99_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp22.1-22.1.8-default_h9c9fc99_6.conda" -checksum = "sha256:c2340ee1cfe1e2aa146d8cdfe9f4dccc18bef55286b14bbd6aef5db7a93c602c" +[conda-packages.linux-arm64."icu-78.3-py311h3512406_2"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-py311h3512406_2.conda" +checksum = "sha256:54d921defd947adb58a90e10203d3bfe6c1f209f5f1a1ad2c6a9f7617f2fb59e" -[conda-packages.linux-arm64."libclang13-22.1.8-default_h1f00bc2_6"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-22.1.8-default_h1f00bc2_6.conda" -checksum = "sha256:4423fc1f50d4294faa275442e2c2af6824a592bafa97892f452ae307298073b9" +[conda-packages.linux-arm64."libclang-cpp23.1-23.1.2-default_h01b09c7_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp23.1-23.1.2-default_h01b09c7_0.conda" +checksum = "sha256:9b0ced8d10de3dd1cc8271779dd1603b6168ee2384b0fa79ac7743a1ea0ae47c" -[conda-packages.linux-arm64."libgcc-16.1.0-h205dda4_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.1.0-h205dda4_1.conda" -checksum = "sha256:88a3d400c678df034c9d498f32503779977d5ea826063687c663e42c945abed5" +[conda-packages.linux-arm64."libclang13-23.1.2-default_h473506b_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-23.1.2-default_h473506b_0.conda" +checksum = "sha256:17bbfe80fd9c58e614e5de34bb3fb5d12158cbbccc789a3e8fecb110db607223" -[conda-packages.linux-arm64."libgomp-16.1.0-h8acb6b2_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.1.0-h8acb6b2_1.conda" -checksum = "sha256:1c609a4a72597350317b92c4d9dfb85d21740219048e2b1d458925a6ccfa3d7a" +[conda-packages.linux-arm64."libgcc-16.2.0-h205dda4_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-16.2.0-h205dda4_7.conda" +checksum = "sha256:eae7a3449d5a3b5351c5427137c076cc3fc826645c7bfc42dc10772b783826f1" -[conda-packages.linux-arm64."libiconv-1.18-h90929bb_2"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda" -checksum = "sha256:1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9" +[conda-packages.linux-arm64."libgomp-16.2.0-h8acb6b2_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-16.2.0-h8acb6b2_7.conda" +checksum = "sha256:4406fd67c5beeb99b9372f9bf07aa3e40ca141e337eceebac3ff64aa72799494" -[conda-packages.linux-arm64."libllvm22-22.1.8-hfd2ba90_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm22-22.1.8-hfd2ba90_1.conda" -checksum = "sha256:dc943f1730a27f5fb36682c9852f7196f671c3a9df4a0a7a8f7ba665637c9151" +[conda-packages.linux-arm64."libiconv-1.18-h1ea5142_3"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h1ea5142_3.conda" +checksum = "sha256:d22c666eb887afd2119aac2110e23a0e817e9391bda99293421f7c46dab1564c" + +[conda-packages.linux-arm64."libllvm23-23.1.2-h680871c_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm23-23.1.2-h680871c_0.conda" +checksum = "sha256:9b7820c041aeebea33d738a917c185ae554b6b89e2491e83e64f9a2fe675f88c" [conda-packages.linux-arm64."liblzma-5.8.3-he30d5cf_1"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_1.conda" checksum = "sha256:f760669fd1cea27f689f411c0d5488e26ce50e382c9b63e4ad348f959850124a" -[conda-packages.linux-arm64."libstdcxx-16.1.0-hef695bb_1"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.1.0-hef695bb_1.conda" -checksum = "sha256:81ef9a10a0e01ffc7e03d429ed048410153411b2d8bbf95c334bdf3dcf175ab0" +[conda-packages.linux-arm64."libstdcxx-16.2.0-hef695bb_7"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-16.2.0-hef695bb_7.conda" +checksum = "sha256:b241a3acfa9cdb1359112864a1241225533c92642de3000d52ae65ef5d3a9786" -[conda-packages.linux-arm64."libxml2-16-2.15.3-h064b767_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.3-h064b767_0.conda" -checksum = "sha256:96e9bd642c013ce3407c23b3819204ea8a591567d62b49baa4bafb2f1487326c" +[conda-packages.linux-arm64."libxml2-16-2.15.4-h2e5089f_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-16-2.15.4-h2e5089f_0.conda" +checksum = "sha256:58bf7fcf64bae7f624a5e2aed860ddea614a8ec13c8c43fe150420a275b8bdb5" -[conda-packages.linux-arm64."libxml2-2.15.3-h9ba8346_0"] -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.3-h9ba8346_0.conda" -checksum = "sha256:74aa3c62e0ec4491343b95ce4ca8812ad2f9bb015369e29cb3b4b9b4302d8cb0" +[conda-packages.linux-arm64."libxml2-2.15.4-h92b9305_0"] +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.15.4-h92b9305_0.conda" +checksum = "sha256:3345c88fa9ebb373bcf4069ede898950005fa2d1707e56a13a1ac6339919492f" [conda-packages.linux-arm64."libzlib-1.3.2-hdc9db2a_3"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_3.conda" @@ -68,61 +72,57 @@ checksum = "sha256:427fd14bcb3b8659796fecc682716617409350fb5a98e5b7b47558a10d1a2 url = "https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda" checksum = "sha256:1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9" -[conda-packages.linux-x64."clang-format-22-22.1.8-default_h08c5240_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-format-22-22.1.8-default_h08c5240_6.conda" -checksum = "sha256:8e0fb4bf20bc89b5de16357e73a8d3344db814aafcab354aecf968571e62fb21" - -[conda-packages.linux-x64."clang-format-22.1.8-default_h36682a0_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-format-22.1.8-default_h36682a0_6.conda" -checksum = "sha256:03a3c632e594375b1416c0baf9131596aa4b11e80a8f557f69162fd1c7aed309" +[conda-packages.linux-x64."clang-format-23-23.1.2-default_h0acdd01_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-format-23-23.1.2-default_h0acdd01_0.conda" +checksum = "sha256:9197253eb34cce59ea2377ade9c99cc3fffd87e5e303a36799bb672197bff42c" -[conda-packages.linux-x64."clang-scan-deps-22.1.8-default_h08c5240_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-22.1.8-default_h08c5240_6.conda" -checksum = "sha256:f41e133972fdd5ae6d72316b629c4c8824b40149afe584df09566689c4fe5b52" +[conda-packages.linux-x64."clang-format-23.1.2-default_he6de646_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-format-23.1.2-default_he6de646_0.conda" +checksum = "sha256:7bb544a5150d2ca9fbf83b5bf07de80c83ead88d4dacca613b09bd52950233ae" -[conda-packages.linux-x64."icu-78.3-py310h44b86e0_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-py310h44b86e0_2.conda" -checksum = "sha256:9f07834f0c546ab14d885ce0366285f61f44e326c0edd1fc63b8294e113ae432" +[conda-packages.linux-x64."clang-scan-deps-23.1.2-default_h0acdd01_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-scan-deps-23.1.2-default_h0acdd01_0.conda" +checksum = "sha256:7c8a8382a7ab32f731302d1af010e73329cdac9ad29fa2d77c3a5048307c9308" -[conda-packages.linux-x64."libclang-cpp22.1-22.1.8-default_h08c5240_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.8-default_h08c5240_6.conda" -checksum = "sha256:fc2981a8e45dd232ae88cf2580f7e75c258f4dccdc96f879b68ef0a9b45c9a2b" +[conda-packages.linux-x64."libclang-cpp23.1-23.1.2-default_h0acdd01_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp23.1-23.1.2-default_h0acdd01_0.conda" +checksum = "sha256:49156155d4f0ab4f479bc96d24db2c48c0b6bdb5659135c194f03c289ae2c523" -[conda-packages.linux-x64."libclang13-22.1.8-default_hd70ba2e_6"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libclang13-22.1.8-default_hd70ba2e_6.conda" -checksum = "sha256:8475136d3be6c2d16bdb801dcaf8769cb2ba372cad239c89ebd6a58912e14465" +[conda-packages.linux-x64."libclang13-23.1.2-default_hfab3205_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libclang13-23.1.2-default_hfab3205_0.conda" +checksum = "sha256:6009280c06f52fcce68f4c95c19e23a13aaf3edc99c4ae1e574c4c5f09eccac3" -[conda-packages.linux-x64."libgcc-16.1.0-ha9f2e26_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.1.0-ha9f2e26_1.conda" -checksum = "sha256:d5cb8475131c31680f8fd30512c418f373064e272e452063276a8fb14c9fa42f" +[conda-packages.linux-x64."libgcc-16.2.0-ha9f2e26_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda" +checksum = "sha256:e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea" -[conda-packages.linux-x64."libgomp-16.1.0-he0feb66_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.1.0-he0feb66_1.conda" -checksum = "sha256:62cb599ad0539d99386515326d9d5e8f51f75a60c69c2131b21df76edf35bd89" +[conda-packages.linux-x64."libgomp-16.2.0-he0feb66_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda" +checksum = "sha256:92a0bb350c7be6a4eedcb4e111c60aefd176018e6b1c009a6e025dbe9bbcd758" -[conda-packages.linux-x64."libiconv-1.18-h3b78370_2"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda" -checksum = "sha256:c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f" +[conda-packages.linux-x64."libiconv-1.18-h0cb94f2_3"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h0cb94f2_3.conda" +checksum = "sha256:f943117edb9cd4d9c61cc972eee5a34291dc55ea7a6e9e38da104995841cbcb6" -[conda-packages.linux-x64."libllvm22-22.1.8-hf7376ad_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.8-hf7376ad_1.conda" -checksum = "sha256:e9b5f301d6b001a9b8ce782157f56b75c92c4fbc9eba95dc6345c1139251d13b" +[conda-packages.linux-x64."libllvm23-23.1.2-h474f4eb_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libllvm23-23.1.2-h474f4eb_0.conda" +checksum = "sha256:253a11a58756a3584c72c625752fb6ccf0a8885815f3e911f05731cfc24ea0ed" [conda-packages.linux-x64."liblzma-5.8.3-hb03c661_1"] url = "https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda" checksum = "sha256:9787df8c22a59c9a70d3e5a10db9ad663485e75e9ccc3f09bd092cb7b95e0dab" -[conda-packages.linux-x64."libstdcxx-16.1.0-h934c35e_1"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.1.0-h934c35e_1.conda" -checksum = "sha256:79721dd08aeb0ab9e773f1f9ef41cf4e6c17477e3d72319147619045bce05a09" +[conda-packages.linux-x64."libstdcxx-16.2.0-h934c35e_7"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda" +checksum = "sha256:fa7018298629fc429971fffd6ecba3d27a7b02e4e890d6a93ea01ffebe8cb745" -[conda-packages.linux-x64."libxml2-16-2.15.3-hca6bf5a_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.3-hca6bf5a_0.conda" -checksum = "sha256:3d44f737c5ae52d5af32682cc1530df433f401f8e58a7533926536244127572a" +[conda-packages.linux-x64."libxml2-16-2.15.4-hbdfff7e_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.4-hbdfff7e_0.conda" +checksum = "sha256:b6f96287c408269f5067bb4f7a61693ff5c856152902362964d9807152b9c146" -[conda-packages.linux-x64."libxml2-2.15.3-h49c6c72_0"] -url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.3-h49c6c72_0.conda" -checksum = "sha256:3bc5551720c58591f6ea1146f7d1539c734ed1c40e7b9f5cb8cb7e900c509aba" +[conda-packages.linux-x64."libxml2-2.15.4-ha7a5771_0"] +url = "https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.4-ha7a5771_0.conda" +checksum = "sha256:db52c038430a508656530fc7b5650ae3e2629875693a6a256cc48dec203f8bfe" [conda-packages.linux-x64."libzlib-1.3.2-h25fd6f3_3"] url = "https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda" @@ -132,49 +132,53 @@ checksum = "sha256:eb8a0db0aa570124f7d2a93d7c7f596e3390df5e047818d873baad32985fc url = "https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda" checksum = "sha256:47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fbc60" -[conda-packages.macos-arm64."clang-format-22-22.1.8-default_hc257da1_6"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-22-22.1.8-default_hc257da1_6.conda" -checksum = "sha256:6006eca9bf44cf05e7de18fe9468a559b0ff90c858004ba726db82f0f728d112" +[conda-packages.macos-arm64."clang-format-23-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-23-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:c3e71811d7fcb94f845bd816b6fc321fbb916136062890cbbc0cede88f7c686b" -[conda-packages.macos-arm64."clang-format-22.1.8-default_h1fde8bb_6"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-22.1.8-default_h1fde8bb_6.conda" -checksum = "sha256:39b0943dcd17275b153c87c067b54c0f8645be4839321fcd539358eb175d5195" +[conda-packages.macos-arm64."clang-format-23.1.2-default_h7e305d6_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-23.1.2-default_h7e305d6_0.conda" +checksum = "sha256:e579f52d29526b470689149326934ef61770d8ba42af59aa4fa0b67a90349204" -[conda-packages.macos-arm64."clang-scan-deps-22.1.8-default_hc257da1_6"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-22.1.8-default_hc257da1_6.conda" -checksum = "sha256:d5ab08fccabeb9b0e081b0303ed613fa91c0210878c50d4f05cd9d6e07f6e348" +[conda-packages.macos-arm64."clang-scan-deps-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-scan-deps-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:99a684bc5eb5348de9b78dd57af40dd6d91e85ec241f6e753611dcea1762ba32" -[conda-packages.macos-arm64."libclang-cpp22.1-22.1.8-default_hc257da1_6"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp22.1-22.1.8-default_hc257da1_6.conda" -checksum = "sha256:5f16d1b4324284f2a360f56566867fd05c4a9dfbddff650887788f6285f956a9" +[conda-packages.macos-arm64."icu-78.3-py310h579977c_2"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-py310h579977c_2.conda" +checksum = "sha256:6cdb5dee54c72e56ab189fb3ad33cb28533553d42590e7e831160248f4416a43" -[conda-packages.macos-arm64."libclang13-22.1.8-default_hed75349_6"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-22.1.8-default_hed75349_6.conda" -checksum = "sha256:8d7d0ecabc11a7ed0b8cccff96815d8cc1cc712affc0dcdc540d9e18f6e7158f" +[conda-packages.macos-arm64."libclang-cpp23.1-23.1.2-default_h79071a4_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp23.1-23.1.2-default_h79071a4_0.conda" +checksum = "sha256:7a176b6dda75f39184cc96b548fa436581451547bb185c610627a9b6dca05ca8" -[conda-packages.macos-arm64."libcxx-22.1.8-h55c6f16_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.8-h55c6f16_0.conda" -checksum = "sha256:a2e7abab5add9750fab064c024394de48e49f97631c605ad5db5c8ac3fc769ef" +[conda-packages.macos-arm64."libclang13-23.1.2-default_h8f9c3af_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-23.1.2-default_h8f9c3af_0.conda" +checksum = "sha256:8fd0a585f9f4701a991ddf311aeb315c402783aa5b21c24b14b4034eb8cc3f20" -[conda-packages.macos-arm64."libiconv-1.18-h23cfdf5_2"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-h23cfdf5_2.conda" -checksum = "sha256:de0336e800b2af9a40bdd694b03870ac4a848161b35c8a2325704f123f185f03" +[conda-packages.macos-arm64."libcxx-23.1.2-h55c6f16_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-23.1.2-h55c6f16_0.conda" +checksum = "sha256:087a610bacee7901d259ef72c6f060d795ab26831bd7541ba75ced786a5a63f9" -[conda-packages.macos-arm64."libllvm22-22.1.8-h89af1be_1"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm22-22.1.8-h89af1be_1.conda" -checksum = "sha256:9c0ece5160e3d8749f43f8dd86777be4cfdb51490fb32f4d8269f8fd9866ce55" +[conda-packages.macos-arm64."libiconv-1.18-he4c29f2_3"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.18-he4c29f2_3.conda" +checksum = "sha256:689a14968267f2f97c07112fca5636e7d756036b9aee969911267c20bd3eea1f" + +[conda-packages.macos-arm64."libllvm23-23.1.2-h759d1ac_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libllvm23-23.1.2-h759d1ac_0.conda" +checksum = "sha256:9717b7ae514600cebeb43ea89bf008bef6e96fbbefa1dda40843c394f2b6a46e" [conda-packages.macos-arm64."liblzma-5.8.3-h8088a28_1"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_1.conda" checksum = "sha256:23d0630046a3e8b164d8f80f2b74ed2605af2e7050ab9913018056402fae4311" -[conda-packages.macos-arm64."libxml2-16-2.15.3-h6967ea9_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.3-h6967ea9_0.conda" -checksum = "sha256:43895a7517c055b8893531290f9dc48bd751eb04be04f14bbce3b6c71b052be6" +[conda-packages.macos-arm64."libxml2-16-2.15.4-heb56d2d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-16-2.15.4-heb56d2d_0.conda" +checksum = "sha256:8a26f7c94ab849c1930da36c298f4b82e892382b70ae865cd7274188d9d783e2" -[conda-packages.macos-arm64."libxml2-2.15.3-heed7d32_0"] -url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.3-heed7d32_0.conda" -checksum = "sha256:4d9c117b2dd222cf891710d5f6a570ebb275479979843a1477ac54ed50907b40" +[conda-packages.macos-arm64."libxml2-2.15.4-h550178d_0"] +url = "https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.15.4-h550178d_0.conda" +checksum = "sha256:81217fcd4d4abdc69ee63cdb9cdb22e05a20b9ba7a76f596579914a838fe5960" [conda-packages.macos-arm64."libzlib-1.3.2-h8088a28_3"] url = "https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_3.conda" @@ -184,49 +188,49 @@ checksum = "sha256:a18fa5d5bac452401459f966cf0d872224e8080c4ff93c77e168d43ab42ef url = "https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hf451053_7.conda" checksum = "sha256:da867f5092eb0cb746d353694f0098031fd9817a4ce7d5743121209ae0f406ca" -[conda-packages.macos-x64."clang-format-22-22.1.8-default_hf44d2de_6"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-format-22-22.1.8-default_hf44d2de_6.conda" -checksum = "sha256:bf25063df012aa70205c8c7ebafa87451e5a93c3daea7d509cbb84bd49156acf" +[conda-packages.macos-x64."clang-format-23-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-format-23-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:7a5c7348a1232bce113c7dbd65b7ee09d94848791a49b0d6ffb799f49320072a" -[conda-packages.macos-x64."clang-format-22.1.8-default_hb28dbfe_6"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-format-22.1.8-default_hb28dbfe_6.conda" -checksum = "sha256:c40a1105c6b0d8633ba67a5a42db9c0e43a5711a3694146f0aea4486a92e8de5" +[conda-packages.macos-x64."clang-format-23.1.2-default_h5167a8e_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-format-23.1.2-default_h5167a8e_0.conda" +checksum = "sha256:dd3bb81e12891e51c4fa7f6f57e070ed0cc54557823f838dbd016dba4e922363" -[conda-packages.macos-x64."clang-scan-deps-22.1.8-default_hf44d2de_6"] -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-22.1.8-default_hf44d2de_6.conda" -checksum = "sha256:85a3055f2be6150b7ab315c3b02758d1472101ebd37b3caf15eb3bf6cc629dcd" +[conda-packages.macos-x64."clang-scan-deps-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-scan-deps-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:a587f276042f1ca56da7fd6f7e13db7d4da22d5b6c05d8bf7f38301c91971e4b" -[conda-packages.macos-x64."libclang-cpp22.1-22.1.8-default_hf44d2de_6"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp22.1-22.1.8-default_hf44d2de_6.conda" -checksum = "sha256:e8cc65cdb55f639a2398de6fedfb8b8c46ab99a35d46cbbd9f51b616388b3717" +[conda-packages.macos-x64."libclang-cpp23.1-23.1.2-default_h6e863b9_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp23.1-23.1.2-default_h6e863b9_0.conda" +checksum = "sha256:491c85fac38f91060802761e59e3a1505ee738ed2849504e8d0f3ecf0c520537" -[conda-packages.macos-x64."libclang13-22.1.8-default_h436299c_6"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libclang13-22.1.8-default_h436299c_6.conda" -checksum = "sha256:ded2c6fbff5a8843c4b23e36c625b3f0d816f9ed54a289eea976e281405119cc" +[conda-packages.macos-x64."libclang13-23.1.2-default_h3065a3b_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libclang13-23.1.2-default_h3065a3b_0.conda" +checksum = "sha256:0dfe44aa4d56eae2ac5832a611ce1167d44ff17181c85596de01e149c04af01c" -[conda-packages.macos-x64."libcxx-22.1.8-h19cb2f5_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-22.1.8-h19cb2f5_0.conda" -checksum = "sha256:57ee997f1f800cf38abc743c0f0a9ddfe6a101c697c35510452ce6f4ddf96361" +[conda-packages.macos-x64."libcxx-23.1.2-h19cb2f5_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libcxx-23.1.2-h19cb2f5_0.conda" +checksum = "sha256:0ad8c788c3681674f100820cf5e76fcc8ec88502e7aa64f4776581985009a7be" -[conda-packages.macos-x64."libiconv-1.18-h57a12c2_2"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h57a12c2_2.conda" -checksum = "sha256:a1c8cecdf9966921e13f0ae921309a1f415dfbd2b791f2117cf7e8f5e61a48b6" +[conda-packages.macos-x64."libiconv-1.18-h4ae439b_3"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.18-h4ae439b_3.conda" +checksum = "sha256:2389e03a58ed0f5e8f2469eb4d4ba80d0af378b38854ae5eee65e5b641244082" -[conda-packages.macos-x64."libllvm22-22.1.8-hab754da_1"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm22-22.1.8-hab754da_1.conda" -checksum = "sha256:c2bd652c5a6c4f0e6029786c4e59c54c09018049664006e94d674db4561238ea" +[conda-packages.macos-x64."libllvm23-23.1.2-hd11396f_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libllvm23-23.1.2-hd11396f_0.conda" +checksum = "sha256:f6174a6f25f900bbcebaa6461ad7152937ff5769e6dbec500a385c321e5adbc2" [conda-packages.macos-x64."liblzma-5.8.3-hbb4bfdb_1"] url = "https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.3-hbb4bfdb_1.conda" checksum = "sha256:7915dac7c71c208e40e716e2f6d3eff41a8d5584e0e7c2d46f9bf9bd5f9aa739" -[conda-packages.macos-x64."libxml2-16-2.15.3-h0d7f165_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.3-h0d7f165_0.conda" -checksum = "sha256:daa69a1dd887b2dbac44327bc5af73a4d41fa63bc6dc609782fdda9aec187895" +[conda-packages.macos-x64."libxml2-16-2.15.4-h341e563_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-16-2.15.4-h341e563_0.conda" +checksum = "sha256:bc284057b85e4a0ecc158598d81c3081fa58e9111969a05d3056ab7a8442c837" -[conda-packages.macos-x64."libxml2-2.15.3-h0712280_0"] -url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.3-h0712280_0.conda" -checksum = "sha256:caf6e73fa53c3dec3227ea67de231b0f7009544252684e816c6f2f414aeb55c9" +[conda-packages.macos-x64."libxml2-2.15.4-h3668fe6_0"] +url = "https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.15.4-h3668fe6_0.conda" +checksum = "sha256:9cf91223637981568c8fbd5c4dbbc1e6137592e919828554ae436bf259aa91d0" [conda-packages.macos-x64."libzlib-1.3.2-hbb4bfdb_3"] url = "https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_3.conda" @@ -236,37 +240,41 @@ checksum = "sha256:b2dba286dd6632292b12296e761193b5ef9fb0eaeecaa481f5ba9af72c0c1 url = "https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-hbc1a06c_7.conda" checksum = "sha256:5277886d9704a624dc9b79ac985861e1e431bdb39a57c082507ab577a138ec6c" -[conda-packages.windows-x64."clang-format-22.1.8-default_h2778606_6"] -url = "https://conda.anaconda.org/conda-forge/win-64/clang-format-22.1.8-default_h2778606_6.conda" -checksum = "sha256:7d7fd597d8d42128d7db6ac3b01bb0833a47dd31fd1d9bafe9cf36b7d209b6d0" +[conda-packages.windows-x64."clang-format-23.1.2-default_hacd6ee9_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/clang-format-23.1.2-default_hacd6ee9_0.conda" +checksum = "sha256:cc165bd6352a8408b10b4a1cc0ac8be64fe7d70ff32617f3f720f9137cfe86b5" + +[conda-packages.windows-x64."icu-78.3-h5112557_2"] +url = "https://conda.anaconda.org/conda-forge/win-64/icu-78.3-h5112557_2.conda" +checksum = "sha256:75c549b55b673e15de8785a8e5dd85bca7eb612eee0ff4dc8d7bdaa15eacbdbb" -[conda-packages.windows-x64."libclang13-22.1.8-default_h2778606_6"] -url = "https://conda.anaconda.org/conda-forge/win-64/libclang13-22.1.8-default_h2778606_6.conda" -checksum = "sha256:ddab96250fe45da60cf3d94df81d9d0988db157e5feffa29f8e15aea53b50b16" +[conda-packages.windows-x64."libclang13-23.1.2-default_hacd6ee9_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libclang13-23.1.2-default_hacd6ee9_0.conda" +checksum = "sha256:216cf2224a81090c15230ff2e6e2a01259ceb70b29da4ef72e64de1fffb0ce22" -[conda-packages.windows-x64."libiconv-1.18-hc1393d2_2"] -url = "https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_2.conda" -checksum = "sha256:0dcdb1a5f01863ac4e8ba006a8b0dc1a02d2221ec3319b5915a1863254d7efa7" +[conda-packages.windows-x64."libiconv-1.18-hc1393d2_3"] +url = "https://conda.anaconda.org/conda-forge/win-64/libiconv-1.18-hc1393d2_3.conda" +checksum = "sha256:35e04e3ddac7720fc7c550a1c9f998604299d6a7bd1f3ec9b2825d825061daa2" [conda-packages.windows-x64."liblzma-5.8.3-hfd05255_1"] url = "https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_1.conda" checksum = "sha256:d36c4a1e1f80fd08e18a407e03622ff2f34dfdd022da6488ad19603dea19e6d5" -[conda-packages.windows-x64."libxml2-16-2.15.3-h692994f_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.3-h692994f_0.conda" -checksum = "sha256:8038084c60eda2006d0122d05e3364fe8db0a18935ca6ed0168b5ba5aa33f904" +[conda-packages.windows-x64."libxml2-16-2.15.4-h3cfd58e_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda" +checksum = "sha256:9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac" -[conda-packages.windows-x64."libxml2-2.15.3-hbc0d294_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.3-hbc0d294_0.conda" -checksum = "sha256:da68af9d9d28d65a6916db1bef68f8a25c64c4fdcf759f32a2d2f2f143220adf" +[conda-packages.windows-x64."libxml2-2.15.4-he095d88_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda" +checksum = "sha256:a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88" [conda-packages.windows-x64."libzlib-1.3.2-hfd05255_3"] url = "https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_3.conda" checksum = "sha256:0629c2cc0404d3bb29d6baa7b4ba62da80797015e86de050db81ea5a07050527" -[conda-packages.windows-x64."llvm-openmp-22.1.8-h4fa8253_0"] -url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-22.1.8-h4fa8253_0.conda" -checksum = "sha256:50c02902bb516eeb56680358f052be38b5bf74b40e78ea4b2a675e84957e7307" +[conda-packages.windows-x64."llvm-openmp-23.1.2-h49e36cd_0"] +url = "https://conda.anaconda.org/conda-forge/win-64/llvm-openmp-23.1.2-h49e36cd_0.conda" +checksum = "sha256:8b462c021d6bf3f956749d305bd3f52deb82ae2901047c0c7061a21c3550e48f" [conda-packages.windows-x64."ucrt-10.0.26100.0-h57928b3_0"] url = "https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda" @@ -289,232 +297,236 @@ url = "https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_7.conda checksum = "sha256:ca7daae4f218a11fab82cc2857f0ea518ec3f46acec60490485347a4c22c6b3e" [[tools."conda:clang-format"]] -version = "22.1.8" +version = "23.1.2" backend = "conda:clang-format" [tools."conda:clang-format".options] channel = "conda-forge" [tools."conda:clang-format"."platforms.linux-arm64"] -checksum = "sha256:f872e60a7ce3079e370650c1722d66148d41f36def051b89afd46eff7ab192f9" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-22.1.8-default_h7c587c8_6.conda" +checksum = "sha256:7841a0b232fc0c324ef4680f8cb76f448ece36a97c6f6bd4e9563cba4727dc5d" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-23.1.2-default_h9f22059_0.conda" conda_deps = [ - "clang-format-22-22.1.8-default_h9c9fc99_6", - "libclang-cpp22.1-22.1.8-default_h9c9fc99_6", + "clang-format-23-23.1.2-default_h01b09c7_0", + "libclang-cpp23.1-23.1.2-default_h01b09c7_0", + "libllvm23-23.1.2-h680871c_0", "libzlib-1.3.2-hdc9db2a_3", - "libstdcxx-16.1.0-hef695bb_1", - "libgcc-16.1.0-h205dda4_1", + "libxml2-16-2.15.4-h2e5089f_0", + "libxml2-2.15.4-h92b9305_0", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", "zstd-1.5.7-h9d15635_7", - "libxml2-2.15.3-h9ba8346_0", - "libxml2-16-2.15.3-h064b767_0", - "libllvm22-22.1.8-hfd2ba90_1", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libiconv-1.18-h90929bb_2", + "libgomp-16.2.0-h8acb6b2_7", + "icu-78.3-py311h3512406_2", + "libiconv-1.18-h1ea5142_3", "liblzma-5.8.3-he30d5cf_1", ] [tools."conda:clang-format"."platforms.linux-x64"] -checksum = "sha256:03a3c632e594375b1416c0baf9131596aa4b11e80a8f557f69162fd1c7aed309" -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-format-22.1.8-default_h36682a0_6.conda" +checksum = "sha256:7bb544a5150d2ca9fbf83b5bf07de80c83ead88d4dacca613b09bd52950233ae" +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-format-23.1.2-default_he6de646_0.conda" conda_deps = [ - "clang-format-22-22.1.8-default_h08c5240_6", - "libclang-cpp22.1-22.1.8-default_h08c5240_6", + "clang-format-23-23.1.2-default_h0acdd01_0", + "libclang-cpp23.1-23.1.2-default_h0acdd01_0", + "libllvm23-23.1.2-h474f4eb_0", "libzlib-1.3.2-h25fd6f3_3", - "libstdcxx-16.1.0-h934c35e_1", - "libgcc-16.1.0-ha9f2e26_1", + "libxml2-16-2.15.4-hbdfff7e_0", + "libxml2-2.15.4-ha7a5771_0", + "libstdcxx-16.2.0-h934c35e_7", + "libgcc-16.2.0-ha9f2e26_7", "zstd-1.5.7-hb78ec9c_7", - "libxml2-2.15.3-h49c6c72_0", - "libxml2-16-2.15.3-hca6bf5a_0", - "libllvm22-22.1.8-hf7376ad_1", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", - "libiconv-1.18-h3b78370_2", + "libgomp-16.2.0-he0feb66_7", "liblzma-5.8.3-hb03c661_1", - "icu-78.3-py310h44b86e0_2", + "libiconv-1.18-h0cb94f2_3", ] [tools."conda:clang-format"."platforms.macos-arm64"] -checksum = "sha256:39b0943dcd17275b153c87c067b54c0f8645be4839321fcd539358eb175d5195" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-22.1.8-default_h1fde8bb_6.conda" +checksum = "sha256:e579f52d29526b470689149326934ef61770d8ba42af59aa4fa0b67a90349204" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-23.1.2-default_h7e305d6_0.conda" conda_deps = [ - "libcxx-22.1.8-h55c6f16_0", - "clang-format-22-22.1.8-default_hc257da1_6", - "libclang-cpp22.1-22.1.8-default_hc257da1_6", + "libcxx-23.1.2-h55c6f16_0", + "clang-format-23-23.1.2-default_h79071a4_0", + "libclang-cpp23.1-23.1.2-default_h79071a4_0", + "libllvm23-23.1.2-h759d1ac_0", "libzlib-1.3.2-h8088a28_3", - "libxml2-2.15.3-heed7d32_0", - "libxml2-16-2.15.3-h6967ea9_0", + "libxml2-16-2.15.4-heb56d2d_0", + "libxml2-2.15.4-h550178d_0", "zstd-1.5.7-hf451053_7", - "libllvm22-22.1.8-h89af1be_1", - "libiconv-1.18-h23cfdf5_2", "liblzma-5.8.3-h8088a28_1", + "icu-78.3-py310h579977c_2", + "libiconv-1.18-he4c29f2_3", ] [tools."conda:clang-format"."platforms.macos-x64"] -checksum = "sha256:c40a1105c6b0d8633ba67a5a42db9c0e43a5711a3694146f0aea4486a92e8de5" -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-format-22.1.8-default_hb28dbfe_6.conda" +checksum = "sha256:dd3bb81e12891e51c4fa7f6f57e070ed0cc54557823f838dbd016dba4e922363" +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-format-23.1.2-default_h5167a8e_0.conda" conda_deps = [ - "libcxx-22.1.8-h19cb2f5_0", - "clang-format-22-22.1.8-default_hf44d2de_6", - "libclang-cpp22.1-22.1.8-default_hf44d2de_6", + "libcxx-23.1.2-h19cb2f5_0", + "clang-format-23-23.1.2-default_h6e863b9_0", + "libclang-cpp23.1-23.1.2-default_h6e863b9_0", + "libllvm23-23.1.2-hd11396f_0", + "libxml2-16-2.15.4-h341e563_0", + "libxml2-2.15.4-h3668fe6_0", "libzlib-1.3.2-hbb4bfdb_3", "zstd-1.5.7-hbc1a06c_7", - "libxml2-2.15.3-h0712280_0", - "libxml2-16-2.15.3-h0d7f165_0", - "libllvm22-22.1.8-hab754da_1", - "libiconv-1.18-h57a12c2_2", "liblzma-5.8.3-hbb4bfdb_1", + "libiconv-1.18-h4ae439b_3", ] [tools."conda:clang-format"."platforms.windows-x64"] -checksum = "sha256:7d7fd597d8d42128d7db6ac3b01bb0833a47dd31fd1d9bafe9cf36b7d209b6d0" -url = "https://conda.anaconda.org/conda-forge/win-64/clang-format-22.1.8-default_h2778606_6.conda" +checksum = "sha256:cc165bd6352a8408b10b4a1cc0ac8be64fe7d70ff32617f3f720f9137cfe86b5" +url = "https://conda.anaconda.org/conda-forge/win-64/clang-format-23.1.2-default_hacd6ee9_0.conda" conda_deps = [ - "llvm-openmp-22.1.8-h4fa8253_0", + "llvm-openmp-23.1.2-h49e36cd_0", "vc-14.5-ha367084_41", "vc14_runtime-14.51.36247-habf1de7_41", "vcomp14-14.51.36247-habf1de7_41", "ucrt-10.0.26100.0-h57928b3_0", + "libxml2-16-2.15.4-h3cfd58e_0", + "libxml2-2.15.4-he095d88_0", "libzlib-1.3.2-hfd05255_3", - "libxml2-2.15.3-hbc0d294_0", - "libxml2-16-2.15.3-h692994f_0", "zstd-1.5.7-h534d264_7", - "libiconv-1.18-hc1393d2_2", + "icu-78.3-h5112557_2", + "libiconv-1.18-hc1393d2_3", "liblzma-5.8.3-hfd05255_1", ] [[tools."conda:clang-tools"]] -version = "22.1.8" +version = "23.1.2" backend = "conda:clang-tools" [tools."conda:clang-tools".options] channel = "conda-forge" [tools."conda:clang-tools"."platforms.linux-arm64"] -checksum = "sha256:e18aa9d93495e9aac9d163d33013f5bde074ee5e744bf10f34aa98f7fb3df727" -url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-22.1.8-default_h1b0c604_6.conda" +checksum = "sha256:9b9a06b9564dcb255c6dd26e8be13c7625a0d5e23c477cca71d638db84d0f74d" +url = "https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-23.1.2-default_hd113019_0.conda" conda_deps = [ - "clang-scan-deps-22.1.8-default_h9c9fc99_6", - "clang-format-22.1.8-default_h7c587c8_6", - "clang-format-22-22.1.8-default_h9c9fc99_6", + "libllvm23-23.1.2-h680871c_0", + "libclang-cpp23.1-23.1.2-default_h01b09c7_0", + "clang-scan-deps-23.1.2-default_h01b09c7_0", + "libclang13-23.1.2-default_h473506b_0", + "clang-format-23.1.2-default_h9f22059_0", + "clang-format-23-23.1.2-default_h01b09c7_0", "libzlib-1.3.2-hdc9db2a_3", - "libllvm22-22.1.8-hfd2ba90_1", - "libclang13-22.1.8-default_h1f00bc2_6", - "libclang-cpp22.1-22.1.8-default_h9c9fc99_6", - "libstdcxx-16.1.0-hef695bb_1", - "libgcc-16.1.0-h205dda4_1", + "libxml2-16-2.15.4-h2e5089f_0", + "libxml2-2.15.4-h92b9305_0", + "libstdcxx-16.2.0-hef695bb_7", + "libgcc-16.2.0-h205dda4_7", "zstd-1.5.7-h9d15635_7", - "libxml2-2.15.3-h9ba8346_0", - "libxml2-16-2.15.3-h064b767_0", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-h8acb6b2_1", - "libiconv-1.18-h90929bb_2", + "libgomp-16.2.0-h8acb6b2_7", + "icu-78.3-py311h3512406_2", + "libiconv-1.18-h1ea5142_3", "liblzma-5.8.3-he30d5cf_1", ] [tools."conda:clang-tools"."platforms.linux-x64"] -checksum = "sha256:ce6381b8a5d144d38d092c9cd9bfcf2fc303b9bf5bb45ddf3691767a1b3cdceb" -url = "https://conda.anaconda.org/conda-forge/linux-64/clang-tools-22.1.8-default_h1af49a9_6.conda" +checksum = "sha256:08aa7166f2a0b6a7aa987351a5f399d7be0c17d3646e422f7be23e5e11111b26" +url = "https://conda.anaconda.org/conda-forge/linux-64/clang-tools-23.1.2-default_hd43de2f_0.conda" conda_deps = [ - "clang-scan-deps-22.1.8-default_h08c5240_6", - "clang-format-22.1.8-default_h36682a0_6", - "clang-format-22-22.1.8-default_h08c5240_6", + "libllvm23-23.1.2-h474f4eb_0", + "libclang-cpp23.1-23.1.2-default_h0acdd01_0", + "clang-scan-deps-23.1.2-default_h0acdd01_0", + "libclang13-23.1.2-default_hfab3205_0", + "clang-format-23.1.2-default_he6de646_0", + "clang-format-23-23.1.2-default_h0acdd01_0", "libzlib-1.3.2-h25fd6f3_3", - "libllvm22-22.1.8-hf7376ad_1", - "libclang13-22.1.8-default_hd70ba2e_6", - "libclang-cpp22.1-22.1.8-default_h08c5240_6", - "libstdcxx-16.1.0-h934c35e_1", - "libgcc-16.1.0-ha9f2e26_1", + "libxml2-16-2.15.4-hbdfff7e_0", + "libxml2-2.15.4-ha7a5771_0", + "libstdcxx-16.2.0-h934c35e_7", + "libgcc-16.2.0-ha9f2e26_7", "zstd-1.5.7-hb78ec9c_7", - "libxml2-2.15.3-h49c6c72_0", - "libxml2-16-2.15.3-hca6bf5a_0", "_openmp_mutex-4.5-20_gnu", - "libgomp-16.1.0-he0feb66_1", - "libiconv-1.18-h3b78370_2", + "libgomp-16.2.0-he0feb66_7", "liblzma-5.8.3-hb03c661_1", - "icu-78.3-py310h44b86e0_2", + "libiconv-1.18-h0cb94f2_3", ] [tools."conda:clang-tools"."platforms.macos-arm64"] -checksum = "sha256:a27f988b3319ec1b62c3cfbe0538936e5feb061ac95154147fb60d80b03ebb86" -url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-22.1.8-default_ha2fb705_6.conda" +checksum = "sha256:e1a54616214026f8fccae0bce7f19e652c4da03514d2f40790aa9c644ccb0e2b" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-23.1.2-default_hebf77b1_0.conda" conda_deps = [ - "libcxx-22.1.8-h55c6f16_0", - "clang-scan-deps-22.1.8-default_hc257da1_6", - "clang-format-22.1.8-default_h1fde8bb_6", - "clang-format-22-22.1.8-default_hc257da1_6", + "libllvm23-23.1.2-h759d1ac_0", + "libcxx-23.1.2-h55c6f16_0", + "libclang-cpp23.1-23.1.2-default_h79071a4_0", + "clang-scan-deps-23.1.2-default_h79071a4_0", + "libclang13-23.1.2-default_h8f9c3af_0", + "clang-format-23.1.2-default_h7e305d6_0", + "clang-format-23-23.1.2-default_h79071a4_0", "libzlib-1.3.2-h8088a28_3", - "libllvm22-22.1.8-h89af1be_1", - "libclang13-22.1.8-default_hed75349_6", - "libclang-cpp22.1-22.1.8-default_hc257da1_6", - "libxml2-2.15.3-heed7d32_0", - "libxml2-16-2.15.3-h6967ea9_0", + "libxml2-16-2.15.4-heb56d2d_0", + "libxml2-2.15.4-h550178d_0", "zstd-1.5.7-hf451053_7", - "libiconv-1.18-h23cfdf5_2", "liblzma-5.8.3-h8088a28_1", + "icu-78.3-py310h579977c_2", + "libiconv-1.18-he4c29f2_3", ] [tools."conda:clang-tools"."platforms.macos-x64"] -checksum = "sha256:72e87297ad39e8588dc77e6e8046eb9f2483490c339650e2cd9473051ef7c45e" -url = "https://conda.anaconda.org/conda-forge/osx-64/clang-tools-22.1.8-default_h66fc4d7_6.conda" +checksum = "sha256:e5f28aa17da56933b679b01be3d951a4e4c3f32bec8d20b73f43ddc2d885254b" +url = "https://conda.anaconda.org/conda-forge/osx-64/clang-tools-23.1.2-default_h335211a_0.conda" conda_deps = [ - "libcxx-22.1.8-h19cb2f5_0", - "clang-scan-deps-22.1.8-default_hf44d2de_6", - "clang-format-22.1.8-default_hb28dbfe_6", - "clang-format-22-22.1.8-default_hf44d2de_6", + "libllvm23-23.1.2-hd11396f_0", + "libcxx-23.1.2-h19cb2f5_0", + "libclang-cpp23.1-23.1.2-default_h6e863b9_0", + "clang-scan-deps-23.1.2-default_h6e863b9_0", + "libclang13-23.1.2-default_h3065a3b_0", + "clang-format-23.1.2-default_h5167a8e_0", + "clang-format-23-23.1.2-default_h6e863b9_0", + "libxml2-16-2.15.4-h341e563_0", + "libxml2-2.15.4-h3668fe6_0", "libzlib-1.3.2-hbb4bfdb_3", - "libllvm22-22.1.8-hab754da_1", - "libclang13-22.1.8-default_h436299c_6", - "libclang-cpp22.1-22.1.8-default_hf44d2de_6", "zstd-1.5.7-hbc1a06c_7", - "libxml2-2.15.3-h0712280_0", - "libxml2-16-2.15.3-h0d7f165_0", - "libiconv-1.18-h57a12c2_2", "liblzma-5.8.3-hbb4bfdb_1", + "libiconv-1.18-h4ae439b_3", ] [tools."conda:clang-tools"."platforms.windows-x64"] -checksum = "sha256:7e60f758c602149d4bc39ea359e9cf1173f715013a44566f56a6580b4fe76a9d" -url = "https://conda.anaconda.org/conda-forge/win-64/clang-tools-22.1.8-default_hd9aebca_6.conda" +checksum = "sha256:ccbce711c88e77ff991312461668768984528b5590ccaf3f5d19794ea2f94a73" +url = "https://conda.anaconda.org/conda-forge/win-64/clang-tools-23.1.2-default_h3c7e615_0.conda" conda_deps = [ - "llvm-openmp-22.1.8-h4fa8253_0", - "clang-format-22.1.8-default_h2778606_6", + "llvm-openmp-23.1.2-h49e36cd_0", + "libclang13-23.1.2-default_hacd6ee9_0", + "clang-format-23.1.2-default_hacd6ee9_0", + "libxml2-16-2.15.4-h3cfd58e_0", + "libxml2-2.15.4-he095d88_0", "libzlib-1.3.2-hfd05255_3", - "libclang13-22.1.8-default_h2778606_6", "ucrt-10.0.26100.0-h57928b3_0", "vc-14.5-ha367084_41", "vc14_runtime-14.51.36247-habf1de7_41", "vcomp14-14.51.36247-habf1de7_41", - "libxml2-2.15.3-hbc0d294_0", - "libxml2-16-2.15.3-h692994f_0", "zstd-1.5.7-h534d264_7", - "libiconv-1.18-hc1393d2_2", + "icu-78.3-h5112557_2", + "libiconv-1.18-hc1393d2_3", "liblzma-5.8.3-hfd05255_1", ] [[tools."github:christianhelle/openapi2zig"]] -version = "0.4.2" +version = "0.5.6" backend = "github:christianhelle/openapi2zig" [tools."github:christianhelle/openapi2zig"."platforms.linux-x64"] -checksum = "sha256:15071956b818767867b687b8f9db36899e3e397691aa005150050e76dc2b6d81" -url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.4.2/openapi2zig-linux-x86_64.tar.gz" -url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/495403966" +checksum = "sha256:f2d5ffe4da00c3c2e6201eedd0b535f25cbc5ff1064d6e06d506ddf858114431" +url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.5.6/openapi2zig-linux-x86_64.tar.gz" +url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/544463834" [tools."github:christianhelle/openapi2zig"."platforms.macos-arm64"] -checksum = "sha256:c3a6607ed3fd734a5e424f4244b8ed91f228ab47b5c59c749cb5ad5e17ad2866" -url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.4.2/openapi2zig-macos-aarch64.tar.gz" -url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/495403964" +checksum = "sha256:0437c7f838f8b4039a3bd973a68209642ea2e08e04ba86268a113b0d672e964d" +url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.5.6/openapi2zig-macos-aarch64.tar.gz" +url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/544463835" [tools."github:christianhelle/openapi2zig"."platforms.macos-x64"] -checksum = "sha256:7e30f6f9e1335cfd04b463bf98715ffe59a0bf1e60a34d7296fb017d61d42276" -url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.4.2/openapi2zig-macos-x86_64.tar.gz" -url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/495403963" +checksum = "sha256:e2d67a2bd484cd635f00d3732dadf86d5401a25e0be6e270eb2ee5a37a08973c" +url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.5.6/openapi2zig-macos-x86_64.tar.gz" +url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/544463833" [tools."github:christianhelle/openapi2zig"."platforms.windows-x64"] -checksum = "sha256:e8704c9e59087fb302ecabb76e86bc0a6a623cbf5d2392ac5ecf0f9710a167b4" -url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.4.2/openapi2zig-windows-x86_64.zip" -url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/495403965" +checksum = "sha256:3f7380c8149b99ab7cca512c1fa98826b2d6fb1d08eedd97d6f2e038a958f6d5" +url = "https://github.com/christianhelle/openapi2zig/releases/download/v0.5.6/openapi2zig-windows-x86_64.zip" +url_api = "https://api.github.com/repos/christianhelle/openapi2zig/releases/assets/544463838" [[tools."github:mstorsjo/llvm-mingw"]] version = "20260602" diff --git a/CLAUDE.md b/AGENTS.md similarity index 89% rename from CLAUDE.md rename to AGENTS.md index 56ee6ddf..fcfeaab7 100644 --- a/CLAUDE.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ -# CLAUDE.md +# AGENTS.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This file provides guidance to coding agents working with code in this repository. ## Check the branch is on top of `origin/main` before starting @@ -222,15 +222,9 @@ pass off an unverified change as a fix. ## Keep lines <= 120 characters -`editorconfig-checker` (`ec`, wired into `mise run check` via the `editorconfig-check` task) enforces a 120-char -limit on every file the `[*]` rule in `.editorconfig` covers -- which is almost all of them. A small number of -files have explicit overrides (`LICENSE-*` and generated trees under `generated/`), but assume every file you -touch is bound by 120 unless you have specific evidence otherwise. - -When writing comments, doc strings, `#[expect(reason = "...")]` reasons, `description = "..."` fields in TOML, -markdown tables, JSON schemas, etc., keep each line under the limit on the first draft rather than relying on a -follow-up fix-up pass. The most common offenders are: long `reason = "..."` strings on lint attributes, JSON -`description` fields, markdown table rows, and CI-task `description` fields. +Assume every file you touch is bound by the 120-char limit, and keep each line under it on the first draft rather +than relying on a fix-up pass. The common offenders are long `reason = "..."` strings on lint attributes, JSON +`description` fields, markdown table rows, and task `description` fields. Under the limit is the floor, not the target -- write prose and comments to **maximise** use of the 120-char width repo-wide. Fill each line close to 120 before wrapping rather than breaking early at 60-80 chars; a paragraph that @@ -240,62 +234,22 @@ rule messages), markdown, and Rego/policy headers. When you touch a block that w the width -- for Rust, run `mise run parfit-fmt ` on the files you changed rather than re-wrapping by hand; every other surface is still reflowed manually. -## Keep everything ASCII - -Non-ASCII characters are **banned repo-wide** (enforced by the `no-non-ascii` semgrep rule). Write ASCII on the -first draft -- never paste a glyph and expect a fix-up pass. Use the ASCII spelling instead: `--` for an em-dash, -`->` for an arrow, `...` for an ellipsis, `<=`/`>=`/`!=`/`^2` for math glyphs, and straight `'`/`"` quotes for -curly quotes. ASCII keeps terminals, log scrapers, and `grep` reading the same bytes the editor shows. The only -exemptions are generator-owned trees (`generated/`, `verification/`, `**/HELP.md`, `**/pkg/`), license texts, and -binary assets -- everything you hand-write is bound by the ban. - -## No trailing-backslash line continuations - -Trailing-backslash line continuations (a line ending in `\` to join with the next) are **banned everywhere** in -this repo. The only exceptions are README files and generated trees (e.g. `verification/`). Character escapes -_inside_ string literals -- `"\n"`, `"\t"`, regex `\d`, a Windows path `C:\Foo\Bar` as a value -- are NOT -continuations and are fine; the ban is on the end-of-line `\` that joins source lines into one logical statement. - -If a logical line would otherwise exceed the 120-char limit, pick a no-backslash split. Some patterns that work in the -languages this repo uses: - -- **mise task `run` bodies**: factor into shell variables / `[vars]` - entries / multiple statements. Do this on the first draft (see also the line-limit rule above), not as a fix-up pass. -- **Dockerfile ENV / ARG**: build the value across multiple `ARG`s and - compose the final `ENV` from them via `${VAR}` expansion. Example - from `Dockerfile.nanoserver`'s `MISE_DISABLE_TOOLS`: - - ARG MISE_DT_BASE=cargo:dart-typegen,conda:m2-gnupg,... - ARG MISE_DT_PY=pipx:componentize-py,pipx:... - ENV MISE_DISABLE_TOOLS=${MISE_DT_BASE},${MISE_DT_PY} - -- **Dockerfile `RUN` block**: switch to BuildKit's HEREDOC form - (`RUN bash <<'EOF'` ... `EOF`) -- each shell command sits on its own line - with no continuation needed. Three rules, all enforced by - `config/conftest/policy/dockerfile/dockerfile.rego` + the matching semgrep rule - under `config/semgrep/`: (1) interpreter is **`bash`, placed BEFORE the - `< - `ENV FOO=${FOO}`); (3) **first body line must be `set -euo pipefail`** - -- HEREDOC RUNs go through bash without inheriting strict mode from any - outer setting, so the invariant has to be re-declared inside every - body. Leave a blank line between the closing `EOF` and the next - instruction -- hadolint's parser otherwise errors with `unexpected 'E' - expecting a new line...`. -- **YAML run-bodies**: a `|` block scalar already keeps each shell - line natural; no continuations are necessary. -- **Long flag lists**: drop them into a config file (`.env`, `.cfg`, - task `[vars]`) or split into one flag per line inside a HEREDOC / - block scalar. +## Write ASCII, and never join lines with a trailing backslash + +Both are banned repo-wide, and both are cheaper to get right on the first draft than to fix up: write `--` for an +em-dash, `->` for an arrow and straight quotes for curly ones. When a logical line would exceed the 120-char limit, +pick a split that needs no trailing `\`: + +- **mise task `run` bodies**: factor into shell variables, `[vars]` entries or multiple statements. +- **Dockerfile ENV / ARG**: build the value across multiple `ARG`s and compose the final `ENV` from them via `${VAR}` + expansion, as `Dockerfile.nanoserver`'s `MISE_DISABLE_TOOLS` does. +- **Dockerfile `RUN` block**: use BuildKit's heredoc form, `RUN bash <<'EOF'` ... `EOF`, so each command sits on its + own line. The checks hold its shape (interpreter before the tag, quoted delimiter, `set -euo pipefail` first); an + ARG the body needs must be promoted to ENV first, since the quoted delimiter defers every expansion to bash. Leave + a blank line between the closing `EOF` and the next instruction. +- **YAML run-bodies**: a `|` block scalar already keeps each shell line natural. +- **Long flag lists**: drop them into a config file or task `[vars]`, or one flag per line inside a heredoc or block + scalar. If a split honestly isn't possible without `\`, stop and surface the constraint -- do not reintroduce the regression. Existing `\` uses in the repo (Dockerfile RUN-block multi-liners, etc.) are regressions slated for @@ -398,11 +352,12 @@ results that don't match the canonical pipeline (different excludes, different ` settings, different file globs). taplo specifically: the only right way to format TOML in this repo is `mise run taplo-fmt`. -The `mise run ` formatters and checks per file type. The aggregates (`fmt`/`check`/`fmt-all`/`check-all`) -run every loaded language's row; guest rows need their `MISE_ENV` loaded. +`CHECKS.md` lists every check task across every `MISE_ENV` -- the tool it runs, the env that declares it, the +config it reads -- and every rule those tools are configured with, generated from the task tables and rule files +themselves. Pick the check tasks for the files you touched from there; a guest-language task needs its `MISE_ENV` +loaded. -Formatter task(s) per file type (a list rather than a table: padded to the same column widths as the check table -below, the two tables' shared file-type rows read as a clone to jscpd): +Formatter task(s) per file type: - `*.rs` -> `cargo-fmt`, `cargo-clippy-fix`, `parfit-fmt` - `*.toml` -> `taplo-fmt` @@ -411,29 +366,12 @@ below, the two tables' shared file-type rows read as a clone to jscpd): - `*.zig` -> `fmt:zig` - `*.c`, `*.cpp` -> `clang-format` - `*.cs` -> `fmt:dotnet` +- `*.md`, `*.yaml`, `*.json`, `*.ts`/`*.js`, `*.css`, `*.html`, `*.java`, `Dockerfile*` -> `dprint-fmt` +- multi-line task bodies in `.mise/config*.toml` -> `shfmt-mise-fmt` -| File type | Check task(s) | -| -------------- | ---------------------------------------------------------------------------------------------- | -| `*.rs` | `cargo-check`, `cargo-clippy`, `cargo-fmt-check`, `cargo-doc-check`, `ast-grep-check` | -| `*.toml` | `taplo-check`, `conftest-check-toml`, `semgrep-check` | -| `*.yaml` | `ast-grep-check`, `conftest-check-yaml`, `ryl-check`, `action-validator-check`, `zizmor-check` | -| `*.json` | `semgrep-check` | -| `*.py` | `check:python` | -| `*.dart` | `check:dart` | -| `*.zig` | `check:zig` | -| `*.c`, `*.cpp` | `clang-format-check`, `clang-tidy-check`, `cpplint-check` | -| `*.cs` | `check:dotnet` | -| `*.java` | `check:java` | - -`dprint-fmt` / `dprint-check` cover `*.md`, `*.yaml`, `*.json`/`*.jsonc`, `*.ts`/`*.js`, `*.css`, `*.html`, -`*.java`, and `Dockerfile*`. `*.json`/`*.jsonc` is formatted by **two** tools, so a new config JSON must satisfy -both: `oxfmt-fmt` / `oxfmt-check` (in the `js` env, alongside `oxlint-check`) also claim it, and they break ties -differently -- oxfmt collapses a short array onto one line where dprint leaves it expanded, so a file dprint -accepts can still fail `oxfmt-check` in CI. `hadolint-check` also lints Dockerfiles, and `link-check` scans -`*.md` + `*.rs`. Every file is covered by `editorconfig-check`, `typos-check` and `gitleaks-check`, file and -directory names by `ls-lint-check`, and `*.yml` is rejected by `semgrep-check` (use `*.yaml`). A multi-line task -body inside `.mise/config*.toml` is shell, not TOML, so it carries two more of its own: `shfmt-mise-fmt` / -`shfmt-mise-check` format it, and `shellcheck-mise-check` lints it. +`*.json`/`*.jsonc` is formatted by **two** tools, so a new config JSON must satisfy both: `oxfmt-fmt` (in the `js` +env) breaks ties differently from `dprint-fmt` -- it collapses a short array onto one line where dprint leaves it +expanded -- so a file dprint accepts can still fail `oxfmt-check` in CI. For Rust inner-loop iteration on a single crate, use `mise run cargo-clippy-check-pkg ` (alias `clippy-pkg`) instead of `cargo-clippy-check` -- it runs `cargo clippy --keep-going --tests -p ` so you @@ -510,8 +448,8 @@ Languages: - **Zig -> WASM**: zig-data1, zig-except1 (C++ wasm-exception-handling demo), zig-math1 - **Python (componentize-py -> WASI Preview 2 component)**: wasi-graphics-info -- runs in - `et-ws-wasi-runner` rather than the browser. The WIT world the component implements is at - `services/ws-wasi-runner/wit/world.wit` and is mirrored under the module's own `wit/`. + `et-ws-wasi-runner` rather than the browser. The WIT world the component implements is + `generated/specs/wit/world.wit`. Drives two standardised WASI interfaces end-to-end: (1) `wasi:webgpu/webgpu@0.3.0-rc.2` for a real 4x4 compute matmul through a host wgpu device, and (2) `wasi:nn/{graph, tensor, inference}` for MNIST inference. Bundles `mnist-12.onnx` (served @@ -531,7 +469,7 @@ browser WASM modules). It fetches the module's `pkg/package.json` from the ws-se the `.wasm` named by the `wasi-main` field, instantiates it under `wasmtime` with async support, and calls the exported `entry.run` function. -Host imports (defined in `wit/world.wit`, package `et:ws-wasi@0.1.0`): +Host imports (defined in `generated/specs/wit/world.wit`, package `et:ws-wasi@0.1.0`): - `log` -- `log` and `set-status` for guest output - `clock` -- `sleep-ms`, `now-ms` @@ -573,11 +511,11 @@ Plus, attached to the same Linker but defined by external WIT packages: sources of truth (AsyncAPI/OpenAPI YAML, WIT, KDL, schema JSON, the typed Rust REST client, the Zig client). - **onnx** (`et-onnx`) -- ONNX model utilities. -Each utility has a committed `HELP.md` (under its crate dir) that mirrors the clap-derive tree via the -`markdown-help` feature + hidden `--markdown-help` flag. **Read `utilities//HELP.md` to learn what -the CLI does -- don't run `cargo run -p -- --help`** (much slower: cargo has to build the binary -first; HELP.md is the same content as a static file). `mise run gen-help-all` regenerates them all; the -`gen-help-check` task (wired into `check:rust`) fails on drift. +Each utility has a committed `HELP.md` (under its crate dir) that mirrors its clap-derive tree, written by +`et-int-gen help-md` from each crate's command tree. **Read `utilities//HELP.md` to learn what the CLI does -- +don't run `cargo run -p -- --help`** (much slower: cargo has to build the binary first; HELP.md is the same +content as a static file). `mise run gen-help-all` regenerates them all; the `gen-help-check` task (wired into +`check:rust`) fails on drift. ### Verification (`verification/`) @@ -1192,39 +1130,15 @@ variadic arg and one with a plain arg, on the mise version the CI lanes install. ## Linting Lint checks must be expressed through one of the repo's linters -- **never** as a bespoke shell script, whether a -standalone file or a mise task `run`. The available linters: - -- **ast-grep** (`config/ast-grep/rules/`) -- structural rules for code **and - YAML** (e.g. GitHub Actions workflows). -- **semgrep** (`config/semgrep/`) -- incl. `languages: [generic]`, which works on - TOML/text (e.g. `mise-config.yaml` lints `.mise/config*.toml`). -- **taplo** JSON-schemas (`config/taplo/`) -- TOML structure, applied via - `taplo lint --schema` in `taplo-check`. -- **conftest** (`config/conftest/policy/`) -- Rego policies over the combined - TOML/YAML config set, for cross-file checks the schema linters can't express. -- **regal** (`config/regal.yaml`, via `regal-check`) -- lints the Rego policies - themselves (style, idioms, bugs). Carves out conftest-specific patterns - (multiple `deny` rules per file, cross-package `data.*` references, no OPA - entrypoints) that vanilla regal would flag. -- **shellcheck on mise task bodies** (`.mise/shellcheck-mise.jq`, via - `shellcheck-mise-check`) -- extracts every multi-line bash-shell `run = """ ... - """` from `.mise/config*.toml`, masks Tera tokens (`{{ ... }}` -> `MISEVAR`, - `{% ... %}` -> empty), and shellchecks the lot. This is how shell-quality - lints reach mise task bodies (shellcheck itself doesn't read TOML). -- **shfmt on mise task bodies** (`.mise/shfmt-mise.awk`, via `shfmt-mise-fmt` and `shfmt-mise-check`) -- splits those - same bodies out, shfmt-formats each one, and merges the result back over the config, so a task body is held to the - same formatting as any other shell in the repo. The check reports shfmt's own diff and names `shfmt-mise-fmt` as the - fix. Its one demand on how a body is written: inside a `"""` block a backslash meant to reach the shell must be - doubled, since a lone `\n` / `\r` / `\b` is TOML syntax that folds into a control character rather than the two bytes - the shell wants -- the split pass rejects one instead of guessing which was meant. `\\` and `\"` are the two escapes - it does decode, so an embedded quote stays written the TOML way. -- plus hadolint, ls-lint (file/dir naming), zizmor (Actions security), ryl - (YAML), lychee (links), clang-format / clang-tidy / cpplint / flawfinder (C, in the zig config), - editorconfig-checker, typos, and action-validator for their domains. - -ast-grep has no TOML grammar, so it **cannot** lint TOML -- use a taplo schema or -a semgrep `generic` rule there. If none of the above can express a check, -propose adding a new mise-installable linter rather than scripting it by hand. +standalone file or a mise task `run`. `CHECKS.md` lists every linter, its config and its rules. When writing a new +rule, pick the home by what it inspects: structural rules over code **and YAML** go to ast-grep; text, including +TOML, to a semgrep `languages: [generic]` rule; TOML structure to a taplo schema; cross-file checks over the +combined TOML/YAML config set to a conftest policy. ast-grep has no TOML grammar, so it **cannot** lint TOML. If +none of them can express a check, propose adding a new mise-installable linter rather than scripting it by hand. + +Inside a `"""` task body a backslash meant to reach the shell must be doubled, since a lone `\n` / `\r` / `\b` is +TOML syntax that folds into a control character rather than the two bytes the shell wants; the task-body formatter +rejects one rather than guessing which was meant. `\\` and `\"` are the two escapes it decodes. ### Maximise linter coverage; suppress only narrowly, with justification @@ -1289,8 +1203,10 @@ of the duplicated text -- not on a file path or line range. So editing any line already-duplicated block re-hashes it, and a clone the baseline has recorded for months is reported as `[NEW]` without one line of fresh copy-paste. A repo-wide mechanical edit lights up every duplicated block it touches at once, which reads alarmingly and tempts exactly the baseline rewrite this rule forbids. Read a `[NEW]` clone as -"this duplication is now in front of you", not as "you wrote this duplication": check whether the pair predates -your change, then remove the duplication on its merits. +"this duplication is now in front of you", not as "you wrote this duplication", and check whether the pair predates +your change. If it does, do not refactor it away as a side effect of the unrelated edit, and do not run +`jscpd-baseline-update` yourself: stop and ask the operator to re-baseline, naming each pre-existing clone pair and +the edit that re-hashed it. Only duplication your change actually introduced is yours to factor out. A baseline gets rewritten only for a change that is genuinely not about the finding: a mass rename, a directory move, a vendored tree landing wholesale. Even then, say so explicitly, get the operator's sign-off first, and @@ -1323,7 +1239,7 @@ addresses one occurrence, and the local rule is what stops the next one. ### When you spot a style or consistency issue, write a rule -If a code-review comment, a fix-up commit, or a CLAUDE.md paragraph would tell the next contributor "don't do X" +If a code-review comment, a fix-up commit, or an AGENTS.md paragraph would tell the next contributor "don't do X" or "always do Y", that's evidence the codebase wants a _rule_, not just a note. Reach for the linter stack first: which of the available tools (`ast-grep` / `semgrep` / `taplo` / `conftest` / `regal` / `shellcheck-mise` / ...) can express the rule? Code-as-policy stays in sync with the codebase; prose drifts. Documentation has its place when @@ -1452,16 +1368,11 @@ linter to ignore it. `generated/` trees that we commit (`generated/python-rest/` are the canonical case -- see the existing `[generated/python-rest/**]` block in `.editorconfig` for the shape. Reach for a config-file exclude only after confirming gitignoring isn't viable. -## No `scripts/` directory - -Do not create a `scripts/` directory or drop loose shell/Python scripts in the -repo. Every script belongs in one of two places: +## Where a script goes -- **Short and simple** -> an inline `mise` task (`run = """ ... """` in - `.mise/config.toml` or a `.mise/config..toml`). It stays discoverable - via `mise tasks` and runs as `mise run `. -- **More involved** -> its own tool directory under `utilities/` with its own - `README.md` documenting what it does and how to run it. +A loose shell or Python script has no place in the repo. A short, simple one is an inline `mise` task, which stays +discoverable via `mise tasks`; anything more involved is its own tool directory under `utilities/`, with a +`README.md` saying what it does and how to run it. ## Don't depend on host tools in mise tasks @@ -1542,8 +1453,8 @@ isolated run yet be _required_ by CI. **Validate with the full `mise run check`, before touching one of these `#[expect]`s.** (The clean fix -- `[resolver] feature-unification = "workspace"` so every build sees the same features -- is still nightly-only via `-Z feature-unification`.) -The workspace denies a broad set of clippy lints (see `[workspace.lints.clippy]` in `Cargo.toml`), including -restriction lints. One you'll hit often: **`clippy::single_call_fn`** fires on a private function called from +The workspace denies a broad set of clippy lints, restriction lints included, all listed in `CHECKS.md`. One +you'll hit often: **`clippy::single_call_fn`** fires on a private function called from exactly one site. Do **not** inline the function just to silence it -- a function that is a distinct, named step (kept separate for readability, or that will gain more callers) is legitimate. Keep it and annotate with `#[expect(...)]` and a real justification: @@ -1566,12 +1477,8 @@ missing, not which subprocess failed. The caller is then left to invent an expla invents is a guess -- which is how a missing tool surfaces three layers up as an empty list rather than as the sentence naming the tool. -**A function returning `Option` is the sharpest form of this**, because the return type is where the reason -would have gone. `Result` carries it; `Option` discards it at exactly the moment it was known. If a function -can fail, it returns `Result` with an error that says what happened. `Option` is for a value that is -legitimately absent without anything having gone wrong -- and that case is rarer than it looks, which is why -`new-fn-returns-option` rejects a new one and holds the existing returns in an explicit list. A name joining -that list is a decision to record, not a default to fall into. +**A function returning `Option` is the sharpest form of this**, and `new-fn-returns-option` rejects a new one; a +name joining its list of existing returns is a decision to record, not a default to fall into. The same applies to a field. `Option` for "unset means work it out" is a third state that every reader has to resolve; a `#[serde(default = "...")]` naming the function that computes the default says the same diff --git a/CHECKS.md b/CHECKS.md new file mode 100644 index 00000000..a6ec8f88 --- /dev/null +++ b/CHECKS.md @@ -0,0 +1,1015 @@ +# Checks + +- **Checks:** 66 +- **Tools:** 44 +- **Shell-script checks:** 9 +- **Rules:** 303 custom local rules, or non-default strict linter settings + +Every check is listed across every `MISE_ENV`, filed under the tool it runs. Each entry names the env whose config +declares it, the aggregate that runs it as part of `mise run check`, and the config files it reads. Generated by `mise +run gen:checks` from the task tables in `.mise/config*.toml`, the rule files under `config/` and the `[workspace.lints]` +in `Cargo.toml`; `mise run checks-md-check` fails when this file drifts from them. + +## `action-validator` + +- `action-validator-check` (`default` env; run by `check:rust`) -- Validate GitHub Actions workflow + composite-action + YAML. + +## `actionlint` + +- `actionlint-check` (`default` env; run by `check:rust`) -- Lint GitHub Actions workflows (actionlint): local-action + input validation, expression syntax, shellcheck. + +## `agent-lint` + +- `agent-lint-check` (`default` env; run by `check:rust`) -- Lint this repository's agent configuration (AGENTS.md, + .claude/) with agent-lint. + +## `ast-grep` + +- `ast-grep-check` (`default` env; run by `check:rust`) -- Run ast-grep structural-search rules. Config: + `config/ast-grep/sgconfig.yaml`. + +Rules, from `config/ast-grep/rules`: + +- `command-requires-command-error` -- A file that imports `std::process::Command` via `use` must also `use + command_error::CommandExt` (import it as `use command_error::CommandExt as _;`) so command execution goes through the + checked methods (`status_checked` / `output_checked` / `spawn_checked`), whose errors carry the command line and exit + status -- a raw `std` `Command`'s `.status()` / `.output()` / `.spawn()` errors carry none of that. If a call + genuinely needs the raw outcome (e.g. a test that asserts a non-zero exit, or an exit-code proxy), fully-qualify + `std::process::Command` at the call site instead of importing it, so this rule does not apply. +- `derive-attribute-order` -- Put `#[derive(...)]` before every inert or helper attribute on the same item -- + `#[non_exhaustive]`, `#[repr]`, `#[cfg_attr]`, and derive helpers such as `#[serde]`, `#[command]`, `#[strum]` or + `#[asyncapi]`. Only doc comments, `#[cfg]`, `#[expect]` and attribute macros that must see the item before the derive + runs (`#[serde_inline_default]`, `#[wasm_bindgen]`) may come first. One order everywhere puts an item's derive list in + the same place on every type, and keeps each helper next to the derive that reads it. A new attribute macro that has + to precede the derive joins the allow-list in this rule. +- `doc-summary-ends-with-period` -- A doc comment's first line must be a complete one-line summary ending in terminal + punctuation (`.`, `!`, or `?`). Put any elaboration in a following paragraph after a blank `///` line so the summary + stays a single line -- rustdoc and readers treat that first line as the item's summary. +- `gha-check-lane-fetch-depth-0` -- The check lane's `actions/checkout@...` step must declare `fetch-depth: 0` in its + `with:` block. Two of the checks this lane runs read the commit graph rather than the worktree. At depth 1 the only + commit that exists is the tip, so every commit hash written into a tracked file resolves to nothing and the lane fails + on a repo that is perfectly fine -- while the branch-freshness check, having no `origin/main` to compare against, + quietly skips itself and reports success. The history is a few MiB, so fetching all of it costs close to nothing here. +- `gha-checkout-fetch-depth-1` -- Every `actions/checkout@...` step in these workflows must declare `fetch-depth: 1` in + its `with:` block. Explicit-beats-implicit (the action default is already 1, but pinning it at the call site keeps the + value visible in review and ensures a future default change doesn't silently start cloning more), and the rule's + primary purpose is to prevent `fetch-depth: 0` from creeping back in -- nothing these lanes run reads the commit + graph, so cloning every commit just burns runner minutes and disk. The check lane is excluded here, and held to the + opposite requirement, because two of the checks it runs do read the commit graph and resolve nothing at depth 1. +- `gha-default-shell-bash` -- Every GitHub Actions workflow must declare the default run shell as bash with -euo + pipefail, exactly: defaults: run: shell: bash --noprofile --norc -euo pipefail {0} so steps run in bash on every + runner (Windows included) with strict-mode flags on every step -- no per-step `set -euo pipefail` boilerplate needed. + GHA's bare `shell: bash` already implies `-e -o pipefail`; this explicit form additionally adds `-u` (unset variable + -> error). (Pairs with gha-no-step-shell, which forbids per-step `shell:`.) +- `gha-job-timeout-minutes` -- Every GitHub Actions job must declare `timeout-minutes:` at the job level. The runner's + default per-job timeout is 360 minutes (6 hours), which is long enough that a hung job (deadlocked test, + infinite-recurse cargo resolver, stuck `docker pull`) drains the runner-minutes budget before anyone notices. Pin + every job to a realistic ceiling for that job's work. Use `${{ matrix.timeout }}` or similar if the right value varies + by entry. +- `gha-no-folded-strip` -- Don't use `>-` (folded block scalar with strip-chomping) in workflow YAML. The output reflows + whitespace and silently swallows trailing newlines, which bites when the step's `run:` is a shell command that depends + on line breaks -- a `>-` block joins lines with spaces, not newlines. Use either: - a plain single-line `run: + `, or - a literal block `run: |` (which preserves newlines verbatim). +- `gha-no-step-shell` -- Don't set `shell:` on a workflow step. Every workflow defaults to bash (defaults.run.shell) and + steps must use it -- write the step in bash (e.g. `sc`/`net`/`printf` instead of PowerShell cmdlets, even on Windows + runners, which have Git Bash) rather than overriding the shell per step. No per-step shell override is permitted in + these workflows. +- `gha-no-step-shell-upstream-cache` -- In upstream-cache.yaml the only permitted per-step `shell:` override is `shell: + msys2 {0}` -- the wrapper msys2/setup-msys2 requires for the augeas Windows build to run inside its MINGW64 env (Git + Bash isn't a substitute). Any other shell override must use the workflow default bash. +- `gha-standard-concurrency` -- Every GitHub Actions workflow must declare the standard top-level concurrency block + exactly: concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: ${{ startsWith(github.ref, + 'refs/pull/') }} This groups runs per workflow per ref, and cancels older in-progress runs on a PR ref only -- so a + push to main never cancels its predecessor (lest the merge-queue lose a result), but PR pushes don't burn runner + minutes on superseded commits. Deviating from this group/key shape leads to surprising cancellation behaviour. +- `gha-strategy-fail-fast-false` -- Any job that declares `strategy:` (matrix or otherwise) must also set `fail-fast: + false` inside it. GHA's default of `fail-fast: true` cancels every other matrix entry the moment one fails, which + hides the failure modes specific to other OS / version / runner cells -- exactly the matrix cells we added the matrix + to exercise. Opt out explicitly: strategy: fail-fast: false matrix: ... +- `inherent-impl-first` -- Put a type's inherent `impl` block before its trait `impl`s in the same module. A reader then + meets the type's own constructors and methods first, and the trait impls that follow read as what they are: the type's + conformance to interfaces defined elsewhere. +- `new-fn-returns-option` -- This function returns `Option`, and a new one may not. The return type is where the reason + a call failed would have gone: `Result` carries it, `Option` discards it at the moment it was known. `None` says + "there isn't one" and nothing else -- not which input was wrong, not which file was missing, not which subprocess + failed -- so the caller invents an explanation, and a missing tool surfaces three layers up as an empty list rather + than as the sentence naming the tool. Return `Result` with an error that says what happened. `Option` is for a value + that is legitimately absent without anything having gone wrong, which is rarer than it looks. The list below is every + function that returned `Option` when this rule was written. It is a record of what is already here, not a pattern to + copy: a name joins it only with the operator's sign-off, and the point of naming them one by one is that adding to it + is a decision somebody makes rather than a default anything falls into. Prefer emptying it -- a function that leaves + the list has had its failures given names. +- `no-allow-attributes` -- `#[allow()]` and `#![allow()]` are forbidden. Use `#[expect(, reason = + "...")]` (or `#![expect(...)]` at module / crate scope). `#[expect]` requires the lint to actually fire, so the + suppression is removed automatically when the underlying issue is fixed upstream -- `#[allow]` can sit silently + forever. This rule complements the workspace's `clippy::allow_attributes` lint, which doesn't fire on inner attributes + (`#![allow(...)]`) -- see . +- `no-cargo-manifest-dir` -- `CARGO_MANIFEST_DIR` is forbidden outside the project-root helper. It points at the crate + directory, not the repository root, so reaching repo files through it needs brittle `..` hops. Locate the repository + root with `et_path::find_project_root_from_manifest()` in a `build.rs` (compile time) or + `edge_toolkit::config::get_project_root()` (runtime) instead. +- `no-concat-raw-strings` -- `concat!(...)` of raw-string (`r#"..."#`) fragments is forbidden -- it is an unreadable way + to build one string (a regex, an embedded template) out of a stack of `r#"..."#,` lines. Use a single multi-line raw + string literal instead, or a named `const`, or -- for a regex -- `(?x)` verbose mode so the pattern can span lines + without concatenation. Plain-string `concat!` (wrapping a long message, `concat!(env!(...), "...")`) is fine; only + raw-string fragments are banned. +- `no-consecutive-expect` -- Consecutive `#[expect(...)]` attributes on the same item. Merge them into a single + `#[expect(lint_a, lint_b, reason = "...")]` (one attribute can list several lints). Stacking separate `#[expect]`s -- + even with a comment between them -- fragments the suppression and makes it easy to leave one behind when the + underlying issue is fixed. Applies to inner `#![expect(...)]` too. +- `no-current-dir` -- `std::env::current_dir()` is forbidden outside the project-root helper. The current directory is + not a reliable anchor for repository files -- it depends on where the binary happens to be invoked. Use + `edge_toolkit::config::get_project_root()` at runtime, or `et_path::find_project_root()` from a build script at + compile time; both locate the repository root via the `.dprint.jsonc` marker. +- `no-doctest` -- Doctests are forbidden. Move runnable examples into a `tests/` file (every test file must start with + `#![cfg(test)]`). +- `no-env-macro` -- `env!` / `option_env!` read a compile-time environment variable and are forbidden for app config -- + read configuration through a `serde`-derived struct deserialised with `serde-env` (see the `no-std-env-var` rule and + `et-ws-runner-common::config`) so every variable is declared in one typed place. Only these cargo-provided constants, + which have no serde-env equivalent, are exempt: - `CARGO_BIN_EXE_` -- the built binary's path, injected by cargo + for an integration test. - `CARGO_PKG_VERSION` / `CARGO_PKG_NAME` -- crate identity baked into the binary. - + `ET_WIT_DIR` -- the WIT directory injected at build time for wit-bindgen. `CARGO_MANIFEST_DIR` is deliberately NOT + exempt -- use `edge_toolkit::config::get_project_root()` at runtime (see the `no-cargo-manifest-dir` rule). +- `no-expect-used-suppression` -- Suppressing `clippy::expect_used` is forbidden -- `.expect("...")` messages are not + wanted in this codebase, so the workspace-denied lint must stay in force everywhere. Use `.unwrap()` instead: tests + get it for free (clippy.toml's `allow-unwrap-in-tests`), and non-test code that genuinely must panic suppresses + `clippy::unwrap_used` narrowly with a reason, or better, handles the error. No autofix: these attributes usually list + other lints that must be kept, so removing just the `clippy::expect_used` entry (and rewriting the `.expect(...)` + calls it permitted) is context-dependent. +- `no-extern-crate-self` -- `extern crate self as ;` re-introduces the crate's own name as a path root inside its + library, letting code write `::foo` instead of `crate::foo` / `self::foo`. Without it, rustc already rejects + own-name paths in lib code (E0433); the alias is only needed by proc-macro crates whose generated code emits + `::::...`. This workspace has none, so use `crate::` / `self::` for local paths instead. +- `no-inline-mod` -- Inline `mod X { ... }` blocks are forbidden. Move the module body into a separate file (`X.rs` or + `X/mod.rs`) and declare it with `mod X;` instead. +- `no-map-err` -- `.map_err(...)` is forbidden. Convert through `From` (thiserror's `#[from]` / `#[error(transparent)]`) + and rely on `?`, or define an extension trait whose impl carries the only `map_err` for the pattern. At actix-web + boundaries, derive `ResponseError` via `actix-web-thiserror` instead of building `actix_web::error::Error*` values + inside `map_err` closures. +- `no-mixed-doc-line-comments` -- Doc comment (`///`) is adjacent to a regular `//` comment. Either turn the regular + comment into a doc comment (`///`) or move it away from the doc block -- readers expect a contiguous `///` run to be + the item's rustdoc. +- `no-mod-in-tests` -- `mod` is forbidden inside test files (`tests/**/*.rs` and `src/test_*.rs`). Keep shared test + helpers in a test-support library crate -- `et-test-helpers` for low-dependency helpers, or a dedicated crate such as + `et-ws-test-server` / `et-test-otlp` -- and `use` them, rather than a `tests/common/mod.rs` include or an inline `mod + { ... }`. A library gives each helper one compiled home (so coverage and lints see it once) instead of recompiling it + per test binary, and it keeps integration-test files flat: one file per test binary. +- `no-non-ascii` -- Non-ASCII character in a string literal or doc comment. Stick to ASCII in source: use `--` for an + em-dash, `->` for an arrow, and straight quotes for curly quotes, etc. ASCII-only source keeps terminals, log + scrapers, and `grep` reading the same bytes the editor shows. +- `no-relative-path-literal` -- Relative path literals ("." / ".." / "./..." / "../...") are forbidden: they hardcode a + location relative to the process's current directory or this crate's directory, which is brittle. Anchor paths to the + repository root instead -- `edge_toolkit::config::get_project_root()` (runtime) or + `et_path::find_project_root_from_manifest()` (build scripts) -- and join the remainder onto it. (Char literals like + `'.'` for splitting are unaffected.) +- `no-result-alias` -- Defining a `type Result<...>` alias shadows `std::result::Result` at file scope and makes every + `Result` ambiguous to readers. Spell the error type at each call site instead (`Result`). +- `no-result-string-err` -- `Result<_, String>` flattens any typed error to a free-form string at the point of failure + -- losing the source variant, the ability to branch on it, and the chain of causes. Define a `thiserror` enum (or + reuse one of the workspace's `*Error` types) and return that instead. +- `no-shadow-result` -- Don't shadow `std::result::Result` at file scope -- every bare `Result` then becomes + ambiguous to readers. Either spell the error type at each call site (`Result`), reference the local + alias by its qualified path (`crate::Result`, `et_int_gen::Result`), or alias the import (`use foo::Result as + FooResult;`). +- `no-std-env-var` -- `std::env::var` / `std::env::var_os` is forbidden for app config. Read configuration through a + `serde`-derived struct deserialised with `serde-env` (see the runner `config` modules and + `et-ws-runner-common::config`), so every variable is declared in one typed place with defaults and validation. + Exemptions, intentionally narrow: - `RUST_*` (e.g. `RUST_LOG`, consumed by tracing) -- diagnostics. - `ET_TEST_*` -- + test-only switches; production binaries must NOT branch on these. The integration test in + services/ws-wasi-runner/tests/ sets one to opt the spawned runner into a macOS-only fast-exit path. - `MISE_*` (e.g. + `MISE_ENV`) -- the mise tool's own state, not app config; reading these lets helpers like `mise_env_includes` reflect + tooling behaviour without round-tripping through a struct. Every exemption above is a name prefix, which keeps it + self-limiting: a variable has to be named into the exemption to use it. A bare variable name would not be -- it would + open that read to every file in the repo, including production code that has a config struct to put it in. `PATH` was + such an entry, and is now a one-line `ast-grep-ignore` on the single test helper that shapes `PATH` for a stand-in. +- `no-std-fs` -- `std::fs` is forbidden -- its `io::Error`s carry no path, so a failure reads "No such file or + directory" with no clue which file. Use `fs_err` (`fs-err` workspace dep), whose drop-in wrappers attach the offending + path to every error. Import it as `use fs_err as fs;` and call `fs::read`, `fs::write`, `fs::File::open`, etc., + exactly as you would `std::fs`. +- `no-string-literal-line-continuation` -- Backslash-newline inside a Rust string literal is a line continuation (the + `\` + newline + leading whitespace all get elided at parse time). Banned per the repo-wide no-trailing-backslash rule. + Use `concat!("a", "b")` to assemble a multi-line string literal, keep it on one line, or drop to a raw string `r"..."` + if the content really needs literal backslashes at line ends. A generic-regex rule catches the same pattern repo-wide; + this variant is the Rust-AST-aware companion, and runs faster. +- `no-string-new` -- `String::new()` is banned (`DeepSource RS-W1079`): construct empty strings with `String::default()` + instead, so the zero value routes through the `Default` impl like every other default-constructed value in the + codebase. +- `org-identity-lives-in-et-org` -- This constant spells out the organisation name or the crate prefix. Both belong to + `et-org`, which is the one place either literal is written: take the value from `et_org::ORG`, `et_org::CRATE_PREFIX`, + `et_org::NPM_SCOPE`, `et_org::REPOSITORY_URL` or `et_org::IMAGE_REGISTRY`, or build a longer string from them, rather + than writing the name out again here. These strings are the same fact wearing different clothes -- the npm scope, the + container registry, the repository URL and the crate prefix all move together if the project is renamed -- so a copy + living outside `et-org` is a copy that gets missed. `et-org` writes the organisation exactly once and assembles the + rest from it, which is what makes that rename a one-line change. A `concat!` cannot take a constant, so a call site + that has to embed the URL at compile time uses `et_org::repository_url!()`; `et_org::org!()` is there for the same + reason. This does not apply to a specific name that merely starts with the prefix. `et-ws-server` names one crate and + `et-path-prefix-probe` names one test fixture; neither is the project's identity, and neither changes because the + organisation did. Only the bare prefix `"et-"` and any string carrying the organisation name are covered. Tests are + deliberately not exempt from the definition rule, but asserting a literal is not defining one: a test that pinned + expected output against `et_org::NPM_SCOPE` would keep passing if that constant were wrong, so those assertions stay + spelled out. +- `prefer-self-mod-use-bare-chain` -- This file declares `mod $X;` and references it via `use $X::...`. Write `use + self::$X::...` to make the local reference explicit. +- `prefer-self-mod-use-bare-group` -- This file declares `mod $X;` and references it via `use $X::{...}`. Write `use + self::$X::{...}` to make the local reference explicit. +- `prefer-self-mod-use-pub-chain` -- This file declares `mod $X;` and re-exports it via `pub use $X::...`. Write `pub + use self::$X::...` to make the local reference explicit. +- `prefer-self-mod-use-pub-group` -- This file declares `mod $X;` and re-exports it via `pub use $X::{...}`. Write `pub + use self::$X::{...}` to make the local reference explicit. +- `prefer-self-mod-use-pubcrate-chain` -- This file declares `mod $X;` and re-exports it via `pub(crate) use $X::...`. + Write `pub(crate) use self::$X::...` to make the local reference explicit. +- `prefer-self-mod-use-pubcrate-group` -- This file declares `mod $X;` and re-exports it via `pub(crate) use $X::{...}`. + Write `pub(crate) use self::$X::{...}` to make the local reference explicit. +- `prefer-self-mod-use-pubsuper-chain` -- This file declares `mod $X;` and re-exports it via `pub(super) use $X::...`. + Write `pub(super) use self::$X::...` to make the local reference explicit. +- `prefer-self-mod-use-pubsuper-group` -- This file declares `mod $X;` and re-exports it via `pub(super) use $X::{...}`. + Write `pub(super) use self::$X::{...}` to make the local reference explicit. +- `use-mod-order` -- Order top-level items: external `use` (std / third-party) first, then `mod` / `pub mod` + declarations, then local `use self::` / `crate::` / `super::`. So an external `use` must not appear after a `mod`, and + a `self`/`crate`/`super` `use` must not appear before a `mod`. +- `write-ending-newline` -- A `write!` whose format string ends in `\n` is a `writeln!` written the long way: use + `writeln!` and drop the final `\n`. This mirrors `DeepSource RS-C1005`. clippy's `write_with_newline` covers only a + single trailing newline and deliberately skips a string ending in `\n\n`, which is the case this rule exists to catch. + +## `cargo check` + +- `cargo-check` (`default` env; run by `check:rust`). + +## `cargo clippy` + +- `cargo-clippy-check` (`default` env; run by `check:rust`). Config: `Cargo.toml`, `config/clippy.toml`. +- `cargo-clippy-check-pkg` (`default` env; not run by `mise run check`) -- cargo clippy on a single workspace package + (narrow inner-loop check). Config: `Cargo.toml`, `config/clippy.toml`. + +Rules, from `Cargo.toml`: + +- [`clippy::absolute_paths`][absolute_paths] -- allow, priority 4 +- `clippy::all` -- deny, priority -1 +- [`clippy::allow_attributes`][allow_attributes] -- deny, priority 4 +- [`clippy::allow_attributes_without_reason`][allow_attributes_without] -- allow, priority 4 +- [`clippy::arbitrary_source_item_ordering`][arbitrary_source_item] -- allow, priority 4 +- [`clippy::as_conversions`][as_conversions] -- deny +- [`clippy::blanket_clippy_restriction_lints`][blanket_clippy_restriction] -- allow, priority 8 +- [`clippy::cast_lossless`][cast_lossless] -- deny +- [`clippy::cast_possible_wrap`][cast_possible_wrap] -- deny +- [`clippy::clone_on_ref_ptr`][clone_on_ref_ptr] -- deny, priority 4 +- `clippy::complexity` -- deny, priority -1 +- `clippy::correctness` -- deny, priority -1 +- [`clippy::future_not_send`][future_not_send] -- deny, priority 4 +- [`clippy::impl_trait_in_params`][impl_trait_in_params] -- deny, priority 4 +- [`clippy::implicit_return`][implicit_return] -- allow, priority 8, opposite of `clippy::needless_return` +- [`clippy::infinite_loop`][infinite_loop] -- deny +- [`clippy::integer_division_remainder_used`][integer_division_remainder] -- deny, priority 8 +- [`clippy::let_underscore_must_use`][let_underscore_must_use] -- deny, priority 4 +- [`clippy::let_underscore_untyped`][let_underscore_untyped] -- deny, priority 4 +- [`clippy::lint_groups_priority`][lint_groups_priority] -- allow, priority 8 +- [`clippy::min_ident_chars`][min_ident_chars] -- deny, priority 4 +- [`clippy::missing_docs_in_private_items`][missing_docs_in_private_items] -- allow, priority 2 +- [`clippy::missing_errors_doc`][missing_errors_doc] -- allow, priority 4 +- [`clippy::missing_inline_in_public_items`][missing_inline_in_public] -- allow, priority 4 +- [`clippy::missing_panics_doc`][missing_panics_doc] -- allow, priority 4 +- [`clippy::missing_trait_methods`][missing_trait_methods] -- allow, priority 4 +- [`clippy::mod_module_files`][mod_module_files] -- allow, priority 4, opposite of `clippy::self_named_module_files` +- [`clippy::module_name_repetitions`][module_name_repetitions] -- allow, priority 4 +- `clippy::nursery` -- deny, priority -1 +- [`clippy::pattern_type_mismatch`][pattern_type_mismatch] -- allow, priority 4 +- `clippy::pedantic` -- deny, priority -1 +- `clippy::perf` -- deny, priority -1 +- [`clippy::pub_use`][pub_use] -- allow, priority 4 +- [`clippy::pub_with_shorthand`][pub_with_shorthand] -- allow, priority 4, opposite of `clippy::pub_without_shorthand` +- [`clippy::pub_without_shorthand`][pub_without_shorthand] -- deny, priority 4 +- [`clippy::question_mark_used`][question_mark_used] -- allow, priority 8 +- [`clippy::redundant_pub_crate`][redundant_pub_crate] -- allow, priority 4 +- [`clippy::rest_pattern_accessible_field`][rest_pattern_accessible_field] -- allow, priority 4, opposite of + `clippy::unneeded_field_pattern` +- `clippy::restriction` -- deny, priority -1 +- [`clippy::self_named_module_files`][self_named_module_files] -- deny, priority 4 +- [`clippy::semicolon_if_nothing_returned`][semicolon_if_nothing_returned] -- deny, priority 4 +- [`clippy::semicolon_outside_block`][semicolon_outside_block] -- allow, priority 4, opposite of + `clippy::semicolon_inside_block` +- [`clippy::separated_literal_suffix`][separated_literal_suffix] -- allow, priority 4, opposite of + `clippy::unseparated_literal_suffix` +- [`clippy::shadow_reuse`][shadow_reuse] -- allow, priority 4 +- [`clippy::shadow_same`][shadow_same] -- allow, priority 4 +- [`clippy::shadow_unrelated`][shadow_unrelated] -- allow, priority 4 +- [`clippy::single_call_fn`][single_call_fn] -- deny, priority 4 +- [`clippy::std_instead_of_alloc`][std_instead_of_alloc] -- allow, priority 8 +- [`clippy::std_instead_of_core`][std_instead_of_core] -- allow, priority 8 +- [`clippy::str_to_string`][str_to_string] -- allow, priority 4 +- [`clippy::struct_excessive_bools`][struct_excessive_bools] -- allow, priority 8 +- `clippy::style` -- deny, priority -1 +- `clippy::suspicious` -- deny, priority -1 +- [`clippy::too_many_arguments`][too_many_arguments] -- deny, priority 2 +- [`clippy::type_complexity`][type_complexity] -- deny, priority 4 +- [`clippy::unseparated_literal_suffix`][unseparated_literal_suffix] -- allow, priority 4 +- [`clippy::unused_async`][unused_async] -- deny, priority 2 +- [`dead_code`][dead_code] -- deny +- [`let_underscore`][let_underscore] -- deny, priority -1 +- [`macro_use_extern_crate`][macro_use_extern_crate] -- deny +- [`non_ascii_idents`][non_ascii_idents] -- deny +- [`private_bounds`][private_bounds] -- allow +- [`private_interfaces`][private_interfaces] -- allow +- [`redundant_imports`][redundant_imports] -- deny +- [`redundant_lifetimes`][redundant_lifetimes] -- deny +- [`rustdoc::private_intra_doc_links`][private_intra_doc_links] -- deny, priority 8 +- [`trivial_numeric_casts`][trivial_numeric_casts] -- deny +- [`unfulfilled_lint_expectations`][unfulfilled_lint] -- deny +- [`unnameable_types`][unnameable_types] -- allow +- [`unsafe_attr_outside_unsafe`][unsafe_attr_outside] -- deny +- [`unsafe_code`][unsafe_code] -- deny +- [`unsafe_op_in_unsafe_fn`][unsafe_op_in_unsafe_fn] -- deny +- [`unused`][unused] -- deny, priority -1 +- [`unused_results`][unused_results] -- deny + +[absolute_paths]: https://rust-lang.github.io/rust-clippy/stable/index.html#absolute_paths +[allow_attributes]: https://rust-lang.github.io/rust-clippy/stable/index.html#allow_attributes +[allow_attributes_without]: https://rust-lang.github.io/rust-clippy/stable/index.html#allow_attributes_without_reason +[arbitrary_source_item]: https://rust-lang.github.io/rust-clippy/stable/index.html#arbitrary_source_item_ordering +[as_conversions]: https://rust-lang.github.io/rust-clippy/stable/index.html#as_conversions +[blanket_clippy_restriction]: https://rust-lang.github.io/rust-clippy/stable/index.html#blanket_clippy_restriction_lints +[cast_lossless]: https://rust-lang.github.io/rust-clippy/stable/index.html#cast_lossless +[cast_possible_wrap]: https://rust-lang.github.io/rust-clippy/stable/index.html#cast_possible_wrap +[clone_on_ref_ptr]: https://rust-lang.github.io/rust-clippy/stable/index.html#clone_on_ref_ptr +[future_not_send]: https://rust-lang.github.io/rust-clippy/stable/index.html#future_not_send +[impl_trait_in_params]: https://rust-lang.github.io/rust-clippy/stable/index.html#impl_trait_in_params +[implicit_return]: https://rust-lang.github.io/rust-clippy/stable/index.html#implicit_return +[infinite_loop]: https://rust-lang.github.io/rust-clippy/stable/index.html#infinite_loop +[integer_division_remainder]: https://rust-lang.github.io/rust-clippy/stable/index.html#integer_division_remainder_used +[let_underscore_must_use]: https://rust-lang.github.io/rust-clippy/stable/index.html#let_underscore_must_use +[let_underscore_untyped]: https://rust-lang.github.io/rust-clippy/stable/index.html#let_underscore_untyped +[lint_groups_priority]: https://rust-lang.github.io/rust-clippy/stable/index.html#lint_groups_priority +[min_ident_chars]: https://rust-lang.github.io/rust-clippy/stable/index.html#min_ident_chars +[missing_docs_in_private_items]: https://rust-lang.github.io/rust-clippy/stable/index.html#missing_docs_in_private_items +[missing_errors_doc]: https://rust-lang.github.io/rust-clippy/stable/index.html#missing_errors_doc +[missing_inline_in_public]: https://rust-lang.github.io/rust-clippy/stable/index.html#missing_inline_in_public_items +[missing_panics_doc]: https://rust-lang.github.io/rust-clippy/stable/index.html#missing_panics_doc +[missing_trait_methods]: https://rust-lang.github.io/rust-clippy/stable/index.html#missing_trait_methods +[mod_module_files]: https://rust-lang.github.io/rust-clippy/stable/index.html#mod_module_files +[module_name_repetitions]: https://rust-lang.github.io/rust-clippy/stable/index.html#module_name_repetitions +[pattern_type_mismatch]: https://rust-lang.github.io/rust-clippy/stable/index.html#pattern_type_mismatch +[pub_use]: https://rust-lang.github.io/rust-clippy/stable/index.html#pub_use +[pub_with_shorthand]: https://rust-lang.github.io/rust-clippy/stable/index.html#pub_with_shorthand +[pub_without_shorthand]: https://rust-lang.github.io/rust-clippy/stable/index.html#pub_without_shorthand +[question_mark_used]: https://rust-lang.github.io/rust-clippy/stable/index.html#question_mark_used +[redundant_pub_crate]: https://rust-lang.github.io/rust-clippy/stable/index.html#redundant_pub_crate +[rest_pattern_accessible_field]: https://rust-lang.github.io/rust-clippy/stable/index.html#rest_pattern_accessible_field +[self_named_module_files]: https://rust-lang.github.io/rust-clippy/stable/index.html#self_named_module_files +[semicolon_if_nothing_returned]: https://rust-lang.github.io/rust-clippy/stable/index.html#semicolon_if_nothing_returned +[semicolon_outside_block]: https://rust-lang.github.io/rust-clippy/stable/index.html#semicolon_outside_block +[separated_literal_suffix]: https://rust-lang.github.io/rust-clippy/stable/index.html#separated_literal_suffix +[shadow_reuse]: https://rust-lang.github.io/rust-clippy/stable/index.html#shadow_reuse +[shadow_same]: https://rust-lang.github.io/rust-clippy/stable/index.html#shadow_same +[shadow_unrelated]: https://rust-lang.github.io/rust-clippy/stable/index.html#shadow_unrelated +[single_call_fn]: https://rust-lang.github.io/rust-clippy/stable/index.html#single_call_fn +[std_instead_of_alloc]: https://rust-lang.github.io/rust-clippy/stable/index.html#std_instead_of_alloc +[std_instead_of_core]: https://rust-lang.github.io/rust-clippy/stable/index.html#std_instead_of_core +[str_to_string]: https://rust-lang.github.io/rust-clippy/stable/index.html#str_to_string +[struct_excessive_bools]: https://rust-lang.github.io/rust-clippy/stable/index.html#struct_excessive_bools +[too_many_arguments]: https://rust-lang.github.io/rust-clippy/stable/index.html#too_many_arguments +[type_complexity]: https://rust-lang.github.io/rust-clippy/stable/index.html#type_complexity +[unseparated_literal_suffix]: https://rust-lang.github.io/rust-clippy/stable/index.html#unseparated_literal_suffix +[unused_async]: https://rust-lang.github.io/rust-clippy/stable/index.html#unused_async +[dead_code]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#dead-code +[let_underscore]: https://doc.rust-lang.org/rustc/lints/groups.html +[macro_use_extern_crate]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#macro-use-extern-crate +[non_ascii_idents]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents +[private_bounds]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#private-bounds +[private_interfaces]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#private-interfaces +[redundant_imports]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#redundant-imports +[redundant_lifetimes]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#redundant-lifetimes +[private_intra_doc_links]: https://doc.rust-lang.org/rustdoc/lints.html#private_intra_doc_links +[trivial_numeric_casts]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#trivial-numeric-casts +[unfulfilled_lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unfulfilled-lint-expectations +[unnameable_types]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unnameable-types +[unsafe_attr_outside]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-attr-outside-unsafe +[unsafe_code]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-code +[unsafe_op_in_unsafe_fn]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn +[unused]: https://doc.rust-lang.org/rustc/lints/groups.html +[unused_results]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unused-results + +## `cargo deny` + +- `cargo-deny-check` (`default` env; not run by `mise run check`) -- Audit dependencies with cargo-deny (advisories, + bans, licenses, sources). Config: `config/deny.toml`. + +## `cargo doc` + +- `cargo-doc-check` (`default` env; run by `check:rust`) -- Type-check rustdoc with -D warnings to fail on any doc + issues. + +## `cargo fmt` + +- `cargo-fmt-check` (`default` env; run by `check:rust`). Config: `.rustfmt.toml`. + +## `cargo unmaintained` + +- `cargo-unmaintained-check` (`default` env; not run by `mise run check`) -- Flag dependencies whose upstream repo is + archived or unmaintained. + +## `clang-format` + +- `clang-format-check` (`zig` env; run by `check:zig`) -- Check C/C++ source formatting (clang-format). Config: + `config/clang-format.yaml`. + +## `clang-tidy` + +- `clang-tidy-check` (`zig` env; run by `check:zig`) -- Lint C/C++ sources (clang-tidy). Config: + `config/clang-tidy.yaml`. + +## `conftest` + +- `conftest-check-dockerfile` (`default` env; run by `conftest-check`) -- Cross-check Dockerfiles against mise [tools] + pins + heredoc body-first-line invariants. Config: `config/conftest/policy`. +- `conftest-check-generated-trees` (`default` env; run by `conftest-check`) -- Cross-check config/generated-trees.toml + against the linter configs it governs (conftest). Config: `config/ast-grep/rules`, `config/conftest/policy`, + `config/generated-trees.toml`, `config/jscpd.json`, `config/pyrefly.toml`, `config/semgrep`. +- `conftest-check-jscpd` (`default` env; run by `conftest-check`) -- Check the jscpd baseline has not grown (conftest). + Config: `config/conftest/policy`, `config/jscpd-baseline.json`. +- `conftest-check-policy-pairs` (`default` env; run by `conftest-check`) -- Check every conftest policy has a test file + beside it (conftest). Config: `config/conftest/policy`. +- `conftest-check-policy-tests` (`default` env; run by `conftest-check`) -- Run the Rego unit tests beside the conftest + policies (conftest verify). Config: `config/conftest/policy`. +- `conftest-check-toml` (`default` env; run by `conftest-check`) -- Run conftest OPA/Rego policies over the TOML + config + lock files. Config: `config/conftest/policy`, `config/deny.toml`, `config/upstream-cache/data.toml`. +- `conftest-check-yaml` (`default` env; run by `conftest-check`) -- Run conftest OPA/Rego policies over the GitHub + Actions workflow + action YAML. Config: `config/conftest/policy`. + +Rules, from `config/conftest/policy`: + +- `advisories` (`config/conftest/policy/advisories/advisories.rego`): + - Every advisory ignore must carry a `reason = "expires YYYY-MM-DD"` review date. + - Nanoseconds in a day, added to the parsed midnight so an entry survives the whole of its review date. +- `cargo` (`config/conftest/policy/cargo/cargo.rego`): + - The root Cargo.toml must not depend on a crate this repo has banned. + - Member crates: no path deps, no wildcard versions, no inline git deps. + - A member crate must not take a dependency at a wildcard version. + - A member crate must not take an inline git dependency. + - Member [dependencies]/[dev-dependencies] must inherit via workspace = true so pins stay in [workspace.dependencies]. + - A crate with a [lib] must disable the doctest harness and must not rename the lib. + - A member crate's [lib] must not rename the library away from the package name. + - Every member must inherit the workspace lint tables. + - Every member crate must be registered in the root [workspace].members. + - Shared [package] metadata must be inherited from [workspace.package] via `.workspace = true`. + - Crate names are namespaced: "edge-toolkit" or "et-" for normal crates, "int-" marking an internal one. + - `publish` is stated in every manifest rather than left to cargo's implicit default. + - The "int-" marker and publishability are the same fact, so the name and the flag must agree both ways. + - A crate without the int- marker must set publish = true. + - A path dependency's `version` must match the version its crate actually declares. + - A root workspace dependency must be pinned to major.minor, not a patch version, unless it is excepted. + - The exception map is a two-way contract. + - crates.io rejects an upload whose manifest carries no description, so every publishable crate has one. + - An empty `features = []` on a dependency is pointless noise -- drop it. + - A member crate's feature must not share its name with one of its dependencies. + - Dependency overrides ([patch]/[replace]) belong in the root manifest, not a member crate. +- `checksums` (`config/conftest/policy/checksums/checksums.rego`): + - Every `_asset` var in the mise configs must have an [asset] table in config/upstream-cache/data.toml. + - Every [asset] table in config/upstream-cache/data.toml must be referenced by a mise `_asset` var. + - Per-entry shape check on each asset table. + - Every recorded asset must name its `upstream` project URL. + - Every recorded asset must carry its `license` as an SPDX expression. + - Every recorded asset must carry a `sha256`, left empty only while bootstrapping. +- `wasm-bindgen-sync` (`config/conftest/policy/cross/wasm-bindgen-sync.rego`): + - The mise wasm-bindgen pin must match the wasm-bindgen version Cargo.lock resolves. +- `dockerfile` (`config/conftest/policy/dockerfile/dockerfile.rego`): + - A version a Dockerfile hard-codes must match the [tools] pin for the same tool. + - Every pipx:* tool in an in-scope config must be in Dockerfile.nanoserver's MISE_DISABLE_TOOLS. + - RUN heredocs must invoke `bash` and use a QUOTED delimiter (`RUN bash <<'EOF'`). Two-part rule. + - A RUN heredoc must quote its delimiter so bash, not the outer shell, does the expansion. + - A Dockerfile `apt-get install` must pass --no-install-recommends on the same line. + - A Dockerfile must use `apt-get`, never `apt`. + - A renamed or removed ARG would leave the comparison undefined, which reads as a pass; fail instead. + - [bootstrap.packages] must list every package the Dockerfile ARGs install. + - [bootstrap.packages] must not list a package the Dockerfile ARGs do not install. + - Dockerfile.nanoserver is exempt: it deliberately loads a subset, because pipx tools cannot run on Nano Server. + - Every other Dockerfile's COMMON_PACKAGES must be drawn from the root Dockerfile's list. + - A Dockerfile's MISE_VERSION must match .mise/config.toml's min_version. +- `dockerfile_heredoc` (`config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc.rego`): + - A RUN heredoc's first body line must be `set -euo pipefail`. +- `generated_trees` (`config/conftest/policy/generated_trees/generated_trees.rego`): + - Every config a generated tree requires must carry that tree's exclusion pattern. + - Reverse direction, matched on the tree prefix rather than on the exact pattern. + - A `required_in` entry that no [anchor] key covers would make the forward rule above vacuous. +- `gha` (`config/conftest/policy/gha/gha.rego`): + - Every workflow must set the default run shell so steps run in bash on every runner without a per-step `shell:`. + - Steps must not override the shell -- rely on the workflow default. + - Every workflow must declare MISE_ENV at the workflow level so the set of loaded language envs is visible at a + glance. + - The MISE_ENV VALUE must be the full guest-language set. + - `DOCKER_BUILDKIT=1` must not be set in the docker-windows workflow. + - The docker-windows workflow must not set DOCKER_BUILDKIT at job scope either. + - Nor at step scope. + - A workflow's trigger paths must cover every local action it uses, so an edit to one re-runs it. + - A workflow step's `apt-get install` must pass --no-install-recommends on the same line. + - A workflow step must use `apt-get`, never `apt`. + - Every actions/upload-artifact step must set with.if-no-files-found: error. + - Scalar lists: `matrix.: [a, b, c]`. + - `include:` entries, which is where the per-combination keys live. +- `gha_action` (`config/conftest/policy/gha_action/gha_action.rego`): + - Composite-action `run:` steps require an explicit `shell:`. + - Every actions/upload-artifact step must set with.if-no-files-found: error. +- `gha_combined` (`config/conftest/policy/gha_combined/gha_combined.rego`): + - Every workflow must trigger on pull_request so PR CI runs it when relevant code changes. + - Every workflow must support manual workflow_dispatch: re-running a failed/flaky run shouldn't need a no-op commit. + - When a workflow scopes its pull_request trigger by `paths`, the workflow's own YAML must be in that list. +- `gha_mise` (`config/conftest/policy/gha_mise/gha_mise.rego`): + - Every setup-dotnet `dotnet-version` must equal the mise `dotnet` pin. + - Any workflow string embedding a mise install path must track the matching [tools] pin. + - A workflow's env.MISE_ENV must match .mise/config.toml's ALL_LANGS. +- `gha_uses` (`config/conftest/policy/gha_uses/gha_uses.rego`): + - A step must not pass an input that the local action it calls does not declare. + - Matched with `contains` rather than `startswith`, since the root need not begin the string. +- `jscpd` (`config/conftest/policy/jscpd/jscpd.rego`): + - Module-scope sprintf templates, each on its own line so the source stays inside the line limit. + - declared_clones may sit at most max_slack above the baseline, so progress gets banked. +- `mise` (`config/conftest/policy/mise/mise.rego`): + - A task `run` must be a string, not an array. + - A multiline `run` must use `shell = "{{ vars.task_shell }}"`. + - Task descriptions must be single-line. + - `compgen` is a bash builtin that busybox-w32 ash (Nano Server's shell) does not provide. + - A task `run` must not embed version-like text (an `X.Y.Z` literal), comments included. + - A `cargo:` tool must not build from source unless allowlisted or os-scoped to a second-tier platform. + - `ubi:` is deprecated; the `http:` backend replaces it. + - An `http:` tool must not fetch from a forge URL; use the github: backend instead. + - No per-platform URL of an `http:` tool may point at a forge either. + - A tool must not be os-scoped unless allowlisted, since every tool must work on every OS. + - A mise install path that a config string embeds must name the version [tools] pins. + - python must be pinned to a full version triple (X.Y.Z), not a minor alias. + - Each OS's preinstall task must read its package lists from the Dockerfile ARGs. + - Every usage arg a task declares must be read by its run body. + - The uppercase spelling is a no-op everywhere except Windows, so it is rejected on sight. +- `mise_lock` (`config/conftest/policy/mise_lock/mise_lock.rego`): + - A tool locks a glibc Linux build without an allowlist entry. + - An allowlist entry names a tool that no longer locks a glibc build anywhere. +- `no_trailing_backslash` (`config/conftest/policy/no_trailing_backslash/no_trailing_backslash.rego`): + - Flag any string leaf containing `\` followed by `\n` (LF), reporting its path key in the message. +- `policy_pairing` (`config/conftest/policy/policy_pairing/policy_pairing.rego`): + - Every policy must have a test file beside it, or a reasoned untested_policy entry. + - The map is a two-way contract, the same way a lint suppression is. + - An entry naming a policy that is no longer there has outlived what it described. +- `pyproject` (`config/conftest/policy/pyproject/pyproject.rego`): + - A `path = ".."` uv source points at the parent directory, which isn't a package -- almost always a mistake. + - A pyproject's uv_build requirement must pin the uv version mise installs. + +## `cpplint` + +- `cpplint-check` (`zig` env; run by `check:zig`) -- Lint C/C++ sources for Google C++ style (cpplint). + +## `dart` + +- `dart-check` (`dart` env; run by `check:dart`). +- `dart-fmt-check` (`dart` env; run by `check:dart`). + +## `dotnet` + +- `dotnet-check` (`dotnet` env; run by `check:dotnet`) -- Check dotnet C# formatting. + +## `dprint` + +- `dprint-check` (`default` env; run by `check:rust`). Config: `.dprint.jsonc`, `config/dprint.jsonc`. + +## `editorconfig-checker` + +- `editorconfig-check` (`default` env; run by `check:rust`). Config: `.editorconfig`. + +## `et-int-gen` + +- `checks-md-check` (`default` env; run by `check:rust`) -- Fail if CHECKS.md is stale vs the mise task tables and rule + files (run `mise run gen:checks`). +- `gen-help-all` (`default` env; run by `check:rust`) -- Regenerate HELP.md for every clap-using utility under + utilities/. +- `gen-help-check` (`default` env; run by `check:rust`) -- Fail if any utility's checked-in HELP.md is stale vs the clap + tree (run `mise run gen-help-all`). + +## `et-repo-check` + +- `repo-check` (`default` env; run by `check:rust`) -- Repository-wide checks that need to read git itself (commit + hashes, ...). + +## `flawfinder` + +- `flawfinder-check` (`zig` env; run by `check:zig`) -- Scan C/C++ sources for risky C APIs (flawfinder security lint). + +## `gitleaks` + +- `gitleaks-check` (`default` env; run by `check:rust`) -- Scan the working tree for committed secrets with gitleaks. + Config: `config/gitleaks.toml`. + +## `gocloc` + +- `sloc-crosscheck` (`coverage` env; not run by `mise run check`) -- Re-count sloc's file lists with gocloc, an + independent implementation of cloc's rules. + +## `hadolint` + +- `hadolint-check` (`default` env; run by `check:rust`) -- Lint the Dockerfiles with hadolint. Config: + `config/hadolint.yaml`. + +## `jscpd` + +- `jscpd-check` (`default` env; run by `check:rust`) -- Detect copy/pasted code across every language (jscpd). Config: + `config/jscpd-baseline.json`, `config/jscpd.json`. + +## `kubeconform` + +- `kubeconform-check` (`default` env; run by `check:rust`) -- Validate the generated Kubernetes manifests against the + Kubernetes API schemas. + +## `ls-lint` + +- `ls-lint-check` (`default` env; run by `check:rust`) -- Lint file and directory naming conventions (ls-lint). Config: + `config/ls-lint.yaml`. + +## `lychee` + +- `link-check` (`default` env; run by `check:rust`) -- Check that URLs in prose, source and config files are reachable + (network). Config: `config/lychee.toml`. + +## `osv-scanner` + +- `osv-scanner-check` (`default` env; not run by `mise run check`). Config: `config/osv-scanner.toml`. + +## `oxfmt` + +- `oxfmt-check` (`js` env; run by `check:js`) -- Check JS/TS formatting (oxfmt). Config: `config/oxfmtrc.jsonc`. + +## `oxlint` + +- `oxlint-check` (`js` env; run by `check:js`) -- Lint JavaScript/TypeScript sources (oxlint). Config: + `config/oxlintrc.jsonc`, `config/tsconfig.json`. + +## `pyrefly` + +- `pyrefly-check` (`python` env; run by `check:python`). Config: `config/pyrefly.toml`. + +## `regal` + +- `regal-check` (`default` env; run by `check:rust`) -- Lint Rego policy files with Regal (style, idiomatic, bugs). + Config: `config/conftest/policy`, `config/regal.yaml`. + +## `roslynator` + +- `roslynator-check` (`dotnet` env; run by `check:dotnet`) -- Analyze C# sources (Roslynator). + +## `ruff` + +- `ruff-check` (`python` env; run by `check:python`). Config: `ruff.toml`. +- `ruff-fmt-check` (`python` env; run by `check:python`). Config: `ruff.toml`. + +## `ryl` + +- `ryl-check` (`default` env; run by `check:rust`) -- Lint YAML with ryl (a yamllint-compatible Rust linter). Config: + `config/ryl.yaml`. + +## `semgrep` + +- `semgrep-check` (`default` env; run by `check:rust`) -- Run Semgrep generic-mode rules (e.g. Cargo.toml style). + Config: `.semgrepignore`, `config/semgrep`. + +Rules, from `config/semgrep`: + +- `anyhow-only-in-error-rs` -- `anyhow` may only be named in an `error.rs`, in a `#[from]` variant of the crate's error + enum. Domain code returns that enum and relies on `?`, so an `anyhow::Error` never reaches a public signature or a + match arm. If a foreign API hands you one here, add the `#[from]` variant to this crate's `error.rs` and let `?` do + the conversion. +- `bare-workspace-inline-dep` -- Use the dotted form `dep.workspace = true` instead of the inline table `dep = { + workspace = true }`. (Inline tables with extra keys, e.g. `dep = { workspace = true, features = [...] }`, are fine.) +- `comment-summary-line` -- A multi-line `#` comment block must open with a single summary line ending in a full stop + (PEP 257 style). The summary describes the whole block in one sentence; continuation lines follow. End the first + comment line with a `.`. +- `comment-summary-line-c` -- A multi-line C-style comment (a `/* */` block or a `//` run) must open with a single + summary line ending in a full stop (PEP 257 style). The summary describes the whole block in one sentence; + continuation lines follow. End the first comment line with a `.`. +- `deepsource-code-must-name-its-analyzer` -- Write a DeepSource finding as `DeepSource RS-W1079`, naming the analyzer + in front of the code. A bare code is unreadable to anyone who does not already know whose it is: `RS-`, `JS-` and + `CXX-` look like they could belong to any of the analyzers this repo runs, and a search for one turns up nothing + unless the searcher guesses the vendor first. The exception is a `skipcq:` pragma, whose grammar DeepSource defines -- + leave the code bare there, and let the surrounding comment carry the reason. +- `dockerfile-heredoc-set-euo-pipefail` -- Dockerfile RUN heredocs must begin with `set -euo pipefail` as the first body + line. BuildKit's default heredoc shell carries neither -e nor -o pipefail (and dash on Debian/Ubuntu doesn't support + -o pipefail at all), so the strict-mode invariant has to be re-declared per body. Paired with the policy that requires + `RUN <`. A bare `mkdir`/`cp`/`rm`/... runs whatever the host ships -- BSD on macOS, GNU on Linux, busybox + or Git Bash on Windows -- so flags and behaviour differ per machine, and the task depends on a tool mise does not pin. + A command that is run by another shell (inside a container or pod) is a genuine exception: suppress it on that line + with a `nosemgrep` comment saying where it runs. +- `module-description-length` -- A ws-module description is the module-dropdown label on the ws-server index page; keep + it at most 40 characters so the dropdown stays readable. +- `multiline-literal-string-needs-backslash` -- Write a multi-line string without a backslash as `"""..."""`, not + `'''...'''`. A TOML literal string exists to keep backslashes verbatim (Windows paths, regex escapes); without one it + only makes this value differ from the `"""` bodies around it, and the next reader looks for an escape that is not + there. +- `multiline-string-closes-on-own-line` -- Close a multi-line `"""` (or `'''`) string with the delimiter alone on its + own line, not on the end of its last line. Every multi-line value then ends the same way and appending a line never + means editing the one before it. In a Tera value, end the last tag with `-%}` (e.g. `{%- endif -%}`) so the newline + before the delimiter is trimmed and the rendered value is unchanged. +- `multiline-task-run-needs-bash-shell` -- A mise task with a multiline `run` must be immediately followed by `shell = + "{{ vars.task_shell }}"`. Put `shell` on the line right after the closing `"""`/`'''`, so a failing command fails the + task instead of being masked. `task_shell_trace` is also accepted (xtrace, used on the Windows OS-specific preinstall + for failure-diagnosis transcripts); `task_shell_plain` is not, since it carries no `-e`. bash is installed before any + task on Windows (see preinstall), so even the setup tasks can use it. +- `no-action-validator-mentions` -- Do not name the workflow schema validator outside the files that install and run it. + Whether a workflow key is spelled a certain way to keep a validator happy is not what a reader of that workflow needs; + say what the key does. +- `no-actionlint-mentions` -- Do not name the GitHub Actions linter outside the files that install and run it. A + workflow comment crediting it for a shell quoting or expression change says nothing a reader of the workflow can use. +- `no-ast-grep-mentions` -- Do not name the structural search tool outside its own ruleset and the configs that scope + it. Pointing at one of its rules from the code that rule governs duplicates the rule's own message, which is where the + explanation belongs and where it stays correct. +- `no-build-task-name-mentions` -- Do not name a module build task outside the images, jobs and READMEs that run it. A + skip message telling a developer which build to run is the exception, and the reason it works is that it is addressed + to someone at a terminal; a comment in the module's own source is not. +- `no-cargo-deny-mentions` -- Do not name the dependency auditor outside its config and the job that runs it. A + dependency is chosen or avoided for a licensing or advisory reason, which stands on its own; the auditor that would + have noticed is not part of it. +- `no-cargo-unmaintained-mentions` -- Do not name the unmaintained-crate scanner outside its ignore list and the job + that runs it. Its ignore entries need the tool's own heuristics explained; nothing else in the tree does. +- `no-cat-heredoc` -- Writing a file by piping a heredoc through `cat` is banned in this repo. A program embedded that + way is invisible to every checker: it is a string as far as the surrounding file is concerned, so nothing lints it, + formats it, or reports it in a diff as the language it is written in, and the quoting rules of two layers have to be + satisfied before its first byte reaches the interpreter. Put the content in its own file beside whatever runs it -- + `.mise/` for a mise task body -- named with the extension of whatever reads it (`.awk`, `.jq`, `.sh`), and point the + tool at that path instead. It then reads as the program it is, and a path is all the caller needs. +- `no-check-task-name-mentions` -- Do not name a check or formatter task outside its own config, the images and jobs + that run it, and the docs that say when to. Saying code is written a certain way because one of these would object + describes the check rather than the code, and it is the first thing to rot: the task gets renamed, folded into an + aggregate, or its rule moves, and the comment keeps asserting the old arrangement. State the constraint. +- `no-clang-format-mentions` -- Do not name the C formatter outside its own config. Formatted code carries no evidence + of who formatted it, and a comment claiming a brace or a blank line is the formatter's doing is unverifiable noise. +- `no-clang-tidy-mentions` -- Do not name the C static analyzer outside its config. Its suppression marker is a bare `// + NOLINT` naming the check, which is all a reader needs -- spelling out the analyzer beside it adds nothing and dates + the comment to whichever analyzer happened to run that week. +- `no-cmd-scripts` -- A `.cmd` file is banned everywhere in this tree, with no exemption at all -- not in `.mise/`, and + not under a `.venv/` the way its sibling extensions are. The reasoning is the same one that bans `.bat` and `.ps1`: a + Windows-only shell file is exercised on one of five platforms and silently untested on the other four. It gets no + carve-out because nothing generates one -- a virtualenv writes `activate.bat` and `activate.ps1` but never a `.cmd` -- + so every `.cmd` in the tree is something a person wrote by hand, and belongs in a task body under `.mise/` or its own + directory under `utilities/` instead. +- `no-codacy-mentions` -- Do not name this analyzer outside its own config and the few files it excludes by path, where + the header is the exclusion's canonical home. It runs after a push, so a source comment about it describes something + the reader cannot see, run, or check; state the property the code actually has. +- `no-codecov-mentions` -- Do not name the coverage service outside the jobs that upload to it. A test exists to pin + behaviour, and saying it was added for a coverage percentage tells the next reader to delete it once the number moves. +- `no-comment-in-dev-dependencies` -- Do not comment entries in a `[dev-dependencies]` section. What a test dependency + is for belongs in the test that uses it, where the reader is already looking; a note here duplicates that and goes + stale the moment the test changes. Delete the comment, and put anything genuinely worth saying next to the code that + depends on it. +- `no-conftest-mentions` -- Do not name the policy runner outside its own policy tree and the tasks that feed it. A + config entry is shaped by what the config has to express; a note that some policy would otherwise object belongs in + that policy's own deny message, where it is shown to the person who trips it. +- `no-coverage-task-name-mentions` -- Do not name a coverage task outside the pipeline that runs it. Where one is a + genuine precondition -- it starts the server a test needs, or it is the trusted caller that makes an argv-derived path + safe -- the name is the precondition and belongs there. A test's own assertions never are. +- `no-cpplint-mentions` -- Do not name the C++ style checker outside the configs that run it or defer to it. Its + suppression marker carries the rule name already, and nothing else in a C file is the checker's business. +- `no-curl-pipe` -- Piping `curl` into another command is banned in this repo. `curl ... | sh` executes an unreviewed + remote script outright: whoever controls the URL, or anyone able to substitute the response, chooses what runs, and a + truncated download is indistinguishable from a good one. Download to a file first, verify it with a pinned `sha256sum + -c` or a signature, and only then use it. `| tar` is banned too, and is not the safe exception it looks like: `tar + --to-command=` runs every archive member through that command, and `-I` / `--use-compress-program` likewise hand + an arbitrary program the stream, so a piped archive can execute code just as a piped script can. Fetch, verify, then + extract. +- `no-deepsource-mentions` -- Do not name this analyzer outside its own config, the pragmas it reads, and a reference to + one of its codes. Naming it in front of a code -- `DeepSource RS-W1079` -- is required, because the code alone does + not say whose it is. Naming it anywhere else describes the tool's reaction rather than the code. +- `no-dprint-mentions` -- Do not name the markdown/YAML/JSON formatter outside its config and the configs held to agree + with it. Where a generator has to emit already-formatted output, say which shape the output must have; naming the + formatter dates the comment to a config the generator never reads. +- `no-editorconfig-check-mentions` -- Do not name the editorconfig checker outside the task that runs it. Write "the + editorconfig line length" when a comment genuinely has to mention the limit -- that names the constraint and its + source, which is what a reader can act on. +- `no-flawfinder-mentions` -- Do not name the C/C++ security scanner except in the `flawfinder: ignore` pragma, which + only works spelled out on the line it covers. Its justification belongs on that same line and says why the call is + safe. +- `no-generator-task-name-mentions` -- Do not name a generator task outside the generator, the files it writes, and the + docs that say when to run it. A generated file's own header is where the name belongs, because a reader who must not + hand-edit the file needs the command that rebuilds it. Elsewhere, "the drift check fails" says everything the reader + can act on, and survives the task being renamed or folded into an aggregate. +- `no-gitleaks-mentions` -- Do not name the secret scanner outside its config and the `gitleaks:allow` marker it reads. + A credential is kept out of a tracked file because it is a credential, not because a scanner would find it. +- `no-hadolint-mentions` -- Do not name the Dockerfile linter outside its config, its `hadolint ignore=` pragmas, and + the code that emits them. Say what the instruction does and why it is written that way; a pragma already carries the + code it suppresses. +- `no-jscpd-mentions` -- Do not name the duplication checker outside its config, its baseline, and the policy that + ratchets them. A reported clone is a request to remove duplication: factor the shared part out so it exists once. + Where a clone is genuinely irreducible -- the same few lines every caller must write verbatim -- leave the code plain + and raise it, rather than annotating the source with the tool's name. +- `no-kubeconform-mentions` -- Do not name the manifest schema validator outside the job that runs it. A manifest field + is set because Kubernetes requires or honours it, which is what the comment beside it should say. +- `no-line-length-in-comment` -- Do not hardcode the line-length number in a comment. Say "editorconfig line length" + when the comment genuinely needs the constraint, otherwise drop the mention entirely -- the number drifts and adds + noise. +- `no-ls-lint-mentions` -- Do not name the file-naming linter outside its config and the rule that governs it. A file or + directory is named for what it holds; the checker that would object to another name is not part of that. +- `no-lychee-mentions` -- Do not name the link checker outside its config and the task that runs it. A link is written + to point somewhere useful, and a note that the checker accepts or skips it will outlive the reason it did. +- `no-maintainer-task-name-mentions` -- Do not name an install, prefetch or asset-publishing task outside the jobs, + images and asset tables that invoke it. These run on a maintainer's machine or a runner, never from the code, so a + source file naming one is describing an operation it has no part in. +- `no-nextest-mentions` -- Do not name the test runner outside its config and the jobs that invoke it. A test asserts + what the code must do, and how it happens to be scheduled is the runner's business rather than the test's -- unless + the schedule is load-bearing, which is a constraint worth stating and worth allowlisting for. +- `no-non-ascii` -- Non-ASCII character. Keep source, config, and docs ASCII-only: use `--` for an em-dash, `->` for an + arrow, `...` for an ellipsis, `<=`/`!=`/`^2` for math glyphs, and straight quotes for curly quotes. ASCII keeps + terminals, log scrapers, and `grep` reading the same bytes the editor shows. Generated trees (generated/, + verification/, HELP.md) are exempt because their generator owns the output. +- `no-observability-task-name-mentions` -- Do not name an observability task outside the configs it loads and the things + that launch it. A collector config naming the task that reads it is how a reader finds its way in; a comment elsewhere + saying some value exists for one of these tasks is not. +- `no-osv-scanner-mentions` -- Do not name the vulnerability scanner outside its config, the job that runs it, and the + ignore lists that have to say which scanner honours which id. Everywhere else, describe the dependency, not the scan. +- `no-oxfmt-mentions` -- Do not name the JS formatter outside its config and the config held to agree with it. When a + statement has to be split to keep both formatters happy, the fix is in the source -- a shorter line, an extracted + local -- and the split stands on its own without a comment naming either tool. +- `no-oxlint-mentions` -- Do not name the JS linter outside its config. A `skipcq` or eslint-style disable comment + already carries the rule it silences plus the reason it is safe; adding the linter's name tells the reader nothing + more. +- `no-pyrefly-mentions` -- Do not name the Python type checker outside its config and the rules that protect what it can + see. An annotation states the type the code requires; that it also satisfies a checker follows, and need not be + written down. +- `no-python-outside-modules` -- Python outside the module trees is banned. It is a guest language in this repo, not a + tooling language: it is here so that a module can be written in it and run in a browser or a runner, and every such + file sits under `services/ws-modules/` beside the manifest that builds and packages it. A `.py` anywhere else is a + loose script by another name, carrying every problem one brings -- nothing invokes it, nothing tests it, and nothing + fails when it stops working. Short and simple belongs in a task body under `.mise/`; anything more involved gets its + own directory under `utilities/` with a `README.md`. +- `no-regal-mentions` -- Do not name the Rego linter outside its own config. A policy is written the way Rego reads + best; if one of its idioms is deliberate, say what the idiom does rather than which linter asked for it. +- `no-roslynator-mentions` -- Do not name the C# analyzer outside the tasks and images that install it. A `#pragma + warning disable` already names the diagnostic, which is the part a reader can look up. +- `no-ruff-mentions` -- Do not name the Python linter/formatter outside its config and the configs that defer to it. A + `# noqa` carries the code it silences and should carry the reason too; the tool that issued the code does not need + naming beside it. +- `no-ryl-mentions` -- Do not name the YAML linter outside its own config. YAML is written to be read; where its shape + is forced, say what forces it, which is almost always the schema the file answers to rather than a linter. +- `no-scripts-dir` -- A `scripts/` directory is banned in this repo. Every script belongs in one of exactly two places, + and neither of them is a loose tree of files that nothing points at. Short and simple goes inline in a task body under + `.mise/`, where it is listed alongside every other entry point and runs by name. Anything more involved gets its own + directory under `utilities/`, with a `README.md` saying what it does and how to run it. A file under `scripts/` has + neither: no caller, no documentation, and nothing that fails when it stops working. Move it to whichever of the two + fits, and drop the directory. +- `no-semgrep-mentions` -- Do not name this tool outside its own ruleset and the configs that scope it. A `nosemgrep` + marker is the one place the name belongs in source, and it needs the rule id and a reason beside it; anywhere else, + pointing at a rule duplicates the message that rule already shows whoever trips it. +- `no-shell-scripts` -- A `.sh` file outside `.mise/` is banned. Shell that is short and simple belongs inline in a task + body, where it is discoverable and runs by name; shell that has outgrown that is a program, and belongs in its own + directory under `utilities/`, written in a language with types, tests and a linter behind it. The one exception is + `.mise/`, where a task body too long to sit inside a TOML string is split into a file beside the config that invokes + it, named for the interpreter that reads it -- that file is formatted and linted as the shell it is, which a string + embedded in a config never can be. +- `no-shellcheck-mentions` -- Do not name the shell linter except in the `# shellcheck disable=` pragma, which only + works spelled out above the line it covers, and in the configs that run it. The pragma needs the code and the reason + the construct is deliberate; nothing else in the script does. +- `no-shfmt-mentions` -- Do not name the shell formatter outside the tasks that run it. Formatted shell carries no + evidence of who formatted it, so a comment claiming an indent is the formatter's doing cannot be checked. +- `no-split-url-in-comment` -- A URL is broken across two comment lines, which leaves a dead link. Rejoin it onto one + line, even if that line then runs past the usual width, and re-wrap the surrounding prose around it. A comment reflow + that split it cannot be told to keep a URL whole, so the repair is always by hand. +- `no-taplo-mentions` -- Do not name the TOML formatter and schema linter outside its config and schemas. Where a + generator has to emit TOML the formatter will accept unchanged, say which shape the output must have -- sorted arrays, + aligned comments -- rather than naming the tool that would otherwise rewrite it. +- `no-test-task-name-mentions` -- Do not name a test or server task outside the jobs and docs that run it. A test file + may name the task that supplies something it cannot create for itself -- a browser harness, a listening backend, a + port group -- because that is a precondition. Naming one to explain why an assertion exists is not. +- `no-todo` -- TODOs are not allowed in this repo. Either resolve the work now, or, if it must defer, add a single-line + justification in the surrounding code and add this file's path to no-todo.yaml's paths.exclude allowlist. Do not + duplicate a TODO across multiple files -- pick the single canonical home and let `grep TODO` find it there. +- `no-trailing-backslash` -- Trailing-backslash line continuations are not allowed in this repo. Keep it on one line, or + use a language-appropriate alternative (concat!(...) in Rust, a mise [vars] entry, a YAML/array form). If a file + genuinely needs them, add it to this rule's paths.exclude allowlist. +- `no-trivy-mentions` -- Do not name the container and manifest scanner outside its ignore file and the task that runs + it. Its ignore entries need its own resolution behaviour explained; nothing it scans does. +- `no-type-comments` -- Legacy `# type:` comment. Use an inline annotation (`x: T = ...`, `def f(a: T) -> R:`) instead. + The compiled Pyrefly type checker that backs `check:python` parses annotations but silently ignores legacy type + comments, so a broken one (an undefined name, a stray `--`) rots unseen -- exactly `DeepSource TYP-025`. Annotations + are the only form both tools check. `# type: ignore` (the suppression pragma) is exempt. +- `no-typos-check-mentions` -- Do not name the spelling checker's tasks outside the config that defines them. An + identifier spelled an unusual way is either correct or a typo; if it is correct, say what it means, and add it to the + checker's own allowlist rather than explaining it where it appears. +- `no-wget` -- Use `curl` instead of `wget` for downloads in this repo. Two download tools means two sets of flags, two + retry behaviours and two failure modes for one job, and the difference is easy to get wrong: `wget` writes a file by + default while `curl` writes to stdout unless told otherwise, so a command translated between them silently changes + what it produces. `curl` is also the one already installed -- it is in the Dockerfiles' COMMON_PACKAGES and present on + the CI runners, whereas `wget` is in none of the image package lists, so reaching for it adds an undeclared dependency + on whatever the host happens to ship. Note that piping a download into an interpreter stays banned whichever tool + fetches it. +- `no-windows-shell-scripts` -- A `.bat` or `.ps1` file is banned. Windows is a first-tier platform here, which is + precisely why its shell gets no scripts of its own: a task body runs the same way on all five supported platforms, so + logic written once is logic every lane exercises, whereas a batch or PowerShell file is reachable from one platform + and silently untested on the other four. That is how a Windows-only path rots unnoticed until it is the lane holding + up a merge. Write the logic once in a task body under `.mise/`, or in its own directory under `utilities/` when it has + outgrown one, and let every platform run the same thing. The `.venv/` exemption covers the activation scripts a + virtualenv generates for itself, which are the tool's output rather than anyone's source. +- `no-zizmor-mentions` -- Do not name the Actions security auditor except in the `zizmor: ignore[...]` pragma, which + only works spelled out, and in the configs that run it. A workflow step is written to be safe; say why it is, and let + the pragma carry the audit it waives. +- `prefer-yaml-extension` -- Use the .yaml extension, not .yml -- rename the file. +- `prefer-yaml-toml-over-json` -- Prefer YAML or TOML over JSON/JSONC/JSONL for config. If the tool requires a + JSON-family format, prefer .jsonc over .json so the config can carry inline comments, and add the file to this rule's + paths.exclude allowlist. +- `single-key-env-subtable-should-be-inline` -- `[tasks.X.env]` subtable has a single `KEY = "value"` assignment. Inline + it on the parent task as `env = { KEY = "value" }` when the resulting line fits the editorconfig line length -- + subtable form is reserved for multi-key envs. +- `single-line-description-in-mise-config` -- mise task `description` fields must be single-line `"..."` strings, not + multi-line `"""..."""`. Keep the description short enough to fit on one line. +- `sorted-lists` -- Keep this list in ASCII order of each item as written: the traits in a `#[derive(...)]` (`Clone, + Debug, Deserialize, Eq, PartialEq, Serialize`, a qualified `strum::EnumIter` after every bare name), the lints in an + `#[expect(...)]` before its `reason` (`clippy::` lints together, rustc lints after them), and adjacent `feature = + "..."` predicates in an `any(...)` / `all(...)`. A sorted list reads the same everywhere, makes a missing or + duplicated entry easy to spot, and keeps a diff to the one entry that changed. +- `task-shell-must-use-task-shell-var` -- Declare a task `shell` through one of the `task_shell` vars, never as a bare + `bash ...` command line. The vars run the body through a wrapper script instead of `-c`, which is what repairs the + mangled PATH mise hands a Windows task; a raw `bash ... -c` bypasses the wrapper and every tool goes missing on the + Windows lanes. Use `{{ vars.task_shell }}`, or `task_shell_trace` for xtrace, or `task_shell_plain` for a body that + checks its own exit codes. + +## `shellcheck` + +- `shellcheck-check` (`default` env; run by `check:rust`) -- shellcheck the standalone shell fragments committed under + .mise/. +- `shellcheck-mise-check` (`default` env; run by `check:rust`) -- shellcheck every bash-shell mise task body across + .mise/config*.toml. Config: `.mise/shellcheck-mise.jq`. + +## `taplo` + +- `taplo-check` (`default` env; run by `check:rust`). Config: `config/taplo.toml`, + `config/taplo/mise-cargo-backend-allowlist.schema.json`, `config/taplo/mise-no-ubi-backend.schema.json`, + `config/taplo/mise-run-not-array.schema.json`, `config/taplo/no-banned-deps.schema.json`, + `config/taplo/no-lib-name.schema.json`, `config/taplo/no-path-deps.schema.json`, + `config/taplo/no-wildcard-or-git-deps.schema.json`, `config/taplo/require-lib-doctest-false.schema.json`, + `config/taplo/require-lints-section.schema.json`, `config/taplo/require-workspace-deps.schema.json`. +- `taplo-fmt-check` (`default` env; run by `check:rust`). Config: `config/taplo.toml`. + +Rules, from `config/taplo`: + +- `mise-cargo-backend-allowlist` -- mise [tools] -- cargo backend allowlist: `cargo:` source build; tools with no + prebuilt + os-scoped fallbacks (findutils, ryl). +- `mise-no-ubi-backend` -- mise [tools] -- no ubi backend: The `ubi:` backend is deprecated; use `http:` instead. +- `mise-run-not-array` -- mise tasks -- `run` must be a string, not an array: `run` must be a string, not an array: + taplo reorder_arrays would re-sort the commands. +- `no-banned-deps` -- Cargo.toml -- banned deps: Crates this repo deliberately doesn't take on; const = rejection + message. +- `no-lib-name` -- Workspace member Cargo.toml -- [lib] must not override the crate name: The library name must default + from the package name; an explicit `[lib] name` rename is banned. +- `no-path-deps` -- Workspace member Cargo.toml -- no path dependencies: Forbids `path = ...` deps outside workspace + root; `const` is a hack so taplo prints it as the error. +- `no-wildcard-or-git-deps` -- Workspace member Cargo.toml -- no wildcard or git deps: Forbids `*` and inline `git = + ...` in [dependencies] / [dev-dependencies] / [build-dependencies]. +- `require-lib-doctest-false` -- Workspace member Cargo.toml -- [lib] must set doctest = false: Pairs with the ban on + fenced blocks in doc comments; runnable examples go in tests/. +- `require-lints-section` -- Workspace member Cargo.toml -- must inherit workspace lints: Member crates must include + `[lints] workspace = true` to inherit workspace lints. +- `require-workspace-deps` -- Workspace member Cargo.toml -- deps must inherit: [dependencies] / [dev-dependencies] / + [build-dependencies] entries must use `.workspace = true`. + +## `trivy` + +- `trivy-check` (`default` env; run by `check:rust`) -- Check every Dockerfile and generated Kubernetes manifest for + hardening findings. Config: `config/trivyignore.yaml`. + +## `typos` + +- `typos-check` (`default` env; run by `check:rust`). Config: `config/typos.toml`. + +## `xcrun` + +- `macos-sdk-check` (`default` env; not run by `mise run check`) -- Fail if the macOS SDK is missing or older than the + minimum this repo builds against. + +## `zig` + +- `zig-check` (`zig` env; run by `check:zig`). + +## `zizmor` + +- `zizmor-check` (`default` env; run by `check:rust`) -- Audit GitHub Actions workflows + composite actions for security + issues (zizmor). Config: `config/zizmor.yaml`. + +## Shell-script checks + +- `action-validator-check` (`windows` env; run by `check:rust`). +- `agent-lint-check` (`windows` env; run by `check:rust`). +- `branch-up-to-date-check` (`default` env; run by `check:rust`) -- Fail if the current branch does not already contain + origin/main (rebase needed). +- `check-ghcr-visibility` (`maint` env; not run by `mise run check`) -- Verify every GHCR package is public; print + settings URLs for any still private. +- `dockerignore-check` (`default` env; run by `check:rust`) -- Fail if .dockerignore is stale vs .gitignore (run `mise + run gen:dockerignore`). +- `gen-specs-check` (`default` env; run by `check:rust`) -- Fail if any checked-in et-int-gen artifact is stale. +- `mise-lock-check` (`default` env; run by `check:rust`) -- Fail if .mise/mise*.lock records a different tool set or + version than a full install resolves. +- `readme-mise-version-check` (`default` env; run by `check:rust`) -- Fail if README.md's mise version differs from + min_version in .mise/config.toml. +- `verification-check` (`default` env; run by `check:rust`) -- Fail if generated scenario output files are stale. diff --git a/Cargo.lock b/Cargo.lock index 48fd2d98..5b907d71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4311,7 +4311,6 @@ name = "et-cli" version = "0.1.1" dependencies = [ "clap", - "clap-markdown", "command-error", "edge-toolkit", "et-org", @@ -4344,7 +4343,9 @@ dependencies = [ "clap-markdown", "command-error", "edge-toolkit", + "et-cli", "et-modules-service", + "et-onnx", "et-storage-service", "et-test-helpers", "et-ws-server", @@ -4364,7 +4365,9 @@ dependencies = [ "serde_json", "serde_yaml", "syn 3.0.5", + "tempfile", "thiserror 2.0.20", + "toml 1.1.6+spec-1.1.0", "tree-sitter", "tree-sitter-zig", "utoipa", @@ -4396,7 +4399,6 @@ name = "et-onnx" version = "0.1.0" dependencies = [ "clap", - "clap-markdown", "onnx-extractor", ] diff --git a/Cargo.toml b/Cargo.toml index 060e92be..48ebe5fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,7 +88,9 @@ deno_resolver = "0.85" # baking our own startup snapshot we'd otherwise hit the panic on first run. deno_runtime = { version = "0.262", features = ["transpile", "hmr"] } edge-toolkit = { path = "libs/edge-toolkit", version = "0.3.1" } +et-cli = { path = "utilities/cli", version = "0.1.1" } et-modules-service = { path = "services/modules", version = "0.2.0" } +et-onnx = { path = "utilities/onnx", version = "0.1.0" } et-org = { path = "libs/org", version = "0.1.0" } et-otlp = { path = "libs/et-otlp", version = "0.2.0" } et-path = { path = "libs/path", version = "0.2.0" } @@ -311,6 +313,7 @@ private_intra_doc_links = { level = "deny", priority = 8 } all = { level = "deny", priority = -1 } complexity = { level = "deny", priority = -1 } correctness = { level = "deny", priority = -1 } +# Opposite of clippy::needless_return. implicit_return = { level = "allow", priority = 8 } nursery = { level = "deny", priority = -1 } pedantic = { level = "deny", priority = -1 } @@ -337,9 +340,11 @@ semicolon_if_nothing_returned = { level = "deny", priority = 4 } shadow_reuse = { level = "allow", priority = 4 } shadow_same = { level = "allow", priority = 4 } shadow_unrelated = { level = "allow", priority = 4 } +# Opposite of clippy::semicolon_inside_block. # Block-scoped statements like `{ *guard = ...; }` use the closing brace to drop borrows. # Moving the `;` outside risks extending MutexGuard lifetimes past the intended scope. semicolon_outside_block = { level = "allow", priority = 4 } +# Opposite of clippy::unseparated_literal_suffix. # Allowing separated_literal_suffix & unseparated_literal_suffix is an explicit style choice. separated_literal_suffix = { level = "allow", priority = 4 } unseparated_literal_suffix = { level = "allow", priority = 4 } @@ -348,6 +353,10 @@ absolute_paths = { level = "allow", priority = 4 } # Allowing pub_use is an explicit style choice to streamline coding. impl_trait_in_params = { level = "deny", priority = 4 } pub_use = { level = "allow", priority = 4 } +# Opposite of clippy::unneeded_field_pattern. +# Allowing rest_pattern_accessible_field is an explicit style choice: a struct pattern skips fields with `..`. +rest_pattern_accessible_field = { level = "allow", priority = 4 } +# Opposite of clippy::self_named_module_files. # Allowing module_name_repetitions & mod_module_files are an explicit code layout choice. mod_module_files = { level = "allow", priority = 4 } module_name_repetitions = { level = "allow", priority = 4 } @@ -372,6 +381,7 @@ infinite_loop = "deny" too_many_arguments = { level = "deny", priority = 2 } # Allowing missing_trait_methods to avoid forcing explicit implementation of default trait methods missing_trait_methods = { level = "allow", priority = 4 } +# Opposite of clippy::pub_without_shorthand. pub_with_shorthand = { level = "allow", priority = 4 } pub_without_shorthand = { level = "deny", priority = 4 } # clippy removing pub(crate) is quite confusing at times diff --git a/Dockerfile b/Dockerfile index 3e1de23f..d217ea90 100644 --- a/Dockerfile +++ b/Dockerfile @@ -179,7 +179,7 @@ EOF # SHASUMS256.txt covering every asset, so `--ignore-missing` verifies exactly the one archive downloaded here. # mise's own apt repository was the obvious alternative and was rejected: it publishes only the newest version, # so it cannot honour the pin, and a floating mise is what writes lockfile entries an older CI mise then refuses. -ARG MISE_VERSION=v2026.9.0 +ARG MISE_VERSION=v2026.9.17 # TARGETARCH is an automatic BuildKit build ARG; re-declaring it brings it into this stage. ARG TARGETARCH ENV MISE_VERSION=${MISE_VERSION} diff --git a/Dockerfile.nanoserver b/Dockerfile.nanoserver index 37acc6ba..6f2c9a94 100644 --- a/Dockerfile.nanoserver +++ b/Dockerfile.nanoserver @@ -22,7 +22,7 @@ # `build` are the CI frontier (see "Known unknowns" at the foot). # # Base: Nano Server (~120 MB vs Server Core's ~1.25 GB), kept on Nano per the -# CLAUDE.md non-negotiable. Same MSI/PowerShell-installer-avoidance posture as +# AGENTS.md non-negotiable. Same MSI/PowerShell-installer-avoidance posture as # any minimal Windows image -- nothing is installed the Windows way; mise (a # single .exe the workflow stages in the build context) is copied in, and # `mise install` pulls the rest. @@ -85,7 +85,7 @@ RUN curl -fsSL -o vc_redist.exe https://aka.ms/vs/17/release/vc_redist.x64.exe & # https://github.com/edge-toolkit/core/commit/1f544590b473887015754f67c3af843f970d8dbc # (https://github.com/edge-toolkit/core/actions/runs/31559765225/job/94252377147) # while the windows-2025 lane of that same run downloaded it fine. Per the -# CLAUDE.md fetch-resilience rule, the fix for a blocked upstream is to serve +# AGENTS.md fetch-resilience rule, the fix for a blocked upstream is to serve # the asset from a release we control, never a retry wrapper. # # SHA256 pin: a republish under the same URL fails the build instead of @@ -495,7 +495,7 @@ RUN (if exist C:\token\gh_token set /p GITHUB_TOKEN= Foo` only pairs with `impl Display for Foo`. +rule: + kind: impl_item + all: + - has: + field: trait + regex: . + - has: + field: type + pattern: $TY + precedes: + kind: impl_item + has: + field: type + pattern: $TY + not: + has: + field: trait + regex: . + stopBy: end +ignores: + - generated/** + # Generated; refer to int-gen bindings.rs for details. + - services/ws-wasi-runner/src/bindings.rs diff --git a/config/ast-grep/rules/write-ending-newline.yaml b/config/ast-grep/rules/write-ending-newline.yaml new file mode 100644 index 00000000..60a5f964 --- /dev/null +++ b/config/ast-grep/rules/write-ending-newline.yaml @@ -0,0 +1,20 @@ +id: write-ending-newline +language: Rust +severity: error +message: | + A `write!` whose format string ends in `\n` is a `writeln!` written the long way: use `writeln!` and drop the + final `\n`. This mirrors `DeepSource RS-C1005`. clippy's `write_with_newline` covers only a single trailing + newline and deliberately skips a string ending in `\n\n`, which is the case this rule exists to catch. +# There is no autofix. +# The rewrite renames the macro and edits the string literal inside its token tree at once, which a single `fix:` +# template over the whole invocation cannot express without re-spelling every argument. +rule: + kind: macro_invocation + has: + field: macro + regex: ^write$ + regex: '(?s)^write!\s*\((?:[^"()]|\([^()]*\))*,\s*"(?:[^"\\]|\\.)*\\n"' +ignores: + - generated/** + # Generated; refer to int-gen bindings.rs for details. + - services/ws-wasi-runner/src/bindings.rs diff --git a/config/conftest/policy/advisories/advisories.rego b/config/conftest/policy/advisories/advisories.rego index eb4b11c7..503d5acd 100644 --- a/config/conftest/policy/advisories/advisories.rego +++ b/config/conftest/policy/advisories/advisories.rego @@ -36,6 +36,7 @@ dated[id] := date if { id := entry.id } +# Every advisory ignore must carry a `reason = "expires YYYY-MM-DD"` review date. deny contains msg if { some entry in entries id := advisory_id(entry) @@ -48,7 +49,7 @@ day_ns := 86400000000000 deny contains msg if { some id, date in dated - midnight := time.parse_rfc3339_ns(concat("", [date, "T00:00:00Z"])) + midnight := time.parse_rfc3339_ns($"{date}T00:00:00Z") time.now_ns() >= midnight + day_ns msg := sprintf(lapsed_msg, [id, date]) } diff --git a/config/conftest/policy/advisories/advisories_test.rego b/config/conftest/policy/advisories/advisories_test.rego index 214cd80b..c8107439 100644 --- a/config/conftest/policy/advisories/advisories_test.rego +++ b/config/conftest/policy/advisories/advisories_test.rego @@ -16,7 +16,7 @@ day_ns := 86400000000000 deny_file(entries) := [{"path": "config/deny.toml", "contents": {"advisories": {"ignore": entries}}}] -dated(id, date) := {"id": id, "reason": sprintf("expires %s", [date])} +dated(id, date) := {"id": id, "reason": $"expires {date}"} names(msgs, fragment) if { some msg in msgs diff --git a/config/conftest/policy/cargo/cargo.rego b/config/conftest/policy/cargo/cargo.rego index 092ce025..c5111381 100644 --- a/config/conftest/policy/cargo/cargo.rego +++ b/config/conftest/policy/cargo/cargo.rego @@ -44,11 +44,12 @@ banned := { "ureq": "use reqwest::blocking or reqwest -- one HTTPS stack only", } +# The root Cargo.toml must not depend on a crate this repo has banned. deny contains msg if { some [path, name, _] in dep path == "Cargo.toml" reason := banned[name] - msg := sprintf("%s: banned dependency %q -- %s", [path, name, reason]) + msg := $"{path}: banned dependency \"{name}\" -- {reason}" } # Member crates: no path deps, no wildcard versions, no inline git deps. @@ -58,22 +59,24 @@ deny contains msg if { path != "Cargo.toml" is_object(spec) spec.path - msg := sprintf("%s: dependency %q uses a path dep; use workspace = true instead", [path, name]) + msg := $"{path}: dependency \"{name}\" uses a path dep; use workspace = true instead" } +# A member crate must not take a dependency at a wildcard version. deny contains msg if { some [path, name, spec] in dep path != "Cargo.toml" wildcard(spec) - msg := sprintf("%s: dependency %q uses a wildcard version; pin via [workspace.dependencies]", [path, name]) + msg := $"{path}: dependency \"{name}\" uses a wildcard version; pin via [workspace.dependencies]" } +# A member crate must not take an inline git dependency. deny contains msg if { some [path, name, spec] in dep path != "Cargo.toml" is_object(spec) spec.git - msg := sprintf("%s: dependency %q is an inline git dep; pin via [workspace.dependencies]", [path, name]) + msg := $"{path}: dependency \"{name}\" is an inline git dep; pin via [workspace.dependencies]" } wildcard(spec) if { @@ -107,6 +110,7 @@ deny contains msg if { msg := sprintf("%s: [lib] must set doctest = false", [file.path]) } +# A member crate's [lib] must not rename the library away from the package name. deny contains msg if { some file in input is_member(file) @@ -132,6 +136,7 @@ workspace_member contains m if { some m in file.contents.workspace.members } +# Every member crate must be registered in the root [workspace].members. deny contains msg if { some file in input is_member(file) @@ -190,6 +195,7 @@ deny contains msg if { msg := sprintf("%s: crate %q carries the int- marker, so it must set publish = false", [file.path, name]) } +# A crate without the int- marker must set publish = true. deny contains msg if { some file in input is_member(file) @@ -259,6 +265,7 @@ root_dep[name] := spec if { some name, spec in file.contents.workspace.dependencies } +# A root workspace dependency must be pinned to major.minor, not a patch version, unless it is excepted. deny contains msg if { some name, spec in root_dep not path_dep(spec) @@ -278,7 +285,7 @@ exception_is_live(name) if patch_pinned(requirement(root_dep[name])) deny contains msg if { some name, reason in patch_pin_exception not exception_is_live(name) - msg := sprintf("Cargo.toml: patch_pin_exception entry %q is stale (%s); remove it", [name, reason]) + msg := $"Cargo.toml: patch_pin_exception entry \"{name}\" is stale ({reason}); remove it" } # crates.io rejects an upload whose manifest carries no description, so every publishable crate has one. @@ -297,7 +304,7 @@ deny contains msg if { some [path, name, spec] in dep is_object(spec) spec.features == [] - msg := sprintf("%s: dependency %q has an empty features = []; remove it", [path, name]) + msg := $"{path}: dependency \"{name}\" has an empty features = []; remove it" } # A feature must not share its name with a dependency. @@ -308,6 +315,7 @@ is_dep_name(file, name) if { file.contents[table][name] } +# A member crate's feature must not share its name with one of its dependencies. deny contains msg if { some file in input is_member(file) diff --git a/config/conftest/policy/cargo/cargo_test.rego b/config/conftest/policy/cargo/cargo_test.rego index 98daeb8e..d9d75f88 100644 --- a/config/conftest/policy/cargo/cargo_test.rego +++ b/config/conftest/policy/cargo/cargo_test.rego @@ -14,13 +14,13 @@ manifest(deps) := [{"path": "Cargo.toml", "contents": {"workspace": {"dependenci flagged(msgs, name) if { some msg in msgs - contains(msg, sprintf("%q", [name])) + contains(msg, $"\"{name}\"") contains(msg, "to a patch version") } stale(msgs, name) if { some msg in msgs - contains(msg, sprintf("patch_pin_exception entry %q is stale", [name])) + contains(msg, $"patch_pin_exception entry \"{name}\" is stale") } # The two shapes the rule exists to require, and the one it exists to reject. diff --git a/config/conftest/policy/checksums/checksums.rego b/config/conftest/policy/checksums/checksums.rego index 53b28766..672cc902 100644 --- a/config/conftest/policy/checksums/checksums.rego +++ b/config/conftest/policy/checksums/checksums.rego @@ -18,6 +18,10 @@ is_upstream_cache(file) if file.path == "config/upstream-cache/data.toml" # Module-scope sprintf templates each live on their own line so the source stays readable. missing_sha256_msg := "config/upstream-cache/data.toml: [asset.%q] is missing `sha256` (use `\"\"` while bootstrapping)" +asset_var_hint := "referenced via a `_asset` var in .mise/config*.toml" + +unreferenced_msg := "is recorded but no `_asset` var in .mise/config*.toml references it" + # Asset filenames declared in any .mise/config*.toml's [vars]. mise_assets contains filename if { some file in input @@ -33,22 +37,18 @@ recorded_assets contains filename if { some filename, _ in file.contents.asset } +# Every `_asset` var in the mise configs must have an [asset] table in config/upstream-cache/data.toml. deny contains msg if { some asset in mise_assets not asset in recorded_assets - msg := sprintf( - "config/upstream-cache/data.toml: missing [asset.%q] table (referenced via a `_asset` var in .mise/config*.toml)", - [asset], - ) + msg := $"config/upstream-cache/data.toml: missing [asset.\"{asset}\"] table ({asset_var_hint})" } +# Every [asset] table in config/upstream-cache/data.toml must be referenced by a mise `_asset` var. deny contains msg if { some asset in recorded_assets not asset in mise_assets - msg := sprintf( - "config/upstream-cache/data.toml: [asset.%q] is recorded but no `_asset` var in .mise/config*.toml references it", - [asset], - ) + msg := $"config/upstream-cache/data.toml: [asset.\"{asset}\"] {unreferenced_msg}" } # Per-entry shape check on each asset table. @@ -58,25 +58,28 @@ deny contains msg if { is_upstream_cache(file) some filename, entry in file.contents.asset not entry.url - msg := sprintf("config/upstream-cache/data.toml: [asset.%q] is missing `url` (the download URL)", [filename]) + msg := $"config/upstream-cache/data.toml: [asset.\"{filename}\"] is missing `url` (the download URL)" } +# Every recorded asset must name its `upstream` project URL. deny contains msg if { some file in input is_upstream_cache(file) some filename, entry in file.contents.asset not entry.upstream - msg := sprintf("config/upstream-cache/data.toml: [asset.%q] is missing `upstream` (the project URL)", [filename]) + msg := $"config/upstream-cache/data.toml: [asset.\"{filename}\"] is missing `upstream` (the project URL)" } +# Every recorded asset must carry its `license` as an SPDX expression. deny contains msg if { some file in input is_upstream_cache(file) some filename, entry in file.contents.asset not entry.license - msg := sprintf("config/upstream-cache/data.toml: [asset.%q] is missing `license` (SPDX expression)", [filename]) + msg := $"config/upstream-cache/data.toml: [asset.\"{filename}\"] is missing `license` (SPDX expression)" } +# Every recorded asset must carry a `sha256`, left empty only while bootstrapping. deny contains msg if { some file in input is_upstream_cache(file) diff --git a/config/conftest/policy/cross/wasm-bindgen-sync.rego b/config/conftest/policy/cross/wasm-bindgen-sync.rego index f57e6adb..971c8fc3 100644 --- a/config/conftest/policy/cross/wasm-bindgen-sync.rego +++ b/config/conftest/policy/cross/wasm-bindgen-sync.rego @@ -19,10 +19,8 @@ lock_version := ver if { ver := pkg.version } +# The mise wasm-bindgen pin must match the wasm-bindgen version Cargo.lock resolves. deny contains msg if { mise_pin != lock_version - msg := sprintf( - "wasm-bindgen: mise pin %q != Cargo.lock %q; bump the pin in .mise/config.toml", - [mise_pin, lock_version], - ) + msg := $"wasm-bindgen: mise pin \"{mise_pin}\" != Cargo.lock \"{lock_version}\"; bump the pin in .mise/config.toml" } diff --git a/config/conftest/policy/dockerfile/dockerfile.rego b/config/conftest/policy/dockerfile/dockerfile.rego index 3f175668..6972e0aa 100644 --- a/config/conftest/policy/dockerfile/dockerfile.rego +++ b/config/conftest/policy/dockerfile/dockerfile.rego @@ -25,6 +25,7 @@ docker_strings contains entry if { entry := {"path": file.path, "value": value} } +# A version a Dockerfile hard-codes must match the [tools] pin for the same tool. deny contains msg if { some entry in docker_strings some d in mise.version_drift(entry.value) @@ -87,7 +88,7 @@ pipx_scope_path contains path if { pipx_scope_path contains path if { some file in input some lang in nano_langs - endswith(file.path, sprintf(".mise/config.%s.toml", [lang])) + endswith(file.path, $".mise/config.{lang}.toml") path := file.path } @@ -140,6 +141,7 @@ deny contains msg if { ) } +# A RUN heredoc must quote its delimiter so bash, not the outer shell, does the expansion. deny contains msg if { some file in input is_array(file.contents) @@ -156,6 +158,7 @@ deny contains msg if { ) } +# A Dockerfile `apt-get install` must pass --no-install-recommends on the same line. deny contains msg if { some file in input is_array(file.contents) @@ -169,6 +172,7 @@ deny contains msg if { msg := sprintf("%s: `apt-get install` must include --no-install-recommends on the same line", [file.path]) } +# A Dockerfile must use `apt-get`, never `apt`. deny contains msg if { some file in input is_array(file.contents) @@ -201,7 +205,7 @@ arg_packages[name] := pkgs if { instr.Cmd == "arg" some value in instr.Value some name in package_arg_names - startswith(value, concat("", [name, "="])) + startswith(value, $"{name}=") raw := trim(substring(value, count(name) + 1, -1), "\"") pkgs := {p | some p in split(raw, " "); p != ""} } @@ -213,7 +217,7 @@ bootstrap_packages[mgr] := pkgs if { some mgr in {"apt", "dnf"} pkgs := {p | some key, _ in file.contents.bootstrap.packages - startswith(key, concat("", [mgr, ":"])) + startswith(key, $"{mgr}:") p := substring(key, count(mgr) + 1, -1) } } @@ -226,9 +230,10 @@ expected_packages["dnf"] := arg_packages.COMMON_PACKAGES | arg_packages.DNF_PACK deny contains msg if { some name in package_arg_names not arg_packages[name] - msg := sprintf("Dockerfile: ARG %s not found -- the [bootstrap.packages] cross-check cannot run", [name]) + msg := $"Dockerfile: ARG {name} not found -- the [bootstrap.packages] cross-check cannot run" } +# [bootstrap.packages] must list every package the Dockerfile ARGs install. deny contains msg if { some mgr, want in expected_packages missing := want - bootstrap_packages[mgr] @@ -239,6 +244,7 @@ deny contains msg if { ) } +# [bootstrap.packages] must not list a package the Dockerfile ARGs do not install. deny contains msg if { some mgr, want in expected_packages extra := bootstrap_packages[mgr] - want @@ -323,6 +329,7 @@ root_common_packages contains pkg if { some pkg in decl.packages } +# Every other Dockerfile's COMMON_PACKAGES must be drawn from the root Dockerfile's list. deny contains msg if { some decl in common_packages_decls decl.path != "Dockerfile" @@ -357,6 +364,7 @@ mise_version_args contains entry if { entry := {"path": file.path, "value": substring(value, count("MISE_VERSION="), -1)} } +# A Dockerfile's MISE_VERSION must match .mise/config.toml's min_version. deny contains msg if { some decl in mise_version_args not startswith(decl.value, "$") diff --git a/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc.rego b/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc.rego index 5c3ad8b0..a6db8121 100644 --- a/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc.rego +++ b/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc.rego @@ -12,6 +12,7 @@ entries(file) := items if { items := file.contents[0] } +# A RUN heredoc's first body line must be `set -euo pipefail`. deny contains msg if { some file in input items := entries(file) diff --git a/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc_test.rego b/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc_test.rego index 9da965b9..82cd1b0b 100644 --- a/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc_test.rego +++ b/config/conftest/policy/dockerfile_heredoc/dockerfile_heredoc_test.rego @@ -15,7 +15,7 @@ dockerfile(originals) := [{"path": "Dockerfile", "contents": [lines]}] if { lines := [line | some o in originals; line := {"Original": o}] } -# The form CLAUDE.md requires and every Dockerfile in this repo uses: bash first, delimiter quoted. +# The form AGENTS.md requires and every Dockerfile in this repo uses: bash first, delimiter quoted. test_quoted_delimiter_accepts_a_correct_body if { msgs := dockerfile_heredoc.deny with input as dockerfile([ "RUN bash <<'EOF'", diff --git a/config/conftest/policy/generated_trees/generated_trees.rego b/config/conftest/policy/generated_trees/generated_trees.rego index 8bcf8e5d..56281e33 100644 --- a/config/conftest/policy/generated_trees/generated_trees.rego +++ b/config/conftest/policy/generated_trees/generated_trees.rego @@ -75,6 +75,7 @@ accounted(config, value, name) if { value in allowed(config, name) } +# Every config a generated tree requires must carry that tree's exclusion pattern. deny contains msg if { some name, tree in trees some config in tree.required_in diff --git a/config/conftest/policy/gha/gha.rego b/config/conftest/policy/gha/gha.rego index 5422a2c6..d5ca41be 100644 --- a/config/conftest/policy/gha/gha.rego +++ b/config/conftest/policy/gha/gha.rego @@ -12,7 +12,7 @@ required_shell := "bash --noprofile --norc -euo pipefail {0}" deny contains msg if { not input.defaults.run.shell == required_shell - msg := sprintf("workflow must set defaults.run.shell: %q (gets -euo pipefail on every step)", [required_shell]) + msg := $"workflow must set defaults.run.shell: \"{required_shell}\" (gets -euo pipefail on every step)" } # Steps must not override the shell -- rely on the workflow default. @@ -24,7 +24,7 @@ deny contains msg if { some step in job.steps step.shell not step_shell_allowed(step) - msg := sprintf("job %q sets shell: on a step; use the workflow default", [name]) + msg := $"job \"{name}\" sets shell: on a step; use the workflow default" } step_shell_allowed(step) if { @@ -71,50 +71,46 @@ buildkit_error_hint := "GHA Windows runners ship without buildx; build aborts" deny contains msg if { input.name == "docker-windows" input.env.DOCKER_BUILDKIT - msg := sprintf( - "docker-windows must not set DOCKER_BUILDKIT at workflow scope (%s)", - [buildkit_error_hint], - ) + msg := $"docker-windows must not set DOCKER_BUILDKIT at workflow scope ({buildkit_error_hint})" } +# The docker-windows workflow must not set DOCKER_BUILDKIT at job scope either. deny contains msg if { input.name == "docker-windows" some name, job in input.jobs job.env.DOCKER_BUILDKIT - msg := sprintf( - "docker-windows job %q must not set DOCKER_BUILDKIT (%s)", - [name, buildkit_error_hint], - ) + msg := $"docker-windows job \"{name}\" must not set DOCKER_BUILDKIT ({buildkit_error_hint})" } +# Nor at step scope. deny contains msg if { input.name == "docker-windows" some name, job in input.jobs some step in job.steps step.env.DOCKER_BUILDKIT - msg := sprintf( - "docker-windows job %q must not set DOCKER_BUILDKIT on a step (%s)", - [name, buildkit_error_hint], - ) + msg := $"docker-windows job \"{name}\" must not set DOCKER_BUILDKIT on a step ({buildkit_error_hint})" } # A workflow using a local composite action with a paths: trigger filter must list that action's location. -# This covers a workflow that uses a local composite action (./.github/actions/) and also filters its triggers +# This covers a workflow that uses a local composite action ($/.github/actions/) and also filters its triggers # with a paths: list. Otherwise edits to the composite action won't re-trigger this workflow on a PR that changes it. # Workflows without a paths filter already trigger on every PR/push and are skipped by this rule. local_actions_used contains action_dir if { some job in input.jobs some step in job.steps - startswith(step.uses, "./.github/actions/") + startswith(step.uses, "$/.github/actions/") - # Strip the leading "./" to get the repo-relative dir. + # Strip the leading "$/" to get the repo-relative dir. # This matches the gitignore-style path filters in `on..paths`. action_dir := substring(step.uses, 2, -1) } # Paths array configured for a trigger event, if any. +# The YAML parser reads a bare `on:` key as the boolean `true` (YAML 1.1), so the trigger table is found under that +# key; `on` is checked as well for an input that quoted it. trigger_paths(event) := paths if { - paths := input.on[event].paths + some key in ["on", "true"] + paths := input[key][event].paths is_array(paths) } @@ -125,17 +121,19 @@ paths_cover_dir(paths, action_dir) if { startswith(p, action_dir) } +untriggered_hint := "edits won't re-trigger this workflow" + +# A workflow's trigger paths must cover every local action it uses, so an edit to one re-runs it. deny contains msg if { some action_dir in local_actions_used some event in ["pull_request", "pull_request_target", "push"] paths := trigger_paths(event) not paths_cover_dir(paths, action_dir) - msg := sprintf( - "workflow uses ./%s but on.%s.paths doesn't include it (e.g. %q) -- edits won't re-trigger this workflow", - [action_dir, event, sprintf("%s/**", [action_dir])], - ) + cover := $"{action_dir}/**" + msg := $"workflow uses $/{action_dir} but on.{event}.paths doesn't include it (e.g. \"{cover}\") -- {untriggered_hint}" } +# A workflow step's `apt-get install` must pass --no-install-recommends on the same line. deny contains msg if { some name, job in input.jobs some step in job.steps @@ -144,9 +142,10 @@ deny contains msg if { not startswith(trim_space(line), "#") regex.match(`\bapt-get\s+install\b`, line) not contains(line, "--no-install-recommends") - msg := sprintf("job %q: `apt-get install` must include --no-install-recommends on the same line", [name]) + msg := $"job \"{name}\": `apt-get install` must include --no-install-recommends on the same line" } +# A workflow step must use `apt-get`, never `apt`. deny contains msg if { some name, job in input.jobs some step in job.steps @@ -154,7 +153,7 @@ deny contains msg if { some line in split(step.run, "\n") not startswith(trim_space(line), "#") regex.match(`\bapt(\s|$)`, line) - msg := sprintf("job %q: use `apt-get`, not `apt` (apt's UI is not stable across releases)", [name]) + msg := $"job \"{name}\": use `apt-get`, not `apt` (apt's UI is not stable across releases)" } # Every actions/upload-artifact step must set with.if-no-files-found: error. @@ -167,7 +166,7 @@ deny contains msg if { some step in job.steps startswith(step.uses, "actions/upload-artifact") object.get(step, ["with", "if-no-files-found"], "warn") != "error" - msg := sprintf("job %q: actions/upload-artifact must set with.if-no-files-found: error", [name]) + msg := $"job \"{name}\": actions/upload-artifact must set with.if-no-files-found: error" } # Every matrix value is spliced into the GitHub job name, so a long one wrecks the Actions UI. diff --git a/config/conftest/policy/gha/gha_test.rego b/config/conftest/policy/gha/gha_test.rego new file mode 100644 index 00000000..747d7b96 --- /dev/null +++ b/config/conftest/policy/gha/gha_test.rego @@ -0,0 +1,28 @@ +package gha_test + +import data.gha + +# A workflow as the YAML parser hands it over: a bare `on:` key arrives as the boolean `true`. +workflow(paths) := { + "name": "probe", + "true": {"pull_request": {"paths": paths}}, + "jobs": {"build": {"steps": [{"uses": "$/.github/actions/install-mise"}]}}, +} + +untriggered(msgs) if { + some msg in msgs + contains(msg, "but on.pull_request.paths doesn't include it") +} + +test_local_action_outside_the_paths_filter_is_denied if { + untriggered(gha.deny) with input as workflow(["src/**"]) +} + +test_local_action_inside_the_paths_filter_is_allowed if { + not untriggered(gha.deny) with input as workflow(["src/**", ".github/actions/install-mise/**"]) +} + +test_quoted_on_key_is_read_too if { + quoted := object.union(object.remove(workflow(["src/**"]), ["true"]), {"on": {"pull_request": {"paths": ["src/**"]}}}) + untriggered(gha.deny) with input as quoted +} diff --git a/config/conftest/policy/gha_mise/gha_mise.rego b/config/conftest/policy/gha_mise/gha_mise.rego index f4855a16..559a3611 100644 --- a/config/conftest/policy/gha_mise/gha_mise.rego +++ b/config/conftest/policy/gha_mise/gha_mise.rego @@ -58,6 +58,7 @@ all_langs := value if { value := file.contents.env.ALL_LANGS } +# A workflow's env.MISE_ENV must match .mise/config.toml's ALL_LANGS. deny contains msg if { some file in input endswith(file.path, ".yaml") diff --git a/config/conftest/policy/gha_uses/gha_uses.rego b/config/conftest/policy/gha_uses/gha_uses.rego index 83f0423b..c6b05a24 100644 --- a/config/conftest/policy/gha_uses/gha_uses.rego +++ b/config/conftest/policy/gha_uses/gha_uses.rego @@ -1,6 +1,6 @@ # Cross-file check: every input passed to a LOCAL composite action must be one that the action declares. # Run with `--namespace gha_uses` over the workflow YAML plus every .github/actions/*/action.yaml, combined -# (--combine) so a single evaluation resolves each `uses: ./.github/actions/` against that action's `inputs:`. +# (--combine) so a single evaluation resolves each `uses: $/.github/actions/` against that action's `inputs:`. # GitHub Actions only emits a *warning* -- never an error -- when a caller passes a `with:` key the target action # does not declare, so a typo'd input name silently defaults to "" and the intended value is dropped. (Concrete # regression: install-mise-tools passed `install-action:` to install-mise, whose input is `install-action-tools`, @@ -39,11 +39,12 @@ caller_steps contains entry if { entry := {"path": file.path, "step": step} } +# A step must not pass an input that the local action it calls does not declare. deny contains msg if { some entry in caller_steps step := entry.step - startswith(step.uses, "./.github/actions/") - name := trim_prefix(step.uses, "./.github/actions/") + startswith(step.uses, "$/.github/actions/") + name := trim_prefix(step.uses, "$/.github/actions/") declared := declared_inputs[name] some key, _ in step.with not declared[key] @@ -81,7 +82,7 @@ windows_tool_path contains entry if { # Requiring it immediately before the tool dir is the actual invariant either way. deny contains msg if { some entry in windows_tool_path - not contains(entry.value, sprintf("%s\\http-busybox", [mise_installs_dir])) + not contains(entry.value, $"{mise_installs_dir}\\http-busybox") msg := sprintf( "%s: the http-busybox path must sit under the MISE_INSTALLS_DIR install-mise exports (%q)", [entry.path, mise_installs_dir], diff --git a/config/conftest/policy/jscpd/jscpd.rego b/config/conftest/policy/jscpd/jscpd.rego index a1dc05a4..70f9ea7e 100644 --- a/config/conftest/policy/jscpd/jscpd.rego +++ b/config/conftest/policy/jscpd/jscpd.rego @@ -41,6 +41,7 @@ deny contains msg if { msg := sprintf(grew_msg, [baseline_clones, declared_clones]) } +# declared_clones may sit at most max_slack above the baseline, so progress gets banked. deny contains msg if { slack := declared_clones - baseline_clones slack > max_slack diff --git a/config/conftest/policy/mise/mise.rego b/config/conftest/policy/mise/mise.rego index 62b86254..50f8c1ba 100644 --- a/config/conftest/policy/mise/mise.rego +++ b/config/conftest/policy/mise/mise.rego @@ -125,6 +125,7 @@ cargo_scoped_to_second_tier(spec) if { } } +# A `cargo:` tool must not build from source unless allowlisted or os-scoped to a second-tier platform. deny contains msg if { some file in input is_mise(file) @@ -179,6 +180,7 @@ forge_url(url) if contains(url, "gitlab.com") http_forge_msg := "%s: tool %q fetches %s over http:; use the github: backend so versions resolve and artifacts verify" +# An `http:` tool must not fetch from a forge URL; use the github: backend instead. deny contains msg if { some file in input is_mise(file) @@ -189,6 +191,7 @@ deny contains msg if { msg := sprintf(http_forge_msg, [file.path, name, tool.url]) } +# No per-platform URL of an `http:` tool may point at a forge either. deny contains msg if { some file in input is_mise(file) @@ -200,7 +203,7 @@ deny contains msg if { msg := sprintf(http_forge_msg, [file.path, name, platform.url]) } -# Tools should work on every OS (CLAUDE.md "Tools must work on every OS"). +# Tools should work on every OS (AGENTS.md "Tools must work on every OS"). # Any os-scoped [tools] entry must be in this list -- a genuinely platform-specific tool, a per-platform backend pair # that still covers every OS (findutils, ryl), or an optional tool that self-skips on the omitted platform (pipx:torch). allowed_os_scoped_tool := { @@ -261,6 +264,7 @@ allowed_os_scoped_tool := { "conda:clang", } +# A tool must not be os-scoped unless allowlisted, since every tool must work on every OS. deny contains msg if { some file in input is_mise(file) @@ -318,7 +322,7 @@ config_strings contains entry if { # (data.mise.version_drift). version_drift(value) := {drift | some [dir, _] in tool_versions - pattern := sprintf(`(?:^|[\\/}])%s[\\/]([A-Za-z0-9._-]+)`, [dir]) + pattern := $`(?:^|[\\/}]){dir}[\\/]([A-Za-z0-9._-]+)` some m in regex.find_all_string_submatch_n(pattern, value, -1) seg := m[1] not [dir, seg] in tool_versions @@ -326,6 +330,7 @@ version_drift(value) := {drift | drift := {"dir": dir, "seg": seg, "pinned": pinned} } +# A mise install path that a config string embeds must name the version [tools] pins. deny contains msg if { some entry in config_strings contains(entry.value, "installs") @@ -362,6 +367,7 @@ required_package_args := { ".mise/config.macos.toml": {"APT_PACKAGES", "COMMON_PACKAGES"}, } +# Each OS's preinstall task must read its package lists from the Dockerfile ARGs. deny contains msg if { some file in input some required in required_package_args[file.path] @@ -402,6 +408,7 @@ usage_vars(spec) := vars if { } } +# Every usage arg a task declares must be read by its run body. deny contains msg if { some file in input is_mise(file) diff --git a/config/conftest/policy/mise_lock/mise_lock.rego b/config/conftest/policy/mise_lock/mise_lock.rego new file mode 100644 index 00000000..6c189b8b --- /dev/null +++ b/config/conftest/policy/mise_lock/mise_lock.rego @@ -0,0 +1,71 @@ +# .mise/mise*.lock policy: a Linux tool locks its musl build unless it is allowlisted for a glibc one. +# Evaluated over conftest's `--combine` input (an array of {path, contents}). Run with `--namespace mise_lock`. +# +# A glibc build starts only where the host's glibc is at least as new as the one it was linked against, and the +# oldest image bases this repo builds on ship glibc 2.35 (ubuntu:22.04) and 2.36 (debian:bookworm). mise picks the +# gnu asset for a glibc platform whenever a release publishes both, so a lock refresh can silently swap a portable +# musl build for one those images cannot run: uutils coreutils did exactly that, and every `coreutils` call on +# both images failed with it. +package mise_lock + +is_lock(file) if regex.match(`^\.mise/mise(\.[a-z]+)?\.lock$`, replace(file.path, "\\", "/")) + +# Tools allowed to lock a glibc Linux build, each with the glibc floor it was measured to need. +# +# The floor is the highest GLIBC_ symbol version the tool's binaries reference. A floor above 2.35 is a build the +# ubuntu:22.04 image cannot start; such an entry stays only because no musl build exists for it. +gnu_allowed := { + "aqua:01mf02/jaq": "GLIBC_2.34", + "aqua:vectordotdev/vector": "GLIBC_2.28", + "ast-grep": "GLIBC_2.34", + "cargo-binstall": "GLIBC_2.17", + "dprint": "GLIBC_2.17", + "github:caldempsey/parfit": "GLIBC_2.34", + "github:grok-rs/waitup": "GLIBC_2.39 on x64, above the 2.35 floor", + "github:nextest-rs/nextest": "GLIBC_2.27", + "github:owenlamont/ryl": "GLIBC_2.34", + "github:uutils/findutils": "GLIBC_2.29", + "github:wasm-bindgen/wasm-bindgen": "GLIBC_2.39 on arm64, above the 2.35 floor", + "http:augeas": "GLIBC_2.38, above the 2.35 floor; the upstream-cache mirror builds no musl variant", + "http:et-rp": "GLIBC_2.38, above the 2.35 floor; the upstream-cache mirror builds no musl variant", + "http:oxfmt": "GLIBC_2.18", + "http:oxlint": "GLIBC_2.18", + "python": "GLIBC_2.17", + "ripgrep": "GLIBC_2.18", + "ruff": "GLIBC_2.17", + "uv": "GLIBC_2.28", + "watchexec": "GLIBC_2.39 on arm64, above the 2.35 floor", + "zizmor": "GLIBC_2.34", +} + +# Every (lockfile, tool, platform) whose locked Linux asset is a glibc build. +gnu_locks contains [file.path, name, platform] if { + some file in input + is_lock(file) + some name, entries in file.contents.tools + some entry in entries + some key, locked in entry + startswith(key, "platforms.linux-") + regex.match(`linux[-_]gnu`, locked.url) + platform := trim_prefix(key, "platforms.") +} + +musl_hint := "select its musl asset (a github backend `asset_pattern` per Linux platform), or allowlist its floor" + +# A tool locks a glibc Linux build without an allowlist entry. +deny contains msg if { + some [path, name, platform] in gnu_locks + not gnu_allowed[name] + msg := $"{path}: {name} locks a glibc build for {platform}; {musl_hint}" +} + +# An allowlist entry names a tool that no longer locks a glibc build anywhere. +deny contains msg if { + some name, reason in gnu_allowed + not name in gnu_locked_names + msg := $"mise_lock.rego: gnu_allowed lists {name} ({reason}), which no longer locks a glibc build; drop the entry" +} + +gnu_locked_names contains name if { + some [_, name, _] in gnu_locks +} diff --git a/config/conftest/policy/mise_lock/mise_lock_test.rego b/config/conftest/policy/mise_lock/mise_lock_test.rego new file mode 100644 index 00000000..06217702 --- /dev/null +++ b/config/conftest/policy/mise_lock/mise_lock_test.rego @@ -0,0 +1,50 @@ +package mise_lock_test + +import data.mise_lock + +allowed := {"github:example/allowed": "GLIBC_2.17"} + +# One lockfile holding a single tool locked to the given Linux URL. +lock(name, url) := [{ + "path": ".mise/mise.lock", + "contents": {"tools": {name: [{"version": "1", "platforms.linux-x64": {"url": url}}]}}, +}] + +denied_for(msgs, name) if { + some msg in msgs + contains(msg, $"{name} locks a glibc build for linux-x64") +} + +test_musl_build_is_allowed if { + not denied_for(mise_lock.deny, "github:example/tool") with input as lock( + "github:example/tool", + "https://example.test/tool-x86_64-unknown-linux-musl.tar.gz", + ) + with mise_lock.gnu_allowed as {} +} + +test_unlisted_gnu_build_is_denied if { + denied_for(mise_lock.deny, "github:example/tool") with input as lock( + "github:example/tool", + "https://example.test/tool-x86_64-unknown-linux-gnu.tar.gz", + ) + with mise_lock.gnu_allowed as allowed +} + +test_allowlisted_gnu_build_is_allowed if { + msgs := mise_lock.deny with input as lock( + "github:example/allowed", + "https://example.test/allowed-x86_64-unknown-linux-gnu.zip", + ) + with mise_lock.gnu_allowed as allowed + count(msgs) == 0 +} + +test_stale_allowlist_entry_is_denied if { + some msg in mise_lock.deny with input as lock( + "github:example/tool", + "https://example.test/tool-x86_64-unknown-linux-musl.tar.gz", + ) + with mise_lock.gnu_allowed as allowed + contains(msg, "gnu_allowed lists github:example/allowed") +} diff --git a/config/conftest/policy/policy_pairing/policy_pairing.rego b/config/conftest/policy/policy_pairing/policy_pairing.rego index 63e75318..63b48d05 100644 --- a/config/conftest/policy/policy_pairing/policy_pairing.rego +++ b/config/conftest/policy/policy_pairing/policy_pairing.rego @@ -45,18 +45,18 @@ untested_policy := { "config/conftest/policy/jscpd/jscpd.rego": "two arithmetic comparisons against one declared number", "config/conftest/policy/pyproject/pyproject.rego": "direct key presence checks over one table", "config/conftest/policy/dockerfile/dockerfile.rego": "pattern-driven; predates the rule, write tests", - "config/conftest/policy/gha/gha.rego": "pattern-driven; predates the rule, write tests", "config/conftest/policy/gha_combined/gha_combined.rego": "pattern-driven; predates the rule, write tests", "config/conftest/policy/gha_mise/gha_mise.rego": "pattern-driven; predates the rule, write tests", "config/conftest/policy/gha_uses/gha_uses.rego": "pattern-driven; predates the rule, write tests", } +# Every policy must have a test file beside it, or a reasoned untested_policy entry. deny contains msg if { some path in policy_files not untested_policy[path] expected := expected_test(path) not expected in paired_tests - msg := sprintf("%s: add %s, or record the policy in untested_policy with its reason", [path, expected]) + msg := $"{path}: add {expected}, or record the policy in untested_policy with its reason" } # The map is a two-way contract, the same way a lint suppression is. @@ -65,12 +65,12 @@ deny contains msg if { deny contains msg if { some path, reason in untested_policy expected_test(path) in paired_tests - msg := sprintf("%s: now has a test, so drop its untested_policy entry (%s)", [path, reason]) + msg := $"{path}: now has a test, so drop its untested_policy entry ({reason})" } # An entry naming a policy that is no longer there has outlived what it described. deny contains msg if { some path, reason in untested_policy not path in policy_files - msg := sprintf("%s: untested_policy names a policy that no longer exists (%s)", [path, reason]) + msg := $"{path}: untested_policy names a policy that no longer exists ({reason})" } diff --git a/config/conftest/policy/pyproject/pyproject.rego b/config/conftest/policy/pyproject/pyproject.rego index eac6ef08..473b07a9 100644 --- a/config/conftest/policy/pyproject/pyproject.rego +++ b/config/conftest/policy/pyproject/pyproject.rego @@ -21,11 +21,12 @@ uv_version := v if { v := file.contents.tools.uv } +# A pyproject's uv_build requirement must pin the uv version mise installs. deny contains msg if { some file in input endswith(file.path, "pyproject.toml") some req in file.contents["build-system"].requires startswith(req, "uv_build") - req != sprintf("uv_build==%s", [uv_version]) + req != $"uv_build=={uv_version}" msg := sprintf("%s: pin uv_build==%s to match mise's uv (found %q)", [file.path, uv_version, req]) } diff --git a/config/generated-trees.toml b/config/generated-trees.toml index ca0b1b65..b0a8f2f9 100644 --- a/config/generated-trees.toml +++ b/config/generated-trees.toml @@ -42,7 +42,9 @@ regenerated_by = "mise run gen-specs-all" required_in = [ "config/ast-grep/rules/command-requires-command-error.yaml", + "config/ast-grep/rules/derive-attribute-order.yaml", "config/ast-grep/rules/doc-summary-ends-with-period.yaml", + "config/ast-grep/rules/inherent-impl-first.yaml", "config/ast-grep/rules/no-allow-attributes.yaml", "config/ast-grep/rules/no-concat-raw-strings.yaml", "config/ast-grep/rules/no-consecutive-expect.yaml", @@ -59,6 +61,7 @@ required_in = [ "config/ast-grep/rules/no-string-new.yaml", "config/ast-grep/rules/prefer-self-mod-use.yaml", "config/ast-grep/rules/use-mod-order.yaml", + "config/ast-grep/rules/write-ending-newline.yaml", "config/jscpd.json", "config/pyrefly.toml", "config/semgrep/anyhow-only-in-error-rs.yaml", @@ -69,6 +72,7 @@ required_in = [ "config/semgrep/no-task-name-mentions.yaml", "config/semgrep/no-todo.yaml", "config/semgrep/no-type-comments.yaml", + "config/semgrep/sorted-lists.yaml", ] # Scenario-generator outputs checked in beside their inputs; holds no Rust, so the Rust-only rules are absent. diff --git a/config/gitleaks.toml b/config/gitleaks.toml index c12772a4..8d761d3c 100644 --- a/config/gitleaks.toml +++ b/config/gitleaks.toml @@ -21,6 +21,7 @@ paths = [ '''(^|/)\.git/''', '''(^|/)\.gradle/''', '''(^|/)\.kotlin/''', + '''(^|/)\.mise/locks/''', '''(^|/)\.pytest_cache/''', '''(^|/)\.ruff_cache/''', '''(^|/)\.venv/''', diff --git a/config/jscpd-baseline.json b/config/jscpd-baseline.json index e5d8260b..ff46e19c 100644 --- a/config/jscpd-baseline.json +++ b/config/jscpd-baseline.json @@ -3,7 +3,6 @@ "fingerprints": { "006f44d440c27cda": 1, "023513f38a87a1e6": 1, - "025e751ba88e4efb": 1, "02c3bb68a9cb1430": 1, "03e4e07acff327e2": 1, "04199950b57990a0": 1, @@ -20,6 +19,7 @@ "0ea84f1f5db88fe7": 1, "100c4984075d3662": 1, "100c5a39e529a691": 1, + "106569d682a6a53f": 1, "109b672c3d6939d9": 1, "10b898032781bd2b": 1, "12bdba43f82ce591": 1, @@ -30,7 +30,6 @@ "161f873e1c1bf887": 1, "162b7eccbfa52a74": 1, "16acb47f836cc1f8": 1, - "16cc2ae0719020a6": 1, "16ff0dbe3f3bf18c": 1, "1a07ddf368451c0a": 1, "1a1867cca4e1d4e8": 1, @@ -67,16 +66,17 @@ "31a1985df946271b": 1, "31a98e49914dbdda": 1, "331841e078587935": 1, + "3355d5d4a61ff011": 1, "3369118fac56660d": 1, "34b2a7c1a1a932c1": 1, "34cd0de3c97e4264": 1, "35d7f304546de8a8": 1, "389aea3e8662fb9b": 1, + "39df8b0c7c0dccc1": 1, "3a075ed2f78fa99e": 1, "3aec07afda461f58": 1, "3afe9805243f94d2": 1, "3c0efbffa8bb6f9b": 1, - "3d7d16d66b899144": 1, "3de59029c7b786b0": 1, "3e5aadc3e77078b6": 1, "3e6e51f257b8453d": 1, @@ -91,6 +91,7 @@ "468a45c2019ca4cd": 1, "4a5b2cd87f30b9d3": 1, "4ab1b3a095eeb338": 1, + "4e1f48e8e76d2edd": 1, "4eff6767e2aba30c": 1, "506af004dd69d586": 1, "50b373907a5a8f78": 1, @@ -134,6 +135,7 @@ "6bad88d8a503b406": 1, "6d80cc58c007a238": 1, "6f84b76a00168521": 1, + "70e0d868d8dd652b": 1, "70f2dd70bb5a794f": 1, "71c439c66817fc57": 1, "71d4c22b912832b9": 1, @@ -146,7 +148,6 @@ "76b4bda9089c9985": 1, "773fa53d9003b640": 1, "781cc393068d5440": 1, - "791347abafa6f64e": 1, "7ac63870d0087e3b": 1, "7aee849465ea91ab": 1, "7ca55da801def6b2": 1, @@ -254,7 +255,6 @@ "ce09350cb036bbc9": 1, "ce990318bfc4aa30": 1, "cfe89c13ebd13c2e": 1, - "d02a1d7e66024e72": 1, "d0824c4dc47397f2": 1, "d2c9c708a567ce7e": 1, "d53180eb9c1c97e5": 1, diff --git a/config/ls-lint.yaml b/config/ls-lint.yaml index ce05984f..5c03cab6 100644 --- a/config/ls-lint.yaml +++ b/config/ls-lint.yaml @@ -35,6 +35,8 @@ ignore: - .git - target - generated + # The npm dependency graphs `mise lock` records beside a scenario's lockfile, named by the package and version. + - verification/published/output/math1/.mise # Bundled data/model assets -- names are not hand-chosen. # This also covers the pnpm symlink farm under data/split-learning-demo, whose nested package dirs are vendored. - data diff --git a/config/lychee.toml b/config/lychee.toml index eddcec91..d3121db4 100644 --- a/config/lychee.toml +++ b/config/lychee.toml @@ -34,7 +34,7 @@ exclude_path = ["data", "generated", "node_modules", "target"] # was observed, fully expecting them to age out (GHA log retention is 3 months), and github.com serves those # pages inconsistently to anonymous clients even while they exist -- the check lane got # [404] https://github.com/edge-toolkit/core/actions/runs/28698136445/job/85111320237 (at 447:1) -# from CLAUDE.md's attestation-flake note on commit +# from AGENTS.md's attestation-flake note on commit # https://github.com/edge-toolkit/core/commit/e401831a98197068f978ef760134caff882e2615 while the same URL # returned 200 to a local curl minutes later. Checking them is all noise, no signal. # diff --git a/config/semgrep/mise-config.yaml b/config/semgrep/mise-config.yaml index d82179c2..c0d20cc7 100644 --- a/config/semgrep/mise-config.yaml +++ b/config/semgrep/mise-config.yaml @@ -24,6 +24,40 @@ rules: before any task on Windows (see preinstall), so even the setup tasks can use it. severity: ERROR + - id: multiline-string-closes-on-own-line + languages: [generic] + paths: + include: + - "/.mise/config*.toml" + # Match a multi-line `"""` / `'''` string whose closing delimiter trails its last line instead of standing alone. + # The opening line and the lines before the last may not contain the delimiter, so a single-line `"""x"""` and a + # string that does close on its own line never match, and the scan cannot run on into the next value. No autofix: + # moving the delimiter appends a newline to the value, which is harmless in a task body but changes a Tera + # `[vars]` / `[env]` value unless its last tag trims with `-%}`, and a template cannot tell the two apart. + pattern-regex: '(?m)^[^\n#]*?= ("""|'''''')(?:(?!\1)[^\n])*\n(?:(?![^\n]*\1)[^\n]*\n)*?(?:(?!\1)[^\n])*\S\1' + message: >- + Close a multi-line `"""` (or `'''`) string with the delimiter alone on its own line, not on the end of its + last line. Every multi-line value then ends the same way and appending a line never means editing the one + before it. In a Tera value, end the last tag with `-%}` (e.g. `{%- endif -%}`) so the newline before the + delimiter is trimmed and the rendered value is unchanged. + severity: ERROR + + - id: multiline-literal-string-needs-backslash + languages: [generic] + paths: + include: + - "/.mise/config*.toml" + # Match a multi-line `'''` literal string that holds no backslash, the one character it exists to keep verbatim. + # The lookahead requires a newline before the closing `'''`, so a single-line value is out of scope. A body that + # contains `"""` is exempt too, since it cannot be written as a `"""` string at all. Swapping the delimiters is + # exactly the fix, but semgrep's `fix-regex` rewrites one pattern and the two ends need it together. + pattern-regex: '= ''''''(?=(?:(?!''''''|""")[^\\])*?\n)(?:(?!''''''|""")[^\\])*''''''' + message: >- + Write a multi-line string without a backslash as `"""..."""`, not `'''...'''`. A TOML literal string exists + to keep backslashes verbatim (Windows paths, regex escapes); without one it only makes this value differ from + the `"""` bodies around it, and the next reader looks for an escape that is not there. + severity: ERROR + - id: task-shell-must-use-task-shell-var languages: [generic] paths: @@ -61,3 +95,30 @@ rules: Inline it on the parent task as `env = { KEY = "value" }` when the resulting line fits the editorconfig line length -- subtable form is reserved for multi-key envs. severity: WARNING + + - id: mise-task-coreutils-prefix + languages: [generic] + paths: + include: + - "/.mise/config*.toml" + # A banned name only counts in command position, so `mise ls`, `docker rm` and prose stay clear of it. + # Command position is the start of a line or of a `run = "..."` string, or just after `;`, `|`, `&`, `(`, a + # backtick, or `then`/`do`/`else`. The prefix class stops at `#`, so a comment line or a trailing comment + # never matches; a name already behind `coreutils` or `"$coreutils"` follows a word, not a separator. + # `(?x)` lets the regex wrap: unescaped whitespace is ignored, so literal spaces are written `[ ]`. + # The `pattern-not-regex` drops every line that assigns a TOML key other than `run`, so a `description` or + # any other value that only mentions a command -- `"Inspect files (ls -la)"` -- is never read as one. + patterns: + - pattern-regex: >- + (?mx) ^( (?: [^#\n]*? (?: [;|&(`] | \bthen | \bdo | \belse | \brun[ ]=[ ]["'] ) )? [ \t]* ) + (cat|cp|cut|ls|mkdir|mktemp|mv|rm|sort|tr) (?=[ \t]|$) + - pattern-not-regex: '(?m)^[ \t]*(?!run[ \t]*=)[A-Za-z_][\w.-]*[ \t]*=[^\n]*$' + # Check-only, because the pinned semgrep silently drops a `fix-regex` on a generic `pattern-regex` rule. + # Inserting the `coreutils ` prefix is therefore left to the human. + message: >- + Call POSIX utilities in mise task bodies through the mise-managed uutils multicall, as `coreutils `. + A bare `mkdir`/`cp`/`rm`/... runs whatever the host ships -- BSD on macOS, GNU on Linux, busybox or Git + Bash on Windows -- so flags and behaviour differ per machine, and the task depends on a tool mise does not + pin. A command that is run by another shell (inside a container or pod) is a genuine exception: suppress it + on that line with a `nosemgrep` comment saying where it runs. + severity: ERROR diff --git a/config/semgrep/no-check-tool-mentions.yaml b/config/semgrep/no-check-tool-mentions.yaml index 8e4570be..d85b01de 100644 --- a/config/semgrep/no-check-tool-mentions.yaml +++ b/config/semgrep/no-check-tool-mentions.yaml @@ -19,13 +19,14 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.codacy.yaml" # Names the workflow linters Codacy defers to, as its exclusion rationale. - "/.github/actions/install-mise-tools/action.yaml" # Stages the tool for CI. - "/.github/workflows/test.yaml" # Notes the Windows lane's source-build fallback for it. - "/Dockerfile" # Disables the tool for an image whose build does not need it. - "/config/conftest/policy/mise/mise.rego" # Allowlists it as a `cargo:` tool with no prebuilt. - "/config/taplo/mise-cargo-backend-allowlist.schema.json" # Same allowlist, as a TOML schema enum. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)action-validator" message: >- @@ -40,6 +41,7 @@ rules: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - "/.codacy.yaml" # Names the workflow linters Codacy defers to, as its exclusion rationale. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)actionlint" message: >- @@ -52,12 +54,14 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the scan/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.codacy.yaml" # Names the workflow linters Codacy defers to, as its exclusion rationale. - "/config/ast-grep/**" # Its own ruleset, where the tool's own syntax is the subject. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. - "/config/generated-trees.toml" # Maps each generated tree onto the exclusion key this tool needs. - "/config/conftest/policy/generated_trees/generated_trees.rego" # Enforces that mapping. - "/config/conftest/policy/generated_trees/generated_trees_test.rego" # Unit tests for it. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. - "/libs/test-helpers/src/lib.rs" # Carries a suppression pragma, which only works spelled out. pattern-regex: "(?i)ast-grep" @@ -74,6 +78,7 @@ rules: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - "/.github/workflows/dependencies.yaml" # Runs the audit on CI. - "/config/deny.toml" # Its own config, including which scanner honours which advisory id. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)cargo-deny" message: >- @@ -89,6 +94,7 @@ rules: - "/.mise/**" # Tool pin and the task that runs it. - "/.github/workflows/dependencies.yaml" # Runs the scan on CI. - "/Cargo.toml" # Its per-crate ignore list, where each entry's reason is the false positive it hit. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)cargo-unmaintained" message: >- @@ -101,8 +107,9 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the format/check tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/config/clang-format.yaml" # Its own config, including the settings held to agree with the C linters. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)clang-format" message: >- @@ -115,10 +122,11 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the check/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.github/workflows/codeql.yaml" # Names the check that keeps the coverage an excluded query gave up. - "/config/clang-tidy.yaml" # Its own config, including which external code each check mirrors. - "/config/conftest/policy/mise/mise.rego" # Allowlists it as a `cargo:` tool with no prebuilt. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)clang-tidy" message: >- @@ -132,7 +140,7 @@ rules: paths: exclude: - "/.mise/**" # Names the tool in the task that mirrors its secret scan locally. - - "/CLAUDE.md" # Documents how a finding from an external analyzer must reach a local checker. + - "/AGENTS.md" # Documents how a finding from an external analyzer must reach a local checker. - "/.codacy.yaml" # Its own config, whose path excludes each carry their reason. - "/libs/wasi-guest/src/coverage.rs" # Path-excluded there; its header is that exclusion's only home. - "/services/ws-test-server/src/bin/cov-server.rs" # Likewise path-excluded, rationale in its header. @@ -140,6 +148,7 @@ rules: - "/services/ws-web-runner/mingw-shim/msvc_crt_locale_cache.c" # Likewise. - "/utilities/cli/src/hub_ws_url.rs" # Likewise. - "/utilities/wasm-cov-wrapper/src/main.rs" # Likewise. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)codacy" message: >- @@ -153,12 +162,13 @@ rules: paths: exclude: - "/.mise/**" # The coverage tasks that produce and upload its reports. - - "/CLAUDE.md" # Records which coverage check on a PR is the one that has to pass. + - "/AGENTS.md" # Records which coverage check on a PR is the one that has to pass. - "/.deepsource.toml" # Declares the coverage artifact both services read. - "/.github/workflows/coverage.yaml" # Uploads to it on CI. - "/.gitignore" # Ignores its downloaded uploader binary. - "/.dockerignore" # The same ignore, generated from it. - "/verification/**" # Generator-owned output, carrying whatever the generator wrote. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. patterns: - pattern-regex: "(?i)codecov" @@ -176,7 +186,7 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entries, and the per-format policy tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.codacy.yaml" # Names the config linters Codacy defers to, as its exclusion rationale. - "/.editorconfig" # `conftest fmt` owns Rego indentation and is not configurable, hence the override. - "/Dockerfile" # Stages or disables the tool for the image build. @@ -184,6 +194,7 @@ rules: - "/config/conftest/**" # Its own policy tree, where the tool's input shape is the subject. - "/config/generated-trees.toml" # Declares the policy that enforces the linter/tree mapping. - "/config/regal.yaml" # Carves out the conftest-specific Rego patterns vanilla regal would flag. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)conftest" message: >- @@ -197,10 +208,11 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.github/workflows/codeql.yaml" # Names the check that keeps the coverage an excluded query gave up. - "/Dockerfile.nanoserver" # Disables the tool for an image whose build does not need it. - "/config/clang-format.yaml" # The formatter setting chosen so the two agree on comment spacing. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)cpplint" message: >- @@ -213,10 +225,11 @@ rules: paths: exclude: - "/.mise/**" # The coverage tasks that produce the reports it ingests. - - "/CLAUDE.md" # Documents how a finding from an external analyzer must reach a local checker. + - "/AGENTS.md" # Documents how a finding from an external analyzer must reach a local checker. - "/.deepsource.toml" # Its own config. - "/.codacy.yaml" # Names it as the analyzer still covering what Codacy skips. - "/.github/workflows/coverage.yaml" # Reports coverage to it on CI. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. - "/config/semgrep/deepsource-codes-are-qualified.yaml" # Requires the name, so it has to write it. # Unlike its siblings, this one permits the name where it qualifies one of the analyzer's codes. @@ -235,7 +248,7 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the format/check tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.dprint.jsonc" # The root config, which is also this repo's root-marker file. - "/.codacy.yaml" # Names the formatters Codacy defers to, as its exclusion rationale. - "/.gitattributes" # Records that the formatters write LF, which the checkout must preserve. @@ -248,6 +261,10 @@ rules: - "/config/ast-grep/rules/no-current-dir.yaml" # Names the root-marker file, not the tool. - "/libs/path/src/lib.rs" # Holds that marker filename as a constant. - "/libs/path/tests/find.rs" # Writes the marker file to build a fixture root. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. + - "/utilities/int-gen/src/checks.rs" # Names the root config stub the tool finds without being told to. + - "/utilities/int-gen/src/help.rs" # Runs it to format the HELP.md files it writes. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)dprint" message: >- @@ -261,7 +278,9 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. + - "/utilities/int-gen/src/checks.rs" # Names the root config the tool finds without being told to. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)editorconfig-check" message: >- @@ -275,9 +294,10 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/Dockerfile.nanoserver" # Disables the tool for an image whose build does not need it. - "/services/ws-modules/zig-except1/src/exceptions.cpp" # A `flawfinder: ignore` pragma, spelled out. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)flawfinder" message: >- @@ -290,8 +310,9 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/config/gitleaks.toml" # Its own config, including how far its inline marker reaches. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)gitleaks" message: >- @@ -304,7 +325,7 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.github/workflows/docker-linux.yaml" # Stages every Dockerfile where the tool can find it. - "/Dockerfile" # Carries `# hadolint ignore=` pragmas, which only work spelled out. - "/Dockerfile.nanoserver" # Same, plus the tool's own MISE_DISABLE_TOOLS entry. @@ -313,6 +334,7 @@ rules: - "/config/hadolint.yaml" # Its own config, and the shellcheck code it emits from its embedded copy. - "/utilities/cli/src/deployment_types/scenario_image.rs" # Emits those pragmas into generated images. - "/verification/**" # The generated images holding them. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)hadolint" message: >- @@ -326,7 +348,7 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the tasks that run and report it. - - "/CLAUDE.md" # Documents the baseline-is-a-debt-ledger rule, which is where that policy belongs. + - "/AGENTS.md" # Documents the baseline-is-a-debt-ledger rule, which is where that policy belongs. - "/config/jscpd.json" # Its own config. - "/config/jscpd-baseline.json" # The clone-fingerprint baseline it reads. - "/config/conftest/policy/jscpd/jscpd.rego" # Ratchets that baseline, and takes the tool as its package. @@ -337,6 +359,7 @@ rules: - "/config/semgrep/prefer-yaml-toml.yaml" # Allowlists its two files, which cannot be YAML or take comments. - "/config/typos.toml" # The same carve-out for those two files. - "/Dockerfile.nanoserver" # Disables the tool for an image whose verifier cannot install it. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)jscpd" message: >- @@ -354,6 +377,7 @@ rules: - "/README.md" # Tells a contributor which checks validate the generated manifests. - "/.codacy.yaml" # Names the manifest checks Codacy defers to, as its exclusion rationale. - "/.github/workflows/k3s.yaml" # Runs the validation on CI. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)kubeconform" message: >- @@ -366,9 +390,10 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs, and keeping its ignores in sync with .gitignore. + - "/AGENTS.md" # Documents which checks an agent runs, and keeping its ignores in sync with .gitignore. - "/config/ls-lint.yaml" # Its own config. - "/config/semgrep/ls-lint-no-glob.yaml" # The rule holding that config to literal paths. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)ls-lint" message: >- @@ -381,12 +406,13 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the link-check task. - - "/CLAUDE.md" # Documents which checks an agent runs, and keeping its ignores in sync with .gitignore. + - "/AGENTS.md" # Documents which checks an agent runs, and keeping its ignores in sync with .gitignore. - "/config/lychee.toml" # Its own config. - "/Dockerfile.nanoserver" # Disables the tool for an image whose build does not need it. - "/.gitignore" # Ignores its on-disk cache. - "/.dockerignore" # The same ignore, generated from it. - "/verification/**" # Generator-owned output, carrying whatever the generator wrote. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)lychee" message: >- @@ -405,6 +431,8 @@ rules: # Every test here wants one fixed port, and only that config's test group keeps them apart. # That is a constraint nothing in the file itself can express, and a silent corruption when bypassed. - "/utilities/cli/tests/scenario_runners.rs" + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)nextest" message: >- @@ -423,6 +451,7 @@ rules: - "/config/deny.toml" # Records which of the two scanners honours each advisory id. - "/pnpm-workspace.yaml" # One root lockfile exists so the npm scan has a single committed target. - "/pubspec.yaml" # The same, for the Dart ecosystem. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)osv-scanner" message: >- @@ -435,11 +464,13 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the format/check tasks. - - "/CLAUDE.md" # Documents how to write JS that both formatters accept. + - "/AGENTS.md" # Documents how to write JS that both formatters accept. - "/config/oxfmtrc.jsonc" # Its own config. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. - "/config/dprint.jsonc" # The other formatter, tuned to agree with it. - "/config/semgrep/prefer-yaml-toml.yaml" # Allowlists its config, which can only be JSONC. - "/config/conftest/policy/mise/mise.rego" # Allowlists it as a tool with no prebuilt at some triple. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)oxfmt" message: >- @@ -453,11 +484,13 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the lint/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. - "/config/oxlintrc.jsonc" # Its own config, including which external code each rule mirrors. - "/config/oxfmtrc.jsonc" # Names the shared JSONC configs the formatter must skip. - "/config/semgrep/prefer-yaml-toml.yaml" # Allowlists its config, which can only be JSONC. - "/config/conftest/policy/mise/mise.rego" # Allowlists it as a tool with no prebuilt at some triple. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)oxlint" message: >- @@ -474,6 +507,7 @@ rules: - "/config/semgrep/no-type-comments.yaml" # The rule keeping annotations the only form it can check. - "/config/generated-trees.toml" # Maps each generated tree onto the exclusion key this tool needs. - "/config/conftest/policy/generated_trees/generated_trees.rego" # Enforces that mapping. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)pyrefly" message: >- @@ -487,8 +521,9 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the check/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/config/regal.yaml" # Its own config. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: '(?i)\bregal\b' message: >- @@ -503,6 +538,7 @@ rules: - "/.mise/**" # Tool pin, lockfile entry, and the .NET check task. - "/Dockerfile.nanoserver" # Disables the tool for an image whose build does not need it. - "/Dockerfile.windows" # Same. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)roslynator" message: >- @@ -515,7 +551,8 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the format/check/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. - "/ruff.toml" # Its own config, kept at the root so editors discover it. - "/.editorconfig" # Records that the formatter owns docstring and doc-comment reflow. - "/config/dprint.jsonc" # Skips the Python files this tool formats instead. @@ -523,6 +560,8 @@ rules: - "/config/semgrep/no-line-length-in-comment.yaml" # Names the configs that hold the line-length value. - "/config/openapi-python-client.yaml" # Turns off the generator's own hooks, which a task already runs. - "/generated/**" # Generator-owned output, carrying whatever the generator wrote. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. + - "/utilities/int-gen/src/checks.rs" # Names the root config the tool finds without being told to. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: '(?i)\bruff\b' message: >- @@ -536,10 +575,12 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/config/ryl.yaml" # Its own config. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. - "/config/conftest/policy/mise/mise.rego" # Allowlists it as a tool with no prebuilt at some triple. - "/config/taplo/mise-cargo-backend-allowlist.schema.json" # The same allowlist, as a TOML schema enum. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: '(?i)\bryl\b' message: >- @@ -552,7 +593,7 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the scan/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.semgrepignore" # Its own ignore file, whose comments explain what the tool's default skips. - "/.codacy.yaml" # Excludes this ruleset, which its own copy of the tool misparses. - "/.github/workflows/test.yaml" # Notes the Windows lane's handling of the tool. @@ -561,6 +602,8 @@ rules: - "/config/generated-trees.toml" # Maps each generated tree onto the exclusion key this tool needs. - "/config/conftest/policy/generated_trees/generated_trees.rego" # Enforces that mapping. - "/config/conftest/policy/generated_trees/generated_trees_test.rego" # Unit tests for it. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. + - "/utilities/int-gen/src/checks.rs" # Names the ignore file the tool reads without being told to. pattern-regex: "(?i)semgrep" message: >- Do not name this tool outside its own ruleset and the configs that scope it. A `nosemgrep` marker is the @@ -573,7 +616,7 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, the task-body extractor, and the `# shellcheck disable=` pragmas in task bodies. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/.github/workflows/docker-linux.yaml" # Carries those pragmas in its run bodies. - "/.github/workflows/docker-windows.yaml" # Same. - "/.github/workflows/upstream-cache.yaml" # Same. @@ -582,6 +625,7 @@ rules: - "/config/hadolint.yaml" # Ignores a code raised by the copy embedded in the Dockerfile linter. - "/utilities/cli/src/deployment_types/scenario_image.rs" # Emits those pragmas into generated images. - "/verification/**" # The generated images holding them. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)shellcheck" message: >- @@ -595,7 +639,8 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the extractor that formats mise task bodies with it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)shfmt" message: >- @@ -608,10 +653,12 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the format/check tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/config/taplo.toml" # Its own config. - "/config/taplo/**" # The JSON schemas it lints TOML against. - "/config/conftest/policy/mise/mise.rego" # Allowlists it as a tool with no prebuilt at some triple. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. + - "/utilities/int-gen/src/checks.rs" # Names the config an `[env]` variable hands the tool. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)taplo" message: >- @@ -628,6 +675,7 @@ rules: - "/README.md" # Tells a contributor which checks validate the generated manifests. - "/.codacy.yaml" # Names the manifest checks Codacy defers to, as its exclusion rationale. - "/config/trivyignore.yaml" # Its own ignore file, where each entry states why the finding is an artifact. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)trivy" message: >- @@ -640,7 +688,8 @@ rules: paths: exclude: - "/.mise/**" # Tool pin and the check/fix tasks. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)typos-(check|fix)" message: >- @@ -654,11 +703,13 @@ rules: paths: exclude: - "/.mise/**" # Tool pin, lockfile entry, and the task that runs it. - - "/CLAUDE.md" # Documents which checks an agent runs for which file types. + - "/AGENTS.md" # Documents which checks an agent runs for which file types. - "/config/zizmor.yaml" # Its own config. + - "/config/conftest/policy/mise_lock/mise_lock.rego" # Allowlists it as a tool locking a glibc build. - "/.codacy.yaml" # Names the workflow linters Codacy defers to, as its exclusion rationale. - "/.github/actions/install-mise/action.yaml" # A `zizmor: ignore[...]` pragma, which only works spelled out. - "/.github/workflows/upstream-cache.yaml" # The same pragma. + - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: "(?i)zizmor" message: >- diff --git a/config/semgrep/no-curl-pipe.yaml b/config/semgrep/no-curl-pipe.yaml index cbb77cf9..3df6747f 100644 --- a/config/semgrep/no-curl-pipe.yaml +++ b/config/semgrep/no-curl-pipe.yaml @@ -14,6 +14,8 @@ rules: # rule flags its own definition however the message is worded. Scoped to this one file rather than the # whole rules directory, so every other rule here stays covered. - "/config/semgrep/no-curl-pipe.yaml" + # The generated catalogue of every check reproduces this rule's message, so it matches for the same reason. + - "/CHECKS.md" # Match a `curl` whose output is piped anywhere at all. # `[^|\n]*` keeps the match inside one command rather than reaching a later, unrelated pipe. # There is deliberately no exemption for `| tar`. One was tried and removed, because `tar` can be told to diff --git a/config/semgrep/no-task-name-mentions.yaml b/config/semgrep/no-task-name-mentions.yaml index 5352a83d..5f74c254 100644 --- a/config/semgrep/no-task-name-mentions.yaml +++ b/config/semgrep/no-task-name-mentions.yaml @@ -23,7 +23,7 @@ rules: exclude: - "/.mise/**" # Where the tasks are defined and depend on each other. - "/.github/**" # Runs them, and fails a PR on drift between their output and what is committed. - - "/CLAUDE.md" # Documents which generator to run after changing a source of truth. + - "/AGENTS.md" # Documents which generator to run after changing a source of truth. - "/README.md" # Same, for a contributor. - "**/README.md" # A generated tree's README names the command that rewrites it. - "/generated/**" # Generator-owned output, whose headers name the task that wrote it. @@ -37,11 +37,13 @@ rules: - "/config/typos.toml" # A vendored word that cannot be corrected here, only where it is fetched from. - "/services/ws-wasi-runner/src/bindings.rs" # Generated; the header is how a reader rebuilds it. - "/utilities/int-gen/src/**" # The generator itself, whose entry points are these tasks. + - "/CHECKS.md" # The generated catalogue of every check, which names each task by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: >- (?ix)(?- Do not name a generator task outside the generator, the files it writes, and the docs that say when to run it. A generated file's own header is where the name belongs, because a reader who must not hand-edit the @@ -55,7 +57,7 @@ rules: exclude: - "/.mise/**" # Where the tasks are defined and depend on each other. - "/.github/**" # Builds the modules on CI. - - "/CLAUDE.md" # Documents how to build one module rather than the whole set. + - "/AGENTS.md" # Documents how to build one module rather than the whole set. - "/README.md" # Tells a contributor how to build a module. - "**/README.md" # A module's own README names the command that builds it. - "/Dockerfile" # Builds the modules into the image. @@ -70,6 +72,7 @@ rules: - "/services/ws-wasi-runner/tests/modules.rs" - "/services/ws-wasi-runner/tests/otel_propagation.rs" - "/services/ws-web-runner/tests/modules.rs" + - "/CHECKS.md" # The generated catalogue of every check, which names each task by design. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. pattern-regex: >- (?ix)(?- (?ix)(?- (?ix)(?- (?ix)(?- (?ix)(?- (?ix)(?- TODOs are not allowed in this repo. diff --git a/config/semgrep/no-wget.yaml b/config/semgrep/no-wget.yaml index f7da4c86..802dd378 100644 --- a/config/semgrep/no-wget.yaml +++ b/config/semgrep/no-wget.yaml @@ -11,6 +11,8 @@ rules: # Naming the banned command is unavoidable in a rule that bans it, so the id, the message and the # pattern below would each be a finding. - "/config/semgrep/no-wget.yaml" + # The generated catalogue of every check reproduces this rule's message, so it matches for the same reason. + - "/CHECKS.md" pattern-regex: '\bwget\b' message: >- Use `curl` instead of `wget` for downloads in this repo. diff --git a/config/semgrep/sorted-lists.yaml b/config/semgrep/sorted-lists.yaml new file mode 100644 index 00000000..c7e6daa2 --- /dev/null +++ b/config/semgrep/sorted-lists.yaml @@ -0,0 +1,128 @@ +rules: + - id: sorted-lists + languages: [generic] + paths: + include: + - "*.rs" + exclude: + # Generated trees; their contents are not ours to shape. + - "/generated/**" + - "/services/ws-wasi-runner/src/bindings.rs" + # Flag an adjacent pair that is out of ASCII order in a derive list, a lint list, or a cfg feature list. + # Each `pattern-either` arm pairs a regex that captures two adjacent keys as `$PAIR` with one that confines it to + # its list -- semgrep keeps a match only where every positive pattern covers it -- and the one comparator below + # then judges every arm's pairs. The arms live in one rule because a comparator shared through a YAML anchor + # fails semgrep-core's rule validation with "Expected a string value for regex". + # + # Derives: two adjacent derive paths, compared as written, inside a `#[derive(...)]` bare or under `cfg_attr`. + # Lints: two adjacent lint paths, so every `clippy::` lint sorts together. The later item must be followed by `,` + # or `)`, which keeps `reason` out of the comparison, and the context stops at the first `"` or `=` so words + # inside the reason string never form a pair. Features: adjacent `feature = "..."` predicates in one + # `any(...)` / `all(...)`, by feature name; the context covers only the list's own level, so a predicate nested + # in `not(...)` is never paired with its neighbours. + # + # The comparator matches when the first key of `$PAIR` sorts AFTER the second. A key is a run of `[-\w:]`, so a + # path such as `clippy::unwrap_used` is one key: the first key leads `$PAIR`, the second trails it, and the + # separator holds at least one other character. semgrep's `metavariable-comparison` orders only numbers, so the + # comparison is spelt out in PCRE: `([-\w:]*)` captures the keys' common prefix, then each branch names the first + # character at which the first key differs and requires the second to carry a lower character there via + # `\1[...]`. The first branch is the remaining case, a second key that is a proper prefix of the first. The + # branch lines are mechanical -- each class is every key character below the branch's own -- which is also why + # there is no autofix: semgrep cannot sort a list in a `fix:` template. + patterns: + - pattern-either: + - patterns: + - pattern-regex: |- + (?x) (? (?:::)? (?:\w+::)* \w+ \s*,\s*+ (?:::)? (?:\w+::)* \w+ ) (?![\w:]) ) + (?:::)? \w+ + - pattern-regex: '#\[\s*(?:cfg_attr\s*\([^\]]*?,\s*)?derive\s*\([^()\]]*' + - patterns: + - pattern-regex: '(?(?:\w+::)*\w+\s*,\s*+(?:\w+::)*\w+)(?![\w:])\s*[,)])\w+' + - pattern-regex: '#!?\[\s*(?:cfg_attr\s*\([^\]]*?,\s*)?(?:allow|expect)\s*\([^"=()\]]*' + - patterns: + - pattern-regex: 'feature\s*=\s*"(?=(?P[-\w]+"\s*,\s*+feature\s*=\s*"[-\w]+)")[-\w]+' + - pattern-regex: '\b(?:all|any)\s*\([^()]*' + - metavariable-regex: + metavariable: $PAIR + regex: |- + (?xs) + ^ ([-\w:]*) + (?: + [-\w:]+ [^-\w:] (?:.*[^-\w:])? \1 $ + | 0 (?&rest) \1 [-] (?&end) + | 1 (?&rest) \1 [-0] (?&end) + | 2 (?&rest) \1 [-01] (?&end) + | 3 (?&rest) \1 [-0-2] (?&end) + | 4 (?&rest) \1 [-0-3] (?&end) + | 5 (?&rest) \1 [-0-4] (?&end) + | 6 (?&rest) \1 [-0-5] (?&end) + | 7 (?&rest) \1 [-0-6] (?&end) + | 8 (?&rest) \1 [-0-7] (?&end) + | 9 (?&rest) \1 [-0-8] (?&end) + | : (?&rest) \1 [-0-9] (?&end) + | A (?&rest) \1 [-0-9:] (?&end) + | B (?&rest) \1 [-0-9:A] (?&end) + | C (?&rest) \1 [-0-9:AB] (?&end) + | D (?&rest) \1 [-0-9:A-C] (?&end) + | E (?&rest) \1 [-0-9:A-D] (?&end) + | F (?&rest) \1 [-0-9:A-E] (?&end) + | G (?&rest) \1 [-0-9:A-F] (?&end) + | H (?&rest) \1 [-0-9:A-G] (?&end) + | I (?&rest) \1 [-0-9:A-H] (?&end) + | J (?&rest) \1 [-0-9:A-I] (?&end) + | K (?&rest) \1 [-0-9:A-J] (?&end) + | L (?&rest) \1 [-0-9:A-K] (?&end) + | M (?&rest) \1 [-0-9:A-L] (?&end) + | N (?&rest) \1 [-0-9:A-M] (?&end) + | O (?&rest) \1 [-0-9:A-N] (?&end) + | P (?&rest) \1 [-0-9:A-O] (?&end) + | Q (?&rest) \1 [-0-9:A-P] (?&end) + | R (?&rest) \1 [-0-9:A-Q] (?&end) + | S (?&rest) \1 [-0-9:A-R] (?&end) + | T (?&rest) \1 [-0-9:A-S] (?&end) + | U (?&rest) \1 [-0-9:A-T] (?&end) + | V (?&rest) \1 [-0-9:A-U] (?&end) + | W (?&rest) \1 [-0-9:A-V] (?&end) + | X (?&rest) \1 [-0-9:A-W] (?&end) + | Y (?&rest) \1 [-0-9:A-X] (?&end) + | Z (?&rest) \1 [-0-9:A-Y] (?&end) + | _ (?&rest) \1 [-0-9:A-Z] (?&end) + | a (?&rest) \1 [-0-9:A-Z_] (?&end) + | b (?&rest) \1 [-0-9:A-Z_a] (?&end) + | c (?&rest) \1 [-0-9:A-Z_ab] (?&end) + | d (?&rest) \1 [-0-9:A-Z_a-c] (?&end) + | e (?&rest) \1 [-0-9:A-Z_a-d] (?&end) + | f (?&rest) \1 [-0-9:A-Z_a-e] (?&end) + | g (?&rest) \1 [-0-9:A-Z_a-f] (?&end) + | h (?&rest) \1 [-0-9:A-Z_a-g] (?&end) + | i (?&rest) \1 [-0-9:A-Z_a-h] (?&end) + | j (?&rest) \1 [-0-9:A-Z_a-i] (?&end) + | k (?&rest) \1 [-0-9:A-Z_a-j] (?&end) + | l (?&rest) \1 [-0-9:A-Z_a-k] (?&end) + | m (?&rest) \1 [-0-9:A-Z_a-l] (?&end) + | n (?&rest) \1 [-0-9:A-Z_a-m] (?&end) + | o (?&rest) \1 [-0-9:A-Z_a-n] (?&end) + | p (?&rest) \1 [-0-9:A-Z_a-o] (?&end) + | q (?&rest) \1 [-0-9:A-Z_a-p] (?&end) + | r (?&rest) \1 [-0-9:A-Z_a-q] (?&end) + | s (?&rest) \1 [-0-9:A-Z_a-r] (?&end) + | t (?&rest) \1 [-0-9:A-Z_a-s] (?&end) + | u (?&rest) \1 [-0-9:A-Z_a-t] (?&end) + | v (?&rest) \1 [-0-9:A-Z_a-u] (?&end) + | w (?&rest) \1 [-0-9:A-Z_a-v] (?&end) + | x (?&rest) \1 [-0-9:A-Z_a-w] (?&end) + | y (?&rest) \1 [-0-9:A-Z_a-x] (?&end) + | z (?&rest) \1 [-0-9:A-Z_a-y] (?&end) + ) + (?(DEFINE) + (? [-\w:]* [^-\w:] (?:.*[^-\w:])? ) + (? [-\w:]* $ ) + ) + message: >- + Keep this list in ASCII order of each item as written: the traits in a `#[derive(...)]` (`Clone, Debug, + Deserialize, Eq, PartialEq, Serialize`, a qualified `strum::EnumIter` after every bare name), the lints in an + `#[expect(...)]` before its `reason` (`clippy::` lints together, rustc lints after them), and adjacent + `feature = "..."` predicates in an `any(...)` / `all(...)`. A sorted list reads the same everywhere, makes a + missing or duplicated entry easy to spot, and keeps a diff to the one entry that changed. + severity: ERROR diff --git a/config/taplo.toml b/config/taplo.toml index e6422b5f..b1a4b25c 100644 --- a/config/taplo.toml +++ b/config/taplo.toml @@ -2,9 +2,9 @@ # Both are gitignored, but taplo's baseline `taplo lint` / `format` don't honour .gitignore: `target/` holds # scratch + build artifacts (and auto-associates any stray `Cargo.toml` with the SchemaStore Cargo schema), # and `data/` holds external upstream repo clones whose TOML files we must never reformat. target/ is also -# CLAUDE.md's scratch area, so scratch TOML is skipped here too -- to lint or test a scratch TOML, pipe it +# AGENTS.md's scratch area, so scratch TOML is skipped here too -- to lint or test a scratch TOML, pipe it # through `taplo format -` / `taplo lint -` (stdin has no path to exclude). -exclude = ["data/**", "target/**"] +exclude = ["**/node_modules/**", "data/**", "target/**"] [formatting] column_width = 120 diff --git a/generated/zig-rest/src/et_rest_client.zig b/generated/zig-rest/src/et_rest_client.zig index 50b22472..a3fd0866 100644 --- a/generated/zig-rest/src/et_rest_client.zig +++ b/generated/zig-rest/src/et_rest_client.zig @@ -1,23 +1,16 @@ // -// This code was generated by openapi2zig 0.4.2 (ac9e5bf) +// This code was generated by openapi2zig 0.5.6 (42c672b) // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated +// Checksum: 3e1a49aa14019014 // const std = @import("std"); -/////////////////////////////////////////// -// Generated Zig structures from OpenAPI -/////////////////////////////////////////// - pub const HealthResponse = struct { status: []const u8, service: []const u8, }; -/////////////////////////////////////////// -// Generated Zig API client from OpenAPI -/////////////////////////////////////////// - pub fn Owned(comptime T: type) type { return struct { allocator: std.mem.Allocator, @@ -84,6 +77,15 @@ pub const Client = struct { default_headers: []const std.http.Header = &.{}, http_observer: ?HttpObserver = null, + /// Optional predicate polled while reading a streaming response body. + /// When it returns true, a successfully started background watcher interrupts + /// a blocked SSE socket read within about 10 ms and the stream exits with + /// error.Cancelled. A CancelableReader also checks the predicate at every read + /// boundary. If watcher startup fails, cancellation remains read-boundary only. + /// Point it at an app-level cancel flag; it composes with a CancellationToken. + /// When null (default), no watcher thread is spawned. + cancel_check: ?*const fn () bool = null, + pub fn init(allocator: std.mem.Allocator, io: std.Io, api_key: []const u8) Client { return .{ .allocator = allocator, @@ -142,10 +144,57 @@ fn appendQueryParam(writer: *std.Io.Writer, first_query: *bool, name: []const u8 try writeQueryValue(writer, value); } +/// Serializes an `in: header` parameter value to an owned string. Reuses +/// the same primitive-type coverage as query parameters (string, integer, +/// float, boolean, enum). The caller frees the returned slice. +fn formatHeaderValue(allocator: std.mem.Allocator, value: anytype) ![]u8 { + const T = @TypeOf(value); + return switch (@typeInfo(T)) { + .pointer => |ptr| blk: { + if (ptr.size == .slice and ptr.child == u8) { + break :blk try allocator.dupe(u8, value); + } + @compileError("OpenAPI header values must be strings, numbers, booleans, or enums"); + }, + .@"enum" => try allocator.dupe(u8, @tagName(value)), + .int, .comptime_int, .float, .comptime_float, .bool => try std.fmt.allocPrint(allocator, "{}", .{value}), + else => @compileError("OpenAPI header values must be strings, numbers, booleans, or enums"), + }; +} + +/// Appends `value` under `name`, replacing (case-insensitively) any +/// existing header of the same name. Used so a declared operation header +/// parameter always wins over an equal-named client default header while +/// emitting exactly one header on the wire. +fn appendOrReplaceHeader(allocator: std.mem.Allocator, headers: *std.ArrayList(std.http.Header), name: []const u8, value: []const u8) !void { + var i: usize = 0; + while (i < headers.items.len) { + if (std.ascii.eqlIgnoreCase(headers.items[i].name, name)) { + _ = headers.orderedRemove(i); + } else { + i += 1; + } + } + try headers.append(allocator, .{ .name = name, .value = value }); +} + pub fn requestRaw(client: *Client, method: std.http.Method, url: []const u8, payload: ?[]const u8) !RawResponse { return requestRawWithContentType(client, method, url, payload, "application/json"); } +pub fn requestRawWithExtraHeaders(client: *Client, method: std.http.Method, url: []const u8, payload: ?[]const u8, extra_headers: []const std.http.Header) !RawResponse { + return requestRawWithContentTypeAndExtraHeaders(client, method, url, payload, "application/json", extra_headers); +} + +pub fn requestRawWithContentTypeAndExtraHeaders(client: *Client, method: std.http.Method, url: []const u8, payload: ?[]const u8, content_type_value: []const u8, extra_headers: []const std.http.Header) !RawResponse { + // Replaced by et-int-gen: delegate to the rewritten `requestRawWithContentType`, which dispatches via the + // host JS shim instead of `std.http.Client.fetch`. Every per-operation wrapper that declares headers funnels + // through here. The host import carries no request headers, so `extra_headers` is dropped there exactly as + // the client's default headers are. + _ = extra_headers; + return requestRawWithContentType(client, method, url, payload, content_type_value); +} + pub fn requestRawWithContentType(client: *Client, method: std.http.Method, url: []const u8, payload: ?[]const u8, content_type_value: []const u8) !RawResponse { // Replaced by et-int-gen: dispatch via the host JS shim instead of // `std.http.Client.fetch`, which can't reach the network from @@ -211,107 +260,11 @@ pub fn getJsonResult(comptime T: type, client: *Client, path: []const u8) !ApiRe pub fn postJsonResult(comptime T: type, client: *Client, path: []const u8, payload: anytype) !ApiResult(T) { return parseRawResponse(T, try postJsonRaw(client, path, payload)); } -fn stringifyStreamRequest(allocator: std.mem.Allocator, requestBody: anytype) ![]u8 { - var buf: std.Io.Writer.Allocating = .init(allocator); - defer buf.deinit(); - try std.json.Stringify.value(requestBody, .{ .emit_null_optional_fields = false }, &buf.writer); - - var parsed = try std.json.parseFromSlice(std.json.Value, allocator, buf.written(), .{ .ignore_unknown_fields = true }); - defer parsed.deinit(); - - if (parsed.value == .object) { - try parsed.value.object.put(parsed.arena.allocator(), "stream", .{ .bool = true }); - } - - var out: std.Io.Writer.Allocating = .init(allocator); - errdefer out.deinit(); - try std.json.Stringify.value(parsed.value, .{ .emit_null_optional_fields = false }, &out.writer); - return try out.toOwnedSlice(); -} - -fn streamJsonTyped(comptime T: type, client: *Client, path: []const u8, requestBody: anytype, callback: anytype, cancellation_token: ?*CancellationToken) !void { - const Callback = @TypeOf(callback.*); - var typed_callback: TypedSseCallback(T, Callback) = .{ .allocator = client.allocator, .callback = callback }; - try streamJson(client, path, requestBody, &typed_callback, cancellation_token); -} - -fn streamJson(client: *Client, path: []const u8, requestBody: anytype, callback: anytype, cancellation_token: ?*CancellationToken) !void { - const allocator = client.allocator; - const payload = try stringifyStreamRequest(allocator, requestBody); - defer allocator.free(payload); - - var headers = std.ArrayList(std.http.Header).empty; - defer headers.deinit(allocator); - const auth_header = try appendClientHeaders(allocator, &headers, client, "application/json", "text/event-stream"); - defer if (auth_header) |value| allocator.free(value); - - const url = try std.fmt.allocPrint(allocator, "{s}{s}", .{ client.base_url, path }); - defer allocator.free(url); - - if (client.http_observer) |obs| { - if (obs.onRequest) |cb| cb(obs.ctx, .POST, url, headers.items, payload); - } - - const uri = try std.Uri.parse(url); - try checkCancellation(cancellation_token); - - const start = std.Io.Clock.awake.now(client.io); - var req = client.http.request(.POST, uri, .{ - .redirect_behavior = .unhandled, - .headers = .{ .accept_encoding = .{ .override = "identity" } }, - .extra_headers = headers.items, - }) catch |err| { - if (client.http_observer) |obs| { - if (obs.onError) |cb| cb(obs.ctx, .POST, url, @errorName(err)); - } - return err; - }; - defer req.deinit(); - - req.transfer_encoding = .{ .content_length = payload.len }; - var request_body = try req.sendBodyUnflushed(&.{}); - try request_body.writer.writeAll(payload); - try request_body.end(); - try req.connection.?.flush(); - try checkCancellation(cancellation_token); - - var response = req.receiveHead(&.{}) catch |err| { - if (client.http_observer) |obs| { - if (obs.onError) |cb| cb(obs.ctx, .POST, url, @errorName(err)); - } - return err; - }; - const elapsed_ns = @as(u64, @intCast(start.untilNow(client.io, .awake).nanoseconds)); - if (response.head.status.class() != .success) { - if (client.http_observer) |obs| { - if (obs.onResponse) |cb| cb(obs.ctx, .POST, url, response.head.status, &.{}, "", elapsed_ns); - } - return error.ResponseError; - } - - if (client.http_observer) |obs| { - if (obs.onResponse) |cb| cb(obs.ctx, .POST, url, response.head.status, &.{}, "", elapsed_ns); - } - - var transfer_buffer: [8 * 1024]u8 = undefined; - const reader = response.reader(&transfer_buffer); - parseSseReader(allocator, reader, callback, cancellation_token) catch |err| switch (err) { - error.ReadFailed => return response.bodyErr() orelse err, - else => return err, - }; -} - -fn appendClientHeaders(allocator: std.mem.Allocator, headers: *std.ArrayList(std.http.Header), client: *Client, content_type: ?[]const u8, accept: []const u8) !?[]u8 { +fn appendClientHeaders(allocator: std.mem.Allocator, headers: *std.ArrayList(std.http.Header), client: *Client, content_type: ?[]const u8, accept: []const u8) !void { if (content_type) |ct| { try headers.append(allocator, .{ .name = "Content-Type", .value = ct }); } try headers.append(allocator, .{ .name = "Accept", .value = accept }); - - var auth_header: ?[]u8 = null; - if (client.api_key.len > 0) { - auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key}); - try headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? }); - } if (client.organization) |organization| { try headers.append(allocator, .{ .name = "OpenAI-Organization", .value = organization }); } @@ -321,7 +274,6 @@ fn appendClientHeaders(allocator: std.mem.Allocator, headers: *std.ArrayList(std for (client.default_headers) |header| { try headers.append(allocator, header); } - return auth_header; } pub const CancellationToken = struct { @@ -346,6 +298,46 @@ fn checkCancellation(token: ?*CancellationToken) !void { } } +/// Wraps an underlying reader and checks an optional cancel predicate before +/// every read of the underlying reader. When the predicate returns true, the +/// read fails with error.ReadFailed; callers translate that into +/// error.Cancelled. Cancellation is only observed at read boundaries: a read +/// already blocked inside the underlying reader (e.g. waiting for the next SSE +/// chunk on the socket) is not aborted until that read returns. +pub const CancelableReader = struct { + inner: *std.Io.Reader, + reader: std.Io.Reader, + should_cancel: ?*const fn () bool, + + pub fn init(inner: *std.Io.Reader, buffer: []u8, should_cancel: ?*const fn () bool) CancelableReader { + return .{ + .inner = inner, + .reader = .{ + .buffer = buffer, + .seek = 0, + .end = 0, + .vtable = &vtable, + }, + .should_cancel = should_cancel, + }; + } + + const vtable: std.Io.Reader.VTable = .{ + .stream = stream, + .discard = std.Io.Reader.defaultDiscard, + .readVec = std.Io.Reader.defaultReadVec, + .rebase = std.Io.Reader.defaultRebase, + }; + + fn stream(ctx: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + const self: *CancelableReader = @fieldParentPtr("reader", ctx); + if (self.should_cancel) |pred| { + if (pred()) return error.ReadFailed; + } + return self.inner.stream(w, limit); + } +}; + pub fn parseSseBytes(allocator: std.mem.Allocator, bytes: []const u8, callback: anytype, cancellation_token: ?*CancellationToken) !void { var reader: std.Io.Reader = .fixed(bytes); try parseSseReader(allocator, &reader, callback, cancellation_token); @@ -468,7 +460,21 @@ pub fn list_modules_handlerRaw(client: *Client) !RawResponse { try uri_buf.writer.print("{s}/modules/", .{client.base_url}); const payload: ?[]const u8 = null; - return requestRaw(client, std.http.Method.GET, uri_buf.written(), payload); + var operation_headers = std.ArrayList(std.http.Header).empty; + defer operation_headers.deinit(allocator); + var operation_header_values = std.ArrayList([]u8).empty; + defer { + for (operation_header_values.items) |item| allocator.free(item); + operation_header_values.deinit(allocator); + } + var auth_header: ?[]u8 = null; + defer if (auth_header) |value| allocator.free(value); + if (client.api_key.len > 0) { + auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key}); + try operation_headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? }); + } + + return requestRawWithExtraHeaders(client, std.http.Method.GET, uri_buf.written(), payload, operation_headers.items); } pub fn list_modules_handlerResult(client: *Client) !ApiResult([]const std.json.Value) { @@ -505,7 +511,21 @@ pub fn healthRaw(client: *Client) !RawResponse { try uri_buf.writer.print("{s}/health", .{client.base_url}); const payload: ?[]const u8 = null; - return requestRaw(client, std.http.Method.GET, uri_buf.written(), payload); + var operation_headers = std.ArrayList(std.http.Header).empty; + defer operation_headers.deinit(allocator); + var operation_header_values = std.ArrayList([]u8).empty; + defer { + for (operation_header_values.items) |item| allocator.free(item); + operation_header_values.deinit(allocator); + } + var auth_header: ?[]u8 = null; + defer if (auth_header) |value| allocator.free(value); + if (client.api_key.len > 0) { + auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key}); + try operation_headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? }); + } + + return requestRawWithExtraHeaders(client, std.http.Method.GET, uri_buf.written(), payload, operation_headers.items); } pub fn healthResult(client: *Client) !ApiResult(HealthResponse) { @@ -529,7 +549,21 @@ pub fn get_fileRaw(client: *Client, agent_id: []const u8, filename: []const u8) try uri_buf.writer.print("{s}/storage/{s}/{s}", .{ client.base_url, agent_id, filename }); const payload: ?[]const u8 = null; - return requestRaw(client, std.http.Method.GET, uri_buf.written(), payload); + var operation_headers = std.ArrayList(std.http.Header).empty; + defer operation_headers.deinit(allocator); + var operation_header_values = std.ArrayList([]u8).empty; + defer { + for (operation_header_values.items) |item| allocator.free(item); + operation_header_values.deinit(allocator); + } + var auth_header: ?[]u8 = null; + defer if (auth_header) |value| allocator.free(value); + if (client.api_key.len > 0) { + auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key}); + try operation_headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? }); + } + + return requestRawWithExtraHeaders(client, std.http.Method.GET, uri_buf.written(), payload, operation_headers.items); } ///////////////// @@ -579,7 +613,21 @@ pub fn head_fileRaw(client: *Client, agent_id: []const u8, filename: []const u8) try uri_buf.writer.print("{s}/storage/{s}/{s}", .{ client.base_url, agent_id, filename }); const payload: ?[]const u8 = null; - return requestRaw(client, std.http.Method.HEAD, uri_buf.written(), payload); + var operation_headers = std.ArrayList(std.http.Header).empty; + defer operation_headers.deinit(allocator); + var operation_header_values = std.ArrayList([]u8).empty; + defer { + for (operation_header_values.items) |item| allocator.free(item); + operation_header_values.deinit(allocator); + } + var auth_header: ?[]u8 = null; + defer if (auth_header) |value| allocator.free(value); + if (client.api_key.len > 0) { + auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key}); + try operation_headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? }); + } + + return requestRawWithExtraHeaders(client, std.http.Method.HEAD, uri_buf.written(), payload, operation_headers.items); } ///////////////// @@ -608,7 +656,21 @@ pub fn get_module_fileRaw(client: *Client, name: []const u8, path: []const u8) ! try uri_buf.writer.print("{s}/modules/{s}/{s}", .{ client.base_url, name, path }); const payload: ?[]const u8 = null; - return requestRaw(client, std.http.Method.GET, uri_buf.written(), payload); + var operation_headers = std.ArrayList(std.http.Header).empty; + defer operation_headers.deinit(allocator); + var operation_header_values = std.ArrayList([]u8).empty; + defer { + for (operation_header_values.items) |item| allocator.free(item); + operation_header_values.deinit(allocator); + } + var auth_header: ?[]u8 = null; + defer if (auth_header) |value| allocator.free(value); + if (client.api_key.len > 0) { + auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{client.api_key}); + try operation_headers.append(allocator, .{ .name = "Authorization", .value = auth_header.? }); + } + + return requestRawWithExtraHeaders(client, std.http.Method.GET, uri_buf.written(), payload, operation_headers.items); } /// Host-provided HTTP transport. The JS shim implements this against diff --git a/libs/edge-toolkit/src/config.rs b/libs/edge-toolkit/src/config.rs index f6ec0863..a19a427f 100644 --- a/libs/edge-toolkit/src/config.rs +++ b/libs/edge-toolkit/src/config.rs @@ -234,7 +234,7 @@ pub fn mise_is_available() -> bool { /// `strum::IntoStaticStr` derives the canonical lowercase name used in /// `MISE_ENV` and the config filename; `strum::EnumIter` enumerates all /// variants in declaration order. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::IntoStaticStr, strum::EnumIter)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, strum::EnumIter, strum::IntoStaticStr)] #[strum(serialize_all = "lowercase")] #[non_exhaustive] pub enum Language { diff --git a/libs/edge-toolkit/src/ws.rs b/libs/edge-toolkit/src/ws.rs index 1198bcfe..3257d441 100644 --- a/libs/edge-toolkit/src/ws.rs +++ b/libs/edge-toolkit/src/ws.rs @@ -42,7 +42,7 @@ fn byte_array_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { clippy::exhaustive_enums, reason = "wire protocol enum: variants exhaustively describe the JSON shape, downstream matches are exhaustive" )] -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum ConnectStatus { @@ -54,7 +54,7 @@ pub enum ConnectStatus { clippy::exhaustive_enums, reason = "wire protocol enum: variants exhaustively describe the JSON shape, downstream matches are exhaustive" )] -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum MessageDeliveryStatus { @@ -68,7 +68,7 @@ pub enum MessageDeliveryStatus { clippy::exhaustive_enums, reason = "wire protocol enum: variants exhaustively describe the JSON shape, downstream matches are exhaustive" )] -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum MessageScope { @@ -80,7 +80,7 @@ pub enum MessageScope { clippy::exhaustive_enums, reason = "wire protocol enum: variants exhaustively describe the JSON shape, downstream matches are exhaustive" )] -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))] #[serde(rename_all = "snake_case")] pub enum AgentConnectionState { @@ -88,7 +88,7 @@ pub enum AgentConnectionState { Disconnected, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[non_exhaustive] #[cfg_attr(feature = "schema-export", derive(schemars::JsonSchema))] pub struct AgentSummary { @@ -129,10 +129,10 @@ fn has_et_prefix(text: &str) -> bool { clippy::exhaustive_enums, reason = "wire protocol enum: variants exhaustively describe the JSON shape, downstream matches are exhaustive" )] -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr( feature = "schema-export", - derive(schemars::JsonSchema, asyncapi_rust::ToAsyncApiMessage) + derive(asyncapi_rust::ToAsyncApiMessage, schemars::JsonSchema) )] #[serde(tag = "type")] pub enum ClientMessage { @@ -217,10 +217,10 @@ impl ClientMessage { clippy::exhaustive_enums, reason = "wire protocol enum: variants exhaustively describe the JSON shape, downstream matches are exhaustive" )] -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr( feature = "schema-export", - derive(schemars::JsonSchema, asyncapi_rust::ToAsyncApiMessage) + derive(asyncapi_rust::ToAsyncApiMessage, schemars::JsonSchema) )] #[serde(tag = "type")] pub enum ServerMessage { diff --git a/libs/edge-toolkit/src/ws_server.rs b/libs/edge-toolkit/src/ws_server.rs index 395d2298..45f6dd03 100644 --- a/libs/edge-toolkit/src/ws_server.rs +++ b/libs/edge-toolkit/src/ws_server.rs @@ -76,7 +76,7 @@ pub fn is_valid_agent_id(id: &str) -> bool { .all(|character| character.is_ascii_alphanumeric() || matches!(character, '.' | '_' | '-')) } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[non_exhaustive] pub struct PendingDirectMessage { pub message_id: String, @@ -85,7 +85,7 @@ pub struct PendingDirectMessage { pub message: serde_json::Value, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[non_exhaustive] pub struct AgentRecord { pub state: AgentConnectionState, @@ -132,14 +132,6 @@ impl AgentRegistry { } } -impl Default for AgentRegistry { - fn default() -> Self { - Self { - agents: Arc::new(Mutex::new(BTreeMap::new())), - } - } -} - impl AgentRegistry { pub fn load(path: &std::path::Path) -> Result { if !path.exists() { @@ -341,3 +333,11 @@ impl AgentRegistry { session } } + +impl Default for AgentRegistry { + fn default() -> Self { + Self { + agents: Arc::new(Mutex::new(BTreeMap::new())), + } + } +} diff --git a/libs/edge-toolkit/tests/pipx_site_packages.rs b/libs/edge-toolkit/tests/pipx_site_packages.rs index e6a966f6..5d65d85a 100644 --- a/libs/edge-toolkit/tests/pipx_site_packages.rs +++ b/libs/edge-toolkit/tests/pipx_site_packages.rs @@ -137,7 +137,10 @@ fn a_tool_list_that_is_not_json_yields_no_paths() { // `mise ls --current --json` answered with something unparsable -- an older mise, a wrapper that printed // a warning first, a truncated pipe. The runner must come away with an empty `sys.path` addition rather // than failing to start, so the interpreter still boots and only the mise-managed imports are missing. - assert!(edge_toolkit::config::site_packages_from_tool_list(b"mise: not a tool list").is_empty()); + assert_eq!( + edge_toolkit::config::site_packages_from_tool_list(b"mise: not a tool list"), + Vec::::new() + ); assert!( edge_toolkit::config::site_packages_from_tool_list(b"").is_empty(), "an empty body is not valid JSON either" diff --git a/libs/edge-toolkit/tests/staged_module_dirs.rs b/libs/edge-toolkit/tests/staged_module_dirs.rs index fcbd94c3..3dd92b82 100644 --- a/libs/edge-toolkit/tests/staged_module_dirs.rs +++ b/libs/edge-toolkit/tests/staged_module_dirs.rs @@ -21,7 +21,10 @@ fn staged_install(root: &TempDir, install: &str, package: &str) -> std::path::Pa fn a_tool_list_that_is_not_json_yields_no_directories() { // An older mise, a wrapper that printed a warning first, a truncated pipe. The hub has to come away with nothing // rather than fail to start, so it serves what it can and says what is missing. - assert!(staged_module_dirs_from_tool_list(b"mise: not a tool list").is_empty()); + assert_eq!( + staged_module_dirs_from_tool_list(b"mise: not a tool list"), + Vec::::new() + ); assert!( staged_module_dirs_from_tool_list(b"").is_empty(), "an empty body is not valid JSON either" @@ -32,8 +35,14 @@ fn a_tool_list_that_is_not_json_yields_no_directories() { fn a_listing_that_is_not_an_object_yields_no_directories() { // Valid JSON, wrong shape: mise answers with a map of tool id to versions, and anything else is a version of mise // this does not know how to read. - assert!(staged_module_dirs_from_tool_list(b"[]").is_empty()); - assert!(staged_module_dirs_from_tool_list(b"\"a string\"").is_empty()); + assert_eq!( + staged_module_dirs_from_tool_list(b"[]"), + Vec::::new() + ); + assert_eq!( + staged_module_dirs_from_tool_list(b"\"a string\""), + Vec::::new() + ); } #[test] @@ -81,7 +90,10 @@ fn an_entry_with_no_version_or_no_install_path_is_skipped() { "npm:et-ws-path-not-a-string": [{ "install_path": 42_i32 }], }); - assert!(staged_module_dirs_from_tool_list(&serde_json::to_vec(&tool_list).unwrap()).is_empty()); + assert_eq!( + staged_module_dirs_from_tool_list(&serde_json::to_vec(&tool_list).unwrap()), + Vec::::new() + ); } #[test] @@ -89,5 +101,8 @@ fn no_mise_to_ask_contributes_no_directories() { // The other half of the lookup: with no `mise` to run there is no listing to interpret, and a deployment that // staged nothing has to reach the same empty answer as one whose listing named nothing. An empty PATH hides the // binary from the spawn, and `with_empty_path` puts PATH back so sibling tests in this binary still find it. - assert!(et_test_helpers::with_empty_path(mise_staged_module_dirs).is_empty()); + assert_eq!( + et_test_helpers::with_empty_path(mise_staged_module_dirs), + Vec::::new() + ); } diff --git a/libs/test-helpers/src/lib.rs b/libs/test-helpers/src/lib.rs index b2ba3e26..0f73fc10 100644 --- a/libs/test-helpers/src/lib.rs +++ b/libs/test-helpers/src/lib.rs @@ -1,6 +1,6 @@ //! Low-dependency helpers shared across the workspace's integration tests. //! -//! Only genuinely reusable, low-dependency utilities belong here (see CLAUDE.md). Heavier or +//! Only genuinely reusable, low-dependency utilities belong here (see AGENTS.md). Heavier or //! domain-specific fixtures live in their own test-support crate instead -- e.g. `et-ws-test-server` //! (an in-process ws-server) or `et-test-otlp` (OTLP emit + capture-assertion support). #![expect( diff --git a/libs/ws-runner-common/src/config.rs b/libs/ws-runner-common/src/config.rs index 4d08c755..395e3ecd 100644 --- a/libs/ws-runner-common/src/config.rs +++ b/libs/ws-runner-common/src/config.rs @@ -31,7 +31,7 @@ macro_rules! runner_config { $vis:vis struct $name:ident { $($(#[$field_meta:meta])* $field_vis:vis $field:ident : $ty:ty),* $(,)? } ) => { $(#[$struct_meta])* - #[derive(Clone, Debug, ::serde::Deserialize)] + #[derive(::serde::Deserialize, Clone, Debug)] #[non_exhaustive] $vis struct $name { /// `RUNNER_*` settings (`RUNNER_MODULE`, `RUNNER_TIMEOUT`). diff --git a/services/ws-modules/except1/src/lib.rs b/services/ws-modules/except1/src/lib.rs index 66f8a385..0ebf95d8 100644 --- a/services/ws-modules/except1/src/lib.rs +++ b/services/ws-modules/except1/src/lib.rs @@ -27,7 +27,7 @@ pub fn init() { } /// Failure of [`checked_divide`]: the quotient is unrepresentable (zero divisor, or `i32::MIN / -1`). -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Eq, PartialEq)] struct DivideError; impl fmt::Display for DivideError { diff --git a/services/ws-modules/face-detection/src/test_face_detection.rs b/services/ws-modules/face-detection/src/test_face_detection.rs index a573ebdd..ba36dc16 100644 --- a/services/ws-modules/face-detection/src/test_face_detection.rs +++ b/services/ws-modules/face-detection/src/test_face_detection.rs @@ -1,8 +1,7 @@ #![cfg(test)] #![expect( - clippy::float_cmp, clippy::default_numeric_fallback, - reason = "test code: exact float comparisons and inline f64 fixtures are intentional" + reason = "test code: inline f64 fixtures are intentional" )] use super::*; @@ -78,7 +77,7 @@ fn nms_keeps_boxes_when_iou_equals_threshold() { #[test] fn softmax_handles_empty_equal_and_large_values() { - assert!(softmax(&[]).is_empty()); + assert_eq!(softmax(&[]), Vec::::new()); let equal = softmax(&[4.0, 4.0, 4.0, 4.0]); assert!(equal.iter().all(|value| (*value - 0.25).abs() < 1e-6)); diff --git a/services/ws-modules/har1/src/test_har1.rs b/services/ws-modules/har1/src/test_har1.rs index 2dd99834..1ef54ed8 100644 --- a/services/ws-modules/har1/src/test_har1.rs +++ b/services/ws-modules/har1/src/test_har1.rs @@ -1,8 +1,7 @@ #![cfg(test)] #![expect( - clippy::float_cmp, clippy::default_numeric_fallback, - reason = "test code: exact float comparisons and inline f64 sensor fixtures are intentional" + reason = "test code: inline f64 sensor fixtures are intentional" )] use super::*; @@ -41,7 +40,7 @@ fn flatten_samples_preserves_sample_order_and_feature_order() { fn flatten_samples_handles_empty_buffer() { let samples = VecDeque::new(); - assert!(flatten_samples(&samples).is_empty()); + assert_eq!(flatten_samples(&samples), Vec::::new()); } #[test] diff --git a/services/ws-modules/llm1/src/lib.rs b/services/ws-modules/llm1/src/lib.rs index 22ef51d3..c7bf8e83 100644 --- a/services/ws-modules/llm1/src/lib.rs +++ b/services/ws-modules/llm1/src/lib.rs @@ -52,7 +52,7 @@ thread_local! { } /// One chat turn as transformers.js wants it: a role and its content. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct Turn { pub role: String, diff --git a/services/ws-modules/pic-viewer/src/lib.rs b/services/ws-modules/pic-viewer/src/lib.rs index 129543ce..00882489 100644 --- a/services/ws-modules/pic-viewer/src/lib.rs +++ b/services/ws-modules/pic-viewer/src/lib.rs @@ -39,7 +39,7 @@ const MAX_RUNTIME_POLLS: u32 = 3_000; const CAPTURE_KIND: &str = "pyeye1_capture_stored"; /// One decoded capture announcement: who stored the image and the storage path to fetch it from. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct CaptureNotification { pub from_agent_id: String, diff --git a/services/ws-modules/zig-except1/src/exceptions.cpp b/services/ws-modules/zig-except1/src/exceptions.cpp index fa81077c..72bf8f41 100644 --- a/services/ws-modules/zig-except1/src/exceptions.cpp +++ b/services/ws-modules/zig-except1/src/exceptions.cpp @@ -91,8 +91,10 @@ struct MinimalTypeInfo { const void *vtable; const char *name; }; -// NOLINTNEXTLINE(bugprone-reserved-identifier, cert-dcl37-c, cert-dcl51-cpp) +// The `asm` here is a symbol label naming the libc++abi typeinfo, not inline assembly. +// NOLINTNEXTLINE(bugprone-reserved-identifier, cert-dcl37-c, cert-dcl51-cpp, portability-no-assembler) extern const MinimalTypeInfo int_type_info asm("_ZTIi"); +// NOLINTNEXTLINE(portability-no-assembler) -- defines the asm-labelled declaration above; no assembly is emitted. const MinimalTypeInfo int_type_info = {nullptr, "i"}; } // extern "C" @@ -103,6 +105,7 @@ namespace { // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) -- num/den are named, order-obvious division operands. int32_t checked_divide(int32_t num, int32_t den) { if (den == 0) { + // NOLINTNEXTLINE(bugprone-std-exception-baseclass) -- this runtime only provides typeinfo for `int` (_ZTIi). throw den; } return num / den; diff --git a/services/ws-pyo3-runner/Dockerfile b/services/ws-pyo3-runner/Dockerfile index b3a679d4..f1a20da7 100644 --- a/services/ws-pyo3-runner/Dockerfile +++ b/services/ws-pyo3-runner/Dockerfile @@ -49,7 +49,7 @@ EOF # no-curl-pipe rule bans. The release's SHASUMS256.txt covers every asset, so `--ignore-missing` checks exactly the # archive downloaded here. Pinned rather than taken from mise's apt repository, which carries only the newest # version: a floating mise writes lockfile entries an older CI mise then refuses to install. -ARG MISE_VERSION=v2026.9.0 +ARG MISE_VERSION=v2026.9.17 ARG TARGETARCH ENV MISE_VERSION=${MISE_VERSION} ENV TARGETARCH=${TARGETARCH} diff --git a/services/ws-pyo3-runner/src/hub_module.rs b/services/ws-pyo3-runner/src/hub_module.rs index 11bf0f39..2856fc8b 100644 --- a/services/ws-pyo3-runner/src/hub_module.rs +++ b/services/ws-pyo3-runner/src/hub_module.rs @@ -21,7 +21,7 @@ use crate::error::RunnerError; use crate::python::module_is_importable; /// A user module fetched from the hub, ready to be compiled. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] #[non_exhaustive] pub struct HubModule { /// Name the source is compiled under: the stem of the hub's `main` file. diff --git a/services/ws-pyo3-runner/src/lib.rs b/services/ws-pyo3-runner/src/lib.rs index c4caba3a..3f873eeb 100644 --- a/services/ws-pyo3-runner/src/lib.rs +++ b/services/ws-pyo3-runner/src/lib.rs @@ -12,8 +12,8 @@ //! See `python/echo.py` for the contract. #![expect( - clippy::single_call_fn, clippy::integer_division_remainder_used, + clippy::single_call_fn, reason = "register/drive/storage_worker/python_worker single-use; select! uses %; RunnerError: tungstenite::Error" )] diff --git a/services/ws-pyo3-runner/src/python.rs b/services/ws-pyo3-runner/src/python.rs index 4f7748f3..5c2c27f8 100644 --- a/services/ws-pyo3-runner/src/python.rs +++ b/services/ws-pyo3-runner/src/python.rs @@ -147,7 +147,7 @@ impl From for PyErr { /// One frame queued on the agent's outbound channel. /// /// The WS loop in `agent.rs` drains this and writes to the socket. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] #[non_exhaustive] pub enum OutboundFrame { Text(String), diff --git a/services/ws-server/src/main.rs b/services/ws-server/src/main.rs index a4eb9749..cf76ef3b 100644 --- a/services/ws-server/src/main.rs +++ b/services/ws-server/src/main.rs @@ -19,7 +19,7 @@ use tracing::{error, info, warn}; use tracing_actix_web::TracingLogger; use tracing_subscriber::{layer::SubscriberExt as _, util::SubscriberInitExt as _}; -#[derive(Parser, Debug)] +#[derive(Debug, Parser)] #[command(author, version, about, long_about = None)] struct Args { /// Path to agent registry YAML file. diff --git a/services/ws-wasi-runner/Dockerfile b/services/ws-wasi-runner/Dockerfile index b72e8491..3be539ad 100644 --- a/services/ws-wasi-runner/Dockerfile +++ b/services/ws-wasi-runner/Dockerfile @@ -38,7 +38,7 @@ EOF # no-curl-pipe rule bans. The release's SHASUMS256.txt covers every asset, so `--ignore-missing` checks exactly the # archive downloaded here. Pinned rather than taken from mise's apt repository, which carries only the newest # version: a floating mise writes lockfile entries an older CI mise then refuses to install. -ARG MISE_VERSION=v2026.9.0 +ARG MISE_VERSION=v2026.9.17 ARG TARGETARCH ENV MISE_VERSION=${MISE_VERSION} ENV TARGETARCH=${TARGETARCH} diff --git a/services/ws-wasi-runner/src/bindings.rs b/services/ws-wasi-runner/src/bindings.rs index 2e33476c..017a27bb 100644 --- a/services/ws-wasi-runner/src/bindings.rs +++ b/services/ws-wasi-runner/src/bindings.rs @@ -3,15 +3,15 @@ //! GENERATED by `mise run gen:wasmtime-bindings` (et-int-gen) from `generated/specs/wit`. Do not edit -- //! change the WIT or the generator instead, and regenerate. `gen-specs-check` fails when this drifts. #![allow( - unsafe_code, - unused_variables, clippy::all, + clippy::missing_const_for_fn, clippy::pedantic, clippy::restriction, - clippy::missing_const_for_fn, clippy::too_long_first_doc_paragraph, clippy::type_repetition_in_bounds, clippy::use_self, + unsafe_code, + unused_variables, reason = "generated from WIT by wasmtime-internal-wit-bindgen; we don't control its output. The group allows cover most of it, but Cargo's [lints] table passes -D per group on the command line, which an in-source group allow does not override -- so the four lints that still fire are named individually. diff --git a/services/ws-wasi-runner/src/host/mod.rs b/services/ws-wasi-runner/src/host/mod.rs index 43f2408c..608d6fc4 100644 --- a/services/ws-wasi-runner/src/host/mod.rs +++ b/services/ws-wasi-runner/src/host/mod.rs @@ -5,125 +5,13 @@ //! used by the storage interface, the ws connection state, and the wgpu device //! used by the gfx interface. -use std::sync::Arc; - -use tokio::sync::Mutex; -use wasmtime::component::ResourceTable; -// DirPerms/FilePerms are only used by the coverage `/cov` preopen below. -#[cfg(feature = "coverage")] -use wasmtime_wasi::{DirPerms, FilePerms}; -use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView}; - mod error; mod log; +mod state; pub mod wasi_keyvalue; pub mod wasi_nn; pub mod ws; pub use self::error::kv_not_implemented; +pub use self::state::HostState; pub use self::ws::WsBackend; - -#[non_exhaustive] -pub struct HostState { - pub wasi_ctx: WasiCtx, - pub resource_table: ResourceTable, - - /// WebSocket URL of the ws-server (e.g. `ws://localhost:8080/ws`). - pub ws_url: String, - - /// How long the host waits for `et-connect-ack`; `None` waits forever. - pub connect_ack_timeout: Option, - - /// Typed REST client for the ws-server (modules + per-agent storage). - /// Generated by `cargo-progenitor` from `generated/specs/rest.yaml`. - pub rest: et_rest_client::Client, - pub ws: Arc>>, - /// wasi-nn context. - /// Constructed once at startup so model loads + compute reuse the same `ort` session pool across calls. - pub wasi_nn_ctx: wasmtime_wasi_nn::wit::WasiNnCtx, - - /// wgpu instance backing `wasi:webgpu`. - /// One per store, created eagerly: adapter enumeration is what the guest's first call needs, and - /// `wasi-webgpu-wasmtime` borrows this handle rather than owning it. - pub wgpu_instance: Arc, -} - -impl HostState { - #[must_use] - #[cfg_attr( - not(feature = "coverage"), - expect( - unused_variables, - reason = "coverage gates the /cov preopen, compiled only under the feature" - ) - )] - pub fn new( - http_base: &str, - ws_url: String, - connect_ack_timeout: Option, - coverage: bool, - ) -> Self { - let mut builder = WasiCtxBuilder::new(); - #[expect(unused_results, reason = "WasiCtxBuilder setters return &mut Self")] - { - builder.inherit_stdio().inherit_env(); - } - // Instrumented guests write their minicov `.profraw` to `/cov`; map it to target/wasi-cov so the - // wasi-cov task finds it. Repo-root-anchored (not CWD) so it lands consistently under the test harness. - #[cfg(feature = "coverage")] - if coverage { - #[expect( - unused_results, - clippy::unwrap_used, - reason = "preopen setter returns &mut Self; a coverage-preopen failure is a misconfigured test run" - )] - { - let cov_dir = edge_toolkit::config::get_project_root().join("target/wasi-cov"); - fs_err::create_dir_all(&cov_dir).unwrap(); - builder - .preopened_dir(&cov_dir, "/cov", DirPerms::all(), FilePerms::all()) - .unwrap(); - } - } - let wasi_ctx = builder.build(); - - Self { - wasi_ctx, - resource_table: ResourceTable::new(), - ws_url, - connect_ack_timeout, - rest: et_rest_client::Client::new(http_base), - ws: Arc::new(Mutex::new(None)), - wasi_nn_ctx: wasi_nn::new_ctx(), - wgpu_instance: Arc::new(wgpu_core::global::Global::new( - "webgpu", - wgpu_types::InstanceDescriptor { - backends: wgpu_types::Backends::all(), - flags: wgpu_types::InstanceFlags::from_build_config(), - backend_options: wgpu_types::BackendOptions::default(), - memory_budget_thresholds: wgpu_types::MemoryBudgetThresholds::default(), - display: None, - }, - None, - )), - } - } -} - -impl wasi_webgpu_wasmtime::WasiWebGpuCtxView for HostState { - fn webgpu_ctx(&mut self) -> wasi_webgpu_wasmtime::WasiWebGpuCtx<'_> { - wasi_webgpu_wasmtime::WasiWebGpuCtx { - instance: &self.wgpu_instance, - table: &mut self.resource_table, - } - } -} - -impl WasiView for HostState { - fn ctx(&mut self) -> WasiCtxView<'_> { - WasiCtxView { - ctx: &mut self.wasi_ctx, - table: &mut self.resource_table, - } - } -} diff --git a/services/ws-wasi-runner/src/host/state.rs b/services/ws-wasi-runner/src/host/state.rs new file mode 100644 index 00000000..ae6aaaaf --- /dev/null +++ b/services/ws-wasi-runner/src/host/state.rs @@ -0,0 +1,116 @@ +use std::sync::Arc; + +use tokio::sync::Mutex; +use wasmtime::component::ResourceTable; +// DirPerms/FilePerms are only used by the coverage `/cov` preopen below. +#[cfg(feature = "coverage")] +use wasmtime_wasi::{DirPerms, FilePerms}; +use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView}; + +use super::wasi_nn; +use super::ws::WsBackend; + +#[non_exhaustive] +pub struct HostState { + pub wasi_ctx: WasiCtx, + pub resource_table: ResourceTable, + + /// WebSocket URL of the ws-server (e.g. `ws://localhost:8080/ws`). + pub ws_url: String, + + /// How long the host waits for `et-connect-ack`; `None` waits forever. + pub connect_ack_timeout: Option, + + /// Typed REST client for the ws-server (modules + per-agent storage). + /// Generated by `cargo-progenitor` from `generated/specs/rest.yaml`. + pub rest: et_rest_client::Client, + pub ws: Arc>>, + /// wasi-nn context. + /// Constructed once at startup so model loads + compute reuse the same `ort` session pool across calls. + pub wasi_nn_ctx: wasmtime_wasi_nn::wit::WasiNnCtx, + + /// wgpu instance backing `wasi:webgpu`. + /// One per store, created eagerly: adapter enumeration is what the guest's first call needs, and + /// `wasi-webgpu-wasmtime` borrows this handle rather than owning it. + pub wgpu_instance: Arc, +} + +impl HostState { + #[must_use] + #[cfg_attr( + not(feature = "coverage"), + expect( + unused_variables, + reason = "coverage gates the /cov preopen, compiled only under the feature" + ) + )] + pub fn new( + http_base: &str, + ws_url: String, + connect_ack_timeout: Option, + coverage: bool, + ) -> Self { + let mut builder = WasiCtxBuilder::new(); + #[expect(unused_results, reason = "WasiCtxBuilder setters return &mut Self")] + { + builder.inherit_stdio().inherit_env(); + } + // Instrumented guests write their minicov `.profraw` to `/cov`; map it to target/wasi-cov so the + // wasi-cov task finds it. Repo-root-anchored (not CWD) so it lands consistently under the test harness. + #[cfg(feature = "coverage")] + if coverage { + #[expect( + clippy::unwrap_used, + unused_results, + reason = "preopen setter returns &mut Self; a coverage-preopen failure is a misconfigured test run" + )] + { + let cov_dir = edge_toolkit::config::get_project_root().join("target/wasi-cov"); + fs_err::create_dir_all(&cov_dir).unwrap(); + builder + .preopened_dir(&cov_dir, "/cov", DirPerms::all(), FilePerms::all()) + .unwrap(); + } + } + let wasi_ctx = builder.build(); + + Self { + wasi_ctx, + resource_table: ResourceTable::new(), + ws_url, + connect_ack_timeout, + rest: et_rest_client::Client::new(http_base), + ws: Arc::new(Mutex::new(None)), + wasi_nn_ctx: wasi_nn::new_ctx(), + wgpu_instance: Arc::new(wgpu_core::global::Global::new( + "webgpu", + wgpu_types::InstanceDescriptor { + backends: wgpu_types::Backends::all(), + flags: wgpu_types::InstanceFlags::from_build_config(), + backend_options: wgpu_types::BackendOptions::default(), + memory_budget_thresholds: wgpu_types::MemoryBudgetThresholds::default(), + display: None, + }, + None, + )), + } + } +} + +impl wasi_webgpu_wasmtime::WasiWebGpuCtxView for HostState { + fn webgpu_ctx(&mut self) -> wasi_webgpu_wasmtime::WasiWebGpuCtx<'_> { + wasi_webgpu_wasmtime::WasiWebGpuCtx { + instance: &self.wgpu_instance, + table: &mut self.resource_table, + } + } +} + +impl WasiView for HostState { + fn ctx(&mut self) -> WasiCtxView<'_> { + WasiCtxView { + ctx: &mut self.wasi_ctx, + table: &mut self.resource_table, + } + } +} diff --git a/services/ws-wasi-runner/src/host/ws.rs b/services/ws-wasi-runner/src/host/ws.rs index d5368d16..d5dd5cf3 100644 --- a/services/ws-wasi-runner/src/host/ws.rs +++ b/services/ws-wasi-runner/src/host/ws.rs @@ -365,8 +365,8 @@ fn server_message_to_wit(msg: ServerMessage) -> Result WitConnectStatus { @@ -377,8 +377,8 @@ const fn et_connect_status(value: EtConnectStatus) -> WitConnectStatus { } #[expect( - clippy::single_call_fn, clippy::needless_pass_by_value, + clippy::single_call_fn, reason = "WIT/edge-toolkit enum bridge; Copy enum, by value keeps call sites uniform" )] const fn et_message_scope(value: EtMessageScope) -> WitMessageScope { @@ -389,8 +389,8 @@ const fn et_message_scope(value: EtMessageScope) -> WitMessageScope { } #[expect( - clippy::single_call_fn, clippy::needless_pass_by_value, + clippy::single_call_fn, reason = "WIT/edge-toolkit enum bridge; Copy enum, by value keeps call sites uniform" )] const fn et_delivery_status(value: EtMessageDeliveryStatus) -> WitMessageDeliveryStatus { @@ -403,8 +403,8 @@ const fn et_delivery_status(value: EtMessageDeliveryStatus) -> WitMessageDeliver } #[expect( - clippy::single_call_fn, clippy::needless_pass_by_value, + clippy::single_call_fn, reason = "WIT/edge-toolkit enum bridge; Copy enum, by value keeps call sites uniform" )] const fn et_agent_connection_state(value: EtAgentConnectionState) -> WitAgentConnectionState { diff --git a/services/ws-wasi-runner/tests/otel_propagation.rs b/services/ws-wasi-runner/tests/otel_propagation.rs index c6619b7c..4e4a009d 100644 --- a/services/ws-wasi-runner/tests/otel_propagation.rs +++ b/services/ws-wasi-runner/tests/otel_propagation.rs @@ -22,8 +22,8 @@ #![cfg(test)] #![expect( - clippy::uninlined_format_args, clippy::needless_collect, + clippy::uninlined_format_args, reason = "test code: assertion-helper format/collect idioms" )] diff --git a/services/ws-wasm-agent/src/lib.rs b/services/ws-wasm-agent/src/lib.rs index 0bbeae96..1aa4722e 100644 --- a/services/ws-wasm-agent/src/lib.rs +++ b/services/ws-wasm-agent/src/lib.rs @@ -37,7 +37,7 @@ pub fn init_tracing() { clippy::exhaustive_enums, reason = "ConnectionState enumerates the WebSocket client's lifecycle; downstream code matches exhaustively" )] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum ConnectionState { Disconnected, Connecting, @@ -176,8 +176,8 @@ impl WsClient { /// Connect to the WebSocket server. #[wasm_bindgen] #[expect( - clippy::too_many_lines, clippy::cognitive_complexity, + clippy::too_many_lines, reason = "single-method connect+wire-up; on_message closure dispatches all ServerMessage variants inline" )] pub fn connect(&mut self) -> Result<(), JsValue> { diff --git a/services/ws-web-runner/mingw-shim/msvc_crt_alloc.c b/services/ws-web-runner/mingw-shim/msvc_crt_alloc.c index 332c8603..8bbd0b9a 100644 --- a/services/ws-web-runner/mingw-shim/msvc_crt_alloc.c +++ b/services/ws-web-runner/mingw-shim/msvc_crt_alloc.c @@ -9,7 +9,9 @@ * operator-new symbols resolve the msvc_crt_ops.s jumps in the shim archive. */ #include +// skipcq: CXX-W2030 -- this is C; exists only in C++ #include +// skipcq: CXX-W2030 -- this is C; exists only in C++ #include #include @@ -57,19 +59,19 @@ int _dupenv_s(char **buf, size_t *len, const char *name) { /* MSVC C++ operator new/delete impls (statically linked in MSVC's CRT), forwarded to the mingw heap. * V8 frees what it allocates, so pairing stays within one heap. Throwing-new degrades to abort-on-OOM. */ void *shim_op_new(size_t n) { - void *p = malloc(n ? n : 1U); - if (!p) { + void *p = malloc((n != 0U) ? n : 1U); + if (p == NULL) { abort(); } return p; } void *shim_op_new_nothrow(size_t n, void *tag) { (void)tag; - return malloc(n ? n : 1U); + return malloc((n != 0U) ? n : 1U); } void *shim_op_new_aligned(size_t n, size_t align) { - void *p = _aligned_malloc(n ? n : 1U, align); - if (!p) { + void *p = _aligned_malloc((n != 0U) ? n : 1U, align); + if (p == NULL) { abort(); } return p; diff --git a/services/ws-web-runner/mingw-shim/msvc_crt_locale.c b/services/ws-web-runner/mingw-shim/msvc_crt_locale.c index b4cc2dd2..5ce94e40 100644 --- a/services/ws-web-runner/mingw-shim/msvc_crt_locale.c +++ b/services/ws-web-runner/mingw-shim/msvc_crt_locale.c @@ -22,6 +22,7 @@ * LoadLibraryW ref). Uses GetProcAddress rather than an import lib because ucrtbase's own import-lib members * define these same names and would collide. */ +// skipcq: CXX-W2030 -- this is C; exists only in C++ #include #include diff --git a/services/ws-web-runner/mingw-shim/msvc_crt_shim.c b/services/ws-web-runner/mingw-shim/msvc_crt_shim.c index d439cdf9..d7d8421c 100644 --- a/services/ws-web-runner/mingw-shim/msvc_crt_shim.c +++ b/services/ws-web-runner/mingw-shim/msvc_crt_shim.c @@ -12,7 +12,9 @@ * every analyzer that reports those, `DeepSource CXX-E2000` (reserved identifier) and `DeepSource CXX-W2009` * (non-const) included. */ +// skipcq: CXX-W2030 -- this is C; exists only in C++ #include +// skipcq: CXX-W2030 -- this is C; exists only in C++ #include #include @@ -89,6 +91,7 @@ void __dyn_tls_on_demand_init(void) {} /* Chromium libc++'s verbose abort, which exists only to die loudly. * It is referenced from the archive's absl objects but its own definition is not archive-extractable. */ +// skipcq: CXX-W2014 -- the variadic signature is libc++'s ABI for __libcpp_verbose_abort, and C has no packs _Noreturn void shim_libcpp_verbose_abort(const char *fmt, ...) { (void)fmt; abort(); diff --git a/services/ws-web-runner/src/error.rs b/services/ws-web-runner/src/error.rs index 088404d5..f719308a 100644 --- a/services/ws-web-runner/src/error.rs +++ b/services/ws-web-runner/src/error.rs @@ -27,7 +27,7 @@ pub enum RunnerError { /// Maps any `Display` error into a generic `JsErrorBox`. /// -/// Per repo naming convention (see CLAUDE.md), these are `map_*` because they +/// Per repo naming convention (see AGENTS.md), these are `map_*` because they /// are custom-`map_err` wrappers -- the name signals "this calls `map_err` /// under the hood, just hiding the closure." pub trait JsErrExt { diff --git a/services/ws-web-runner/src/runtime.rs b/services/ws-web-runner/src/runtime.rs index 557d21d4..f1606b30 100644 --- a/services/ws-web-runner/src/runtime.rs +++ b/services/ws-web-runner/src/runtime.rs @@ -309,8 +309,8 @@ fn create_web_worker_cb( /// spawn fresh `WebWorker`s on their own threads sharing a `BackingStore` store for `SharedArrayBuffer` cross-isolate /// transfer. #[expect( - clippy::single_call_fn, clippy::future_not_send, + clippy::single_call_fn, reason = "MainWorker is !Send; called from single-threaded tokio" )] pub async fn run_js_module( diff --git a/services/ws/src/lib.rs b/services/ws/src/lib.rs index 4f4a1f51..aaac2619 100644 --- a/services/ws/src/lib.rs +++ b/services/ws/src/lib.rs @@ -103,7 +103,7 @@ const fn default_connection_timeout() -> Option { /// /// `Json` is the normal path for protocol messages. `Text` and `Binary` carry payloads the server forwards verbatim -- /// used by the hub-style fallback that broadcasts unrecognised frames to every other connected agent. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] #[non_exhaustive] pub enum SessionMessage { Json(ServerMessage), diff --git a/services/ws/tests/load_registry.rs b/services/ws/tests/load_registry.rs index d42e6bc0..d55f3618 100644 --- a/services/ws/tests/load_registry.rs +++ b/services/ws/tests/load_registry.rs @@ -15,7 +15,7 @@ fn missing_file_yields_an_empty_registry() { let registry = load_registry(&path).unwrap(); - assert!(registry.list_agents().is_empty()); + assert_eq!(registry.list_agents(), Vec::::new()); } #[test] diff --git a/utilities/cli/Cargo.toml b/utilities/cli/Cargo.toml index b47d15bc..be005425 100644 --- a/utilities/cli/Cargo.toml +++ b/utilities/cli/Cargo.toml @@ -17,7 +17,6 @@ path = "src/main.rs" [dependencies] clap.workspace = true -clap-markdown = { workspace = true, optional = true } edge-toolkit.workspace = true et-org.workspace = true et-path.workspace = true @@ -41,8 +40,5 @@ et-test-helpers.workspace = true et-ws-test-server.workspace = true tempfile.workspace = true -[features] -markdown-help = ["dep:clap-markdown"] - [lints] workspace = true diff --git a/utilities/cli/src/cli.rs b/utilities/cli/src/cli.rs index 59768878..62141c8d 100644 --- a/utilities/cli/src/cli.rs +++ b/utilities/cli/src/cli.rs @@ -1,20 +1,21 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; -use et_cli::OutputType; + +use crate::OutputType; #[derive(Parser)] +#[non_exhaustive] pub struct Cli { #[command(subcommand)] pub command: Option, - - /// Print the full clap help tree as markdown (used to regenerate HELP.md). - #[cfg(feature = "markdown-help")] - #[arg(long, hide = true)] - pub markdown_help: bool, } #[derive(Subcommand)] +#[expect( + clippy::exhaustive_enums, + reason = "the binary matches every subcommand, so adding one has to fail that match rather than fall through" +)] pub enum Commands { /// Generate deployment config from a cluster input YAML. GenerateDeployment { diff --git a/utilities/cli/src/deployment_types/hub.rs b/utilities/cli/src/deployment_types/hub.rs new file mode 100644 index 00000000..cc54486e --- /dev/null +++ b/utilities/cli/src/deployment_types/hub.rs @@ -0,0 +1,29 @@ +use std::path::Path; + +use crate::input::ClusterInput; + +/// Whether this cluster's hub is opened in a browser, and so needs the page module and what it imports. +/// +/// An agent with no `runner` is one whose modules a browser loads, and a cluster with no agents at all is the bare hub, +/// which exists to serve that page. Everything else runs headless: the hub relays between runner processes and nothing +/// ever opens it, so a front page there would provision a module nobody loads, along with the runtimes its first import +/// pulls in. +pub(crate) fn serves_a_page(cluster: &ClusterInput) -> bool { + cluster.agents.is_empty() + || cluster + .agents + .iter() + .any(|agent| agent.runner.as_deref().is_none_or(|kind| kind.trim().is_empty())) +} + +/// The module the hub serves at `/`, named as its own `package.json` declares it. +/// +/// Read from that manifest rather than written out, so a generated deployment carries whatever the page module is +/// actually called -- including the owner scope publishing puts on it -- without this crate holding a second copy of +/// the name to drift from it. Every deployment format that serves the page needs it: the hub has no default for which +/// module is a deployment's front page, so the deployment that knows names it. +pub(crate) fn hub_root_module(ws_server_dir: &Path) -> String { + crate::module_package_json(&ws_server_dir.join("static")) + .and_then(|package| package.name) + .unwrap_or_default() +} diff --git a/utilities/cli/src/deployment_types/k3s.rs b/utilities/cli/src/deployment_types/k3s.rs index 11a1e24e..e629d1e3 100644 --- a/utilities/cli/src/deployment_types/k3s.rs +++ b/utilities/cli/src/deployment_types/k3s.rs @@ -160,8 +160,8 @@ fn fixed_documents( /// Serialise one object, in the YAML style the repo's formatters hold a committed file to. #[expect( - clippy::unwrap_used, clippy::unwrap_in_result, + clippy::unwrap_used, reason = "pretty_yaml only fails on malformed YAML and serde output is always well-formed" )] fn document(object: &T) -> Result diff --git a/utilities/cli/src/deployment_types/mod.rs b/utilities/cli/src/deployment_types/mod.rs index e991bf11..af704023 100644 --- a/utilities/cli/src/deployment_types/mod.rs +++ b/utilities/cli/src/deployment_types/mod.rs @@ -1,39 +1,11 @@ -use std::path::Path; - mod docker_compose; +mod hub; mod k3s; mod mise; mod scenario_image; -use crate::input::ClusterInput; - -/// Whether this cluster's hub is opened in a browser, and so needs the page module and what it imports. -/// -/// An agent with no `runner` is one whose modules a browser loads, and a cluster with no agents at all is the bare hub, -/// which exists to serve that page. Everything else runs headless: the hub relays between runner processes and nothing -/// ever opens it, so a front page there would provision a module nobody loads, along with the runtimes its first import -/// pulls in. -pub(crate) fn serves_a_page(cluster: &ClusterInput) -> bool { - cluster.agents.is_empty() - || cluster - .agents - .iter() - .any(|agent| agent.runner.as_deref().is_none_or(|kind| kind.trim().is_empty())) -} - -/// The module the hub serves at `/`, named as its own `package.json` declares it. -/// -/// Read from that manifest rather than written out, so a generated deployment carries whatever the page module is -/// actually called -- including the owner scope publishing puts on it -- without this crate holding a second copy of -/// the name to drift from it. Every deployment format that serves the page needs it: the hub has no default for which -/// module is a deployment's front page, so the deployment that knows names it. -pub(crate) fn hub_root_module(ws_server_dir: &Path) -> String { - crate::module_package_json(&ws_server_dir.join("static")) - .and_then(|package| package.name) - .unwrap_or_default() -} - pub use self::docker_compose::{docker_image_module_paths, generate_docker_compose_deployment}; +pub(crate) use self::hub::{hub_root_module, serves_a_page}; pub use self::k3s::generate_k3s_deployment; pub(crate) use self::mise::STORAGE_DIR; pub use self::mise::{ScenarioModules, generate_mise_deployment, scenario_module_paths}; diff --git a/utilities/cli/src/deployment_types/scenario_image.rs b/utilities/cli/src/deployment_types/scenario_image.rs index df312299..668b820e 100644 --- a/utilities/cli/src/deployment_types/scenario_image.rs +++ b/utilities/cli/src/deployment_types/scenario_image.rs @@ -185,7 +185,7 @@ const DEPS_BASE_STAGE: &str = concat!( "# checks exactly the archive downloaded here. Pinned rather than installed from mise's apt repository,\n", "# which carries only the newest version: a floating mise writes lockfile entries an older CI mise\n", "# then refuses to install.\n", - "ARG MISE_VERSION=v2026.9.0\n", + "ARG MISE_VERSION=v2026.9.17\n", "ARG TARGETARCH\n", "ENV MISE_VERSION=${MISE_VERSION}\n", "ENV TARGETARCH=${TARGETARCH}\n", diff --git a/utilities/cli/src/input.rs b/utilities/cli/src/input.rs index 22ac35da..83dda87b 100644 --- a/utilities/cli/src/input.rs +++ b/utilities/cli/src/input.rs @@ -22,7 +22,7 @@ const REPOSITORY_URL: &str = et_org::REPOSITORY_URL; clippy::exhaustive_enums, reason = "OutputType enumerates the supported deployment formats; downstream code matches exhaustively" )] -#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq, ValueEnum)] +#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, ValueEnum)] #[serde(rename_all = "lowercase")] pub enum OutputType { #[default] @@ -45,7 +45,7 @@ impl OutputType { } } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[non_exhaustive] pub struct ClusterInput { pub cluster_name: String, @@ -111,7 +111,7 @@ impl Default for ClusterInput { /// `Published` is the default because it is the only one of the two that always works. Building from the working tree /// needs a working tree, so `Local` is an answer available to almost nobody: everyone generating a deployment for their /// own cluster has the releases and not this repository. -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] #[non_exhaustive] #[serde(rename_all = "lowercase")] pub enum ArtifactSource { @@ -165,7 +165,7 @@ pub fn manifest_declares_this_repository(manifest: &str) -> bool { == Some(REPOSITORY_URL) } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[non_exhaustive] pub struct Agent { pub name: String, @@ -189,7 +189,7 @@ pub struct Agent { pub resources: Vec, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[non_exhaustive] pub struct Resource { #[serde(rename = "type")] diff --git a/utilities/cli/src/lib.rs b/utilities/cli/src/lib.rs index 5e8c9a83..440e4a7f 100644 --- a/utilities/cli/src/lib.rs +++ b/utilities/cli/src/lib.rs @@ -12,6 +12,7 @@ use et_path::{absolute_from, relative_path_from}; use fs_err as fs; use serde::Deserialize; +pub mod cli; mod deployment_types; mod error; mod hub_ws_url; @@ -20,8 +21,9 @@ mod module_package_json; mod scenario_password; // `pub` here means "reachable from the binary or from `tests/`", and nothing else. This crate is a command line tool -// that happens to be split into a lib target so integration tests can drive it; no consumer outside this directory -// builds on it, and nothing exported is a promise. Everything the generators share among themselves is `pub(crate)`, so +// that happens to be split into a lib target so integration tests can drive it; the only consumer outside this +// directory is et-int-gen, which reads the `cli` tree to write HELP.md, and nothing exported is a promise. Everything +// the generators share among themselves is `pub(crate)`, so // what remains below is the whole of the surface anyone could depend on -- short enough to read, which is what makes an // accidental addition to it visible. pub use self::deployment_types::{ScenarioModules, docker_image_module_paths, scenario_module_paths}; @@ -47,7 +49,7 @@ fn generated_output_files(output_types: &[OutputType]) -> Vec<&'static str> { files } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct DeploymentSummary { pub cluster_name: String, @@ -55,7 +57,7 @@ pub struct DeploymentSummary { pub module_names: Vec, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct RegeneratedScenario { pub input_file: PathBuf, @@ -63,7 +65,7 @@ pub struct RegeneratedScenario { pub summary: DeploymentSummary, } -#[derive(Debug, Clone, Default, Deserialize)] +#[derive(Clone, Debug, Default, Deserialize)] #[non_exhaustive] pub struct PackageJson { pub name: Option, @@ -122,7 +124,7 @@ struct CargoWsModule { /// The deployment generators need this to tell apart the two provisioning routes: a repo directory can be copied /// straight out of the Docker build context, whereas a mise-staged package exists only in the tool's install dir and /// has to be installed before it can be staged. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub(crate) enum ModuleSource { /// A directory in this repository, as a path relative to the repository root. @@ -222,7 +224,7 @@ pub(crate) fn image_prefix(images: ArtifactSource) -> String { } } -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] #[non_exhaustive] pub(crate) struct ModuleRegistryEntry { pub mise_path: String, @@ -1416,7 +1418,7 @@ pub fn npm_module_path(package: &str) -> Result { pub(crate) const DERIVED_RUNNER_ENV: [&str; 2] = ["RUNNER_MODULE", "WS_SERVER_URL"]; /// One runner process the generated deployment starts, resolved from an agent that names a `runner:`. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] #[non_exhaustive] pub(crate) struct RunnerInstance { /// Deployment-unique name for the process: the task name in `mise.toml`, the service name in `compose.yaml`. diff --git a/utilities/cli/src/main.rs b/utilities/cli/src/main.rs index 6f5ff9fe..57e414da 100644 --- a/utilities/cli/src/main.rs +++ b/utilities/cli/src/main.rs @@ -1,21 +1,12 @@ #![expect(clippy::print_stdout, reason = "CLI tool: println! is the intended UX")] use clap::{CommandFactory as _, Parser as _}; +use et_cli::cli::{Cli, Commands}; use et_cli::{CliError, generate_deployment, generate_module_package_json, npm_module_path, regenerate_verification}; -mod cli; - -use crate::cli::{Cli, Commands}; - fn main() -> Result<(), CliError> { let cli = Cli::parse(); - #[cfg(feature = "markdown-help")] - if cli.markdown_help { - clap_markdown::print_help_markdown::(); - return Ok(()); - } - let Some(command) = cli.command.as_ref() else { Cli::command().print_help()?; return Ok(()); diff --git a/utilities/cli/src/module_package_json/generate.rs b/utilities/cli/src/module_package_json/generate.rs new file mode 100644 index 00000000..545c9615 --- /dev/null +++ b/utilities/cli/src/module_package_json/generate.rs @@ -0,0 +1,434 @@ +#![expect( + unused_results, + reason = "serde_json::Map::insert discards the prior Value at each key, which is the intended overwrite" +)] + +use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; + +use fs_err as fs; +use serde::Deserialize; +use serde_json::{Map, Value, json}; + +use crate::MODULE_SCOPE; +use crate::error::{CliError, parse_json, parse_toml, serialize_json_pretty}; + +/// The name a module publishes under, given the name its crate or project declares. +/// +/// Every module carries the owner scope, because a registry that would accept an unscoped one does not exist +/// for this project: GitHub Packages rejects any package not scoped to the repository owner. Carrying it on a +/// module nobody publishes costs nothing, since the hub takes the scope back off when it names a module -- +/// so a scoped and an unscoped build of the same module are served identically, and a tree part way through +/// this rename behaves uniformly. Applied here rather than at each call site so one rule covers every module +/// whose manifest this generator writes. +fn scoped_package_name(declared: &str) -> String { + if declared.starts_with(MODULE_SCOPE) { + return declared.to_string(); + } + format!("{MODULE_SCOPE}{declared}") +} + +/// Prefix every module of this project's own carries, and so what marks a dependency as one to scope. +const OWN_MODULE_PREFIX: &str = et_org::CRATE_PREFIX; + +/// The name a declared dependency is written as in the published manifest. +/// +/// A module's `dependencies` name the other modules the hub has to serve alongside it, and a deployment +/// resolves them by the served name. Publishing turns that list into something a registry reads too, so a +/// module of this project's own has to appear under the name the registry knows it by -- installing a +/// published module otherwise fails on a dependency no registry has. Everything else a module declares +/// (`onnxruntime-web`, `pyodide`, the `@huggingface` and `@mediapipe` packages) is somebody else's, already +/// published under exactly that name, and scoping it would point the install at a package that never existed. +/// The prefix separates the two: every module here carries it, and no third-party dependency does. +pub(crate) fn scoped_dependency_name(declared: &str) -> String { + if declared.starts_with(OWN_MODULE_PREFIX) { + return scoped_package_name(declared); + } + declared.to_string() +} + +#[derive(Deserialize)] +struct Project { + name: String, + version: String, + description: Option, + license: Option, + #[serde(default)] + urls: BTreeMap, +} + +/// Shared shape of `[tool.ws-module]` (pyproject.toml) and `[package.metadata.ws-module]` (Cargo.toml). +#[derive(Default, Deserialize)] +struct WsModule { + /// Override for the resolved entry file (relative to `pkg/`). + /// + /// When `None`, the entry is derived from the package name -- see [`resolve_main`]. + #[serde(default)] + main: Option, + #[serde(default)] + dependencies: BTreeMap, +} + +#[derive(Deserialize)] +struct Tool { + #[serde(rename = "ws-module", default)] + ws_module: WsModule, +} + +#[derive(Deserialize)] +struct Pyproject { + project: Project, + #[serde(default)] + tool: Option, +} + +#[derive(Deserialize)] +struct CargoToml { + package: Option, + workspace: Option, + #[serde(default)] + dependencies: BTreeMap, + #[serde(default)] + target: BTreeMap, +} + +/// One `[target.]` table, carrying only the runtime dependencies the module kind is read from. +#[derive(Deserialize)] +struct CargoTarget { + #[serde(default)] + dependencies: BTreeMap, +} + +#[derive(Deserialize)] +struct CargoPackageMetadata { + name: String, + version: Option, + repository: Option, + metadata: Option, +} + +#[derive(Deserialize)] +struct CargoMetadata { + #[serde(rename = "ws-module")] + ws_module: Option, +} + +#[derive(Deserialize)] +struct CargoWorkspace { + package: Option, +} + +#[derive(Default, Deserialize)] +struct WorkspacePackage { + version: Option, + repository: Option, +} + +/// A Cargo `[package]` field that is either a literal value or inherited from the workspace. +/// +/// The two spellings are `version = "0.1.0"` and `version.workspace = true`. +#[derive(Deserialize)] +#[serde(untagged)] +enum MaybeInherited { + Direct(String), + Workspace { + #[expect( + dead_code, + reason = "field exists only to make serde's untagged deserializer pick this variant" + )] + workspace: bool, + }, +} + +/// Writes `/pkg/package.json` from the module's `pyproject.toml` or `Cargo.toml`. +pub fn generate_module_package_json(module_dir: &Path) -> Result { + let out_path = module_dir.join("pkg/package.json"); + let package_json = if module_dir.join("pyproject.toml").is_file() { + package_json_from_pyproject(module_dir)? + } else if module_dir.join("Cargo.toml").is_file() { + package_json_from_cargo(module_dir, &out_path)? + } else { + return Err(CliError::MissingManifest(module_dir.to_path_buf())); + }; + + let parent = out_path + .parent() + .ok_or_else(|| CliError::NoParentDir(out_path.clone()))?; + fs::create_dir_all(parent)?; + let mut out = serialize_json_pretty(&package_json)?; + out.push('\n'); + fs::write(&out_path, &out)?; + + Ok(out_path) +} + +fn package_json_from_pyproject(module_dir: &Path) -> Result { + let pyproject_path = module_dir.join("pyproject.toml"); + let pyproject: Pyproject = read_toml(&pyproject_path)?; + let project = &pyproject.project; + let ws_module = pyproject.tool.map(|tool| tool.ws_module).unwrap_or_default(); + + let pkg_dir = module_dir.join("pkg"); + let kind = detect_python_kind(module_dir); + let main = resolve_main(&pkg_dir, &project.name, kind, ws_module.main.as_deref())?; + + let mut pkg = Map::from_iter([ + ("name".to_string(), json!(scoped_package_name(&project.name))), + ("type".to_string(), json!("module")), + ( + "description".to_string(), + json!(project.description.as_deref().unwrap_or("")), + ), + ("version".to_string(), json!(project.version)), + ("license".to_string(), json!(project.license.as_deref().unwrap_or(""))), + ("main".to_string(), json!(main)), + ]); + if let Some(repo) = project_repository(&project.urls) { + pkg.insert("repository".to_string(), repository_json(repo)); + } + if !ws_module.dependencies.is_empty() { + let dependencies: BTreeMap = ws_module + .dependencies + .into_iter() + .map(|(name, version)| (scoped_dependency_name(&name), version)) + .collect(); + pkg.insert("dependencies".to_string(), json!(dependencies)); + } + Ok(Value::Object(pkg)) +} + +/// Pick the source-of-truth URL out of a PEP 621 `[project.urls]` map. +/// +/// `[project.urls]` is a free-form map keyed by display name. The PyPI-recommended convention is to call the +/// source-of-truth URL one of these (case-sensitive); we accept all of them. +fn project_repository(urls: &BTreeMap) -> Option<&str> { + ["Repository", "repository", "Source", "source"] + .iter() + .find_map(|key| urls.get(*key)) + .map(String::as_str) +} + +fn package_json_from_cargo(module_dir: &Path, out_path: &Path) -> Result { + let cargo_toml_path = module_dir.join("Cargo.toml"); + let cargo_toml_src = fs::read_to_string(&cargo_toml_path)?; + let mut cargo_toml: CargoToml = parse_toml(&cargo_toml_path, &cargo_toml_src)?; + let kind = detect_cargo_kind(&cargo_toml); + let package = cargo_toml + .package + .take() + .ok_or_else(|| CliError::MissingPackageSection(cargo_toml_path.clone()))?; + let crate_name = package.name; + let workspace = find_workspace_package(module_dir)?; + + let mut pkg = read_package_json(out_path)?.unwrap_or_else(|| { + let mut pkg = Map::new(); + pkg.insert("name".to_string(), json!(scoped_package_name(&crate_name))); + pkg.insert("type".to_string(), json!("module")); + pkg + }); + + // Normalise whatever name is already there rather than only filling in a missing one. A `pkg/` written by + // wasm-pack arrives carrying its own name, so leaving an existing one alone meant a module built before + // the scope existed kept its bare name forever. Scoping what is there preserves a deliberate rename while + // still guaranteeing the scope; for a name wasm-pack derived from the crate the result is identical. + let declared = pkg + .get("name") + .and_then(Value::as_str) + .map_or_else(|| crate_name.clone(), str::to_string); + pkg.insert("name".to_string(), json!(scoped_package_name(&declared))); + let ws_version = workspace.as_ref().and_then(|ws| ws.version.as_deref()); + let ws_repository = workspace.as_ref().and_then(|ws| ws.repository.as_deref()); + if !pkg.contains_key("version") + && let Some(version) = resolve_inherited(package.version.as_ref(), ws_version) + { + pkg.insert("version".to_string(), json!(version)); + } + if !pkg.contains_key("repository") + && let Some(repo) = resolve_inherited(package.repository.as_ref(), ws_repository) + { + pkg.insert("repository".to_string(), repository_json(&repo)); + } + + let ws_module = package + .metadata + .and_then(|metadata| metadata.ws_module) + .unwrap_or_default(); + + let existing_main = pkg.get("main").and_then(|value| value.as_str()).map(str::to_string); + let main_override = ws_module.main.as_deref().or(existing_main.as_deref()); + let pkg_dir = module_dir.join("pkg"); + let main = resolve_main(&pkg_dir, &crate_name, kind, main_override)?; + pkg.insert("main".to_string(), json!(main)); + + if !ws_module.dependencies.is_empty() { + let dependencies = pkg + .entry("dependencies".to_string()) + .or_insert_with(|| Value::Object(Map::new())); + let dependency_map = dependencies + .as_object_mut() + .ok_or_else(|| CliError::NonObjectDependencies(out_path.to_path_buf()))?; + for (name, version) in ws_module.dependencies { + dependency_map.insert(scoped_dependency_name(&name), json!(version)); + } + // An entry left by an earlier generation carries whatever name the rule produced then, so the map is + // normalised as a whole rather than only where this run inserted. Without it a module that was + // generated before the scope existed keeps the bare key and gains the scoped one beside it, and the + // hub is handed the same dependency twice under two names. + let normalised: Map = dependency_map + .iter() + .map(|(name, version)| (scoped_dependency_name(name), version.clone())) + .collect(); + *dependency_map = normalised; + } + + Ok(Value::Object(pkg)) +} + +/// Resolve a `[package]` field that may be inherited from the workspace. +/// +/// `direct` is the value read from the crate's Cargo.toml; `workspace` is the corresponding `[workspace.package]` value +/// (if any). Returns the literal direct value, or the workspace value when the crate declares `field.workspace = true`. +fn resolve_inherited(direct: Option<&MaybeInherited>, workspace: Option<&str>) -> Option { + match direct { + Some(MaybeInherited::Direct(value)) => Some(value.clone()), + Some(MaybeInherited::Workspace { .. }) => workspace.map(str::to_string), + None => None, + } +} + +/// Walk parents of `start` for a Cargo.toml with a `[workspace]` table and return its `[workspace.package]`. +fn find_workspace_package(start: &Path) -> Result, CliError> { + for dir in start.ancestors().skip(1) { + let cargo = dir.join("Cargo.toml"); + if !cargo.is_file() { + continue; + } + let toml: CargoToml = read_toml(&cargo)?; + if let Some(ws) = toml.workspace { + return Ok(ws.package); + } + } + Ok(None) +} + +/// Build the object form of npm's `repository` field for `url`. +/// +/// npm accepts either a bare URL string or the object form. The object form matches what wasm-pack emits, so we use +/// that for visual consistency across generated package.json files. +fn repository_json(url: &str) -> Value { + json!({ "type": "git", "url": url }) +} + +/// Whether a module is built as a WASI Preview 2 component or as JS that browser/Pyodide loads. +#[derive(Clone, Copy)] +enum ModuleKind { + Wasi, + Js, +} + +impl ModuleKind { + const fn extension(self) -> &'static str { + match self { + Self::Wasi => "wasm", + Self::Js => "js", + } + } +} + +/// Classify a Python module as WASI or Pyodide by the presence of a `wit_world/` package. +/// +/// `componentize-py bindings` writes `wit_world/` next to the module's `pyproject.toml`, so it only exists for a WASI +/// Python module. +fn detect_python_kind(module_dir: &Path) -> ModuleKind { + if module_dir.join("wit_world").is_dir() { + ModuleKind::Wasi + } else { + ModuleKind::Js + } +} + +/// The runtime dependency names that identify a WASI component guest. +const WASI_GUEST_MARKERS: [&str; 2] = ["et-wasi-guest", "wit-bindgen"]; + +/// WASI Rust modules reach the component bindings one of two ways; wasm-pack browser modules do neither. +/// +/// `et-wasi-guest` generates the bindings once and shares them, so a guest that depends on it names no +/// `wit-bindgen` of its own -- and a guest predating that crate, or generating its own for some reason, still +/// names `wit-bindgen` directly. Either marker identifies a component, and missing one is not cosmetic: the kind +/// picks the extension the entry file is looked up by, so a component read as a browser module goes looking for a +/// `.js` that was never built and the module's `package.json` cannot be written at all. +/// +/// Only a runtime dependency counts -- `[dependencies]` or `[target..dependencies]`. The name turning up in +/// a comment, in `[package.metadata]`, in a `[patch]` pin, or under `dev-`/`build-dependencies` says nothing +/// about what the module compiles to, and reading one of those as a component sends the resolver after a `.wasm` +/// that was never built, failing a browser module that would otherwise have generated cleanly. +fn detect_cargo_kind(cargo_toml: &CargoToml) -> ModuleKind { + let target_deps = cargo_toml.target.values().flat_map(|target| target.dependencies.keys()); + if cargo_toml + .dependencies + .keys() + .chain(target_deps) + .any(|name| WASI_GUEST_MARKERS.contains(&name.as_str())) + { + ModuleKind::Wasi + } else { + ModuleKind::Js + } +} + +/// Resolve the `main` entry file in `pkg_dir`. +/// +/// If `main_override` is set, that filename is used. Otherwise the entry is derived from `name` by trying both its `_` +/// and `-` variants with the extension dictated by `kind` (`.wasm` for WASI, `.js` for browser/Pyodide). The resolved +/// file must exist in `pkg_dir`; this errors otherwise. +fn resolve_main(pkg_dir: &Path, name: &str, kind: ModuleKind, main_override: Option<&str>) -> Result { + if let Some(main) = main_override { + if !pkg_dir.join(main).is_file() { + return Err(CliError::MissingMainFile { + main: main.to_string(), + dir: pkg_dir.to_path_buf(), + }); + } + return Ok(main.to_string()); + } + let underscored = name.replace('-', "_"); + let hyphenated = name.replace('_', "-"); + let stems: &[&str] = if underscored == hyphenated { + &[underscored.as_str()] + } else { + &[underscored.as_str(), hyphenated.as_str()] + }; + let ext = kind.extension(); + for stem in stems { + let candidate = format!("{stem}.{ext}"); + if pkg_dir.join(&candidate).is_file() { + return Ok(candidate); + } + } + Err(CliError::UnresolvedMainFile { + dir: pkg_dir.to_path_buf(), + underscored, + hyphenated, + ext, + }) +} + +fn read_toml(path: &Path) -> Result +where + T: for<'de> Deserialize<'de>, +{ + let src = fs::read_to_string(path)?; + parse_toml(path, &src) +} + +fn read_package_json(path: &Path) -> Result>, CliError> { + let src = match fs::read_to_string(path) { + Ok(src) => src, + Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(source) => return Err(CliError::Io(source)), + }; + let Value::Object(pkg) = parse_json(path, &src)? else { + return Err(CliError::NonObjectPackageJson(path.to_path_buf())); + }; + Ok(Some(pkg)) +} diff --git a/utilities/cli/src/module_package_json/mod.rs b/utilities/cli/src/module_package_json/mod.rs index e9990bff..0bb8a480 100644 --- a/utilities/cli/src/module_package_json/mod.rs +++ b/utilities/cli/src/module_package_json/mod.rs @@ -1,434 +1,4 @@ -#![expect( - unused_results, - reason = "serde_json::Map::insert discards the prior Value at each key, which is the intended overwrite" -)] +mod generate; -use std::collections::BTreeMap; -use std::path::{Path, PathBuf}; - -use fs_err as fs; -use serde::Deserialize; -use serde_json::{Map, Value, json}; - -use crate::MODULE_SCOPE; -use crate::error::{CliError, parse_json, parse_toml, serialize_json_pretty}; - -/// The name a module publishes under, given the name its crate or project declares. -/// -/// Every module carries the owner scope, because a registry that would accept an unscoped one does not exist -/// for this project: GitHub Packages rejects any package not scoped to the repository owner. Carrying it on a -/// module nobody publishes costs nothing, since the hub takes the scope back off when it names a module -- -/// so a scoped and an unscoped build of the same module are served identically, and a tree part way through -/// this rename behaves uniformly. Applied here rather than at each call site so one rule covers every module -/// whose manifest this generator writes. -fn scoped_package_name(declared: &str) -> String { - if declared.starts_with(MODULE_SCOPE) { - return declared.to_string(); - } - format!("{MODULE_SCOPE}{declared}") -} - -/// Prefix every module of this project's own carries, and so what marks a dependency as one to scope. -const OWN_MODULE_PREFIX: &str = et_org::CRATE_PREFIX; - -/// The name a declared dependency is written as in the published manifest. -/// -/// A module's `dependencies` name the other modules the hub has to serve alongside it, and a deployment -/// resolves them by the served name. Publishing turns that list into something a registry reads too, so a -/// module of this project's own has to appear under the name the registry knows it by -- installing a -/// published module otherwise fails on a dependency no registry has. Everything else a module declares -/// (`onnxruntime-web`, `pyodide`, the `@huggingface` and `@mediapipe` packages) is somebody else's, already -/// published under exactly that name, and scoping it would point the install at a package that never existed. -/// The prefix separates the two: every module here carries it, and no third-party dependency does. -pub(crate) fn scoped_dependency_name(declared: &str) -> String { - if declared.starts_with(OWN_MODULE_PREFIX) { - return scoped_package_name(declared); - } - declared.to_string() -} - -#[derive(Deserialize)] -struct Project { - name: String, - version: String, - description: Option, - license: Option, - #[serde(default)] - urls: BTreeMap, -} - -/// Shared shape of `[tool.ws-module]` (pyproject.toml) and `[package.metadata.ws-module]` (Cargo.toml). -#[derive(Deserialize, Default)] -struct WsModule { - /// Override for the resolved entry file (relative to `pkg/`). - /// - /// When `None`, the entry is derived from the package name -- see [`resolve_main`]. - #[serde(default)] - main: Option, - #[serde(default)] - dependencies: BTreeMap, -} - -#[derive(Deserialize)] -struct Tool { - #[serde(rename = "ws-module", default)] - ws_module: WsModule, -} - -#[derive(Deserialize)] -struct Pyproject { - project: Project, - #[serde(default)] - tool: Option, -} - -#[derive(Deserialize)] -struct CargoToml { - package: Option, - workspace: Option, - #[serde(default)] - dependencies: BTreeMap, - #[serde(default)] - target: BTreeMap, -} - -/// One `[target.]` table, carrying only the runtime dependencies the module kind is read from. -#[derive(Deserialize)] -struct CargoTarget { - #[serde(default)] - dependencies: BTreeMap, -} - -#[derive(Deserialize)] -struct CargoPackageMetadata { - name: String, - version: Option, - repository: Option, - metadata: Option, -} - -#[derive(Deserialize)] -struct CargoMetadata { - #[serde(rename = "ws-module")] - ws_module: Option, -} - -#[derive(Deserialize)] -struct CargoWorkspace { - package: Option, -} - -#[derive(Deserialize, Default)] -struct WorkspacePackage { - version: Option, - repository: Option, -} - -/// A Cargo `[package]` field that is either a literal value or inherited from the workspace. -/// -/// The two spellings are `version = "0.1.0"` and `version.workspace = true`. -#[derive(Deserialize)] -#[serde(untagged)] -enum MaybeInherited { - Direct(String), - Workspace { - #[expect( - dead_code, - reason = "field exists only to make serde's untagged deserializer pick this variant" - )] - workspace: bool, - }, -} - -/// Writes `/pkg/package.json` from the module's `pyproject.toml` or `Cargo.toml`. -pub fn generate_module_package_json(module_dir: &Path) -> Result { - let out_path = module_dir.join("pkg/package.json"); - let package_json = if module_dir.join("pyproject.toml").is_file() { - package_json_from_pyproject(module_dir)? - } else if module_dir.join("Cargo.toml").is_file() { - package_json_from_cargo(module_dir, &out_path)? - } else { - return Err(CliError::MissingManifest(module_dir.to_path_buf())); - }; - - let parent = out_path - .parent() - .ok_or_else(|| CliError::NoParentDir(out_path.clone()))?; - fs::create_dir_all(parent)?; - let mut out = serialize_json_pretty(&package_json)?; - out.push('\n'); - fs::write(&out_path, &out)?; - - Ok(out_path) -} - -fn package_json_from_pyproject(module_dir: &Path) -> Result { - let pyproject_path = module_dir.join("pyproject.toml"); - let pyproject: Pyproject = read_toml(&pyproject_path)?; - let project = &pyproject.project; - let ws_module = pyproject.tool.map(|tool| tool.ws_module).unwrap_or_default(); - - let pkg_dir = module_dir.join("pkg"); - let kind = detect_python_kind(module_dir); - let main = resolve_main(&pkg_dir, &project.name, kind, ws_module.main.as_deref())?; - - let mut pkg = Map::from_iter([ - ("name".to_string(), json!(scoped_package_name(&project.name))), - ("type".to_string(), json!("module")), - ( - "description".to_string(), - json!(project.description.as_deref().unwrap_or("")), - ), - ("version".to_string(), json!(project.version)), - ("license".to_string(), json!(project.license.as_deref().unwrap_or(""))), - ("main".to_string(), json!(main)), - ]); - if let Some(repo) = project_repository(&project.urls) { - pkg.insert("repository".to_string(), repository_json(repo)); - } - if !ws_module.dependencies.is_empty() { - let dependencies: BTreeMap = ws_module - .dependencies - .into_iter() - .map(|(name, version)| (scoped_dependency_name(&name), version)) - .collect(); - pkg.insert("dependencies".to_string(), json!(dependencies)); - } - Ok(Value::Object(pkg)) -} - -/// Pick the source-of-truth URL out of a PEP 621 `[project.urls]` map. -/// -/// `[project.urls]` is a free-form map keyed by display name. The PyPI-recommended convention is to call the -/// source-of-truth URL one of these (case-sensitive); we accept all of them. -fn project_repository(urls: &BTreeMap) -> Option<&str> { - ["Repository", "repository", "Source", "source"] - .iter() - .find_map(|key| urls.get(*key)) - .map(String::as_str) -} - -fn package_json_from_cargo(module_dir: &Path, out_path: &Path) -> Result { - let cargo_toml_path = module_dir.join("Cargo.toml"); - let cargo_toml_src = fs::read_to_string(&cargo_toml_path)?; - let mut cargo_toml: CargoToml = parse_toml(&cargo_toml_path, &cargo_toml_src)?; - let kind = detect_cargo_kind(&cargo_toml); - let package = cargo_toml - .package - .take() - .ok_or_else(|| CliError::MissingPackageSection(cargo_toml_path.clone()))?; - let crate_name = package.name; - let workspace = find_workspace_package(module_dir)?; - - let mut pkg = read_package_json(out_path)?.unwrap_or_else(|| { - let mut pkg = Map::new(); - pkg.insert("name".to_string(), json!(scoped_package_name(&crate_name))); - pkg.insert("type".to_string(), json!("module")); - pkg - }); - - // Normalise whatever name is already there rather than only filling in a missing one. A `pkg/` written by - // wasm-pack arrives carrying its own name, so leaving an existing one alone meant a module built before - // the scope existed kept its bare name forever. Scoping what is there preserves a deliberate rename while - // still guaranteeing the scope; for a name wasm-pack derived from the crate the result is identical. - let declared = pkg - .get("name") - .and_then(Value::as_str) - .map_or_else(|| crate_name.clone(), str::to_string); - pkg.insert("name".to_string(), json!(scoped_package_name(&declared))); - let ws_version = workspace.as_ref().and_then(|ws| ws.version.as_deref()); - let ws_repository = workspace.as_ref().and_then(|ws| ws.repository.as_deref()); - if !pkg.contains_key("version") - && let Some(version) = resolve_inherited(package.version.as_ref(), ws_version) - { - pkg.insert("version".to_string(), json!(version)); - } - if !pkg.contains_key("repository") - && let Some(repo) = resolve_inherited(package.repository.as_ref(), ws_repository) - { - pkg.insert("repository".to_string(), repository_json(&repo)); - } - - let ws_module = package - .metadata - .and_then(|metadata| metadata.ws_module) - .unwrap_or_default(); - - let existing_main = pkg.get("main").and_then(|value| value.as_str()).map(str::to_string); - let main_override = ws_module.main.as_deref().or(existing_main.as_deref()); - let pkg_dir = module_dir.join("pkg"); - let main = resolve_main(&pkg_dir, &crate_name, kind, main_override)?; - pkg.insert("main".to_string(), json!(main)); - - if !ws_module.dependencies.is_empty() { - let dependencies = pkg - .entry("dependencies".to_string()) - .or_insert_with(|| Value::Object(Map::new())); - let dependency_map = dependencies - .as_object_mut() - .ok_or_else(|| CliError::NonObjectDependencies(out_path.to_path_buf()))?; - for (name, version) in ws_module.dependencies { - dependency_map.insert(scoped_dependency_name(&name), json!(version)); - } - // An entry left by an earlier generation carries whatever name the rule produced then, so the map is - // normalised as a whole rather than only where this run inserted. Without it a module that was - // generated before the scope existed keeps the bare key and gains the scoped one beside it, and the - // hub is handed the same dependency twice under two names. - let normalised: Map = dependency_map - .iter() - .map(|(name, version)| (scoped_dependency_name(name), version.clone())) - .collect(); - *dependency_map = normalised; - } - - Ok(Value::Object(pkg)) -} - -/// Resolve a `[package]` field that may be inherited from the workspace. -/// -/// `direct` is the value read from the crate's Cargo.toml; `workspace` is the corresponding `[workspace.package]` value -/// (if any). Returns the literal direct value, or the workspace value when the crate declares `field.workspace = true`. -fn resolve_inherited(direct: Option<&MaybeInherited>, workspace: Option<&str>) -> Option { - match direct { - Some(MaybeInherited::Direct(value)) => Some(value.clone()), - Some(MaybeInherited::Workspace { .. }) => workspace.map(str::to_string), - None => None, - } -} - -/// Walk parents of `start` for a Cargo.toml with a `[workspace]` table and return its `[workspace.package]`. -fn find_workspace_package(start: &Path) -> Result, CliError> { - for dir in start.ancestors().skip(1) { - let cargo = dir.join("Cargo.toml"); - if !cargo.is_file() { - continue; - } - let toml: CargoToml = read_toml(&cargo)?; - if let Some(ws) = toml.workspace { - return Ok(ws.package); - } - } - Ok(None) -} - -/// Build the object form of npm's `repository` field for `url`. -/// -/// npm accepts either a bare URL string or the object form. The object form matches what wasm-pack emits, so we use -/// that for visual consistency across generated package.json files. -fn repository_json(url: &str) -> Value { - json!({ "type": "git", "url": url }) -} - -/// Whether a module is built as a WASI Preview 2 component or as JS that browser/Pyodide loads. -#[derive(Clone, Copy)] -enum ModuleKind { - Wasi, - Js, -} - -impl ModuleKind { - const fn extension(self) -> &'static str { - match self { - Self::Wasi => "wasm", - Self::Js => "js", - } - } -} - -/// Classify a Python module as WASI or Pyodide by the presence of a `wit_world/` package. -/// -/// `componentize-py bindings` writes `wit_world/` next to the module's `pyproject.toml`, so it only exists for a WASI -/// Python module. -fn detect_python_kind(module_dir: &Path) -> ModuleKind { - if module_dir.join("wit_world").is_dir() { - ModuleKind::Wasi - } else { - ModuleKind::Js - } -} - -/// The runtime dependency names that identify a WASI component guest. -const WASI_GUEST_MARKERS: [&str; 2] = ["et-wasi-guest", "wit-bindgen"]; - -/// WASI Rust modules reach the component bindings one of two ways; wasm-pack browser modules do neither. -/// -/// `et-wasi-guest` generates the bindings once and shares them, so a guest that depends on it names no -/// `wit-bindgen` of its own -- and a guest predating that crate, or generating its own for some reason, still -/// names `wit-bindgen` directly. Either marker identifies a component, and missing one is not cosmetic: the kind -/// picks the extension the entry file is looked up by, so a component read as a browser module goes looking for a -/// `.js` that was never built and the module's `package.json` cannot be written at all. -/// -/// Only a runtime dependency counts -- `[dependencies]` or `[target..dependencies]`. The name turning up in -/// a comment, in `[package.metadata]`, in a `[patch]` pin, or under `dev-`/`build-dependencies` says nothing -/// about what the module compiles to, and reading one of those as a component sends the resolver after a `.wasm` -/// that was never built, failing a browser module that would otherwise have generated cleanly. -fn detect_cargo_kind(cargo_toml: &CargoToml) -> ModuleKind { - let target_deps = cargo_toml.target.values().flat_map(|target| target.dependencies.keys()); - if cargo_toml - .dependencies - .keys() - .chain(target_deps) - .any(|name| WASI_GUEST_MARKERS.contains(&name.as_str())) - { - ModuleKind::Wasi - } else { - ModuleKind::Js - } -} - -/// Resolve the `main` entry file in `pkg_dir`. -/// -/// If `main_override` is set, that filename is used. Otherwise the entry is derived from `name` by trying both its `_` -/// and `-` variants with the extension dictated by `kind` (`.wasm` for WASI, `.js` for browser/Pyodide). The resolved -/// file must exist in `pkg_dir`; this errors otherwise. -fn resolve_main(pkg_dir: &Path, name: &str, kind: ModuleKind, main_override: Option<&str>) -> Result { - if let Some(main) = main_override { - if !pkg_dir.join(main).is_file() { - return Err(CliError::MissingMainFile { - main: main.to_string(), - dir: pkg_dir.to_path_buf(), - }); - } - return Ok(main.to_string()); - } - let underscored = name.replace('-', "_"); - let hyphenated = name.replace('_', "-"); - let stems: &[&str] = if underscored == hyphenated { - &[underscored.as_str()] - } else { - &[underscored.as_str(), hyphenated.as_str()] - }; - let ext = kind.extension(); - for stem in stems { - let candidate = format!("{stem}.{ext}"); - if pkg_dir.join(&candidate).is_file() { - return Ok(candidate); - } - } - Err(CliError::UnresolvedMainFile { - dir: pkg_dir.to_path_buf(), - underscored, - hyphenated, - ext, - }) -} - -fn read_toml(path: &Path) -> Result -where - T: for<'de> Deserialize<'de>, -{ - let src = fs::read_to_string(path)?; - parse_toml(path, &src) -} - -fn read_package_json(path: &Path) -> Result>, CliError> { - let src = match fs::read_to_string(path) { - Ok(src) => src, - Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None), - Err(source) => return Err(CliError::Io(source)), - }; - let Value::Object(pkg) = parse_json(path, &src)? else { - return Err(CliError::NonObjectPackageJson(path.to_path_buf())); - }; - Ok(Some(pkg)) -} +pub use self::generate::generate_module_package_json; +pub(crate) use self::generate::scoped_dependency_name; diff --git a/utilities/int-gen/Cargo.toml b/utilities/int-gen/Cargo.toml index 822bc605..85eecaa4 100644 --- a/utilities/int-gen/Cargo.toml +++ b/utilities/int-gen/Cargo.toml @@ -18,10 +18,12 @@ path = "src/bin/int-gen.rs" anyhow.workspace = true asyncapi-rust.workspace = true clap.workspace = true -clap-markdown = { workspace = true, optional = true } +clap-markdown.workspace = true command-error.workspace = true edge-toolkit = { workspace = true, features = ["schema-export"] } +et-cli.workspace = true et-modules-service = { workspace = true, features = ["openapi-spec"] } +et-onnx.workspace = true et-storage-service = { workspace = true, features = ["openapi-spec"] } et-ws-server = { workspace = true, features = ["openapi-spec"] } fs-err.workspace = true @@ -40,7 +42,9 @@ serde.workspace = true serde_json.workspace = true serde_yaml.workspace = true syn.workspace = true +tempfile.workspace = true thiserror.workspace = true +toml.workspace = true tree-sitter.workspace = true tree-sitter-zig.workspace = true utoipa.workspace = true @@ -48,9 +52,6 @@ wasmtime-internal-wit-bindgen.workspace = true wit-encoder = { workspace = true, features = ["from-parser"] } wit-parser.workspace = true -[features] -markdown-help = ["dep:clap-markdown"] - [dev-dependencies] et-test-helpers.workspace = true diff --git a/utilities/int-gen/HELP.md b/utilities/int-gen/HELP.md index e590af7f..43d8a161 100644 --- a/utilities/int-gen/HELP.md +++ b/utilities/int-gen/HELP.md @@ -7,10 +7,12 @@ This document contains the help content for the `et-int-gen` command-line progra - [`et-int-gen`↴](#et-int-gen) - [`et-int-gen generate`↴](#et-int-gen-generate) - [`et-int-gen fetch-deps`↴](#et-int-gen-fetch-deps) +- [`et-int-gen checks`↴](#et-int-gen-checks) +- [`et-int-gen help-md`↴](#et-int-gen-help-md) ## `et-int-gen` -Generate checked-in artifacts under generated/ from in-repo Rust sources of truth +Generate checked-in artifacts (generated/, CHECKS.md, HELP.md) from in-repo sources of truth **Usage:** `et-int-gen [COMMAND]` @@ -18,6 +20,8 @@ Generate checked-in artifacts under generated/ from in-repo Rust sources of trut - `generate` — Emit the generated artifacts for one target (default: all) - `fetch-deps` — Fetch upstream WASI WIT packages into generated/specs/wit/ at pinned versions +- `checks` — Write CHECKS.md, the catalogue of every check across every `MISE_ENV` +- `help-md` — Write each utility's HELP.md from its clap command tree ## `et-int-gen generate` @@ -49,6 +53,26 @@ Fetch upstream WASI WIT packages into generated/specs/wit/ at pinned versions **Usage:** `et-int-gen fetch-deps` +## `et-int-gen checks` + +Write CHECKS.md, the catalogue of every check across every `MISE_ENV` + +**Usage:** `et-int-gen checks [OPTIONS]` + +###### **Options:** + +- `--check` — Compare against the committed CHECKS.md and fail on drift instead of writing it + +## `et-int-gen help-md` + +Write each utility's HELP.md from its clap command tree + +**Usage:** `et-int-gen help-md [OPTIONS]` + +###### **Options:** + +- `--check` — Compare against the committed HELP.md files and fail on drift instead of writing them +
diff --git a/utilities/int-gen/src/bin/int-gen.rs b/utilities/int-gen/src/bin/int-gen.rs index 346a4652..b727deac 100644 --- a/utilities/int-gen/src/bin/int-gen.rs +++ b/utilities/int-gen/src/bin/int-gen.rs @@ -1,60 +1,17 @@ //! CLI entrypoint for `et-int-gen`. All real work lives in the library (`et_int_gen`); this file just parses arguments //! and dispatches. -use clap::{Parser, Subcommand, ValueEnum}; +use clap::Parser as _; use edge_toolkit::config::get_project_root; -use et_int_gen::{generate, generate_bindings, generate_core, generate_rust, generate_zig, wit::upstream}; - -#[derive(Parser)] -#[command(about = "Generate checked-in artifacts under generated/ from in-repo Rust sources of truth")] -struct Cli { - #[command(subcommand)] - command: Option, - - /// Print the full clap help tree as markdown (used to regenerate HELP.md). - #[cfg(feature = "markdown-help")] - #[arg(long, hide = true)] - markdown_help: bool, -} - -#[derive(Subcommand)] -enum Command { - /// Emit the generated artifacts for one target (default: all). - Generate { - /// Which artifacts to emit; defaults to `all`. - #[arg(value_enum, default_value_t = Target::All)] - target: Target, - }, - /// Fetch upstream WASI WIT packages into generated/specs/wit/ at pinned versions. - FetchDeps, -} - -/// Per-language target selector for the `generate` subcommand. -/// -/// Mirrors the `MISE_ENV`-scoped `gen:*` tasks: `core` (language-agnostic specs), `rust`, `bindings`, `zig`, or `all`. -#[derive(Clone, Copy, ValueEnum)] -enum Target { - /// Language-agnostic specs: AsyncAPI/OpenAPI YAML, WIT, KDL, schema JSON. - Core, - /// The typed Rust REST client. - Rust, - /// The wasmtime host bindings for the ws-wasi-runner `runner` world. - Bindings, - /// The Zig REST client (skipped when openapi2zig is absent). - Zig, - /// Core + Rust + bindings + Zig. - All, -} +use et_int_gen::cli::{Cli, Command, Target}; +use et_int_gen::{ + check_checks, check_help, generate, generate_bindings, generate_checks, generate_core, generate_help, + generate_rust, generate_zig, wit::upstream, +}; fn main() -> Result<(), et_int_gen::Error> { let cli = Cli::parse(); - #[cfg(feature = "markdown-help")] - if cli.markdown_help { - clap_markdown::print_help_markdown::(); - return Ok(()); - } - match cli.command.unwrap_or(Command::Generate { target: Target::All }) { Command::Generate { target } => match target { Target::Core => generate_core(), @@ -64,5 +21,9 @@ fn main() -> Result<(), et_int_gen::Error> { Target::All => generate(), }, Command::FetchDeps => upstream::run(&get_project_root()), + Command::Checks { check: true } => check_checks(), + Command::Checks { check: false } => generate_checks(), + Command::HelpMd { check: true } => check_help(), + Command::HelpMd { check: false } => generate_help(), } } diff --git a/utilities/int-gen/src/checks.rs b/utilities/int-gen/src/checks.rs new file mode 100644 index 00000000..d6e051c7 --- /dev/null +++ b/utilities/int-gen/src/checks.rs @@ -0,0 +1,1051 @@ +//! Render `CHECKS.md`, the catalogue of every check this repo runs. +//! +//! The source of truth is the task tables of every `.mise/config*.toml`, read as plain TOML rather than through +//! `mise tasks`: mise loads only the configs its `MISE_ENV` and the host OS select, and the document has to come out +//! identical whichever lane renders it. A check is any task the `check` / `check:` aggregates reach through +//! `depends`, plus any task named as a check that nothing reaches, which the document marks as run by hand. Each +//! check is filed under the tool its `run` body invokes -- the first command that is not shell plumbing -- or under +//! the shell-script section when it invokes none. Where a check's configuration is a set of rules this repo writes, +//! every rule is listed too, with the name and description its rule file gives it. +#![expect( + clippy::single_call_fn, + reason = "each helper is one named step of the render, kept separate so the steps read one at a time" +)] + +use std::collections::{BTreeMap, BTreeSet}; +use std::fmt::Write as _; +use std::path::{Path, PathBuf}; + +use command_error::CommandExt as _; +use fs_err as fs; +use regex::Regex; +use serde::Deserialize as _; + +use crate::Error; + +/// The line width the rendered document wraps to, which is the repo-wide editorconfig limit. +const WIDTH: usize = 120; + +/// The section heading for checks whose `run` body invokes no tool beyond shell plumbing. +const SHELL_SECTION: &str = "Shell-script checks"; + +/// Commands that only move data around a check rather than performing it. +/// +/// A command word in this list ends the search through that command, so its arguments are never mistaken for the tool: +/// in `git ls-files | xargs ` the tool is the one `xargs` runs, and a body built only from these is a shell +/// script. +const PLUMBING: &[&str] = &[ + ":", + "cat", + "cd", + "command", + "coreutils", + "cp", + "cut", + "echo", + "exit", + "export", + "false", + "find", + "gh", + "git", + "goawk", + "jaq", + "jq", + "local", + "ls", + "mise", + "mkdir", + "mv", + "printf", + "read", + "return", + "rg", + "rm", + "set", + "shift", + "sort", + "tr", + "true", + "yq", +]; + +/// Shell words that introduce a command rather than being one, so the search continues past them. +const PREFIXES: &[&str] = &[ + "!", "do", "done", "elif", "else", "esac", "fi", "if", "then", "until", "while", "{", "}", +]; + +/// Configs a tool finds by itself, from the repo root or an `[env]` variable, rather than through its command line. +const IMPLICIT_CONFIGS: &[(&str, &[&str])] = &[ + ("cargo clippy", &["Cargo.toml", "config/clippy.toml"]), + ("cargo fmt", &[".rustfmt.toml"]), + ("dprint", &[".dprint.jsonc", "config/dprint.jsonc"]), + ("editorconfig-checker", &[".editorconfig"]), + ("ruff", &["ruff.toml"]), + ("semgrep", &[".semgrepignore"]), + ("taplo", &["config/taplo.toml"]), +]; + +/// For each check, the aggregates that list it in `depends`. +type Parents = BTreeMap>; + +/// One task as one config file declares it. +struct Task { + name: String, + env: String, + description: String, + body: String, + depends: Vec, +} + +/// One rule this repo writes, with the description its rule file gives it. +struct Rule { + name: String, + description: String, + /// The rule's documentation page, or empty for a rule whose description is all there is. + link: String, +} + +/// The rules one section's checks are configured with. +struct SectionRules { + /// The deepest directory every rule file shares. + location: String, + rendered: String, + count: usize, +} + +/// What a single shell command contributed to the search for a check's tool. +enum Found { + Tool(String), + Nothing, +} + +/// Render the whole document from the configs and rule files under `root`. +pub fn render(root: &Path) -> Result { + let tasks = load_tasks(&root.join(".mise"))?; + let (reached, parents) = reachable(&tasks)?; + let check_name = Regex::new("(?:^|[-:])check(?:$|[-:])|crosscheck")?; + + let mut sections: BTreeMap> = BTreeMap::new(); + for task in &tasks { + let aggregate = task.name == "check" || task.name.starts_with("check:"); + let wrapper = task.body.contains("mise run "); + let listed = reached.contains(&task.name) || check_name.is_match(&task.name); + if listed && !aggregate && !wrapper && !task.body.trim().is_empty() { + sections.entry(runner_label(&task.body)?).or_default().push(task); + } + } + + let shell = sections.remove(SHELL_SECTION); + let mut body = String::default(); + let mut rule_count = 0_usize; + for (label, entries) in §ions { + writeln!(body, "\n## `{label}`\n")?; + render_entries(&mut body, label, entries, &parents)?; + let rules = section_rules(root, label, entries)?; + rule_count = rule_count.saturating_add(rules.count); + if !rules.rendered.is_empty() { + writeln!(body, "\nRules, from `{}`:\n", rules.location)?; + body.push_str(&rules.rendered); + } + } + let check_count = sections.values().chain(&shell).map(Vec::len).sum::(); + let shell_count = shell.as_ref().map_or(0, Vec::len); + if let Some(entries) = shell { + writeln!(body, "\n## {SHELL_SECTION}\n")?; + render_entries(&mut body, SHELL_SECTION, &entries, &parents)?; + } + + let mut out = String::from("# Checks\n\n"); + writeln!(out, "- **Checks:** {check_count}")?; + writeln!(out, "- **Tools:** {}", sections.len())?; + writeln!(out, "- **Shell-script checks:** {shell_count}")?; + writeln!( + out, + "- **Rules:** {rule_count} custom local rules, or non-default strict linter settings\n" + )?; + let intro = [ + "Every check is listed across every `MISE_ENV`, filed under the tool it runs. Each entry names the env", + "whose config declares it, the aggregate that runs it as part of `mise run check`, and the config files", + "it reads. Generated by `mise run gen:checks` from the task tables in `.mise/config*.toml`, the rule", + "files under `config/` and the `[workspace.lints]` in `Cargo.toml`; `mise run checks-md-check` fails when", + "this file drifts from them.", + ]; + out.push_str(&wrap("", "", &intro.join(" "))); + out.push_str(&body); + Ok(out) +} + +/// Name the tool a `run` body invokes, or the shell-script section when it invokes none. +/// +/// The search walks the body's commands in order and returns the first command word that is not shell plumbing. `cargo +/// ` is reported with its subcommand, since each one is a different checker, and `cargo run -p ` as the +/// package it runs. An upper-case `$VAR` in command position is a tool the env hands over (`$MVN`), and a `$(...)` +/// substitution is searched like any other command. +pub fn runner_label(body: &str) -> Result { + let assignment = Regex::new("^[A-Za-z_][A-Za-z0-9_]*=")?; + let command_word = Regex::new("^[A-Za-z][A-Za-z0-9_.+-]*$")?; + for command in commands(body) { + if let Found::Tool(tool) = command_tool(&command, &assignment, &command_word)? { + return Ok(tool); + } + } + Ok(SHELL_SECTION.to_owned()) +} + +/// Every config file path a `run` body or its task's env names: `config/...` and the `.mise/` helper scripts. +pub fn config_paths(text: &str) -> Result, Error> { + let path = Regex::new(r"(?:^|[^\w.-])((?:config/[\w./-]*\w)|(?:\.mise/[\w-]+\.(?:awk|jq|sh)))")?; + Ok(path + .captures_iter(text) + .filter_map(|caps| caps.get(1)) + .map(|found| found.as_str().to_owned()) + .collect()) +} + +/// The summary line of every `deny` / `warn` rule in one Rego policy, in source order. +/// +/// A rule's summary is the first line of the last top-level comment block before it within the same stretch of the file +/// -- the comments between the previous rule's closing brace and this rule. Every rule must have one: a rule with no +/// comment of its own is an error naming `file` and the rule's line, since the catalogue lists every rule by its +/// description. +pub fn rego_summaries(file: &str, source: &str) -> Result, Error> { + let mut summaries = Vec::new(); + let mut summary = String::default(); + let mut in_block = false; + for (index, line) in source.lines().enumerate() { + if let Some(comment) = line.strip_prefix('#') { + if !in_block { + comment.trim().clone_into(&mut summary); + } + in_block = true; + continue; + } + in_block = false; + if line.starts_with("deny") || line.starts_with("warn") { + if summary.is_empty() { + let line_number = index.saturating_add(1); + return Err(Error::UndescribedRule(format!( + "{file}:{line_number}: rule has no summary comment; describe it in a comment directly above it" + ))); + } + summaries.push(core::mem::take(&mut summary)); + } else if line == "}" || line.starts_with("package ") { + summary.clear(); + } else { + // A helper definition between a rule's comment and the rule keeps that comment as the summary. + } + } + Ok(summaries) +} + +/// Fail unless a rule's description field is present and non-empty. +fn described(file: &Path, rule: &str, field: &str, value: &str) -> Result<(), Error> { + if value.trim().is_empty() { + let file = file.display(); + Err(Error::UndescribedRule(format!( + "{file}: rule `{rule}` has no `{field}` describing it" + ))) + } else { + Ok(()) + } +} + +/// Wrap `text` to the document width, the first line behind `first` and every later line behind `rest`. +#[must_use] +pub fn wrap(first: &str, rest: &str, text: &str) -> String { + let mut out = String::default(); + let mut line = first.to_owned(); + let mut prefix_len = first.len(); + let mut empty = true; + for word in text.split_whitespace() { + let needed = line.len().saturating_add(1).saturating_add(word.len()); + if !empty && needed > WIDTH { + // A continuation line must not open with a Markdown block marker, or it starts a new list item, quote or + // heading; the word before it moves down too so the marker is never first. + let carried = match line.rsplit_once(' ') { + Some((head, last)) if starts_block(word) && head.len() > prefix_len => { + let last = last.to_owned(); + line.truncate(head.len()); + last + } + Some(_) | None => String::default(), + }; + out.push_str(line.trim_end()); + out.push('\n'); + rest.clone_into(&mut line); + prefix_len = rest.len(); + empty = carried.is_empty(); + line.push_str(&carried); + } + if !empty { + line.push(' '); + } + line.push_str(word); + empty = false; + } + out.push_str(line.trim_end()); + out.push('\n'); + out +} + +/// Whether a word would open a Markdown block -- a list item, quote or heading -- if it began a line. +fn starts_block(word: &str) -> bool { + let ordinal = word + .strip_suffix(['.', ')']) + .is_some_and(|number| !number.is_empty() && number.chars().all(|digit| digit.is_ascii_digit())); + matches!(word, "+" | "-" | "*" | ">") || word.starts_with('#') || ordinal +} + +/// Read every task from every `config*.toml` in `mise_dir`, in file order. +fn load_tasks(mise_dir: &Path) -> Result, Error> { + let mut files: Vec<_> = fs::read_dir(mise_dir)? + .map(|entry| entry.map(|found| found.path())) + .collect::>()?; + files.sort(); + let mut tasks = Vec::new(); + for file in files { + let Some(file_name) = file.file_name().and_then(|name| name.to_str()) else { + continue; + }; + let Some(env) = file_name + .strip_prefix("config") + .and_then(|rest| rest.strip_suffix(".toml")) + else { + continue; + }; + // A mise local override is untracked and per-machine, so its tasks must never reach the committed catalogue. + if env == ".local" || has_extension(Path::new(env), "local") { + continue; + } + let env = env.strip_prefix('.').unwrap_or("default").to_owned(); + let table: toml::Table = toml::from_str(&fs::read_to_string(&file)?)?; + let Some(defined) = table.get("tasks").and_then(toml::Value::as_table) else { + continue; + }; + for (name, value) in defined { + tasks.push(task(name, &env, value)); + } + } + Ok(tasks) +} + +/// Build one task from its TOML value: a full table, or the `name = "command"` shorthand. +fn task(name: &str, env: &str, value: &toml::Value) -> Task { + let text = |key: &str| value.get(key).map(strings).unwrap_or_default().join("\n"); + let mut body = value.as_str().map_or_else(|| text("run"), str::to_owned); + let windows = text("run_windows"); + if !windows.is_empty() { + body.push('\n'); + body.push_str(&windows); + } + let env_values = value.get("env").and_then(toml::Value::as_table).map(|table| { + table + .values() + .filter_map(toml::Value::as_str) + .collect::>() + .join("\n") + }); + if let Some(env_values) = env_values { + body.push('\n'); + body.push_str(&env_values); + } + Task { + name: name.to_owned(), + env: env.to_owned(), + description: text("description"), + body, + depends: value.get("depends").map(strings).unwrap_or_default(), + } +} + +/// The strings a TOML value holds: itself, each string of an array, or each `task` of an array of tables. +fn strings(value: &toml::Value) -> Vec { + if let Some(single) = value.as_str() { + return vec![single.to_owned()]; + } + value + .as_array() + .map(|items| { + items + .iter() + .filter_map(|item| item.as_str().or_else(|| item.get("task").and_then(toml::Value::as_str))) + .map(str::to_owned) + .collect() + }) + .unwrap_or_default() +} + +/// Every task the `check` aggregates run, and for each one the aggregates that list it in `depends`. +/// +/// The search descends only through aggregates -- tasks with no `run` of their own, which only group other checks -- +/// so a check's own prerequisites (the generator a drift check reruns first) are not mistaken for checks. +fn reachable(tasks: &[Task]) -> Result<(BTreeSet, Parents), Error> { + let names: BTreeSet<&str> = tasks.iter().map(|task| task.name.as_str()).collect(); + let mut depends: BTreeMap<&str, Vec<&str>> = BTreeMap::new(); + for task in tasks.iter().filter(|task| task.body.trim().is_empty()) { + depends + .entry(&task.name) + .or_default() + .extend(task.depends.iter().map(String::as_str)); + } + let mut queue: Vec = names + .iter() + .filter(|name| **name == "check" || name.starts_with("check:")) + .map(|name| (*name).to_owned()) + .collect(); + let mut reached: BTreeSet = queue.iter().cloned().collect(); + let mut parents: BTreeMap> = BTreeMap::new(); + while let Some(parent) = queue.pop() { + for pattern in depends.get(parent.as_str()).into_iter().flatten() { + let glob = Regex::new(&format!("^{}$", regex::escape(pattern).replace(r"\*", ".*")))?; + for child in names.iter().filter(|name| glob.is_match(name)) { + let _first_parent: bool = parents.entry((*child).to_owned()).or_default().insert(parent.clone()); + if reached.insert((*child).to_owned()) { + queue.push((*child).to_owned()); + } + } + } + } + Ok((reached, parents)) +} + +/// Split a shell body into its commands, each a list of words with the shell's quoting removed. +/// +/// Commands end at an unquoted newline, `;`, `|`, `||` or `&&`. A `$(...)` substitution stays one word, operators and +/// all, so it can be searched as a command of its own, and a `#` that starts a word comments out the rest of the line. +fn commands(body: &str) -> Vec> { + let mut commands = Vec::new(); + let mut words = Vec::new(); + let mut word = String::default(); + let mut quote = None; + let mut inner_quote = None; + let mut depth = 0_usize; + let mut comment = false; + let mut chars = body.chars().peekable(); + while let Some(current) = chars.next() { + if comment { + if current == '\n' { + comment = false; + end_command(&mut commands, &mut words, &mut word); + } + continue; + } + if let Some(open) = quote { + if current == open { + quote = None; + } else { + word.push(current); + } + continue; + } + if current == '$' && chars.peek() == Some(&'(') { + depth = depth.saturating_add(1); + word.push(current); + continue; + } + if depth > 0 { + // Quotes inside the substitution are kept, and shield a `)` they contain from closing it. + if inner_quote == Some(current) { + inner_quote = None; + } else if inner_quote.is_none() && matches!(current, '\'' | '"') { + inner_quote = Some(current); + } else if inner_quote.is_none() && current == ')' { + depth = depth.saturating_sub(1); + } else { + // Any other character is part of the substitution's text. + } + word.push(current); + continue; + } + match current { + '\'' | '"' => quote = Some(current), + '#' if word.is_empty() => comment = true, + '\n' | ';' | '|' | '&' => end_command(&mut commands, &mut words, &mut word), + ' ' | '\t' => end_word(&mut words, &mut word), + _ => word.push(current), + } + } + end_command(&mut commands, &mut words, &mut word); + commands +} + +/// Close the word being built, if any. +fn end_word(words: &mut Vec, word: &mut String) { + if !word.is_empty() { + words.push(core::mem::take(word)); + } +} + +/// Close the word and the command being built, if any. +fn end_command(commands: &mut Vec>, words: &mut Vec, word: &mut String) { + end_word(words, word); + if !words.is_empty() { + commands.push(core::mem::take(words)); + } +} + +/// Search a `$(...)` substitution's command for the tool it runs. +fn substitution_tool(inner: &str) -> Result { + let tool = runner_label(inner)?; + Ok(if tool == SHELL_SECTION { + Found::Nothing + } else { + Found::Tool(tool) + }) +} + +/// Search one command for the tool it runs. +fn command_tool(words: &[String], assignment: &Regex, command: &Regex) -> Result { + let mut rest = words.iter(); + let mut after_xargs = false; + while let Some(word) = rest.next() { + if let Some(inner) = word.strip_prefix("$(").and_then(|inner| inner.strip_suffix(')')) { + return substitution_tool(inner); + } + if word.starts_with("{{") { + if !word.ends_with("}}") { + let _closing: Option<&String> = rest.by_ref().find(|later| later.ends_with("}}")); + } + continue; + } + if assignment.is_match(word) { + let value = word.split_once('=').map(|(_, value)| value).unwrap_or_default(); + let inner = value.strip_prefix("$(").and_then(|inner| inner.strip_suffix(')')); + if let Some(Found::Tool(tool)) = inner.map(substitution_tool).transpose()? { + return Ok(Found::Tool(tool)); + } + continue; + } + if after_xargs && word.starts_with('-') { + continue; + } + let name = word.as_str(); + if name == "xargs" { + after_xargs = true; + continue; + } + if PREFIXES.contains(&name) { + continue; + } + if PLUMBING.contains(&name) || matches!(name, "[" | "[[" | "test" | "for" | "case" | "eval") { + return Ok(Found::Nothing); + } + if name == "cargo" { + return Ok(Found::Tool(cargo_label(rest.as_slice()))); + } + if name == "conda_exe" { + let binary = rest.nth(1).map_or_else(|| "conda_exe".to_owned(), Clone::clone); + return Ok(Found::Tool(binary)); + } + if let Some(variable) = name.strip_prefix('$') { + if !variable.is_empty() + && variable + .chars() + .all(|letter| letter.is_ascii_uppercase() || letter == '_') + { + return Ok(Found::Tool(variable.to_ascii_lowercase())); + } + return Ok(Found::Nothing); + } + if command.is_match(name) { + return Ok(Found::Tool(name.to_owned())); + } + return Ok(Found::Nothing); + } + Ok(Found::Nothing) +} + +/// Label a `cargo` invocation by its subcommand, or by the package a `cargo run -p` runs. +/// +/// A `+toolchain` selector is skipped, including one spelt as a `+{{ vars.... }}` template across several words. +fn cargo_label(args: &[String]) -> String { + let mut in_template = false; + let mut words = args.iter().filter(|word| { + let skip = in_template || word.starts_with('+'); + if word.contains("{{") && !word.contains("}}") { + in_template = true; + } else if word.contains("}}") { + in_template = false; + } else { + // A word outside any template leaves the state as it was. + } + !skip + }); + let Some(subcommand) = words.next() else { + return "cargo".to_owned(); + }; + if subcommand == "run" { + let mut after = words.skip_while(|word| *word != "-p"); + if let Some(package) = after.nth(1).filter(|package| !package.starts_with('$')) { + return package.clone(); + } + } + format!("cargo {subcommand}") +} + +/// Write one section's checks, each with its env, the aggregate that runs it, its description and its configs. +fn render_entries(out: &mut String, label: &str, entries: &[&Task], parents: &Parents) -> Result<(), Error> { + let mut sorted = entries.to_vec(); + sorted.sort_by(|left, right| (&left.name, &left.env).cmp(&(&right.name, &right.env))); + for task in sorted { + let run_by = parents.get(&task.name).map_or_else( + || "not run by `mise run check`".to_owned(), + |names| { + format!( + "run by {}", + names + .iter() + .map(|name| format!("`{name}`")) + .collect::>() + .join(", ") + ) + }, + ); + let mut configs = config_paths(&task.body)?; + configs.extend(implicit_configs(label).iter().map(|path| (*path).to_owned())); + let mut text = format!("`{}` (`{}` env; {run_by})", task.name, task.env); + if !task.description.is_empty() { + write!(text, " -- {}", task.description.trim_end_matches('.'))?; + } + text.push('.'); + if !configs.is_empty() { + let listed = configs + .iter() + .map(|path| format!("`{path}`")) + .collect::>() + .join(", "); + write!(text, " Config: {listed}.")?; + } + out.push_str(&wrap("- ", " ", &text)); + } + Ok(()) +} + +/// The paths a `run` body passes as a tool's configuration: those following a config-style flag. +/// +/// A path handed over as an input to check rather than as configuration -- a rule directory a policy validates the +/// layout of -- follows no such flag, so it is not mistaken for the rules of the check that reads it. +pub fn rule_sources(body: &str) -> Result, Error> { + let flagged = Regex::new( + r#"(?:^|\s)(?:--config-file|--config|--policy|--schema|--rule|-c|-p)(?:\s+|=)"?[^"\s]*?(config/[\w./-]*\w)"#, + )?; + Ok(flagged + .captures_iter(body) + .filter_map(|caps| caps.get(1)) + .map(|found| found.as_str().to_owned()) + .collect()) +} + +/// The rules a section's checks are configured with, and the deepest directory every rule file shares. +/// +/// Rule files are recognised by format rather than by tool: a `.rego` policy (its tests excepted), a `.schema.json` +/// schema, and a YAML document that is a rule (`id` + `message`), lists rules (`rules:` as a sequence), or points at +/// directories of them (`ruleDirs:`), and a TOML manifest's `[workspace.lints]` tables. Sources are the paths the +/// checks pass as configuration plus the configs the section's tool finds by itself. A directory is searched +/// recursively. A section with none renders nothing. +fn section_rules(root: &Path, label: &str, entries: &[&Task]) -> Result { + let mut sources = BTreeSet::new(); + for task in entries { + sources.extend(rule_sources(&task.body)?); + } + sources.extend(implicit_configs(label).iter().map(|path| (*path).to_owned())); + let mut files = BTreeSet::new(); + for source in sources { + collect_rule_files(&root.join(source), &mut files)?; + } + let mut listed = Vec::new(); + let mut policies = String::default(); + let mut policy_rules = 0_usize; + for file in &files { + let name = file.file_name().and_then(|found| found.to_str()).unwrap_or_default(); + if let Some(stem) = name.strip_suffix(".rego") { + let summaries = rego_summaries(&relative_path(root, file), &fs::read_to_string(file)?)?; + policy_rules = policy_rules.saturating_add(summaries.len()); + policies.push_str(&render_policy(root, file, stem, &summaries)); + } else if let Some(stem) = name.strip_suffix(".schema.json") { + listed.push(schema_rule(file, stem)?); + } else if has_extension(file, "toml") { + listed.extend(lint_rules(file)?); + } else { + listed.extend(yaml_rules(file)?); + } + } + listed.sort_by(|left, right| left.name.cmp(&right.name)); + let mut rendered = render_rules(&listed)?; + rendered.push_str(&policies); + let location = match files.iter().collect::>().as_slice() { + [single] => relative_path(root, single), + _ => common_dir(root, &files), + }; + Ok(SectionRules { + location, + rendered, + count: listed.len().saturating_add(policy_rules), + }) +} + +/// Add every rule file at `path` to `files`, searching a directory recursively and following `ruleDirs`. +fn collect_rule_files(path: &Path, files: &mut BTreeSet) -> Result<(), Error> { + if path.is_dir() { + let mut children: Vec<_> = fs::read_dir(path)? + .map(|entry| entry.map(|found| found.path())) + .collect::>()?; + children.sort(); + for child in children { + collect_rule_files(&child, files)?; + } + return Ok(()); + } + let name = path.file_name().and_then(|found| found.to_str()).unwrap_or_default(); + if !path.is_file() || name.ends_with("_test.rego") { + return Ok(()); + } + if has_extension(path, "rego") || is_schema(path) || (has_extension(path, "toml") && declares_lints(path)?) { + let _new_file: bool = files.insert(path.to_path_buf()); + return Ok(()); + } + if !has_extension(path, "yaml") { + return Ok(()); + } + for document in yaml_documents(path)? { + let rule_dirs = document.get("ruleDirs").and_then(serde_yaml::Value::as_sequence); + for dir in rule_dirs.into_iter().flatten().filter_map(serde_yaml::Value::as_str) { + collect_rule_files(&path.parent().unwrap_or(path).join(dir), files)?; + } + let single = document.get("id").is_some() && document.get("message").is_some(); + let listed = document.get("rules").and_then(serde_yaml::Value::as_sequence).is_some(); + if single || listed { + let _new_file: bool = files.insert(path.to_path_buf()); + } + } + Ok(()) +} + +/// The configs a section's tool finds by itself, or none. +fn implicit_configs(label: &str) -> &'static [&'static str] { + IMPLICIT_CONFIGS + .iter() + .find(|(tool, _)| *tool == label) + .map_or(&[], |(_, paths)| paths) +} + +/// The `[workspace.lints]` tables of a TOML manifest, keyed by lint tool (`rust`, `clippy`, `rustdoc`). +fn workspace_lints(path: &Path) -> Result { + let manifest: toml::Table = toml::from_str(&fs::read_to_string(path)?)?; + let lints = manifest.get("workspace").and_then(|workspace| workspace.get("lints")); + Ok(lints.and_then(toml::Value::as_table).cloned().unwrap_or_default()) +} + +/// Whether a TOML manifest configures any lints in `[workspace.lints]`. +fn declares_lints(path: &Path) -> Result { + Ok(!workspace_lints(path)?.is_empty()) +} + +/// A `[workspace.lints.]` entry's lint, named as a `#[expect]` would name it. +/// +/// A lint of the `rust` table is the compiler's own and goes unprefixed; every other table names its tool, as in +/// `clippy::unwrap_used`. +fn lint_name(tool: &str, lint: &str) -> String { + if tool == "rust" { + lint.to_owned() + } else { + format!("{tool}::{lint}") + } +} + +/// The lint each `[workspace.lints]` entry is marked as the opposite of, keyed by the entry's `lint_name`. +/// +/// Some lints, most of them in clippy's `restriction` group, come in pairs where one demands the spelling the other +/// rejects, so the workspace can deny at most one of the two. The entry that settles such a pair carries an +/// `# Opposite of .` line in the comment block directly above it, naming the other lint the same way. +#[must_use] +pub fn lint_opposites(manifest: &str) -> BTreeMap { + let mut opposites = Vec::new(); + let mut tool = ""; + let mut opposite = ""; + for line in manifest.lines().map(str::trim) { + if let Some(header) = line.strip_prefix('[') { + tool = header + .strip_prefix("workspace.lints.") + .and_then(|rest| rest.strip_suffix(']')) + .unwrap_or_default(); + opposite = ""; + } else if let Some(comment) = line.strip_prefix('#') { + if let Some(name) = comment + .trim() + .strip_prefix("Opposite of ") + .and_then(|rest| rest.strip_suffix('.')) + { + opposite = name; + } + } else if let Some((lint, _)) = line.split_once('=') + && !tool.is_empty() + && !opposite.is_empty() + { + opposites.push((lint_name(tool, lint.trim()), opposite.to_owned())); + opposite = ""; + } else { + opposite = ""; + } + } + opposites.into_iter().collect() +} + +/// Every lint a manifest's `[workspace.lints]` sets, named by [`lint_name`], with its level. +/// +/// The description is the level, with the priority when one is set and the lint it is the opposite of when its entry +/// is marked as one by [`lint_opposites`]. +fn lint_rules(path: &Path) -> Result, Error> { + let rustc_levels = rustc_lint_levels()?; + let opposites = lint_opposites(&fs::read_to_string(path)?); + let mut rules = Vec::new(); + for (tool, lints) in workspace_lints(path)? { + for (lint, setting) in lints.as_table().into_iter().flatten() { + let name = lint_name(&tool, lint); + let level = setting + .as_str() + .or_else(|| setting.get("level").and_then(toml::Value::as_str)) + .unwrap_or_default(); + described(path, &name, "level", level)?; + let priority = setting.get("priority").and_then(toml::Value::as_integer); + let mut description = priority.map_or_else(|| level.to_owned(), |rank| format!("{level}, priority {rank}")); + if let Some(opposite) = opposites.get(&name) { + write!(description, ", opposite of `{opposite}`")?; + } + let link = lint_link(&tool, lint, &rustc_levels); + rules.push(Rule { + name, + description, + link, + }); + } + } + Ok(rules) +} + +/// Whether `path` carries `extension`, compared case-insensitively. +fn has_extension(path: &Path, extension: &str) -> bool { + path.extension() + .is_some_and(|found| found.eq_ignore_ascii_case(extension)) +} + +/// Whether `path` is a JSON schema, named `.schema.json`. +fn is_schema(path: &Path) -> bool { + has_extension(path, "json") + && path + .file_stem() + .is_some_and(|stem| has_extension(Path::new(stem), "schema")) +} + +/// Every YAML document in one file. +fn yaml_documents(path: &Path) -> Result, Error> { + let source = fs::read_to_string(path)?; + let mut documents = Vec::new(); + for document in serde_yaml::Deserializer::from_str(&source) { + documents.push(serde_yaml::Value::deserialize(document)?); + } + Ok(documents) +} + +/// The rules one YAML rule file defines: each document that is a rule, or each entry of a `rules:` list. +fn yaml_rules(path: &Path) -> Result, Error> { + let mut rules = Vec::new(); + for document in yaml_documents(path)? { + let entries = document + .get("rules") + .and_then(serde_yaml::Value::as_sequence) + .map_or_else(|| vec![document.clone()], Clone::clone); + for entry in entries.iter().filter(|entry| entry.get("id").is_some()) { + let field = |key: &str| { + entry + .get(key) + .and_then(serde_yaml::Value::as_str) + .unwrap_or_default() + .to_owned() + }; + let rule = Rule { + name: field("id"), + description: field("message"), + link: String::default(), + }; + described(path, &rule.name, "message", &rule.description)?; + rules.push(rule); + } + } + Ok(rules) +} + +/// One schema rule: the schema's file stem, with its `title` and `description`. +fn schema_rule(path: &Path, stem: &str) -> Result { + let schema: serde_json::Value = serde_json::from_str(&fs::read_to_string(path)?)?; + let field = |key: &str| { + schema + .get(key) + .and_then(serde_json::Value::as_str) + .unwrap_or_default() + .to_owned() + }; + described(path, stem, "title", &field("title"))?; + described(path, stem, "description", &field("description"))?; + Ok(Rule { + name: stem.to_owned(), + description: format!("{}: {}", field("title"), field("description")), + link: String::default(), + }) +} + +/// One policy file, followed by the summary of each of its rules; nothing for a file with no rules. +fn render_policy(root: &Path, path: &Path, stem: &str, summaries: &[String]) -> String { + if summaries.is_empty() { + return String::default(); + } + let relative = relative_path(root, path); + let mut out = wrap("- ", " ", &format!("`{stem}` (`{relative}`):")); + for summary in summaries { + out.push_str(&wrap(" - ", " ", summary)); + } + out +} + +/// The deepest directory, relative to `root`, that contains every one of `files`. +fn common_dir(root: &Path, files: &BTreeSet) -> String { + let mut parents = files.iter().filter_map(|file| file.parent()); + let Some(first) = parents.next() else { + return String::default(); + }; + let mut common = first.to_path_buf(); + for parent in parents { + while !parent.starts_with(&common) { + if !common.pop() { + break; + } + } + } + relative_path(root, &common) +} + +/// `path` relative to `root`, with `/` separators on every platform. +fn relative_path(root: &Path, path: &Path) -> String { + path.strip_prefix(root) + .unwrap_or(path) + .to_string_lossy() + .replace('\\', "/") +} + +/// Render a rule list, one bullet per rule, its description flattened onto wrapped lines. +/// +/// A rule with a documentation page links to it through a reference labelled by [`link_label`], its URL defined +/// after the list, so a long lint name and its URL never have to share one line. +fn render_rules(rules: &[Rule]) -> Result { + let mut out = String::default(); + let mut references = String::default(); + let mut labels = BTreeSet::new(); + for rule in rules { + let mut shown = format!("`{}`", rule.name); + if !rule.link.is_empty() { + let label = link_label(&rule.name, &rule.link); + if !labels.insert(label.clone()) { + return Err(Error::DuplicateLinkLabel(format!( + "`{}` would share the link label `{label}` with an earlier rule", + rule.name + ))); + } + writeln!(references, "[{label}]: {}", rule.link)?; + shown = format!("[{shown}][{label}]"); + } + out.push_str(&wrap("- ", " ", &format!("{shown} -- {}", rule.description))); + } + if !references.is_empty() { + out.push('\n'); + out.push_str(&references); + } + Ok(out) +} + +/// The reference label a rule's documentation link is defined under, derived from the rule's name alone. +/// +/// The label is the name without its tool prefix, so adding or removing a rule never relabels any other. Where +/// `[label]: ` would run past `WIDTH`, whole words are dropped from the end of the name until it fits -- +/// `allow_attributes_without_reason` becomes `allow_attributes_without` -- which is just as stable, and leaves only +/// real words for the spell checker to read. +#[must_use] +pub fn link_label(name: &str, link: &str) -> String { + let bare = name.rsplit("::").next().unwrap_or(name); + let budget = WIDTH.saturating_sub(link.len()).saturating_sub("[]: ".len()); + let mut words: Vec<&str> = bare.split('_').collect(); + while words.len() > 1 && words.join("_").len() > budget { + let _: Option<&str> = words.pop(); + } + words.join("_") +} + +/// The lint groups, which name a set of lints and have no entry of their own in the lint index. +const CLIPPY_GROUPS: &[&str] = &[ + "all", + "cargo", + "complexity", + "correctness", + "nursery", + "pedantic", + "perf", + "restriction", + "style", + "suspicious", +]; + +/// The documentation page for one lint of a `[workspace.lints.]` table, or empty when it has none. +/// +/// A clippy lint links to its entry in the stable lint index, and a clippy group to nothing, since groups have no +/// entry there. A rustdoc lint links to its heading on the rustdoc lints page. A compiler lint's page depends on its +/// default level -- the rustc book lists allow-, warn- and deny-by-default lints on separate pages, and groups on a +/// fourth -- so it is found in `rustc_levels`; a lint the installed rustc does not list stays unlinked. +fn lint_link(tool: &str, lint: &str, rustc_levels: &BTreeMap) -> String { + let anchor = lint.replace('_', "-"); + let rustc_page = |page: &str| format!("https://doc.rust-lang.org/rustc/lints/listing/{page}"); + match tool { + "clippy" if !CLIPPY_GROUPS.contains(&lint) => { + format!("https://rust-lang.github.io/rust-clippy/stable/index.html#{lint}") + } + "rustdoc" => format!("https://doc.rust-lang.org/rustdoc/lints.html#{lint}"), + "rust" => match rustc_levels.get(lint).map(String::as_str) { + Some("group") => "https://doc.rust-lang.org/rustc/lints/groups.html".to_owned(), + Some("allow") => rustc_page(&format!("allowed-by-default.html#{anchor}")), + Some("warn") => rustc_page(&format!("warn-by-default.html#{anchor}")), + Some("deny" | "forbid") => rustc_page(&format!("deny-by-default.html#{anchor}")), + Some(_) | None => String::default(), + }, + _ => String::default(), + } +} + +/// The default level rustc gives each of its own lints, and `group` for each lint group, read from `rustc -W help`. +/// +/// Names are returned in their `snake_case` spelling, as `[workspace.lints.rust]` writes them; rustc prints them +/// hyphenated. +fn rustc_lint_levels() -> Result, Error> { + let help = std::process::Command::new("rustc") + .args(["-W", "help"]) + .output_checked_utf8()? + .stdout; + let mut levels = BTreeMap::new(); + let mut in_groups = false; + for line in help.lines() { + if line.starts_with("Lint groups provided by rustc") { + in_groups = true; + continue; + } + let mut columns = line.split_whitespace(); + let (Some(name), Some(second)) = (columns.next(), columns.next()) else { + continue; + }; + if name == "name" || name.starts_with("----") { + continue; + } + let level = if in_groups { "group" } else { second }; + if in_groups || matches!(level, "allow" | "warn" | "deny" | "forbid") { + let _previous: Option = levels.insert(name.replace('-', "_"), level.to_owned()); + } + } + Ok(levels) +} diff --git a/utilities/int-gen/src/cli.rs b/utilities/int-gen/src/cli.rs new file mode 100644 index 00000000..c15c8592 --- /dev/null +++ b/utilities/int-gen/src/cli.rs @@ -0,0 +1,60 @@ +//! The `et-int-gen` command line, kept in the library so [`crate::help`] can read its clap tree to write HELP.md. + +use clap::{Parser, Subcommand, ValueEnum}; + +#[derive(Parser)] +#[command(about = "Generate checked-in artifacts (generated/, CHECKS.md, HELP.md) from in-repo sources of truth")] +#[non_exhaustive] +pub struct Cli { + #[command(subcommand)] + pub command: Option, +} + +#[derive(Subcommand)] +#[expect( + clippy::exhaustive_enums, + reason = "the binary matches every subcommand, so adding one has to fail that match rather than fall through" +)] +pub enum Command { + /// Emit the generated artifacts for one target (default: all). + Generate { + /// Which artifacts to emit; defaults to `all`. + #[arg(value_enum, default_value_t = Target::All)] + target: Target, + }, + /// Fetch upstream WASI WIT packages into generated/specs/wit/ at pinned versions. + FetchDeps, + /// Write CHECKS.md, the catalogue of every check across every `MISE_ENV`. + Checks { + /// Compare against the committed CHECKS.md and fail on drift instead of writing it. + #[arg(long)] + check: bool, + }, + /// Write each utility's HELP.md from its clap command tree. + HelpMd { + /// Compare against the committed HELP.md files and fail on drift instead of writing them. + #[arg(long)] + check: bool, + }, +} + +/// Per-language target selector for the `generate` subcommand. +/// +/// Mirrors the `MISE_ENV`-scoped `gen:*` tasks: `core` (language-agnostic specs), `rust`, `bindings`, `zig`, or `all`. +#[derive(Clone, Copy, ValueEnum)] +#[expect( + clippy::exhaustive_enums, + reason = "the binary matches every target, so adding one has to fail that match rather than fall through" +)] +pub enum Target { + /// Language-agnostic specs: AsyncAPI/OpenAPI YAML, WIT, KDL, schema JSON. + Core, + /// The typed Rust REST client. + Rust, + /// The wasmtime host bindings for the ws-wasi-runner `runner` world. + Bindings, + /// The Zig REST client (skipped when openapi2zig is absent). + Zig, + /// Core + Rust + bindings + Zig. + All, +} diff --git a/utilities/int-gen/src/error.rs b/utilities/int-gen/src/error.rs index 8a303037..1be26ede 100644 --- a/utilities/int-gen/src/error.rs +++ b/utilities/int-gen/src/error.rs @@ -2,13 +2,12 @@ /// Errors raised by `et-int-gen`. /// -/// Every external error type that fallible functions can produce is wrapped -/// transparently via `#[from]`, so call sites just use `?`. Domain errors -/// (malformed schemas, missing `AsyncAPI` nodes, etc.) sit alongside as -/// non-transparent variants with static messages. +/// Every external error type that fallible functions can produce is wrapped transparently via `#[from]`, so call sites +/// just use `?`. Domain errors (malformed schemas, missing `AsyncAPI` nodes, etc.) sit alongside as non-transparent +/// variants with static messages. #[expect( - clippy::exhaustive_enums, clippy::error_impl_error, + clippy::exhaustive_enums, reason = "internal crate (no SemVer); new variants land with their change, and crate::Error is the sole error type" )] #[derive(Debug, thiserror::Error)] @@ -29,6 +28,21 @@ pub enum Error { Fmt(#[from] std::fmt::Error), #[error(transparent)] Regex(#[from] regex::Error), + #[error(transparent)] + Persist(#[from] tempfile::PersistError), + #[error(transparent)] + Toml(#[from] toml::de::Error), + + // The message is carried as data rather than only in the `#[error]` string because the binary's `main` reports + // errors through `Debug`, which would otherwise print the bare variant name. + #[error("{0}")] + ChecksStale(&'static str), + #[error("{0}")] + UndescribedRule(String), + #[error("{0}")] + DuplicateLinkLabel(String), + #[error("{0}")] + HelpStale(String), #[error("WS message JSON Schema malformed: {0}")] SchemaMalformed(&'static str), @@ -40,17 +54,17 @@ pub enum Error { Progenitor(#[from] progenitor::Error), #[error(transparent)] Syn(#[from] syn::Error), - // `wit-parser` and the wasmtime bindgen return `anyhow::Result`; this variant is what lets `?` convert - // one. A repo-wide rule keeps the name confined to this line. + // `wit-parser` and the wasmtime bindgen return `anyhow::Result`; this variant is what lets `?` convert one. A repo- + // wide rule keeps the name confined to this line. #[error(transparent)] Anyhow(#[from] anyhow::Error), #[error("zig codegen: {0}")] ZigCodegen(String), } -// Left uncovered by design: `LanguageError` has a private field and no public constructor, and `set_language` -// only returns it on a tree-sitter/grammar ABI mismatch -- which would break every Zig-parsing test -- so this -// conversion cannot be exercised by a unit test. +// Left uncovered by design: `LanguageError` has a private field and no public constructor, and `set_language` only +// returns it on a tree-sitter/grammar ABI mismatch -- which would break every Zig-parsing test -- so this conversion +// cannot be exercised by a unit test. impl From for Error { fn from(err: tree_sitter::LanguageError) -> Self { Self::ZigCodegen(format!("set Zig language: {err}")) diff --git a/utilities/int-gen/src/help.rs b/utilities/int-gen/src/help.rs new file mode 100644 index 00000000..39071f39 --- /dev/null +++ b/utilities/int-gen/src/help.rs @@ -0,0 +1,52 @@ +//! Render each utility's `HELP.md` from its clap command tree. +//! +//! clap-markdown writes the whole tree -- every subcommand, argument and default -- and the result goes through the +//! repo's markdown formatter, so the file is byte-identical to what that formatter would leave on disk. + +use std::io::Write as _; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; + +use clap::CommandFactory as _; +use command_error::{ChildExt as _, CommandExt as _}; + +use crate::Error; + +/// Every utility's `HELP.md`, as its path relative to the repo root and its rendered content. +pub fn render(root: &Path) -> Result, Error> { + [ + ("utilities/cli/HELP.md", et_cli::cli::Cli::command()), + ("utilities/int-gen/HELP.md", crate::cli::Cli::command()), + ("utilities/onnx/HELP.md", et_onnx::Args::command()), + ] + .into_iter() + .map(|(path, command)| { + let markdown = clap_markdown::help_markdown_command(&command); + Ok((PathBuf::from(path), format_markdown(root, &markdown)?)) + }) + .collect() +} + +/// Format `markdown` as the repo's markdown formatter would, run from `root` so it finds the repo's config. +#[expect( + clippy::single_call_fn, + reason = "the formatter subprocess is a distinct step of render(); kept separate for its stdin handling" +)] +fn format_markdown(root: &Path, markdown: &str) -> Result { + let mut child = Command::new("dprint") + .args(["fmt", "--stdin", "md"]) + .current_dir(root) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn_checked()?; + // Scoped so stdin closes before the wait, which is what tells the formatter its input has ended. + { + let mut stdin = child + .child_mut() + .stdin + .take() + .ok_or_else(|| std::io::Error::other("the formatter's stdin was not piped"))?; + stdin.write_all(markdown.as_bytes())?; + } + Ok(child.output_checked_utf8()?.stdout) +} diff --git a/utilities/int-gen/src/lib.rs b/utilities/int-gen/src/lib.rs index c3cf4bdb..ec0bd0a1 100644 --- a/utilities/int-gen/src/lib.rs +++ b/utilities/int-gen/src/lib.rs @@ -1,9 +1,8 @@ //! Internal repo-only generator (`int` = internal). //! -//! Emits every checked-in artifact under `generated/` from the Rust sources of -//! truth: `edge_toolkit::ws::{ClientMessage, ServerMessage}` for the WS protocol, and the -//! `#[utoipa::path]`-annotated handlers in `services/*` for the REST surface. -//! Driven by `mise run gen-specs`; `mise run gen-specs-check` fails if the +//! Emits every checked-in artifact under `generated/` from the Rust sources of truth: +//! `edge_toolkit::ws::{ClientMessage, ServerMessage}` for the WS protocol, and the `#[utoipa::path]`-annotated handlers +//! in `services/*` for the REST surface. Driven by `mise run gen-specs`; `mise run gen-specs-check` fails if the //! regenerated tree drifts from what's committed. //! //! Outputs (see [`generate`]): @@ -29,13 +28,12 @@ //! committed); the input `datamodel-codegen` reads for the Python //! client. //! -//! Hand-maintained metadata that lives under `generated/` for proximity to -//! the generated code (package descriptions, dependency declarations) is -//! catalogued in `generated/README.md`. Upstream WASI WIT packages under -//! `generated/specs/wit/deps/wasi-*/` are pulled via -//! `mise run fetch-wit-deps`, handled by the companion [`wit::upstream`] -//! module. +//! Hand-maintained metadata that lives under `generated/` for proximity to the generated code (package +//! descriptions, dependency declarations) is catalogued in `generated/README.md`. Upstream WASI WIT packages +//! under `generated/specs/wit/deps/wasi-*/` are pulled via `mise run fetch-wit-deps`, handled by the companion +//! [`wit::upstream`] module. +use std::io::Write as _; use std::path::Path; use edge_toolkit::config::get_project_root; @@ -44,7 +42,10 @@ use fs_err as fs; use schemars::schema_for; pub mod asyncapi; +pub mod checks; +pub mod cli; pub mod error; +pub mod help; pub mod kdl; pub mod openapi; pub mod wit; @@ -54,8 +55,8 @@ pub use self::error::Error; /// Emit every checked-in artifact under `generated/` (core + Rust + Zig). /// -/// Convenience wrapper over the three per-target functions; `mise run -/// gen-specs` drives them individually per `MISE_ENV` instead. +/// Convenience wrapper over the three per-target functions; `mise run gen-specs` drives them individually per +/// `MISE_ENV` instead. pub fn generate() -> Result<(), Error> { generate_core()?; generate_rust()?; @@ -64,12 +65,59 @@ pub fn generate() -> Result<(), Error> { Ok(()) } +/// Write `CHECKS.md` at the repo root, the catalogue of every check across every `MISE_ENV`. +pub fn generate_checks() -> Result<(), Error> { + let project_root = get_project_root(); + write_if_changed(&project_root.join("CHECKS.md"), &checks::render(&project_root)?) +} + +/// Fail when the committed `CHECKS.md` differs from what [`generate_checks`] would write. +pub fn check_checks() -> Result<(), Error> { + let project_root = get_project_root(); + let committed = fs::read_to_string(project_root.join("CHECKS.md"))?; + if committed == checks::render(&project_root)? { + Ok(()) + } else { + Err(Error::ChecksStale( + "CHECKS.md is out of date with the mise configs and rule files; run `mise run gen:checks`", + )) + } +} + +/// Write each utility's `HELP.md` from its clap command tree. +pub fn generate_help() -> Result<(), Error> { + let project_root = get_project_root(); + for (path, rendered) in help::render(&project_root)? { + write_if_changed(&project_root.join(path), &rendered)?; + } + Ok(()) +} + +/// Fail when any committed `HELP.md` differs from what [`generate_help`] would write, naming each stale file. +pub fn check_help() -> Result<(), Error> { + let project_root = get_project_root(); + let mut stale = Vec::new(); + for (path, rendered) in help::render(&project_root)? { + if fs::read_to_string(project_root.join(&path))? != rendered { + stale.push(path.display().to_string()); + } + } + if stale.is_empty() { + Ok(()) + } else { + Err(Error::HelpStale(format!( + "{} out of date with the clap command trees; run `mise run gen-help-all`", + stale.join(", ") + ))) + } +} + /// Emit the wasmtime host bindings for the `runner` world. /// -/// Writes `services/ws-wasi-runner/src/bindings.rs`, which used to be expanded from -/// `wasmtime::component::bindgen!` at build time against a WIT path outside that crate -- a path -/// `cargo package` cannot include, leaving the crate unable to build from its own tarball. Depends on the -/// `et:ws-messages` WIT that [`generate_core`] emits, so run it after that. +/// Writes `services/ws-wasi-runner/src/bindings.rs`, which used to be expanded from `wasmtime::component::bindgen!` at +/// build time against a WIT path outside that crate -- a path `cargo package` cannot include, leaving the crate unable +/// to build from its own tarball. Depends on the `et:ws-messages` WIT that [`generate_core`] emits, so run it after +/// that. pub fn generate_bindings() -> Result<(), Error> { let project_root = get_project_root(); let rendered = wit::bindings::render(&project_root.join("generated/specs/wit"))?; @@ -79,30 +127,27 @@ pub fn generate_bindings() -> Result<(), Error> { /// Emit the language-agnostic artifacts. /// -/// Namely `ws.yaml`, `rest.yaml`, the `ws.schema.json` intermediates, `ws.kdl`, and the `et:ws-messages` WIT -/// package. These feed every downstream client (the Dart/Python generators consume -/// `ws.kdl`/`*.schema.json`/`rest.yaml`), so this is the prerequisite step -/// every per-language `gen:*` mise task depends on. +/// Namely `ws.yaml`, `rest.yaml`, the `ws.schema.json` intermediates, `ws.kdl`, and the `et:ws-messages` WIT package. +/// These feed every downstream client (the Dart/Python generators consume `ws.kdl`/`*.schema.json`/`rest.yaml`), so +/// this is the prerequisite step every per-language `gen:*` mise task depends on. #[expect( - clippy::unwrap_used, clippy::unwrap_in_result, + clippy::unwrap_used, reason = "pretty_yaml only fails on malformed YAML and serde output is always well-formed" )] pub fn generate_core() -> Result<(), Error> { let project_root = get_project_root(); let specs_dir = project_root.join("generated/specs"); - // Build, merge, and slim the AsyncAPI spec -- all the spec-shaping - // logic lives in `asyncapi`. The returned `Value` is what we serialise - // to ws.yaml below. + // Build, merge, and slim the AsyncAPI spec -- all the spec-shaping logic lives in `asyncapi`. The returned `Value` + // is what we serialise to ws.yaml below. let spec_value = asyncapi::build_spec()?; - // serde_yaml's emitter quotes/indents differently than the repo's YAML - // formatter -- pipe the output through `pretty_yaml`, the same engine that - // formatter runs on, so the committed YAML is already canonical and the - // format check doesn't drift between regenerations. + // serde_yaml's emitter quotes/indents differently than the repo's YAML formatter -- pipe the output through + // `pretty_yaml`, the same engine that formatter runs on, so the committed YAML is already canonical and the format + // check doesn't drift between regenerations. let yaml = serde_yaml::to_string(&spec_value)?; - // serde_yaml always emits well-formed YAML, so pretty_yaml's parse step - // can't fail here -- the only error variant is a syntax error. + // serde_yaml always emits well-formed YAML, so pretty_yaml's parse step can't fail here -- the only error variant + // is a syntax error. let yaml = pretty_yaml::format_text(&yaml, &pretty_yaml::config::FormatOptions::default()).unwrap(); write_if_changed(&specs_dir.join("ws.yaml"), &yaml)?; @@ -111,10 +156,9 @@ pub fn generate_core() -> Result<(), Error> { let rest_yaml = pretty_yaml::format_text(&rest_yaml, &pretty_yaml::config::FormatOptions::default()).unwrap(); write_if_changed(&specs_dir.join("rest.yaml"), &rest_yaml)?; - // Build intermediates land in target/ -- datamodel-codegen reads the JSON - // Schema for Python output, and dart-typegen reads the KDL for Dart. - // Both halves of the protocol contribute schema; the KDL + WIT - // generators consume them as `(client, server)` pairs. + // Build intermediates land in target/ -- datamodel-codegen reads the JSON Schema for Python output, and dart- + // typegen reads the KDL for Dart. Both halves of the protocol contribute schema; the KDL + WIT generators consume + // them as `(client, server)` pairs. let client_schema = schema_for!(ClientMessage); let server_schema = schema_for!(ServerMessage); let schema_json = serde_json::to_string_pretty(&client_schema)?; @@ -141,10 +185,9 @@ pub fn generate_core() -> Result<(), Error> { /// Emit the typed Rust REST client (`generated/rust-rest/src/lib.rs`). /// -/// Same `progenitor::Generator` engine the retired `cargo-progenitor` CLI -/// used, but driven in-process so the spec and client always reflect the -/// same source. Self-contained: re-derives the `OpenAPI` doc in-process, so -/// it needs no ordering relative to [`generate_core`]. +/// Same `progenitor::Generator` engine the retired `cargo-progenitor` CLI used, but driven in-process so the spec +/// and client always reflect the same source. Self-contained: re-derives the `OpenAPI` doc in-process, so it needs no +/// ordering relative to [`generate_core`]. pub fn generate_rust() -> Result<(), Error> { let project_root = get_project_root(); let rust_client = openapi::render_rust_client()?; @@ -154,15 +197,13 @@ pub fn generate_rust() -> Result<(), Error> { /// Emit the Zig REST client (`generated/zig-rest/src/et_rest_client.zig`). /// -/// openapi2zig generates a fully typed client; et-int-gen post-processes it -/// via tree-sitter-zig to swap the native HTTP transport for an extern -/// JS-fetch import (browser wasm target). Self-contained: re-derives the -/// `OpenAPI` JSON in-process. +/// openapi2zig generates a fully typed client; et-int-gen post-processes it via tree-sitter-zig to swap the native +/// HTTP transport for an extern JS-fetch import (browser wasm target). Self-contained: re-derives the `OpenAPI` JSON +/// in-process. /// -/// Upstream openapi2zig has no linux/arm64 release artifact, so mise doesn't -/// install it there -- skip the whole step when the binary is absent. The -/// committed `generated/zig-rest/src/et_rest_client.zig` stays untouched, so -/// `gen-specs-check`'s `git diff --exit-code` still passes on that host. +/// Upstream openapi2zig has no linux/arm64 release artifact, so mise doesn't install it there -- skip the whole step +/// when the binary is absent. The committed `generated/zig-rest/src/et_rest_client.zig` stays untouched, so `gen-specs- +/// check`'s `git diff --exit-code` still passes on that host. #[expect( clippy::print_stderr, reason = "et-int-gen is a CLI; the skip notice on stderr is intended user-visible output" @@ -185,19 +226,25 @@ pub fn generate_zig() -> Result<(), Error> { } /// Write only when the contents differ, so a no-op regeneration leaves no diff behind. +/// +/// The file on disk is read and compared first, and an unchanged file is not touched at all. Changed contents are +/// staged in a second file beside `path` and renamed over it, so the target is never truncated or written into, and a +/// run that dies part way leaves the previous file whole. #[expect( clippy::print_stdout, reason = "et-int-gen is a CLI; `wrote ` per generated file is intended user-visible progress output" )] -pub(crate) fn write_if_changed(path: &Path, contents: &str) -> Result<(), Error> { - if let Some(parent) = path.parent() { - fs::create_dir_all(parent)?; - } - let unchanged = fs::read_to_string(path).is_ok_and(|existing| existing == contents); - if unchanged { +pub fn write_if_changed(path: &Path, contents: &str) -> Result<(), Error> { + if fs::read(path).is_ok_and(|existing| existing == contents.as_bytes()) { return Ok(()); } - fs::write(path, contents)?; + let dir = path + .parent() + .ok_or_else(|| std::io::Error::other(format!("{} has no parent directory", path.display())))?; + fs::create_dir_all(dir)?; + let mut staged = tempfile::NamedTempFile::new_in(dir)?; + staged.write_all(contents.as_bytes())?; + staged.persist(path)?.sync_all()?; println!("wrote {}", path.display()); Ok(()) } diff --git a/utilities/int-gen/src/openapi.rs b/utilities/int-gen/src/openapi.rs index 929bdee3..e5e53172 100644 --- a/utilities/int-gen/src/openapi.rs +++ b/utilities/int-gen/src/openapi.rs @@ -91,8 +91,8 @@ pub fn render_json() -> String { /// span end-to-end -- distributed tracing works without each call site repeating the boilerplate the old /// `inject_traceparent` helper did. With the feature off the hook is a no-op. #[expect( - clippy::unwrap_used, clippy::unwrap_in_result, + clippy::unwrap_used, reason = "progenitor's emit feeds straight into syn::parse2; a parse failure means progenitor produced invalid Rust" )] pub fn render_rust_client() -> Result { diff --git a/utilities/int-gen/src/wit/bindings.rs b/utilities/int-gen/src/wit/bindings.rs index 6f302b38..3abd0fdb 100644 --- a/utilities/int-gen/src/wit/bindings.rs +++ b/utilities/int-gen/src/wit/bindings.rs @@ -45,15 +45,15 @@ const HEADER: &str = r#"//! Wasmtime host bindings for the `runner` world. //! GENERATED by `mise run gen:wasmtime-bindings` (et-int-gen) from `generated/specs/wit`. Do not edit -- //! change the WIT or the generator instead, and regenerate. `gen-specs-check` fails when this drifts. #![allow( - unsafe_code, - unused_variables, clippy::all, + clippy::missing_const_for_fn, clippy::pedantic, clippy::restriction, - clippy::missing_const_for_fn, clippy::too_long_first_doc_paragraph, clippy::type_repetition_in_bounds, clippy::use_self, + unsafe_code, + unused_variables, reason = "generated from WIT by wasmtime-internal-wit-bindgen; we don't control its output. The group allows cover most of it, but Cargo's [lints] table passes -D per group on the command line, which an in-source group allow does not override -- so the four lints that still fire are named individually. diff --git a/utilities/int-gen/src/wit/messages.rs b/utilities/int-gen/src/wit/messages.rs index 8065b55e..1efb5c4e 100644 --- a/utilities/int-gen/src/wit/messages.rs +++ b/utilities/int-gen/src/wit/messages.rs @@ -34,8 +34,8 @@ fn to_kebab(input: &str) -> String { type EnumSet = HashSet; #[expect( - clippy::unwrap_used, clippy::unwrap_in_result, + clippy::unwrap_used, reason = "the semver literal is a compile-time constant; an Err means the literal was mistyped" )] pub fn render(client_schema: &Schema, server_schema: &Schema) -> Result { diff --git a/utilities/int-gen/src/wit/upstream.rs b/utilities/int-gen/src/wit/upstream.rs index 56438c12..bfae15e9 100644 --- a/utilities/int-gen/src/wit/upstream.rs +++ b/utilities/int-gen/src/wit/upstream.rs @@ -104,8 +104,8 @@ pub fn run(project_root: &Path) -> Result<(), Error> { } #[expect( - clippy::single_call_fn, clippy::print_stdout, + clippy::single_call_fn, reason = "helper called once by run(); et-int-gen is a CLI, stdout progress lines are intended user-facing output" )] fn fetch_one(deps_root: &Path, pkg: &UpstreamPackage) -> Result<(), Error> { diff --git a/utilities/int-gen/src/zig.in/request_raw_extra_headers_body.zig b/utilities/int-gen/src/zig.in/request_raw_extra_headers_body.zig new file mode 100644 index 00000000..ff09aad1 --- /dev/null +++ b/utilities/int-gen/src/zig.in/request_raw_extra_headers_body.zig @@ -0,0 +1,8 @@ +{ + // Replaced by et-int-gen: delegate to the rewritten `requestRawWithContentType`, which dispatches via the + // host JS shim instead of `std.http.Client.fetch`. Every per-operation wrapper that declares headers funnels + // through here. The host import carries no request headers, so `extra_headers` is dropped there exactly as + // the client's default headers are. + _ = extra_headers; + return requestRawWithContentType(client, method, url, payload, content_type_value); +} diff --git a/utilities/int-gen/src/zig.rs b/utilities/int-gen/src/zig.rs index ecdf927a..1bab35e6 100644 --- a/utilities/int-gen/src/zig.rs +++ b/utilities/int-gen/src/zig.rs @@ -12,11 +12,15 @@ //! * Binary / text bodies (e.g. `application/octet-stream`) *inline* their //! own `client.http.fetch` in the per-operation `*Raw` function rather //! than delegating. +//! * Since 0.5, operations that declare headers route through +//! `requestRawWithContentTypeAndExtraHeaders`, which holds a second copy of +//! the shared `client.http.fetch`. //! //! We funnel everything through one host import. First we swap the body of //! the shared `requestRawWithContentType` for one that delegates to a single //! `extern fn js_rest_request(...)` (host-implemented via `fetch()` and -//! `SharedArrayBuffer` in the JS shim). Then we rewrite each inlined binary +//! `SharedArrayBuffer` in the JS shim), and the extra-headers variant's body +//! for a call to it. Then we rewrite each inlined binary //! operation to delegate to that same shared function instead of calling //! `client.http.fetch` directly. Finally we assert no reachable //! `client.http.fetch` survived and append the extern declaration. @@ -49,6 +53,14 @@ const SHARED_REQUEST_FN: &str = "requestRawWithContentType"; /// The replacement body spliced into [`SHARED_REQUEST_FN`] by [`rewrite`]. const REQUEST_RAW_BODY: &str = include_str!("zig.in/request_raw_body.zig"); +/// The shared request function that operations declaring headers call, with a `client.http.fetch` of its own. +/// +/// openapi2zig 0.5 emits it beside [`SHARED_REQUEST_FN`] rather than delegating to it, so it is rewritten too. +const EXTRA_HEADERS_REQUEST_FN: &str = "requestRawWithContentTypeAndExtraHeaders"; + +/// The replacement body spliced into [`EXTRA_HEADERS_REQUEST_FN`] by [`rewrite`], delegating to [`SHARED_REQUEST_FN`]. +const REQUEST_RAW_EXTRA_HEADERS_BODY: &str = include_str!("zig.in/request_raw_extra_headers_body.zig"); + /// The `extern fn js_rest_request(...)` declaration appended to the generated client by [`rewrite`]. const JS_REST_REQUEST_EXTERN: &str = include_str!("zig.in/js_rest_request_extern.zig"); @@ -121,50 +133,55 @@ fn run_openapi2zig(rest_json: &Path, raw_out: &Path) -> Result<(), Error> { reason = "named helper; pairs with run_openapi2zig() as the two halves of render()" )] fn rewrite(source: &str) -> Result { + let out = replace_fn_body(source, SHARED_REQUEST_FN, REQUEST_RAW_BODY)?; + let out = replace_fn_body(&out, EXTRA_HEADERS_REQUEST_FN, REQUEST_RAW_EXTRA_HEADERS_BODY)?; + let mut out = reroute_inline_binary_ops(&out)?; + if out.contains("client.http.fetch") { + return Err(Error::ZigCodegen( + concat!( + "openapi2zig output still contains a reachable `client.http.fetch` after rewriting ", + "- an operation shape changed; it would attempt real HTTP from wasm. Verify the codegen.", + ) + .into(), + )); + } + out.push_str(JS_REST_REQUEST_EXTERN); + // Strip openapi2zig's volatile header timestamp so the committed client stays byte-identical across regens. + let out = Regex::new(GENERATED_TIMESTAMP_PATTERN)?.replace(&out, "").into_owned(); + Ok(out) +} + +/// Return `source` with the body of the function named `name` replaced by `body`. +/// +/// The function is found by name with `tree-sitter-zig` rather than by string-matching its body, so an openapi2zig +/// bump that reshuffles the implementation does not break the splice; a function that is gone is an error. +fn replace_fn_body(source: &str, name: &str, body: &str) -> Result { let mut parser = Parser::new(); parser.set_language(&tree_sitter_zig::LANGUAGE.into())?; let tree = parser .parse(source, None) .ok_or_else(|| Error::ZigCodegen("tree-sitter parse returned None".into()))?; - let shared_fn = find_fn(tree.root_node(), source, SHARED_REQUEST_FN) - .ok_or_else(|| Error::ZigCodegen(format!("{SHARED_REQUEST_FN} function not found in openapi2zig output")))?; - let body = shared_fn + let function = find_fn(tree.root_node(), source, name) + .ok_or_else(|| Error::ZigCodegen(format!("{name} function not found in openapi2zig output")))?; + let old_body = function .child_by_field_name("body") - .ok_or_else(|| Error::ZigCodegen(format!("{SHARED_REQUEST_FN} has no body field")))?; - - let body_start = body.start_byte(); - let body_end = body.end_byte(); + .ok_or_else(|| Error::ZigCodegen(format!("{name} has no body field")))?; - // 1024 is a comfortable upper bound for the replacement body + extern - // declaration we splice in below; if the additions ever exceed it the - // worst case is one extra reallocation, not a panic. + // 1024 is a comfortable upper bound for the replacement body + extern declaration the caller splices in; if + // the additions ever exceed it the worst case is one extra reallocation, not a panic. let mut out = String::with_capacity(source.len().saturating_add(1024)); - // Indexing into `source` is safe here because tree-sitter byte offsets - // sit on UTF-8 boundaries by construction (it tokenises a UTF-8 - // string and emits byte-aligned spans). + // Indexing into `source` is safe here because tree-sitter byte offsets sit on UTF-8 boundaries by + // construction (it tokenises a UTF-8 string and emits byte-aligned spans). #[expect( clippy::string_slice, reason = "tree-sitter byte offsets are UTF-8 boundary-aligned; we round-trip the source by splicing those spans" )] { - out.push_str(&source[..body_start]); - out.push_str(REQUEST_RAW_BODY.trim_end()); - out.push_str(&source[body_end..]); - } - out = reroute_inline_binary_ops(&out)?; - if out.contains("client.http.fetch") { - return Err(Error::ZigCodegen( - concat!( - "openapi2zig output still contains a reachable `client.http.fetch` after rewriting ", - "- an operation shape changed; it would attempt real HTTP from wasm. Verify the codegen.", - ) - .into(), - )); + out.push_str(&source[..old_body.start_byte()]); + out.push_str(body.trim_end()); + out.push_str(&source[old_body.end_byte()..]); } - out.push_str(JS_REST_REQUEST_EXTERN); - // Strip openapi2zig's volatile header timestamp so the committed client stays byte-identical across regens. - let out = Regex::new(GENERATED_TIMESTAMP_PATTERN)?.replace(&out, "").into_owned(); Ok(out) } diff --git a/utilities/int-gen/tests/checks.rs b/utilities/int-gen/tests/checks.rs new file mode 100644 index 00000000..17a8cf12 --- /dev/null +++ b/utilities/int-gen/tests/checks.rs @@ -0,0 +1,206 @@ +//! Covers the pieces `CHECKS.md` is assembled from: tool detection, config paths, Rego summaries and wrapping. +//! +//! The `run` bodies here use made-up tool names, since what is under test is the shell parsing around them. +#![cfg(test)] + +use std::collections::{BTreeMap, BTreeSet}; + +use et_int_gen::checks::{config_paths, link_label, lint_opposites, rego_summaries, rule_sources, runner_label, wrap}; + +/// The set of paths a path-collecting function is expected to return. +fn paths(expected: &[&str]) -> BTreeSet { + expected.iter().map(|path| (*path).to_owned()).collect() +} + +/// Assert the tool `runner_label` names for a `run` body. +fn assert_tool(body: &str, expected: &str) { + let label = runner_label(body).unwrap(); + assert_eq!(label, expected, "tool for body {body:?}"); +} + +#[test] +fn single_command_names_its_tool() { + assert_tool("lintx scan --config config/lintx --error .", "lintx"); + assert_tool("scanz", "scanz"); +} + +#[test] +fn cargo_is_labelled_by_subcommand_or_package() { + assert_tool("cargo clippy --keep-going --workspace --tests", "cargo clippy"); + assert_tool("cargo +{{ vars.rust_nightly }} fmt -- --check", "cargo fmt"); + assert_tool("cargo run -q -p et-repo-check", "et-repo-check"); + assert_tool( + "cargo run --features markdown-help -q -p \"$crate\" -- --markdown-help", + "cargo run", + ); +} + +#[test] +fn plumbing_and_shell_syntax_are_skipped() { + assert_tool( + "git ls-files '*Dockerfile' | rg -v x |\n xargs -0 lintx --config config/lintx.yaml", + "lintx", + ); + assert_tool("cfg=config/scanz.toml\nscanz --config \"$cfg\" '**/*.md'", "scanz"); + assert_tool( + ": \"${TOKEN:=$(gh auth token)}\"\nexport TOKEN\ncargo udeps\n", + "cargo udeps", + ); + assert_tool("while read -r line; do\n lintx \"$line\"\ndone", "lintx"); + assert_tool("# a comment naming fakecmd\nscanz check", "scanz"); +} + +#[test] +fn substitutions_are_searched_and_quoted_parens_do_not_close_them() { + assert_tool( + "rc=0\nout=\"$(cargo audit --config config/audit.toml check 2>&1)\" || rc=$?", + "cargo audit", + ); + assert_tool("tidy=\"$(conda_exe some-pkg tidyq)\"\n\"$tidy\" x.c", "tidyq"); + let lock_check = [ + "drift=$(git diff | rg \"^[-+](version|backend) = \" || true)\n", + "if [ -n \"$drift\" ]; then\n", + " echo \"differ; commit the lockfiles\" >&2\n", + "fi", + ] + .concat(); + assert_tool(&lock_check, "Shell-script checks"); +} + +#[test] +fn env_provided_tools_and_pure_shell_bodies() { + assert_tool("\"$MVN\" -q compile", "mvn"); + assert_tool("git diff --exit-code -- .dockerignore", "Shell-script checks"); + assert_tool( + "for cfg in .mise/config*.toml; do\n echo \"$cfg\"\ndone", + "Shell-script checks", + ); +} + +#[test] +fn config_paths_finds_config_files_and_mise_helpers_only() { + let found = config_paths( + "--config config/audit.toml {{ config_root }}/config/scanz.toml -f .mise/fmt-mise.awk .mise/config*.toml", + ) + .unwrap(); + assert_eq!( + found, + paths(&["config/audit.toml", "config/scanz.toml", ".mise/fmt-mise.awk"]) + ); +} + +#[test] +fn rule_sources_takes_only_flagged_config_paths() { + let body = [ + "lintx -c config/lintx/sgconfig.yaml\n", + "scanz --config config/scanz\n", + "policyq test -p config/policy $files config/inputs/rules\n", + "schemaz lint --schema \"file:///${PWD#/}/config/schemas/one.schema.json\" Cargo.toml", + ] + .concat(); + let expected = [ + "config/lintx/sgconfig.yaml", + "config/scanz", + "config/policy", + "config/schemas/one.schema.json", + ]; + assert_eq!(rule_sources(&body).unwrap(), paths(&expected)); +} + +#[test] +fn rego_summary_is_the_last_comment_block_before_each_rule() { + let source = [ + "# File header.\npackage demo\n\n", + "# Helper summary.\nis_x(file) if true\n\n", + "# First rule.\n# More.\ndeny contains msg if {\n\t# body comment\n\tmsg := \"a\"\n}\n\n", + "# Second rule.\nallowed := {1}\n\ndeny contains msg if {\n\tmsg := \"b\"\n}\n", + ] + .concat(); + assert_eq!( + rego_summaries("demo.rego", &source).unwrap(), + ["First rule.", "Second rule."] + ); +} + +#[test] +fn rego_rule_without_a_summary_comment_is_rejected() { + let source = "package demo\n\n# Described.\ndeny contains msg if {\n}\n\ndeny contains msg if {\n}\n"; + let error = rego_summaries("demo.rego", source).unwrap_err().to_string(); + assert!( + error.starts_with("demo.rego:7: rule has no summary comment"), + "names the file and line: {error}" + ); +} + +#[test] +fn lint_opposite_is_read_from_the_comment_block_directly_above_its_entry() { + let manifest = [ + "[workspace.lints.clippy]\n", + "# Opposite of clippy::lint_b.\n# Why this side was chosen.\nlint_a = \"allow\"\n", + "lint_c = \"allow\"\n", + "# Opposite of clippy::lint_e.\n\nlint_d = \"allow\"\n", + "[workspace.lints.rust]\n# Opposite of lint_g.\nlint_f = \"allow\"\n", + "[workspace.package]\n# Opposite of clippy::lint_i.\nlint_h = \"allow\"\n", + ] + .concat(); + let expected = BTreeMap::from([ + ("clippy::lint_a".to_owned(), "clippy::lint_b".to_owned()), + ("lint_f".to_owned(), "lint_g".to_owned()), + ]); + assert_eq!(lint_opposites(&manifest), expected); +} + +#[test] +fn link_label_is_the_lint_name_without_its_tool() { + assert_eq!( + link_label("clippy::unwrap_used", "https://example.test/#unwrap_used"), + "unwrap_used" + ); + assert_eq!( + link_label("unused_results", "https://example.test/#unused-results"), + "unused_results" + ); +} + +#[test] +fn link_label_is_shortened_when_its_definition_would_overflow_the_line() { + let link = format!( + "https://example.test/{}#allow_attributes_without_reason", + "x".repeat(36) + ); + assert_eq!( + link_label("clippy::allow_attributes_without_reason", &link), + "allow_attributes_without" + ); +} + +#[test] +fn wrap_never_starts_a_continuation_line_with_a_block_marker() { + let text = format!("{} + lock files", "word ".repeat(23)); + let wrapped = wrap("- ", " ", &text); + assert!(wrapped.lines().count() > 1, "the text must wrap: {wrapped}"); + assert!( + wrapped.lines().skip(1).all(|line| !line.trim_start().starts_with("+ ")), + "no line opens with `+`: {wrapped}" + ); +} + +#[test] +fn wrap_fills_lines_to_the_width_with_a_continuation_prefix() { + let text = "word ".repeat(40); + let wrapped = wrap("- ", " ", &text); + let lines: Vec<&str> = wrapped.lines().collect(); + assert!(lines.len() > 1, "40 words must not fit on one line"); + assert!( + lines.iter().all(|line| line.len() <= 120), + "every line within the width: {wrapped}" + ); + assert!( + lines.first().is_some_and(|line| line.starts_with("- word")), + "first prefix applied: {wrapped}" + ); + assert!( + lines.iter().skip(1).all(|line| line.starts_with(" word")), + "continuation prefix applied: {wrapped}" + ); +} diff --git a/utilities/int-gen/tests/help_md.rs b/utilities/int-gen/tests/help_md.rs new file mode 100644 index 00000000..79720ed6 --- /dev/null +++ b/utilities/int-gen/tests/help_md.rs @@ -0,0 +1,23 @@ +//! Covers `help-md`: every committed HELP.md matches what the generator renders from its crate's clap tree. +#![cfg(test)] + +use edge_toolkit::config::get_project_root; + +#[test] +fn committed_help_files_match_the_command_trees() { + et_int_gen::check_help().unwrap(); +} + +#[test] +fn every_utility_has_a_rendered_help_file() { + let rendered = et_int_gen::help::render(&get_project_root()).unwrap(); + let paths: Vec = rendered.iter().map(|(path, _)| path.display().to_string()).collect(); + assert_eq!( + paths, + [ + "utilities/cli/HELP.md", + "utilities/int-gen/HELP.md", + "utilities/onnx/HELP.md" + ] + ); +} diff --git a/utilities/int-gen/tests/write_if_changed.rs b/utilities/int-gen/tests/write_if_changed.rs new file mode 100644 index 00000000..115ed17b --- /dev/null +++ b/utilities/int-gen/tests/write_if_changed.rs @@ -0,0 +1,51 @@ +//! Covers `write_if_changed`: it creates missing parents, replaces changed contents, and leaves no staged file behind. +#![cfg(test)] + +use et_int_gen::write_if_changed; +use fs_err as fs; +use tempfile::TempDir; + +/// The names directly inside `dir`, sorted. +fn entries(dir: &std::path::Path) -> Vec { + let mut names: Vec = fs::read_dir(dir) + .unwrap() + .map(|entry| entry.unwrap().file_name().to_string_lossy().into_owned()) + .collect(); + names.sort(); + names +} + +#[test] +fn a_missing_file_is_written_with_its_parents() { + let root = TempDir::new().unwrap(); + let path = root.path().join("nested/dir/out.txt"); + + write_if_changed(&path, "first\n").unwrap(); + + assert_eq!(fs::read_to_string(&path).unwrap(), "first\n"); + assert_eq!(entries(&root.path().join("nested/dir")), ["out.txt"]); +} + +#[test] +fn changed_contents_replace_the_file() { + let root = TempDir::new().unwrap(); + let path = root.path().join("out.txt"); + fs::write(&path, "old\n").unwrap(); + + write_if_changed(&path, "new\n").unwrap(); + + assert_eq!(fs::read_to_string(&path).unwrap(), "new\n"); + assert_eq!(entries(root.path()), ["out.txt"]); +} + +#[test] +fn unchanged_contents_leave_the_file_alone() { + let root = TempDir::new().unwrap(); + let path = root.path().join("out.txt"); + fs::write(&path, "same\n").unwrap(); + + write_if_changed(&path, "same\n").unwrap(); + + assert_eq!(fs::read_to_string(&path).unwrap(), "same\n"); + assert_eq!(entries(root.path()), ["out.txt"]); +} diff --git a/utilities/onnx/Cargo.toml b/utilities/onnx/Cargo.toml index 78547500..bd304fa6 100644 --- a/utilities/onnx/Cargo.toml +++ b/utilities/onnx/Cargo.toml @@ -7,6 +7,10 @@ edition.workspace = true license.workspace = true repository.workspace = true +[lib] +doctest = false +test = false + [[bin]] doctest = false name = "et-onnx" @@ -15,11 +19,7 @@ test = false [dependencies] clap.workspace = true -clap-markdown = { workspace = true, optional = true } onnx-extractor.workspace = true -[features] -markdown-help = ["dep:clap-markdown"] - [lints] workspace = true diff --git a/utilities/onnx/src/lib.rs b/utilities/onnx/src/lib.rs new file mode 100644 index 00000000..c4e85ad9 --- /dev/null +++ b/utilities/onnx/src/lib.rs @@ -0,0 +1,14 @@ +//! The `et-onnx` command line, split into a lib target so et-int-gen can read its clap tree to write HELP.md. + +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Debug, Parser)] +#[command(author, version, about, long_about = None)] +#[non_exhaustive] +pub struct Args { + /// Path to the ONNX model file. + #[arg(short, long)] + pub filename: Option, +} diff --git a/utilities/onnx/src/main.rs b/utilities/onnx/src/main.rs index c11a7373..034da6b7 100644 --- a/utilities/onnx/src/main.rs +++ b/utilities/onnx/src/main.rs @@ -1,29 +1,9 @@ -use std::path::PathBuf; - -use clap::Parser; - -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct Args { - /// Path to the ONNX model file. - #[arg(short, long)] - filename: Option, - - /// Print the full clap help tree as markdown (used to regenerate HELP.md). - #[cfg(feature = "markdown-help")] - #[arg(long, hide = true)] - markdown_help: bool, -} +use clap::Parser as _; +use et_onnx::Args; fn main() -> Result<(), Box> { let args = Args::parse(); - #[cfg(feature = "markdown-help")] - if args.markdown_help { - clap_markdown::print_help_markdown::(); - return Ok(()); - } - let Some(filename) = args.filename.as_ref() else { return Err("--filename is required".into()); }; diff --git a/utilities/repo-check/src/error.rs b/utilities/repo-check/src/error.rs index 670223ba..4b611db1 100644 --- a/utilities/repo-check/src/error.rs +++ b/utilities/repo-check/src/error.rs @@ -3,8 +3,8 @@ /// Errors raised by `et-repo-check`. #[derive(Debug, thiserror::Error)] #[expect( - clippy::exhaustive_enums, clippy::error_impl_error, + clippy::exhaustive_enums, reason = "one internal binary with no SemVer surface; every check returns this type and adds variants with itself" )] pub enum Error { diff --git a/verification/local/output/default/Dockerfile.dockerignore b/verification/local/output/default/Dockerfile.dockerignore index 9bc9fe1a..654e6240 100644 --- a/verification/local/output/default/Dockerfile.dockerignore +++ b/verification/local/output/default/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/local/output/facility-security-scenario/Dockerfile b/verification/local/output/facility-security-scenario/Dockerfile index 07fa4533..325b2f78 100644 --- a/verification/local/output/facility-security-scenario/Dockerfile +++ b/verification/local/output/facility-security-scenario/Dockerfile @@ -42,7 +42,7 @@ EOF # checks exactly the archive downloaded here. Pinned rather than installed from mise's apt repository, # which carries only the newest version: a floating mise writes lockfile entries an older CI mise # then refuses to install. -ARG MISE_VERSION=v2026.9.0 +ARG MISE_VERSION=v2026.9.17 ARG TARGETARCH ENV MISE_VERSION=${MISE_VERSION} ENV TARGETARCH=${TARGETARCH} diff --git a/verification/local/output/facility-security-scenario/Dockerfile.dockerignore b/verification/local/output/facility-security-scenario/Dockerfile.dockerignore index 75cedc4f..421ab492 100644 --- a/verification/local/output/facility-security-scenario/Dockerfile.dockerignore +++ b/verification/local/output/facility-security-scenario/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/local/output/math1/Dockerfile.dockerignore b/verification/local/output/math1/Dockerfile.dockerignore index 5f1a403e..5375bedf 100644 --- a/verification/local/output/math1/Dockerfile.dockerignore +++ b/verification/local/output/math1/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/local/output/pyo3-math1/Dockerfile.dockerignore b/verification/local/output/pyo3-math1/Dockerfile.dockerignore index a5e4c474..202b0747 100644 --- a/verification/local/output/pyo3-math1/Dockerfile.dockerignore +++ b/verification/local/output/pyo3-math1/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/local/output/wasi-math1/Dockerfile.dockerignore b/verification/local/output/wasi-math1/Dockerfile.dockerignore index 2eebdb85..2ef3bff0 100644 --- a/verification/local/output/wasi-math1/Dockerfile.dockerignore +++ b/verification/local/output/wasi-math1/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/published/output/default/Dockerfile.dockerignore b/verification/published/output/default/Dockerfile.dockerignore index 9bc9fe1a..654e6240 100644 --- a/verification/published/output/default/Dockerfile.dockerignore +++ b/verification/published/output/default/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/published/output/math1/Dockerfile.dockerignore b/verification/published/output/math1/Dockerfile.dockerignore index 5f1a403e..5375bedf 100644 --- a/verification/published/output/math1/Dockerfile.dockerignore +++ b/verification/published/output/math1/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/published/output/pyo3-math1/Dockerfile.dockerignore b/verification/published/output/pyo3-math1/Dockerfile.dockerignore index a5e4c474..202b0747 100644 --- a/verification/published/output/pyo3-math1/Dockerfile.dockerignore +++ b/verification/published/output/pyo3-math1/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a diff --git a/verification/published/output/wasi-math1/Dockerfile.dockerignore b/verification/published/output/wasi-math1/Dockerfile.dockerignore index 2eebdb85..2ef3bff0 100644 --- a/verification/published/output/wasi-math1/Dockerfile.dockerignore +++ b/verification/published/output/wasi-math1/Dockerfile.dockerignore @@ -66,6 +66,8 @@ services/ws-server/storage/ # whatever the machine that ran it happened to resolve. One rule here rather than a `.gitignore` generated into # each scenario, so a scenario added later is covered without anything having to be written into it. verification/**/*.lock +# The npm dependency graphs `mise lock` records beside that lockfile, a by-product for the same reason. +verification/**/.mise/locks/ # No rule for the per-scenario credential file, deliberately. # Under verification/ it is committed like every other generated artifact: the password is derived from an # input this repository already carries, so the file reproduces from public material rather than keeping a