diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ccc80e2a2..c8deef42b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -31,15 +31,15 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Initialize CodeQL - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: languages: ${{ matrix.language }} queries: security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/autobuild@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: category: "/language:${{ matrix.language }}" diff --git a/AGENTS.md b/AGENTS.md index bb7c43dbd..052aded9d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,7 +38,8 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. ### Project memory - + + @aidd_docs/memory/architecture.md @aidd_docs/memory/browsing.md @aidd_docs/memory/codebase-map.md @@ -47,7 +48,8 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. @aidd_docs/memory/project-brief.md @aidd_docs/memory/testing.md @aidd_docs/memory/vcs.md - + + - If the block above is empty, run `ls -1tr aidd_docs/memory/` and read each file. - Load `aidd_docs/memory/external/*` when the user asks. diff --git a/CLAUDE.md b/CLAUDE.md index 0a8d13084..a61cf56d6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,7 +38,8 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. ### Project memory - + + @aidd_docs/memory/architecture.md @aidd_docs/memory/browsing.md @aidd_docs/memory/codebase-map.md @@ -47,7 +48,8 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. @aidd_docs/memory/project-brief.md @aidd_docs/memory/testing.md @aidd_docs/memory/vcs.md - + + - If the block above is empty, run `ls -1tr aidd_docs/memory/` and read each file. - Load `aidd_docs/memory/external/*` when the user asks. diff --git a/README.md b/README.md index d08a2c210..b286b4623 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,24 @@ AIDD -# The AI-Driven Dev Framework πŸ‡«πŸ‡· +# AI-Driven Dev Framework -`Open source` agnostic framework **to generate high quality clean code**. +## Enterprise-grade SDLC for high-quality software development. -_(Already tested on `Legacy` codebases)_ +Unify **engineering teams** around **standardized workflows** and **shared best practices**, across modern stacks and **legacy systems**, while reducing **technical debt**. -[![Made in France](https://img.shields.io/badge/made%20in-France-0055A4?labelColor=EF4135)](https://www.ai-driven-dev.fr/) +🧱 **IDE agnostic** Β· πŸ—οΈ **Legacy systems** Β· 🌱 **Token-optimized** Β· πŸ‡«πŸ‡· **Made in France**

- 7 plugins Β· 47 skills Β· 2 agents Β· MIT + 7 plugins Β· 47 skills Β· 2 agents

-[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +[![Open Source](https://img.shields.io/badge/Open_Source-Yes-yellow?logo=open-source-initiative&logoColor=white)](https://opensource.org/) +[![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](LICENSE) [![Latest Release](https://img.shields.io/github/v/release/ai-driven-dev/framework?include_prereleases&sort=semver)](https://github.com/ai-driven-dev/framework/releases) [![CI](https://github.com/ai-driven-dev/framework/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ai-driven-dev/framework/actions/workflows/ci.yml) +

πŸ—ΊοΈ Live roadmap

@@ -195,18 +197,36 @@ flowchart TD end subgraph loop["β‘‘ Per feature β€” repeat"] - direction LR - B["brainstorm"] --> P["plan"] --> I["implement"] --> R["review"] --> C["commit"] --> PR(["βœ… PR"]) + direction TB + subgraph frame["Frame"] + direction LR + N["functional need
or User Story"] --> T["issue / ticket"] --> P["plan"] + end + subgraph deliver["Deliver"] + direction LR + I["implement"] --> V["validate"] --> R["review"] + end + subgraph ship["Ship"] + direction LR + PR["PR"] --> S(["βœ… production"]) --> L["learn"] + end + P --> I + R --> PR end - Onboard --> Memory --> B + Onboard --> Memory --> N + L -. next need .-> N classDef hub fill:#D97757,stroke:#9c4f37,color:#fff; classDef done fill:#2ea043,stroke:#1a7f37,color:#fff; class Onboard hub; - class PR done; + class S done; ``` +Start with a functional need or User Story, then track it as an issue or ticket +before planning. Shipping follows the project's own delivery process. Capture a +learning only when it is durable enough to improve the next feature. + > 🍳 **More flows** β†’ bundled recipes: [start a project](plugins/aidd-context/skills/12-cook/assets/recipes/start-a-project.md), [ship a feature](plugins/aidd-context/skills/12-cook/assets/recipes/ship-a-feature.md), and more. ## 🧩 Plugins diff --git a/aidd_docs/CONTRIBUTING.md b/aidd_docs/CONTRIBUTING.md index 7f3c59870..2b0c79b38 100644 --- a/aidd_docs/CONTRIBUTING.md +++ b/aidd_docs/CONTRIBUTING.md @@ -26,7 +26,7 @@ The skill contract itself lives in one file: `aidd-context:04-skill-generate/ref ## Syncing Across Tools -If the project uses multiple AI tools (e.g. Claude Code plus Cursor), the same content must be available to each. The memory bank is shared automatically via the `` block kept in sync by `aidd-context:02-project-memory`. Skills are loaded per-plugin by the runtime, so any skill installed via the marketplace is available across tools that support skills. +If the project uses multiple AI tools (e.g. Claude Code plus Cursor), the same content must be available to each. The memory bank is shared automatically via the project memory block kept in sync by `aidd-context:02-project-memory`. Skills are loaded per-plugin by the runtime, so any skill installed via the marketplace is available across tools that support skills. When tools differ in syntax (frontmatter, slash command name, references), follow the IDE mapping reference shipped with each plugin. diff --git a/aidd_docs/README.md b/aidd_docs/README.md index 2f6c32ac7..0d6bb246a 100644 --- a/aidd_docs/README.md +++ b/aidd_docs/README.md @@ -84,7 +84,7 @@ my-project/ ### Memory Block Lifecycle -Each AI context file (`CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`, etc.) contains an `` block. It is: +Each AI context file (`CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`, etc.) contains a project memory block. It is: 1. **Seeded** the first time by `aidd-context:02-project-memory` (the skill creates the block if absent). 2. **Kept in sync** automatically by a session-start hook (`aidd-context/hooks/update_memory.js`) that scans `aidd_docs/memory/` and writes the current list of `.md` files into the block. diff --git a/aidd_docs/tasks/2026_08/2026_08_28_memory-block-markers/brainstorm.md b/aidd_docs/tasks/2026_08/2026_08_28_memory-block-markers/brainstorm.md new file mode 100644 index 000000000..b03a4fede --- /dev/null +++ b/aidd_docs/tasks/2026_08/2026_08_28_memory-block-markers/brainstorm.md @@ -0,0 +1,26 @@ +# Memory block markers that cannot silently stop loading + +The `` block that `update_memory.js` writes into every AI context file is delimited by a bare XML-style tag on its own line. Markdown treats that as an HTML block running until the next blank line, and Claude Code's import parser skips imports inside it exactly as it skips a fenced code block. Every `@aidd_docs/memory/*.md` line the hook generates is therefore ignored, and the project memory never loads. The failure is invisible from inside a session: the agent starts, nothing is reported, and it simply reasons without the memory bank. + +The fix is to stop delimiting the block with a construct whose correctness depends on an adjacent blank line, and use HTML comment markers instead. A comment closes on its own line, so nothing following it can ever be captured, whatever a formatter or a future rewrite does to the surrounding whitespace. The same hook already uses that convention for the memory README index. Existing installed repositories carry the old tag, so the change is only complete if the hook migrates them; otherwise the fix ships and those repositories stay dark while the changelog claims otherwise. + +## What Is Clear + +- Reported in issue #719 and confirmed independently: `CLAUDE.md:41-50` in this repository holds the glued shape, and a session loading it shows the `@` lines unexpanded, with eight memory files absent. +- Single emitter: `buildBlockContent` in `plugins/aidd-context/hooks/update_memory.js`. `updateMarkers` splices between two constant strings and needs no change when those strings change. +- The bug is the tag shape, not the content. `buildBlockContent` already pushes a blank line before the on-demand note, so that blank line terminates the HTML block and the on-demand list renders correctly. Only the `@` lines above it are swallowed. That asymmetry is the signature. +- Chosen shape: the existing `### Project memory` heading for human readers, with `` and `` as the machine anchors. The heading is prose the hook does not own; the markers stay the anchor. +- Rejected: adding a blank line after the opening tag. It is one character and needs no migration, but it is a load-bearing convention nothing in the file declares, and a rewrite already reverted it once. +- Migration is part of the fix, not a follow-up. The hook returns `null` when the close marker is absent and skips the file with no output, so every already-installed repository would silently stop syncing. +- The tag name is load-bearing beyond the hook and those references move with it: `plugins/aidd-context/skills/00-onboard/references/state/zones.md`, `plugins/aidd-context/skills/11-explore/actions/01-survey.md`, and the `02-project-memory` templates for `AGENTS.md`, `README.md`, and `memory/README.md`. +- A regression guard stays in scope: walk a context file line by line, track whether a line opens an HTML block, and fail when an `@` import is found inside one. Comment markers make this specific regression near-impossible, but the guard covers hand-written context files and future generators. +- Out of scope, its own ticket: generating a `CLAUDE.md` that contains `@AGENTS.md` for repositories that only have `AGENTS.md`. It adds a capability rather than fixing a defect, and it drags in the separate question of which context files the project owns. + +## Still Open + +- Assumption, unverified: the XML tag currently buys nothing the model uses. Whether the wrapper survives import resolution into the prompt in a form the model reads has not been checked. If it does, the heading in the chosen shape is the replacement cue. +- Whether the CLI test fixtures under `cli/tests/fixtures/**` that embed the old tag should be migrated with the rest or left pinned to the legacy shape as regression material. + +## Next Move + +Turn this into a change: new markers in the hook, a one-pass rewrite of the legacy tag before the splice, the template and documentation references moved to the new shape, and a check that fails when an import sits inside an HTML block. diff --git a/cli/CLAUDE.md b/cli/CLAUDE.md index 15f1b82e0..0d68bfa46 100644 --- a/cli/CLAUDE.md +++ b/cli/CLAUDE.md @@ -37,7 +37,8 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. ### Project memory - + + @aidd_docs/memory/architecture.md @aidd_docs/memory/auth.md @aidd_docs/memory/cli.md @@ -47,7 +48,11 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. @aidd_docs/memory/project-brief.md @aidd_docs/memory/testing.md @aidd_docs/memory/vcs.md - + + +- aidd_docs/memory/internal/decisions/self-update-version-source-npm.md + + - If the block above is empty, run `ls -1tr aidd_docs/memory/` and read each file. - Load `aidd_docs/memory/external/*` when the user asks. diff --git a/cli/aidd_docs/memory/README.md b/cli/aidd_docs/memory/README.md index e357c3020..1f6c50d72 100644 --- a/cli/aidd_docs/memory/README.md +++ b/cli/aidd_docs/memory/README.md @@ -4,7 +4,7 @@ Structured context the AI assistant reads at the start of a session, so it does ## How it loads -- The files at the root of `memory/` are referenced by the `` block in the AI context file and load every session. +- The files at the root of `memory/` are referenced by the project memory block in the AI context file and load every session. - `internal/` and `external/` are listed there too, but load on demand, only when relevant. ## Files @@ -21,6 +21,10 @@ The list below is refreshed automatically by the memory hook. Do not edit it by - [project-brief.md](project-brief.md) - [testing.md](testing.md) - [vcs.md](vcs.md) + +Read on demand: + +- [internal/decisions/self-update-version-source-npm.md](internal/decisions/self-update-version-source-npm.md) ## How to maintain it diff --git a/cli/pnpm-lock.yaml b/cli/pnpm-lock.yaml index 606d13454..4c87b453c 100644 --- a/cli/pnpm-lock.yaml +++ b/cli/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: dependencies: '@inquirer/prompts': specifier: ^8.5.2 - version: 8.5.2(@types/node@26.2.0) + version: 8.6.0(@types/node@26.2.0) ajv: specifier: ^8.20.0 version: 8.20.0 @@ -43,17 +43,17 @@ importers: version: 3.36.0 smol-toml: specifier: ^1.6.1 - version: 1.7.1 + version: 1.8.0 devDependencies: '@biomejs/biome': specifier: ^2.4.7 - version: 2.5.7 + version: 2.5.10 '@commitlint/cli': specifier: ^21.2.1 - version: 21.2.1(@types/node@26.2.0)(conventional-commits-parser@7.1.1)(typescript@7.0.2) + version: 21.2.2(@types/node@26.2.0)(conventional-commits-parser@7.1.2)(typescript@7.0.2) '@commitlint/config-conventional': specifier: ^21.2.0 - version: 21.2.0 + version: 21.2.2 '@stryker-mutator/core': specifier: ^9.6.1 version: 9.6.1(@types/node@26.2.0) @@ -77,10 +77,10 @@ importers: version: 4.0.0(@types/react@19.2.18) jscpd: specifier: ^5.0.0 - version: 5.0.14 + version: 5.0.16 knip: specifier: ^6.0.0 - version: 6.32.0 + version: 6.32.2 lefthook: specifier: ^2.1.10 version: 2.1.10 @@ -108,6 +108,10 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.29.3': resolution: {integrity: sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==} engines: {node: '>=6.9.0'} @@ -178,6 +182,10 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -261,55 +269,55 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@biomejs/biome@2.5.7': - resolution: {integrity: sha512-zr8K/DcY5tYsQOQwqMJ0AWElo6QgmgNI7idXgXLhevVszlt8RGVpesEJPqx3ThazLaOwjJ5Y8fz3BtH5fGZNsw==} + '@biomejs/biome@2.5.10': + resolution: {integrity: sha512-WRKXARA3kTuiV5sxqTpobJ/I0MVd4vk3pOL6wnp5az4LntFIhWTj1RWZq3DI9PCEN3lXcqy7p5aqUHzvq8AXyQ==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.5.7': - resolution: {integrity: sha512-vxo/Ls3/PYdQWyLhYYcgMOCzQypAjcY+iihS8M0wW03l16TCLW4zqZzGo75gm1VdCMj38hTVZ31KBWrZ4G9dJw==} + '@biomejs/cli-darwin-arm64@2.5.10': + resolution: {integrity: sha512-ItCrxKK6SXVT6flYs0qIuBd4AA3TTTl4d66Re6YI2FuGZnN85NmuYNzkiTJUyYw8qBLv69L5zTUB6uyWd++h3Q==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.5.7': - resolution: {integrity: sha512-Cd3Ga61amT/Yl/0x8elP5hhGYaFy4bw6WuysTgf7oo8TA5tJ5A1k+DkVoJ2BHbTVil51gTX9VPzArnrlLJ3Kyg==} + '@biomejs/cli-darwin-x64@2.5.10': + resolution: {integrity: sha512-yLsPU9pAmtChXDu8vhKAzErqe+LeeYuwuUB2FZMkRitsmdodxsYRa9KHrFispsUHzzOu+9HB3nP/TQxyia+Sjw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.5.7': - resolution: {integrity: sha512-xPI5yB6XlpDbNkS+bm1t42olw5c4l3UrlOmLg7KtLJvjvkNF/1V4tnUgfkylGIeb3u/T+BzMGYqgQhzjAoJzuQ==} + '@biomejs/cli-linux-arm64-musl@2.5.10': + resolution: {integrity: sha512-t1QAKZwQJRB4dvgJSgFiQ4BNfNPChg69BNonz854qLVxnjT3UvDzQg9mbkTJRu35ZqU0Rw10A73J8Urgbg2RPw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.5.7': - resolution: {integrity: sha512-rR2QE0yF2GYSuYuKIa7pKvODGJqnOH+2eDREAM8wV+mWKSkMQKdAp4zXEZfTaxY8PMoNONnpgSWcBCyLDPDOKg==} + '@biomejs/cli-linux-arm64@2.5.10': + resolution: {integrity: sha512-VG8uQW/86a1roLaIFvtIbEigxIdzdJ190oGyg1tV7VYeQtOS+x10sflk7WbuXgw91EtZX5DlIIIej1YqkNLlcg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.5.7': - resolution: {integrity: sha512-rE5VZi+qtmPgQH+l7jVxYoZ18b/TiHEhulhMpjmCZH1PltSbjRcxNWywC3HZ9tYottG7ORkeTtoscBilKSBm0g==} + '@biomejs/cli-linux-x64-musl@2.5.10': + resolution: {integrity: sha512-pgDDqp9JybHm2I0KRgzN6i4+lt8xu4iqxUwLzglUMmOmyRTU1AYBGKzh9sNMOtIjah7xoWvKHlLVetvyifzoiQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.5.7': - resolution: {integrity: sha512-FQgqJhscrqJUFptGaRSUJWlXAExwWcDwLuK49dvKfkQ1bB5SEEyFssnsxQY83Xm6jR0EbbX3+8+D5bfvYqUG2Q==} + '@biomejs/cli-linux-x64@2.5.10': + resolution: {integrity: sha512-4O6T0eq2heoHZN0a9UX+rWQoxXEBaKf+lRi2hbsGlHneUz9BWXM76nEWMK7Eeq8gzMxR1khQB6BFpAASpeXqGg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.5.7': - resolution: {integrity: sha512-Oq4x0CCwP4jirrcTywXs5kOGZ4v5vuEP+gWrbtjApOA2CL9F3F9GlIdQIci8AKSCa/zURanMRpX/4wQ7Am6hHg==} + '@biomejs/cli-win32-arm64@2.5.10': + resolution: {integrity: sha512-pxAbxduPO4xq/Cvgaa2lOrs9BB0hEXmmDqfMNP4ZOffGOkUrD1/QGw9UAMpFQpX2P8MqTIIRuQKcmetum4Oa6A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.5.7': - resolution: {integrity: sha512-V+0wu/nrj2S+MhP4EQ0uHNolP0IALEsz45pg0WoKkHfDeh0+ItHwP/p7bX5RPoMOl9NkpHYWdYPhIcy2mACHvQ==} + '@biomejs/cli-win32-x64@2.5.10': + resolution: {integrity: sha512-M+2dgBsl3lXRiTfgPVc2p3anS4Tocojke4rzFLScZ2Y/wmF+36dRb1iHCLiyGqOzQGyTplZH1HnEYviiAqi3nA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -318,13 +326,13 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@commitlint/cli@21.2.1': - resolution: {integrity: sha512-blsZGe29hJ72VGEFVl72IVYX+1vsfINpjA9yWQA6i7OKD/McGEOXg08sKIRKjFk4JvzhV/9n0l3i6NooPLTNfg==} + '@commitlint/cli@21.2.2': + resolution: {integrity: sha512-a+6hQxIxnpdvSvS2apvttPNbEliYsVC3PqFYDiiB2kjbwIsQsj1urvQ4Tkf70pKYozPalKAuRQmm/GHwndduqA==} engines: {node: '>=22.12.0'} hasBin: true - '@commitlint/config-conventional@21.2.0': - resolution: {integrity: sha512-Qf8WRDVcyVd14if6VTWenebxFbKnVnbzPUJjlzjkyJGeHK2xCGd63Dr1XZzj0plXKQb9P0BfOxoc1HVeCo2BWQ==} + '@commitlint/config-conventional@21.2.2': + resolution: {integrity: sha512-NxA37SZviusFUEYOQZ5hNnZ1h7O/KiemPkxjOlpzKJNnWxThiwc6/SaZhaPa8fyLvfRBAywhQhJJk8XESHWlpQ==} engines: {node: '>=22.12.0'} '@commitlint/config-validator@21.2.0': @@ -339,40 +347,40 @@ packages: resolution: {integrity: sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==} engines: {node: '>=22.12.0'} - '@commitlint/format@21.2.0': - resolution: {integrity: sha512-c4q64xaav2U83t7k7RyzJerBZurPer7FxUOY0RL5L/6CZijZ7K+s6HIBGIghj0ey1P2+seRX0J9XQYtDued6tg==} + '@commitlint/format@21.2.2': + resolution: {integrity: sha512-v6fvxZSc/AvVMROlr3H34+1766bZSYApRUSCAMjWamStPjKMvZ8GdvVA5YW/VQNgbFTmcMz6OYmSTJEvIjPrfA==} engines: {node: '>=22.12.0'} - '@commitlint/is-ignored@21.2.0': - resolution: {integrity: sha512-4/eB0vBN7L88O/oC4ajAEqi7j2ZfNgxl/+11RfAV9YosejZgDXhY2C9VcHnHJhOzPLoSy5P3Mg/46kqeyJfXKw==} + '@commitlint/is-ignored@21.2.2': + resolution: {integrity: sha512-9UoKNgfFE3LU7FrzierCvk3CdDfMDeVGC86qZiT/n0TIjfq/dmZ9MHuXd45OTNRa26ZanmJRxEtmiXk/lEJihg==} engines: {node: '>=22.12.0'} - '@commitlint/lint@21.2.0': - resolution: {integrity: sha512-ceO5dp9pLjEZ6y6qbq/uXWXDPykqqlTsyzoQ0NzecpisSJhK3kTy9qzQoPeJuWG/IMNdV1lO0RgmzqoAlSi1uw==} + '@commitlint/lint@21.2.2': + resolution: {integrity: sha512-Fy8JxEBzdmsYWFude/61GxXu5O+wEymwiRK2z9GL9R8mCsXphCoGxAFc5iHn5mjlfcSrhiiONE+ksf4KOjnaPg==} engines: {node: '>=22.12.0'} - '@commitlint/load@21.2.0': - resolution: {integrity: sha512-RjlzWQqruRwIenJEfZtq7kG97co97nKoHpflE5YnF61tDLXxHPrdWImgzw6VL6MlFyaOcVlk74eBV8ZQmc3oIA==} + '@commitlint/load@21.2.2': + resolution: {integrity: sha512-0Tt6wDPX167cjKC5D4zhm0+20wJJG+TN/TKovMOspfSe78rOnKX+MNzlVNiu6HyQPZChPJ8QBH31MVt6Bb8fCg==} engines: {node: '>=22.12.0'} '@commitlint/message@21.2.0': resolution: {integrity: sha512-YxGoiXD/HXNXLJPrQwE5poXa+XH0CBEm+mdvbHQP0g6MV/dmJyUFCzPNzZbxL93GvZ70TmtTK0Z0/IBpAqHv8g==} engines: {node: '>=22.12.0'} - '@commitlint/parse@21.2.0': - resolution: {integrity: sha512-QHWxG4d0PLTF634/AdyZ0MQS+CLn5YOuJlCFhMMlSGKFxzYGUetkHBj18xgBD+6fVzUrA2lrCdi/vlS2f/oYXg==} + '@commitlint/parse@21.2.2': + resolution: {integrity: sha512-MEkobPfvRp+z06Wro8HMG1BDGHzZmj82A1LH1nWeG3ipHpg/x4m6v3wEDvMBIKjRFUnfR3nBeFs3MVCr7UdAmg==} engines: {node: '>=22.12.0'} '@commitlint/read@21.2.1': resolution: {integrity: sha512-hUW7EJQnNTL0vPOmVMNK4CrnrNBN0nN+JJHReFkdHO5y4iyHeEmTBwuC15OCqUTjxWo7idnH1LftfpWVIaPWIA==} engines: {node: '>=22.12.0'} - '@commitlint/resolve-extends@21.2.0': - resolution: {integrity: sha512-4O/1j51+79Wth9s/MGxt/5gs0XYLDgNlYpltQfhAvLE0itusLKs9zruxbiNg1oOkmkb9L9L4USYGjEj7n87NxA==} + '@commitlint/resolve-extends@21.2.2': + resolution: {integrity: sha512-RPkJ/IFi7sMUUVbZLqwWFtWw/zRDcfFsmrPSiTMrt5wb7AdxOr86EGQFvmGzef5QKV5IPBWWCujqVTw1RWX44A==} engines: {node: '>=22.12.0'} - '@commitlint/rules@21.2.0': - resolution: {integrity: sha512-C2yXMNpiB8ETZKfx5JD8+ExgF8vTU1VQMKPSUUYwqKpw9oJWQBrlXBpdU038mj2WPjof7o9UzFpmTyBeGMZwZg==} + '@commitlint/rules@21.2.2': + resolution: {integrity: sha512-eplQzyYkBjYB1HyyRj8hkcK11Y9DU9nuBz7uOKEd6NpE9NGDytLFCAnlRE+OoiK/5sHEJsaz2RGhuWBvYzIbNA==} engines: {node: '>=22.12.0'} '@commitlint/to-lines@21.0.1': @@ -387,20 +395,20 @@ packages: resolution: {integrity: sha512-7zVFCDB2reMvJH5dmbKnOQPjZEvjdJTH8jc0U/PIPU1r3/+vf5pD1HlfitV2MWsWXrvu7u39iY1lyLUPOaN0Gw==} engines: {node: '>=22.12.0'} - '@conventional-changelog/git-client@3.1.0': - resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} + '@conventional-changelog/git-client@3.1.2': + resolution: {integrity: sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==} engines: {node: '>=22'} peerDependencies: conventional-commits-filter: ^6.0.1 - conventional-commits-parser: ^7.0.1 + conventional-commits-parser: ^7.1.2 peerDependenciesMeta: conventional-commits-filter: optional: true conventional-commits-parser: optional: true - '@conventional-changelog/template@1.2.1': - resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} + '@conventional-changelog/template@1.3.0': + resolution: {integrity: sha512-GsCw/qu92GI0EX6s7fxUi/SG1lmFjG9XZivxxEDZXqztuQKCn5o5wKdz4v005zci0Md7EZzgAwmQLoIEDZoaow==} engines: {node: '>=22'} '@emnapi/core@1.11.2': @@ -710,8 +718,8 @@ packages: resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/checkbox@5.2.1': - resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} + '@inquirer/checkbox@5.2.2': + resolution: {integrity: sha512-Y5/bAScMy5Y+9isCx0SKbyJebMCaXXX5em0kxkj115eZNscgV9srOHrgyfS0e5xAVymIfOh9piYBKDILktsMMg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -719,8 +727,8 @@ packages: '@types/node': optional: true - '@inquirer/confirm@6.1.1': - resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} + '@inquirer/confirm@6.2.0': + resolution: {integrity: sha512-SKXarWrYhtpqOEctf9XGCGy29QjsvJAM0Aq9ZR9z4Ns94OmpqudOly+aSEfNqUf9SwsQaUgY9+Z8hyzG0xX8fw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -728,8 +736,8 @@ packages: '@types/node': optional: true - '@inquirer/core@11.2.1': - resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} + '@inquirer/core@12.0.0': + resolution: {integrity: sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -737,8 +745,8 @@ packages: '@types/node': optional: true - '@inquirer/editor@5.2.2': - resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} + '@inquirer/editor@5.3.0': + resolution: {integrity: sha512-nnsP/IdJ8s83q7ZuObmgn12QM+uLCkab9E0Oordojbn62WUg1c+v9Ou/F/057pgh0ppX0W+Hj5bO/Dp5hsxQtA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -746,8 +754,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@5.1.1': - resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} + '@inquirer/expand@5.1.2': + resolution: {integrity: sha512-OWIH1IyyWqEKIyqC9Xy+Bnga7NkGMovFdo4atYZMUOTRqf6rO2WCv9E/1MyzvOErDBCxs+9UFliRUDc50xs/jw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -755,8 +763,8 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@3.0.3': - resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} + '@inquirer/external-editor@3.0.4': + resolution: {integrity: sha512-tZbbaK2ovq6vlrRBNQvjrypmrED/p5x2ncIHQ79cD55tei3dD96v5glMMA+6tiq7K104i/25DVYKWVPJuV6ptA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -764,12 +772,12 @@ packages: '@types/node': optional: true - '@inquirer/figures@2.0.7': - resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} + '@inquirer/figures@2.0.8': + resolution: {integrity: sha512-tApbon79GM9ry56ja/Ud3SY2CL4TQsao9fIwDQbgTeNY55025GdMzQ2+UdegV/lx51VNGUB59M0v0nMpybYY4Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/input@5.1.2': - resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} + '@inquirer/input@5.1.3': + resolution: {integrity: sha512-F/BZHtyEzP+HO+IGVd4AjBRgvX/ywm42bx8S0+dENk2YclzE9tJ3X/15THwtT6ehApmKvdYDMsVTuyyDod0gOQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -777,8 +785,8 @@ packages: '@types/node': optional: true - '@inquirer/number@4.1.1': - resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} + '@inquirer/number@4.2.0': + resolution: {integrity: sha512-ew+fSDijsQ/WhD4TV3XLb+if400cDuzTzHfGR8sTNBXkK9CYDWoGE8fhaO8GbT312pNv1AJEOsDxy/z/HVettA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -786,8 +794,8 @@ packages: '@types/node': optional: true - '@inquirer/password@5.1.1': - resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} + '@inquirer/password@5.1.2': + resolution: {integrity: sha512-nSdufycW8xynEVssFkNQEYIzTySilog0UlfOVRwh3pXzPSk4frXUT2jZWjHnKae6RU9PaoF9wfy1pGwewQuqGw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -795,8 +803,8 @@ packages: '@types/node': optional: true - '@inquirer/prompts@8.5.2': - resolution: {integrity: sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==} + '@inquirer/prompts@8.6.0': + resolution: {integrity: sha512-WgBVDRy3IQ4v9XMCpQ1YDGpso2PcMUxYJzZdH4Nt4t0eoXhEPmOCh5iZbXbR4GTbdUB9VPWBbJB12rkjbaGDCw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -804,8 +812,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@5.3.1': - resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} + '@inquirer/rawlist@5.3.2': + resolution: {integrity: sha512-oPSKrYK1X1bMkjXDzIKHUkJp195LFSfgbnVtXnjSKGFjrCbS6I+wyvfAZTwKE9BSt3HwWgfD7JfsXALBgCogzQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -813,8 +821,8 @@ packages: '@types/node': optional: true - '@inquirer/search@4.2.1': - resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} + '@inquirer/search@4.3.0': + resolution: {integrity: sha512-HFxXE5w727ctSUcAwrDquftJGjMgu36OeV5SHEXMlr2j/ahzmRX9xSEeVolV8tzYnTf45cg6vGkdMMRdm3RPhQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -822,8 +830,8 @@ packages: '@types/node': optional: true - '@inquirer/select@5.2.1': - resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} + '@inquirer/select@5.2.2': + resolution: {integrity: sha512-RkI8dRHWt+bh04oLixvF1kFzKC7e5rqJoHKkzcqSHATebBXFC6GmrT8ddbVkgSzLV0HnHs2cPFuBINr8otij8Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -870,134 +878,129 @@ packages: '@kwsites/promise-deferred@1.1.1': resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - '@napi-rs/wasm-runtime@1.2.2': - resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 - '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 - '@oxc-parser/binding-android-arm-eabi@0.142.0': - resolution: {integrity: sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==} + '@oxc-parser/binding-android-arm-eabi@0.143.0': + resolution: {integrity: sha512-n9uozULWflPqBtdmI8lAabLqGKNgLVNN0ZH8HfgCwpKGNtzRzauB76jTiW/3YLkcA7N1zskpi9GdVnZuu1SAvg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm64@0.142.0': - resolution: {integrity: sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==} + '@oxc-parser/binding-android-arm64@0.143.0': + resolution: {integrity: sha512-9BbdjHETk6O3zH/DDid9IgBtF0GlpLabNKN231uraXpRDSfY+iiZxTP5bk1Z63GBownVdhdINFIeddmMz4MzpQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-parser/binding-darwin-arm64@0.142.0': - resolution: {integrity: sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==} + '@oxc-parser/binding-darwin-arm64@0.143.0': + resolution: {integrity: sha512-gh+6ecoHUy4/sUcolBl/1qPXKBbYNxFY0Pk0ujgQvINTMSftJY7o4yb8gOkDJPeZeB8+a+u7xTe6umoP8N5HFA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.142.0': - resolution: {integrity: sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==} + '@oxc-parser/binding-darwin-x64@0.143.0': + resolution: {integrity: sha512-qd1hl2d+lXgHv/VQ/M9qm8TrMC5T4RqDBwtOnl+1D0QMjwcz+8AaB4JSg8STgeag0GP6a6L74XEGAsrTSJWNzQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-parser/binding-freebsd-x64@0.142.0': - resolution: {integrity: sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==} + '@oxc-parser/binding-freebsd-x64@0.143.0': + resolution: {integrity: sha512-M5XXcNa7aOqLPKTR41msfghKu2yQ4xWvCm11/gwU0JzOzHNk5sgW//rVEjJ+LO48+VDAMzXTSzurUVxIDKwozw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': - resolution: {integrity: sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.143.0': + resolution: {integrity: sha512-T/GXusuOkPNQhCQCSBbcU/N8j0rAypuDBl1IyFK+lyYT594XsVz80clPC/OtbSSpBGyJxj8uYEfctxVuxVYoww==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': - resolution: {integrity: sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==} + '@oxc-parser/binding-linux-arm-musleabihf@0.143.0': + resolution: {integrity: sha512-oKu4RcBlXSqo3OC62dp6YTnQaZIurNDpCX3BnAM3+bJxt7s8J2TJKMnC0UYer1qhlRaDCg6wkTaTw+2IlsZ12w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm64-gnu@0.142.0': - resolution: {integrity: sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==} + '@oxc-parser/binding-linux-arm64-gnu@0.143.0': + resolution: {integrity: sha512-WJBbD186AZmMGaSIhlktC+rPl8L3peCTXAh88Ih9uEvK0en2mPojGyCGYiL6mHtV1RPV3JyfJW5t6n5hh0lXhA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@oxc-parser/binding-linux-arm64-musl@0.142.0': - resolution: {integrity: sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==} + '@oxc-parser/binding-linux-arm64-musl@0.143.0': + resolution: {integrity: sha512-t1AcYOwEzgceadT4v5e+vaCCb0AncCA3v5AyzfBAz/tMq11qzVccXKzNHtkWdjBsgvTKwRkaUF3QvT4kot8vcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': - resolution: {integrity: sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==} + '@oxc-parser/binding-linux-ppc64-gnu@0.143.0': + resolution: {integrity: sha512-RsnO/NoD8376LMJq8JS8TwI0ieNaFRTuNe2GVJntQg6gwZNMENZsEbknHdVwjpOmxdGLGodcwaGSbAeRr5Bgjw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': - resolution: {integrity: sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==} + '@oxc-parser/binding-linux-riscv64-gnu@0.143.0': + resolution: {integrity: sha512-48fSVfR9TZi5CASZFyv0VC6z6BCoeihFsX031mAD/oSH7d9PYsPgIqza7d9mjP7Z2KTEpTFyH6SIu0Ui6R1vdg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - '@oxc-parser/binding-linux-riscv64-musl@0.142.0': - resolution: {integrity: sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==} + '@oxc-parser/binding-linux-riscv64-musl@0.143.0': + resolution: {integrity: sha512-T8CpdD+SfE01DnIOD4HpVxu0ZJOfMJ/VhCvikKfaXAxkZ+9veyLM/D2hpi7Y2hFUyPmVQO3FNZHmYzV/WlVR4g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - '@oxc-parser/binding-linux-s390x-gnu@0.142.0': - resolution: {integrity: sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==} + '@oxc-parser/binding-linux-s390x-gnu@0.143.0': + resolution: {integrity: sha512-QLdeMsCcacenPEFsfxnBUDF1y6opyz5+fmOz9bfD5Y7fiGCMupUCuB3KTPQhNwshIG1P9fPqar9MHxuBDd4bwQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - '@oxc-parser/binding-linux-x64-gnu@0.142.0': - resolution: {integrity: sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==} + '@oxc-parser/binding-linux-x64-gnu@0.143.0': + resolution: {integrity: sha512-659ujfqLy6k7cuH3sbzhd8b+ztSq+i6E2E9pG78Q0BmHjAExfGIdgc8cGgMdwAozDXeZFHkJ+LXYJdWsaGdgyw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@oxc-parser/binding-linux-x64-musl@0.142.0': - resolution: {integrity: sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==} + '@oxc-parser/binding-linux-x64-musl@0.143.0': + resolution: {integrity: sha512-/Mw/9j4TfZcnKphPrzOE6t4MMknXadcAAuVUlDRTF/ETWB5xOgQvOJV2Mh9We/bWxZdoxaGAdc+hy4GuYwQ2yQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@oxc-parser/binding-openharmony-arm64@0.142.0': - resolution: {integrity: sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==} + '@oxc-parser/binding-openharmony-arm64@0.143.0': + resolution: {integrity: sha512-8rIKWR2BFuifbIK/1XB9wTaSdtuJ25dlE7ZQYDnEwj/2xH2vHsxnvIjHT3ZjSVuLLwGGlSslIG/fbOJ8TV8rTw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-wasm32-wasi@0.142.0': - resolution: {integrity: sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@oxc-parser/binding-win32-arm64-msvc@0.142.0': - resolution: {integrity: sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==} + '@oxc-parser/binding-win32-arm64-msvc@0.143.0': + resolution: {integrity: sha512-5U9kQYMfRRI6Zq7KDxgbIP0RMnKrfn3gLepRMgJuRkPSUALTiRCk9d/uyhb4lGDjUdzwK7mBkKqhLgzBPCmLpQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.142.0': - resolution: {integrity: sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==} + '@oxc-parser/binding-win32-ia32-msvc@0.143.0': + resolution: {integrity: sha512-25P7AaHk4R88Yv2XH4gToDVmh0cOu+bEURQU10CRrmvgabfRArSGAP5osmwUKeSUHj0VS50upbpbRWWW/m7mHA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.142.0': - resolution: {integrity: sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==} + '@oxc-parser/binding-win32-x64-msvc@0.143.0': + resolution: {integrity: sha512-ORMh3JE1s6V7ySicdRK7vgaDQnn5o+UHg9ct989PlWHbel8O9ARrmWXM6kZjrBMtNucxNayQ8g69G0VfWzhANw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxc-project/types@0.142.0': - resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} + '@oxc-project/types@0.143.0': + resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} '@oxc-resolver/binding-android-arm-eabi@11.24.2': resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} @@ -1632,12 +1635,12 @@ 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==} + conventional-changelog-angular@9.3.0: + resolution: {integrity: sha512-0MWQLVUT1oVCsUGs9aAWteBVxPlLwJTn5VbQH7B0B3fDizZgrJ9QGnKl/2mp1+5P7153GCBCjO/v1aKJ6eysCg==} engines: {node: '>=22'} - conventional-changelog-conventionalcommits@10.2.1: - resolution: {integrity: sha512-n4Kr1HFMTf3iMbES0TMxKIcYtUUv4rKqyQQp2JwfOEfFCOfGT3Tq4mCyJ8S9/YPyWhydjfKrrvnyl+gCjA+mJQ==} + conventional-changelog-conventionalcommits@10.3.0: + resolution: {integrity: sha512-qag0zFD867Qq1DK0jAWicyWlEMS1FFC/BLVLISaoeI7Y6Em6aWchk7BCkhOTsecRpMsV6qX41XmlNnghiiTmSw==} engines: {node: '>=22'} conventional-commits-parser@7.1.1: @@ -1645,6 +1648,11 @@ packages: engines: {node: '>=22'} hasBin: true + conventional-commits-parser@7.1.2: + resolution: {integrity: sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==} + engines: {node: '>=22'} + hasBin: true + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -1652,16 +1660,16 @@ packages: resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - cosmiconfig-typescript-loader@6.2.0: - resolution: {integrity: sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==} + cosmiconfig-typescript-loader@6.3.0: + resolution: {integrity: sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==} engines: {node: '>=v18'} peerDependencies: '@types/node': '*' cosmiconfig: '>=9' typescript: '>=5' - cosmiconfig@9.0.1: - resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + cosmiconfig@9.0.2: + resolution: {integrity: sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==} engines: {node: '>=14'} peerDependencies: typescript: '>=4.9.5' @@ -1743,6 +1751,9 @@ packages: es-toolkit@1.50.0: resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} + es-toolkit@1.51.0: + resolution: {integrity: sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -1994,6 +2005,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 @@ -2018,42 +2033,42 @@ packages: resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} hasBin: true - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + js-yaml@4.3.1: + resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true - jscpd-darwin-arm64@5.0.14: - resolution: {integrity: sha512-Ojjl79SBuj9tEW6WbjZ1a/1ZOR89dneH9yLQYQu8WyWaQownttnx7RYFEHU6aGhS4jIvwUEbr+1wxzFTb37cwg==} + jscpd-darwin-arm64@5.0.16: + resolution: {integrity: sha512-Tu6OAg3Rp6m7LCZqOtPViJxYGTKXTLrI/xMyjEKe79N9L7GpbI3XhgotGDpoE+PjLRbgJgGhRKbkKK18FPySmQ==} cpu: [arm64] os: [darwin] - jscpd-darwin-x64@5.0.14: - resolution: {integrity: sha512-DxFg5XvjMZ81iVeqillnM5apqcGCfNTbroNF+mPLr7RkHLGH6mudLgtO+ILL/hfpZXy1bF9oIY5BSudPmN/k9A==} + jscpd-darwin-x64@5.0.16: + resolution: {integrity: sha512-3btQ1aG8K7+9rvJjyaRJRcSBD0DvHgZOUVlecjnyO99FYzMvdFREq67UIl5CAXFeYf5EY8TSorCMZQxL6TBD0w==} cpu: [x64] os: [darwin] - jscpd-linux-arm64-gnu@5.0.14: - resolution: {integrity: sha512-1uw+XBHEt9pONXNICSp5HpaVWPjG6mQ6deDXaq9Yb0xCNJkX4/8gmn0vhzekIyZD2DspRYKPUolbDsqm/HEdYg==} + jscpd-linux-arm64-gnu@5.0.16: + resolution: {integrity: sha512-L1F9CNHxRPqGJCKgGRA4gtZcESACFkS2lgfPgWn9fG+4CkiewLcYyy/oxrafJJL1/PPTQ24sbLuzPaKUxJuvuw==} cpu: [arm64] os: [linux] - jscpd-linux-x64-gnu@5.0.14: - resolution: {integrity: sha512-dFTbyyrm+Z9pcXIVzJQCw8QAgiNqIiO69sm4AfA7/wFdPoizoVzjhaXsYXcSV4bs0aoPiWbNazg0J0HgslT/5A==} + jscpd-linux-x64-gnu@5.0.16: + resolution: {integrity: sha512-BruP+sAr0+6QsEQZvOkgcS+xR23y4s1hLA0xfkcO1zFFXdnmQdJ4w23/U8VlPwqO2dFRaAEseYEXjHs5oQQGFw==} cpu: [x64] os: [linux] - jscpd-linux-x64-musl@5.0.14: - resolution: {integrity: sha512-SayS7qQJvixyy9eR0+UjepkTsUUwqvlsiuSxfIdHgG2qzqoh/thnkgiu4By8fsiiDpQONsQrRrZDwHRQ3GDrBQ==} + jscpd-linux-x64-musl@5.0.16: + resolution: {integrity: sha512-T36RtMnF695Y1/T3cLEhgvspHdKoiF+oxK/lklGJWriLieImZolSOjGXsecW2bp7MNMMGlqLLRzr2RNgnwy+Hg==} cpu: [x64] os: [linux] - jscpd-windows-x64-msvc@5.0.14: - resolution: {integrity: sha512-DqjxlVkUanlahGgY2lY7Zkrau4BUTI+AwWky+bPGK4kSK2AIOaUziY9Q19u8b58idXmJA9FKK98Fuu4ajNXVjQ==} + jscpd-windows-x64-msvc@5.0.16: + resolution: {integrity: sha512-BcrY18r6uje+TjgBKdFZJz6qfAAh9QT24KZYZk+jk6tuIKOYIm6oRMeQEu3Tzr/len9ZethN2h1bKmv+EfHcGw==} cpu: [x64] os: [win32] - jscpd@5.0.14: - resolution: {integrity: sha512-zge+FPZZAymt2Do5Z0+QHyIn4/XcUhrO/W7of9HcHZfx2AK8++dYhLA1uWtwXj47ml3Of8PbcUW4wUWvYMCc3w==} + jscpd@5.0.16: + resolution: {integrity: sha512-TiQ4zKtKeldep6UswXFHjVCDhVdLBaJyQcZjhCSzVOmKpT6HBj0jUZiphP1vK1X3VSSuzwcfifJVNpsOIiwRCg==} engines: {node: '>=18'} hasBin: true @@ -2080,8 +2095,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@6.32.0: - resolution: {integrity: sha512-KDX9OmmOFmlvmxTkrx6Z0GHISMut+pXMSKR8eg84bovaxJKx2NdQD4JYCXveSbvieRe107W6vCD2xCpmz0qBYA==} + knip@6.32.2: + resolution: {integrity: sha512-WXTXbmocrw7gqm1A1TQvFN0OgJ7hUSU6E1g6SPRIzzHFogUBhXByc7cYeOFVtJ2uODg7DP4VbESYBYnfbtBYsg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2245,8 +2260,8 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - oxc-parser@0.142.0: - resolution: {integrity: sha512-kKR+jPiRJYJDexVoziIg/FVGvr1fT1FZSSJOk6tVoMKKSlsf1Cso+cgGCJkOEDWOP174vRntCPFKg+AS7InWvw==} + oxc-parser@0.143.0: + resolution: {integrity: sha512-ov0NzaDCOInknS7mP1cwKdJERt3utPW8ldjtdUXQ8Ty0GEFD08wk422vCUN0d7pST6kqtV7dxoI9w1Zi0l/9TA==} engines: {node: ^20.19.0 || >=22.12.0} oxc-resolver@11.24.2: @@ -2405,6 +2420,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2446,8 +2466,8 @@ packages: resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==} engines: {node: '>=22'} - smol-toml@1.7.1: - resolution: {integrity: sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ==} + smol-toml@1.8.0: + resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} engines: {node: '>= 18'} source-map-js@1.2.1: @@ -2544,8 +2564,8 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} engines: {node: '>=18'} tinyglobby@0.2.15: @@ -2802,6 +2822,12 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.29.3': {} '@babel/core@7.29.0': @@ -2908,6 +2934,8 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.29.2': @@ -3014,53 +3042,53 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@biomejs/biome@2.5.7': + '@biomejs/biome@2.5.10': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.5.7 - '@biomejs/cli-darwin-x64': 2.5.7 - '@biomejs/cli-linux-arm64': 2.5.7 - '@biomejs/cli-linux-arm64-musl': 2.5.7 - '@biomejs/cli-linux-x64': 2.5.7 - '@biomejs/cli-linux-x64-musl': 2.5.7 - '@biomejs/cli-win32-arm64': 2.5.7 - '@biomejs/cli-win32-x64': 2.5.7 + '@biomejs/cli-darwin-arm64': 2.5.10 + '@biomejs/cli-darwin-x64': 2.5.10 + '@biomejs/cli-linux-arm64': 2.5.10 + '@biomejs/cli-linux-arm64-musl': 2.5.10 + '@biomejs/cli-linux-x64': 2.5.10 + '@biomejs/cli-linux-x64-musl': 2.5.10 + '@biomejs/cli-win32-arm64': 2.5.10 + '@biomejs/cli-win32-x64': 2.5.10 - '@biomejs/cli-darwin-arm64@2.5.7': + '@biomejs/cli-darwin-arm64@2.5.10': optional: true - '@biomejs/cli-darwin-x64@2.5.7': + '@biomejs/cli-darwin-x64@2.5.10': optional: true - '@biomejs/cli-linux-arm64-musl@2.5.7': + '@biomejs/cli-linux-arm64-musl@2.5.10': optional: true - '@biomejs/cli-linux-arm64@2.5.7': + '@biomejs/cli-linux-arm64@2.5.10': optional: true - '@biomejs/cli-linux-x64-musl@2.5.7': + '@biomejs/cli-linux-x64-musl@2.5.10': optional: true - '@biomejs/cli-linux-x64@2.5.7': + '@biomejs/cli-linux-x64@2.5.10': optional: true - '@biomejs/cli-win32-arm64@2.5.7': + '@biomejs/cli-win32-arm64@2.5.10': optional: true - '@biomejs/cli-win32-x64@2.5.7': + '@biomejs/cli-win32-x64@2.5.10': optional: true '@colors/colors@1.5.0': optional: true - '@commitlint/cli@21.2.1(@types/node@26.2.0)(conventional-commits-parser@7.1.1)(typescript@7.0.2)': + '@commitlint/cli@21.2.2(@types/node@26.2.0)(conventional-commits-parser@7.1.2)(typescript@7.0.2)': 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.2.0)(typescript@7.0.2) - '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.1) + '@commitlint/config-conventional': 21.2.2 + '@commitlint/format': 21.2.2 + '@commitlint/lint': 21.2.2 + '@commitlint/load': 21.2.2(@types/node@26.2.0)(typescript@7.0.2) + '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.2) '@commitlint/types': 21.2.0 - tinyexec: 1.0.2 + tinyexec: 1.3.0 yargs: 18.1.0 transitivePeerDependencies: - '@types/node' @@ -3068,10 +3096,10 @@ snapshots: - conventional-commits-parser - typescript - '@commitlint/config-conventional@21.2.0': + '@commitlint/config-conventional@21.2.2': dependencies: '@commitlint/types': 21.2.0 - conventional-changelog-conventionalcommits: 10.2.1 + conventional-changelog-conventionalcommits: 10.3.0 '@commitlint/config-validator@21.2.0': dependencies: @@ -3081,36 +3109,36 @@ snapshots: '@commitlint/ensure@21.2.0': dependencies: '@commitlint/types': 21.2.0 - es-toolkit: 1.50.0 + es-toolkit: 1.51.0 '@commitlint/execute-rule@21.0.1': {} - '@commitlint/format@21.2.0': + '@commitlint/format@21.2.2': dependencies: '@commitlint/types': 21.2.0 picocolors: 1.1.1 - '@commitlint/is-ignored@21.2.0': + '@commitlint/is-ignored@21.2.2': dependencies: '@commitlint/types': 21.2.0 - semver: 7.7.4 + semver: 7.8.5 - '@commitlint/lint@21.2.0': + '@commitlint/lint@21.2.2': dependencies: - '@commitlint/is-ignored': 21.2.0 - '@commitlint/parse': 21.2.0 - '@commitlint/rules': 21.2.0 + '@commitlint/is-ignored': 21.2.2 + '@commitlint/parse': 21.2.2 + '@commitlint/rules': 21.2.2 '@commitlint/types': 21.2.0 - '@commitlint/load@21.2.0(@types/node@26.2.0)(typescript@7.0.2)': + '@commitlint/load@21.2.2(@types/node@26.2.0)(typescript@7.0.2)': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/execute-rule': 21.0.1 - '@commitlint/resolve-extends': 21.2.0 + '@commitlint/resolve-extends': 21.2.2 '@commitlint/types': 21.2.0 - cosmiconfig: 9.0.1(typescript@7.0.2) - cosmiconfig-typescript-loader: 6.2.0(@types/node@26.2.0)(cosmiconfig@9.0.1(typescript@7.0.2))(typescript@7.0.2) - es-toolkit: 1.50.0 + cosmiconfig: 9.0.2(typescript@7.0.2) + cosmiconfig-typescript-loader: 6.3.0(@types/node@26.2.0)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2) + es-toolkit: 1.51.0 is-plain-obj: 4.1.0 picocolors: 1.1.1 transitivePeerDependencies: @@ -3119,31 +3147,31 @@ snapshots: '@commitlint/message@21.2.0': {} - '@commitlint/parse@21.2.0': + '@commitlint/parse@21.2.2': dependencies: '@commitlint/types': 21.2.0 - conventional-changelog-angular: 9.2.1 - conventional-commits-parser: 7.1.1 + conventional-changelog-angular: 9.3.0 + conventional-commits-parser: 7.1.2 - '@commitlint/read@21.2.1(conventional-commits-parser@7.1.1)': + '@commitlint/read@21.2.1(conventional-commits-parser@7.1.2)': dependencies: '@commitlint/top-level': 21.2.0 '@commitlint/types': 21.2.0 - '@conventional-changelog/git-client': 3.1.0(conventional-commits-parser@7.1.1) - tinyexec: 1.0.2 + '@conventional-changelog/git-client': 3.1.2(conventional-commits-parser@7.1.2) + tinyexec: 1.3.0 transitivePeerDependencies: - conventional-commits-filter - conventional-commits-parser - '@commitlint/resolve-extends@21.2.0': + '@commitlint/resolve-extends@21.2.2': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/types': 21.2.0 - es-toolkit: 1.50.0 + es-toolkit: 1.51.0 global-directory: 5.0.0 resolve-from: 5.0.0 - '@commitlint/rules@21.2.0': + '@commitlint/rules@21.2.2': dependencies: '@commitlint/ensure': 21.2.0 '@commitlint/message': 21.2.0 @@ -3161,15 +3189,15 @@ snapshots: conventional-commits-parser: 7.1.1 picocolors: 1.1.1 - '@conventional-changelog/git-client@3.1.0(conventional-commits-parser@7.1.1)': + '@conventional-changelog/git-client@3.1.2(conventional-commits-parser@7.1.2)': dependencies: '@simple-libs/child-process-utils': 2.0.0 '@simple-libs/stream-utils': 2.0.0 - semver: 7.7.4 + semver: 7.8.5 optionalDependencies: - conventional-commits-parser: 7.1.1 + conventional-commits-parser: 7.1.2 - '@conventional-changelog/template@1.2.1': {} + '@conventional-changelog/template@1.3.0': {} '@emnapi/core@1.11.2': dependencies: @@ -3336,26 +3364,26 @@ snapshots: '@inquirer/ansi@2.0.7': {} - '@inquirer/checkbox@5.2.1(@types/node@26.2.0)': + '@inquirer/checkbox@5.2.2(@types/node@26.2.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.2.0) - '@inquirer/figures': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@26.2.0) + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/confirm@6.1.1(@types/node@26.2.0)': + '@inquirer/confirm@6.2.0(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/core@11.2.1(@types/node@26.2.0)': + '@inquirer/core@12.0.0(@types/node@26.2.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/figures': 2.0.7 + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@26.2.0) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 @@ -3364,87 +3392,87 @@ snapshots: optionalDependencies: '@types/node': 26.2.0 - '@inquirer/editor@5.2.2(@types/node@26.2.0)': + '@inquirer/editor@5.3.0(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) - '@inquirer/external-editor': 3.0.3(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) + '@inquirer/external-editor': 3.0.4(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/expand@5.1.1(@types/node@26.2.0)': + '@inquirer/expand@5.1.2(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/external-editor@3.0.3(@types/node@26.2.0)': + '@inquirer/external-editor@3.0.4(@types/node@26.2.0)': dependencies: chardet: 2.2.0 iconv-lite: 0.7.3 optionalDependencies: '@types/node': 26.2.0 - '@inquirer/figures@2.0.7': {} + '@inquirer/figures@2.0.8': {} - '@inquirer/input@5.1.2(@types/node@26.2.0)': + '@inquirer/input@5.1.3(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/number@4.1.1(@types/node@26.2.0)': + '@inquirer/number@4.2.0(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/password@5.1.1(@types/node@26.2.0)': + '@inquirer/password@5.1.2(@types/node@26.2.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/prompts@8.5.2(@types/node@26.2.0)': - dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@26.2.0) - '@inquirer/confirm': 6.1.1(@types/node@26.2.0) - '@inquirer/editor': 5.2.2(@types/node@26.2.0) - '@inquirer/expand': 5.1.1(@types/node@26.2.0) - '@inquirer/input': 5.1.2(@types/node@26.2.0) - '@inquirer/number': 4.1.1(@types/node@26.2.0) - '@inquirer/password': 5.1.1(@types/node@26.2.0) - '@inquirer/rawlist': 5.3.1(@types/node@26.2.0) - '@inquirer/search': 4.2.1(@types/node@26.2.0) - '@inquirer/select': 5.2.1(@types/node@26.2.0) + '@inquirer/prompts@8.6.0(@types/node@26.2.0)': + dependencies: + '@inquirer/checkbox': 5.2.2(@types/node@26.2.0) + '@inquirer/confirm': 6.2.0(@types/node@26.2.0) + '@inquirer/editor': 5.3.0(@types/node@26.2.0) + '@inquirer/expand': 5.1.2(@types/node@26.2.0) + '@inquirer/input': 5.1.3(@types/node@26.2.0) + '@inquirer/number': 4.2.0(@types/node@26.2.0) + '@inquirer/password': 5.1.2(@types/node@26.2.0) + '@inquirer/rawlist': 5.3.2(@types/node@26.2.0) + '@inquirer/search': 4.3.0(@types/node@26.2.0) + '@inquirer/select': 5.2.2(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/rawlist@5.3.1(@types/node@26.2.0)': + '@inquirer/rawlist@5.3.2(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) + '@inquirer/core': 12.0.0(@types/node@26.2.0) '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/search@4.2.1(@types/node@26.2.0)': + '@inquirer/search@4.3.0(@types/node@26.2.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.2.0) - '@inquirer/figures': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@26.2.0) + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 - '@inquirer/select@5.2.1(@types/node@26.2.0)': + '@inquirer/select@5.2.2(@types/node@26.2.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.2.0) - '@inquirer/figures': 2.0.7 + '@inquirer/core': 12.0.0(@types/node@26.2.0) + '@inquirer/figures': 2.0.8 '@inquirer/type': 4.0.7(@types/node@26.2.0) optionalDependencies: '@types/node': 26.2.0 @@ -3491,78 +3519,71 @@ snapshots: '@kwsites/promise-deferred@1.1.1': {} - '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': dependencies: '@emnapi/core': 1.11.2 '@emnapi/runtime': 1.11.2 '@tybys/wasm-util': 0.10.3 optional: true - '@oxc-parser/binding-android-arm-eabi@0.142.0': + '@oxc-parser/binding-android-arm-eabi@0.143.0': optional: true - '@oxc-parser/binding-android-arm64@0.142.0': + '@oxc-parser/binding-android-arm64@0.143.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.142.0': + '@oxc-parser/binding-darwin-arm64@0.143.0': optional: true - '@oxc-parser/binding-darwin-x64@0.142.0': + '@oxc-parser/binding-darwin-x64@0.143.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.142.0': + '@oxc-parser/binding-freebsd-x64@0.143.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.143.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.143.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.142.0': + '@oxc-parser/binding-linux-arm64-gnu@0.143.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.142.0': + '@oxc-parser/binding-linux-arm64-musl@0.143.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.143.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.143.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.142.0': + '@oxc-parser/binding-linux-riscv64-musl@0.143.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.142.0': + '@oxc-parser/binding-linux-s390x-gnu@0.143.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.142.0': + '@oxc-parser/binding-linux-x64-gnu@0.143.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.142.0': + '@oxc-parser/binding-linux-x64-musl@0.143.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.142.0': + '@oxc-parser/binding-openharmony-arm64@0.143.0': optional: true - '@oxc-parser/binding-wasm32-wasi@0.142.0': - dependencies: - '@emnapi/core': 1.11.2 - '@emnapi/runtime': 1.11.2 - '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@oxc-parser/binding-win32-arm64-msvc@0.143.0': optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.142.0': + '@oxc-parser/binding-win32-ia32-msvc@0.143.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.142.0': + '@oxc-parser/binding-win32-x64-msvc@0.143.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.142.0': - optional: true - - '@oxc-project/types@0.142.0': {} + '@oxc-project/types@0.143.0': {} '@oxc-resolver/binding-android-arm-eabi@11.24.2': optional: true @@ -3616,7 +3637,7 @@ snapshots: dependencies: '@emnapi/core': 1.11.2 '@emnapi/runtime': 1.11.2 - '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) optional: true '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': @@ -3728,7 +3749,7 @@ snapshots: '@stryker-mutator/core@9.6.1(@types/node@26.2.0)': dependencies: - '@inquirer/prompts': 8.5.2(@types/node@26.2.0) + '@inquirer/prompts': 8.6.0(@types/node@26.2.0) '@stryker-mutator/api': 9.6.1 '@stryker-mutator/instrumenter': 9.6.1 '@stryker-mutator/util': 9.6.1 @@ -4091,35 +4112,40 @@ snapshots: consola@3.4.2: {} - conventional-changelog-angular@9.2.1: + conventional-changelog-angular@9.3.0: dependencies: - '@conventional-changelog/template': 1.2.1 + '@conventional-changelog/template': 1.3.0 - conventional-changelog-conventionalcommits@10.2.1: + conventional-changelog-conventionalcommits@10.3.0: dependencies: - '@conventional-changelog/template': 1.2.1 + '@conventional-changelog/template': 1.3.0 conventional-commits-parser@7.1.1: dependencies: '@simple-libs/stream-utils': 2.0.0 argue-cli: 3.1.0 + conventional-commits-parser@7.1.2: + dependencies: + '@simple-libs/stream-utils': 2.0.0 + argue-cli: 3.1.0 + convert-source-map@2.0.0: {} convert-to-spaces@2.0.1: {} - cosmiconfig-typescript-loader@6.2.0(@types/node@26.2.0)(cosmiconfig@9.0.1(typescript@7.0.2))(typescript@7.0.2): + cosmiconfig-typescript-loader@6.3.0(@types/node@26.2.0)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2): dependencies: '@types/node': 26.2.0 - cosmiconfig: 9.0.1(typescript@7.0.2) - jiti: 2.7.0 + cosmiconfig: 9.0.2(typescript@7.0.2) + jiti: 2.6.1 typescript: 7.0.2 - cosmiconfig@9.0.1(typescript@7.0.2): + cosmiconfig@9.0.2(typescript@7.0.2): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.3.1 parse-json: 5.2.0 optionalDependencies: typescript: 7.0.2 @@ -4181,6 +4207,8 @@ snapshots: es-toolkit@1.50.0: {} + es-toolkit@1.51.0: {} + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -4484,6 +4512,8 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jiti@2.6.1: {} + jiti@2.7.0: {} joycon@3.1.1: {} @@ -4501,36 +4531,36 @@ snapshots: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.1: + js-yaml@4.3.1: dependencies: argparse: 2.0.1 - jscpd-darwin-arm64@5.0.14: + jscpd-darwin-arm64@5.0.16: optional: true - jscpd-darwin-x64@5.0.14: + jscpd-darwin-x64@5.0.16: optional: true - jscpd-linux-arm64-gnu@5.0.14: + jscpd-linux-arm64-gnu@5.0.16: optional: true - jscpd-linux-x64-gnu@5.0.14: + jscpd-linux-x64-gnu@5.0.16: optional: true - jscpd-linux-x64-musl@5.0.14: + jscpd-linux-x64-musl@5.0.16: optional: true - jscpd-windows-x64-msvc@5.0.14: + jscpd-windows-x64-msvc@5.0.16: optional: true - jscpd@5.0.14: + jscpd@5.0.16: optionalDependencies: - jscpd-darwin-arm64: 5.0.14 - jscpd-darwin-x64: 5.0.14 - jscpd-linux-arm64-gnu: 5.0.14 - jscpd-linux-x64-gnu: 5.0.14 - jscpd-linux-x64-musl: 5.0.14 - jscpd-windows-x64-msvc: 5.0.14 + jscpd-darwin-arm64: 5.0.16 + jscpd-darwin-x64: 5.0.16 + jscpd-linux-arm64-gnu: 5.0.16 + jscpd-linux-x64-gnu: 5.0.16 + jscpd-linux-x64-musl: 5.0.16 + jscpd-windows-x64-msvc: 5.0.16 jsesc@3.1.0: {} @@ -4544,16 +4574,16 @@ snapshots: kind-of@6.0.3: {} - knip@6.32.0: + knip@6.32.2: dependencies: fdir: 6.5.0(picomatch@4.0.5) formatly: 0.3.0 get-tsconfig: 4.14.1 jiti: 2.7.0 - oxc-parser: 0.142.0 + oxc-parser: 0.143.0 oxc-resolver: 11.24.2 picomatch: 4.0.5 - smol-toml: 1.7.1 + smol-toml: 1.8.0 strip-json-comments: 5.0.3 tinyglobby: 0.2.17 unbash: 4.0.10 @@ -4695,30 +4725,29 @@ snapshots: dependencies: mimic-fn: 2.1.0 - oxc-parser@0.142.0: + oxc-parser@0.143.0: dependencies: - '@oxc-project/types': 0.142.0 + '@oxc-project/types': 0.143.0 optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.142.0 - '@oxc-parser/binding-android-arm64': 0.142.0 - '@oxc-parser/binding-darwin-arm64': 0.142.0 - '@oxc-parser/binding-darwin-x64': 0.142.0 - '@oxc-parser/binding-freebsd-x64': 0.142.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.142.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.142.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.142.0 - '@oxc-parser/binding-linux-arm64-musl': 0.142.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.142.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.142.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.142.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.142.0 - '@oxc-parser/binding-linux-x64-gnu': 0.142.0 - '@oxc-parser/binding-linux-x64-musl': 0.142.0 - '@oxc-parser/binding-openharmony-arm64': 0.142.0 - '@oxc-parser/binding-wasm32-wasi': 0.142.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.142.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.142.0 - '@oxc-parser/binding-win32-x64-msvc': 0.142.0 + '@oxc-parser/binding-android-arm-eabi': 0.143.0 + '@oxc-parser/binding-android-arm64': 0.143.0 + '@oxc-parser/binding-darwin-arm64': 0.143.0 + '@oxc-parser/binding-darwin-x64': 0.143.0 + '@oxc-parser/binding-freebsd-x64': 0.143.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.143.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.143.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.143.0 + '@oxc-parser/binding-linux-arm64-musl': 0.143.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.143.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.143.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.143.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.143.0 + '@oxc-parser/binding-linux-x64-gnu': 0.143.0 + '@oxc-parser/binding-linux-x64-musl': 0.143.0 + '@oxc-parser/binding-openharmony-arm64': 0.143.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.143.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.143.0 + '@oxc-parser/binding-win32-x64-msvc': 0.143.0 oxc-resolver@11.24.2: optionalDependencies: @@ -4750,7 +4779,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.29.0 + '@babel/code-frame': 7.29.7 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -4882,6 +4911,8 @@ snapshots: semver@7.7.4: {} + semver@7.8.5: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -4937,7 +4968,7 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 - smol-toml@1.7.1: {} + smol-toml@1.8.0: {} source-map-js@1.2.1: {} @@ -5030,7 +5061,7 @@ snapshots: tinyexec@0.3.2: {} - tinyexec@1.0.2: {} + tinyexec@1.3.0: {} tinyglobby@0.2.15: dependencies: diff --git a/lefthook.yml b/lefthook.yml index b494ecc1b..21b099b4d 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -21,6 +21,14 @@ pre-commit: exit 1 fi node scripts/validate-yaml.mjs {files} + scripts-tests: + glob: "{scripts,plugins/aidd-context/hooks}/**" + run: | + if ! command -v node >/dev/null 2>&1; then + echo "ℹ️ node not available; skipping scripts-tests" + exit 0 + fi + node --test 'scripts/__tests__/*.test.js' skill-frontmatter: glob: "plugins/*/skills/*/SKILL.md" run: | @@ -43,6 +51,18 @@ pre-commit: exit 0 fi node scripts/check-skill-argument-hints.mjs + context-imports: + # Two patterns, because "**/" needs a literal slash and so never matches + # a file at the repository root. + glob: + - "{CLAUDE,AGENTS,copilot-instructions}.md" + - "**/{CLAUDE,AGENTS,copilot-instructions}.md" + run: | + if ! command -v node >/dev/null 2>&1; then + echo "ℹ️ node not available; skipping context-imports" + exit 0 + fi + node scripts/check-context-imports.js markdown-links: glob: "**/*.md" run: | diff --git a/package.json b/package.json index bc195738d..03f4f7bbf 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,11 @@ "prepare": "lefthook install || true" }, "devDependencies": { - "@commitlint/cli": "^21.2.1", - "@commitlint/config-conventional": "^21.2.0", + "@commitlint/cli": "^21.2.2", + "@commitlint/config-conventional": "^21.2.2", "ajv": "8.20.0", "ajv-formats": "3.0.1", - "js-yaml": "5.2.3", + "js-yaml": "5.3.0", "lefthook": "^2.1.10" } } diff --git a/plugins/aidd-context/hooks/update_memory.js b/plugins/aidd-context/hooks/update_memory.js index 495b4ea7e..191cde402 100644 --- a/plugins/aidd-context/hooks/update_memory.js +++ b/plugins/aidd-context/hooks/update_memory.js @@ -1,8 +1,9 @@ #!/usr/bin/env node /** - * update_memory.js - Syncs the block in AI context files. + * update_memory.js - Syncs the project memory block in AI context files. * - * Scans aidd_docs/memory/ and updates the block in each + * Scans aidd_docs/memory/ and updates the block delimited by + * / in each * context file with two tiers: * - Root memory files -> always loaded, via a tool-appropriate reference. * - internal/ and external/ -> listed (plain paths, no @), read on demand. @@ -28,8 +29,18 @@ const DOCS_DIR = "aidd_docs"; const MEMORY_SUBDIR = "memory"; const ON_DEMAND_DIRS = ["internal", "external"]; -const BLOCK_OPEN = ""; -const BLOCK_CLOSE = ""; +// HTML comment markers, not a bare tag. A line opening a +// bare tag starts an HTML block that runs to the next blank line, and an @import +// inside one is skipped by the context loader exactly like a fenced code block, +// so the memory silently never loads. A comment closes on its own line. +const BLOCK_OPEN = ""; +const BLOCK_CLOSE = ""; + +// The shape written before the markers above. Blocks already in a user's context +// file are rewritten to the new markers on the next run; without that they stop +// matching, the file is skipped with no output, and the memory stays unloaded. +const LEGACY_BLOCK_OPEN = ""; +const LEGACY_BLOCK_CLOSE = ""; const ON_DEMAND_NOTE = ""; const EXCLUDED_FILES = new Set([".gitkeep", "README.md"]); @@ -117,20 +128,79 @@ function buildBlockContent(rootFiles, onDemandFiles, syntax) { lines.push("", ON_DEMAND_NOTE); for (const f of onDemandFiles) lines.push(`- ${f.replace(/\\/g, "/")}`); } - if (lines.length === 0) return ""; - return `\n${lines.join("\n")}\n`; + if (lines.length === 0) return "\n"; + // Blank line on each side of the content. The markers are comments, which + // close on their own line, but a context loader that treats any line opening + // with `<` as an HTML block running to the next blank line would otherwise + // swallow the imports. The blank lines hold under either reading. + return `\n\n${lines.join("\n")}\n\n`; +} + +// The real block is the one whose markers each own their line, outside any code +// fence. Substring search is not enough: these markers are the strings every +// upgrade note and migration doc quotes, and cutting on a quoted one would +// mangle that prose while leaving the real block untouched and unloaded. +function findBlockLines(lines, open, close) { + let fence = null; + let openLine = -1; + + for (let i = 0; i < lines.length; i++) { + const trimmed = lines[i].trim(); + const opener = /^(`{3,}|~{3,})/u.exec(trimmed); + + if (fence !== null) { + // A fence closes only on the same character, repeated at least as often, + // so a ``` inside a ```` example does not end it early. + if (opener && opener[1][0] === fence[0] && opener[1].length >= fence.length) fence = null; + continue; + } + if (opener) { + fence = opener[1]; + continue; + } + if (trimmed === open) openLine = i; + else if (trimmed === close && openLine !== -1) return { openLine, closeLine: i }; + } + + return null; } // Replace the text between an open and close marker, leaving the rest intact. -// Anchor on the close, then take the nearest open before it: a bare marker -// quoted in hand-written prose above the real block must not become the cut -// point and splice out everything between it and the block. function updateMarkers(content, open, close, innerContent) { - const closeIdx = content.indexOf(close); - if (closeIdx === -1) return null; - const openIdx = content.lastIndexOf(open, closeIdx); - if (openIdx === -1) return null; - return content.slice(0, openIdx + open.length) + innerContent + content.slice(closeIdx); + const lines = content.split("\n"); + const found = findBlockLines(lines, open, close); + if (found === null) return null; + + return ( + lines.slice(0, found.openLine + 1).join("\n") + + innerContent + + lines.slice(found.closeLine).join("\n") + ); +} + +// Rewrite a legacy block to the comment markers. +function migrateLegacyMarkers(content) { + const lines = content.split("\n"); + const found = findBlockLines(lines, LEGACY_BLOCK_OPEN, LEGACY_BLOCK_CLOSE); + if (found === null) return content; + + lines[found.openLine] = lines[found.openLine].replace(LEGACY_BLOCK_OPEN, BLOCK_OPEN); + lines[found.closeLine] = lines[found.closeLine].replace(LEGACY_BLOCK_CLOSE, BLOCK_CLOSE); + return lines.join("\n"); +} + +// A file carrying one marker without its pair can never be filled again. Say so: +// silence about a block that does not sync is what kept the memory unloaded. +function reportUnpairedMarkers(filePath, content) { + const has = (marker) => content.includes(marker); + const unpaired = + has(BLOCK_OPEN) !== has(BLOCK_CLOSE) || + has(LEGACY_BLOCK_OPEN) !== has(LEGACY_BLOCK_CLOSE); + + if (unpaired) { + console.error(`update_memory: ${filePath} has an unpaired project memory marker, not synced`); + } + return unpaired; } function updateBlock(content, innerContent) { @@ -185,6 +255,10 @@ function gitAdd(childProcess, files) { // ── Main ────────────────────────────────────────────────────────── +// Runs as a script, never imported: no require, no module.exports, and every +// dependency pulled in with dynamic import(). The file is copied into the user's +// project by the CLI, so a project declaring "type": "module" decides how it is +// parsed. CommonJS syntax here would crash the hook on load in any such project. (async () => { const fs = await import("node:fs"); const path = await import("node:path"); @@ -204,15 +278,23 @@ function gitAdd(childProcess, files) { const rootFiles = scanRootFiles(fs, path); const onDemandFiles = ON_DEMAND_DIRS.flatMap((sub) => scanSubdir(fs, path, sub)); const changed = []; + let unpaired = false; for (const target of targets) { const original = readTextOrNull(fs, target.path); if (original === null) continue; const innerContent = buildBlockContent(rootFiles, onDemandFiles, target.syntax); - const updated = updateBlock(original, innerContent); - - if (updated === null || updated === original) continue; + // Compare against what is on disk, not against the migrated text: a file + // whose memory list is unchanged would otherwise look identical and skip + // the write, leaving the legacy markers in place forever. + const updated = updateBlock(migrateLegacyMarkers(original), innerContent); + + if (updated === null) { + if (reportUnpairedMarkers(target.path, original)) unpaired = true; + continue; + } + if (updated === original) continue; fs.writeFileSync(target.path, updated, "utf8"); changed.push(target.path); @@ -235,4 +317,9 @@ function gitAdd(childProcess, files) { // so staging its own two would leave a partial index that reads like the whole // change. The skill reports instead, and the user stages what they mean to commit. if (changed.length > 0 && tools.length === 0) gitAdd(childProcess, changed); + + // Only when tools were named, which means the skill called us and its sync + // action stops on a non-zero exit. The auto hook must never fail a session + // start over a file the user has yet to repair. + if (unpaired && tools.length > 0) process.exit(1); })(); diff --git a/plugins/aidd-context/skills/00-onboard/references/state/zones.md b/plugins/aidd-context/skills/00-onboard/references/state/zones.md index c0f57b545..ead0a597b 100644 --- a/plugins/aidd-context/skills/00-onboard/references/state/zones.md +++ b/plugins/aidd-context/skills/00-onboard/references/state/zones.md @@ -10,7 +10,7 @@ State-aware order: existing repo (code) => memory first, stack skipped. Greenfie | -------------- | ------------------------------------------------------------- | ------------------------ | -------------------------- | -------------------------------- | | tech stack | `INSTALL.md` exists OR repo established (code or synced memory) | β€” | tech stack | `aidd-context:01-bootstrap` | | project memory | `aidd_docs/memory/` has real content | files empty/placeholder | project knowledge saved | `aidd-context:02-project-memory` | -| memory wiring | the standard `` block in each used tool's context file | block present, off shape | knowledge loaded by the AI | `aidd-context:02-project-memory` | +| memory wiring | the standard project memory block in each used tool's context file | block present, off shape | knowledge loaded by the AI | `aidd-context:02-project-memory` | - tech stack missing only on greenfield (no code AND no synced memory). - memory wiring: no block or no context file = missing. Drift = a block present but not the standard one that imports the memory files. diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md index 9d3c13395..84d30658d 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md @@ -37,8 +37,8 @@ Project docs, memory, specs, and plans live in `aidd_docs/`. ### Project memory - - + + - If the block above is empty, run `ls -1tr aidd_docs/memory/` and read each file. - Load `aidd_docs/memory/external/*` when the user asks. diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/README.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/README.md index fb43b82a9..4e053e830 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/README.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/README.md @@ -10,7 +10,7 @@ Structured context the AI assistant reads to work on this project, so it does no - `CONTRIBUTING.md`: how to add or change project context. - `tasks/`: specs, plans, and run summaries, created as work happens. -The `` block inside each AI context file (`CLAUDE.md`, `AGENTS.md`, and the rest) is generated and kept in sync, never edited by hand. To change what the AI sees, add or remove files under `memory/`. See [`memory/README.md`](memory/README.md) for the load tiers and the current file index. +The project memory block inside each AI context file (`CLAUDE.md`, `AGENTS.md`, and the rest) is generated and kept in sync, never edited by hand. To change what the AI sees, add or remove files under `memory/`. See [`memory/README.md`](memory/README.md) for the load tiers and the current file index. ## The framework diff --git a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md index b97c915c8..11d30d42a 100644 --- a/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md +++ b/plugins/aidd-context/skills/02-project-memory/assets/templates/memory/README.md @@ -10,7 +10,7 @@ flowchart LR notes["internal/ Β· external/"] -.->|on demand| ai ``` -The root files load every session through the `` block in each AI context file. `internal/` and `external/` load only when relevant. +The root files load every session through the project memory block in each AI context file. `internal/` and `external/` load only when relevant. ## Files diff --git a/plugins/aidd-context/skills/10-learn/references/gather-protocol.md b/plugins/aidd-context/skills/10-learn/references/gather-protocol.md index 8ad631959..8b2287f76 100644 --- a/plugins/aidd-context/skills/10-learn/references/gather-protocol.md +++ b/plugins/aidd-context/skills/10-learn/references/gather-protocol.md @@ -17,6 +17,15 @@ Extract only durable project learning. | Signal outside the selected source's scope, even when noticed while reading | Drop | | Bug already fixed as part of the current change, unless the user explicitly asked to remember it as a decision | Drop | +## Retrospective lens + +For completed work, ask before applying the signal filter: + +- What caused avoidable delay, rework, or confusion? +- What should change next time? +- What durable context was missing? +- What should be removed, clarified, or automated? + For each candidate, include: - Source label. diff --git a/plugins/aidd-context/skills/11-explore/actions/01-survey.md b/plugins/aidd-context/skills/11-explore/actions/01-survey.md index d4fd5f180..19e06c0a2 100644 --- a/plugins/aidd-context/skills/11-explore/actions/01-survey.md +++ b/plugins/aidd-context/skills/11-explore/actions/01-survey.md @@ -14,7 +14,7 @@ A map grouped by axis, Tooling, Context, and Codebase. Each axis lists what is t 1. **Detect the tools.** Find which AI tools the project uses by the presence signal in [ai-mapping.md](../references/ai-mapping.md), keying on a tool's own mapped surfaces, never a shared parent directory. Propose the set when it is ambiguous, never assume one silently. 2. **Scan Tooling.** For each detected tool, gather the installed skills, agents, commands, rules, hooks, MCP servers, and plugins from the surfaces in [ai-mapping.md](../references/ai-mapping.md). -3. **Scan Context.** The memory bank under `aidd_docs/memory/` and whether its files are filled, any specs or plans under `aidd_docs/`, and whether the AI context files carry the `` block. +3. **Scan Context.** The memory bank under `aidd_docs/memory/` and whether its files are filled, any specs or plans under `aidd_docs/`, and whether the AI context files carry the project memory block. 4. **Scan Codebase.** The stack, from the manifest or from the memory bank, and the few top-level modules or layers. 5. **Present the map.** One section per axis, each a short list or count with one-line purposes. 6. **Propose to dig in.** Offer the three axes or all, and hand the pick to `02-drill`. Wait for the answer. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd363ec9c..c660f5134 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,11 +9,11 @@ importers: .: devDependencies: '@commitlint/cli': - specifier: ^21.2.1 - version: 21.2.1(@types/node@25.3.5)(conventional-commits-parser@7.1.0)(typescript@5.9.3) + specifier: ^21.2.2 + version: 21.2.2(@types/node@25.3.5)(conventional-commits-parser@7.1.2)(typescript@5.9.3) '@commitlint/config-conventional': - specifier: ^21.2.0 - version: 21.2.0 + specifier: ^21.2.2 + version: 21.2.2 ajv: specifier: 8.20.0 version: 8.20.0 @@ -21,8 +21,8 @@ importers: specifier: 3.0.1 version: 3.0.1(ajv@8.20.0) js-yaml: - specifier: 5.2.3 - version: 5.2.3 + specifier: 5.3.0 + version: 5.3.0 lefthook: specifier: ^2.1.10 version: 2.1.10 @@ -37,13 +37,13 @@ packages: resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@commitlint/cli@21.2.1': - resolution: {integrity: sha512-blsZGe29hJ72VGEFVl72IVYX+1vsfINpjA9yWQA6i7OKD/McGEOXg08sKIRKjFk4JvzhV/9n0l3i6NooPLTNfg==} + '@commitlint/cli@21.2.2': + resolution: {integrity: sha512-a+6hQxIxnpdvSvS2apvttPNbEliYsVC3PqFYDiiB2kjbwIsQsj1urvQ4Tkf70pKYozPalKAuRQmm/GHwndduqA==} engines: {node: '>=22.12.0'} hasBin: true - '@commitlint/config-conventional@21.2.0': - resolution: {integrity: sha512-Qf8WRDVcyVd14if6VTWenebxFbKnVnbzPUJjlzjkyJGeHK2xCGd63Dr1XZzj0plXKQb9P0BfOxoc1HVeCo2BWQ==} + '@commitlint/config-conventional@21.2.2': + resolution: {integrity: sha512-NxA37SZviusFUEYOQZ5hNnZ1h7O/KiemPkxjOlpzKJNnWxThiwc6/SaZhaPa8fyLvfRBAywhQhJJk8XESHWlpQ==} engines: {node: '>=22.12.0'} '@commitlint/config-validator@21.2.0': @@ -58,40 +58,40 @@ packages: resolution: {integrity: sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==} engines: {node: '>=22.12.0'} - '@commitlint/format@21.2.0': - resolution: {integrity: sha512-c4q64xaav2U83t7k7RyzJerBZurPer7FxUOY0RL5L/6CZijZ7K+s6HIBGIghj0ey1P2+seRX0J9XQYtDued6tg==} + '@commitlint/format@21.2.2': + resolution: {integrity: sha512-v6fvxZSc/AvVMROlr3H34+1766bZSYApRUSCAMjWamStPjKMvZ8GdvVA5YW/VQNgbFTmcMz6OYmSTJEvIjPrfA==} engines: {node: '>=22.12.0'} - '@commitlint/is-ignored@21.2.0': - resolution: {integrity: sha512-4/eB0vBN7L88O/oC4ajAEqi7j2ZfNgxl/+11RfAV9YosejZgDXhY2C9VcHnHJhOzPLoSy5P3Mg/46kqeyJfXKw==} + '@commitlint/is-ignored@21.2.2': + resolution: {integrity: sha512-9UoKNgfFE3LU7FrzierCvk3CdDfMDeVGC86qZiT/n0TIjfq/dmZ9MHuXd45OTNRa26ZanmJRxEtmiXk/lEJihg==} engines: {node: '>=22.12.0'} - '@commitlint/lint@21.2.0': - resolution: {integrity: sha512-ceO5dp9pLjEZ6y6qbq/uXWXDPykqqlTsyzoQ0NzecpisSJhK3kTy9qzQoPeJuWG/IMNdV1lO0RgmzqoAlSi1uw==} + '@commitlint/lint@21.2.2': + resolution: {integrity: sha512-Fy8JxEBzdmsYWFude/61GxXu5O+wEymwiRK2z9GL9R8mCsXphCoGxAFc5iHn5mjlfcSrhiiONE+ksf4KOjnaPg==} engines: {node: '>=22.12.0'} - '@commitlint/load@21.2.0': - resolution: {integrity: sha512-RjlzWQqruRwIenJEfZtq7kG97co97nKoHpflE5YnF61tDLXxHPrdWImgzw6VL6MlFyaOcVlk74eBV8ZQmc3oIA==} + '@commitlint/load@21.2.2': + resolution: {integrity: sha512-0Tt6wDPX167cjKC5D4zhm0+20wJJG+TN/TKovMOspfSe78rOnKX+MNzlVNiu6HyQPZChPJ8QBH31MVt6Bb8fCg==} engines: {node: '>=22.12.0'} '@commitlint/message@21.2.0': resolution: {integrity: sha512-YxGoiXD/HXNXLJPrQwE5poXa+XH0CBEm+mdvbHQP0g6MV/dmJyUFCzPNzZbxL93GvZ70TmtTK0Z0/IBpAqHv8g==} engines: {node: '>=22.12.0'} - '@commitlint/parse@21.2.0': - resolution: {integrity: sha512-QHWxG4d0PLTF634/AdyZ0MQS+CLn5YOuJlCFhMMlSGKFxzYGUetkHBj18xgBD+6fVzUrA2lrCdi/vlS2f/oYXg==} + '@commitlint/parse@21.2.2': + resolution: {integrity: sha512-MEkobPfvRp+z06Wro8HMG1BDGHzZmj82A1LH1nWeG3ipHpg/x4m6v3wEDvMBIKjRFUnfR3nBeFs3MVCr7UdAmg==} engines: {node: '>=22.12.0'} '@commitlint/read@21.2.1': resolution: {integrity: sha512-hUW7EJQnNTL0vPOmVMNK4CrnrNBN0nN+JJHReFkdHO5y4iyHeEmTBwuC15OCqUTjxWo7idnH1LftfpWVIaPWIA==} engines: {node: '>=22.12.0'} - '@commitlint/resolve-extends@21.2.0': - resolution: {integrity: sha512-4O/1j51+79Wth9s/MGxt/5gs0XYLDgNlYpltQfhAvLE0itusLKs9zruxbiNg1oOkmkb9L9L4USYGjEj7n87NxA==} + '@commitlint/resolve-extends@21.2.2': + resolution: {integrity: sha512-RPkJ/IFi7sMUUVbZLqwWFtWw/zRDcfFsmrPSiTMrt5wb7AdxOr86EGQFvmGzef5QKV5IPBWWCujqVTw1RWX44A==} engines: {node: '>=22.12.0'} - '@commitlint/rules@21.2.0': - resolution: {integrity: sha512-C2yXMNpiB8ETZKfx5JD8+ExgF8vTU1VQMKPSUUYwqKpw9oJWQBrlXBpdU038mj2WPjof7o9UzFpmTyBeGMZwZg==} + '@commitlint/rules@21.2.2': + resolution: {integrity: sha512-eplQzyYkBjYB1HyyRj8hkcK11Y9DU9nuBz7uOKEd6NpE9NGDytLFCAnlRE+OoiK/5sHEJsaz2RGhuWBvYzIbNA==} engines: {node: '>=22.12.0'} '@commitlint/to-lines@21.0.1': @@ -106,20 +106,20 @@ packages: resolution: {integrity: sha512-7zVFCDB2reMvJH5dmbKnOQPjZEvjdJTH8jc0U/PIPU1r3/+vf5pD1HlfitV2MWsWXrvu7u39iY1lyLUPOaN0Gw==} engines: {node: '>=22.12.0'} - '@conventional-changelog/git-client@3.1.0': - resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} + '@conventional-changelog/git-client@3.1.2': + resolution: {integrity: sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==} engines: {node: '>=22'} peerDependencies: conventional-commits-filter: ^6.0.1 - conventional-commits-parser: ^7.0.1 + conventional-commits-parser: ^7.1.2 peerDependenciesMeta: conventional-commits-filter: optional: true conventional-commits-parser: optional: true - '@conventional-changelog/template@1.2.1': - resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} + '@conventional-changelog/template@1.3.0': + resolution: {integrity: sha512-GsCw/qu92GI0EX6s7fxUi/SG1lmFjG9XZivxxEDZXqztuQKCn5o5wKdz4v005zci0Md7EZzgAwmQLoIEDZoaow==} engines: {node: '>=22'} '@simple-libs/child-process-utils@2.0.0': @@ -144,8 +144,8 @@ packages: ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} engines: {node: '>=12'} ansi-styles@6.2.3: @@ -167,21 +167,16 @@ packages: resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} engines: {node: '>=20'} - conventional-changelog-angular@9.2.1: - resolution: {integrity: sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==} + conventional-changelog-angular@9.3.0: + resolution: {integrity: sha512-0MWQLVUT1oVCsUGs9aAWteBVxPlLwJTn5VbQH7B0B3fDizZgrJ9QGnKl/2mp1+5P7153GCBCjO/v1aKJ6eysCg==} engines: {node: '>=22'} - conventional-changelog-conventionalcommits@10.2.1: - resolution: {integrity: sha512-n4Kr1HFMTf3iMbES0TMxKIcYtUUv4rKqyQQp2JwfOEfFCOfGT3Tq4mCyJ8S9/YPyWhydjfKrrvnyl+gCjA+mJQ==} + conventional-changelog-conventionalcommits@10.3.0: + resolution: {integrity: sha512-qag0zFD867Qq1DK0jAWicyWlEMS1FFC/BLVLISaoeI7Y6Em6aWchk7BCkhOTsecRpMsV6qX41XmlNnghiiTmSw==} engines: {node: '>=22'} - conventional-commits-parser@7.0.1: - resolution: {integrity: sha512-6VtskFpPsNkGVk/TY2RnV/MEdKfvCPBtQZN9x8jh9+k5RWBQ+tiaWn5UFCzTr0Dd88iKx7xghxbjBRp5uIzp3g==} - engines: {node: '>=22'} - hasBin: true - - conventional-commits-parser@7.1.0: - resolution: {integrity: sha512-DPp6hkUjvwIivxbkrTiLXeRswNv1A/4GFA2X6scXma0AMa9632V3TwxmrlkUIEtUktiM3Ln+RrSH2xlP3/jUTw==} + conventional-commits-parser@7.1.2: + resolution: {integrity: sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==} engines: {node: '>=22'} hasBin: true @@ -212,8 +207,8 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-toolkit@1.49.0: - resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + es-toolkit@1.50.0: + resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==} escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} @@ -263,8 +258,8 @@ packages: resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true - js-yaml@5.2.3: - resolution: {integrity: sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==} + js-yaml@5.3.0: + resolution: {integrity: sha512-muutsYr+e2+d3rTgUGslq5rxbBlUy3cJ61IsHag2QNDQV+7zXWjkUpmALIajhrlLlrgRUiymj6U3zUr/TMK84Q==} hasBin: true json-parse-even-better-errors@2.3.1: @@ -330,10 +325,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - meow@14.1.0: - resolution: {integrity: sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==} - engines: {node: '>=20'} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -366,12 +357,16 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.2.2: + resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} + engines: {node: '>=20'} + strip-ansi@7.2.0: resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} - tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} engines: {node: '>=18'} typescript@5.9.3: @@ -394,8 +389,8 @@ packages: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + yargs@18.1.0: + resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} snapshots: @@ -408,26 +403,26 @@ snapshots: '@babel/helper-validator-identifier@7.29.7': {} - '@commitlint/cli@21.2.1(@types/node@25.3.5)(conventional-commits-parser@7.1.0)(typescript@5.9.3)': + '@commitlint/cli@21.2.2(@types/node@25.3.5)(conventional-commits-parser@7.1.2)(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@25.3.5)(typescript@5.9.3) - '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.0) + '@commitlint/config-conventional': 21.2.2 + '@commitlint/format': 21.2.2 + '@commitlint/lint': 21.2.2 + '@commitlint/load': 21.2.2(@types/node@25.3.5)(typescript@5.9.3) + '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.2) '@commitlint/types': 21.2.0 - tinyexec: 1.2.4 - yargs: 18.0.0 + tinyexec: 1.3.0 + yargs: 18.1.0 transitivePeerDependencies: - '@types/node' - conventional-commits-filter - conventional-commits-parser - typescript - '@commitlint/config-conventional@21.2.0': + '@commitlint/config-conventional@21.2.2': dependencies: '@commitlint/types': 21.2.0 - conventional-changelog-conventionalcommits: 10.2.1 + conventional-changelog-conventionalcommits: 10.3.0 '@commitlint/config-validator@21.2.0': dependencies: @@ -437,36 +432,36 @@ snapshots: '@commitlint/ensure@21.2.0': dependencies: '@commitlint/types': 21.2.0 - es-toolkit: 1.49.0 + es-toolkit: 1.50.0 '@commitlint/execute-rule@21.0.1': {} - '@commitlint/format@21.2.0': + '@commitlint/format@21.2.2': dependencies: '@commitlint/types': 21.2.0 picocolors: 1.1.1 - '@commitlint/is-ignored@21.2.0': + '@commitlint/is-ignored@21.2.2': dependencies: '@commitlint/types': 21.2.0 semver: 7.8.5 - '@commitlint/lint@21.2.0': + '@commitlint/lint@21.2.2': dependencies: - '@commitlint/is-ignored': 21.2.0 - '@commitlint/parse': 21.2.0 - '@commitlint/rules': 21.2.0 + '@commitlint/is-ignored': 21.2.2 + '@commitlint/parse': 21.2.2 + '@commitlint/rules': 21.2.2 '@commitlint/types': 21.2.0 - '@commitlint/load@21.2.0(@types/node@25.3.5)(typescript@5.9.3)': + '@commitlint/load@21.2.2(@types/node@25.3.5)(typescript@5.9.3)': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/execute-rule': 21.0.1 - '@commitlint/resolve-extends': 21.2.0 + '@commitlint/resolve-extends': 21.2.2 '@commitlint/types': 21.2.0 cosmiconfig: 9.0.2(typescript@5.9.3) cosmiconfig-typescript-loader: 6.3.0(@types/node@25.3.5)(cosmiconfig@9.0.2(typescript@5.9.3))(typescript@5.9.3) - es-toolkit: 1.49.0 + es-toolkit: 1.50.0 is-plain-obj: 4.1.0 picocolors: 1.1.1 transitivePeerDependencies: @@ -475,31 +470,31 @@ snapshots: '@commitlint/message@21.2.0': {} - '@commitlint/parse@21.2.0': + '@commitlint/parse@21.2.2': dependencies: '@commitlint/types': 21.2.0 - conventional-changelog-angular: 9.2.1 - conventional-commits-parser: 7.1.0 + conventional-changelog-angular: 9.3.0 + conventional-commits-parser: 7.1.2 - '@commitlint/read@21.2.1(conventional-commits-parser@7.1.0)': + '@commitlint/read@21.2.1(conventional-commits-parser@7.1.2)': 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) - tinyexec: 1.2.4 + '@conventional-changelog/git-client': 3.1.2(conventional-commits-parser@7.1.2) + tinyexec: 1.3.0 transitivePeerDependencies: - conventional-commits-filter - conventional-commits-parser - '@commitlint/resolve-extends@21.2.0': + '@commitlint/resolve-extends@21.2.2': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/types': 21.2.0 - es-toolkit: 1.49.0 + es-toolkit: 1.50.0 global-directory: 5.0.0 resolve-from: 5.0.0 - '@commitlint/rules@21.2.0': + '@commitlint/rules@21.2.2': dependencies: '@commitlint/ensure': 21.2.0 '@commitlint/message': 21.2.0 @@ -514,18 +509,18 @@ snapshots: '@commitlint/types@21.2.0': dependencies: - conventional-commits-parser: 7.0.1 + conventional-commits-parser: 7.1.2 picocolors: 1.1.1 - '@conventional-changelog/git-client@3.1.0(conventional-commits-parser@7.1.0)': + '@conventional-changelog/git-client@3.1.2(conventional-commits-parser@7.1.2)': dependencies: '@simple-libs/child-process-utils': 2.0.0 '@simple-libs/stream-utils': 2.0.0 semver: 7.8.5 optionalDependencies: - conventional-commits-parser: 7.1.0 + conventional-commits-parser: 7.1.2 - '@conventional-changelog/template@1.2.1': {} + '@conventional-changelog/template@1.3.0': {} '@simple-libs/child-process-utils@2.0.0': dependencies: @@ -548,7 +543,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ansi-regex@6.2.2: {} + ansi-regex@6.3.0: {} ansi-styles@6.2.3: {} @@ -564,20 +559,15 @@ snapshots: strip-ansi: 7.2.0 wrap-ansi: 9.0.2 - conventional-changelog-angular@9.2.1: - dependencies: - '@conventional-changelog/template': 1.2.1 - - conventional-changelog-conventionalcommits@10.2.1: + conventional-changelog-angular@9.3.0: dependencies: - '@conventional-changelog/template': 1.2.1 + '@conventional-changelog/template': 1.3.0 - conventional-commits-parser@7.0.1: + conventional-changelog-conventionalcommits@10.3.0: dependencies: - '@simple-libs/stream-utils': 2.0.0 - meow: 14.1.0 + '@conventional-changelog/template': 1.3.0 - conventional-commits-parser@7.1.0: + conventional-commits-parser@7.1.2: dependencies: '@simple-libs/stream-utils': 2.0.0 argue-cli: 3.1.0 @@ -606,7 +596,7 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-toolkit@1.49.0: {} + es-toolkit@1.50.0: {} escalade@3.2.0: {} @@ -641,7 +631,7 @@ snapshots: dependencies: argparse: 2.0.1 - js-yaml@5.2.3: + js-yaml@5.3.0: dependencies: argparse: 2.0.1 @@ -694,8 +684,6 @@ snapshots: lines-and-columns@1.2.4: {} - meow@14.1.0: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -723,11 +711,16 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 + string-width@8.2.2: + dependencies: + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 - tinyexec@1.2.4: {} + tinyexec@1.3.0: {} typescript@5.9.3: {} @@ -743,11 +736,11 @@ snapshots: yargs-parser@22.0.0: {} - yargs@18.0.0: + yargs@18.1.0: dependencies: cliui: 9.0.1 escalade: 3.2.0 get-caller-file: 2.0.5 - string-width: 7.2.0 + string-width: 8.2.2 y18n: 5.0.8 yargs-parser: 22.0.0 diff --git a/scripts/__tests__/check-context-imports.test.js b/scripts/__tests__/check-context-imports.test.js new file mode 100644 index 000000000..f6e32e90d --- /dev/null +++ b/scripts/__tests__/check-context-imports.test.js @@ -0,0 +1,72 @@ +const assert = require("node:assert/strict"); +const test = require("node:test"); + +const path = require("node:path"); + +const { findHiddenImports, runCli } = require("../check-context-imports.js"); + +test("an import inside a bare tag block never loads", () => { + const hidden = findHiddenImports( + ["", "@aidd_docs/memory/vcs.md", ""].join("\n"), + ); + + assert.equal(hidden.length, 1); + assert.equal(hidden[0].line, 2); + assert.equal(hidden[0].openedBy.text, ""); +}); + +test("a blank line after the opening marker takes the imports out of the block", () => { + const hidden = findHiddenImports( + [ + "", + "", + "@aidd_docs/memory/vcs.md", + "", + "", + ].join("\n"), + ); + + assert.deepEqual(hidden, []); +}); + +test("an import glued to a comment marker is still hidden", () => { + const hidden = findHiddenImports( + ["", "@aidd_docs/memory/vcs.md"].join("\n"), + ); + + assert.equal(hidden.length, 1); +}); + +test("the broken shape quoted in documentation is not a finding", () => { + const hidden = findHiddenImports( + ["Do not write this:", "", "```markdown", "", "@a.md", "```", ""].join("\n"), + ); + + assert.deepEqual(hidden, []); +}); + +test("an import on a bare line loads", () => { + assert.deepEqual(findHiddenImports("# Title\n\n@a.md\n"), []); +}); + +test("a longer fence is not closed by a shorter one inside it", () => { + const hidden = findHiddenImports( + ["````markdown", "```", "", "@a.md", "```", "````", ""].join("\n"), + ); + + assert.deepEqual(hidden, []); +}); + +test("an explicit path that cannot be read fails instead of passing", () => { + const said = []; + assert.equal(runCli(["does-not-exist.md"], (line) => said.push(line)), 1); + assert.match(said.join("\n"), /Not a readable file/u); +}); + +test("a directory given as an explicit path fails instead of crashing", () => { + assert.equal(runCli(["scripts"], () => {}), 1); +}); + +test("the repository's own context files load their imports", () => { + assert.equal(runCli([path.join(__dirname, "..", "..", "CLAUDE.md")], () => {}), 0); +}); diff --git a/scripts/__tests__/update-memory.test.js b/scripts/__tests__/update-memory.test.js new file mode 100644 index 000000000..e5bae51f9 --- /dev/null +++ b/scripts/__tests__/update-memory.test.js @@ -0,0 +1,192 @@ +const assert = require("node:assert/strict"); +const { spawnSync } = require("node:child_process"); +const fs = require("node:fs"); +const os = require("node:os"); +const path = require("node:path"); +const test = require("node:test"); + +// The hook is a script, not a module: the CLI copies it into the user's project, +// where a "type": "module" package.json decides how it is parsed. Driving it as a +// subprocess is the only way to test what actually ships. +const HOOK = path.resolve(__dirname, "../../plugins/aidd-context/hooks/update_memory.js"); + +const OPEN = ""; +const CLOSE = ""; + +/** A throwaway project with a memory bank, a context file, and the hook run in it. */ +function run({ context, bank = ["architecture.md"], onDemand = [], packageJson, hookAt, args, runs = 1 }) { + const root = fs.mkdtempSync(path.join(os.tmpdir(), "update-memory-")); + try { + fs.mkdirSync(path.join(root, "aidd_docs/memory"), { recursive: true }); + for (const file of bank) fs.writeFileSync(path.join(root, "aidd_docs/memory", file), "# x\n"); + for (const file of onDemand) { + const full = path.join(root, "aidd_docs/memory", file); + fs.mkdirSync(path.dirname(full), { recursive: true }); + fs.writeFileSync(full, "# x\n"); + } + if (context !== undefined) fs.writeFileSync(path.join(root, "CLAUDE.md"), context); + if (packageJson) fs.writeFileSync(path.join(root, "package.json"), packageJson); + + // Copying the hook in mirrors how the CLI installs it, so the project's own + // package.json governs the module system exactly as it does for a user. + let hook = HOOK; + if (hookAt) { + hook = path.join(root, hookAt); + fs.mkdirSync(path.dirname(hook), { recursive: true }); + fs.copyFileSync(HOOK, hook); + } + + const invoke = () => spawnSync(process.execPath, [hook, ...(args ?? ["claude"])], { cwd: root }); + const read = () => fs.readFileSync(path.join(root, "CLAUDE.md"), "utf8"); + + const first = invoke(); + const content = read(); + // Read everything before the finally below removes the project. + return { + status: first.status, + stderr: first.stderr.toString(), + content, + contentAfterRerun: runs > 1 ? (invoke(), read()) : content, + }; + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } +} + +test("the hook runs in a project declaring itself an ES module", () => { + const run1 = run({ + context: `# P\n\n${OPEN}\n${CLOSE}\n`, + packageJson: '{ "type": "module" }\n', + hookAt: ".claude/hooks/aidd-context/update_memory.js", + }); + + assert.equal(run1.stderr, ""); + assert.equal(run1.status, 0); + assert.match(run1.content, /@aidd_docs\/memory\/architecture\.md/u); +}); + +test("a legacy block is migrated to the comment markers and filled", () => { + const content = run({ + context: "# P\n\n\n@aidd_docs/memory/old.md\n\n", + }).content; + + assert.equal(content.includes(""), false); + assert.equal(content, `# P\n\n${OPEN}\n\n@aidd_docs/memory/architecture.md\n\n${CLOSE}\n`); +}); + +test("a legacy pair quoted in prose is left alone and the real block still migrates", () => { + const quote = "Old shape: `` ... ``."; + const content = run({ + context: `${quote}\n\n\n\n`, + }).content; + + assert.equal(content.split("\n")[0], quote); + assert.equal(content.split("\n")[2], OPEN); +}); + +test("a legacy pair inside a code fence is not the block that gets rewritten", () => { + const content = run({ + context: [ + "```markdown", + "", + "", + "```", + "", + "", + "", + "", + ].join("\n"), + }).content; + + const lines = content.split("\n"); + assert.equal(lines[1], ""); + assert.equal(lines[5], OPEN); +}); + +test("the imports keep a blank line on each side, so nothing hides them", () => { + const content = run({ + context: `${OPEN}\n${CLOSE}\n`, + bank: ["architecture.md", "vcs.md"], + }).content; + + assert.equal( + content, + `${OPEN}\n\n@aidd_docs/memory/architecture.md\n@aidd_docs/memory/vcs.md\n\n${CLOSE}\n`, + ); +}); + +test("filling is idempotent", () => { + const result = run({ context: `${OPEN}\n${CLOSE}\n`, runs: 2 }); + + assert.equal(result.contentAfterRerun, result.content); + assert.match(result.content, /@aidd_docs\/memory\/architecture\.md/u); +}); + +test("the on-demand tier is listed without an import prefix", () => { + const content = run({ + context: `${OPEN}\n${CLOSE}\n`, + onDemand: ["internal/decision.md"], + }).content; + + assert.match(content, /^- aidd_docs\/memory\/internal\/decision\.md$/mu); +}); + +test("a file holding one marker without its pair reports instead of skipping silently", () => { + const result = run({ context: `# P\n\n\n${CLOSE}\n` }); + + assert.match(result.stderr, /unpaired project memory marker/u); +}); + +test("a context file with no block at all is skipped quietly", () => { + const result = run({ context: "# P\n\nNo block here.\n" }); + + assert.equal(result.stderr, ""); + assert.equal(result.content, "# P\n\nNo block here.\n"); +}); + +test("an unknown tool name is rejected", () => { + const result = run({ context: `${OPEN}\n${CLOSE}\n`, args: ["emacs"] }); + + assert.equal(result.status, 1); + assert.match(result.stderr, /unknown tool emacs/u); +}); + +test("a new-marker pair quoted in prose above the block does not hijack the splice", () => { + const quote = `Upgrade note: the block now uses \`${OPEN}\` and \`${CLOSE}\`.`; + const result = run({ context: `${quote}\n\n${OPEN}\n${CLOSE}\n` }); + + assert.equal(result.content.split("\n")[0], quote); + assert.equal( + result.content, + `${quote}\n\n${OPEN}\n\n@aidd_docs/memory/architecture.md\n\n${CLOSE}\n`, + ); +}); + +test("a nested fence does not close the example that documents the old shape", () => { + const content = run({ + context: [ + "````markdown", + "```", + "", + "", + "```", + "````", + "", + "", + "", + "", + ].join("\n"), + }).content; + + const lines = content.split("\n"); + assert.equal(lines[2], "", "the documented example must stay as written"); + assert.equal(lines[7], OPEN, "the real block must be the one migrated"); + assert.match(content, /@aidd_docs\/memory\/architecture\.md/u); +}); + +test("an unpaired marker fails the run when the skill named the tools", () => { + const result = run({ context: `# P\n\n${OPEN}\n@stale.md\n` }); + + assert.equal(result.status, 1); + assert.match(result.stderr, /unpaired project memory marker/u); +}); diff --git a/scripts/check-context-imports.js b/scripts/check-context-imports.js new file mode 100644 index 000000000..7dca7100f --- /dev/null +++ b/scripts/check-context-imports.js @@ -0,0 +1,143 @@ +#!/usr/bin/env node +/** + * check-context-imports.js - Fails when an `@import` in an AI context file sits + * inside an HTML block, where the context loader skips it. + * + * Any line whose first non-space character is `<` is treated as opening an HTML + * block that runs until the next blank line. Imports inside one are ignored + * exactly like those in a fenced code block, so the file looks correct and loads + * nothing, and nothing reports it. + * + * That rule is deliberately stricter than CommonMark, which closes a comment on + * its own line. Context loaders are not all CommonMark, and a blank line after + * the opening line costs nothing and holds under either reading. + * + * Usage: + * node scripts/check-context-imports.js every context file + * node scripts/check-context-imports.js CLAUDE.md ... only those files + */ + +const fs = require("node:fs"); +const path = require("node:path"); + +const ROOT = path.resolve(__dirname, ".."); + +// The files a context loader reads. Anywhere in the tree, not just the root: +// a monorepo package carries its own. +const CONTEXT_FILENAMES = ["CLAUDE.md", "AGENTS.md", "copilot-instructions.md"]; + +// Directories to never walk into, matched by name at any depth. Same set as +// scripts/check-markdown-links.js, which walks the same tree. +const SKIPPED_DIRS = new Set([".git", "node_modules", "worktrees", ".specstory"]); + +// Snapshots of older framework versions, kept on the old shape as test input. +const EXCLUDED_PATHS = ["cli/tests/fixtures"]; + +const IMPORT_LINE = /^\s{0,3}@\S+/u; +const HTML_BLOCK_OPEN = /^\s{0,3} normalized === dir || normalized.startsWith(`${dir}/`)); +} + +function collectContextFiles(dir = ROOT, found = []) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (SKIPPED_DIRS.has(entry.name)) continue; + if (isExcluded(path.relative(ROOT, full))) continue; + collectContextFiles(full, found); + } else if (CONTEXT_FILENAMES.includes(entry.name)) { + found.push(full); + } + } + return found; +} + +/** + * Imports that a context loader will skip, with the line that hid them. + * Code blocks are skipped: the broken shape is quoted in documentation. + */ +function findHiddenImports(content) { + const hidden = []; + let fence = null; + let openedAt = null; + + content.split("\n").forEach((line, index) => { + const opener = FENCE.exec(line); + + if (fence) { + // A fence closes only on the same character, repeated at least as often. + if (opener && opener[1][0] === fence[0] && opener[1].length >= fence.length) fence = null; + return; + } + if (opener) { + fence = opener[1]; + return; + } + if (line.trim() === "") { + openedAt = null; + return; + } + if (openedAt === null && HTML_BLOCK_OPEN.test(line)) { + openedAt = { line: index + 1, text: line.trim() }; + return; + } + if (openedAt !== null && IMPORT_LINE.test(line)) { + hidden.push({ line: index + 1, import: line.trim(), openedBy: openedAt }); + } + }); + + return hidden; +} + +function checkFiles(files) { + const problems = []; + for (const file of files) { + for (const hidden of findHiddenImports(fs.readFileSync(file, "utf8"))) { + problems.push({ file, ...hidden }); + } + } + return problems; +} + +function reportProblems(problems, logger = console.error, successLogger = console.log) { + if (problems.length === 0) { + successLogger("βœ… context imports load: none sit inside an HTML block"); + return; + } + logger(`❌ ${problems.length} import(s) never load: inside an HTML block`); + for (const problem of problems) { + const where = `${path.relative(ROOT, problem.file)}:${problem.line}`; + logger(` ${where} ${problem.import}`); + logger(` inside the block opened line ${problem.openedBy.line} by ${problem.openedBy.text}`); + } + logger(" Add a blank line after the opening line, or move the imports out of the block."); +} + +function runCli(argv = process.argv.slice(2), logger = console.error) { + if (argv.length === 0) { + const problems = checkFiles(collectContextFiles()); + reportProblems(problems); + return problems.length === 0 ? 0 : 1; + } + + // A path given explicitly and not read is an error. Skipping it would turn the + // check into a green no-op, which is the failure it exists to catch. + const files = argv.map((f) => path.resolve(ROOT, f)); + const missing = files.filter((f) => !fs.existsSync(f) || !fs.statSync(f).isFile()); + if (missing.length > 0) { + for (const f of missing) logger(`❌ Not a readable file: ${path.relative(ROOT, f)}`); + return 1; + } + + const problems = checkFiles(files); + reportProblems(problems); + return problems.length === 0 ? 0 : 1; +} + +module.exports = { findHiddenImports, checkFiles, reportProblems, collectContextFiles, runCli }; + +if (require.main === module) process.exit(runCli()); diff --git a/scripts/skill-eval/cases.json b/scripts/skill-eval/cases.json index 90aacca46..f0d73ab6e 100644 --- a/scripts/skill-eval/cases.json +++ b/scripts/skill-eval/cases.json @@ -251,7 +251,8 @@ "fileContains": { "CLAUDE.md": [ "@aidd_docs/memory/architecture.md", - "@aidd_docs/memory/vcs.md" + "@aidd_docs/memory/vcs.md", + "" ] } }