diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd14ade92..06f54b3ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: contents: read pull-requests: read steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1 @@ -112,7 +112,7 @@ jobs: if: needs.release-please.outputs.release_created == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Build clean marketplace bundle # A self-contained marketplace a user can extract and register with @@ -159,9 +159,9 @@ jobs: - { tool: codex, mode: flat, flag: "--flat" } - { tool: opencode, mode: flat, flag: "--flat" } steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" @@ -211,7 +211,7 @@ jobs: echo "released=false" >> $GITHUB_OUTPUT fi - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 if: steps.check.outputs.released == 'true' - name: Get plugin version @@ -248,12 +248,12 @@ jobs: if: needs.release-please.outputs.paths_released != '' && contains(fromJSON(needs.release-please.outputs.paths_released), 'cli') runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile @@ -274,7 +274,7 @@ jobs: # `npm publish`, not `pnpm publish`: pnpm's OIDC support is unverified/ # buggy as of this writing (pnpm/pnpm#9812, #11513) — npm's own CLI is # the reference implementation for its own feature. - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" registry-url: "https://registry.npmjs.org" diff --git a/.github/workflows/cli-ci.yml b/.github/workflows/cli-ci.yml index b1f4e7ed1..e832092b2 100644 --- a/.github/workflows/cli-ci.yml +++ b/.github/workflows/cli-ci.yml @@ -24,12 +24,12 @@ jobs: name: cli / Typecheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile @@ -39,12 +39,12 @@ jobs: name: cli / Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile @@ -54,14 +54,14 @@ jobs: name: cli / Test runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install expect (TTY persona tests) run: sudo apt-get update && sudo apt-get install -y expect - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile @@ -71,12 +71,12 @@ jobs: name: cli / Build & Bundle Budget runs-on: ubuntu-latest steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile @@ -87,12 +87,12 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile @@ -103,12 +103,12 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install pnpm run: | corepack enable corepack prepare pnpm@latest --activate - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: "22" - run: cd cli && pnpm install --frozen-lockfile diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6fdfd9664..72da9af3e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,18 +28,18 @@ jobs: language: [javascript-typescript] steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Initialize CodeQL - uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 with: languages: ${{ matrix.language }} queries: security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/autobuild@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 with: category: "/language:${{ matrix.language }}" diff --git a/cli/knip.json b/cli/knip.json index 6486125f5..362280bf9 100644 --- a/cli/knip.json +++ b/cli/knip.json @@ -7,6 +7,6 @@ "tmp/**", "src/domain/models/marketplace-entry.ts" ], - "ignoreBinaries": ["gh", "icacls"], + "ignoreBinaries": ["gh"], "ignoreExportsUsedInFile": true } diff --git a/cli/package.json b/cli/package.json index 42db4db22..7a855fdcc 100644 --- a/cli/package.json +++ b/cli/package.json @@ -69,24 +69,24 @@ "@inquirer/prompts": "^7.0.0", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", - "commander": "^15.0.0", + "commander": "^12.0.0", "simple-git": "^3.36.0", "smol-toml": "^1.6.1" }, "devDependencies": { "@biomejs/biome": "^2.4.7", - "@commitlint/cli": "^21.2.1", + "@commitlint/cli": "^19.0.0", "@commitlint/config-conventional": "^19.0.0", "@stryker-mutator/core": "^9.6.1", "@stryker-mutator/vitest-runner": "^9.6.1", - "@types/node": "^26.1.1", + "@types/node": "^24.0.0", "@vitest/coverage-v8": "^3.2.6", "fast-check": "^4.7.0", "jscpd": "^5.0.0", "knip": "^6.0.0", "lefthook": "^1.13.1", "tsup": "^8.0.0", - "typescript": "^7.0.2", + "typescript": "^5.0.0", "vitest": "^3.2.6" } } diff --git a/cli/pnpm-lock.yaml b/cli/pnpm-lock.yaml index 641f94536..e833d13b7 100644 --- a/cli/pnpm-lock.yaml +++ b/cli/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: dependencies: '@inquirer/prompts': specifier: ^7.0.0 - version: 7.10.1(@types/node@26.1.1) + version: 7.10.1(@types/node@24.10.15) ajv: specifier: ^8.20.0 version: 8.20.0 @@ -24,8 +24,8 @@ importers: specifier: ^3.0.1 version: 3.0.1(ajv@8.20.0) commander: - specifier: ^15.0.0 - version: 15.0.0 + specifier: ^12.0.0 + version: 12.1.0 simple-git: specifier: ^3.36.0 version: 3.36.0 @@ -35,46 +35,46 @@ importers: devDependencies: '@biomejs/biome': specifier: ^2.4.7 - version: 2.5.5 + version: 2.4.7 '@commitlint/cli': - specifier: ^21.2.1 - version: 21.2.1(@types/node@26.1.1)(conventional-commits-parser@7.1.0)(typescript@7.0.2) + specifier: ^19.0.0 + version: 19.8.1(@types/node@24.10.15)(typescript@5.9.3) '@commitlint/config-conventional': specifier: ^19.0.0 version: 19.8.1 '@stryker-mutator/core': specifier: ^9.6.1 - version: 9.6.1(@types/node@26.1.1) + version: 9.6.1(@types/node@24.10.15) '@stryker-mutator/vitest-runner': specifier: ^9.6.1 - version: 9.6.1(@stryker-mutator/core@9.6.1(@types/node@26.1.1))(vitest@3.2.6(@types/node@26.1.1)) + version: 9.6.1(@stryker-mutator/core@9.6.1(@types/node@24.10.15))(vitest@3.2.6(@types/node@24.10.15)) '@types/node': - specifier: ^26.1.1 - version: 26.1.1 + specifier: ^24.0.0 + version: 24.10.15 '@vitest/coverage-v8': specifier: ^3.2.6 - version: 3.2.6(vitest@3.2.6(@types/node@26.1.1)) + version: 3.2.6(vitest@3.2.6(@types/node@24.10.15)) fast-check: specifier: ^4.7.0 - version: 4.9.0 + version: 4.7.0 jscpd: specifier: ^5.0.0 - version: 5.0.12 + version: 5.0.7 knip: specifier: ^6.0.0 - version: 6.27.0 + version: 6.16.1 lefthook: specifier: ^1.13.1 version: 1.13.6 tsup: specifier: ^8.0.0 - version: 8.5.1(jiti@2.7.0)(postcss@8.5.15)(typescript@7.0.2)(yaml@2.9.0) + version: 8.5.1(jiti@2.7.0)(postcss@8.5.15)(typescript@5.9.3)(yaml@2.9.0) typescript: - specifier: ^7.0.2 - version: 7.0.2 + specifier: ^5.0.0 + version: 5.9.3 vitest: specifier: ^3.2.6 - version: 3.2.6(@types/node@26.1.1) + version: 3.2.6(@types/node@24.10.15) packages: @@ -239,166 +239,136 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@biomejs/biome@2.5.5': - resolution: {integrity: sha512-r1S8nFsAG1MY+vJFZALzIvwXAJv6ejDQ0mxP21Tgr9YK3ZFtjrvbBwDdNhx1rUqvccEIeNg20cYCNzl6Cr69pQ==} + '@biomejs/biome@2.4.7': + resolution: {integrity: sha512-vXrgcmNGZ4lpdwZSpMf1hWw1aWS6B+SyeSYKTLrNsiUsAdSRN0J4d/7mF3ogJFbIwFFSOL3wT92Zzxia/d5/ng==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.5.5': - resolution: {integrity: sha512-kUrAhXVWUrwmAUnV2iXSK7umxKFysTwvqK+Ty6ptUcLY/7T3SnCAjUowE4uvwaEej6nXZ7hu/dTtbokKdsPeag==} + '@biomejs/cli-darwin-arm64@2.4.7': + resolution: {integrity: sha512-Oo0cF5mHzmvDmTXw8XSjhCia8K6YrZnk7aCS54+/HxyMdZMruMO3nfpDsrlar/EQWe41r1qrwKiCa2QDYHDzWA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.5.5': - resolution: {integrity: sha512-DamiYc5bUYZ2uxlfc+RLEPtz1Abb6PO5eTbOkufLpSGwd/7AMQAdxhFYiXmwwkJL8IsT8S7GvdgwDHqaMFAvKw==} + '@biomejs/cli-darwin-x64@2.4.7': + resolution: {integrity: sha512-I+cOG3sd/7HdFtvDSnF9QQPrWguUH7zrkIMMykM3PtfWU9soTcS2yRb9Myq6MHmzbeCT08D1UmY+BaiMl5CcoQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.5.5': - resolution: {integrity: sha512-U4WMl/sy/E/Q73vf15VspakLRRs2LDFcCeBxJnQfXzssb88zpV6PJPaQ3ezhQ7H6Ht2/8bvuZeHgJWzmoxllZg==} + '@biomejs/cli-linux-arm64-musl@2.4.7': + resolution: {integrity: sha512-I2NvM9KPb09jWml93O2/5WMfNR7Lee5Latag1JThDRMURVhPX74p9UDnyTw3Ae6cE1DgXfw7sqQgX7rkvpc0vw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.5.5': - resolution: {integrity: sha512-lRKF/pH/1RiYiBKExi3TCZVAtvzEm77aifrvcNiDFrR9WxeAnDUjDnseb6y2XV85mjitLs6SILGm2XG77cHtSQ==} + '@biomejs/cli-linux-arm64@2.4.7': + resolution: {integrity: sha512-om6FugwmibzfP/6ALj5WRDVSND4H2G9X0nkI1HZpp2ySf9lW2j0X68oQSaHEnls6666oy4KDsc5RFjT4m0kV0w==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.5.5': - resolution: {integrity: sha512-m7wC7tjX5Lrmo69dc4md8FeKpPU1NTCY1v7xUoQQ2vadWwNnBS0KZOG8471otFPHrTHihQJAjQPgMObpLvDe6A==} + '@biomejs/cli-linux-x64-musl@2.4.7': + resolution: {integrity: sha512-00kx4YrBMU8374zd2wHuRV5wseh0rom5HqRND+vDldJPrWwQw+mzd/d8byI9hPx926CG+vWzq6AeiT7Yi5y59g==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.5.5': - resolution: {integrity: sha512-H/O39nJEw/2Zm/fm7hrmxxoF8kK/aU1uCoPp70ruXVbomaAdLpJJnCmL11Q2JotT8QVHH06So04Oq53lCSwSwQ==} + '@biomejs/cli-linux-x64@2.4.7': + resolution: {integrity: sha512-bV8/uo2Tj+gumnk4sUdkerWyCPRabaZdv88IpbmDWARQQoA/Q0YaqPz1a+LSEDIL7OfrnPi9Hq1Llz4ZIGyIQQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.5.5': - resolution: {integrity: sha512-7BryINPuYypLUAH3o/o5ZdgomJ4zn3EDR0ChZJst7n32S6ZhKbgHXuYydLu+YAnx59ehGFR0z/MG6qnzQi3Yyw==} + '@biomejs/cli-win32-arm64@2.4.7': + resolution: {integrity: sha512-hOUHBMlFCvDhu3WCq6vaBoG0dp0LkWxSEnEEsxxXvOa9TfT6ZBnbh72A/xBM7CBYB7WgwqboetzFEVDnMxelyw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.5.5': - resolution: {integrity: sha512-bIBFo+n6MIxdNcVFy5CrurbKiZQiUciK3bt8+O9I4wjFZNTfXLpi+giq47522eXqW5NBc9ulx7dR1SlZKi2J5g==} + '@biomejs/cli-win32-x64@2.4.7': + resolution: {integrity: sha512-qEpGjSkPC3qX4ycbMUthXvi9CkRq7kZpkqMY1OyhmYlYLnANnooDQ7hDerM8+0NJ+DZKVnsIc07h30XOpt7LtQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] - '@commitlint/cli@21.2.1': - resolution: {integrity: sha512-blsZGe29hJ72VGEFVl72IVYX+1vsfINpjA9yWQA6i7OKD/McGEOXg08sKIRKjFk4JvzhV/9n0l3i6NooPLTNfg==} - engines: {node: '>=22.12.0'} + '@commitlint/cli@19.8.1': + resolution: {integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==} + engines: {node: '>=v18'} hasBin: true '@commitlint/config-conventional@19.8.1': resolution: {integrity: sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==} engines: {node: '>=v18'} - '@commitlint/config-conventional@21.2.0': - resolution: {integrity: sha512-Qf8WRDVcyVd14if6VTWenebxFbKnVnbzPUJjlzjkyJGeHK2xCGd63Dr1XZzj0plXKQb9P0BfOxoc1HVeCo2BWQ==} - engines: {node: '>=22.12.0'} - - '@commitlint/config-validator@21.2.0': - resolution: {integrity: sha512-t7AzNHAKeIdo/3NRGwzpufKHsKkPHmFs/56N2Fnsh0/r0rGtnQzTxk6vnFgjaGr4hdSQKNB50/KAhR9Yk4LJKA==} - engines: {node: '>=22.12.0'} + '@commitlint/config-validator@19.8.1': + resolution: {integrity: sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==} + engines: {node: '>=v18'} - '@commitlint/ensure@21.2.0': - resolution: {integrity: sha512-76IF9vDNS13lAzEEik9eKwzt8f9hYhWiwVXZ2AnyLCz5/f511FsEQ3pw1X3/zSQpdRLQU7i5qDMVKyXi1GWjSg==} - engines: {node: '>=22.12.0'} + '@commitlint/ensure@19.8.1': + resolution: {integrity: sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==} + engines: {node: '>=v18'} - '@commitlint/execute-rule@21.0.1': - resolution: {integrity: sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==} - engines: {node: '>=22.12.0'} + '@commitlint/execute-rule@19.8.1': + resolution: {integrity: sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==} + engines: {node: '>=v18'} - '@commitlint/format@21.2.0': - resolution: {integrity: sha512-c4q64xaav2U83t7k7RyzJerBZurPer7FxUOY0RL5L/6CZijZ7K+s6HIBGIghj0ey1P2+seRX0J9XQYtDued6tg==} - engines: {node: '>=22.12.0'} + '@commitlint/format@19.8.1': + resolution: {integrity: sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==} + engines: {node: '>=v18'} - '@commitlint/is-ignored@21.2.0': - resolution: {integrity: sha512-4/eB0vBN7L88O/oC4ajAEqi7j2ZfNgxl/+11RfAV9YosejZgDXhY2C9VcHnHJhOzPLoSy5P3Mg/46kqeyJfXKw==} - engines: {node: '>=22.12.0'} + '@commitlint/is-ignored@19.8.1': + resolution: {integrity: sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==} + engines: {node: '>=v18'} - '@commitlint/lint@21.2.0': - resolution: {integrity: sha512-ceO5dp9pLjEZ6y6qbq/uXWXDPykqqlTsyzoQ0NzecpisSJhK3kTy9qzQoPeJuWG/IMNdV1lO0RgmzqoAlSi1uw==} - engines: {node: '>=22.12.0'} + '@commitlint/lint@19.8.1': + resolution: {integrity: sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==} + engines: {node: '>=v18'} - '@commitlint/load@21.2.0': - resolution: {integrity: sha512-RjlzWQqruRwIenJEfZtq7kG97co97nKoHpflE5YnF61tDLXxHPrdWImgzw6VL6MlFyaOcVlk74eBV8ZQmc3oIA==} - engines: {node: '>=22.12.0'} + '@commitlint/load@19.8.1': + resolution: {integrity: sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==} + engines: {node: '>=v18'} - '@commitlint/message@21.2.0': - resolution: {integrity: sha512-YxGoiXD/HXNXLJPrQwE5poXa+XH0CBEm+mdvbHQP0g6MV/dmJyUFCzPNzZbxL93GvZ70TmtTK0Z0/IBpAqHv8g==} - engines: {node: '>=22.12.0'} + '@commitlint/message@19.8.1': + resolution: {integrity: sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==} + engines: {node: '>=v18'} - '@commitlint/parse@21.2.0': - resolution: {integrity: sha512-QHWxG4d0PLTF634/AdyZ0MQS+CLn5YOuJlCFhMMlSGKFxzYGUetkHBj18xgBD+6fVzUrA2lrCdi/vlS2f/oYXg==} - engines: {node: '>=22.12.0'} + '@commitlint/parse@19.8.1': + resolution: {integrity: sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==} + engines: {node: '>=v18'} - '@commitlint/read@21.2.1': - resolution: {integrity: sha512-hUW7EJQnNTL0vPOmVMNK4CrnrNBN0nN+JJHReFkdHO5y4iyHeEmTBwuC15OCqUTjxWo7idnH1LftfpWVIaPWIA==} - engines: {node: '>=22.12.0'} + '@commitlint/read@19.8.1': + resolution: {integrity: sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==} + engines: {node: '>=v18'} - '@commitlint/resolve-extends@21.2.0': - resolution: {integrity: sha512-4O/1j51+79Wth9s/MGxt/5gs0XYLDgNlYpltQfhAvLE0itusLKs9zruxbiNg1oOkmkb9L9L4USYGjEj7n87NxA==} - engines: {node: '>=22.12.0'} + '@commitlint/resolve-extends@19.8.1': + resolution: {integrity: sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==} + engines: {node: '>=v18'} - '@commitlint/rules@21.2.0': - resolution: {integrity: sha512-C2yXMNpiB8ETZKfx5JD8+ExgF8vTU1VQMKPSUUYwqKpw9oJWQBrlXBpdU038mj2WPjof7o9UzFpmTyBeGMZwZg==} - engines: {node: '>=22.12.0'} + '@commitlint/rules@19.8.1': + resolution: {integrity: sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==} + engines: {node: '>=v18'} - '@commitlint/to-lines@21.0.1': - resolution: {integrity: sha512-bd1BFII7p1EQZre9Kaj+kKaMFP3cFCdt21K7DItVux9XP5WjLgJ0/Uy1pJJh9aPwVJ6SKg62PxqlZaHI8hQAXw==} - engines: {node: '>=22.12.0'} + '@commitlint/to-lines@19.8.1': + resolution: {integrity: sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==} + engines: {node: '>=v18'} - '@commitlint/top-level@21.2.0': - resolution: {integrity: sha512-Y5gmQ+KxzqCrBFJfLvFEPvvwD3LDiNZoTT2yeFBm96M8qhmqSzQc5DvX3rheAaAMjyIvMXOCLS/mWfdpONsjyQ==} - engines: {node: '>=22.12.0'} + '@commitlint/top-level@19.8.1': + resolution: {integrity: sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==} + engines: {node: '>=v18'} '@commitlint/types@19.8.1': resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==} engines: {node: '>=v18'} - '@commitlint/types@21.2.0': - resolution: {integrity: sha512-7zVFCDB2reMvJH5dmbKnOQPjZEvjdJTH8jc0U/PIPU1r3/+vf5pD1HlfitV2MWsWXrvu7u39iY1lyLUPOaN0Gw==} - engines: {node: '>=22.12.0'} - - '@conventional-changelog/git-client@3.1.0': - resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} - engines: {node: '>=22'} - peerDependencies: - conventional-commits-filter: ^6.0.1 - conventional-commits-parser: ^7.0.1 - peerDependenciesMeta: - conventional-commits-filter: - optional: true - conventional-commits-parser: - optional: true + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@conventional-changelog/template@1.2.1': - resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} - engines: {node: '>=22'} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@emnapi/core@1.11.0': - resolution: {integrity: sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==} - - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - - '@emnapi/runtime@1.11.0': - resolution: {integrity: sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==} - - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - - '@emnapi/wasi-threads@1.2.2': - resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} @@ -992,226 +962,226 @@ packages: '@kwsites/promise-deferred@1.1.1': resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 - '@oxc-parser/binding-android-arm-eabi@0.137.0': - resolution: {integrity: sha512-KDs+0VPdEmasOkpuJHW9V5WCF+cvYdMQv2Jd+aJXt+cxIx12NToRQRbXaRwUEDsZw+/jMk81Ve8ZFbjUkJTOwA==} + '@oxc-parser/binding-android-arm-eabi@0.133.0': + resolution: {integrity: sha512-l/44caGse+VpnY9gx0yvvc5QnnG3yG1FO3KZgYvNL1GZrfK86zIwAOgGEVlxDyRymzrU/KHiblPFpevKOmJmUA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm64@0.137.0': - resolution: {integrity: sha512-WhALNzfy3x/RfC6bsqX+csavuUY0yHHE7XfgPE5M542uhoBZUUoGTPG+nkMbGoG4+gcfss5s7urMyn5QBHu0sw==} + '@oxc-parser/binding-android-arm64@0.133.0': + resolution: {integrity: sha512-KUHmPMziLBp4u+zbrLdB7iWS7KshuZe+RAp7ELnY9SI9nNXBZ+dp8fiBqWOxhXqn+FQg3a4UcQhwmsJOKV8Jjg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-parser/binding-darwin-arm64@0.137.0': - resolution: {integrity: sha512-bFPr5hgmNMOMoyPTGtdsK4Ug21RovIPojRMgDDhSp1LtCnc/DkLwGONKjgRjszg677RlGnkYSviQ8hHaUPOVYA==} + '@oxc-parser/binding-darwin-arm64@0.133.0': + resolution: {integrity: sha512-q8dWmnU/8ea2tga9w2f1PinQ5rcMPDUGkF64T189b65YMjUomET4oy5oRldOr4AwOQkneOG/Zttnz1Dvrc62wg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.137.0': - resolution: {integrity: sha512-CL5dMm1asqXIDZHg14FLxj3Mc36w8PI7xCWh1uA4is6z8g2XrIILoTcQYOxDbwzuk34RDPX5IAGUxZr6LA9KAg==} + '@oxc-parser/binding-darwin-x64@0.133.0': + resolution: {integrity: sha512-cOKeIELIB2bJnCKwqx4Rdj+1Lss/U6uCbLxRySZrhyOOQa1flKhwZFjEHRHxk8fU1NKmhK5OnTdPQ4CpjuFuVw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-parser/binding-freebsd-x64@0.137.0': - resolution: {integrity: sha512-79h8rYGnSlKPGWo7mHr2ixO6ea7aW8B0CT965SZ8SLbNnCOH5aOYBTeVXUY6eMvEaiLyWr8Skuiugr5pDYgLGw==} + '@oxc-parser/binding-freebsd-x64@0.133.0': + resolution: {integrity: sha512-OpaSv4pW3KgFrMYQxTaS0aOE4T1DQF3qZE/4B6uqqv1KgPWWd4UQhJALi8PJPX1RRV5K7ThKXRfF7qGg2+3l1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-parser/binding-linux-arm-gnueabihf@0.137.0': - resolution: {integrity: sha512-ASgmlSimhGyr0lksgVIo6hibz1obnDq4qJbiMX/AzltfgPnanRrzG1Q+23g8ljOHOjv6dsznkUuCYL3gg0sY1Q==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': + resolution: {integrity: sha512-JGK1wlGrGwxBIlVSF7KWTX1/ru6BEtf28fRROztDRkLfiW+Kxa4onnriezMIiogfn9hVw2KzYcKiLjkLR2ns8A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.137.0': - resolution: {integrity: sha512-AU2J9aa22Sx32wRGnDjybOU9TQXXQUud5sdUi+ZB0XxwM8aToWLweV+yA0wlQm0yIUVqljquqoHCYEq9II8gJQ==} + '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': + resolution: {integrity: sha512-yuZO533Ftonxn/iyoqQzURzLQHMspvsIyfiCSNi1t/ER4eIQaR0SsmUOUm5b/lmSig7IWIUa5/BrbEkAPwcilQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm64-gnu@0.137.0': - resolution: {integrity: sha512-GdEtiG89yMr7XkUGxifgodXEEm2f+xW2f9CpDjlgAnBOwhTmrpQMvhOGobLVKUyzf/qHBXW16smk5zbF3nZU6w==} + '@oxc-parser/binding-linux-arm64-gnu@0.133.0': + resolution: {integrity: sha512-hvpbqT5pN2rR+3+xtWeizwfR/aZ0vGceg6TqYMl+ToxMpk9/tmnX7kSvQnfEUkoua8mhogzvIKsAkn0wxgblBA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@oxc-parser/binding-linux-arm64-musl@0.137.0': - resolution: {integrity: sha512-EGJ+Bs8iXx8KBH8DQ5BLoEm5lnHaYjlh4/8j8vFhrr/6z4tqONy5BZDzLpKmmNWlN6Hlc5r8YOuBVHqZ9vRFEQ==} + '@oxc-parser/binding-linux-arm64-musl@0.133.0': + resolution: {integrity: sha512-wJQGamIosQBoJHW9+S5XxrtKRo3eyJxsnS1XCPrqN0LHi8uw1pTqqTfn3t/NVuvbBg7Pumn4ez9Eidgcn0xbEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@oxc-parser/binding-linux-ppc64-gnu@0.137.0': - resolution: {integrity: sha512-vzFUQENy/fnbSe5DZWovq6tIBc1uhuMztanSW6rz1e9WdQE4gHwYuD7ZII6JnrJifd1R3RSoqiZbgRFlVL2tYQ==} + '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': + resolution: {integrity: sha512-Koaz32/O5+abIfrNGdyndgRvdOZ9jEf5/z3Ep9h3h2QWpdDiUQpVwgH0OcMXCs+l9aXxPLtkupqyVig9W6FDKw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - '@oxc-parser/binding-linux-riscv64-gnu@0.137.0': - resolution: {integrity: sha512-SfVI14HBQs9gtLcUD5hTt5hsNbdrqSUNg9S8muN+LhVQ5nf1WwH3hAoK6B9NKgdYgWAQSXFXGiiBedQ4r/BKuw==} + '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': + resolution: {integrity: sha512-R4vOjWzxhnNWHnVLeiB6jNuIifdy9vcMXZGPc7StXcxBovI+U2zg1QhZ9o8OjV80oGivs1lX5NfPLzk4IPqlRA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - '@oxc-parser/binding-linux-riscv64-musl@0.137.0': - resolution: {integrity: sha512-e7Ppy4FCIFNQxT/ikSeIWFoQ0l+N9vgtRBtLcyZXeolTzApyVoPqEXsYPrcdM/9i0Bwk8knvYd37vaEMxHyi6g==} + '@oxc-parser/binding-linux-riscv64-musl@0.133.0': + resolution: {integrity: sha512-iwgBNUTHiMdxARLYuM0SBlnYeb19iw1Ea5M+4ERZupCsBMLArti6FyZ6UfFjJxIiTDr2oW2DGQFxlQVQ/dW9rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - '@oxc-parser/binding-linux-s390x-gnu@0.137.0': - resolution: {integrity: sha512-Bho5qFwdhqsIFR7gipYEUlqvi3SRrY8sugxXig380MIaakBB1PyU9+7dBiBVScfImTNWhijUxdBwqrprGdq5WA==} + '@oxc-parser/binding-linux-s390x-gnu@0.133.0': + resolution: {integrity: sha512-ZwZNo8FZmB/gVfboQl+wXilBigGl+6nQQs+nITOeAP/HcAOjiHl6XZJL9F/KXNEspODQcbjAiyjUbeCJd9a0fA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - '@oxc-parser/binding-linux-x64-gnu@0.137.0': - resolution: {integrity: sha512-36mGWtg7PyFzjJwGDkH6/F4o2nIDEoKXLPr/X/lwqklkomQwJJt1I5GJVmGhovUEmgPK5WAeAZMqlFCehwiy9Q==} + '@oxc-parser/binding-linux-x64-gnu@0.133.0': + resolution: {integrity: sha512-govCvWx1dBlED3uu4qXctxpRcouu9I8Kn+DBktGCl760JtlGJzc9l/OmPJKlYWSbrRqKkMZehNeZ/4Wfma7uSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@oxc-parser/binding-linux-x64-musl@0.137.0': - resolution: {integrity: sha512-/Jqx6+N7A44n2BdvUr7pXhVr2vFjs6WGH3unZRczwrfiH0H1zY0QwKQMG/dtRiTlKGDKGukznPT8lx84/oEsZg==} + '@oxc-parser/binding-linux-x64-musl@0.133.0': + resolution: {integrity: sha512-ssTlpXD5Mq9uCssDJPzlRWqBt4Y7Zzd9i+XZhWmK/9Y6KUIuAxVYTYiI8lxcGWi0+3/Cz4A8q9UrD4NK9Y2j7g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@oxc-parser/binding-openharmony-arm64@0.137.0': - resolution: {integrity: sha512-9Uj0qHNNl+OgT1UTGwF7ixIXU6T1u2SbMidmgPy/h1h/fl2gRS6YpAxxY1gwHofcWjoTwkoMFd8xs5Vuj6GOFA==} + '@oxc-parser/binding-openharmony-arm64@0.133.0': + resolution: {integrity: sha512-51aByfXhPtLEdWG4a2Ihdw6cPWV1ei1AarALpFdDP8MLWDLE2NuUMgbo3DERR2Kt8fT/ok1GUvBiLxVGke9uUQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-wasm32-wasi@0.137.0': - resolution: {integrity: sha512-gW2vfkytNGgMVADiuzdvOfw0mWG9za20F/1fCJsif5aBMAvWJTSbpIXbIe0XkOe0VENk+PadpQ7cZgUy2sUJcA==} + '@oxc-parser/binding-wasm32-wasi@0.133.0': + resolution: {integrity: sha512-2e16tkKp+wDO2GTAmXfxbBcCmGEaFPIJEIRBBmVKNVXSc8/fJsSIaBGyFTPHM9ST5GNWgJcYIt94rDTks+PLwA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@oxc-parser/binding-win32-arm64-msvc@0.137.0': - resolution: {integrity: sha512-x+pFANF0yL5uK/6T7lu6SlR5qid6sp//eZXKLq5iNsIE+EQg6EaS8/wsW7E91nXXjpnPhSoMOHXShSVhGRdn8w==} + '@oxc-parser/binding-win32-arm64-msvc@0.133.0': + resolution: {integrity: sha512-KPTNDKbxH1cglrqTyVeXHb4Pk4oksz8EcE1/v8zqU7N4UXbiHfA/IwtXZ2U77fnRAWBbgVkl/lZbL7o3hRdejg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.137.0': - resolution: {integrity: sha512-sQUqym80PFi6McRsIqfJrSu2JrSClEZIXXD+/FjAFoULEKzOPsldIdFBG96xdX8aVMzCNQ9792FPx3MfkEIrFA==} + '@oxc-parser/binding-win32-ia32-msvc@0.133.0': + resolution: {integrity: sha512-Una1bNYv9zCavQrfnDR9wuZVB3itLjCEH4Oz7i6CwAJN/Xq9b+zbbcxmvdkKvvJt4Ngc/MBmIYlbLo3zS4TQ0A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.137.0': - resolution: {integrity: sha512-2AsevxlvNN4WKxpEn3RtqD5zbqMaXF+T7JXblsP4gVuY+vC9dXS4ED/PwfRCliFqoeisYS3Iro4DHzxr0TEvVA==} + '@oxc-parser/binding-win32-x64-msvc@0.133.0': + resolution: {integrity: sha512-kjBhCiOGSYTwDJQuuZa7a94JbP8htWu7J0X1KwH74kV2K5eYf6eyJRYmkpCDvr0XEL8tMxYI4WU1VekblFCLgg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxc-project/types@0.137.0': - resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} - '@oxc-resolver/binding-android-arm-eabi@11.21.3': - resolution: {integrity: sha512-eNU11A2WNizh04v3uyaJCootrHIaS0B9aHYXvAvVnPNk4xYSjMUjHnhQ6dewPN2MRYDskV85d1N0Aw0WNWhcyg==} + '@oxc-resolver/binding-android-arm-eabi@11.20.0': + resolution: {integrity: sha512-IjfWOXRgJFNdORDl+Uf1aibNgZY2guOD3zmOhx1BGVb/MIiqlFTdmjpQNplSN58lhWehnX4UNqC3QwpUo8pjJg==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.21.3': - resolution: {integrity: sha512-8Q+ZjTLvn2dIcWsrmhdrEihm7q+ag/k+mkry7Z+t0QbbHaVxXQfvH9AewyVMh/WrpEKhQ3DDgx9fYbqeCpeOEw==} + '@oxc-resolver/binding-android-arm64@11.20.0': + resolution: {integrity: sha512-QqslZAuFQG8Q9xm7JuIn8JUbvywhSBMVhuQHtYW+auirZJloS41oxUUaBXk7uUhZJgp44c5zQLeVvmFaDQB+2Q==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.21.3': - resolution: {integrity: sha512-wkh0qKZGHXVUDxFw3oA1TXnU2BDYY/r775oJflGeIr8uDPPoN2pk8gijQIzYRT6hoql/lg3+Tx/SaTn9e2/aGg==} + '@oxc-resolver/binding-darwin-arm64@11.20.0': + resolution: {integrity: sha512-MUcavykj2ewlR+kc5arpg4tC2RvzJkUxWtNv74pf7lcNk00GpIpN43vXMj+j6r4eMmfZhlb8hueKoIb8e9kAGQ==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.21.3': - resolution: {integrity: sha512-HbNc23FAQYbuyDV2vBWMez4u4mrsm5RAkniGZAWqr6lYZ3N4beeqIb776jzwRl8qL2zRhHVXpUj97X0QgogVzg==} + '@oxc-resolver/binding-darwin-x64@11.20.0': + resolution: {integrity: sha512-BGB16nRUK5Etiv//ihPyzj8Lj1px0mhh4YIfe0FDf045ywknfSm0GEbiRESpr6Q4K82AvnyaRIhhluHByvS4bg==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.21.3': - resolution: {integrity: sha512-K6xNsTUPEUdfrn0+kbMq5nOUB5w1C5pavPQngt4TM2FpN91lP0PBe2srSpamb4d69O7h86oAi/qWX/kZNRSjkw==} + '@oxc-resolver/binding-freebsd-x64@11.20.0': + resolution: {integrity: sha512-JZgtePaqj3qmD5XFHJaSLWzHRxQu0LaPkdoM1KJXYADvAaa83ijXHclV3ej3CueeW0wxfIAbGCZVP45J0CA7uQ==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.3': - resolution: {integrity: sha512-VcFmOpcpWX1zoEy8M58tR2M9YxM+Z9RuQhqAx5q0CTmrruaP7Gveejg75hzd/5sg5nk9G3aLALEa3hE2FsmmTQ==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.20.0': + resolution: {integrity: sha512-hOQ/p3ry3v3SchUBXicrrnszaI/UmYzM4wtS4RGfwgVUX7a+HbyQSzJ5aOzu+o6XZkFkS3ZXN4PZAzhOb77OSg==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.21.3': - resolution: {integrity: sha512-quVoxFLBy43hWaQbbDtQNRwAX5vX76mv7n64icAtQcJ3eNgVeblqmkupF/hAneNthdqSlnd1sTjb3aQSaDPaCQ==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.20.0': + resolution: {integrity: sha512-2ArPksaw0AqeuGBfoS715VF+JvJQAhD2niWgjE5hVO+L+nAfikVQopvngCMX9x4BD8itWoQ3dnikrQyl5Ho5Jg==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.21.3': - resolution: {integrity: sha512-X0AqNZgcD07Q4V3RDK18/vYOj/HQT/FnmEFGYS2jTWqY7JO13ryE3TEs3eAIgUJhBnNkpEaiXqz3VK8M7qQhWQ==} + '@oxc-resolver/binding-linux-arm64-gnu@11.20.0': + resolution: {integrity: sha512-0bJnmYFp62JdZ4nVMDUZ/C58BCZOCcqgKtnUlp7L9Ojf/czIN+3j72YlLPeWLkzlr6SlYvIQA4SGV/HyO0d+qg==} cpu: [arm64] os: [linux] - '@oxc-resolver/binding-linux-arm64-musl@11.21.3': - resolution: {integrity: sha512-YkaQnaKYdbuaXvRt5Qd0GpbihzVnyfR6z1SpYfIUC6RTu4NF7lDKPjVkYb+jRI2gedVO2rVpN35Y6akG6ud4Lw==} + '@oxc-resolver/binding-linux-arm64-musl@11.20.0': + resolution: {integrity: sha512-wKHHzPKZo7Ufhv/Bt6yxT7FOgnIgW4gwXcJUipkShGp68W3wGVqvr1Sr0fY65lN0Oy6y41+g2kIDvkgZaMMUkw==} cpu: [arm64] os: [linux] - '@oxc-resolver/binding-linux-ppc64-gnu@11.21.3': - resolution: {integrity: sha512-gB9HwhrPiFqUzDeEq+y/CgAijz1YdI6BnXz5GaH2Pa9cWdutchlkGFAiAuGb/PjVQpiK6NFKzFuztxrweoit7A==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.20.0': + resolution: {integrity: sha512-RN8goF7Ie0B79L4i4G6OeBocTgSC56vJbQ65VJje+oXnldVpLnOU7j/AQ/dP94TcCS+Yh6WG8u3Qt4ETteXFNQ==} cpu: [ppc64] os: [linux] - '@oxc-resolver/binding-linux-riscv64-gnu@11.21.3': - resolution: {integrity: sha512-zjDWBlYk8QGv0H8dsPUWqkfjYIIjG2TvspGkzXL0eImbgxtZorA/klKeHyolevoT3Kvbi+1iMr9Lhrh7jf54Og==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.20.0': + resolution: {integrity: sha512-5l1yU6/xQEqLZRzxqmMxJfWPslpwCmBsdDGaBvABPehxquCXDC7dd7oraNdKSJUMDXSM7VvVj8H2D2FTjU7oWw==} cpu: [riscv64] os: [linux] - '@oxc-resolver/binding-linux-riscv64-musl@11.21.3': - resolution: {integrity: sha512-4UfsQvacV388y1zpXL7C1x1FNYaV52JtuNRiuzrfQA2z1z6ElVrsidkGsrvQ5EgeSq1Pj7kaKqrgGkvFuxJ/tw==} + '@oxc-resolver/binding-linux-riscv64-musl@11.20.0': + resolution: {integrity: sha512-xHEvkbgz6UC+A3JOyDQy76LkUaxsNSfIr3/GV8slwZsnuooJiIB34gzJfsyvR4JdCYNUUPsRJc/w/oWkODu+hg==} cpu: [riscv64] os: [linux] - '@oxc-resolver/binding-linux-s390x-gnu@11.21.3': - resolution: {integrity: sha512-b5uH+HKH0MP5mNBYaK75SKsJbw52URqrx2LavYdq6wb0l3ExAG5niYRP9DWUNHdKilpaBVM2bXk9HNWrH3ew7Q==} + '@oxc-resolver/binding-linux-s390x-gnu@11.20.0': + resolution: {integrity: sha512-aWPDUUmSeyHvlW+SoEUd+JIJsQhVhu6a5tBpDRMu058naPAchTgAVGCFy35zjbnFlt0i8hLWziff6HX0D3LU4g==} cpu: [s390x] os: [linux] - '@oxc-resolver/binding-linux-x64-gnu@11.21.3': - resolution: {integrity: sha512-PjYlmilBpNRh2ntXNYAK3Am5w/nPfEpnU/96iNx7CI8EzAn12J4JRiec63wHJTH31nLoCNxBg/829pN+3CfG3Q==} + '@oxc-resolver/binding-linux-x64-gnu@11.20.0': + resolution: {integrity: sha512-x2YeSimvhJjKLVD8KSu8f/rqU1potcdEMkApIPJqjZWN7c2Fpt4g2X32WDg1p+XDAmyT7nuQGe0vnhvXeLbH+g==} cpu: [x64] os: [linux] - '@oxc-resolver/binding-linux-x64-musl@11.21.3': - resolution: {integrity: sha512-QTBAb7JuHlZ7JUEyM8UiQi2f7m/L4swBhP2TNpYIDc9Wp/wRw1G/8sl6i13aIzQAXH7LKIm294LeOHd0lQR8zA==} + '@oxc-resolver/binding-linux-x64-musl@11.20.0': + resolution: {integrity: sha512-kcRLEIxpZefeYfLChjpgFf3ilBzRDZ+yobMrpRsQlSrxuFGtm3U6PMU7AaEpMqo3NfDGVyJJseAjnRLzMFHjwQ==} cpu: [x64] os: [linux] - '@oxc-resolver/binding-openharmony-arm64@11.21.3': - resolution: {integrity: sha512-4j1DFwjwv36ec9kds0jU/ucQ5Ha4ERO/H95BxR5JFf0kqUUAJ1kwII7XhTc1vZrkdJkvLGC9Q2MbpObpum8RBg==} + '@oxc-resolver/binding-openharmony-arm64@11.20.0': + resolution: {integrity: sha512-HHcfnApSZGtKhTiHqe8OZruOZe5XuFQH5/E0Yhj3u8fnFvzkM4/k6WjacUf4SvA0SPEAbfbgYmVPuo0VX/fIBQ==} cpu: [arm64] os: [openharmony] - '@oxc-resolver/binding-wasm32-wasi@11.21.3': - resolution: {integrity: sha512-i8oluoel5kru/j1WNrjmQSiA3GQ7wvIYVR1IwIoZtKogAhya2iub+ZKIeSIkcJOrnzQ18Tzl/F+kL3fYOxZLvA==} + '@oxc-resolver/binding-wasm32-wasi@11.20.0': + resolution: {integrity: sha512-Tn0y1XOFYHNfK1wp1Z5QK8Rcld/bsOwRISQXfqAZ5IBpv8Gz1IvV39fUWNprqNdRizgcvFhOzWwFun2zkJsyBg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.21.3': - resolution: {integrity: sha512-M/8dw8dD6aOs+NlPJax401CZB9I7Aut84isQLgALGGwke4Afvw+/7yYhZb94yXf6t2sPLhQLmSmtSV+2FhsOWg==} + '@oxc-resolver/binding-win32-arm64-msvc@11.20.0': + resolution: {integrity: sha512-qPi25YNPe4YenS8MgsQU2+bIFHxxpLx1LVna2444cEHqNPhNjvWf9zqj4aWE43H9LpAsTmkkAlA3eL5ElBU3mA==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.21.3': - resolution: {integrity: sha512-H7BCt/VnS9hnmMp42eGhZ99izSCRvlnWwy/N71K1/J8QoExwY4262Z8QiEkMDtduRJrztayDxETTckmUuAVL9Q==} + '@oxc-resolver/binding-win32-x64-msvc@11.20.0': + resolution: {integrity: sha512-Wb14jWEW8huH6It9F6sXd9vrYmIS7pMrgkU6sxpLxkP+9z+wRgs71hUEhRpcn8FOXAFa27FVWfY2tRpbfTzfLw==} cpu: [x64] os: [win32] @@ -1353,14 +1323,6 @@ packages: '@simple-git/argv-parser@1.1.1': resolution: {integrity: sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==} - '@simple-libs/child-process-utils@2.0.0': - resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} - engines: {node: '>=22'} - - '@simple-libs/stream-utils@2.0.0': - resolution: {integrity: sha512-fCTuZK4QBa+39Oz9l4OGfJfz+GpwCp3AqO7Zch3to99xHPgstVsRFpeQ8LNd2o1Gv8raL2mCFwiaHh7bFSp5DQ==} - engines: {node: '>=22'} - '@sindresorhus/merge-streams@4.0.0': resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} @@ -1388,8 +1350,8 @@ packages: '@stryker-mutator/core': 9.6.1 vitest: '>=2.0.0' - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -1403,128 +1365,8 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/node@26.1.1': - resolution: {integrity: sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==} - - '@typescript/typescript-aix-ppc64@7.0.2': - resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} - engines: {node: '>=16.20.0'} - cpu: [ppc64] - os: [aix] - - '@typescript/typescript-darwin-arm64@7.0.2': - resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [darwin] - - '@typescript/typescript-darwin-x64@7.0.2': - resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [darwin] - - '@typescript/typescript-freebsd-arm64@7.0.2': - resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [freebsd] - - '@typescript/typescript-freebsd-x64@7.0.2': - resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [freebsd] - - '@typescript/typescript-linux-arm64@7.0.2': - resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [linux] - - '@typescript/typescript-linux-arm@7.0.2': - resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} - engines: {node: '>=16.20.0'} - cpu: [arm] - os: [linux] - - '@typescript/typescript-linux-loong64@7.0.2': - resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} - engines: {node: '>=16.20.0'} - cpu: [loong64] - os: [linux] - - '@typescript/typescript-linux-mips64el@7.0.2': - resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} - engines: {node: '>=16.20.0'} - cpu: [mips64el] - os: [linux] - - '@typescript/typescript-linux-ppc64@7.0.2': - resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} - engines: {node: '>=16.20.0'} - cpu: [ppc64] - os: [linux] - - '@typescript/typescript-linux-riscv64@7.0.2': - resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} - engines: {node: '>=16.20.0'} - cpu: [riscv64] - os: [linux] - - '@typescript/typescript-linux-s390x@7.0.2': - resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} - engines: {node: '>=16.20.0'} - cpu: [s390x] - os: [linux] - - '@typescript/typescript-linux-x64@7.0.2': - resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [linux] - - '@typescript/typescript-netbsd-arm64@7.0.2': - resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [netbsd] - - '@typescript/typescript-netbsd-x64@7.0.2': - resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [netbsd] - - '@typescript/typescript-openbsd-arm64@7.0.2': - resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [openbsd] - - '@typescript/typescript-openbsd-x64@7.0.2': - resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [openbsd] - - '@typescript/typescript-sunos-x64@7.0.2': - resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [sunos] - - '@typescript/typescript-win32-arm64@7.0.2': - resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [win32] - - '@typescript/typescript-win32-x64@7.0.2': - resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [win32] + '@types/node@24.10.15': + resolution: {integrity: sha512-BgjLoRuSr0MTI5wA6gMw9Xy0sFudAaUuvrnjgGx9wZ522fYYLA5SYJ+1Y30vTcJEG+DRCyDHx/gzQVfofYzSdg==} '@vitest/coverage-v8@3.2.6': resolution: {integrity: sha512-LsAdmUapA0qSN306d8+zOyawM0hFm2m2Hg9IwVNIKBm+qJV8cijiq2c+gxKZcB1HCfIWAy+0qEZDCUQA58A1cw==} @@ -1564,6 +1406,10 @@ packages: '@vitest/utils@3.2.6': resolution: {integrity: sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==} + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} @@ -1609,10 +1455,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - argue-cli@3.1.0: - resolution: {integrity: sha512-DhBpBfXL4SS2uC0N922MMajKR3CdrTG0u2or1PNYgXMsrSzViJrbtvT0nCLlLGUI0plam/ZZCs7aAauHtW9thw==} - engines: {node: '>=22'} - array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} @@ -1695,9 +1537,9 @@ packages: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} - cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -1706,14 +1548,14 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@14.0.3: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} - commander@15.0.0: - resolution: {integrity: sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==} - engines: {node: '>=22.12.0'} - commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1728,21 +1570,17 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - conventional-changelog-angular@9.2.1: - resolution: {integrity: sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==} - engines: {node: '>=22'} - - conventional-changelog-conventionalcommits@10.2.1: - resolution: {integrity: sha512-n4Kr1HFMTf3iMbES0TMxKIcYtUUv4rKqyQQp2JwfOEfFCOfGT3Tq4mCyJ8S9/YPyWhydjfKrrvnyl+gCjA+mJQ==} - engines: {node: '>=22'} + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} conventional-changelog-conventionalcommits@7.0.2: resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} engines: {node: '>=16'} - conventional-commits-parser@7.1.0: - resolution: {integrity: sha512-DPp6hkUjvwIivxbkrTiLXeRswNv1A/4GFA2X6scXma0AMa9632V3TwxmrlkUIEtUktiM3Ln+RrSH2xlP3/jUTw==} - engines: {node: '>=22'} + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} hasBin: true convert-source-map@2.0.0: @@ -1765,10 +1603,44 @@ packages: typescript: optional: true + cpd-darwin-arm64@5.0.7: + resolution: {integrity: sha512-yfqUd+y1lqCp0Oso462SxYmaLhnkZRumhvZB+Noz/jg4+AvQDZcsVnb7gbjr7Wu3+Te8Jz41mZs+ka2XDJ257g==} + cpu: [arm64] + os: [darwin] + + cpd-darwin-x64@5.0.7: + resolution: {integrity: sha512-RFT71RYdfuejaRY5K0jxEg/hIb/lDX7DK3+Y8SvQixrQi4Epo5EMhtiechCYlIcuDkbq4b2htpldipqssEcc/g==} + cpu: [x64] + os: [darwin] + + cpd-linux-arm64-gnu@5.0.7: + resolution: {integrity: sha512-SBkIVIgH+oqsPJCh89PzOA8EJ0URF97FP9JgGgQrYogfQ3AmNyjJIGpgTClj9IyTb5jTomJVpwa75FYqERXVIQ==} + cpu: [arm64] + os: [linux] + + cpd-linux-x64-gnu@5.0.7: + resolution: {integrity: sha512-UE+BGxcJSYJPNGD01vPZcIFNFKOc3lgMGpe717JppCCSjyjXd8fKO3FXDePcy3MRTZymC67i2rg6IZkLVsmBWQ==} + cpu: [x64] + os: [linux] + + cpd-linux-x64-musl@5.0.7: + resolution: {integrity: sha512-1Lv5BXw5AHTb5x5quL813UryKmbzJAJ2uG2lonnanEarWA+j/D0jKNJjY7k3+rnKaeAugiMltmeF6Rf9PAFSIw==} + cpu: [x64] + os: [linux] + + cpd-windows-x64-msvc@5.0.7: + resolution: {integrity: sha512-rISkx5Vfl9Chl6kIuOJrf03pDtV4xBGqPaXcS32RE5t65JlAO+AEt0uVpjMWDPm9SKS6onyBKHdRoQkiluqW/Q==} + cpu: [x64] + os: [win32] + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1833,9 +1705,6 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - es-toolkit@1.50.0: - resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} - esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -1861,8 +1730,8 @@ packages: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} - fast-check@4.9.0: - resolution: {integrity: sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg==} + fast-check@4.7.0: + resolution: {integrity: sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==} engines: {node: '>=12.17.0'} fast-deep-equal@3.1.3: @@ -1896,6 +1765,10 @@ packages: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + fix-dts-default-cjs-exports@1.0.1: resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} @@ -1924,10 +1797,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.6.0: - resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} - engines: {node: '>=18'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1943,14 +1812,20 @@ packages: get-tsconfig@4.14.0: resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. + hasBin: true + glob@10.5.0: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - global-directory@5.0.0: - resolution: {integrity: sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==} - engines: {node: '>=20'} + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} @@ -1983,12 +1858,15 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ini@6.0.0: - resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} - engines: {node: ^20.17.0 || >=22.9.0} + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -2009,6 +1887,10 @@ packages: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + is-unicode-supported@2.1.0: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} @@ -2035,6 +1917,10 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + jiti@2.7.0: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true @@ -2059,38 +1945,8 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true - jscpd-darwin-arm64@5.0.12: - resolution: {integrity: sha512-CQCDYhQY9yOGGeauzkRGYW/QtXurPCjfDkEhUoM/M5UdmpzxfG3i9mnNsaheJ0RdFRf73mL7JaLVRP8U2l5/kA==} - cpu: [arm64] - os: [darwin] - - jscpd-darwin-x64@5.0.12: - resolution: {integrity: sha512-7XNCDfChP9fPkIWLepd0zGnTov7/5mR7rJ5Utc1MdWFdgkN//qz6FAJ1FhQA0E/qjFedy9XTucfUCgLybSBsjw==} - cpu: [x64] - os: [darwin] - - jscpd-linux-arm64-gnu@5.0.12: - resolution: {integrity: sha512-i/usHD0/8twzb2Qo4vFWcnuAD4IDLS6K/mTXwYy1CiJZDw4gmjfH45jtjdKUyoutTAiNs+ZWZgx1gIRljUbFuA==} - cpu: [arm64] - os: [linux] - - jscpd-linux-x64-gnu@5.0.12: - resolution: {integrity: sha512-TqaeSTaGawcqyXSrQvYJFtLRn4aQeHgphGGsq2ZtVAg+lPeuMmh81c3bl0yi2dL3gDX1RGBQKBVul1XQknOuoA==} - cpu: [x64] - os: [linux] - - jscpd-linux-x64-musl@5.0.12: - resolution: {integrity: sha512-WelugY1/rdoo0Y0sqJ2XQOIvyIZTfRe+vP3MJe4XvEUwPF0v+9SQoS34FnfblRhsddVixyNkgl7x/sHid9UMJw==} - cpu: [x64] - os: [linux] - - jscpd-windows-x64-msvc@5.0.12: - resolution: {integrity: sha512-01x1klKjvfzI6Of5tI9u72x7TIQZQLLG6kMdsEPJKl/BXbskdknrfCepeTXRBbdFPKs25jfcd0klZ4OdDvww5w==} - cpu: [x64] - os: [win32] - - jscpd@5.0.12: - resolution: {integrity: sha512-87dC+akj2mCywlt8p3xnRlDg0B55u4GDbfE9cuwOOeIxbEuWuIoNqGoYi65A0516aJ4EzAjGwBj1Qb/Ahc8WAQ==} + jscpd@5.0.7: + resolution: {integrity: sha512-V2YemuWeT7qOF6TeNG1zkKavamuDJJQppdHOQjG8dR2bzWNEJacaPgi/ALQPTlNbtXoL/rsQGhPQC8ASN+WzMQ==} engines: {node: '>=18'} hasBin: true @@ -2113,8 +1969,12 @@ packages: engines: {node: '>=6'} hasBin: true - knip@6.27.0: - resolution: {integrity: sha512-CngYEYrD0n20N06FXA8n3u/0Wnnugoa+B9k14OP+iKIgkCHuzvIdsP3nfwjhByoc1WfogpxfiriMboAXFETDUw==} + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + knip@6.16.1: + resolution: {integrity: sha512-TKMn1rxgH6h9vXR9Y0B+Cq7AdPTr9EI02IwoT65NzqYUkvoDQAaJ/aPybiFpAhZ1px6cNYYwXf86iHkBgzCo9w==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2183,9 +2043,40 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.groupby@4.6.0: resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} @@ -2209,6 +2100,10 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -2220,6 +2115,9 @@ packages: resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.3: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} @@ -2274,12 +2172,20 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} - oxc-parser@0.137.0: - resolution: {integrity: sha512-yFImD+WLElJpLKy8llG1qe4DCmMsL18peRp8XP1JKfig/gISbJkglnpDtX2aTmAn10kZF7164HbN2H8QPsXxGg==} + oxc-parser@0.133.0: + resolution: {integrity: sha512-661RSx+ZcjBmjBYid+Fpp/2F5EbtildpeoZh5HdgnGs+jZ03nqQEQW8yGkt4BGyOC3OMPDQQRl8M5kqD2/g6jw==} engines: {node: ^20.19.0 || >=22.12.0} - oxc-resolver@11.21.3: - resolution: {integrity: sha512-2Mx3fKQz7+xgrBONjsxOgCGtMHOn38/HxMzW1I5efwXB5a4lRN0Vp40gYUJFBWJslcrvwoofTrqoTnLbwTd3pA==} + oxc-resolver@11.20.0: + resolution: {integrity: sha512-CblytBiV/a/ZXY34dsVU2NxhIOxMXst8CvDCtyBelVITgd7PLrKzbEbA6oKLdPjvDKDzCiW48qzmzZ+mYaqn+g==} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2296,6 +2202,10 @@ packages: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} engines: {node: '>=18'} + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2322,10 +2232,6 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} - picomatch@4.0.5: - resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} - engines: {node: '>=12'} - pirates@4.0.7: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} @@ -2363,8 +2269,8 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} - pure-rand@8.4.2: - resolution: {integrity: sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng==} + pure-rand@8.4.0: + resolution: {integrity: sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==} qs@6.15.2: resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} @@ -2374,6 +2280,10 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -2455,6 +2365,10 @@ packages: resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2469,10 +2383,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2505,6 +2415,10 @@ packages: resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} engines: {node: '>=18'} + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2512,6 +2426,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2583,23 +2500,27 @@ packages: resolution: {integrity: sha512-k4kX5Up6qA68D0Cby2AK+6+vM5k3qTxe+/3FqhnHRExjY5cfbOnzjQZbP/LXleF8hVoDvDqxlgk9KK83HoBZlQ==} engines: {node: '>= 16.0.0'} - typescript@7.0.2: - resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} - engines: {node: '>=16.20.0'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} - unbash@4.0.3: - resolution: {integrity: sha512-3cudTErfToSc4Ggv8XGXVNVli/xHKUtUZvaY5UVwhOcUPbQGz7PeaEnT/SAVgNziZtX67KEN9swMUYkLghxA1w==} + unbash@3.0.0: + resolution: {integrity: sha512-FeFPZ/WFT0mbRCuydiZzpPFlrYN8ZUpphQKoq4EeElVIYjYyGzPMxQR/simUwCOJIyVhpFk4RbtyO7RuMpMnHA==} engines: {node: '>=14'} underscore@1.13.8: resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} - undici-types@8.3.0: - resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} @@ -2704,10 +2625,6 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2720,13 +2637,17 @@ packages: engines: {node: '>= 14.6'} hasBin: true - yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} yoctocolors-cjs@2.1.3: resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} @@ -2736,8 +2657,8 @@ packages: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} - zod@4.4.3: - resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} snapshots: @@ -2964,55 +2885,52 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@biomejs/biome@2.5.5': + '@biomejs/biome@2.4.7': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.5.5 - '@biomejs/cli-darwin-x64': 2.5.5 - '@biomejs/cli-linux-arm64': 2.5.5 - '@biomejs/cli-linux-arm64-musl': 2.5.5 - '@biomejs/cli-linux-x64': 2.5.5 - '@biomejs/cli-linux-x64-musl': 2.5.5 - '@biomejs/cli-win32-arm64': 2.5.5 - '@biomejs/cli-win32-x64': 2.5.5 + '@biomejs/cli-darwin-arm64': 2.4.7 + '@biomejs/cli-darwin-x64': 2.4.7 + '@biomejs/cli-linux-arm64': 2.4.7 + '@biomejs/cli-linux-arm64-musl': 2.4.7 + '@biomejs/cli-linux-x64': 2.4.7 + '@biomejs/cli-linux-x64-musl': 2.4.7 + '@biomejs/cli-win32-arm64': 2.4.7 + '@biomejs/cli-win32-x64': 2.4.7 - '@biomejs/cli-darwin-arm64@2.5.5': + '@biomejs/cli-darwin-arm64@2.4.7': optional: true - '@biomejs/cli-darwin-x64@2.5.5': + '@biomejs/cli-darwin-x64@2.4.7': optional: true - '@biomejs/cli-linux-arm64-musl@2.5.5': + '@biomejs/cli-linux-arm64-musl@2.4.7': optional: true - '@biomejs/cli-linux-arm64@2.5.5': + '@biomejs/cli-linux-arm64@2.4.7': optional: true - '@biomejs/cli-linux-x64-musl@2.5.5': + '@biomejs/cli-linux-x64-musl@2.4.7': optional: true - '@biomejs/cli-linux-x64@2.5.5': + '@biomejs/cli-linux-x64@2.4.7': optional: true - '@biomejs/cli-win32-arm64@2.5.5': + '@biomejs/cli-win32-arm64@2.4.7': optional: true - '@biomejs/cli-win32-x64@2.5.5': + '@biomejs/cli-win32-x64@2.4.7': optional: true - '@commitlint/cli@21.2.1(@types/node@26.1.1)(conventional-commits-parser@7.1.0)(typescript@7.0.2)': + '@commitlint/cli@19.8.1(@types/node@24.10.15)(typescript@5.9.3)': dependencies: - '@commitlint/config-conventional': 21.2.0 - '@commitlint/format': 21.2.0 - '@commitlint/lint': 21.2.0 - '@commitlint/load': 21.2.0(@types/node@26.1.1)(typescript@7.0.2) - '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.0) - '@commitlint/types': 21.2.0 + '@commitlint/format': 19.8.1 + '@commitlint/lint': 19.8.1 + '@commitlint/load': 19.8.1(@types/node@24.10.15)(typescript@5.9.3) + '@commitlint/read': 19.8.1 + '@commitlint/types': 19.8.1 tinyexec: 1.0.2 - yargs: 18.0.0 + yargs: 17.7.2 transitivePeerDependencies: - '@types/node' - - conventional-commits-filter - - conventional-commits-parser - typescript '@commitlint/config-conventional@19.8.1': @@ -3020,137 +2938,110 @@ snapshots: '@commitlint/types': 19.8.1 conventional-changelog-conventionalcommits: 7.0.2 - '@commitlint/config-conventional@21.2.0': - dependencies: - '@commitlint/types': 21.2.0 - conventional-changelog-conventionalcommits: 10.2.1 - - '@commitlint/config-validator@21.2.0': + '@commitlint/config-validator@19.8.1': dependencies: - '@commitlint/types': 21.2.0 + '@commitlint/types': 19.8.1 ajv: 8.20.0 - '@commitlint/ensure@21.2.0': + '@commitlint/ensure@19.8.1': dependencies: - '@commitlint/types': 21.2.0 - es-toolkit: 1.50.0 + '@commitlint/types': 19.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 - '@commitlint/execute-rule@21.0.1': {} + '@commitlint/execute-rule@19.8.1': {} - '@commitlint/format@21.2.0': + '@commitlint/format@19.8.1': dependencies: - '@commitlint/types': 21.2.0 - picocolors: 1.1.1 + '@commitlint/types': 19.8.1 + chalk: 5.6.2 - '@commitlint/is-ignored@21.2.0': + '@commitlint/is-ignored@19.8.1': dependencies: - '@commitlint/types': 21.2.0 + '@commitlint/types': 19.8.1 semver: 7.7.4 - '@commitlint/lint@21.2.0': + '@commitlint/lint@19.8.1': dependencies: - '@commitlint/is-ignored': 21.2.0 - '@commitlint/parse': 21.2.0 - '@commitlint/rules': 21.2.0 - '@commitlint/types': 21.2.0 + '@commitlint/is-ignored': 19.8.1 + '@commitlint/parse': 19.8.1 + '@commitlint/rules': 19.8.1 + '@commitlint/types': 19.8.1 - '@commitlint/load@21.2.0(@types/node@26.1.1)(typescript@7.0.2)': + '@commitlint/load@19.8.1(@types/node@24.10.15)(typescript@5.9.3)': dependencies: - '@commitlint/config-validator': 21.2.0 - '@commitlint/execute-rule': 21.0.1 - '@commitlint/resolve-extends': 21.2.0 - '@commitlint/types': 21.2.0 - cosmiconfig: 9.0.1(typescript@7.0.2) - cosmiconfig-typescript-loader: 6.2.0(@types/node@26.1.1)(cosmiconfig@9.0.1(typescript@7.0.2))(typescript@7.0.2) - es-toolkit: 1.50.0 - is-plain-obj: 4.1.0 - picocolors: 1.1.1 + '@commitlint/config-validator': 19.8.1 + '@commitlint/execute-rule': 19.8.1 + '@commitlint/resolve-extends': 19.8.1 + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + cosmiconfig: 9.0.1(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.2.0(@types/node@24.10.15)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 transitivePeerDependencies: - '@types/node' - typescript - '@commitlint/message@21.2.0': {} + '@commitlint/message@19.8.1': {} - '@commitlint/parse@21.2.0': + '@commitlint/parse@19.8.1': dependencies: - '@commitlint/types': 21.2.0 - conventional-changelog-angular: 9.2.1 - conventional-commits-parser: 7.1.0 + '@commitlint/types': 19.8.1 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 - '@commitlint/read@21.2.1(conventional-commits-parser@7.1.0)': + '@commitlint/read@19.8.1': dependencies: - '@commitlint/top-level': 21.2.0 - '@commitlint/types': 21.2.0 - '@conventional-changelog/git-client': 3.1.0(conventional-commits-parser@7.1.0) + '@commitlint/top-level': 19.8.1 + '@commitlint/types': 19.8.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 tinyexec: 1.0.2 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - '@commitlint/resolve-extends@21.2.0': + '@commitlint/resolve-extends@19.8.1': dependencies: - '@commitlint/config-validator': 21.2.0 - '@commitlint/types': 21.2.0 - es-toolkit: 1.50.0 - global-directory: 5.0.0 + '@commitlint/config-validator': 19.8.1 + '@commitlint/types': 19.8.1 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 resolve-from: 5.0.0 - '@commitlint/rules@21.2.0': + '@commitlint/rules@19.8.1': dependencies: - '@commitlint/ensure': 21.2.0 - '@commitlint/message': 21.2.0 - '@commitlint/to-lines': 21.0.1 - '@commitlint/types': 21.2.0 + '@commitlint/ensure': 19.8.1 + '@commitlint/message': 19.8.1 + '@commitlint/to-lines': 19.8.1 + '@commitlint/types': 19.8.1 - '@commitlint/to-lines@21.0.1': {} + '@commitlint/to-lines@19.8.1': {} - '@commitlint/top-level@21.2.0': + '@commitlint/top-level@19.8.1': dependencies: - escalade: 3.2.0 + find-up: 7.0.0 '@commitlint/types@19.8.1': dependencies: '@types/conventional-commits-parser': 5.0.2 chalk: 5.6.2 - '@commitlint/types@21.2.0': - dependencies: - conventional-commits-parser: 7.1.0 - picocolors: 1.1.1 - - '@conventional-changelog/git-client@3.1.0(conventional-commits-parser@7.1.0)': - dependencies: - '@simple-libs/child-process-utils': 2.0.0 - '@simple-libs/stream-utils': 2.0.0 - semver: 7.7.4 - optionalDependencies: - conventional-commits-parser: 7.1.0 - - '@conventional-changelog/template@1.2.1': {} - - '@emnapi/core@1.11.0': - dependencies: - '@emnapi/wasi-threads': 1.2.2 - tslib: 2.8.1 - optional: true - - '@emnapi/core@1.11.1': + '@emnapi/core@1.10.0': dependencies: - '@emnapi/wasi-threads': 1.2.2 + '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.0': + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.2.2': + '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 optional: true @@ -3306,245 +3197,245 @@ snapshots: '@inquirer/ansi@2.0.5': {} - '@inquirer/checkbox@4.3.2(@types/node@26.1.1)': + '@inquirer/checkbox@4.3.2(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/type': 3.0.10(@types/node@24.10.15) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/checkbox@5.1.4(@types/node@26.1.1)': + '@inquirer/checkbox@5.1.4(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 2.0.5 - '@inquirer/core': 11.1.9(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/confirm@5.1.21(@types/node@26.1.1)': + '@inquirer/confirm@5.1.21(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/confirm@6.0.12(@types/node@26.1.1)': + '@inquirer/confirm@6.0.12(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/core@10.3.2(@types/node@26.1.1)': + '@inquirer/core@10.3.2(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/type': 3.0.10(@types/node@24.10.15) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/core@11.1.9(@types/node@26.1.1)': + '@inquirer/core@11.1.9(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 2.0.5 '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/type': 4.0.5(@types/node@24.10.15) cli-width: 4.1.0 fast-wrap-ansi: 0.2.0 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/editor@4.2.23(@types/node@26.1.1)': + '@inquirer/editor@4.2.23(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/external-editor': 1.0.3(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/editor@5.1.1(@types/node@26.1.1)': + '@inquirer/editor@5.1.1(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/external-editor': 3.0.0(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/external-editor': 3.0.0(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/expand@4.0.23(@types/node@26.1.1)': + '@inquirer/expand@4.0.23(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/expand@5.0.13(@types/node@26.1.1)': + '@inquirer/expand@5.0.13(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/external-editor@1.0.3(@types/node@26.1.1)': + '@inquirer/external-editor@1.0.3(@types/node@24.10.15)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/external-editor@3.0.0(@types/node@26.1.1)': + '@inquirer/external-editor@3.0.0(@types/node@24.10.15)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 '@inquirer/figures@1.0.15': {} '@inquirer/figures@2.0.5': {} - '@inquirer/input@4.3.1(@types/node@26.1.1)': + '@inquirer/input@4.3.1(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/input@5.0.12(@types/node@26.1.1)': + '@inquirer/input@5.0.12(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/number@3.0.23(@types/node@26.1.1)': + '@inquirer/number@3.0.23(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/number@4.0.12(@types/node@26.1.1)': + '@inquirer/number@4.0.12(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/password@4.0.23(@types/node@26.1.1)': + '@inquirer/password@4.0.23(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/password@5.0.12(@types/node@26.1.1)': + '@inquirer/password@5.0.12(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 2.0.5 - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 - - '@inquirer/prompts@7.10.1(@types/node@26.1.1)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@26.1.1) - '@inquirer/confirm': 5.1.21(@types/node@26.1.1) - '@inquirer/editor': 4.2.23(@types/node@26.1.1) - '@inquirer/expand': 4.0.23(@types/node@26.1.1) - '@inquirer/input': 4.3.1(@types/node@26.1.1) - '@inquirer/number': 3.0.23(@types/node@26.1.1) - '@inquirer/password': 4.0.23(@types/node@26.1.1) - '@inquirer/rawlist': 4.1.11(@types/node@26.1.1) - '@inquirer/search': 3.2.2(@types/node@26.1.1) - '@inquirer/select': 4.4.2(@types/node@26.1.1) + '@types/node': 24.10.15 + + '@inquirer/prompts@7.10.1(@types/node@24.10.15)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@24.10.15) + '@inquirer/confirm': 5.1.21(@types/node@24.10.15) + '@inquirer/editor': 4.2.23(@types/node@24.10.15) + '@inquirer/expand': 4.0.23(@types/node@24.10.15) + '@inquirer/input': 4.3.1(@types/node@24.10.15) + '@inquirer/number': 3.0.23(@types/node@24.10.15) + '@inquirer/password': 4.0.23(@types/node@24.10.15) + '@inquirer/rawlist': 4.1.11(@types/node@24.10.15) + '@inquirer/search': 3.2.2(@types/node@24.10.15) + '@inquirer/select': 4.4.2(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 - - '@inquirer/prompts@8.4.2(@types/node@26.1.1)': - dependencies: - '@inquirer/checkbox': 5.1.4(@types/node@26.1.1) - '@inquirer/confirm': 6.0.12(@types/node@26.1.1) - '@inquirer/editor': 5.1.1(@types/node@26.1.1) - '@inquirer/expand': 5.0.13(@types/node@26.1.1) - '@inquirer/input': 5.0.12(@types/node@26.1.1) - '@inquirer/number': 4.0.12(@types/node@26.1.1) - '@inquirer/password': 5.0.12(@types/node@26.1.1) - '@inquirer/rawlist': 5.2.8(@types/node@26.1.1) - '@inquirer/search': 4.1.8(@types/node@26.1.1) - '@inquirer/select': 5.1.4(@types/node@26.1.1) + '@types/node': 24.10.15 + + '@inquirer/prompts@8.4.2(@types/node@24.10.15)': + dependencies: + '@inquirer/checkbox': 5.1.4(@types/node@24.10.15) + '@inquirer/confirm': 6.0.12(@types/node@24.10.15) + '@inquirer/editor': 5.1.1(@types/node@24.10.15) + '@inquirer/expand': 5.0.13(@types/node@24.10.15) + '@inquirer/input': 5.0.12(@types/node@24.10.15) + '@inquirer/number': 4.0.12(@types/node@24.10.15) + '@inquirer/password': 5.0.12(@types/node@24.10.15) + '@inquirer/rawlist': 5.2.8(@types/node@24.10.15) + '@inquirer/search': 4.1.8(@types/node@24.10.15) + '@inquirer/select': 5.1.4(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/rawlist@4.1.11(@types/node@26.1.1)': + '@inquirer/rawlist@4.1.11(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) + '@inquirer/type': 3.0.10(@types/node@24.10.15) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/rawlist@5.2.8(@types/node@26.1.1)': + '@inquirer/rawlist@5.2.8(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/search@3.2.2(@types/node@26.1.1)': + '@inquirer/search@3.2.2(@types/node@24.10.15)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/type': 3.0.10(@types/node@24.10.15) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/search@4.1.8(@types/node@26.1.1)': + '@inquirer/search@4.1.8(@types/node@24.10.15)': dependencies: - '@inquirer/core': 11.1.9(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/select@4.4.2(@types/node@26.1.1)': + '@inquirer/select@4.4.2(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@26.1.1) + '@inquirer/core': 10.3.2(@types/node@24.10.15) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.1.1) + '@inquirer/type': 3.0.10(@types/node@24.10.15) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/select@5.1.4(@types/node@26.1.1)': + '@inquirer/select@5.1.4(@types/node@24.10.15)': dependencies: '@inquirer/ansi': 2.0.5 - '@inquirer/core': 11.1.9(@types/node@26.1.1) + '@inquirer/core': 11.1.9(@types/node@24.10.15) '@inquirer/figures': 2.0.5 - '@inquirer/type': 4.0.5(@types/node@26.1.1) + '@inquirer/type': 4.0.5(@types/node@24.10.15) optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/type@3.0.10(@types/node@26.1.1)': + '@inquirer/type@3.0.10(@types/node@24.10.15)': optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 - '@inquirer/type@4.0.5(@types/node@26.1.1)': + '@inquirer/type@4.0.5(@types/node@24.10.15)': optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 '@isaacs/cliui@8.0.2': dependencies: @@ -3584,145 +3475,138 @@ snapshots: '@kwsites/promise-deferred@1.1.1': {} - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)': + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@emnapi/core': 1.11.0 - '@emnapi/runtime': 1.11.0 - '@tybys/wasm-util': 0.10.3 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@tybys/wasm-util': 0.10.3 + '@oxc-parser/binding-android-arm-eabi@0.133.0': optional: true - '@oxc-parser/binding-android-arm-eabi@0.137.0': + '@oxc-parser/binding-android-arm64@0.133.0': optional: true - '@oxc-parser/binding-android-arm64@0.137.0': + '@oxc-parser/binding-darwin-arm64@0.133.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.137.0': + '@oxc-parser/binding-darwin-x64@0.133.0': optional: true - '@oxc-parser/binding-darwin-x64@0.137.0': + '@oxc-parser/binding-freebsd-x64@0.133.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.137.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.137.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.137.0': + '@oxc-parser/binding-linux-arm64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.137.0': + '@oxc-parser/binding-linux-arm64-musl@0.133.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.137.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.137.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.137.0': + '@oxc-parser/binding-linux-riscv64-musl@0.133.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.137.0': + '@oxc-parser/binding-linux-s390x-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.137.0': + '@oxc-parser/binding-linux-x64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.137.0': + '@oxc-parser/binding-linux-x64-musl@0.133.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.137.0': + '@oxc-parser/binding-openharmony-arm64@0.133.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.137.0': - optional: true - - '@oxc-parser/binding-wasm32-wasi@0.137.0': + '@oxc-parser/binding-wasm32-wasi@0.133.0': dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.137.0': + '@oxc-parser/binding-win32-arm64-msvc@0.133.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.137.0': + '@oxc-parser/binding-win32-ia32-msvc@0.133.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.137.0': + '@oxc-parser/binding-win32-x64-msvc@0.133.0': optional: true - '@oxc-project/types@0.137.0': {} + '@oxc-project/types@0.133.0': {} - '@oxc-resolver/binding-android-arm-eabi@11.21.3': + '@oxc-resolver/binding-android-arm-eabi@11.20.0': optional: true - '@oxc-resolver/binding-android-arm64@11.21.3': + '@oxc-resolver/binding-android-arm64@11.20.0': optional: true - '@oxc-resolver/binding-darwin-arm64@11.21.3': + '@oxc-resolver/binding-darwin-arm64@11.20.0': optional: true - '@oxc-resolver/binding-darwin-x64@11.21.3': + '@oxc-resolver/binding-darwin-x64@11.20.0': optional: true - '@oxc-resolver/binding-freebsd-x64@11.21.3': + '@oxc-resolver/binding-freebsd-x64@11.20.0': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.3': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.20.0': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.21.3': + '@oxc-resolver/binding-linux-arm-musleabihf@11.20.0': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.21.3': + '@oxc-resolver/binding-linux-arm64-gnu@11.20.0': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.21.3': + '@oxc-resolver/binding-linux-arm64-musl@11.20.0': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.21.3': + '@oxc-resolver/binding-linux-ppc64-gnu@11.20.0': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.21.3': + '@oxc-resolver/binding-linux-riscv64-gnu@11.20.0': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.21.3': + '@oxc-resolver/binding-linux-riscv64-musl@11.20.0': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.21.3': + '@oxc-resolver/binding-linux-s390x-gnu@11.20.0': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.21.3': + '@oxc-resolver/binding-linux-x64-gnu@11.20.0': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.21.3': + '@oxc-resolver/binding-linux-x64-musl@11.20.0': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.21.3': + '@oxc-resolver/binding-openharmony-arm64@11.20.0': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.21.3': + '@oxc-resolver/binding-wasm32-wasi@11.20.0': dependencies: - '@emnapi/core': 1.11.0 - '@emnapi/runtime': 1.11.0 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.21.3': + '@oxc-resolver/binding-win32-arm64-msvc@11.20.0': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.21.3': + '@oxc-resolver/binding-win32-x64-msvc@11.20.0': optional: true '@pkgjs/parseargs@0.11.0': @@ -3811,12 +3695,6 @@ snapshots: dependencies: '@simple-git/args-pathspec': 1.0.3 - '@simple-libs/child-process-utils@2.0.0': - dependencies: - '@simple-libs/stream-utils': 2.0.0 - - '@simple-libs/stream-utils@2.0.0': {} - '@sindresorhus/merge-streams@4.0.0': {} '@stryker-mutator/api@9.6.1': @@ -3826,9 +3704,9 @@ snapshots: tslib: 2.8.1 typed-inject: 5.0.0 - '@stryker-mutator/core@9.6.1(@types/node@26.1.1)': + '@stryker-mutator/core@9.6.1(@types/node@24.10.15)': dependencies: - '@inquirer/prompts': 8.4.2(@types/node@26.1.1) + '@inquirer/prompts': 8.4.2(@types/node@24.10.15) '@stryker-mutator/api': 9.6.1 '@stryker-mutator/instrumenter': 9.6.1 '@stryker-mutator/util': 9.6.1 @@ -3877,16 +3755,16 @@ snapshots: '@stryker-mutator/util@9.6.1': {} - '@stryker-mutator/vitest-runner@9.6.1(@stryker-mutator/core@9.6.1(@types/node@26.1.1))(vitest@3.2.6(@types/node@26.1.1))': + '@stryker-mutator/vitest-runner@9.6.1(@stryker-mutator/core@9.6.1(@types/node@24.10.15))(vitest@3.2.6(@types/node@24.10.15))': dependencies: '@stryker-mutator/api': 9.6.1 - '@stryker-mutator/core': 9.6.1(@types/node@26.1.1) + '@stryker-mutator/core': 9.6.1(@types/node@24.10.15) '@stryker-mutator/util': 9.6.1 semver: 7.7.4 tslib: 2.8.1 - vitest: 3.2.6(@types/node@26.1.1) + vitest: 3.2.6(@types/node@24.10.15) - '@tybys/wasm-util@0.10.3': + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 optional: true @@ -3898,77 +3776,17 @@ snapshots: '@types/conventional-commits-parser@5.0.2': dependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} - '@types/node@26.1.1': + '@types/node@24.10.15': dependencies: - undici-types: 8.3.0 - - '@typescript/typescript-aix-ppc64@7.0.2': - optional: true - - '@typescript/typescript-darwin-arm64@7.0.2': - optional: true - - '@typescript/typescript-darwin-x64@7.0.2': - optional: true - - '@typescript/typescript-freebsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-freebsd-x64@7.0.2': - optional: true - - '@typescript/typescript-linux-arm64@7.0.2': - optional: true - - '@typescript/typescript-linux-arm@7.0.2': - optional: true - - '@typescript/typescript-linux-loong64@7.0.2': - optional: true - - '@typescript/typescript-linux-mips64el@7.0.2': - optional: true - - '@typescript/typescript-linux-ppc64@7.0.2': - optional: true - - '@typescript/typescript-linux-riscv64@7.0.2': - optional: true - - '@typescript/typescript-linux-s390x@7.0.2': - optional: true - - '@typescript/typescript-linux-x64@7.0.2': - optional: true - - '@typescript/typescript-netbsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-netbsd-x64@7.0.2': - optional: true - - '@typescript/typescript-openbsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-openbsd-x64@7.0.2': - optional: true + undici-types: 7.16.0 - '@typescript/typescript-sunos-x64@7.0.2': - optional: true - - '@typescript/typescript-win32-arm64@7.0.2': - optional: true - - '@typescript/typescript-win32-x64@7.0.2': - optional: true - - '@vitest/coverage-v8@3.2.6(vitest@3.2.6(@types/node@26.1.1))': + '@vitest/coverage-v8@3.2.6(vitest@3.2.6(@types/node@24.10.15))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -3983,7 +3801,7 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.2 tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/node@26.1.1) + vitest: 3.2.6(@types/node@24.10.15) transitivePeerDependencies: - supports-color @@ -3995,13 +3813,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.6(vite@5.4.21(@types/node@26.1.1))': + '@vitest/mocker@3.2.6(vite@5.4.21(@types/node@24.10.15))': dependencies: '@vitest/spy': 3.2.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 5.4.21(@types/node@26.1.1) + vite: 5.4.21(@types/node@24.10.15) '@vitest/pretty-format@3.2.6': dependencies: @@ -4029,6 +3847,11 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + acorn@8.16.0: {} ajv-formats@3.0.1(ajv@8.20.0): @@ -4065,8 +3888,6 @@ snapshots: argparse@2.0.1: {} - argue-cli@3.1.0: {} - array-ify@1.0.0: {} assertion-error@2.0.1: {} @@ -4140,11 +3961,11 @@ snapshots: cli-width@4.1.0: {} - cliui@9.0.1: + cliui@8.0.1: dependencies: - string-width: 7.2.0 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 color-convert@2.0.1: dependencies: @@ -4152,9 +3973,9 @@ snapshots: color-name@1.1.4: {} - commander@14.0.3: {} + commander@12.1.0: {} - commander@15.0.0: {} + commander@14.0.3: {} commander@4.1.1: {} @@ -4167,40 +3988,56 @@ snapshots: consola@3.4.2: {} - conventional-changelog-angular@9.2.1: - dependencies: - '@conventional-changelog/template': 1.2.1 - - conventional-changelog-conventionalcommits@10.2.1: + conventional-changelog-angular@7.0.0: dependencies: - '@conventional-changelog/template': 1.2.1 + compare-func: 2.0.0 conventional-changelog-conventionalcommits@7.0.2: dependencies: compare-func: 2.0.0 - conventional-commits-parser@7.1.0: + conventional-commits-parser@5.0.0: dependencies: - '@simple-libs/stream-utils': 2.0.0 - argue-cli: 3.1.0 + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 convert-source-map@2.0.0: {} - cosmiconfig-typescript-loader@6.2.0(@types/node@26.1.1)(cosmiconfig@9.0.1(typescript@7.0.2))(typescript@7.0.2): + cosmiconfig-typescript-loader@6.2.0(@types/node@24.10.15)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): dependencies: - '@types/node': 26.1.1 - cosmiconfig: 9.0.1(typescript@7.0.2) - jiti: 2.7.0 - typescript: 7.0.2 + '@types/node': 24.10.15 + cosmiconfig: 9.0.1(typescript@5.9.3) + jiti: 2.6.1 + typescript: 5.9.3 - cosmiconfig@9.0.1(typescript@7.0.2): + cosmiconfig@9.0.1(typescript@5.9.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 js-yaml: 4.1.1 parse-json: 5.2.0 optionalDependencies: - typescript: 7.0.2 + typescript: 5.9.3 + + cpd-darwin-arm64@5.0.7: + optional: true + + cpd-darwin-x64@5.0.7: + optional: true + + cpd-linux-arm64-gnu@5.0.7: + optional: true + + cpd-linux-x64-gnu@5.0.7: + optional: true + + cpd-linux-x64-musl@5.0.7: + optional: true + + cpd-windows-x64-msvc@5.0.7: + optional: true cross-spawn@7.0.6: dependencies: @@ -4208,6 +4045,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + dargs@8.1.0: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -4257,8 +4096,6 @@ snapshots: dependencies: es-errors: 1.3.0 - es-toolkit@1.50.0: {} - esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -4337,9 +4174,9 @@ snapshots: expect-type@1.3.0: {} - fast-check@4.9.0: + fast-check@4.7.0: dependencies: - pure-rand: 8.4.2 + pure-rand: 8.4.0 fast-deep-equal@3.1.3: {} @@ -4359,14 +4196,20 @@ snapshots: dependencies: walk-up-path: 4.0.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.4 figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + fix-dts-default-cjs-exports@1.0.1: dependencies: magic-string: 0.30.21 @@ -4391,8 +4234,6 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.6.0: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4420,6 +4261,12 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + glob@10.5.0: dependencies: foreground-child: 3.3.1 @@ -4429,9 +4276,9 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - global-directory@5.0.0: + global-directory@4.0.1: dependencies: - ini: 6.0.0 + ini: 4.1.1 gopd@1.2.0: {} @@ -4456,9 +4303,11 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-meta-resolve@4.2.0: {} + inherits@2.0.4: {} - ini@6.0.0: {} + ini@4.1.1: {} is-arrayish@0.2.1: {} @@ -4470,6 +4319,10 @@ snapshots: is-stream@4.0.1: {} + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + is-unicode-supported@2.1.0: {} isexe@2.0.0: {} @@ -4501,6 +4354,8 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jiti@2.6.1: {} + jiti@2.7.0: {} joycon@3.1.1: {} @@ -4517,32 +4372,14 @@ snapshots: dependencies: argparse: 2.0.1 - jscpd-darwin-arm64@5.0.12: - optional: true - - jscpd-darwin-x64@5.0.12: - optional: true - - jscpd-linux-arm64-gnu@5.0.12: - optional: true - - jscpd-linux-x64-gnu@5.0.12: - optional: true - - jscpd-linux-x64-musl@5.0.12: - optional: true - - jscpd-windows-x64-msvc@5.0.12: - optional: true - - jscpd@5.0.12: + jscpd@5.0.7: optionalDependencies: - jscpd-darwin-arm64: 5.0.12 - jscpd-darwin-x64: 5.0.12 - jscpd-linux-arm64-gnu: 5.0.12 - jscpd-linux-x64-gnu: 5.0.12 - jscpd-linux-x64-musl: 5.0.12 - jscpd-windows-x64-msvc: 5.0.12 + cpd-darwin-arm64: 5.0.7 + cpd-darwin-x64: 5.0.7 + cpd-linux-arm64-gnu: 5.0.7 + cpd-linux-x64-gnu: 5.0.7 + cpd-linux-x64-musl: 5.0.7 + cpd-windows-x64-msvc: 5.0.7 jsesc@3.1.0: {} @@ -4554,21 +4391,23 @@ snapshots: json5@2.2.3: {} - knip@6.27.0: + jsonparse@1.3.1: {} + + knip@6.16.1: dependencies: - fdir: 6.5.0(picomatch@4.0.5) + fdir: 6.5.0(picomatch@4.0.4) formatly: 0.3.0 get-tsconfig: 4.14.0 jiti: 2.7.0 - oxc-parser: 0.137.0 - oxc-resolver: 11.21.3 - picomatch: 4.0.5 + oxc-parser: 0.133.0 + oxc-resolver: 11.20.0 + picomatch: 4.0.4 smol-toml: 1.6.1 strip-json-comments: 5.0.3 tinyglobby: 0.2.17 - unbash: 4.0.3 + unbash: 3.0.0 yaml: 2.9.0 - zod: 4.4.3 + zod: 4.3.6 lefthook-darwin-arm64@1.13.6: optional: true @@ -4619,8 +4458,30 @@ snapshots: load-tsconfig@0.2.5: {} + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash.camelcase@4.3.0: {} + lodash.groupby@4.6.0: {} + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + loupe@3.2.1: {} lru-cache@10.4.3: {} @@ -4645,6 +4506,8 @@ snapshots: math-intrinsics@1.1.0: {} + meow@12.1.1: {} + minimalistic-assert@1.0.1: {} minimatch@10.2.4: @@ -4655,6 +4518,8 @@ snapshots: dependencies: brace-expansion: 2.1.1 + minimist@1.2.8: {} + minipass@7.1.3: {} mlly@1.8.0: @@ -4668,7 +4533,7 @@ snapshots: mutation-server-protocol@0.4.1: dependencies: - zod: 4.4.3 + zod: 4.3.6 mutation-testing-elements@3.7.3: {} @@ -4701,52 +4566,60 @@ snapshots: object-inspect@1.13.4: {} - oxc-parser@0.137.0: + oxc-parser@0.133.0: dependencies: - '@oxc-project/types': 0.137.0 + '@oxc-project/types': 0.133.0 optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.137.0 - '@oxc-parser/binding-android-arm64': 0.137.0 - '@oxc-parser/binding-darwin-arm64': 0.137.0 - '@oxc-parser/binding-darwin-x64': 0.137.0 - '@oxc-parser/binding-freebsd-x64': 0.137.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.137.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.137.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.137.0 - '@oxc-parser/binding-linux-arm64-musl': 0.137.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.137.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.137.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.137.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.137.0 - '@oxc-parser/binding-linux-x64-gnu': 0.137.0 - '@oxc-parser/binding-linux-x64-musl': 0.137.0 - '@oxc-parser/binding-openharmony-arm64': 0.137.0 - '@oxc-parser/binding-wasm32-wasi': 0.137.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.137.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.137.0 - '@oxc-parser/binding-win32-x64-msvc': 0.137.0 - - oxc-resolver@11.21.3: + '@oxc-parser/binding-android-arm-eabi': 0.133.0 + '@oxc-parser/binding-android-arm64': 0.133.0 + '@oxc-parser/binding-darwin-arm64': 0.133.0 + '@oxc-parser/binding-darwin-x64': 0.133.0 + '@oxc-parser/binding-freebsd-x64': 0.133.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.133.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.133.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.133.0 + '@oxc-parser/binding-linux-arm64-musl': 0.133.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.133.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.133.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.133.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.133.0 + '@oxc-parser/binding-linux-x64-gnu': 0.133.0 + '@oxc-parser/binding-linux-x64-musl': 0.133.0 + '@oxc-parser/binding-openharmony-arm64': 0.133.0 + '@oxc-parser/binding-wasm32-wasi': 0.133.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.133.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.133.0 + '@oxc-parser/binding-win32-x64-msvc': 0.133.0 + + oxc-resolver@11.20.0: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.21.3 - '@oxc-resolver/binding-android-arm64': 11.21.3 - '@oxc-resolver/binding-darwin-arm64': 11.21.3 - '@oxc-resolver/binding-darwin-x64': 11.21.3 - '@oxc-resolver/binding-freebsd-x64': 11.21.3 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.21.3 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.21.3 - '@oxc-resolver/binding-linux-arm64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-arm64-musl': 11.21.3 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-riscv64-musl': 11.21.3 - '@oxc-resolver/binding-linux-s390x-gnu': 11.21.3 - '@oxc-resolver/binding-linux-x64-gnu': 11.21.3 - '@oxc-resolver/binding-linux-x64-musl': 11.21.3 - '@oxc-resolver/binding-openharmony-arm64': 11.21.3 - '@oxc-resolver/binding-wasm32-wasi': 11.21.3 - '@oxc-resolver/binding-win32-arm64-msvc': 11.21.3 - '@oxc-resolver/binding-win32-x64-msvc': 11.21.3 + '@oxc-resolver/binding-android-arm-eabi': 11.20.0 + '@oxc-resolver/binding-android-arm64': 11.20.0 + '@oxc-resolver/binding-darwin-arm64': 11.20.0 + '@oxc-resolver/binding-darwin-x64': 11.20.0 + '@oxc-resolver/binding-freebsd-x64': 11.20.0 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.20.0 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.20.0 + '@oxc-resolver/binding-linux-arm64-gnu': 11.20.0 + '@oxc-resolver/binding-linux-arm64-musl': 11.20.0 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.20.0 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.20.0 + '@oxc-resolver/binding-linux-riscv64-musl': 11.20.0 + '@oxc-resolver/binding-linux-s390x-gnu': 11.20.0 + '@oxc-resolver/binding-linux-x64-gnu': 11.20.0 + '@oxc-resolver/binding-linux-x64-musl': 11.20.0 + '@oxc-resolver/binding-openharmony-arm64': 11.20.0 + '@oxc-resolver/binding-wasm32-wasi': 11.20.0 + '@oxc-resolver/binding-win32-arm64-msvc': 11.20.0 + '@oxc-resolver/binding-win32-x64-msvc': 11.20.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.2 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 package-json-from-dist@1.0.1: {} @@ -4763,6 +4636,8 @@ snapshots: parse-ms@4.0.0: {} + path-exists@5.0.0: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -4780,8 +4655,6 @@ snapshots: picomatch@4.0.4: {} - picomatch@4.0.5: {} - pirates@4.0.7: {} pkg-types@1.3.1: @@ -4810,7 +4683,7 @@ snapshots: progress@2.0.3: {} - pure-rand@8.4.2: {} + pure-rand@8.4.0: {} qs@6.15.2: dependencies: @@ -4818,6 +4691,8 @@ snapshots: readdirp@4.1.2: {} + require-directory@2.1.1: {} + require-from-string@2.0.2: {} resolve-from@4.0.0: {} @@ -4921,6 +4796,8 @@ snapshots: source-map@0.7.6: {} + split2@4.2.0: {} + stackback@0.0.2: {} std-env@3.10.0: {} @@ -4937,12 +4814,6 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.2.0 - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -4979,6 +4850,8 @@ snapshots: glob: 10.5.0 minimatch: 10.2.4 + text-extensions@2.4.0: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -4987,6 +4860,8 @@ snapshots: dependencies: any-promise: 1.3.0 + through@2.3.8: {} + tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -4995,13 +4870,13 @@ snapshots: tinyglobby@0.2.15: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 tinypool@1.1.1: {} @@ -5015,7 +4890,7 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(jiti@2.7.0)(postcss@8.5.15)(typescript@7.0.2)(yaml@2.9.0): + tsup@8.5.1(jiti@2.7.0)(postcss@8.5.15)(typescript@5.9.3)(yaml@2.9.0): dependencies: bundle-require: 5.1.0(esbuild@0.27.3) cac: 6.7.14 @@ -5036,7 +4911,7 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: postcss: 8.5.15 - typescript: 7.0.2 + typescript: 5.9.3 transitivePeerDependencies: - jiti - supports-color @@ -5055,36 +4930,17 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.8 - typescript@7.0.2: - optionalDependencies: - '@typescript/typescript-aix-ppc64': 7.0.2 - '@typescript/typescript-darwin-arm64': 7.0.2 - '@typescript/typescript-darwin-x64': 7.0.2 - '@typescript/typescript-freebsd-arm64': 7.0.2 - '@typescript/typescript-freebsd-x64': 7.0.2 - '@typescript/typescript-linux-arm': 7.0.2 - '@typescript/typescript-linux-arm64': 7.0.2 - '@typescript/typescript-linux-loong64': 7.0.2 - '@typescript/typescript-linux-mips64el': 7.0.2 - '@typescript/typescript-linux-ppc64': 7.0.2 - '@typescript/typescript-linux-riscv64': 7.0.2 - '@typescript/typescript-linux-s390x': 7.0.2 - '@typescript/typescript-linux-x64': 7.0.2 - '@typescript/typescript-netbsd-arm64': 7.0.2 - '@typescript/typescript-netbsd-x64': 7.0.2 - '@typescript/typescript-openbsd-arm64': 7.0.2 - '@typescript/typescript-openbsd-x64': 7.0.2 - '@typescript/typescript-sunos-x64': 7.0.2 - '@typescript/typescript-win32-arm64': 7.0.2 - '@typescript/typescript-win32-x64': 7.0.2 + typescript@5.9.3: {} ufo@1.6.3: {} - unbash@4.0.3: {} + unbash@3.0.0: {} underscore@1.13.8: {} - undici-types@8.3.0: {} + undici-types@7.16.0: {} + + unicorn-magic@0.1.0: {} unicorn-magic@0.3.0: {} @@ -5094,13 +4950,13 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - vite-node@3.2.4(@types/node@26.1.1): + vite-node@3.2.4(@types/node@24.10.15): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 5.4.21(@types/node@26.1.1) + vite: 5.4.21(@types/node@24.10.15) transitivePeerDependencies: - '@types/node' - less @@ -5112,20 +4968,20 @@ snapshots: - supports-color - terser - vite@5.4.21(@types/node@26.1.1): + vite@5.4.21(@types/node@24.10.15): dependencies: esbuild: 0.21.5 postcss: 8.5.15 rollup: 4.59.0 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 fsevents: 2.3.3 - vitest@3.2.6(@types/node@26.1.1): + vitest@3.2.6(@types/node@24.10.15): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.6 - '@vitest/mocker': 3.2.6(vite@5.4.21(@types/node@26.1.1)) + '@vitest/mocker': 3.2.6(vite@5.4.21(@types/node@24.10.15)) '@vitest/pretty-format': 3.2.6 '@vitest/runner': 3.2.6 '@vitest/snapshot': 3.2.6 @@ -5143,11 +4999,11 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 5.4.21(@types/node@26.1.1) - vite-node: 3.2.4(@types/node@26.1.1) + vite: 5.4.21(@types/node@24.10.15) + vite-node: 3.2.4(@types/node@24.10.15) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 26.1.1 + '@types/node': 24.10.15 transitivePeerDependencies: - less - lightningcss @@ -5190,31 +5046,28 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.2.0 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - y18n@5.0.8: {} yallist@3.1.1: {} yaml@2.9.0: {} - yargs-parser@22.0.0: {} + yargs-parser@21.1.1: {} - yargs@18.0.0: + yargs@17.7.2: dependencies: - cliui: 9.0.1 + cliui: 8.0.1 escalade: 3.2.0 get-caller-file: 2.0.5 - string-width: 7.2.0 + require-directory: 2.1.1 + string-width: 4.2.3 y18n: 5.0.8 - yargs-parser: 22.0.0 + yargs-parser: 21.1.1 + + yocto-queue@1.2.2: {} yoctocolors-cjs@2.1.3: {} yoctocolors@2.1.2: {} - zod@4.4.3: {} + zod@4.3.6: {} diff --git a/cli/src/application/commands/framework.ts b/cli/src/application/commands/framework.ts index 2e1f45d6a..70fa94da8 100644 --- a/cli/src/application/commands/framework.ts +++ b/cli/src/application/commands/framework.ts @@ -1,14 +1,15 @@ import { resolve } from "node:path"; import type { Command } from "commander"; -import { - type FrameworkBuildMode, - type FrameworkBuildTarget, - SUPPORTED_BUILD_TARGETS, +import type { + FrameworkBuildMode, + FrameworkBuildTarget, } from "../../domain/models/framework-build.js"; import { createDeps, createFrameworkBuildUseCase } from "../../infrastructure/deps.js"; import { ErrorHandler } from "../error-handler.js"; import { parseGlobalOptions } from "./global-options.js"; +const SUPPORTED_TARGETS: readonly string[] = ["claude", "cursor", "copilot", "codex", "opencode"]; + export function registerFrameworkCommand(program: Command): void { const framework = program .command("framework") @@ -35,9 +36,9 @@ export function registerFrameworkCommand(program: Command): void { const { verbose, output, projectRoot } = parseGlobalOptions(program); const errorHandler = new ErrorHandler(output); - if (!(SUPPORTED_BUILD_TARGETS as readonly string[]).includes(cmdOptions.target)) { + if (!SUPPORTED_TARGETS.includes(cmdOptions.target)) { output.error( - `Unsupported target '${cmdOptions.target}'. Supported targets: ${SUPPORTED_BUILD_TARGETS.join(", ")}.` + `Unsupported target '${cmdOptions.target}'. Supported targets: ${SUPPORTED_TARGETS.join(", ")}.` ); process.exit(1); } diff --git a/cli/src/application/use-cases/framework/strategies/marketplace-strategy-helpers.ts b/cli/src/application/use-cases/framework/strategies/marketplace-strategy-helpers.ts index 45234b040..6cbadfc21 100644 --- a/cli/src/application/use-cases/framework/strategies/marketplace-strategy-helpers.ts +++ b/cli/src/application/use-cases/framework/strategies/marketplace-strategy-helpers.ts @@ -166,7 +166,7 @@ export function buildClaudeStyleMarketplace( return obj; } -export function buildClaudeStyleCatalogEntry( +export function buildClaudeStyleMarketplaceEntry( name: string, description: string, version: string, diff --git a/cli/src/application/use-cases/framework/strategies/tool-contracts.ts b/cli/src/application/use-cases/framework/strategies/tool-contracts.ts index 3f1f09e84..42e1eae39 100644 --- a/cli/src/application/use-cases/framework/strategies/tool-contracts.ts +++ b/cli/src/application/use-cases/framework/strategies/tool-contracts.ts @@ -61,8 +61,8 @@ import { mergeCodexConfigToml } from "../../../../domain/tools/ai/codex.js"; import { transformMcpToOpencode } from "../../../../domain/tools/ai/opencode.js"; import type { PluginPresence, ToolBuildContract } from "../../../../domain/tools/build-contract.js"; import { - buildClaudeStyleCatalogEntry, buildClaudeStyleMarketplace, + buildClaudeStyleMarketplaceEntry, buildCodexMarketplace, buildCodexMarketplaceEntry, resolveDescription, @@ -106,7 +106,7 @@ async function buildClaudeStyleEntry( const args = [fs, name, srcEntry, outDir, manifestRelative] as const; const version = await resolveVersion(...args); const description = await resolveDescription(...args); - return buildClaudeStyleCatalogEntry( + return buildClaudeStyleMarketplaceEntry( name, description, version, diff --git a/cli/src/application/use-cases/global/restore-all-use-case.ts b/cli/src/application/use-cases/global/restore-all-use-case.ts index 58f4107c2..b48b607db 100644 --- a/cli/src/application/use-cases/global/restore-all-use-case.ts +++ b/cli/src/application/use-cases/global/restore-all-use-case.ts @@ -1,9 +1,21 @@ import { DOCS_DIR } from "../../../domain/models/paths.js"; +import type { AiToolId } from "../../../domain/models/tool-ids.js"; +import type { AssetProvider } from "../../../domain/ports/asset-provider.js"; +import type { FileMerger } from "../../../domain/ports/file-merger.js"; +import type { FileReader } from "../../../domain/ports/file-reader.js"; +import type { FileWriter } from "../../../domain/ports/file-writer.js"; +import type { Hasher } from "../../../domain/ports/hasher.js"; +import type { Logger } from "../../../domain/ports/logger.js"; import type { ManifestRepository } from "../../../domain/ports/manifest-repository.js"; +import type { Platform } from "../../../domain/ports/platform.js"; +import type { PluginDistributionReader } from "../../../domain/ports/plugin-distribution-reader.js"; +import type { PluginFetcher } from "../../../domain/ports/plugin-fetcher.js"; import type { Prompter } from "../../../domain/ports/prompter.js"; import { NoManifestError } from "../../errors.js"; -import type { RestoreUseCase } from "../restore/restore-use-case.js"; -import type { StatusUseCase } from "../status-use-case.js"; +import { RestorePluginUseCase } from "../restore/restore-plugin-use-case.js"; +import { RestoreUseCase } from "../restore/restore-use-case.js"; +import type { BuiltMaterializationDeps } from "../shared/apply-plugin-files-use-case.js"; +import { StatusUseCase } from "../status-use-case.js"; import type { GlobalExecutionError } from "./update-all-use-case.js"; export interface RestoreAllResult { @@ -15,10 +27,16 @@ export interface RestoreAllResult { export class RestoreAllUseCase { constructor( + private readonly fs: FileReader & FileWriter & FileMerger, private readonly manifestRepo: ManifestRepository, + private readonly hasher: Hasher, + private readonly logger: Logger, + private readonly platform: Platform, private readonly prompter: Prompter, - private readonly statusUseCase: StatusUseCase, - private readonly restoreUseCase: RestoreUseCase + private readonly pluginFetcher: PluginFetcher, + private readonly pluginDistributionReader: PluginDistributionReader, + private readonly assetProvider?: AssetProvider, + private readonly builtDeps?: BuiltMaterializationDeps ) {} async execute(projectRoot: string, interactive: boolean): Promise { @@ -36,11 +54,12 @@ export class RestoreAllUseCase { manifest, errors ); + const pluginNames = await this.restoreAllPlugins(projectRoot, manifest, errors); return { totalRestored: restoreResult.totalRestored, totalKept: restoreResult.totalKept, - pluginNamesRestored: restoreResult.restoredPluginNames, + pluginNamesRestored: pluginNames, errors, }; } @@ -55,7 +74,8 @@ export class RestoreAllUseCase { } private async promptForFiles(projectRoot: string): Promise { - const report = await this.statusUseCase.execute({ projectRoot }); + const statusUseCase = new StatusUseCase(this.fs, this.manifestRepo, this.hasher); + const report = await statusUseCase.execute({ projectRoot }); const driftedFiles = report.tools.flatMap((t) => t.drifted .filter((d) => d.status === "modified" || d.status === "deleted") @@ -76,10 +96,22 @@ export class RestoreAllUseCase { interactive: boolean, manifest: Awaited>, errors: GlobalExecutionError[] - ): Promise<{ totalRestored: number; totalKept: number; restoredPluginNames: string[] }> { + ): Promise<{ totalRestored: number; totalKept: number }> { try { - if (manifest === null) return { totalRestored: 0, totalKept: 0, restoredPluginNames: [] }; - const result = await this.restoreUseCase.execute({ + const restoreUseCase = new RestoreUseCase( + this.fs, + this.manifestRepo, + this.hasher, + this.logger, + this.platform, + this.prompter, + this.pluginFetcher, + this.pluginDistributionReader, + this.assetProvider, + this.builtDeps + ); + if (manifest === null) return { totalRestored: 0, totalKept: 0 }; + const result = await restoreUseCase.execute({ version, docsDir: DOCS_DIR, projectRoot, @@ -88,17 +120,54 @@ export class RestoreAllUseCase { interactive, manifest, }); - return { - totalRestored: result.totalRestored, - totalKept: result.totalKept, - restoredPluginNames: result.restoredPluginNames, - }; + return { totalRestored: result.totalRestored, totalKept: result.totalKept }; } catch (err) { errors.push({ scope: "config-restore", message: err instanceof Error ? err.message : String(err), }); - return { totalRestored: 0, totalKept: 0, restoredPluginNames: [] }; + return { totalRestored: 0, totalKept: 0 }; } } + + private async restoreAllPlugins( + projectRoot: string, + manifest: NonNullable>>, + errors: GlobalExecutionError[] + ): Promise { + const restored: string[] = []; + const restorePluginUseCase = new RestorePluginUseCase( + this.fs, + this.manifestRepo, + this.pluginFetcher, + this.pluginDistributionReader, + this.hasher, + this.builtDeps + ); + const allPluginNames = this.collectAllPluginNames(manifest); + for (const name of allPluginNames) { + try { + await restorePluginUseCase.execute({ pluginName: name, projectRoot }); + restored.push(name); + } catch (err) { + errors.push({ + scope: `plugin:${name}`, + message: err instanceof Error ? err.message : String(err), + }); + } + } + return restored; + } + + private collectAllPluginNames( + manifest: NonNullable>> + ): string[] { + const names = new Set(); + for (const toolId of manifest.getInstalledToolIds()) { + for (const plugin of manifest.getPlugins(toolId as AiToolId)) { + names.add(plugin.name); + } + } + return [...names]; + } } diff --git a/cli/src/application/use-cases/global/status-all-use-case.ts b/cli/src/application/use-cases/global/status-all-use-case.ts index d8ab9096a..c429f5207 100644 --- a/cli/src/application/use-cases/global/status-all-use-case.ts +++ b/cli/src/application/use-cases/global/status-all-use-case.ts @@ -1,4 +1,7 @@ -import type { StatusUseCase } from "../status-use-case.js"; +import type { FileReader } from "../../../domain/ports/file-reader.js"; +import type { Hasher } from "../../../domain/ports/hasher.js"; +import type { ManifestRepository } from "../../../domain/ports/manifest-repository.js"; +import { StatusUseCase } from "../status-use-case.js"; import type { GlobalExecutionError } from "./update-all-use-case.js"; type StatusReport = Awaited>; @@ -11,12 +14,17 @@ export interface StatusAllResult { } export class StatusAllUseCase { - constructor(private readonly statusUseCase: StatusUseCase) {} + constructor( + private readonly fs: FileReader, + private readonly manifestRepo: ManifestRepository, + private readonly hasher: Hasher + ) {} async execute(projectRoot: string): Promise { const errors: GlobalExecutionError[] = []; + const useCase = new StatusUseCase(this.fs, this.manifestRepo, this.hasher); const [aiTools, ideTools, plugins] = await this.collectCategoryReports( - this.statusUseCase, + useCase, projectRoot, errors ); diff --git a/cli/src/application/use-cases/global/update-all-use-case.ts b/cli/src/application/use-cases/global/update-all-use-case.ts index 5ff4f1ca6..50d466fe3 100644 --- a/cli/src/application/use-cases/global/update-all-use-case.ts +++ b/cli/src/application/use-cases/global/update-all-use-case.ts @@ -1,14 +1,21 @@ import { Manifest } from "../../../domain/models/manifest.js"; +import type { FileReader } from "../../../domain/ports/file-reader.js"; import type { ManifestRepository } from "../../../domain/ports/manifest-repository.js"; import type { VersionReader } from "../../../domain/ports/version-reader.js"; import type { ToolId } from "../../../domain/tools/registry.js"; +import type { InstallIdeConfigUseCase } from "../install/install-ide-config-use-case.js"; +import type { InstallRuntimeConfigUseCase } from "../install/install-runtime-config-use-case.js"; import type { MarketplaceRefreshUseCase } from "../marketplace/marketplace-refresh-use-case.js"; import type { PluginUpdateUseCase } from "../plugin/plugin-update-use-case.js"; -import { BulkConflictState } from "../shared/resolve-update-decision-use-case.js"; -import type { - GlobalExecutionError, +import { + BulkConflictState, + type ResolveUpdateDecisionUseCase, +} from "../shared/resolve-update-decision-use-case.js"; +import { + type GlobalExecutionError, UpdateOneToolUseCase, } from "../shared/update-one-tool-use-case.js"; +import type { SyncConflictResolverUseCase } from "../sync/sync-conflict-resolver-use-case.js"; export type { GlobalExecutionError }; @@ -26,13 +33,27 @@ export interface UpdateAllResult { } export class UpdateAllUseCase { + private readonly updateOneToolUseCase: UpdateOneToolUseCase; + constructor( private readonly manifestRepo: ManifestRepository, private readonly versionReader: VersionReader, + installRuntimeConfigUseCase: InstallRuntimeConfigUseCase, + installIdeConfigUseCase: InstallIdeConfigUseCase, private readonly pluginUpdateUseCase: PluginUpdateUseCase, private readonly marketplaceRefreshUseCase: MarketplaceRefreshUseCase, - private readonly updateOneToolUseCase: UpdateOneToolUseCase - ) {} + conflictResolver: SyncConflictResolverUseCase, + decisionUseCase: ResolveUpdateDecisionUseCase, + fs: FileReader + ) { + this.updateOneToolUseCase = new UpdateOneToolUseCase( + installRuntimeConfigUseCase, + installIdeConfigUseCase, + conflictResolver, + decisionUseCase, + fs + ); + } async execute(input: UpdateAllInput): Promise { const { projectRoot, userForce, interactive } = input; diff --git a/cli/src/application/use-cases/plugin/plugin-add-use-case.ts b/cli/src/application/use-cases/plugin/plugin-add-use-case.ts index 03fefed4d..cf9a9b4c7 100644 --- a/cli/src/application/use-cases/plugin/plugin-add-use-case.ts +++ b/cli/src/application/use-cases/plugin/plugin-add-use-case.ts @@ -9,10 +9,10 @@ import { import type { Manifest } from "../../../domain/models/manifest.js"; import { DOCS_DIR, PLUGIN_CACHE_SUBDIR } from "../../../domain/models/paths.js"; import { Plugin } from "../../../domain/models/plugin.js"; -import { PluginContentTranslator } from "../../../domain/models/plugin-content-translator.js"; import type { PluginDistribution } from "../../../domain/models/plugin-distribution.js"; import type { PluginSource } from "../../../domain/models/plugin-source.js"; import type { ReadonlySkipList } from "../../../domain/models/plugin-translation-skip.js"; +import { PluginTranslator } from "../../../domain/models/plugin-translator.js"; import type { AiToolId } from "../../../domain/models/tool-ids.js"; import type { FileReader } from "../../../domain/ports/file-reader.js"; import type { FileWriter } from "../../../domain/ports/file-writer.js"; @@ -273,7 +273,7 @@ export class PluginAddUseCase { previousMcpEntries ); } - const { files, componentPaths, skipped } = new PluginContentTranslator( + const { files, componentPaths, skipped } = new PluginTranslator( this.hasher ).translateWithComponentPaths(dist, toolConfig, docsDir); if (files.length === 0) return { skipped }; diff --git a/cli/src/application/use-cases/plugin/plugin-update-use-case.ts b/cli/src/application/use-cases/plugin/plugin-update-use-case.ts index 74fda8519..b435e0bb9 100644 --- a/cli/src/application/use-cases/plugin/plugin-update-use-case.ts +++ b/cli/src/application/use-cases/plugin/plugin-update-use-case.ts @@ -4,8 +4,8 @@ import type { PluginsCapability } from "../../../domain/capabilities/plugins-cap import type { Manifest } from "../../../domain/models/manifest.js"; import { DOCS_DIR, PLUGIN_CACHE_SUBDIR } from "../../../domain/models/paths.js"; import { Plugin } from "../../../domain/models/plugin.js"; -import { PluginContentTranslator } from "../../../domain/models/plugin-content-translator.js"; import type { PluginDistribution } from "../../../domain/models/plugin-distribution.js"; +import { PluginTranslator } from "../../../domain/models/plugin-translator.js"; import { compareSemver } from "../../../domain/models/semver.js"; import type { AiToolId } from "../../../domain/models/tool-ids.js"; import type { FileReader } from "../../../domain/ports/file-reader.js"; @@ -127,7 +127,7 @@ export class PluginUpdateUseCase { ); return; } - const { files: newFiles, componentPaths } = new PluginContentTranslator( + const { files: newFiles, componentPaths } = new PluginTranslator( this.hasher ).translateWithComponentPaths(dist, toolConfig, docsDir); const isLocalMarketplace = plugin.source.kind === "local" && plugin.marketplace !== undefined; diff --git a/cli/src/application/use-cases/plugin/translator/mode-b-flat-materialization-translator.ts b/cli/src/application/use-cases/plugin/translator/mode-b-flat-materialization-translator.ts index 1791a96e1..b3abb9886 100644 --- a/cli/src/application/use-cases/plugin/translator/mode-b-flat-materialization-translator.ts +++ b/cli/src/application/use-cases/plugin/translator/mode-b-flat-materialization-translator.ts @@ -6,13 +6,13 @@ import { mergeOpencodeMcp } from "../../../../domain/formats/opencode-mcp-merge. import type { InstallationFile } from "../../../../domain/models/file.js"; import type { Manifest } from "../../../../domain/models/manifest.js"; import { Plugin } from "../../../../domain/models/plugin.js"; -import { PluginContentTranslator } from "../../../../domain/models/plugin-content-translator.js"; import type { PluginDistribution } from "../../../../domain/models/plugin-distribution.js"; import type { PluginSource } from "../../../../domain/models/plugin-source.js"; import type { PluginTranslationSkip, ReadonlySkipList, } from "../../../../domain/models/plugin-translation-skip.js"; +import { PluginTranslator as PluginTranslatorHelper } from "../../../../domain/models/plugin-translator.js"; import type { AiToolId } from "../../../../domain/models/tool-ids.js"; import type { FileReader } from "../../../../domain/ports/file-reader.js"; import type { FileWriter } from "../../../../domain/ports/file-writer.js"; @@ -85,7 +85,7 @@ export class ModeBFlatMaterializationTranslator implements PluginTranslator { if (pluginsCap.mode === "native" && pluginsCap.installScope !== "user") { throw new CursorProjectScopeUnsupportedError(); } - const { files, componentPaths, skipped } = new PluginContentTranslator( + const { files, componentPaths, skipped } = new PluginTranslatorHelper( this.hasher ).translateWithComponentPaths(dist, toolConfig, docsDir); const baseDir = this.resolveBaseDir(pluginsCap, projectRoot); diff --git a/cli/src/application/use-cases/restore/restore-all-plugins-use-case.ts b/cli/src/application/use-cases/restore/restore-all-plugins-use-case.ts index 7a9e54d94..cf62c5e09 100644 --- a/cli/src/application/use-cases/restore/restore-all-plugins-use-case.ts +++ b/cli/src/application/use-cases/restore/restore-all-plugins-use-case.ts @@ -7,12 +7,7 @@ import type { FileWriter } from "../../../domain/ports/file-writer.js"; import type { Hasher } from "../../../domain/ports/hasher.js"; import type { PluginDistributionReader } from "../../../domain/ports/plugin-distribution-reader.js"; import type { PluginFetcher } from "../../../domain/ports/plugin-fetcher.js"; -import { - getToolConfig, - isAiTool, - type ToolConfig, - type ToolId, -} from "../../../domain/tools/registry.js"; +import { getToolConfig, isAiTool, type ToolConfig } from "../../../domain/tools/registry.js"; import { ApplyPluginFilesUseCase, type BuiltMaterializationDeps, @@ -24,14 +19,6 @@ interface RestoreAllPluginsOptions { docsDir: string; fileFilter: ((p: string) => boolean) | null; pluginName?: string; - /** Restrict which AI tools' plugins get touched. Undefined means every installed AI tool (unscoped). */ - toolIds?: readonly ToolId[]; -} - -export interface RestoreAllPluginsResult { - totalFiles: number; - /** Names of plugins that had >=1 file actually restored, deduped across tools. */ - pluginNames: string[]; } export class RestoreAllPluginsUseCase { @@ -43,17 +30,15 @@ export class RestoreAllPluginsUseCase { private readonly builtDeps?: BuiltMaterializationDeps ) {} - async execute(options: RestoreAllPluginsOptions): Promise { - const { projectRoot, manifest, docsDir, fileFilter, pluginName, toolIds } = options; + async execute(options: RestoreAllPluginsOptions): Promise { + const { projectRoot, manifest, docsDir, fileFilter, pluginName } = options; const cacheDir = join(projectRoot, PLUGIN_CACHE_SUBDIR); - let totalFiles = 0; - const restoredNames = new Set(); + let total = 0; for (const toolId of AI_TOOL_IDS) { if (!manifest.hasTool(toolId)) continue; - if (toolIds !== undefined && !toolIds.includes(toolId)) continue; const toolConfig = getToolConfig(toolId); if (!isAiTool(toolConfig)) continue; - const result = await this.restoreToolPlugins( + total += await this.restoreToolPlugins( toolId, manifest, toolConfig, @@ -63,10 +48,8 @@ export class RestoreAllPluginsUseCase { fileFilter, pluginName ); - totalFiles += result.totalFiles; - for (const name of result.pluginNames) restoredNames.add(name); } - return { totalFiles, pluginNames: [...restoredNames] }; + return total; } private async restoreToolPlugins( @@ -78,14 +61,13 @@ export class RestoreAllPluginsUseCase { docsDir: string, fileFilter: ((p: string) => boolean) | null, pluginName: string | undefined - ): Promise { - let totalFiles = 0; - const pluginNames: string[] = []; + ): Promise { + let total = 0; const plugins = manifest.getPlugins(toolId); const targets = pluginName !== undefined ? plugins.filter((p) => p.name === pluginName) : plugins; for (const plugin of targets) { - const filesWritten = await new ApplyPluginFilesUseCase( + total += await new ApplyPluginFilesUseCase( this.fs, this.hasher, this.pluginFetcher, @@ -101,9 +83,7 @@ export class RestoreAllPluginsUseCase { docsDir, fileFilter, }); - totalFiles += filesWritten; - if (filesWritten > 0) pluginNames.push(plugin.name); } - return { totalFiles, pluginNames }; + return total; } } diff --git a/cli/src/application/use-cases/restore/restore-plugin-use-case.ts b/cli/src/application/use-cases/restore/restore-plugin-use-case.ts new file mode 100644 index 000000000..29954f081 --- /dev/null +++ b/cli/src/application/use-cases/restore/restore-plugin-use-case.ts @@ -0,0 +1,82 @@ +import { join } from "node:path"; +import { PluginNotFoundError } from "../../../domain/errors.js"; +import type { Manifest } from "../../../domain/models/manifest.js"; +import { DOCS_DIR, PLUGIN_CACHE_SUBDIR } from "../../../domain/models/paths.js"; +import { AI_TOOL_IDS, type AiToolId } from "../../../domain/models/tool-ids.js"; +import type { FileMerger } from "../../../domain/ports/file-merger.js"; +import type { FileReader } from "../../../domain/ports/file-reader.js"; +import type { FileWriter } from "../../../domain/ports/file-writer.js"; +import type { Hasher } from "../../../domain/ports/hasher.js"; +import type { ManifestRepository } from "../../../domain/ports/manifest-repository.js"; +import type { PluginDistributionReader } from "../../../domain/ports/plugin-distribution-reader.js"; +import type { PluginFetcher } from "../../../domain/ports/plugin-fetcher.js"; +import { getToolConfig, isAiTool } from "../../../domain/tools/registry.js"; +import { NoManifestError } from "../../errors.js"; +import { + ApplyPluginFilesUseCase, + type BuiltMaterializationDeps, +} from "../shared/apply-plugin-files-use-case.js"; + +export interface RestorePluginOptions { + pluginName: string; + projectRoot: string; +} + +export interface RestorePluginResult { + totalRestored: number; +} + +export class RestorePluginUseCase { + constructor( + private readonly fs: FileReader & FileWriter & FileMerger, + private readonly manifestRepo: ManifestRepository, + private readonly pluginFetcher: PluginFetcher, + private readonly pluginDistributionReader: PluginDistributionReader, + private readonly hasher: Hasher, + private readonly builtDeps?: BuiltMaterializationDeps + ) {} + + async execute(options: RestorePluginOptions): Promise { + const { pluginName, projectRoot } = options; + const manifest = await this.manifestRepo.load(); + if (manifest === null) throw new NoManifestError(); + const cacheDir = join(projectRoot, PLUGIN_CACHE_SUBDIR); + const docsDir = DOCS_DIR; + const toolIds = AI_TOOL_IDS.filter((id) => manifest.hasTool(id)) as AiToolId[]; + let totalRestored = 0; + for (const toolId of toolIds) { + totalRestored += await this.applyPluginForTool( + toolId, + pluginName, + projectRoot, + cacheDir, + manifest, + docsDir + ); + } + if (totalRestored === 0) throw new PluginNotFoundError(pluginName); + await this.manifestRepo.save(manifest); + return { totalRestored }; + } + + private async applyPluginForTool( + toolId: AiToolId, + pluginName: string, + projectRoot: string, + cacheDir: string, + manifest: Manifest, + docsDir: string + ): Promise { + const plugin = manifest.getPlugins(toolId).find((p) => p.name === pluginName); + if (plugin === undefined) return 0; + const toolConfig = getToolConfig(toolId); + if (!isAiTool(toolConfig)) return 0; + return new ApplyPluginFilesUseCase( + this.fs, + this.hasher, + this.pluginFetcher, + this.pluginDistributionReader, + this.builtDeps + ).execute({ toolId, plugin, toolConfig, projectRoot, cacheDir, manifest, docsDir }); + } +} diff --git a/cli/src/application/use-cases/restore/restore-use-case.ts b/cli/src/application/use-cases/restore/restore-use-case.ts index 648c96413..a1dd4e9e9 100644 --- a/cli/src/application/use-cases/restore/restore-use-case.ts +++ b/cli/src/application/use-cases/restore/restore-use-case.ts @@ -19,10 +19,7 @@ import type { Prompter } from "../../../domain/ports/prompter.js"; import type { ToolId } from "../../../domain/tools/registry.js"; import { NoManifestError } from "../../errors.js"; import type { BuiltMaterializationDeps } from "../shared/apply-plugin-files-use-case.js"; -import { - type RestoreAllPluginsResult, - RestoreAllPluginsUseCase, -} from "./restore-all-plugins-use-case.js"; +import { RestoreAllPluginsUseCase } from "./restore-all-plugins-use-case.js"; import { type RestoreToolFilesResult, RestoreToolFilesUseCase, @@ -68,7 +65,6 @@ interface RestoreResult { totalRestored: number; totalKept: number; totalPluginFilesRestored: number; - restoredPluginNames: string[]; } export class RestoreUseCase { @@ -116,9 +112,9 @@ export class RestoreUseCase { private async executeRestore(ctx: RestoreCtx): Promise { const toolResults = await this.runToolRestores(ctx); - const pluginResult = await this.runPluginRestore(ctx); - await this.saveIfChanged(toolResults, pluginResult.totalFiles, ctx.manifest); - return this.buildTotals(toolResults, pluginResult); + const totalPluginFilesRestored = await this.runPluginRestore(ctx); + await this.saveIfChanged(toolResults, totalPluginFilesRestored, ctx.manifest); + return this.buildTotals(toolResults, totalPluginFilesRestored); } private async runToolRestores(ctx: RestoreCtx): Promise { @@ -137,10 +133,8 @@ export class RestoreUseCase { return results; } - private async runPluginRestore(ctx: RestoreCtx): Promise { - if (this.pluginFetcher === undefined || this.pluginDistributionReader === undefined) { - return { totalFiles: 0, pluginNames: [] }; - } + private async runPluginRestore(ctx: RestoreCtx): Promise { + if (this.pluginFetcher === undefined || this.pluginDistributionReader === undefined) return 0; return new RestoreAllPluginsUseCase( this.fs, this.hasher, @@ -153,7 +147,6 @@ export class RestoreUseCase { docsDir: ctx.docsDir, fileFilter: ctx.fileFilter, pluginName: ctx.pluginName, - toolIds: ctx.toolIds, }); } @@ -169,14 +162,13 @@ export class RestoreUseCase { private buildTotals( toolResults: RestoreToolFilesResult[], - pluginResult: RestoreAllPluginsResult + totalPluginFilesRestored: number ): RestoreResult { return { tools: toolResults, totalRestored: toolResults.reduce((s, t) => s + t.restored.length, 0), totalKept: toolResults.reduce((s, t) => s + t.kept.length, 0), - totalPluginFilesRestored: pluginResult.totalFiles, - restoredPluginNames: pluginResult.pluginNames, + totalPluginFilesRestored, }; } diff --git a/cli/src/application/use-cases/shared/apply-plugin-files-use-case.ts b/cli/src/application/use-cases/shared/apply-plugin-files-use-case.ts index 791adf71a..2676a858c 100644 --- a/cli/src/application/use-cases/shared/apply-plugin-files-use-case.ts +++ b/cli/src/application/use-cases/shared/apply-plugin-files-use-case.ts @@ -2,8 +2,8 @@ import { join } from "node:path"; import type { PluginsCapability } from "../../../domain/capabilities/plugins-capability.js"; import type { Manifest } from "../../../domain/models/manifest.js"; import type { Plugin } from "../../../domain/models/plugin.js"; -import { PluginContentTranslator } from "../../../domain/models/plugin-content-translator.js"; import type { PluginDistribution } from "../../../domain/models/plugin-distribution.js"; +import { PluginTranslator } from "../../../domain/models/plugin-translator.js"; import type { AiToolId } from "../../../domain/models/tool-ids.js"; import type { FileReader } from "../../../domain/ports/file-reader.js"; import type { FileWriter } from "../../../domain/ports/file-writer.js"; @@ -93,7 +93,7 @@ export class ApplyPluginFilesUseCase { options: ApplyPluginFilesOptions ): Promise { const { toolId, plugin, toolConfig, projectRoot, manifest, docsDir, fileFilter } = options; - const files = new PluginContentTranslator(this.hasher).translate(dist, toolConfig, docsDir); + const files = new PluginTranslator(this.hasher).translate(dist, toolConfig, docsDir); let restored = 0; for (const f of files) { if (fileFilter !== null && fileFilter !== undefined && !fileFilter(f.relativePath)) continue; diff --git a/cli/src/domain/models/framework-build.ts b/cli/src/domain/models/framework-build.ts index 1704d2072..9fada99a3 100644 --- a/cli/src/domain/models/framework-build.ts +++ b/cli/src/domain/models/framework-build.ts @@ -6,33 +6,6 @@ export type FrameworkBuildTarget = "claude" | "cursor" | "copilot" | "codex" | " /** Output layout discriminant: marketplace dist (Mode A) vs direct workspace inject (Mode B flat). */ export type FrameworkBuildMode = "marketplace" | "flat"; -export interface FrameworkBuildTargetMode { - readonly target: FrameworkBuildTarget; - readonly mode: FrameworkBuildMode; -} - -/** - * Every target/mode combination the build pipeline supports — the single source of truth - * for "which target:mode pairs exist". Infrastructure wiring (deps.ts's build registry) - * must not diverge from this list; commands read it here, not through infrastructure. - */ -export const FRAMEWORK_BUILD_TARGET_MODES: readonly FrameworkBuildTargetMode[] = [ - { target: "claude", mode: "marketplace" }, - { target: "claude", mode: "flat" }, - { target: "cursor", mode: "marketplace" }, - { target: "cursor", mode: "flat" }, - { target: "copilot", mode: "marketplace" }, - { target: "copilot", mode: "flat" }, - { target: "codex", mode: "marketplace" }, - { target: "codex", mode: "flat" }, - { target: "opencode", mode: "flat" }, -]; - -/** Every target with at least one supported build mode, derived from FRAMEWORK_BUILD_TARGET_MODES. */ -export const SUPPORTED_BUILD_TARGETS: readonly FrameworkBuildTarget[] = [ - ...new Set(FRAMEWORK_BUILD_TARGET_MODES.map((entry) => entry.target)), -]; - export interface FrameworkBuildOptions { readonly sourceDir: string; readonly outDir: string; diff --git a/cli/src/domain/models/plugin-content-translator.ts b/cli/src/domain/models/plugin-translator.ts similarity index 99% rename from cli/src/domain/models/plugin-content-translator.ts rename to cli/src/domain/models/plugin-translator.ts index 5d9ef376e..f5ebbe521 100644 --- a/cli/src/domain/models/plugin-content-translator.ts +++ b/cli/src/domain/models/plugin-translator.ts @@ -42,7 +42,7 @@ interface SkillCap { serialize: (fm: Record, body: string) => string; } -export class PluginContentTranslator { +export class PluginTranslator { constructor(private readonly hasher: Hasher) {} translate(dist: PluginDistribution, toolConfig: ToolConfig, docsDir: string): InstallationFile[] { diff --git a/cli/src/infrastructure/deps.ts b/cli/src/infrastructure/deps.ts index 6f692e51b..71ac1dc8e 100644 --- a/cli/src/infrastructure/deps.ts +++ b/cli/src/infrastructure/deps.ts @@ -448,11 +448,6 @@ export async function createDeps( ); const assetProvider = new BundledAssetProviderAdapter(); const jsonSchemaValidator = new AjvSchemaValidatorAdapter(); - // force:true is safe here: outDir is always builtMarketplaceDir(), an aidd-owned - // disposable cache under .aidd/cache/built/, never a user-owned directory. A - // collision only means "the cache from a previous build already exists" — the - // whole point of a rebuild. The real user --force (framework.ts) is unrelated - // and already threaded correctly for the direct `framework build --flat` path. const frameworkBuildFor: FrameworkBuildFor = (target, mode, outDir) => createFrameworkBuildUseCase( { fs, assetProvider, logger }, @@ -623,12 +618,18 @@ export async function createDeps( builtMaterializationDeps ); const uninstallUseCase = new UninstallUseCase(fs, manifestRepo, logger); - const statusAllUseCase = new StatusAllUseCase(statusUseCase); + const statusAllUseCase = new StatusAllUseCase(fs, manifestRepo, hasher); const restoreAllUseCase = new RestoreAllUseCase( + fs, manifestRepo, + hasher, + logger, + platform, prompter, - statusUseCase, - restoreUseCase + pluginFetcher, + pluginDistributionReader, + assetProvider, + builtMaterializationDeps ); const resolveUpdateDecisionUseCase = new ResolveUpdateDecisionUseCase(prompter); const updateOneToolUseCase = new UpdateOneToolUseCase( @@ -641,9 +642,13 @@ export async function createDeps( const updateAllUseCase = new UpdateAllUseCase( manifestRepo, currentVersionProvider, + installRuntimeConfigUseCase, + installIdeConfigUseCase, pluginUpdateUseCase, marketplaceRefreshUseCase, - updateOneToolUseCase + syncConflictResolverUseCase, + resolveUpdateDecisionUseCase, + fs ); const updateAiToolsUseCase = new UpdateAiToolsUseCase( manifestRepo, diff --git a/cli/tests/application/use-cases/framework/marketplace-strategy-helpers.unit.test.ts b/cli/tests/application/use-cases/framework/marketplace-strategy-helpers.unit.test.ts index 8ab0b500d..e2121d857 100644 --- a/cli/tests/application/use-cases/framework/marketplace-strategy-helpers.unit.test.ts +++ b/cli/tests/application/use-cases/framework/marketplace-strategy-helpers.unit.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from "vitest"; import type { PluginPresenceFlags } from "../../../../src/application/use-cases/framework/strategies/marketplace-strategy-helpers.js"; import { - buildClaudeStyleCatalogEntry, buildClaudeStyleMarketplace, + buildClaudeStyleMarketplaceEntry, synthesizeClaudeStyleManifest, } from "../../../../src/application/use-cases/framework/strategies/marketplace-strategy-helpers.js"; @@ -223,9 +223,9 @@ describe("buildClaudeStyleMarketplace", () => { }); }); -describe("buildClaudeStyleCatalogEntry", () => { +describe("buildClaudeStyleMarketplaceEntry", () => { it("builds entry with name, source, description, version", () => { - const entry = buildClaudeStyleCatalogEntry("aidd-dev", "AI Dev plugin", "1.0.0", undefined); + const entry = buildClaudeStyleMarketplaceEntry("aidd-dev", "AI Dev plugin", "1.0.0", undefined); expect(entry.name).toBe("aidd-dev"); expect(entry.source).toBe("./plugins/aidd-dev"); expect(entry.description).toBe("AI Dev plugin"); @@ -233,7 +233,7 @@ describe("buildClaudeStyleCatalogEntry", () => { }); it("passes through strict and recommended when present", () => { - const entry = buildClaudeStyleCatalogEntry("aidd-dev", "desc", "1.0.0", { + const entry = buildClaudeStyleMarketplaceEntry("aidd-dev", "desc", "1.0.0", { strict: true, recommended: false, }); @@ -242,13 +242,13 @@ describe("buildClaudeStyleCatalogEntry", () => { }); it("omits strict and recommended when absent", () => { - const entry = buildClaudeStyleCatalogEntry("aidd-dev", "desc", "1.0.0", undefined); + const entry = buildClaudeStyleMarketplaceEntry("aidd-dev", "desc", "1.0.0", undefined); expect(entry.strict).toBeUndefined(); expect(entry.recommended).toBeUndefined(); }); it("only includes strict when it is boolean (not string/number)", () => { - const entry = buildClaudeStyleCatalogEntry("aidd-dev", "desc", "1.0.0", { strict: true }); + const entry = buildClaudeStyleMarketplaceEntry("aidd-dev", "desc", "1.0.0", { strict: true }); expect(typeof entry.strict).toBe("boolean"); }); }); diff --git a/cli/tests/application/use-cases/restore-all-use-case.unit.test.ts b/cli/tests/application/use-cases/restore-all-use-case.unit.test.ts deleted file mode 100644 index 0a44f79f2..000000000 --- a/cli/tests/application/use-cases/restore-all-use-case.unit.test.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { join } from "node:path"; -import { describe, expect, it } from "vitest"; -import { RestoreAllUseCase } from "../../../src/application/use-cases/global/restore-all-use-case.js"; -import { PluginAddUseCase } from "../../../src/application/use-cases/plugin/plugin-add-use-case.js"; -import { RestoreUseCase } from "../../../src/application/use-cases/restore/restore-use-case.js"; -import { StatusUseCase } from "../../../src/application/use-cases/status-use-case.js"; -import { PluginDistributionReaderAdapter } from "../../../src/infrastructure/adapters/plugin-distribution-reader-adapter.js"; -import { buildUnitDeps, initAndInstall, installTool } from "../../helpers/ports/build-unit-deps.js"; -import { fakeEnsureBuiltMarketplace } from "../../helpers/ports/fake-ensure-built-marketplace.js"; -import { FakePlatform } from "../../helpers/ports/fake-platform.js"; -import { OverwritePrompter, ScriptedPrompter } from "../../helpers/ports/scripted-prompter.js"; -import { seedFromDirectory } from "../../helpers/ports/seed-from-directory.js"; - -const PROJECT_ROOT = "/test-project"; -const PLUGIN_FIXTURE = join(process.cwd(), "tests/fixtures/plugins/claude-format/sample-plugin"); - -type Deps = Awaited>; - -function builtDeps(deps: Deps) { - return { - ensureBuilt: fakeEnsureBuiltMarketplace(), - marketplaceRegistry: deps.marketplaceRegistry, - homedir: () => "/home/test", - }; -} - -async function installPlugin( - deps: Deps, - toolId: "claude" | "cursor", - pluginReader: PluginDistributionReaderAdapter -): Promise { - await new PluginAddUseCase( - deps.fs, - deps.manifestRepo, - deps.pluginFetcher, - pluginReader, - deps.hasher, - deps.logger, - deps.marketplaceRegistry, - fakeEnsureBuiltMarketplace() - ).execute({ - source: { kind: "local", path: PLUGIN_FIXTURE }, - toolIds: [toolId], - projectRoot: PROJECT_ROOT, - interactive: false, - }); -} - -function makeRestoreAllUseCase( - deps: Deps, - pluginReader: PluginDistributionReaderAdapter, - prompter: OverwritePrompter | ScriptedPrompter = new OverwritePrompter(), - withBuiltDeps = false -): RestoreAllUseCase { - const statusUseCase = new StatusUseCase(deps.fs, deps.manifestRepo, deps.hasher); - const restoreUseCase = new RestoreUseCase( - deps.fs, - deps.manifestRepo, - deps.hasher, - deps.logger, - new FakePlatform("linux"), - prompter, - deps.pluginFetcher, - pluginReader, - deps.assetProvider, - withBuiltDeps ? builtDeps(deps) : undefined - ); - return new RestoreAllUseCase(deps.manifestRepo, prompter, statusUseCase, restoreUseCase); -} - -function countingReader(fs: Deps["fs"]): { - reader: PluginDistributionReaderAdapter; - count: () => number; -} { - const reader = new PluginDistributionReaderAdapter(fs); - let calls = 0; - const original = reader.read.bind(reader); - reader.read = async (...args: Parameters) => { - calls++; - return original(...args); - }; - return { reader, count: () => calls }; -} - -describe("RestoreAllUseCase — plugin materialization (BUG-E3-02 / A3)", () => { - it("restores a corrupted plugin file with exactly one materialization call (translate-mode: claude)", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initAndInstall(deps, PROJECT_ROOT, "claude"); - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - await installPlugin(deps, "claude", new PluginDistributionReaderAdapter(deps.fs)); - - const pluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(pluginFile, "CORRUPTED CONTENT"); - - // Counting reader wired only from here — installPlugin's own read() must not count. - const { reader, count } = countingReader(deps.fs); - const useCase = makeRestoreAllUseCase(deps, reader); - await useCase.execute(PROJECT_ROOT, false); - - expect(deps.fs.getFile(pluginFile)).not.toBe("CORRUPTED CONTENT"); - expect(deps.fs.getFile(pluginFile)).toContain("Greet from sample-plugin."); - expect(count()).toBe(1); - }); - - it("restores a corrupted plugin file with exactly one materialization call (cursor — installScope:user tool)", async () => { - // A local-source install never hits restoreViaBuiltTree (that path requires - // plugin.marketplace to be set — see apply-plugin-files-use-case.ts), so this - // still exercises restoreViaTranslate like claude, just for a second, differently - // -configured AI tool (installScope:"user", pluginsDir:""). It's not the true - // built-tree double-*write* path (that needs a marketplace-sourced install, out - // of scope here), but it does independently confirm the collapse-to-one-pass - // fix isn't accidentally claude-specific. - const deps = await buildUnitDeps(PROJECT_ROOT); - await initAndInstall(deps, PROJECT_ROOT, "cursor"); - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - await installPlugin(deps, "cursor", new PluginDistributionReaderAdapter(deps.fs)); - - const manifestAfterInstall = await deps.manifestRepo.load(); - const plugin = manifestAfterInstall - ?.getPlugins("cursor") - .find((p) => p.name === "sample-plugin"); - const trackedRelativePath = [...(plugin?.files.keys() ?? [])][0]; - expect(trackedRelativePath).toBeDefined(); - // plugin.files keys are relativePath (see restoreViaTranslate); actual fs storage is - // keyed by the absolute path the file was written to. - const pluginFile = join(PROJECT_ROOT, trackedRelativePath as string); - await deps.fs.writeFile(pluginFile, "CORRUPTED CONTENT"); - - // Counting reader wired only from here — installPlugin's own read() must not count. - const { reader, count } = countingReader(deps.fs); - const useCase = makeRestoreAllUseCase(deps, reader, new OverwritePrompter(), true); - await useCase.execute(PROJECT_ROOT, false); - - expect(deps.fs.getFile(pluginFile)).not.toBe("CORRUPTED CONTENT"); - expect(count()).toBe(1); - }); - - it("result.pluginNamesRestored lists the restored plugin exactly once", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initAndInstall(deps, PROJECT_ROOT, "claude"); - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - const { reader } = countingReader(deps.fs); - await installPlugin(deps, "claude", reader); - - const pluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(pluginFile, "CORRUPTED CONTENT"); - - const result = await makeRestoreAllUseCase(deps, reader).execute(PROJECT_ROOT, false); - - expect(result.pluginNamesRestored).toEqual(["sample-plugin"]); - expect(result.errors).toHaveLength(0); - }); - - it("a plugin already up to date is not listed as restored and produces no error", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initAndInstall(deps, PROJECT_ROOT, "claude"); - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - const { reader } = countingReader(deps.fs); - await installPlugin(deps, "claude", reader); - - // Nothing corrupted — plugin files are already at their installed state. - const manifestBefore = await deps.manifestRepo.load(); - const pluginBefore = manifestBefore - ?.getPlugins("claude") - .find((p) => p.name === "sample-plugin"); - - const result = await makeRestoreAllUseCase(deps, reader).execute(PROJECT_ROOT, false); - - expect(result.pluginNamesRestored).toEqual([]); - expect(result.errors).toHaveLength(0); - const manifestAfter = await deps.manifestRepo.load(); - const pluginAfter = manifestAfter?.getPlugins("claude").find((p) => p.name === "sample-plugin"); - expect(pluginAfter?.files).toEqual(pluginBefore?.files); - }); - - it("interactive restore with an explicit file selection also skips unselected plugin files (translate-mode)", async () => { - // Plugin drift isn't offered by the interactive picker at all (StatusUseCase's - // pluginDrift is never read by promptForFiles) — so once the user picks ANY - // specific regular file, ctx.fileFilter becomes active and every plugin path - // fails to match it (it was never a selectable option). This mirrors what - // ai.ts/ide.ts's `restore ` already does today (ctx.fileFilter already - // reached plugin restore for THAT path before this fix) — this test proves the - // global `aidd restore` command now behaves the same way, consistently. - const deps = await buildUnitDeps(PROJECT_ROOT); - await initAndInstall(deps, PROJECT_ROOT, "claude"); - await installTool(deps, PROJECT_ROOT, "vscode"); - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - const { reader } = countingReader(deps.fs); - await installPlugin(deps, "claude", reader); - - const pluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(pluginFile, "CORRUPTED CONTENT"); - // keybindings.json is a plain tracked file (unlike settings.json, which is merge-type - // and reports composite "path > key" drift entries, not a plain selectable path). - const vscodeKeybindingsPath = join(PROJECT_ROOT, ".vscode/keybindings.json"); - await deps.fs.writeFile(vscodeKeybindingsPath, "CORRUPTED KEYBINDINGS"); - - // User selects only the regular vscode file from the drifted-files checkbox - // (StatusUseCase reports relativePath, not the absolute path). Whether - // keybindings.json itself is actually repaired isn't asserted here: RestoreAllUseCase - // never supplies frameworkPath to RestoreUseCase, so CONFIG_REFS-driven regular-file - // content can't regenerate through this path at all — a separate, pre-existing gap, - // out of scope for BUG-E3-02. What this test proves is narrower and in scope: making - // ANY explicit selection turns fileFilter on, and once on, it excludes every plugin - // path (never offered as a choice), where pre-fix Pass 2 ignored fileFilter entirely. - const prompter = new ScriptedPrompter([ - ScriptedPrompter.answer.checkbox([".vscode/keybindings.json"]), - ]); - const useCase = makeRestoreAllUseCase(deps, reader, prompter); - await useCase.execute(PROJECT_ROOT, true); - - expect(deps.fs.getFile(pluginFile)).toBe("CORRUPTED CONTENT"); - }); - - it("unscoped restore still restores every installed AI tool's plugins (no regression)", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initAndInstall(deps, PROJECT_ROOT, "claude"); - await installTool(deps, PROJECT_ROOT, "codex"); - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - const { reader } = countingReader(deps.fs); - await installPlugin(deps, "claude", reader); - await new PluginAddUseCase( - deps.fs, - deps.manifestRepo, - deps.pluginFetcher, - reader, - deps.hasher, - deps.logger, - deps.marketplaceRegistry, - fakeEnsureBuiltMarketplace() - ).execute({ - source: { kind: "local", path: PLUGIN_FIXTURE }, - toolIds: ["codex"], - projectRoot: PROJECT_ROOT, - interactive: false, - }); - - const claudePluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - const codexPluginFile = join(PROJECT_ROOT, ".codex/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(claudePluginFile, "CORRUPTED CLAUDE"); - await deps.fs.writeFile(codexPluginFile, "CORRUPTED CODEX"); - - await makeRestoreAllUseCase(deps, reader).execute(PROJECT_ROOT, false); - - expect(deps.fs.getFile(claudePluginFile)).not.toBe("CORRUPTED CLAUDE"); - expect(deps.fs.getFile(codexPluginFile)).not.toBe("CORRUPTED CODEX"); - }); -}); diff --git a/cli/tests/application/use-cases/restore-plugin.unit.test.ts b/cli/tests/application/use-cases/restore-plugin.unit.test.ts new file mode 100644 index 000000000..418476a6a --- /dev/null +++ b/cli/tests/application/use-cases/restore-plugin.unit.test.ts @@ -0,0 +1,74 @@ +import { join } from "node:path"; +import { describe, expect, it } from "vitest"; +import { PluginAddUseCase } from "../../../src/application/use-cases/plugin/plugin-add-use-case.js"; +import { RestorePluginUseCase } from "../../../src/application/use-cases/restore/restore-plugin-use-case.js"; +import { PluginNotFoundError } from "../../../src/domain/errors.js"; +import { PluginDistributionReaderAdapter } from "../../../src/infrastructure/adapters/plugin-distribution-reader-adapter.js"; +import { buildUnitDeps, initAndInstall } from "../../helpers/ports/build-unit-deps.js"; +import { fakeEnsureBuiltMarketplace } from "../../helpers/ports/fake-ensure-built-marketplace.js"; +import { seedFromDirectory } from "../../helpers/ports/seed-from-directory.js"; + +const PLUGIN_FIXTURE = join(process.cwd(), "tests/fixtures/plugins/claude-format/sample-plugin"); +const PROJECT_ROOT = "/test-project"; + +describe("RestorePluginUseCase", () => { + describe("when plugin files are corrupted", () => { + it("re-writes plugin files to their original content", async () => { + const deps = await buildUnitDeps(PROJECT_ROOT); + await initAndInstall(deps, PROJECT_ROOT, "claude"); + await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); + + const pluginReader = new PluginDistributionReaderAdapter(deps.fs); + + await new PluginAddUseCase( + deps.fs, + deps.manifestRepo, + deps.pluginFetcher, + pluginReader, + deps.hasher, + deps.logger, + deps.marketplaceRegistry, + fakeEnsureBuiltMarketplace() + ).execute({ + source: { kind: "local", path: PLUGIN_FIXTURE }, + toolIds: ["claude"], + projectRoot: PROJECT_ROOT, + interactive: false, + }); + + const pluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); + await deps.fs.writeFile(pluginFile, "CORRUPTED CONTENT"); + + await new RestorePluginUseCase( + deps.fs, + deps.manifestRepo, + deps.pluginFetcher, + pluginReader, + deps.hasher + ).execute({ pluginName: "sample-plugin", projectRoot: PROJECT_ROOT }); + + const restoredContent = deps.fs.getFile(pluginFile) ?? ""; + expect(restoredContent).not.toBe("CORRUPTED CONTENT"); + expect(restoredContent).toContain("Greet from sample-plugin."); + }); + }); + + describe("when plugin does not exist", () => { + it("throws PluginNotFoundError", async () => { + const deps = await buildUnitDeps(PROJECT_ROOT); + await initAndInstall(deps, PROJECT_ROOT, "claude"); + + const pluginReader = new PluginDistributionReaderAdapter(deps.fs); + + await expect( + new RestorePluginUseCase( + deps.fs, + deps.manifestRepo, + deps.pluginFetcher, + pluginReader, + deps.hasher + ).execute({ pluginName: "nonexistent-plugin", projectRoot: PROJECT_ROOT }) + ).rejects.toThrow(PluginNotFoundError); + }); + }); +}); diff --git a/cli/tests/application/use-cases/restore-use-case.unit.test.ts b/cli/tests/application/use-cases/restore-use-case.unit.test.ts index 80a1b00cd..6f1668870 100644 --- a/cli/tests/application/use-cases/restore-use-case.unit.test.ts +++ b/cli/tests/application/use-cases/restore-use-case.unit.test.ts @@ -1,8 +1,6 @@ import { join } from "node:path"; import { describe, expect, it } from "vitest"; -import { PluginAddUseCase } from "../../../src/application/use-cases/plugin/plugin-add-use-case.js"; import { RestoreUseCase } from "../../../src/application/use-cases/restore/restore-use-case.js"; -import { PluginDistributionReaderAdapter } from "../../../src/infrastructure/adapters/plugin-distribution-reader-adapter.js"; import { buildUnitDeps, FIXTURE_DIR, @@ -10,36 +8,10 @@ import { initProject, installTool, } from "../../helpers/ports/build-unit-deps.js"; -import { fakeEnsureBuiltMarketplace } from "../../helpers/ports/fake-ensure-built-marketplace.js"; import { FakePlatform } from "../../helpers/ports/fake-platform.js"; import { KeepPrompter, OverwritePrompter } from "../../helpers/ports/scripted-prompter.js"; -import { seedFromDirectory } from "../../helpers/ports/seed-from-directory.js"; const PROJECT_ROOT = "/test-project"; -const PLUGIN_FIXTURE = join(process.cwd(), "tests/fixtures/plugins/claude-format/sample-plugin"); - -async function installPlugin( - deps: Awaited>, - toolId: "claude" | "codex" -): Promise { - await seedFromDirectory(deps.fs, PLUGIN_FIXTURE, { useAbsolutePaths: true }); - const pluginReader = new PluginDistributionReaderAdapter(deps.fs); - await new PluginAddUseCase( - deps.fs, - deps.manifestRepo, - deps.pluginFetcher, - pluginReader, - deps.hasher, - deps.logger, - deps.marketplaceRegistry, - fakeEnsureBuiltMarketplace() - ).execute({ - source: { kind: "local", path: PLUGIN_FIXTURE }, - toolIds: [toolId], - projectRoot: PROJECT_ROOT, - interactive: false, - }); -} /** RecordingPrompter for tracking resolveConflict calls */ class RecordingPrompter extends OverwritePrompter { @@ -191,79 +163,6 @@ describe("restore", () => { expect(cursorContent).toBe('{"modified": true}'); }); - it("toolIds filter also scopes plugin restore — does not leak to other AI tools (BUG-E3-02 / A2)", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initProject(deps, PROJECT_ROOT); - await installTool(deps, PROJECT_ROOT, "claude"); - await installTool(deps, PROJECT_ROOT, "codex"); - await installPlugin(deps, "claude"); - await installPlugin(deps, "codex"); - - const claudePluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - const codexPluginFile = join(PROJECT_ROOT, ".codex/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(claudePluginFile, "CORRUPTED CLAUDE"); - await deps.fs.writeFile(codexPluginFile, "CORRUPTED CODEX"); - - await makeRestoreUseCase(deps).execute({ - frameworkPath: FIXTURE_DIR, - version: "test", - docsDir: "aidd_docs", - projectRoot: PROJECT_ROOT, - toolIds: ["claude"], - force: true, - }); - - expect(deps.fs.getFile(claudePluginFile)).not.toBe("CORRUPTED CLAUDE"); - expect(deps.fs.getFile(codexPluginFile)).toBe("CORRUPTED CODEX"); - }); - - it("ide restore never touches AI plugin files, scoped or unscoped (BUG-E3-02 / A2) — IDE_TOOL_IDS has a single member so this covers both", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initProject(deps, PROJECT_ROOT); - await installTool(deps, PROJECT_ROOT, "vscode"); - await installTool(deps, PROJECT_ROOT, "claude"); - await installPlugin(deps, "claude"); - - const claudePluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(claudePluginFile, "CORRUPTED CLAUDE"); - - await makeRestoreUseCase(deps).execute({ - frameworkPath: FIXTURE_DIR, - version: "test", - docsDir: "aidd_docs", - projectRoot: PROJECT_ROOT, - toolIds: ["vscode"], - force: true, - }); - - expect(deps.fs.getFile(claudePluginFile)).toBe("CORRUPTED CLAUDE"); - }); - - it("unscoped restore still restores every installed AI tool's plugins (no regression)", async () => { - const deps = await buildUnitDeps(PROJECT_ROOT); - await initProject(deps, PROJECT_ROOT); - await installTool(deps, PROJECT_ROOT, "claude"); - await installTool(deps, PROJECT_ROOT, "codex"); - await installPlugin(deps, "claude"); - await installPlugin(deps, "codex"); - - const claudePluginFile = join(PROJECT_ROOT, ".claude/plugins/sample-plugin/commands/greet.md"); - const codexPluginFile = join(PROJECT_ROOT, ".codex/plugins/sample-plugin/commands/greet.md"); - await deps.fs.writeFile(claudePluginFile, "CORRUPTED CLAUDE"); - await deps.fs.writeFile(codexPluginFile, "CORRUPTED CODEX"); - - await makeRestoreUseCase(deps).execute({ - frameworkPath: FIXTURE_DIR, - version: "test", - docsDir: "aidd_docs", - projectRoot: PROJECT_ROOT, - force: true, - }); - - expect(deps.fs.getFile(claudePluginFile)).not.toBe("CORRUPTED CLAUDE"); - expect(deps.fs.getFile(codexPluginFile)).not.toBe("CORRUPTED CODEX"); - }); - it("does not remove untracked files in tool directory", async () => { const deps = await buildUnitDeps(PROJECT_ROOT); await initAndInstall(deps, PROJECT_ROOT, "claude"); diff --git a/cli/tests/application/use-cases/shared/ensure-built-marketplace-use-case.integration.test.ts b/cli/tests/application/use-cases/shared/ensure-built-marketplace-use-case.integration.test.ts index 92e49b080..e442b5586 100644 --- a/cli/tests/application/use-cases/shared/ensure-built-marketplace-use-case.integration.test.ts +++ b/cli/tests/application/use-cases/shared/ensure-built-marketplace-use-case.integration.test.ts @@ -1,9 +1,7 @@ import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; +import { join } from "node:path"; import { beforeEach, describe, expect, it } from "vitest"; -import { FrameworkBuildUseCase } from "../../../../src/application/use-cases/framework/framework-build-use-case.js"; -import { FlatBuildStrategy } from "../../../../src/application/use-cases/framework/strategies/flat-build-strategy.js"; -import { buildCopilotFlatContract } from "../../../../src/application/use-cases/framework/strategies/tool-contracts.js"; +import type { FrameworkBuildUseCase } from "../../../../src/application/use-cases/framework/framework-build-use-case.js"; import { EnsureBuiltMarketplaceUseCase, type FrameworkBuildFor, @@ -14,46 +12,10 @@ import type { } from "../../../../src/application/use-cases/shared/resolve-marketplace-use-case.js"; import { Marketplace } from "../../../../src/domain/models/marketplace.js"; import { builtMarketplaceDir } from "../../../../src/domain/models/paths.js"; -import type { AssetProvider } from "../../../../src/domain/ports/asset-provider.js"; -import type { JsonSchemaValidator } from "../../../../src/domain/ports/json-schema-validator.js"; import type { VersionReader } from "../../../../src/domain/ports/version-reader.js"; -import { CapturingLogger } from "../../../helpers/ports/capturing-logger.js"; import { InMemoryFileAdapter } from "../../../helpers/ports/in-memory-file-adapter.js"; -import { seedFromDirectory } from "../../../helpers/ports/seed-from-directory.js"; const PROJECT = "/proj"; -const FIXTURE_DIR = resolve(process.cwd(), "tests/fixtures/framework"); -const PLUGIN = "aidd-test"; - -const MINIMAL_MANIFEST_SCHEMA = { - type: "object", - required: ["name"], - properties: { name: { type: "string" } }, -}; - -function noopValidator(): JsonSchemaValidator { - return { validate: () => undefined }; -} - -function stubAssetProvider(): AssetProvider { - return { - loadConfigAsset: () => { - throw new Error("not used"); - }, - loadDefaultMarketplace: () => { - throw new Error("not used"); - }, - loadSchema: (name) => (name === "plugin-manifest" ? MINIMAL_MANIFEST_SCHEMA : {}), - }; -} - -function makeIsDirectory(memFs: InMemoryFileAdapter): (path: string) => Promise { - return async (path: string): Promise => { - if (memFs.has(path)) return false; - const prefix = path.endsWith("/") ? path : `${path}/`; - return memFs.listAll().some((k) => k.startsWith(prefix)); - }; -} function makeMarketplace(): Marketplace { return Marketplace.create({ @@ -215,59 +177,3 @@ describe("EnsureBuiltMarketplaceUseCase", () => { expect(builds).toBe(1); }); }); - -// BUG-E2-01: deps.ts hardcodes force:true for this rebuild path because outDir is always -// builtMarketplaceDir() — an aidd-owned disposable cache, never a user-owned directory. A -// collision here only means "the cache from a previous build already exists" and should be -// overwritten, not treated as a destructive overwrite of user data. This pins that decision -// with a real FlatBuildStrategy (not the fake buildFor stub used above), so it fails if -// force is ever flipped to false here, or if outDir stops being cache-only. -describe("force behavior at the cache-rebuild path (BUG-E2-01)", () => { - it("overwrites a colliding file already present in the build cache instead of throwing FlatTargetExistsError", async () => { - const memFs = new InMemoryFileAdapter(); - await seedFromDirectory(memFs, FIXTURE_DIR, { useAbsolutePaths: true }); - - const builtDir = builtMarketplaceDir(PROJECT, "aidd-framework", "copilot"); - const agentPath = `${builtDir}/.github/agents/${PLUGIN}-code-reviewer.agent.md`; - memFs.setFile(agentPath, "stale cache content from a previous build"); - - const realBuildFor: FrameworkBuildFor = (_target, _mode, outDir) => { - const validator = noopValidator(); - const assetProvider = stubAssetProvider(); - const strategy = new FlatBuildStrategy( - memFs, - validator, - assetProvider, - buildCopilotFlatContract(), - true, // force:true — mirrors deps.ts wiring for every *:flat target - outDir, - makeIsDirectory(memFs), - new CapturingLogger() - ); - return new FrameworkBuildUseCase( - memFs, - validator, - assetProvider, - new CapturingLogger(), - strategy - ); - }; - - const uc = new EnsureBuiltMarketplaceUseCase( - memFs, - fakeResolve(FIXTURE_DIR, "1.0.0"), - realBuildFor, - fakeVersion("5.0.0") - ); - - const result = await uc.execute({ - projectRoot: PROJECT, - marketplace: makeMarketplace(), - target: "copilot", - mode: "flat", - }); - - expect(result.rebuilt).toBe(true); - expect(memFs.getFile(agentPath)).not.toBe("stale cache content from a previous build"); - }); -}); diff --git a/cli/tests/domain/models/plugin-content-translator.unit.test.ts b/cli/tests/domain/models/plugin-distribution-translate.unit.test.ts similarity index 97% rename from cli/tests/domain/models/plugin-content-translator.unit.test.ts rename to cli/tests/domain/models/plugin-distribution-translate.unit.test.ts index 43f774288..c47e6c933 100644 --- a/cli/tests/domain/models/plugin-content-translator.unit.test.ts +++ b/cli/tests/domain/models/plugin-distribution-translate.unit.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it } from "vitest"; import { FileHash } from "../../../src/domain/models/file.js"; -import { PluginContentTranslator } from "../../../src/domain/models/plugin-content-translator.js"; import { type PluginComponentFile, PluginDistribution, } from "../../../src/domain/models/plugin-distribution.js"; +import { PluginTranslator } from "../../../src/domain/models/plugin-translator.js"; import { claude } from "../../../src/domain/tools/ai/claude.js"; import { codex } from "../../../src/domain/tools/ai/codex.js"; import { copilot } from "../../../src/domain/tools/ai/copilot.js"; @@ -14,7 +14,7 @@ import { vscodeToolConfig } from "../../../src/domain/tools/ide/vscode.js"; import type { ToolConfig } from "../../../src/domain/tools/registry.js"; const stubHasher = { hash: (_content: string) => new FileHash("a".repeat(32)) }; -const translator = new PluginContentTranslator(stubHasher); +const translator = new PluginTranslator(stubHasher); const greetContent = `--- name: aidd:04:greet @@ -80,7 +80,7 @@ function pathsFor(tool: ToolConfig, dist = makeDist()): string[] { return translator.translate(dist, tool, "").map((f) => f.relativePath); } -describe("PluginContentTranslator.translate()", () => { +describe("PluginTranslator.translate()", () => { describe("claude target", () => { it("emits all components claude supports under .claude/plugins/sample-plugin/", () => { const paths = pathsFor(claude); @@ -286,7 +286,7 @@ describe("cross-format matrix (source × target)", () => { } }); -describe("PluginContentTranslator.detectFlatCollisions()", () => { +describe("PluginTranslator.detectFlatCollisions()", () => { it("reports no collision when plugins use different plugin names", () => { const dist1 = makeDist({ manifest: { name: "plugin-a", version: "1.0.0" } }); const dist2 = makeDist({ manifest: { name: "plugin-b", version: "1.0.0" } }); diff --git a/cli/tests/domain/models/plugin-content-translator-skip.unit.test.ts b/cli/tests/domain/models/plugin-translator-skip.unit.test.ts similarity index 93% rename from cli/tests/domain/models/plugin-content-translator-skip.unit.test.ts rename to cli/tests/domain/models/plugin-translator-skip.unit.test.ts index 8a965eae8..989ce060d 100644 --- a/cli/tests/domain/models/plugin-content-translator-skip.unit.test.ts +++ b/cli/tests/domain/models/plugin-translator-skip.unit.test.ts @@ -1,13 +1,13 @@ import { describe, expect, it } from "vitest"; import { FileHash } from "../../../src/domain/models/file.js"; -import { PluginContentTranslator } from "../../../src/domain/models/plugin-content-translator.js"; import { PluginDistribution } from "../../../src/domain/models/plugin-distribution.js"; import { OPENCODE_HOOKS_SKIP_REASON } from "../../../src/domain/models/plugin-translation-skip.js"; +import { PluginTranslator } from "../../../src/domain/models/plugin-translator.js"; import { cursor } from "../../../src/domain/tools/ai/cursor.js"; import { opencode } from "../../../src/domain/tools/ai/opencode.js"; const stubHasher = { hash: (_content: string) => new FileHash("a".repeat(32)) }; -const translator = new PluginContentTranslator(stubHasher); +const translator = new PluginTranslator(stubHasher); const HOOKS_CONTENT = JSON.stringify({ hooks: { PreToolUse: [{ hooks: [{ type: "command", command: "node ./hooks/pre.js" }] }] }, @@ -49,7 +49,7 @@ function buildDistWithHooks(name = "test-plugin"): PluginDistribution { }); } -describe("PluginContentTranslator skip list", () => { +describe("PluginTranslator skip list", () => { describe("flat mode (opencode)", () => { it("returns empty skipped list when plugin has no hooks or mcp", () => { const dist = buildDistWithNoHooksMcp(); diff --git a/cli/tests/infrastructure/framework-build-registry.unit.test.ts b/cli/tests/infrastructure/framework-build-registry.unit.test.ts deleted file mode 100644 index 3a19d3731..000000000 --- a/cli/tests/infrastructure/framework-build-registry.unit.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { - FRAMEWORK_BUILD_TARGET_MODES, - type FrameworkBuildMode, - type FrameworkBuildTarget, -} from "../../src/domain/models/framework-build.js"; -import { BundledAssetProviderAdapter } from "../../src/infrastructure/assets/asset-loader.js"; -import { createFrameworkBuildUseCase } from "../../src/infrastructure/deps.js"; -import { CapturingLogger } from "../helpers/ports/capturing-logger.js"; -import { InMemoryFileAdapter } from "../helpers/ports/in-memory-file-adapter.js"; - -const ALL_TARGETS: readonly FrameworkBuildTarget[] = [ - "claude", - "cursor", - "copilot", - "codex", - "opencode", -]; -const ALL_MODES: readonly FrameworkBuildMode[] = ["marketplace", "flat"]; - -function makeDeps() { - return { - fs: new InMemoryFileAdapter(), - assetProvider: new BundledAssetProviderAdapter(), - logger: new CapturingLogger(), - }; -} - -function isSupported(target: FrameworkBuildTarget, mode: FrameworkBuildMode): boolean { - return FRAMEWORK_BUILD_TARGET_MODES.some((e) => e.target === target && e.mode === mode); -} - -describe("deps.ts's build registry matches domain's FRAMEWORK_BUILD_TARGET_MODES exactly", () => { - for (const target of ALL_TARGETS) { - for (const mode of ALL_MODES) { - const label = `${target}:${mode}`; - const expected = isSupported(target, mode); - - it(`${label} is ${expected ? "" : "NOT "}wired in the registry, matching the domain list`, () => { - const useCase = createFrameworkBuildUseCase(makeDeps(), { - target, - mode, - outDir: "/out", - force: false, - }); - expect(useCase !== undefined).toBe(expected); - }); - } - } -}); diff --git a/plugins/aidd-context/skills/12-cook/actions/02-upsert.md b/plugins/aidd-context/skills/12-cook/actions/02-upsert.md index 8dbe2176d..197a7ace7 100644 --- a/plugins/aidd-context/skills/12-cook/actions/02-upsert.md +++ b/plugins/aidd-context/skills/12-cook/actions/02-upsert.md @@ -30,6 +30,6 @@ The recipe file at `aidd_docs/recipes/.md`, filled from the template. ## Test - A new or substantially-updated recipe is drafted from `research` results, not from memory. -- `aidd_docs/recipes/.md` exists and follows the recipe contract: opens with a one-sentence description (no Goal label, no table), each step a `#### N)` emoji heading with a real example, no `<...>` placeholder left. +- `aidd_docs/recipes/.md` exists and follows the recipe contract: opens with a one-sentence description (no Goal label, no table), uses `### N)` for direct steps or `#### N)` below a `###` category without skipping heading levels, gives every step a real example, and leaves no `<...>` placeholder. - A bundled recipe is never overwritten unless the user explicitly asks to change a bundled/framework recipe. - A new recipe that highly overlaps an existing project or bundled recipe triggers an update-or-create prompt before scaffolding. diff --git a/plugins/aidd-context/skills/12-cook/assets/recipe-template.md b/plugins/aidd-context/skills/12-cook/assets/recipe-template.md index 95a189c41..df55f63e3 100644 --- a/plugins/aidd-context/skills/12-cook/assets/recipe-template.md +++ b/plugins/aidd-context/skills/12-cook/assets/recipe-template.md @@ -1,50 +1,37 @@ -# +# Recipe title +- [Recipe title](#recipe-title) + - [Why](#why) + - [Steps to ](#steps-to-) + - [1) First step title](#1--first-step-title) + - [Verify ](#verify-) + ## Why ## Steps to -### 🟢 Beginner + -#### 1) +### 1) First step title 1. 2. -```bash -$ - -``` - -### 🟡 Intermediate - -#### 2) - - - -1. -2. - ``` ``` -### 🔴 Expert - -#### 3) - - - -1. - -![]() - -## Verify +## Verify - diff --git a/plugins/aidd-context/skills/12-cook/assets/recipes/install-aiddy-in-codex.md b/plugins/aidd-context/skills/12-cook/assets/recipes/install-aiddy-in-codex.md index 0c92c2cfb..83b8638bd 100644 --- a/plugins/aidd-context/skills/12-cook/assets/recipes/install-aiddy-in-codex.md +++ b/plugins/aidd-context/skills/12-cook/assets/recipes/install-aiddy-in-codex.md @@ -1,27 +1,35 @@ # Install AIDDy in Codex -Install AIDDy, the Agent Y mascot, as a local Codex pet. +Install AIDDy, the Agent Y mascot, as a local custom pet in the ChatGPT desktop app. + +- [Install AIDDy in Codex](#install-aiddy-in-codex) + - [Why](#why) + - [Steps to install and wake AIDDy](#steps-to-install-and-wake-aiddy) + - [1) 🔗 Open the AIDDy installer](#1--open-the-aiddy-installer) + - [2) 📦 Confirm the installation](#2--confirm-the-installation) + - [3) 🐾 Select AIDDy](#3--select-aiddy) + - [4) ▶️ Wake AIDDy](#4-️-wake-aiddy) + - [Verify](#verify) ## Why -**AIDDy** reflects Codex task activity with the AI-Driven Development mascot. +**AIDDy** reflects ChatGPT task activity with the AI-Driven Development mascot. **Sprite version 2** ensures Codex reads the extended 11-row animation atlas correctly. ## Steps to install and wake AIDDy -#### 1) 🔗 Open the AIDDy installer +### 1) 🔗 Open the AIDDy installer -The versioned deep link opens the Codex pet installer with the canonical AIDDy atlas. +The immutable deep link opens the pet installer with the canonical AIDDy atlas. -1. Use a machine with the Codex desktop app and internet access. -2. Click [Install AIDDy](codex://pets/install?name=AIDDy&imageUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fai-driven-dev%2Fframework%2Fmain%2Fassets%2Fpets%2Faiddy-spritesheet.webp&description=Agent%20Y%20for%20AI-Driven%20Development&spriteVersionNumber=2). +1. In the ChatGPT desktop app, click [Install AIDDy](codex://pets/install?name=AIDDy&imageUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fai-driven-dev%2Fframework%2F1a52770253628062e4e8cbcda1bd062452354c27%2Fassets%2Fpets%2Faiddy-spritesheet.webp&description=Agent%20Y%20for%20AI-Driven%20Development&spriteVersionNumber=2). ```text -codex://pets/install?name=AIDDy&imageUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fai-driven-dev%2Fframework%2Fmain%2Fassets%2Fpets%2Faiddy-spritesheet.webp&description=Agent%20Y%20for%20AI-Driven%20Development&spriteVersionNumber=2 +codex://pets/install?name=AIDDy&imageUrl=https%3A%2F%2Fraw.githubusercontent.com%2Fai-driven-dev%2Fframework%2F1a52770253628062e4e8cbcda1bd062452354c27%2Fassets%2Fpets%2Faiddy-spritesheet.webp&description=Agent%20Y%20for%20AI-Driven%20Development&spriteVersionNumber=2 ``` -#### 2) 📦 Confirm the installation +### 2) 📦 Confirm the installation The confirmation screen lets you verify the pet before writing it to local Codex storage. @@ -34,14 +42,21 @@ Description: Agent Y for AI-Driven Development Sprite version: 2 ``` -#### 3) 🐾 Wake AIDDy +### 3) 🐾 Select AIDDy + +Selecting the installed custom pet makes it active in the ChatGPT desktop app. + +1. Open **Settings > Pets**, select **Refresh** if needed, then choose **AIDDy**. + +```text +Settings > Pets > AIDDy +``` + +### 4) ▶️ Wake AIDDy -Selecting the custom pet makes it available as the animated task companion documented in [Codex pets](https://learn.chatgpt.com/docs/pets). +The `/pet` command wakes the selected companion so it can report task activity. -1. Open **Settings > Pets**. -2. Refresh custom pets if AIDDy is not visible yet. -3. Select **AIDDy**. -4. Enter `/pet` in a task. +1. Enter `/pet` in a task. ```text /pet @@ -51,4 +66,5 @@ Selecting the custom pet makes it available as the animated task companion docum - AIDDy appears in **Settings > Pets** as a custom pet. - `/pet` shows AIDDy and its animation changes with task activity. -- The link uses only the supported [pet install parameters](https://learn.chatgpt.com/docs/reference/app-commands#pets), including `spriteVersionNumber=2`. +- The link uses only the supported [pet install parameters](https://learn.chatgpt.com/docs/reference/commands#pets), including `spriteVersionNumber=2`. +- The pinned atlas has SHA-256 `a97872f637a6711da4a88cbbb56f9038b2fcb4ce870e021c9d2355a3421ad5a4`. diff --git a/plugins/aidd-context/skills/12-cook/assets/recipes/mcp-installation.md b/plugins/aidd-context/skills/12-cook/assets/recipes/mcp-installation.md index 698280dd3..752322dde 100644 --- a/plugins/aidd-context/skills/12-cook/assets/recipes/mcp-installation.md +++ b/plugins/aidd-context/skills/12-cook/assets/recipes/mcp-installation.md @@ -1,60 +1,155 @@ # MCP installations -Decide when to use an MCP server vs a CLI, and wire up the recommended ones. +Choose between a CLI and MCP by capability, then install the integration through the configuration native to your AI client. + +- [MCP installations](#mcp-installations) + - [Why](#why) + - [Steps to install the right integration](#steps-to-install-the-right-integration) + - [1) 🔎 Choose by capability](#1--choose-by-capability) + - [2) ⌨️ Install the CLI route](#2-️-install-the-cli-route) + - [3) 🔌 Install the MCP route](#3--install-the-mcp-route) + - [4) 🔐 Restrict access](#4--restrict-access) + - [5) ✅ Verify the connection](#5--verify-the-connection) + - [6) 🧹 Remove or revoke access](#6--remove-or-revoke-access) + - [Verify](#verify) ## Why -**MCP servers** load their full tool schema into every turn, which bloats the context window. +**Capability fit** matters more than whether a CLI happens to exist. -**CLI calls** cost a few tokens and return only what you ask for. +**[Claude Code Tool Search](https://code.claude.com/docs/en/mcp#scale-with-mcp-tool-search)** defers full MCP tool schemas on supported models and providers; other clients and MCP capabilities may load differently. -**Reach for MCP only when no CLI covers the service.** +**Native configuration** uses the file, schema, scope, and installation flow documented by the selected client. -**Audit what you install** before connecting any server. +**Least privilege** limits the impact of write tools, broad OAuth access, and prompt injection. -## Steps to choose and install the right integration +## Steps to install the right integration -#### 1) 🔎 Check for a CLI first +### 1) 🔎 Choose by capability -The CLI is usually cheaper because it does not inject a large tool schema into every turn. +Choose the smallest interface that fully covers the workflow, authentication model, and data scope. -1. Look for an official CLI before adding an MCP server. -2. Install and authenticate the CLI when it covers the workflow. -3. Keep MCP for services with no useful CLI alternative. +1. Compare the exact operation you need against the table. -| Service | Official MCP | CLI alternative | Recommended | +| Need | Prefer a CLI | Prefer MCP | +| --- | --- | --- | +| Scriptable commands and raw API calls | The official CLI covers the operation and its output is manageable | The client needs typed discovery or structured results | +| Live design or knowledge context | The CLI exposes the required operation and data | The server advertises the required tools, resources, or prompts | +| Authentication | The CLI's login and credential storage fit the workflow | The server's authentication, requested scopes, and host credential storage fit the workflow | +| Context cost | Output is requested only when the command runs | The client supports deferred loading such as [Claude Code Tool Search](https://code.claude.com/docs/en/mcp#scale-with-mcp-tool-search) | + +The last column is a decision heuristic for this recipe, not a provider guarantee. + +| Service | CLI route | MCP route | Recipe heuristic | | --- | --- | --- | --- | -| **GitHub** | [`api.githubcopilot.com/mcp/`](https://github.com/github/github-mcp-server) | [`gh`](https://cli.github.com/) | **CLI**: issues, PRs, releases, and API calls without the MCP schema cost | -| **Atlassian** (Jira / Confluence) | [`mcp.atlassian.com/v1/mcp`](https://www.atlassian.com/platform/remote-mcp-server) | [`acli`](https://developer.atlassian.com/cloud/acli/guides/introduction/) for Jira | **CLI** for Jira, **MCP** for Confluence | -| **Playwright** | [`@playwright/mcp`](https://github.com/microsoft/playwright-mcp) | [`npx playwright`](https://playwright.dev/docs/test-cli) | **CLI**: a real browser through `playwright open`, `codegen`, or `--headed` | -| **Figma** | [`mcp.figma.com/mcp`](https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/) | none for design data | **MCP** | -| **Notion** | [`mcp.notion.com/mcp`](https://developers.notion.com/guides/mcp/get-started-with-mcp) | none official | **MCP** | +| [GitHub](https://github.com/github/github-mcp-server) | [`gh`](https://cli.github.com/) | Remote toolsets, including read-only modes | CLI for routine API work; MCP for typed or remote-only capabilities | +| [Atlassian](https://www.atlassian.com/platform/rovo-mcp) | [`acli`](https://developer.atlassian.com/cloud/acli/guides/introduction/) for Jira | The current Rovo MCP tool catalog; [OAuth 2.1 is recommended](https://support.atlassian.com/atlassian-rovo-mcp-server/docs/configuring-oauth-2-1/), with API-token authentication only when an administrator enables it | Decide from the Atlassian product, operation, and permitted authentication | +| [Playwright](https://github.com/microsoft/playwright-mcp) | [`@playwright/cli`](https://playwright.dev/agent-cli/installation) | `@playwright/mcp` | CLI for direct browser automation; MCP for live tool calls | +| [Figma](https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/) | The [`@figma/code-connect` CLI](https://developers.figma.com/docs/code-connect/cli-reference/) manages component mappings, not live design context or canvas operations | `https://mcp.figma.com/mcp` | CLI for Code Connect mappings; MCP for live design and canvas workflows | +| [Notion](https://developers.notion.com/guides/mcp/get-started-with-mcp) | The official [`ntn` CLI](https://developers.notion.com/cli/get-started/overview) supports API, page, data-source, file, and Worker operations | `https://mcp.notion.com/mcp` | CLI for scripts and raw API work; MCP for agent workflows, with human confirmation | + +### 2) ⌨️ Install the CLI route + +The agent-oriented Playwright CLI is a direct browser alternative to Playwright MCP. + +1. Install `@playwright/cli` from the [official guide](https://playwright.dev/agent-cli/installation), then invoke its `playwright-cli` executable. + +```bash +npm install -g @playwright/cli@latest +playwright-cli open https://example.com --headed +``` + +Use `npx playwright test` for the test runner and `npx playwright codegen` for test generation; they are different command surfaces. + +### 3) 🔌 Install the MCP route + +Use a provider-supported client and distinguish the recommended plugin route from manual MCP configuration. + +1. Pick the [documented Figma route](https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/) for your client. + +| Client | Figma's recommended route | Manual alternative and scope | +| --- | --- | --- | +| Claude Code | `claude plugin install figma@claude-plugins-official` | `claude mcp add --transport http --scope project figma https://mcp.figma.com/mcp` writes project configuration to `.mcp.json` under `mcpServers` | +| Codex | In the Codex app, open **Plugins**, select **+** next to Figma, then **Install Figma** | `codex mcp add figma --url https://mcp.figma.com/mcp` writes to [`~/.codex/config.toml`](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) under `mcp_servers`; trusted projects may instead use `.codex/config.toml` | +| Cursor | Run `/add-plugin figma` | Manual project configuration uses `.cursor/mcp.json` under `mcpServers` | +| GitHub Copilot in VS Code | Run **MCP: Open Workspace Folder MCP Configuration**, paste Figma's documented server object, then select **Start** | Workspace configuration uses `.vscode/mcp.json` under `servers` | + +```bash +claude plugin install figma@claude-plugins-official +``` -#### 2) 🔌 Add MCP only when it is the right integration +[Figma accepts only clients in its MCP catalog](https://www.figma.com/mcp-catalog/); do not extrapolate these instructions to an unlisted host. -An MCP config belongs in the assistant's MCP configuration file, and only for services where MCP is the best available interface. +### 4) 🔐 Restrict access -1. Read the provider docs and permission model. -2. Add the server to `.mcp.json`. -3. Restart the assistant so it picks up the new tools. +Use the server's documented authentication, expose only required capabilities, and enforce confirmation for mutations. + +1. If the remote server uses OAuth, authorize it in the client and review the requested scopes; otherwise follow its documented authentication method. +2. Prefer read-only endpoints, toolsets, or allowlists when the workflow only reads. +3. Configure the host to require confirmation for mutating tools; if it cannot, disable write tools or use a provider-enforced read-only mode. + +[GitHub documents](https://github.com/github/github-mcp-server/blob/main/docs/server-configuration.md#read-only-mode) this VS Code-format server-entry fragment; place it under `servers.github` in `.vscode/mcp.json`, or adapt the wrapper to the selected host: ```json { - "mcpServers": { - "figma": { "url": "https://mcp.figma.com/mcp" } + "type": "http", + "url": "https://api.githubcopilot.com/mcp/", + "headers": { + "X-MCP-Toolsets": "repos,issues", + "X-MCP-Readonly": "true" } } ``` -#### 3) ✅ Verify the integration +[Notion MCP inherits the connected user's workspace access](https://developers.notion.com/guides/mcp/mcp-security-best-practices), so review every write and any data sent to another tool. + +### 5) ✅ Verify the connection + +Verify the configured server, authenticated identity, exposed tools, and one read-only operation before relying on it. + +1. Inspect the server through the client, then run a harmless read. + +```text +Claude Code: /mcp +Codex: codex mcp list +Cursor: Settings > Cursor Settings > Tools & MCP +VS Code: MCP: List Servers +``` + +Figma's documented successful Claude Code flow ends with: -Verification keeps a bad install out of later sessions. +```text +Authentication successful. Connected to figma +``` + +Use Figma's read-only [`whoami`](https://developers.figma.com/docs/figma-mcp-server/tools-and-prompts/#whoami-remote-only) tool to confirm the authenticated email, plans, and seat type. + +### 6) 🧹 Remove or revoke access + +Clear stored authentication, remove local configuration, then revoke the provider grant when one exists. -1. For MCP, confirm the tools appear in the assistant. -2. For a CLI, run a read-only identity command. +1. Clear authentication before removing the server entry. +2. Remove the server or plugin from the client. +3. For Figma, open [**Settings > Security > Connected apps**](https://help.figma.com/hc/en-us/articles/15021280611607-How-do-I-keep-my-account-secure) and select **Revoke access**. + +| Client | Clear authentication | Remove local configuration | +| --- | --- | --- | +| Claude Code | Run `/mcp`, select Figma, then **Clear authentication** | Plugin: `claude plugin uninstall figma@claude-plugins-official`; manual project server: `claude mcp remove --scope project figma` | +| Codex | Manual server: `codex mcp logout figma` | Plugin: remove Figma in the Codex app's **Plugins** panel; manual server: `codex mcp remove figma` | +| Cursor | Disconnect Figma under **Settings > Cursor Settings > Tools & MCP** | Remove the Figma plugin or its manual `.cursor/mcp.json` entry | +| GitHub Copilot in VS Code | Select the server through **MCP: List Servers** | Uninstall the server or remove its `.vscode/mcp.json` entry | ```bash -$ gh auth status -github.com - ✓ Logged in to github.com account octocat +codex mcp logout figma +codex mcp remove figma ``` + +Removing configuration alone does not prove that the OAuth grant was revoked. + +## Verify + +- The server appears in the chosen client's server list with the expected transport and scope. +- Authentication uses the intended account and workspace. +- Only the required tools are enabled; mutating calls require confirmation or are disabled. +- Figma `whoami` returns the intended identity. +- Authentication clearing, local removal, and provider revocation are separate and documented. diff --git a/plugins/aidd-context/skills/12-cook/assets/recipes/token-optimization.md b/plugins/aidd-context/skills/12-cook/assets/recipes/token-optimization.md index 67c096fa9..4709ed1be 100644 --- a/plugins/aidd-context/skills/12-cook/assets/recipes/token-optimization.md +++ b/plugins/aidd-context/skills/12-cook/assets/recipes/token-optimization.md @@ -1,277 +1,339 @@ -# Token optimization for AI IDEs +# Token optimization across coding agents + +Cut token usage across coding agents without confusing general techniques with Claude Code or Codex commands. + +- [Token optimization across coding agents](#token-optimization-across-coding-agents) + - [Why](#why) + - [Steps to cut token usage](#steps-to-cut-token-usage) + - [🟢 Beginner](#-beginner) + - [1) 📏 Record a before-and-after baseline](#1--record-a-before-and-after-baseline) + - [2) 🔎 Inspect Claude's context breakdown](#2--inspect-claudes-context-breakdown) + - [3) ✂️ Trim persistent instructions](#3-️-trim-persistent-instructions) + - [4) 🧭 Plan before expensive rework](#4--plan-before-expensive-rework) + - [5) ♻️ Reset between unrelated tasks](#5-️-reset-between-unrelated-tasks) + - [6) 🗜️ Compact at a natural boundary](#6-️-compact-at-a-natural-boundary) + - [🟡 Intermediate](#-intermediate) + - [7) 📈 Export structured usage telemetry](#7--export-structured-usage-telemetry) + - [8) 🗣️ Make concise output explicit](#8-️-make-concise-output-explicit) + - [9) 🧹 Filter noisy shell output selectively](#9--filter-noisy-shell-output-selectively) + - [10) 🔌 Limit MCP exposure by client](#10--limit-mcp-exposure-by-client) + - [🔴 Expert](#-expert) + - [11) 🔬 Inspect client behavior without mixing shortcuts](#11--inspect-client-behavior-without-mixing-shortcuts) + - [12) 🎯 Route model and reasoning by difficulty](#12--route-model-and-reasoning-by-difficulty) + - [13) 🧫 Isolate noisy work with subagents](#13--isolate-noisy-work-with-subagents) + - [14) 🧊 Protect Claude Code prompt-cache stability](#14--protect-claude-code-prompt-cache-stability) + - [In short](#in-short) + +## Why + +**Token usage** grows with persistent instructions, conversation history, tool output, and reasoning. + +**Command names are not portable contracts**: `/usage`, `/compact`, `/model`, and keyboard shortcuts can differ across clients. + +**Applicability labels** separate portable techniques from verified Claude Code and Codex mechanics. No command is labeled as universal. -Cut token usage and cost in AI coding assistants without losing output quality. +## Steps to cut token usage -## Why optimize your tokens +### 🟢 Beginner -**Token usage** is the bill — every turn re-sends your whole **context window** and you pay for it again. +#### 1) 📏 Record a before-and-after baseline -Most of it is **waste**: filler prose, noisy logs, stale context, bloated instruction files. +**Applies to:** Claude Code and Codex; their counters differ. -Reach for this recipe when **cost** climbs faster than your output. +1. Run the same task with the same model and reasoning level before and after one optimization, then record the command result and quality gate. -## Steps to cut token usage +| Client | Command | Record | +| --- | --- | --- | +| Claude Code | `/usage` | Session usage and available breakdowns | +| Codex | `/status` | Context usage under the current chat configuration | -### 🟢 Beginner +Compare only within the same client. See [Claude Code costs](https://code.claude.com/docs/en/costs) and [Codex commands](https://learn.chatgpt.com/docs/developer-commands?surface=cli). -#### 1) 🔎 See what fills the window — `/context` +#### 2) 🔎 Inspect Claude's context breakdown -`/context` paints your context as a grid, so you cut the biggest consumers instead of guessing. +**Applies to:** Claude Code. Codex has no equivalent component grid. -1. Run `/context` in Claude Code. -2. Find the heavy blocks: tool schemas, instruction files, long file reads. -3. Attack the biggest block first. +1. Run `/context all` only when the baseline shows context pressure. ```text -$ /context - MCP tool schemas ████████████ 28% ← biggest, cut first - file reads ████████ 19% - CLAUDE.md ████ 9% -(illustrative — replace with a screenshot of your real /context) +/context all ``` -#### 2) 💸 Read the bill — `/cost` +Target the largest persistent instruction, tool, or history source before compacting. -`/cost` tells you what a session actually costs and where the spend goes. +#### 3) ✂️ Trim persistent instructions -1. Run `/cost` (alias `/usage`). -2. Read the breakdown by skill, subagent, and MCP server. -3. Re-run it after a change to confirm the spend really dropped. +**Applies to:** All coding agents; the instruction file is client-specific. -```text -$ /cost - Session: $0.42 · 1.2M tokens - By: subagents 38% · MCP 21% · main 41% -(illustrative — replace with a screenshot of your real /cost) -``` +Keep only durable rules in the file that loads for every task, and move specialized procedures to on-demand skills or referenced documents. -#### 3) 🔍 Find your bad habits — `/insights` +1. Open only the persistent instruction file documented by your client. +2. Remove duplicated architecture prose, one-off task details, and commands the agent can discover safely. +3. Keep completion criteria, constraints, and the canonical validation commands. -`/insights` analyses how you prompt — probably sub-optimal — so you fix the pattern, not one prompt. What you repeat every session belongs in the knowledge base, and the counter-intuitive habits you never noticed get surfaced so you can drop them. +| Client | Native persistent instructions | +| --- | --- | +| Claude Code | `CLAUDE.md` | +| Codex | `AGENTS.md` or the closer `AGENTS.override.md` | +| Other clients | Use only the filename and precedence documented by that client | -1. Run `/insights`. -2. Move what you repeat into `CLAUDE.md` or a rule, and drop the habits it flags. +```md +# Persistent instructions -```text -$ /insights - • You restate the test command in ~60% of sessions → put it in CLAUDE.md - • Long "summary" turns inflate output → ask for terse replies -(illustrative — replace with a screenshot of your real /insights) +- Lead with the result. +- Run the smallest relevant validation. +- Preserve unrelated user changes. ``` -#### 4) 📈 Track per-prompt with an analytics tool - -Built-ins show one session; an analytics tool reads all your local logs and reveals where the bill truly sits. The lesson it surfaces: **cache reads dwarf input + output**, so caching, not generation, is most of the bill. +See [Claude Code memory](https://code.claude.com/docs/en/memory) and [Codex AGENTS.md](https://learn.chatgpt.com/docs/agent-configuration/agents-md). -1. Pick one: [`prompt-analytics-for-claude-code`](https://github.com/romainfjgaspard/prompt-analytics-for-claude-code) or [`ccusage`](https://www.npmjs.com/package/ccusage). -2. Run it — `uvx --from prompt-analytics-for-claude-code prompt-analytics summary` — no setup, it parses `~/.claude`. +#### 4) 🧭 Plan before expensive rework -![prompt-analytics dashboard — cost by token type shows cache reads dominate the bill](https://raw.githubusercontent.com/romainfjgaspard/prompt-analytics-for-claude-code/main/docs/screenshots/dashboard-home.png) +**Applies to:** All coding agents as a technique; commands are client-specific. -#### 5) ✂️ Trim your instruction file +Plan first when ambiguity or implementation risk makes a wrong direction expensive. -Your instruction file ships every turn, so each cut line saves on every message. +1. Enter the documented plan surface for your client. +2. Review scope, assumptions, and validation before authorizing implementation. +3. Use a separate read-only permission or sandbox setting when planning must prohibit writes; plan mode alone is not a universal security boundary. -1. Open `CLAUDE.md` (or `.github/copilot-instructions.md`). -2. Cut it to essentials and add explicit conciseness rules. -3. Model it on a real concise instruction file: [AGENTS.md](../../../02-project-memory/assets/AGENTS.md). +| Client | Plan command | +| --- | --- | +| Claude Code | `/plan` or launch with `claude --permission-mode plan` | +| Codex | `/plan`; the command can include the first planning prompt | +| Other clients | Ask for a plan explicitly; use only a documented plan mode if one exists | -```md -# CLAUDE.md — keep it terse (see AGENTS.md for the full example) -- Answer first. Lead with the result, then the reason. Drop pleasantries and hedging. -- No tool-call narration. No decorative tables or emoji unless they carry information. -- Keep verbatim: code, quoted errors, security warnings. Cut the rest. +```text +/plan Propose the smallest implementation and its validation before editing ``` -#### 6) 🧭 Plan before you edit — plan mode +See [Claude Code permission modes](https://code.claude.com/docs/en/permission-modes) and [Codex best practices](https://learn.chatgpt.com/guides/best-practices). -Approving the wrong direction burns tokens on rework, so let Claude explore read-only and propose a plan first. +#### 5) ♻️ Reset between unrelated tasks -1. Press `Shift+Tab` twice to enter plan mode (or start with `claude --permission-mode plan`). -2. Review the plan, then approve to switch to execution. +**Applies to:** All coding agents as a technique; slash commands are verified only for the named clients. -```text -Shift+Tab Shift+Tab → ⏸ plan mode - Claude reads and proposes; no edits until you approve -``` - -See [permission modes](https://code.claude.com/docs/en/permission-modes). - -#### 7) ♻️ Clear context between tasks — `/clear` +Start a fresh conversation when the goal changes instead of paying repeatedly for stale turns. -Stale early turns ride along and get re-billed every turn, so reset when the task changes. +1. Preserve any durable decision outside the disposable transcript. +2. Reset with the client-native action. -1. Finish a task, then run `/clear` to drop the history and reload only `CLAUDE.md` and memory. -2. Use `/compact` instead when you want to keep a summary of the same task. +| Client | Fresh-context action | +| --- | --- | +| Claude Code | `/clear` | +| Codex CLI | `/clear` clears the terminal and starts a fresh chat; `/new` starts another chat without clearing the display | +| Other clients | Start a new conversation through the documented UI | ```text -$ /clear - history dropped → fresh window, CLAUDE.md + memory reloaded +Claude Code: /clear +Codex: /new ``` -See [reduce token usage](https://code.claude.com/docs/en/costs). +#### 6) 🗜️ Compact at a natural boundary -#### 8) 🗜️ Compact deliberately +**Applies to:** Claude Code and Codex; argument syntax differs. -Compacting on your terms keeps what matters instead of letting auto-compaction guess. +Compact only when the same task still needs its earlier decisions and the context pressure justifies a summary. -1. Watch context use and act around 60–70%. -2. Run `/compact` with focus instructions naming what to keep. +1. Preserve the current goal, accepted decisions, failing evidence, and next validation. +2. Use only the syntax documented by your client. + +| Client | Compact action | +| --- | --- | +| Claude Code | `/compact keep the accepted decisions, repro, and failing test` | +| Codex | `/compact`; no inline focus argument is documented | ```text -$ /compact keep the repro steps and the failing test; drop the file dumps +Claude Code: /compact keep the repro and failing test; drop file dumps +Codex: /compact ``` +See [Claude Code commands](https://code.claude.com/docs/en/commands) and [Codex commands](https://learn.chatgpt.com/docs/developer-commands?surface=cli). + ### 🟡 Intermediate -#### 9) 🗣️ Make the agent talk less +#### 7) 📈 Export structured usage telemetry -Output is repetition you pay to generate, so cap the chatter. caveman forces short, filler-free replies (reported ~65% output cut, code intact) and auto-detects 30+ agents. +**Applies to:** Claude Code and Codex; their configuration and telemetry schemas differ. -1. Built-in route: set `"outputStyle": "concise"` in `settings.json`. -2. Harder cut: install the [`caveman`](https://github.com/JuliusBrussee/caveman) skill and invoke it like any skill — `/caveman` (or `/caveman ultra`); stop with "normal mode". +Use your own OpenTelemetry collector when interactive usage commands are not enough for comparisons across sessions. -```text -/caveman +1. Enable the exporter for the selected client. +2. Keep prompt and tool content redacted unless an explicit audit requirement justifies collecting it. +3. Compare token types, model, agent, and tool output; treat cost attribution as an estimate unless it comes from the billing system. -before: The reason your React component is re-rendering is likely because you're creating a new object reference on each render cycle. When you pass an inline object as a prop, React's shallow comparison sees it as a different object every time, which triggers a re-render. I'd recommend using useMemo to memoize the object. +Claude Code metrics export: -after: New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`. +```bash +CLAUDE_CODE_ENABLE_TELEMETRY=1 \ +OTEL_METRICS_EXPORTER=otlp \ +OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics \ +OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf \ +claude ``` -See [output styles](https://code.claude.com/docs/en/output-styles). +Codex log export in `config.toml`: -#### 10) 🧹 Filter noisy command output +```toml +[otel] +environment = "dev" +log_user_prompt = false -Test, install, and build logs flood context with lines the model never needs. +[otel.exporter."otlp-http"] +endpoint = "http://localhost:4318/v1/logs" +protocol = "binary" +``` -1. Install a CLI proxy: [`RTK`](https://github.com/rtk-ai/rtk) (Rust) or [`SNIP`](https://github.com/edouard-claude/snip) (Go, YAML filters). -2. Prefix your command with it: `rtk cargo test`. +Claude Code exports metrics such as `claude_code.token.usage`; Codex emits its own events and token fields. Do not query one client's schema under the other's names. -```mermaid -flowchart LR - A["rtk cargo test"] --> R[RTK proxy] - R --> C["cargo test runs"] - C -->|"~25,000 tokens"| R - R -->|"filter · group · dedupe"| M["~2,500 tokens to model"] -``` +See [Claude Code monitoring](https://code.claude.com/docs/en/monitoring-usage) and [Codex observability](https://learn.chatgpt.com/docs/config-file/config-advanced#observability-and-telemetry). + +#### 8) 🗣️ Make concise output explicit -Real saving: `git push` (15 lines, ~200 tokens) -> `rtk git push` (1 line, ~10 tokens). +**Applies to:** All coding agents as an instruction; persistent mechanisms are client-specific. -#### 11) 🚫 Keep big paths out of context — deny reads +Short answers reduce output tokens only when the instruction does not sacrifice required evidence. -Vendor dirs, build output, and secrets get pulled into context by accident. Deny reads on them so they stay out — they remain grep-able. +1. Add one concise rule to the client-native instruction surface. +2. Use the client-specific output control only when its documented scope matches the goal. -1. In `settings.json`, add `Read(...)` deny rules for large or sensitive paths. -2. `.claudeignore` is not shipped — deny rules are the official way. +| Client | Persistent mechanism | +| --- | --- | +| Claude Code | A short custom file under `.claude/output-styles/`, selected through `/config` | +| Codex | `model_verbosity = "low"` for supported Responses API models, plus a short rule in `AGENTS.md` | +| Other clients | A documented response-style setting or persistent instruction | -```json -{ - "permissions": { - "deny": ["Read(./vendor/**)", "Read(./dist/**)", "Read(./.env)"] - } -} +```text +Answer directly. Preserve code, decisive errors, evidence, and security warnings; omit filler. ``` -See [permissions](https://code.claude.com/docs/en/permissions). +`model_reasoning_summary = "concise"` in Codex shortens the reasoning summary, not the final answer. See [Claude Code output styles](https://code.claude.com/docs/en/output-styles) and [Codex configuration](https://learn.chatgpt.com/docs/config-file/config-reference). -#### 12) 🔌 Prefer CLI over MCP +#### 9) 🧹 Filter noisy shell output selectively -An MCP server's schema rides along every turn; a CLI costs tokens only when you call it. Newer MCP tooling adds tool/context selection that loads only the tools you pick — cheaper than before — but a CLI is still leaner and faster. +**Applies to:** Shell-capable coding agents; RTK and SNIP are third-party tools. -| | CLI (`gh`, `acli`, …) | MCP server | -| --- | --- | --- | -| Token cost | a few, only when called | a schema every turn; less with tool/context selection | -| Speed | fastest | slower | -| Use when | a CLI exists | no CLI, or you need typed/live tool calls | +Reduce model-visible logs only when filtering cannot hide evidence needed for diagnosis. -See [`mcp-installation.md`](mcp-installation.md). +1. Prefer a command's native `--quiet`, `--json`, filtering, or targeted-test option. +2. If that is insufficient, inspect and install a proxy such as [`RTK`](https://github.com/rtk-ai/rtk) or [`SNIP`](https://github.com/edouard-claude/snip). +3. Prefix only materially noisy commands and rerun the raw command when the filtered result is incomplete. -### 🔴 Expert +```bash +rtk cargo test +``` -#### 13) 🔬 Audit which skills and tools run — `Ctrl+O` +Published reduction figures measure model-visible command output, not independently verified billing savings. Never filter the first security failure or the only copy of a diagnostic log. -You optimise what you can see, so expand the transcript to watch what each turn actually invokes and pulls into context. +#### 10) 🔌 Limit MCP exposure by client -1. Press `Ctrl+O` to toggle the transcript — it shows detailed tool and skill usage and expands collapsed MCP calls. -2. Spot skills or tools that load on turns that don't need them, then scope or remove them. +**Applies to:** MCP-capable agents; deferral behavior is client-specific. -```text -Ctrl+O — transcript expanded - ⎿ Skill: token-optimization - ⎿ Called slack 3 times → expanded: 3 tool calls -(illustrative — replace with a screenshot of your real Ctrl+O transcript) +Disable unused servers and expose only required tools without assuming every MCP client has Claude Code Tool Search. + +1. Inventory enabled servers and tools. +2. Apply only controls documented by the selected client. + +| Client | Documented control | +| --- | --- | +| Claude Code | Tool Search defers MCP tool schemas on supported models and providers; avoid `alwaysLoad` unless a small toolset is needed on nearly every turn | +| Codex | Inspect with `/mcp verbose`; disable an unused server with `enabled = false`, or restrict it with `enabled_tools` and `disabled_tools` | +| Other clients | Disable unused servers or tools through their documented configuration; do not assume schema deferral | + +```toml +[mcp_servers.figma] +url = "https://mcp.figma.com/mcp" +enabled = false ``` -See the [keyboard shortcuts](https://code.claude.com/docs/en/interactive-mode). +Codex exposes no public stable setting equivalent to Claude Code's `alwaysLoad`. See [Claude Code MCP](https://code.claude.com/docs/en/mcp#scale-with-mcp-tool-search), [Codex MCP](https://learn.chatgpt.com/docs/extend/mcp?surface=cli), and [`mcp-installation.md`](mcp-installation.md). + +### 🔴 Expert -#### 14) 🎯 Route by difficulty +#### 11) 🔬 Inspect client behavior without mixing shortcuts -The top model on routine work is wasted spend, so pin the model per skill or agent — cheap for routine, top-tier for hard reasoning. +**Applies to:** Claude Code for the commands below; Codex has no documented `/insights` equivalent. -1. Set `model` in a skill's or an agent's frontmatter (`haiku` / `sonnet` / `opus`, a full id, or `inherit`). -2. Give routine scouts a small model; reserve `opus` for the hard reasoning. +Use client-native diagnostics instead of copying shortcuts between products. -```yaml -# .claude/agents/explore.md — routine scouting on a cheap model ---- -name: explore -description: Read-only codebase scout -tools: Read, Grep, Glob -model: haiku ---- +1. In Claude Code, run `/insights` for a session-pattern report. +2. In Claude Code, press `Ctrl+O` to expand the detailed transcript. +3. In Codex, use OTel or the visible transcript for analysis; do not use `Ctrl+O` as a Claude-style transcript toggle. + +```text +Claude Code: /insights +Claude Code: Ctrl+O ``` -A skill's `SKILL.md` takes the same `model:` field (e.g. `model: opus` for a heavy step). See [sub-agents](https://code.claude.com/docs/en/sub-agents) and [skills](https://code.claude.com/docs/en/skills). +In Codex CLI, `Ctrl+O` copies the latest completed response. The experimental `codex debug prompt-input [PROMPT]` command renders model-visible prompt inputs as JSON, but it is not an `/insights` replacement. + +#### 12) 🎯 Route model and reasoning by difficulty + +**Applies to:** Claude Code and Codex; configuration formats and command semantics differ. -#### 15) 🧫 Offload high-volume work to subagents +Use the lowest model and reasoning level that passes a representative task, then raise them only for risk or complexity. -Test runs, log parsing, and wide exploration flood the main window. A subagent does it in its own context and hands back only a summary, so the bloat never lands in your session. +1. Route routine exploration separately from difficult implementation or review. +2. Use the configuration native to each client. -1. Define an agent in `.claude/agents/.md` with only the tools it needs and a small `model`. -2. Let it run the noisy op and return a short result. +| Client | Session control | Agent configuration | +| --- | --- | --- | +| Claude Code | `/model` and `/effort low` | `.claude/agents/*.md` or skill frontmatter with `model` and `effort` | +| Codex | `/model` and `/reasoning` | `.codex/agents/*.toml` with `model` and `model_reasoning_effort` | + +Claude Code agent frontmatter: ```yaml -# .claude/agents/test-runner.md --- -name: test-runner -description: Run the suite and return only the failures -tools: Bash, Read model: haiku +effort: low --- ``` -See [sub-agents](https://code.claude.com/docs/en/sub-agents). +Codex project agent: + +```toml +name = "explorer" +description = "Read-only codebase scout" +model = "gpt-5.6-terra" +model_reasoning_effort = "low" +``` + +Codex skills do not use Claude Code's `model` and `effort` frontmatter. See [Claude Code model configuration](https://code.claude.com/docs/en/model-config) and [Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents). + +#### 13) 🧫 Isolate noisy work with subagents -#### 16) 🧊 Protect your cache hits +**Applies to:** Coding agents with documented subagent support; configuration is client-specific. -Cached input bills far cheaper, and cache reads are most of your tokens (step 4) — so don't throw the cache away mid-task. A model switch, an MCP connect or disconnect, or an effort change rebuilds it from scratch. +Use subagents for context isolation, parallelism, or specialist quality, not as an assumed reduction in total tokens. -1. Set the model and reasoning effort at the start of a task, not mid-work. -2. Switch model or toggle MCP servers only at task boundaries, where a cache rebuild is acceptable. +1. Delegate high-volume exploration, test logs, or independent review. +2. Ask for a short result containing only findings, evidence, and blockers. +3. Keep tightly coupled edits in one agent to avoid coordination overhead. ```text -mid-task model switch → cache invalidated → full re-bill -same model to a boundary → cache reads stay cheap +Delegate the test run to one subagent. Return only failing tests, the shortest decisive error, and the command used. ``` -See [prompt caching](https://code.claude.com/docs/en/prompt-caching). +Both Claude Code and Codex give subagents separate working context, but their own model calls still consume tokens and can increase total usage. See [Claude Code subagents](https://code.claude.com/docs/en/sub-agents) and [Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents). -#### 17) ✅ Cap extended thinking +#### 14) 🧊 Protect Claude Code prompt-cache stability -Extended reasoning can silently add thousands of tokens on tasks that don't need it. +**Applies to:** Claude Code. No equivalent user-facing Codex cache-invalidation contract is documented here. -1. In `settings.json`, set `MAX_THINKING_TOKENS` to `0` for routine work. -2. See the [Claude Code settings docs](https://code.claude.com/docs/en/settings). +Keep the request prefix stable during one task so prompt caching can reuse it. -```json -{ - "env": { - "MAX_THINKING_TOKENS": "0" - } -} +1. Choose the model and effort before the first substantive prompt. +2. Change them mid-task only when the quality gain justifies a cache miss. +3. Keep MCP tools deferred; a change to tools loaded into the prefix can invalidate that layer. + +```text +/model sonnet +/effort medium ``` +For Codex, prompt caching is service-managed rather than a documented `config.toml` control; observe `cached_input` through Codex telemetry instead of transposing Claude settings. See [Claude Code prompt caching](https://code.claude.com/docs/en/prompt-caching) and [Codex observability](https://learn.chatgpt.com/docs/config-file/config-advanced#observability-and-telemetry). + ## In short -Measure first, then stack the cheap wins — trimmed instructions, plan mode, a clean context, less chatter, filtered output — before the advanced routing, subagents, and cache discipline. Most of the bill is cache and repetition; cut those and the cost follows. +Measure first, label every command by client, then reduce persistent instructions, stale history, noisy output, unnecessary tools, and excessive reasoning without hiding evidence or weakening quality. diff --git a/plugins/aidd-context/skills/12-cook/references/recipe-contract.md b/plugins/aidd-context/skills/12-cook/references/recipe-contract.md index f06f1bf0b..36cc62827 100644 --- a/plugins/aidd-context/skills/12-cook/references/recipe-contract.md +++ b/plugins/aidd-context/skills/12-cook/references/recipe-contract.md @@ -20,13 +20,14 @@ Rules for every recipe file the skill writes. ## Steps - The steps section heading is named after the goal: `## Steps to `, never a bare `## Steps`. +- Heading levels express nesting. Never skip a level: a heading may be at most one level deeper than the heading before it. - One step = one action: never bundle several tools or commands under one heading; split them. -- Each step is a `#### N) Title` heading, then one benefit-focused line of what and why in prose. Number steps continuously. +- A step directly under the steps section is a `### N) Title` heading. A step grouped under a `###` category is a `#### N) Title` heading. Number steps continuously. - Write the actions to take as a numbered list; write any description or indication as prose, never as a bullet. - For a tool: where it is, install it from its URL, then how to invoke it (its real command or slash invocation, e.g. `/caveman`). - Reuse the tool's canonical example captured verbatim from its site or README — never a paraphrase, and never on the strength of a summary that says one exists. - Every step carries one concrete example. Prefer an image — a screenshot or short video/GIF that matches the action — over text whenever one exists; for a tool, use its official screenshot. Otherwise: a command with its real output, a config in the file's real syntax (valid JSON for `settings.json`, valid YAML for frontmatter, …), or a snippet. - A step that prefers one option over another uses a comparison table, not prose. - For a structural or flow concept (a proxy, a pipeline, an architecture), add a small Mermaid diagram with concrete example values. -- Level subheadings are optional. Group steps under `### 🟢 Beginner`, `### 🟡 Intermediate`, `### 🔴 Expert` only when the recipe spans difficulty levels and grouping helps the reader; a short or single-level recipe lists its steps directly. Include only the levels that have a step. +- Level subheadings are optional. Group steps under `### 🟢 Beginner`, `### 🟡 Intermediate`, `### 🔴 Expert` only when the recipe spans difficulty levels and grouping helps the reader; their steps use `####`. A short or single-level recipe lists its steps directly with `###`. Include only the levels that have a step. - Link to a reference when applicable.