diff --git a/.archgate/adrs/GEN-001-documentation-site.md b/.archgate/adrs/GEN-001-documentation-site.md new file mode 100644 index 00000000..e969af6c --- /dev/null +++ b/.archgate/adrs/GEN-001-documentation-site.md @@ -0,0 +1,244 @@ +--- +id: GEN-001 +title: Documentation Site +domain: general +rules: false +--- + +## Context + +The Archgate CLI needs a public documentation site for users, contributors, and AI agents. A README and inline code comments are insufficient for a project with multiple commands, an MCP server, a rule API, and editor integrations. Without a dedicated docs site: + +1. **Discoverability is poor** — New users cannot browse guides, reference pages, or examples without reading source code +2. **Onboarding is slow** — Contributors must reverse-engineer conventions from existing code rather than reading a structured guide +3. **AI agents lack context** — AI coding assistants benefit from well-structured reference documentation when generating Archgate-compatible rules and configurations +4. **Information is scattered** — Installation instructions, API reference, and integration guides live in different places (README, source comments, planning docs) with no unified navigation + +**Alternatives considered:** + +- **README-only documentation** — Keeping all documentation in `README.md` is simple and requires no build tooling. However, README files become unwieldy beyond 500 lines, lack navigation, and cannot provide the structured multi-page experience users expect from a CLI tool. The Archgate README would need to cover 9 CLI commands, 5 MCP tools, a full Rule API, 3 editor integrations, and multiple guides — far too much for a single file. +- **Docusaurus (React-based)** — A mature documentation framework with a large ecosystem. However, Docusaurus is built on React and requires Node.js, adding a heavyweight runtime and dependency tree that conflicts with the project's Bun-first philosophy. Its configuration is more complex than needed for a documentation site of this scope. +- **VitePress (Vue-based)** — A fast, Vue-powered documentation generator. While lighter than Docusaurus, it still requires a framework runtime (Vue) and has less flexibility for custom content than Astro. Its Markdown extensions are proprietary rather than standard MDX. +- **Starlight (Astro-based)** — An Astro integration purpose-built for documentation sites. It uses standard MDX, runs under Bun via `bunx --bun astro`, produces static HTML with zero client-side JavaScript by default, and provides built-in search (Pagefind), sidebar navigation, and dark mode. Its component-based architecture allows embedding interactive elements without framework lock-in. + +For Archgate, Starlight is the natural choice: it aligns with the project's Bun-first toolchain ([ARCH-006](./ARCH-006-dependency-policy.md)), produces a fast static site suitable for GitHub Pages, and its MDX format is familiar to TypeScript developers who already write Archgate rules. + +## Decision + +The documentation site MUST be an Astro 5 / Starlight project in the `docs/` directory, deployed to `cli.archgate.dev` via GitHub Pages. The docs site is a **separate concern** from the CLI codebase — it has its own `package.json`, `tsconfig.json`, `bun.lock`, and build pipeline. It does NOT participate in the CLI's `bun run validate` pipeline. + +**Scope:** This ADR covers the documentation site's structure, tooling, content organization, and deployment. It does NOT cover the content itself (what to document) — that is an editorial decision, not an architectural one. + +**Technical stack:** + +- **Framework:** Astro 5 with `@astrojs/starlight` integration +- **Content format:** MDX files in `docs/src/content/docs/` +- **Content API:** Astro 5 Content Layer with `docsLoader()` and `docsSchema()` in `docs/src/content.config.ts` +- **Build runtime:** Bun (`bunx --bun astro build`) +- **Deployment:** GitHub Actions → GitHub Pages (custom domain via `CNAME` in `docs/public/`) +- **TypeScript:** Extends `astro/tsconfigs/strict` (separate from CLI tsconfig) + +**Sidebar structure** follows five categories: + +| Category | Path prefix | Purpose | +| --------------- | ------------------ | --------------------------------------- | +| Getting Started | `getting-started/` | Installation and first-use walkthrough | +| Core Concepts | `concepts/` | ADRs, rules, and domains explained | +| Guides | `guides/` | How-to articles for specific tasks | +| Reference | `reference/` | Exhaustive API and schema documentation | +| Examples | `examples/` | Copy-pasteable code patterns | + +Every content page MUST appear in both the file system (`docs/src/content/docs//.mdx`) and the sidebar configuration in `docs/astro.config.mjs`. + +**Dependencies** are intentionally minimal: + +| Package | Purpose | +| -------------------- | ------------------------- | +| `astro` | Static site generator | +| `@astrojs/starlight` | Documentation integration | +| `sharp` | Image optimization | + +No CLI source dependencies (commander, zod, etc.) are permitted in `docs/package.json`. + +## Do's and Don'ts + +### Do + +- **DO** use MDX format (`.mdx`) for all content pages in `docs/src/content/docs/` +- **DO** follow the 5-category sidebar structure: Getting Started, Core Concepts, Guides, Reference, Examples +- **DO** use the Astro 5 Content Layer API with `docsLoader()` and `docsSchema()` in `docs/src/content.config.ts` +- **DO** keep `docs/package.json` private with only `astro`, `@astrojs/starlight`, and `sharp` as dependencies +- **DO** use `bunx --bun astro` for all Astro commands (`dev`, `build`, `preview`) to run under the Bun runtime +- **DO** place the `CNAME` file in `docs/public/` for GitHub Pages custom domain resolution +- **DO** use root convenience scripts (`docs:dev`, `docs:build`, `docs:preview`) when running docs commands from the repository root +- **DO** escape curly braces in MDX when showing template syntax (e.g., `adr://\{id\}`) — MDX interprets bare `{}` as JavaScript expressions +- **DO** add new pages to both the file system AND the sidebar configuration in `docs/astro.config.mjs` +- **DO** keep reference pages accurate to CLI source code — when CLI APIs change, update the corresponding reference docs in the same PR + +### Don't + +- **DON'T** add the docs build to the CLI `validate` pipeline — docs build failures MUST NOT block CLI development or CI +- **DON'T** share `tsconfig.json` with the CLI project — the docs site uses `astro/tsconfigs/strict`, the CLI uses its own TypeScript configuration +- **DON'T** use bare `{}` in MDX content — always escape as `\{\}` when showing literal curly braces in prose or code fence labels +- **DON'T** add CLI source dependencies (`@commander-js/extra-typings`, `zod`, `@modelcontextprotocol/sdk`, `inquirer`) to `docs/package.json` +- **DON'T** modify the `deploy-docs.yml` workflow to use Node instead of Bun — the project standardizes on Bun for all build tooling +- **DON'T** create content files outside `docs/src/content/docs/` — Starlight expects this exact directory structure via `docsLoader()` +- **DON'T** use auto-generated content collections — Astro 5 requires an explicit `docs/src/content.config.ts` with `docsLoader()` and `docsSchema()` +- **DON'T** install `docs/` dependencies from the repository root — always `cd docs && bun install` or use the `docs:*` convenience scripts + +## Implementation Pattern + +### Directory Structure + +``` +docs/ + astro.config.mjs # Starlight config, sidebar, site URL + package.json # Private, docs-only dependencies + tsconfig.json # Extends astro/tsconfigs/strict + bun.lock # Docs-specific lockfile + public/ + CNAME # cli.archgate.dev + src/ + content.config.ts # Astro 5 Content Layer registration + content/ + docs/ + index.mdx # Landing page (template: splash) + getting-started/ + installation.mdx + quick-start.mdx + concepts/ + adrs.mdx + rules.mdx + domains.mdx + guides/ + writing-adrs.mdx + writing-rules.mdx + ci-integration.mdx + claude-code-plugin.mdx + cursor-integration.mdx + mcp-server.mdx + pre-commit-hooks.mdx + reference/ + cli-commands.mdx + mcp-tools.mdx + rule-api.mdx + adr-schema.mdx + examples/ + common-rule-patterns.mdx +``` + +### Content Layer Configuration + +```typescript +// docs/src/content.config.ts — Required for Astro 5 +import { defineCollection } from "astro:content"; +import { docsLoader } from "@astrojs/starlight/loaders"; +import { docsSchema } from "@astrojs/starlight/schema"; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; +``` + +### Adding a New Page + +When adding a new documentation page, two changes are always required: + +1. Create the MDX file at `docs/src/content/docs//.mdx` with frontmatter: + +```mdx +--- +title: Page Title +description: Brief description for search engines and social cards. +--- + +Content here... +``` + +2. Add the page to the sidebar in `docs/astro.config.mjs`: + +```javascript +{ + label: "Category Name", + items: [ + // existing items... + { label: "Page Title", slug: "category/slug" }, + ], +} +``` + +### MDX Curly Brace Escaping + +MDX treats `{}` as JavaScript expressions. When documenting template-style syntax, escape the braces: + +```mdx + + +The resource URI format is `adr://{id}`. + + + +The resource URI format is `adr://\{id\}`. +``` + +## Consequences + +### Positive + +- **Single source of truth** — All user-facing documentation lives in one structured, navigable site rather than scattered across README, source comments, and planning docs +- **Search built-in** — Starlight integrates Pagefind for full-text search across all documentation pages with zero configuration +- **Consistent with CLI toolchain** — Built with Bun (`bunx --bun astro`), aligning with the project's Bun-first philosophy established in [ARCH-006](./ARCH-006-dependency-policy.md) +- **AI-friendly structure** — AI agents can reference well-structured MDX pages for accurate code generation; the MCP server guide documents how agents interact with Archgate +- **Zero client-side JavaScript** — Astro renders static HTML by default; the docs site loads instantly without framework hydration overhead +- **Automatic deployment** — The `deploy-docs.yml` workflow deploys on every merge to `main` that touches `docs/`, with no manual steps + +### Negative + +- **Separate dependency tree** — The `docs/` directory has its own `node_modules`, `bun.lock`, and package versions that must be maintained independently from the CLI +- **Astro/Starlight learning curve** — Contributors editing documentation must understand MDX syntax, Astro's Content Layer API, and Starlight's component library (CardGrid, Tabs, etc.) +- **Manual sidebar synchronization** — Adding a new page requires updating both the file system and `astro.config.mjs`; forgetting either results in a broken or invisible page + +### Risks + +- **Astro/Starlight breaking changes** — Major version upgrades to Astro or Starlight may change the Content Layer API, configuration format, or component interfaces. + - **Mitigation:** Dependencies are pinned to major versions (`astro@^5`, `@astrojs/starlight@^0.34`). Upgrades are performed explicitly with full build verification. Astro follows semver and publishes migration guides for major releases. +- **Documentation drift from source code** — Reference pages (CLI Commands, Rule API, MCP Tools, ADR Schema) may fall out of sync as the CLI evolves. + - **Mitigation:** The "DO keep reference pages accurate to CLI source code" rule requires docs updates in the same PR that changes CLI APIs. Code reviewers MUST verify this during review. +- **GitHub Pages deployment failures** — Build or deployment failures in `deploy-docs.yml` may leave stale documentation live. + - **Mitigation:** The workflow uses `workflow_dispatch` for manual re-deployment. Build failures are visible in the Actions tab. The docs build is isolated from CLI CI, so docs failures never block CLI releases. + +## Compliance and Enforcement + +### Automated Enforcement + +No automated rules are defined for this ADR (`rules: false`). Future opportunities include: + +- A rule verifying that every MDX file in `docs/src/content/docs/` has a corresponding sidebar entry in `astro.config.mjs` +- A rule checking that `docs/package.json` does not contain CLI source dependencies + +### Manual Enforcement + +Code reviewers MUST verify during docs PRs: + +1. New pages are added to both the file system and the sidebar configuration +2. MDX files use proper frontmatter (`title` and `description` fields) +3. Curly braces in prose are escaped (`\{\}`) when showing template syntax +4. Reference pages are updated when the corresponding CLI API changes +5. No CLI source dependencies are added to `docs/package.json` +6. The docs build succeeds locally (`bun run docs:build`) before merging + +### Deployment + +The `deploy-docs.yml` GitHub Actions workflow handles deployment: + +- **Trigger:** Push to `main` with changes in `docs/**`, or manual `workflow_dispatch` +- **Build:** `moonrepo/setup-toolchain@v0` → `bun install --frozen-lockfile` → `bunx --bun astro build` +- **Deploy:** `actions/upload-pages-artifact@v3` + `actions/deploy-pages@v4` to GitHub Pages +- **Custom domain:** `docs/public/CNAME` contains `cli.archgate.dev` + +## References + +- [Astro documentation](https://docs.astro.build) — Framework reference +- [Starlight documentation](https://starlight.astro.build) — Documentation integration reference +- [ARCH-006 — Dependency Policy](./ARCH-006-dependency-policy.md) — Bun-first toolchain philosophy that extends to the docs build +- [deploy-docs.yml](../../.github/workflows/deploy-docs.yml) — GitHub Actions deployment workflow diff --git a/.claude/agent-memory/archgate-developer/MEMORY.md b/.claude/agent-memory/archgate-developer/MEMORY.md index 8cee1508..2b0e8bd1 100644 --- a/.claude/agent-memory/archgate-developer/MEMORY.md +++ b/.claude/agent-memory/archgate-developer/MEMORY.md @@ -12,7 +12,7 @@ Skipping steps 2 or 3 is a workflow violation. The user should NEVER have to inv ## Version References -- **Minimum version** (`>=1.2.21`): Enforced in `src/cli.ts`, documented in CLAUDE.md "Technology Stack" and `docs/03-technical-plan.md`. This is the user-facing requirement. +- **Minimum version** (`>=1.2.21`): Enforced in `src/cli.ts`, documented in CLAUDE.md "Technology Stack" and `plans/03-technical-plan.md`. This is the user-facing requirement. - **Pinned version** (`1.3.8`): Set in `.prototools`, referenced in ADR risk sections (ARCH-005, ARCH-006) and CLAUDE.md "Toolchain" section. This is the dev toolchain version. - These are intentionally different. When upgrading the pinned version, update `.prototools` + ADR risk sections + CLAUDE.md toolchain. Do NOT change the minimum unless a new Bun API is required. diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 00000000..3f960b71 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,58 @@ +name: Deploy Docs + +on: + push: + branches: + - main + paths: + - "docs/**" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: deploy-docs + cancel-in-progress: true + +jobs: + build: + name: Build Docs + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: moonrepo/setup-toolchain@v0 + with: + auto-install: true + + - name: Install dependencies + run: bun install --frozen-lockfile + working-directory: docs + + - name: Build docs + run: bunx --bun astro build + working-directory: docs + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/dist + + deploy: + name: Deploy to GitHub Pages + needs: build + runs-on: ubuntu-latest + timeout-minutes: 5 + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 684b65f7..b75e8253 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ coverage # Platform package binaries (injected by CI) packages/*/bin/archgate + +# Docs site build artifacts +docs/.astro/ diff --git a/.npmignore b/.npmignore index 44e70b4c..a837b7a5 100644 --- a/.npmignore +++ b/.npmignore @@ -11,4 +11,6 @@ dist .czrc .simple-release.js bunfig.toml -bun.lock \ No newline at end of file +bun.lock +docs +plans \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 0ad8ca06..274a744c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,3 +4,4 @@ coverage bun.lock CHANGELOG.md packages/*/bin/ +docs/.astro diff --git a/README.md b/README.md index 0704aec2..77eca526 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,31 @@ When a rule is violated, `archgate check` reports the file, line, and which ADR ## Installation ```bash +# npm npm install -g archgate + +# Bun +bun install -g archgate + +# Yarn +yarn global add archgate + +# pnpm +pnpm add -g archgate ``` -**Requirements:** macOS (arm64), Linux (x86_64), or Windows (x86_64). Node.js is only needed to run the wrapper — the CLI itself is a standalone binary. +You can also install Archgate as a dev dependency and run it through your package manager: + +```bash +# Install as dev dependency +npm install -D archgate # or: bun add -d archgate + +# Run via package manager +npx archgate check # npm / Yarn / pnpm +bun run archgate check # Bun +``` + +**Requirements:** macOS (arm64), Linux (x86_64), or Windows (x86_64). Node.js is only needed to run the npm/yarn/pnpm wrapper — the CLI itself is a standalone binary. > **Using [proto](https://moonrepo.dev/proto)?** Add the following to `~/.proto/config.toml` and your shell profile so globals persist across Node.js version switches: > @@ -59,8 +80,8 @@ npm install -g archgate ## Quick start ```bash -# 1. Install -npm install -g archgate +# 1. Install (pick your package manager) +npm install -g archgate # or: bun install -g archgate # 2. Initialize governance in your project cd my-project diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs new file mode 100644 index 00000000..b31d7d60 --- /dev/null +++ b/docs/astro.config.mjs @@ -0,0 +1,82 @@ +import { defineConfig } from "astro/config"; +import starlight from "@astrojs/starlight"; + +export default defineConfig({ + site: "https://cli.archgate.dev", + integrations: [ + starlight({ + title: "Archgate", + description: + "Enforce Architecture Decision Records as executable rules — for both humans and AI agents.", + social: [ + { + icon: "github", + label: "GitHub", + href: "https://github.com/archgate/cli", + }, + ], + editLink: { + baseUrl: "https://github.com/archgate/cli/edit/main/docs/", + }, + sidebar: [ + { + label: "Getting Started", + items: [ + { label: "Installation", slug: "getting-started/installation" }, + { label: "Quick Start", slug: "getting-started/quick-start" }, + ], + }, + { + label: "Core Concepts", + items: [ + { + label: "Architecture Decision Records", + slug: "concepts/adrs", + }, + { label: "Rules", slug: "concepts/rules" }, + { label: "Domains", slug: "concepts/domains" }, + ], + }, + { + label: "Guides", + items: [ + { label: "Writing ADRs", slug: "guides/writing-adrs" }, + { label: "Writing Rules", slug: "guides/writing-rules" }, + { label: "CI Integration", slug: "guides/ci-integration" }, + { + label: "Claude Code Plugin", + slug: "guides/claude-code-plugin", + }, + { + label: "Cursor Integration", + slug: "guides/cursor-integration", + }, + { label: "MCP Server", slug: "guides/mcp-server" }, + { + label: "Pre-commit Hooks", + slug: "guides/pre-commit-hooks", + }, + ], + }, + { + label: "Reference", + items: [ + { label: "CLI Commands", slug: "reference/cli-commands" }, + { label: "MCP Tools", slug: "reference/mcp-tools" }, + { label: "Rule API", slug: "reference/rule-api" }, + { label: "ADR Schema", slug: "reference/adr-schema" }, + ], + }, + { + label: "Examples", + items: [ + { + label: "Common Rule Patterns", + slug: "examples/common-rule-patterns", + }, + ], + }, + ], + }), + ], +}); diff --git a/docs/bun.lock b/docs/bun.lock new file mode 100644 index 00000000..25e155b8 --- /dev/null +++ b/docs/bun.lock @@ -0,0 +1,955 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "@archgate/docs", + "dependencies": { + "@astrojs/starlight": "^0.34.0", + "astro": "^5.7.0", + "sharp": "^0.34.1", + }, + }, + }, + "packages": { + "@astrojs/compiler": ["@astrojs/compiler@2.13.1", "", {}, "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg=="], + + "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.5", "", {}, "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA=="], + + "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.10", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.5", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.1", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.19.0", "smol-toml": "^1.5.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A=="], + + "@astrojs/mdx": ["@astrojs/mdx@4.3.13", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.10", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-IHDHVKz0JfKBy3//52JSiyWv089b7GVSChIXLrlUOoTLWowG3wr2/8hkaEgEyd/vysvNQvGk+QhysXpJW5ve6Q=="], + + "@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="], + + "@astrojs/sitemap": ["@astrojs/sitemap@3.7.0", "", { "dependencies": { "sitemap": "^8.0.2", "stream-replace-string": "^2.0.0", "zod": "^3.25.76" } }, "sha512-+qxjUrz6Jcgh+D5VE1gKUJTA3pSthuPHe6Ao5JCxok794Lewx8hBFaWHtOnN0ntb2lfOf7gvOi9TefUswQ/ZVA=="], + + "@astrojs/starlight": ["@astrojs/starlight@0.34.8", "", { "dependencies": { "@astrojs/markdown-remark": "^6.3.1", "@astrojs/mdx": "^4.2.3", "@astrojs/sitemap": "^3.3.0", "@pagefind/default-ui": "^1.3.0", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", "@types/mdast": "^4.0.4", "astro-expressive-code": "^0.41.1", "bcp-47": "^2.1.0", "hast-util-from-html": "^2.0.1", "hast-util-select": "^6.0.2", "hast-util-to-string": "^3.0.0", "hastscript": "^9.0.0", "i18next": "^23.11.5", "js-yaml": "^4.1.0", "klona": "^2.0.6", "mdast-util-directive": "^3.0.0", "mdast-util-to-markdown": "^2.1.0", "mdast-util-to-string": "^4.0.0", "pagefind": "^1.3.0", "rehype": "^13.0.1", "rehype-format": "^5.0.0", "remark-directive": "^3.0.0", "ultrahtml": "^1.6.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "vfile": "^6.0.2" }, "peerDependencies": { "astro": "^5.5.0" } }, "sha512-XuYz0TfCZhje2u1Q9FNtmTdm7/B9QP91RDI1VkPgYvDhSYlME3k8gwgcBMHnR9ASDo2p9gskrqe7t1Pub/qryg=="], + + "@astrojs/telemetry": ["@astrojs/telemetry@3.3.0", "", { "dependencies": { "ci-info": "^4.2.0", "debug": "^4.4.0", "dlv": "^1.1.3", "dset": "^3.1.4", "is-docker": "^3.0.0", "is-wsl": "^3.1.0", "which-pm-runs": "^1.1.0" } }, "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], + + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], + + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], + + "@capsizecss/unpack": ["@capsizecss/unpack@4.0.0", "", { "dependencies": { "fontkitten": "^1.0.0" } }, "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA=="], + + "@ctrl/tinycolor": ["@ctrl/tinycolor@4.2.0", "", {}, "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], + + "@expressive-code/core": ["@expressive-code/core@0.41.7", "", { "dependencies": { "@ctrl/tinycolor": "^4.0.4", "hast-util-select": "^6.0.2", "hast-util-to-html": "^9.0.1", "hast-util-to-text": "^4.0.1", "hastscript": "^9.0.0", "postcss": "^8.4.38", "postcss-nested": "^6.0.1", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } }, "sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg=="], + + "@expressive-code/plugin-frames": ["@expressive-code/plugin-frames@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7" } }, "sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA=="], + + "@expressive-code/plugin-shiki": ["@expressive-code/plugin-shiki@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "shiki": "^3.2.2" } }, "sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ=="], + + "@expressive-code/plugin-text-markers": ["@expressive-code/plugin-text-markers@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7" } }, "sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw=="], + + "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], + + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], + + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], + + "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="], + + "@pagefind/darwin-arm64": ["@pagefind/darwin-arm64@1.4.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ=="], + + "@pagefind/darwin-x64": ["@pagefind/darwin-x64@1.4.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A=="], + + "@pagefind/default-ui": ["@pagefind/default-ui@1.4.0", "", {}, "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ=="], + + "@pagefind/freebsd-x64": ["@pagefind/freebsd-x64@1.4.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q=="], + + "@pagefind/linux-arm64": ["@pagefind/linux-arm64@1.4.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw=="], + + "@pagefind/linux-x64": ["@pagefind/linux-x64@1.4.0", "", { "os": "linux", "cpu": "x64" }, "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg=="], + + "@pagefind/windows-x64": ["@pagefind/windows-x64@1.4.0", "", { "os": "win32", "cpu": "x64" }, "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="], + + "@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], + + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], + + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="], + + "@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="], + + "@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="], + + "@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + + "@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/nlcst": ["@types/nlcst@2.0.3", "", { "dependencies": { "@types/unist": "*" } }, "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA=="], + + "@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="], + + "@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], + + "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], + + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + + "array-iterate": ["array-iterate@2.0.1", "", {}, "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg=="], + + "astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="], + + "astro": ["astro@5.18.0", "", { "dependencies": { "@astrojs/compiler": "^2.13.0", "@astrojs/internal-helpers": "0.7.5", "@astrojs/markdown-remark": "6.3.10", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^4.0.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", "acorn": "^8.15.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.3.1", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.1.1", "cssesc": "^3.0.0", "debug": "^4.4.3", "deterministic-object-hash": "^2.0.2", "devalue": "^5.6.2", "diff": "^8.0.3", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.27.3", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.4.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.1", "magic-string": "^0.30.21", "magicast": "^0.5.1", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.1", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.3", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.3", "shiki": "^3.21.0", "smol-toml": "^1.6.0", "svgo": "^4.0.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", "unifont": "~0.7.3", "unist-util-visit": "^5.0.0", "unstorage": "^1.17.4", "vfile": "^6.0.3", "vite": "^6.4.1", "vitefu": "^1.1.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.3", "zod": "^3.25.76", "zod-to-json-schema": "^3.25.1", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.34.0" }, "bin": { "astro": "astro.js" } }, "sha512-CHiohwJIS4L0G6/IzE1Fx3dgWqXBCXus/od0eGUfxrZJD2um2pE7ehclMmgL/fXqbU7NfE1Ze2pq34h2QaA6iQ=="], + + "astro-expressive-code": ["astro-expressive-code@0.41.7", "", { "dependencies": { "rehype-expressive-code": "^0.41.7" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" } }, "sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ=="], + + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], + + "base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="], + + "bcp-47": ["bcp-47@2.1.0", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w=="], + + "bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="], + + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + + "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], + + "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], + + "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + + "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], + + "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], + + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], + + "cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], + + "crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], + + "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], + + "css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="], + + "css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="], + + "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="], + + "devalue": ["devalue@5.6.3", "", {}, "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], + + "direction": ["direction@2.0.1", "", { "bin": { "direction": "cli.js" } }, "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA=="], + + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], + + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + + "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + + "esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="], + + "esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="], + + "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], + + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="], + + "estree-util-build-jsx": ["estree-util-build-jsx@3.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" } }, "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ=="], + + "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], + + "estree-util-scope": ["estree-util-scope@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0" } }, "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ=="], + + "estree-util-to-js": ["estree-util-to-js@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", "source-map": "^0.7.0" } }, "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg=="], + + "estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], + + "expressive-code": ["expressive-code@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "@expressive-code/plugin-frames": "^0.41.7", "@expressive-code/plugin-shiki": "^0.41.7", "@expressive-code/plugin-text-markers": "^0.41.7" } }, "sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="], + + "fontace": ["fontace@0.4.1", "", { "dependencies": { "fontkitten": "^1.0.2" } }, "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw=="], + + "fontkitten": ["fontkitten@1.0.2", "", { "dependencies": { "tiny-inflate": "^1.0.3" } }, "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="], + + "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], + + "h3": ["h3@1.15.5", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg=="], + + "hast-util-embedded": ["hast-util-embedded@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-is-element": "^3.0.0" } }, "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA=="], + + "hast-util-format": ["hast-util-format@1.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-embedded": "^3.0.0", "hast-util-minify-whitespace": "^1.0.0", "hast-util-phrasing": "^3.0.0", "hast-util-whitespace": "^3.0.0", "html-whitespace-sensitive-tag-names": "^3.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA=="], + + "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], + + "hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="], + + "hast-util-has-property": ["hast-util-has-property@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA=="], + + "hast-util-is-body-ok-link": ["hast-util-is-body-ok-link@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ=="], + + "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="], + + "hast-util-minify-whitespace": ["hast-util-minify-whitespace@1.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-embedded": "^3.0.0", "hast-util-is-element": "^3.0.0", "hast-util-whitespace": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw=="], + + "hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], + + "hast-util-phrasing": ["hast-util-phrasing@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-embedded": "^3.0.0", "hast-util-has-property": "^3.0.0", "hast-util-is-body-ok-link": "^3.0.0", "hast-util-is-element": "^3.0.0" } }, "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ=="], + + "hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="], + + "hast-util-select": ["hast-util-select@6.0.4", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "bcp-47-match": "^2.0.0", "comma-separated-tokens": "^2.0.0", "css-selector-parser": "^3.0.0", "devlop": "^1.0.0", "direction": "^2.0.0", "hast-util-has-property": "^3.0.0", "hast-util-to-string": "^3.0.0", "hast-util-whitespace": "^3.0.0", "nth-check": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw=="], + + "hast-util-to-estree": ["hast-util-to-estree@3.1.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w=="], + + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], + + "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="], + + "hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="], + + "hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="], + + "hast-util-to-text": ["hast-util-to-text@4.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "hast-util-is-element": "^3.0.0", "unist-util-find-after": "^5.0.0" } }, "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + + "html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="], + + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + + "html-whitespace-sensitive-tag-names": ["html-whitespace-sensitive-tag-names@3.0.1", "", {}, "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA=="], + + "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + + "i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="], + + "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], + + "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], + + "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], + + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], + + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], + + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], + + "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], + + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + + "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="], + + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + + "lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "magicast": ["magicast@0.5.2", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ=="], + + "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], + + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + + "mdast-util-definitions": ["mdast-util-definitions@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ=="], + + "mdast-util-directive": ["mdast-util-directive@3.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q=="], + + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], + + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], + + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], + + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], + + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="], + + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], + + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], + + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], + + "mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="], + + "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="], + + "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="], + + "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="], + + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], + + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], + + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], + + "mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="], + + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], + + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], + + "micromark-extension-directive": ["micromark-extension-directive@3.0.2", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "parse-entities": "^4.0.0" } }, "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA=="], + + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], + + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], + + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="], + + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="], + + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="], + + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], + + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], + + "micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q=="], + + "micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.2", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ=="], + + "micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="], + + "micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="], + + "micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="], + + "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], + + "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], + + "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ=="], + + "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], + + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], + + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="], + + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="], + + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="], + + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg=="], + + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], + + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], + + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="], + + "nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="], + + "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + + "node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], + + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + + "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="], + + "oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="], + + "p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="], + + "p-queue": ["p-queue@8.1.1", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ=="], + + "p-timeout": ["p-timeout@6.1.4", "", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="], + + "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], + + "pagefind": ["pagefind@1.4.0", "", { "optionalDependencies": { "@pagefind/darwin-arm64": "1.4.0", "@pagefind/darwin-x64": "1.4.0", "@pagefind/freebsd-x64": "1.4.0", "@pagefind/linux-arm64": "1.4.0", "@pagefind/linux-x64": "1.4.0", "@pagefind/windows-x64": "1.4.0" }, "bin": { "pagefind": "lib/runner/bin.cjs" } }, "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g=="], + + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + + "parse-latin": ["parse-latin@7.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "@types/unist": "^3.0.0", "nlcst-to-string": "^4.0.0", "unist-util-modify-children": "^4.0.0", "unist-util-visit-children": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ=="], + + "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + + "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], + + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + + "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], + + "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + + "recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="], + + "recma-jsx": ["recma-jsx@1.0.1", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" }, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w=="], + + "recma-parse": ["recma-parse@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "esast-util-from-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ=="], + + "recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="], + + "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], + + "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], + + "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + + "rehype": ["rehype@13.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "rehype-parse": "^9.0.0", "rehype-stringify": "^10.0.0", "unified": "^11.0.0" } }, "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A=="], + + "rehype-expressive-code": ["rehype-expressive-code@0.41.7", "", { "dependencies": { "expressive-code": "^0.41.7" } }, "sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ=="], + + "rehype-format": ["rehype-format@5.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-format": "^1.0.0" } }, "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ=="], + + "rehype-parse": ["rehype-parse@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", "unified": "^11.0.0" } }, "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag=="], + + "rehype-raw": ["rehype-raw@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-raw": "^9.0.0", "vfile": "^6.0.0" } }, "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww=="], + + "rehype-recma": ["rehype-recma@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "hast-util-to-estree": "^3.0.0" } }, "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw=="], + + "rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="], + + "remark-directive": ["remark-directive@3.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-directive": "^3.0.0", "micromark-extension-directive": "^3.0.0", "unified": "^11.0.0" } }, "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A=="], + + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], + + "remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="], + + "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], + + "remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="], + + "remark-smartypants": ["remark-smartypants@3.0.2", "", { "dependencies": { "retext": "^9.0.0", "retext-smartypants": "^6.0.0", "unified": "^11.0.4", "unist-util-visit": "^5.0.0" } }, "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA=="], + + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + + "retext": ["retext@9.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "retext-latin": "^4.0.0", "retext-stringify": "^4.0.0", "unified": "^11.0.0" } }, "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA=="], + + "retext-latin": ["retext-latin@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "parse-latin": "^7.0.0", "unified": "^11.0.0" } }, "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA=="], + + "retext-smartypants": ["retext-smartypants@6.2.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ=="], + + "retext-stringify": ["retext-stringify@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unified": "^11.0.0" } }, "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA=="], + + "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], + + "sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="], + + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], + + "shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "sitemap": ["sitemap@8.0.2", "", { "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.4.1" }, "bin": { "sitemap": "dist/cli.js" } }, "sha512-LwktpJcyZDoa0IL6KT++lQ53pbSrx2c9ge41/SeLTyqy2XUNA6uR4+P9u5IVo5lPeL2arAcOKn1aZAxoYbCKlQ=="], + + "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="], + + "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + + "stream-replace-string": ["stream-replace-string@2.0.0", "", {}, "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w=="], + + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], + + "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], + + "svgo": ["svgo@4.0.0", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.4.1" }, "bin": "./bin/svgo.js" }, "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw=="], + + "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], + + "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], + + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + + "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="], + + "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="], + + "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], + + "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], + + "unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="], + + "unist-util-find-after": ["unist-util-find-after@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ=="], + + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], + + "unist-util-modify-children": ["unist-util-modify-children@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "array-iterate": "^2.0.0" } }, "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], + + "unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], + + "unist-util-visit-children": ["unist-util-visit-children@3.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + + "unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], + + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + + "vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], + + "vitefu": ["vitefu@1.1.2", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw=="], + + "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], + + "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="], + + "widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="], + + "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], + + "xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], + + "yocto-spinner": ["yocto-spinner@0.2.3", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ=="], + + "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], + + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + + "zod-to-ts": ["zod-to-ts@1.2.0", "", { "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" } }, "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], + + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + + "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], + + "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + + "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + + "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000..7d81baab --- /dev/null +++ b/docs/package.json @@ -0,0 +1,15 @@ +{ + "name": "@archgate/docs", + "private": true, + "type": "module", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "dependencies": { + "@astrojs/starlight": "^0.34.0", + "astro": "^5.7.0", + "sharp": "^0.34.1" + } +} diff --git a/docs/public/CNAME b/docs/public/CNAME new file mode 100644 index 00000000..f7ffae66 --- /dev/null +++ b/docs/public/CNAME @@ -0,0 +1 @@ +cli.archgate.dev diff --git a/docs/src/content.config.ts b/docs/src/content.config.ts new file mode 100644 index 00000000..7fbcf2c3 --- /dev/null +++ b/docs/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from "astro:content"; +import { docsLoader } from "@astrojs/starlight/loaders"; +import { docsSchema } from "@astrojs/starlight/schema"; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/docs/src/content/docs/concepts/adrs.mdx b/docs/src/content/docs/concepts/adrs.mdx new file mode 100644 index 00000000..e5a88ddc --- /dev/null +++ b/docs/src/content/docs/concepts/adrs.mdx @@ -0,0 +1,176 @@ +--- +title: Architecture Decision Records +description: Understand how Archgate uses ADRs as both documents and executable rules. +--- + +An Architecture Decision Record (ADR) is a short document that captures a single architectural decision along with its context and consequences. ADRs answer the question: _why_ was this decision made, and _what_ are its trade-offs? + +Archgate builds on the ADR concept by giving each decision two expressions: a **document** that humans and AI agents read, and an optional **rules file** that machines execute. + +## Two Expressions of an ADR + +### ADR as Document + +The document is a Markdown file with YAML frontmatter stored in `.archgate/adrs/`. It describes the decision in plain language: what problem it solves, what alternatives were considered, what the team decided, and what consequences follow. + +Both humans and AI agents consume this document. When an AI coding agent is about to write code, it reads the relevant ADRs to understand the constraints before generating anything. + +### ADR as Rules + +The rules file is a companion `.rules.ts` file that exports automated checks via `defineRules()`. When you run `archgate check`, the CLI loads every ADR that has `rules: true` in its frontmatter, executes the companion rules file against your codebase, and reports any violations with file paths and line numbers. + +Not every ADR needs rules. Some decisions are best enforced through code review alone. Set `rules: false` when no automated check is practical. + +## File Naming Convention + +ADR files follow a strict naming convention that encodes the domain prefix, sequence number, and a human-readable slug: + +``` +{PREFIX}-{NNN}-{slug}.md # The document +{PREFIX}-{NNN}-{slug}.rules.ts # The companion rules file (optional) +``` + +For example, an architecture-domain ADR about command structure would produce: + +``` +ARCH-001-command-structure.md +ARCH-001-command-structure.rules.ts +``` + +The prefix comes from the ADR's domain (see [Domains](/concepts/domains/)). The sequence number is zero-padded to three digits and auto-incremented by `archgate adr create`. + +## YAML Frontmatter + +Every ADR document starts with a YAML frontmatter block between `---` delimiters. The frontmatter is the machine-readable metadata that Archgate uses to load, filter, and scope rules. + +| Field | Type | Required | Description | +| -------- | ------------ | -------- | ---------------------------------------------------------------- | +| `id` | string | Yes | Unique identifier like `ARCH-001` or `BE-003` | +| `title` | string | Yes | Human-readable title of the decision | +| `domain` | enum | Yes | One of: `backend`, `frontend`, `data`, `architecture`, `general` | +| `rules` | boolean | Yes | Whether this ADR has a companion `.rules.ts` file | +| `files` | string array | No | Glob patterns that scope which files the rules check | + +The `files` field is optional. When present, it restricts rule execution to only the files matching the given globs. When absent, rules run against all project files. For example, `files: ["src/commands/**/*.ts"]` limits checks to command files only. + +## ADR Body Sections + +After the frontmatter, the ADR body follows a standard section structure: + +### Context + +Describes the problem or situation that prompted the decision. Include alternatives that were considered and why they were rejected. + +### Decision + +States the decision itself and its key constraints. This is the section AI agents pay the most attention to when deciding how to write code. + +### Do's and Don'ts + +Concrete, actionable guidance split into two sub-sections. These act as a quick-reference checklist for developers and AI agents. + +### Consequences + +Split into three sub-sections: + +- **Positive** -- benefits the decision provides +- **Negative** -- trade-offs accepted +- **Risks** -- things that could go wrong and how to mitigate them + +### Compliance and Enforcement + +Describes how the decision is enforced, both through automated rules (with rule IDs and severities) and manual review checklists. + +### References + +Links to related ADRs, external documentation, or design documents. + +## Complete Example + +Below is a full ADR with frontmatter and all sections filled in. + +```markdown +--- +id: BE-001 +title: API Response Envelope +domain: backend +rules: true +files: ["src/api/**/*.ts"] +--- + +## Context + +The API returns data in inconsistent shapes across endpoints. Some endpoints +wrap responses in `{ data, error }`, others return raw arrays, and error +responses vary between plain strings and structured objects. + +**Alternatives considered:** + +- **No envelope** -- Return raw data and rely on HTTP status codes alone. + Simple, but clients cannot distinguish between "the endpoint returned an + empty array" and "the endpoint errored." +- **GraphQL-style errors array** -- Use `{ data, errors: [] }`. Flexible + but adds complexity for simple REST endpoints. + +The chosen envelope balances consistency with simplicity. + +## Decision + +All API endpoints MUST return responses in a standard envelope: + +- Success: `{ data: T }` +- Error: `{ error: { code: string, message: string } }` + +HTTP status codes remain the primary success/failure signal. The envelope +provides a predictable structure for clients to parse. + +## Do's and Don'ts + +### Do + +- Wrap all API responses in the `{ data }` or `{ error }` envelope +- Use specific error codes (e.g., `VALIDATION_FAILED`, `NOT_FOUND`) +- Include the HTTP status code that matches the error semantics + +### Don't + +- Don't return raw arrays or primitives from API endpoints +- Don't nest envelopes (no `{ data: { data: ... } }`) +- Don't put stack traces in the error message field + +## Consequences + +### Positive + +- Clients can parse every response with the same logic +- Error responses always have a machine-readable code for programmatic handling + +### Negative + +- Adds a small amount of boilerplate to every endpoint handler +- Slightly larger payloads due to the wrapper object + +### Risks + +- Developers may forget the envelope on new endpoints. Mitigated by + the automated rule that scans for non-conforming return statements. + +## Compliance and Enforcement + +### Automated Enforcement + +- **Archgate rule** BE-001/response-envelope: Scans API handler files for + return statements and verifies they use the envelope helper. Severity: error. + +### Manual Enforcement + +Code reviewers MUST verify: + +1. New API endpoints use the response envelope +2. Error responses include a specific error code, not a generic message + +## References + +- [Microsoft REST API Guidelines](https://github.com/microsoft/api-guidelines) +- [ARCH-002 -- Error Handling](./ARCH-002-error-handling.md) +``` diff --git a/docs/src/content/docs/concepts/domains.mdx b/docs/src/content/docs/concepts/domains.mdx new file mode 100644 index 00000000..f6d19dbe --- /dev/null +++ b/docs/src/content/docs/concepts/domains.mdx @@ -0,0 +1,96 @@ +--- +title: Domains +description: Categorize ADRs by domain for organized governance. +--- + +Domains are categories that group related ADRs together. Every ADR belongs to exactly one domain, and the domain determines the prefix used in the ADR's identifier. + +## Built-in Domains + +Archgate ships with five built-in domains. Each has a short prefix that appears at the start of every ADR ID in that domain. + +| Domain | Prefix | Use for | +| -------------- | ------ | --------------------------------------------------- | +| `backend` | `BE` | Server-side logic, APIs, databases, services | +| `frontend` | `FE` | UI components, client-side logic, styling patterns | +| `data` | `DATA` | Data models, schemas, pipelines, storage strategies | +| `architecture` | `ARCH` | Cross-cutting architectural decisions | +| `general` | `GEN` | General project conventions and workflows | + +For example, the third backend ADR would have the ID `BE-003`, and a first frontend ADR would be `FE-001`. + +## How Domains Are Used + +### ADR Identification + +The domain prefix is baked into every ADR's `id` field. When you run `archgate adr create` and select a domain, the CLI automatically determines the next available sequence number for that domain's prefix. An architecture domain with two existing ADRs (`ARCH-001`, `ARCH-002`) would assign `ARCH-003` to the next one. + +The file name mirrors the ID: + +``` +ARCH-003-dependency-policy.md +ARCH-003-dependency-policy.rules.ts +``` + +### Filtering + +The `archgate adr list` command supports a `--domain` flag to show only ADRs from a specific domain: + +```bash +archgate adr list --domain backend +archgate adr list --domain architecture +``` + +This is useful in large projects where dozens of ADRs span multiple concerns. Filtering by domain lets you focus on the decisions relevant to your current work. + +### AI Agent Context + +The MCP server's `review_context` tool groups changed files by domain when providing context to AI agents. When an agent is about to write code, it receives only the ADR briefings relevant to the domains its changes touch, rather than the full set of all ADRs. This scoping reduces noise and helps agents focus on the constraints that actually apply. + +### Scoped Validation + +While domains themselves do not restrict which files a rule can check (that is the job of the `files` glob in the ADR frontmatter), domains provide a logical grouping that helps teams organize their governance. A backend team can review all `BE-*` ADRs to understand their constraints, while the frontend team focuses on `FE-*`. + +## When to Use Which Domain + +### backend + +Use for decisions about server-side code: API design patterns, database access conventions, authentication flows, service-to-service communication, queue handling, and background job patterns. + +**Example ADRs:** API response envelope format, database migration strategy, error code taxonomy. + +### frontend + +Use for decisions about client-side code: component structure, state management patterns, styling approaches, accessibility requirements, and build tooling choices. + +**Example ADRs:** Component file structure, CSS methodology, form validation pattern. + +### data + +Use for decisions about data: schema design, data pipeline conventions, storage engine choices, serialization formats, and data validation strategies. + +**Example ADRs:** Event schema versioning, database naming conventions, data retention policy. + +### architecture + +Use for cross-cutting decisions that span multiple domains or affect the project's overall structure. These are decisions that backend, frontend, and data teams all need to follow. + +**Example ADRs:** Command structure, error handling conventions, dependency management policy, testing standards. + +### general + +Use for project-wide conventions that do not fit neatly into a technical domain: code review processes, commit message formats, documentation standards, and onboarding practices. + +**Example ADRs:** Commit message format, PR description template, documentation requirements. + +## Choosing the Right Domain + +When deciding which domain an ADR belongs to, consider who needs to follow it: + +- If only backend developers need to follow it, use `backend`. +- If only frontend developers need to follow it, use `frontend`. +- If it concerns data modeling or pipelines specifically, use `data`. +- If it applies across multiple technical domains, use `architecture`. +- If it is a process or convention rather than a technical decision, use `general`. + +When in doubt between `architecture` and a specific domain, prefer the more specific domain. Reserve `architecture` for decisions that genuinely cut across boundaries. diff --git a/docs/src/content/docs/concepts/rules.mdx b/docs/src/content/docs/concepts/rules.mdx new file mode 100644 index 00000000..a12e3d38 --- /dev/null +++ b/docs/src/content/docs/concepts/rules.mdx @@ -0,0 +1,162 @@ +--- +title: Rules +description: How Archgate's rule system turns ADR decisions into automated checks. +--- + +Rules are the executable side of an ADR. They live in companion `.rules.ts` files alongside the ADR document and export automated checks via the `defineRules()` function. When you run `archgate check`, the CLI loads each ADR that has `rules: true`, imports its companion rules file, and executes every check against your codebase. + +## Defining Rules + +A rules file is a TypeScript module that default-exports the result of `defineRules()`. Import the function from the `archgate/rules` package: + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "rule-key": { + description: "What this rule checks", + severity: "error", + async check(ctx) { + // Inspect files and report violations + }, + }, +}); +``` + +Each key in the object passed to `defineRules()` becomes the rule ID. The full rule identifier shown in check output combines the ADR ID and the rule key, for example `ARCH-004/no-barrel-files`. + +## Rule Structure + +Every rule has three parts: + +| Property | Type | Required | Description | +| ------------- | -------- | -------- | --------------------------------------------- | +| `description` | string | Yes | A short summary of what the rule checks | +| `severity` | string | No | `"error"` (default), `"warning"`, or `"info"` | +| `check` | function | Yes | Async function receiving a `RuleContext` | + +### Severity Levels + +Severity determines what happens when a rule finds a problem: + +| Severity | Exit Code | Effect | +| --------- | --------- | ----------------------------------------- | +| `error` | 1 | Violation is reported and the check fails | +| `warning` | 0 | Warning is logged but the check passes | +| `info` | 0 | Informational message, check passes | + +When `archgate check` runs, exit code 1 means at least one `error`-severity violation was found. Exit code 0 means no errors (warnings and info messages are logged but do not block). + +## The RuleContext + +The `check` function receives a `RuleContext` object that provides everything a rule needs to inspect the codebase and report findings. + +### Project Information + +| Property | Type | Description | +| ------------------ | ---------- | -------------------------------------------------------------------------------- | +| `ctx.projectRoot` | `string` | Absolute path to the project root directory | +| `ctx.scopedFiles` | `string[]` | Files matching the ADR's `files` globs, or all project files if no globs are set | +| `ctx.changedFiles` | `string[]` | Files changed in git (populated when running with `--staged`) | + +### File Operations + +| Method | Returns | Description | +| -------------------- | ------------------- | ---------------------------------- | +| `ctx.glob(pattern)` | `Promise` | Find files matching a glob pattern | +| `ctx.readFile(path)` | `Promise` | Read a file's content as a string | +| `ctx.readJSON(path)` | `Promise` | Read and parse a JSON file | + +### Search Operations + +| Method | Returns | Description | +| ---------------------------------- | ---------------------- | -------------------------------------------- | +| `ctx.grep(file, pattern)` | `Promise` | Search a single file with a regex pattern | +| `ctx.grepFiles(pattern, fileGlob)` | `Promise` | Search across multiple files matching a glob | + +Both `grep` and `grepFiles` return an array of `GrepMatch` objects: + +```typescript +interface GrepMatch { + file: string; // Relative path from project root + line: number; // 1-based line number + column: number; // 1-based column number + content: string; // The full line content +} +``` + +### Reporting + +The `ctx.report` object provides three methods for reporting findings: + +```typescript +ctx.report.violation({ message, file?, line?, fix? }); +ctx.report.warning({ message, file?, line?, fix? }); +ctx.report.info({ message, file?, line?, fix? }); +``` + +Each method accepts an object with: + +| Property | Type | Required | Description | +| --------- | ------ | -------- | ------------------------------------ | +| `message` | string | Yes | What the problem is | +| `file` | string | No | Relative path to the offending file | +| `line` | number | No | Line number where the problem occurs | +| `fix` | string | No | Suggested fix for the violation | + +Use `ctx.report.violation()` for problems that must block merges. Use `ctx.report.warning()` for issues worth flagging but not blocking. Use `ctx.report.info()` for purely informational output. + +## Rule Timeout + +Each rule has a 30-second execution timeout. If a rule's `check` function does not complete within 30 seconds, it is terminated and reported as an error. This prevents runaway rules from blocking the pipeline indefinitely. + +## Complete Example + +Here is a complete rules file that checks for a banned import pattern. It enforces that no source file imports directly from `node:fs` (the project requires using a wrapper instead). + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "no-direct-fs-import": { + description: + "Source files must not import directly from node:fs; use the fs wrapper", + severity: "error", + async check(ctx) { + const sourceFiles = ctx.scopedFiles.filter( + (f) => f.endsWith(".ts") && !f.endsWith(".test.ts") + ); + + for (const file of sourceFiles) { + const matches = await ctx.grep(file, /from ["']node:fs["']/); + + for (const match of matches) { + ctx.report.violation({ + message: `Direct import from "node:fs" is not allowed. Use the fs wrapper from "src/helpers/fs" instead.`, + file: match.file, + line: match.line, + fix: 'Replace the import with: import { readFile, writeFile } from "../helpers/fs"', + }); + } + } + }, + }, +}); +``` + +When this rule runs against a file containing `import { readFileSync } from "node:fs"`, the output looks like: + +``` +ARCH-007/no-direct-fs-import ERROR + src/services/config.ts:3 — Direct import from "node:fs" is not allowed. Use the fs wrapper from "src/helpers/fs" instead. + Fix: Replace the import with: import { readFile, writeFile } from "../helpers/fs" +``` + +## Execution Model + +Rules execute with the following guarantees: + +- **Parallel across ADRs** -- Rules from different ADRs run concurrently for faster execution. +- **Sequential within an ADR** -- Rules belonging to the same ADR run one after another, so earlier rules can establish context for later ones. +- **Scoped files are pre-resolved** -- The `ctx.scopedFiles` array is populated before your `check` function is called, based on the ADR's `files` globs. +- **Changed files for staged mode** -- When running `archgate check --staged`, `ctx.changedFiles` contains only the files staged in git, letting rules skip unchanged files for faster feedback. diff --git a/docs/src/content/docs/examples/common-rule-patterns.mdx b/docs/src/content/docs/examples/common-rule-patterns.mdx new file mode 100644 index 00000000..466cf65f --- /dev/null +++ b/docs/src/content/docs/examples/common-rule-patterns.mdx @@ -0,0 +1,269 @@ +--- +title: Common Rule Patterns +description: Ready-to-use rule patterns for common governance needs. +--- + +This page provides complete, copy-pasteable rule examples for common governance scenarios. Each pattern includes the full rule code, an explanation of how it works, and guidance on when to use it. + +## Pattern 1: Dependency Allowlist + +**When to use:** Restrict production dependencies to a curated list to prevent dependency bloat and supply-chain risk. + +```typescript +import { defineRules } from "archgate/rules"; + +const APPROVED_DEPS = [ + "@commander-js/extra-typings", + "inquirer", + "@modelcontextprotocol/sdk", + "zod", +]; + +export default defineRules({ + "no-unapproved-deps": { + description: "Production dependencies must be on the approved list", + async check(ctx) { + let pkg: { dependencies?: Record }; + try { + pkg = (await ctx.readJSON("package.json")) as typeof pkg; + } catch { + return; // No package.json — nothing to check + } + + const deps = Object.keys(pkg.dependencies ?? {}); + for (const dep of deps) { + if (!APPROVED_DEPS.includes(dep)) { + ctx.report.violation({ + message: `Unapproved production dependency: "${dep}". Approved: ${APPROVED_DEPS.join(", ")}`, + file: "package.json", + fix: `Either add "${dep}" to the approved list in the ADR or move it to devDependencies`, + }); + } + } + }, + }, +}); +``` + +**How it works:** Reads `package.json`, iterates over production `dependencies`, and reports a violation for any package not in the `APPROVED_DEPS` array. Dependencies in `devDependencies` are not checked. The fix message guides the developer toward either getting the dependency approved or reclassifying it. + +--- + +## Pattern 2: Required Export Pattern + +**When to use:** Ensure files in a specific directory export a required function signature, such as the `register*Command` pattern for CLI command files. + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "register-function-export": { + description: "Command files must export a register*Command function", + async check(ctx) { + const files = ctx.scopedFiles.filter((f) => !f.endsWith("index.ts")); + const checks = files.map(async (file) => { + const content = await ctx.readFile(file); + if (!/export\s+function\s+register\w+Command/.test(content)) { + ctx.report.violation({ + message: "Command file must export a register*Command function", + file, + }); + } + }); + await Promise.all(checks); + }, + }, +}); +``` + +**How it works:** Filters out `index.ts` barrel files, then checks each scoped file for an exported function matching the `register*Command` naming pattern. The regex looks for `export function register` followed by any word characters and `Command`. Files that do not match get a violation. + +To adapt this pattern, change the regex to match your project's required export convention. For example, to require a default export of a React component: + +```typescript +if (!/export\s+default\s+function\s+\w+/.test(content)) { +``` + +--- + +## Pattern 3: Banned Import + +**When to use:** Prevent usage of a specific library or module across the codebase. Common use cases include banning heavy libraries like `lodash` or `moment` in favor of native alternatives, or preventing imports from internal modules that are being deprecated. + +```typescript +import { defineRules } from "archgate/rules"; + +const BANNED_IMPORTS = [ + { + pattern: /from\s+['"]lodash['"]/, + name: "lodash", + alternative: "native array methods", + }, + { + pattern: /from\s+['"]moment['"]/, + name: "moment", + alternative: "Temporal API or date-fns", + }, + { + pattern: /from\s+['"]axios['"]/, + name: "axios", + alternative: "native fetch()", + }, +]; + +export default defineRules({ + "no-banned-imports": { + description: "Prevent usage of banned libraries", + async check(ctx) { + for (const banned of BANNED_IMPORTS) { + const matches = await ctx.grepFiles(banned.pattern, "src/**/*.ts"); + for (const match of matches) { + ctx.report.violation({ + message: `Banned import: "${banned.name}" is not allowed. Use ${banned.alternative} instead.`, + file: match.file, + line: match.line, + fix: `Replace ${banned.name} with ${banned.alternative}`, + }); + } + } + }, + }, +}); +``` + +**How it works:** Defines a list of banned imports with the regex pattern to detect them, the library name for the error message, and the recommended alternative. Uses `ctx.grepFiles` to scan all TypeScript files for each banned pattern and reports a violation for every match. + +To add more banned imports, add entries to the `BANNED_IMPORTS` array. The pattern should match the `from "..."` part of the import statement. + +--- + +## Pattern 4: File Naming Convention + +**When to use:** Enforce consistent file naming across a directory, such as requiring kebab-case for all source files. + +```typescript +import { defineRules } from "archgate/rules"; +import { basename } from "node:path"; + +const KEBAB_CASE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*\.(ts|tsx|js|jsx)$/; + +export default defineRules({ + "kebab-case-filenames": { + description: "Source files must use kebab-case naming", + async check(ctx) { + for (const file of ctx.scopedFiles) { + const name = basename(file); + + // Skip test files and type declaration files + if (name.endsWith(".test.ts") || name.endsWith(".d.ts")) continue; + + if (!KEBAB_CASE.test(name)) { + ctx.report.violation({ + message: `File "${name}" does not follow kebab-case naming convention`, + file, + fix: `Rename to ${name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}`, + }); + } + } + }, + }, +}); +``` + +**How it works:** Extracts the basename of each scoped file and tests it against a kebab-case regex. The regex requires lowercase letters and digits separated by hyphens, with a valid file extension. Test files and type declarations are excluded. The fix suggestion auto-converts camelCase to kebab-case. + +To change the naming convention, replace the regex. For example, for camelCase: + +```typescript +const CAMEL_CASE = /^[a-z][a-zA-Z0-9]*\.(ts|tsx|js|jsx)$/; +``` + +--- + +## Pattern 5: No TODO Comments in Production + +**When to use:** Flag TODO, FIXME, HACK, and XXX comments so they are resolved before merging. Uses `warning` severity so it does not block CI, but makes the comments visible in check output. + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "no-todo-comments": { + description: "TODO and FIXME comments should be resolved before merging", + severity: "warning", + async check(ctx) { + const matches = await ctx.grepFiles( + /\/\/\s*(TODO|FIXME|HACK|XXX):/i, + "src/**/*.ts" + ); + for (const match of matches) { + ctx.report.warning({ + message: `${match.content.trim()} -- resolve before merging`, + file: match.file, + line: match.line, + }); + } + }, + }, +}); +``` + +**How it works:** Uses `ctx.grepFiles` to scan all TypeScript files in `src/` for comments starting with `TODO:`, `FIXME:`, `HACK:`, or `XXX:` (case-insensitive). Each match is reported as a warning with the original comment text. Because the severity is `"warning"`, the check exits with code 0 even when matches are found -- it surfaces the comments without blocking merges. + +To make this a hard blocker, change the severity to `"error"` and use `ctx.report.violation()` instead of `ctx.report.warning()`. + +--- + +## Pattern 6: Test File Coverage + +**When to use:** Ensure every source file has a corresponding test file, preventing untested code from being merged. + +```typescript +import { defineRules } from "archgate/rules"; +import { relative } from "node:path"; + +export default defineRules({ + "test-file-exists": { + description: "Every source file should have a corresponding test file", + severity: "warning", + async check(ctx) { + for (const file of ctx.scopedFiles) { + const rel = relative(ctx.projectRoot, file); + const testPath = rel + .replace(/^src\//, "tests/") + .replace(/\.ts$/, ".test.ts"); + const testFiles = await ctx.glob(testPath); + if (testFiles.length === 0) { + ctx.report.warning({ + message: `No test file found at ${testPath}`, + file, + fix: `Create a test file at ${testPath}`, + }); + } + } + }, + }, +}); +``` + +**How it works:** For each scoped source file, converts the path from `src/` to `tests/` and appends `.test.ts`. Then uses `ctx.glob` to check if the test file exists. If not, reports a warning with a fix suggesting the expected test file path. + +This assumes a test directory structure that mirrors `src/`: + +``` +src/ + helpers/ + log.ts + paths.ts +tests/ + helpers/ + log.test.ts + paths.test.ts +``` + +To adapt for projects that colocate tests next to source files, change the path transformation: + +```typescript +const testPath = rel.replace(/\.ts$/, ".test.ts"); +// src/helpers/log.ts -> src/helpers/log.test.ts +``` diff --git a/docs/src/content/docs/getting-started/installation.mdx b/docs/src/content/docs/getting-started/installation.mdx new file mode 100644 index 00000000..402268a0 --- /dev/null +++ b/docs/src/content/docs/getting-started/installation.mdx @@ -0,0 +1,110 @@ +--- +title: Installation +description: Install Archgate CLI on macOS, Linux, or Windows. +--- + +## Install globally + +Install Archgate globally using your preferred package manager: + +```bash +# npm +npm install -g archgate + +# Bun +bun install -g archgate + +# Yarn +yarn global add archgate + +# pnpm +pnpm add -g archgate +``` + +This installs a lightweight wrapper that delegates to a platform-specific binary. The CLI itself is a standalone binary compiled with Bun — Node.js is only needed for the npm/yarn/pnpm wrapper. + +## Install as a dev dependency + +You can also add Archgate as a dev dependency in your project and run it through your package manager's script runner. This is useful for pinning a specific version per project or running checks in CI without a global install. + +```bash +# npm +npm install -D archgate + +# Bun +bun add -d archgate + +# Yarn +yarn add -D archgate + +# pnpm +pnpm add -D archgate +``` + +Then run Archgate via your package manager: + +```bash +# npm / Yarn / pnpm +npx archgate check + +# Bun +bun run archgate check +``` + +Or add a script to your `package.json`: + +```json +{ + "scripts": { + "check:adrs": "archgate check" + } +} +``` + +```bash +# Works with any package manager +npm run check:adrs +bun run check:adrs +yarn check:adrs +pnpm check:adrs +``` + +## Platform support + +Archgate ships pre-built binaries for the following platforms: + +| Platform | Architecture | Package | +| -------- | ------------ | ----------------------- | +| macOS | arm64 | `archgate-darwin-arm64` | +| Linux | x86_64 | `archgate-linux-x64` | +| Windows | x86_64 | `archgate-win32-x64` | + +The correct binary is installed automatically as an `optionalDependency` when you install `archgate`. + +## Verify installation + +```bash +archgate --version +``` + +You should see the installed version printed to stdout. + +## Proto toolchain users + +If you manage Node.js with [proto](https://moonrepo.dev/proto) (moonrepo's toolchain manager), globally installed npm binaries require an additional setup step. + +Add to your proto configuration: + +```toml +# ~/.proto/config.toml +[tools.npm] +shared-globals-dir = true +``` + +Then add the globals directory to your shell profile (`.bashrc`, `.zshrc`, or equivalent): + +```bash +export PATH="$HOME/.proto/tools/node/globals/bin:$PATH" +``` + +Restart your shell, then run `npm install -g archgate` again. The `archgate` command should now be available globally. diff --git a/docs/src/content/docs/getting-started/quick-start.mdx b/docs/src/content/docs/getting-started/quick-start.mdx new file mode 100644 index 00000000..af3f207e --- /dev/null +++ b/docs/src/content/docs/getting-started/quick-start.mdx @@ -0,0 +1,121 @@ +--- +title: Quick Start +description: Get up and running with Archgate in under 5 minutes. +--- + +## 1. Install Archgate + +If you have not installed the CLI yet, install it globally via npm: + +```bash +npm install -g archgate +``` + +See the [Installation](/getting-started/installation/) page for platform details and troubleshooting. + +## 2. Initialize your project + +Navigate to your project root and run the `init` command: + +```bash +cd my-project +archgate init +``` + +This creates the `.archgate/` directory with the following structure: + +``` +.archgate/ + adrs/ + ARCH-001-example.md # Example ADR + ARCH-001-example.rules.ts # Example rules file + lint/ + archgate.config.ts # Archgate configuration +``` + +The generated files give you a working example to build on. + +## 3. Edit the example ADR + +Open `.archgate/adrs/ARCH-001-example.md`. Every ADR starts with YAML frontmatter that defines its identity: + +```yaml +--- +id: ARCH-001 +title: Example Decision +domain: architecture +rules: true +files: ["src/**/*.ts"] +--- +``` + +- **id** — Unique identifier. Convention is `ARCH-NNN` but any string works. +- **title** — Human-readable name for the decision. +- **domain** — Groups related ADRs together (e.g., `architecture`, `security`, `testing`). +- **rules** — Set to `true` if this ADR has a companion `.rules.ts` file with automated checks. +- **files** — Optional glob patterns that scope which files the rules apply to. + +Below the frontmatter, write the decision in markdown. Archgate does not enforce a specific section structure, but the recommended sections are: Context, Decision, Do's and Don'ts, Consequences, Compliance, and References. + +## 4. Add a companion rules file + +Create a `.rules.ts` file next to your ADR with the same name prefix. Rules are written in TypeScript using the `defineRules` function: + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "no-console-error": { + description: "Use logError() instead of console.error()", + async check(ctx) { + for (const file of ctx.scopedFiles) { + const matches = await ctx.grep(file, /console\.error\(/); + for (const match of matches) { + ctx.report.violation({ + message: "Use logError() instead of console.error()", + file: match.file, + line: match.line, + fix: "Import logError from your helpers and use it instead", + }); + } + } + }, + }, +}); +``` + +Each rule has a unique key, a description, and an async `check` function. Inside `check`, you have access to: + +- **`ctx.scopedFiles`** — Files matching the ADR's `files` glob patterns. +- **`ctx.grep(file, pattern)`** — Search a file for regex matches, returning file paths and line numbers. +- **`ctx.report.violation()`** — Report a violation with a message, file path, line number, and optional fix suggestion. + +## 5. Run checks + +Run the compliance checker against your codebase: + +```bash +archgate check +``` + +Archgate loads every ADR with `rules: true`, executes its companion rules file, and prints results. The exit code tells you the outcome: + +| Exit code | Meaning | +| --------- | --------------------------------------------- | +| 0 | All rules pass. No violations found. | +| 1 | One or more violations detected. | +| 2 | Internal error (e.g., malformed ADR or rule). | + +To check only staged files (useful in pre-commit hooks or CI): + +```bash +archgate check --staged +``` + +## What's next? + +Now that you have a working setup, dive deeper: + +- [Writing ADRs](/guides/writing-adrs/) — Learn the full ADR format and best practices for writing effective decisions. +- [Writing Rules](/guides/writing-rules/) — Explore the rule API, advanced patterns, and how to test your rules. +- [CI Integration](/guides/ci-integration/) — Wire `archgate check` into GitHub Actions, GitLab CI, or any pipeline. diff --git a/docs/src/content/docs/guides/ci-integration.mdx b/docs/src/content/docs/guides/ci-integration.mdx new file mode 100644 index 00000000..5f465e14 --- /dev/null +++ b/docs/src/content/docs/guides/ci-integration.mdx @@ -0,0 +1,179 @@ +--- +title: CI Integration +description: Add Archgate checks to your CI/CD pipeline. +--- + +Archgate checks fit into any CI system that respects exit codes. Add a single step to your pipeline and violations will block merges automatically. + +## GitHub Actions + +The simplest setup is a dedicated job that installs Archgate and runs `archgate check`: + +```yaml +name: ADR Compliance +on: [push, pull_request] + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm install -g archgate + - run: archgate check +``` + +This installs the CLI globally and runs all ADR rules. If any rule reports a violation with `error` severity, the step exits with code 1 and the job fails. + +## GitHub Actions annotations + +Use `--ci` to output violations as GitHub Actions workflow annotations. These appear inline on the pull request's "Files changed" tab, pointing directly to the offending file and line. + +```yaml +- run: archgate check --ci +``` + +The `--ci` flag produces `::error` and `::warning` annotations in the format GitHub Actions expects. Each annotation includes the ADR ID, rule ID, file path, and line number. + +## Machine-readable output + +Use `--json` for structured output that other tools can parse: + +```yaml +- run: archgate check --json > results.json +``` + +The JSON output includes: + +```json +{ + "pass": false, + "total": 6, + "passed": 5, + "failed": 1, + "warnings": 0, + "errors": 1, + "infos": 0, + "ruleErrors": 0, + "results": [ + { + "ruleId": "no-unapproved-deps", + "adrId": "ARCH-006", + "message": "Unapproved production dependency: \"chalk\"", + "file": "package.json", + "severity": "error" + } + ], + "durationMs": 142 +} +``` + +## Exit codes + +| Code | Meaning | CI behavior | +| ---- | ---------------- | ------------ | +| 0 | All checks pass | Job succeeds | +| 1 | Violations found | Job fails | +| 2 | Internal error | Job fails | + +Warnings (severity `warning`) are logged but do not affect the exit code. Only `error`-severity violations cause exit code 1. + +## Narrowing scope + +### Check only staged files + +Use `--staged` to limit checking to git-staged files. This is useful in pre-commit hooks or when you only want to validate what is about to be committed: + +```yaml +- run: archgate check --staged +``` + +### Check a specific ADR + +Use `--adr ` to run rules from a single ADR: + +```yaml +- run: archgate check --adr ARCH-006 +``` + +This is useful when a PR only touches files governed by one ADR and you want faster feedback. + +## Adding to an existing pipeline + +If you already have a CI configuration, add Archgate as a single step after your checkout: + +```yaml +# Existing pipeline +steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22" + - run: npm ci + - run: npm test + + # Add Archgate check + - run: npm install -g archgate + - run: archgate check --ci +``` + +No additional dependencies or configuration files are needed beyond the `.archgate/` directory already in your repository. + +## Caching the installation + +Cache the `~/.archgate` directory to speed up repeated installs: + +```yaml +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Cache Archgate + uses: actions/cache@v4 + with: + path: ~/.archgate + key: archgate-${{ runner.os }} + + - run: npm install -g archgate + - run: archgate check --ci +``` + +## GitLab CI + +```yaml +adr-compliance: + image: node:22 + script: + - npm install -g archgate + - archgate check +``` + +## Other CI systems + +Archgate works with any CI system that can run shell commands. The pattern is always the same: + +1. Install: `npm install -g archgate` +2. Run: `archgate check` +3. Check the exit code (0 = pass, 1 = violations, 2 = error) + +For systems that support annotations (Azure DevOps, Buildkite, etc.), use `--json` to parse the output and emit annotations in the format your CI expects. + +## Pre-commit hooks + +You can also run Archgate as a local pre-commit hook. Add this to `.git/hooks/pre-commit` (or use a hook manager like Husky or Lefthook): + +```bash +#!/bin/sh +archgate check --staged +``` + +The `--staged` flag ensures only files about to be committed are checked, keeping the hook fast. + +## Verbose output + +Use `--verbose` to see passing rules and timing information alongside failures. This is helpful for debugging slow checks or confirming that rules are running as expected: + +```yaml +- run: archgate check --verbose +``` diff --git a/docs/src/content/docs/guides/claude-code-plugin.mdx b/docs/src/content/docs/guides/claude-code-plugin.mdx new file mode 100644 index 00000000..b345477d --- /dev/null +++ b/docs/src/content/docs/guides/claude-code-plugin.mdx @@ -0,0 +1,96 @@ +--- +title: Claude Code Plugin +description: Give AI agents a full governance workflow with the Archgate Claude Code plugin. +--- + +The Archgate Claude Code plugin gives AI agents working in [Claude Code](https://claude.ai/code) a structured governance workflow. Instead of relying on prompt instructions that drift over time, agents read your ADRs directly through the MCP server and validate their own code against your rules. + +## What the plugin provides + +The plugin adds role-based skills to Claude Code. Each skill encapsulates a specific part of the governance workflow, so agents follow the same process every time -- read decisions before coding, validate after, and capture new patterns for the team. + +### Skills included + +| Skill | Purpose | +| -------------------------- | ------------------------------------------------------------------------------------- | +| `archgate:developer` | General development agent that reads ADRs before coding and validates after | +| `archgate:architect` | Validates code changes against all project ADRs for structural compliance | +| `archgate:quality-manager` | Reviews rule coverage and proposes new ADRs when patterns emerge | +| `archgate:adr-author` | Creates and edits ADRs following project conventions | +| `archgate:onboard` | One-time setup: explores the codebase, interviews the developer, creates initial ADRs | + +## Installation + +Install the plugin from the `archgate/claude-code-plugin` GitHub repository. Follow the instructions in the repository README to add it to your Claude Code configuration. + +## Initial setup with onboard + +After installation, run the `archgate:onboard` skill in your project once. This skill: + +1. Explores your codebase structure (directories, key files, package configuration) +2. Interviews you about your team's conventions, constraints, and architectural decisions +3. Creates an initial set of ADRs based on your responses +4. Sets up the `.archgate/` directory with your first rules + +The onboard skill is designed to run once per project. After onboarding, the other skills handle day-to-day development. + +## How it works in practice + +The plugin follows a structured workflow for every coding task: + +### 1. Read applicable ADRs + +When the developer gives a coding task, the agent reads all ADRs that apply to the files being changed. The MCP server provides a condensed briefing with the **Decision** and **Do's and Don'ts** sections from each relevant ADR. + +The agent does not write code until it has read the applicable ADRs. This is enforced by the `archgate:developer` skill. + +### 2. Write code following ADR constraints + +The agent writes code that complies with the constraints from the ADRs. The Do's and Don'ts sections serve as concrete guardrails -- the agent references them while coding. + +### 3. Validate changes + +After writing code, the agent runs `archgate check` to execute automated rules against the changes. Any violations are fixed before proceeding. + +### 4. Architect review + +The agent invokes `archgate:architect` to validate structural ADR compliance beyond what automated rules catch. The architect skill reviews the full context of the changes against all applicable ADRs. + +### 5. Capture learnings + +The agent invokes `archgate:quality-manager` to review the work and identify patterns worth capturing. The quality manager may propose new ADRs or updates to existing ones when recurring conventions emerge. + +## ADR-driven refusal + +When the agent encounters a task that would require violating an ADR, it refuses and explains which ADR would be violated. It then suggests how to achieve the same goal while staying compliant. + +For example, if a developer asks the agent to add `chalk` as a dependency in a project governed by ARCH-006 (dependency policy), the agent will: + +1. Refuse, citing ARCH-006 and the approved dependency list +2. Suggest using `styleText()` from `node:util` instead +3. Offer to implement the task using the compliant alternative + +This behavior is consistent regardless of how the developer phrases the request. ADRs are treated as mandatory constraints, not suggestions. + +## MCP server integration + +The plugin communicates with your project's ADRs through the Archgate MCP server. The server provides: + +- **ADR content** -- full text of any ADR, accessible by ID +- **Review context** -- condensed briefings of all ADRs applicable to a set of changed files +- **Rule checking** -- execution of automated rules with violation reporting +- **ADR listing** -- inventory of all ADRs in the project with metadata + +The MCP server runs locally and reads directly from your `.archgate/adrs/` directory. No data leaves your machine. + +## When to use each skill + +| Scenario | Skill to use | +| -------------------------------------------- | -------------------------- | +| Starting a new project with Archgate | `archgate:onboard` | +| Day-to-day coding tasks | `archgate:developer` | +| Reviewing a PR for ADR compliance | `archgate:architect` | +| Noticing a recurring pattern worth codifying | `archgate:quality-manager` | +| Creating or editing an ADR | `archgate:adr-author` | + +The `archgate:developer` skill orchestrates the others automatically -- it invokes `archgate:architect` and `archgate:quality-manager` as part of its workflow. Most of the time, you only need to interact with the developer skill directly. diff --git a/docs/src/content/docs/guides/cursor-integration.mdx b/docs/src/content/docs/guides/cursor-integration.mdx new file mode 100644 index 00000000..f18b82c6 --- /dev/null +++ b/docs/src/content/docs/guides/cursor-integration.mdx @@ -0,0 +1,67 @@ +--- +title: Cursor Integration +description: Use Archgate with Cursor IDE for AI-assisted development with governance. +--- + +## Setup + +Run `archgate init` with the `--editor cursor` flag to configure Cursor integration in your project: + +```bash +archgate init --editor cursor +``` + +This creates the following files inside your project: + +| File | Purpose | +| --------------------------------------- | -------------------------------------------------------------- | +| `.cursor/mcp.json` | MCP server connection so Cursor's AI agent can access ADRs | +| `.cursor/rules/archgate-governance.mdc` | Always-on Cursor rule that instructs the agent to consult ADRs | + +If `.cursor/mcp.json` already exists, Archgate merges its configuration additively -- existing MCP server entries are preserved. + +## What it configures + +The generated `.cursor/mcp.json` registers the Archgate MCP server: + +```json +{ + "mcpServers": { + "archgate": { + "command": "archgate", + "args": ["mcp"] + } + } +} +``` + +The governance rule in `.cursor/rules/archgate-governance.mdc` uses `alwaysApply: true`, which means the Cursor agent always has governance context available without manual activation. + +## How it works + +Once configured, Cursor's AI agent connects to the Archgate MCP server and gains access to your project's ADRs. The workflow follows four steps: + +1. **Review context** -- The agent calls `review_context` to see which ADRs apply to the files being changed. This returns changed files grouped by domain with condensed ADR briefings (Decision and Do's/Don'ts sections only). + +2. **Read individual ADRs** -- For full context on a specific decision, the agent reads the `adr://` resource (for example, `adr://ARCH-001`) to get the complete ADR content including rationale, consequences, and compliance sections. + +3. **Write code** -- The agent implements changes following the constraints from the applicable ADRs. + +4. **Run compliance checks** -- The agent calls `check` (optionally with `staged: true` for pre-commit scenarios) to validate that the code complies with all ADR rules. Violations include file paths and line numbers. + +## Session transcript access + +The `cursor_session_context` MCP tool reads Cursor agent session transcripts from disk. This allows Archgate-aware plugins and skills to access the history of the current Cursor agent conversation, which is useful for recovering context that may have been compacted or truncated. + +The tool accepts two optional parameters: + +- `maxEntries` -- Maximum number of entries to return (default: 200, most recent entries). +- `sessionId` -- A specific session UUID to read. If omitted, the most recent session is used. + +## Tips for effective usage + +- **Run `check` before committing.** Use `staged: true` to scope checks to only the files being committed. +- **Use `review_context` at the start of a task.** It is more efficient than calling `list_adrs` and reading each ADR individually. +- **Read full ADRs when the briefing is not enough.** The `adr://` resource provides the complete document including rationale and examples. +- **Commit the `.cursor/` directory.** This ensures every team member gets the same governance configuration when they clone the repository. +- **Keep ADR rules files up to date.** The agent enforces what the rules check for -- if a rule is missing, the violation will not be caught. diff --git a/docs/src/content/docs/guides/mcp-server.mdx b/docs/src/content/docs/guides/mcp-server.mdx new file mode 100644 index 00000000..4901d609 --- /dev/null +++ b/docs/src/content/docs/guides/mcp-server.mdx @@ -0,0 +1,119 @@ +--- +title: MCP Server +description: Use the Archgate MCP server for AI agent integration. +--- + +The Archgate MCP server exposes your project's ADRs and compliance checks to AI agents over the [Model Context Protocol](https://modelcontextprotocol.io/). Any MCP-compatible client -- Claude Code, Cursor, or custom tooling -- can connect to it. + +## Starting the server + +The server uses stdio transport. Start it with: + +```bash +archgate mcp +``` + +You do not typically run this command manually. Instead, configure your AI tool to launch it automatically (see below). + +## Configuring in Claude Code + +Add the following to your project's `.mcp.json` file (create it if it does not exist): + +```json +{ + "mcpServers": { + "archgate": { + "command": "archgate", + "args": ["mcp"] + } + } +} +``` + +Claude Code reads this file on startup and connects to the Archgate MCP server automatically. You can also run `archgate init` (which defaults to `--editor claude`) to generate this configuration along with the full `.archgate/` directory. + +## Configuring in Cursor + +Run `archgate init --editor cursor` to generate `.cursor/mcp.json` with the same server configuration. See the [Cursor Integration](/guides/cursor-integration/) guide for details. + +## Available MCP tools + +The server registers five tools that AI agents can call. + +### `check` + +Run ADR compliance checks against the codebase. + +| Parameter | Type | Description | +| --------- | ---------- | ------------------------------- | +| `adrId` | `string?` | Only check a specific ADR by ID | +| `staged` | `boolean?` | Only check git-staged files | + +Returns a JSON summary with pass/fail status, violation counts, and detailed results including file paths and line numbers. + +### `list_adrs` + +List all ADRs in the project with metadata. + +| Parameter | Type | Description | +| --------- | --------- | --------------------------------------------------------------------------- | +| `domain` | `string?` | Filter by domain (`backend`, `frontend`, `data`, `architecture`, `general`) | + +Returns an array of objects with `id`, `title`, `domain`, and `rules` fields for each ADR. + +### `review_context` + +Get changed files grouped by domain with applicable ADR briefings. This is the recommended starting point for an agent beginning a task -- it combines file change detection, domain grouping, and ADR summarization into a single call. + +| Parameter | Type | Description | +| ----------- | ---------- | -------------------------------------------------------------------- | +| `staged` | `boolean?` | When true, only include git-staged files. Default: all changed files | +| `runChecks` | `boolean?` | When true, run compliance checks and include results | +| `domain` | `string?` | Filter results to a single domain | + +Returns briefings containing only the Decision and Do's/Don'ts sections of each applicable ADR, keeping the response concise. + +### `claude_code_session_context` + +Read the current Claude Code session transcript for the project. Returns filtered entries (user and assistant messages) from the most recent session JSONL file. + +| Parameter | Type | Description | +| ------------ | --------- | -------------------------------------------------------------- | +| `maxEntries` | `number?` | Maximum relevant entries to return (default: 200, most recent) | + +### `cursor_session_context` + +Read Cursor agent session transcripts for the project. Returns filtered entries from Cursor's agent-transcripts JSONL files. + +| Parameter | Type | Description | +| ------------ | --------- | ------------------------------------------------------------------------ | +| `maxEntries` | `number?` | Maximum relevant entries to return (default: 200, most recent) | +| `sessionId` | `string?` | Specific session UUID to read. If omitted, reads the most recent session | + +## Available MCP resources + +### `adr://\{id\}` + +Read the full content of an ADR by ID. Replace the `id` placeholder with the ADR identifier (for example, `adr://ARCH-001`). + +Returns the complete ADR markdown including frontmatter, rationale, decision, do's and don'ts, consequences, compliance, and references sections. + +## No-project behavior + +If the MCP server starts in a directory without an `.archgate/` directory, all tools remain available but return guidance instructing the agent to run `archgate init` to initialize governance. The server does not crash or refuse to start -- it provides actionable feedback so the agent can bootstrap the project. + +## Example usage flow + +A typical AI agent session using the MCP server follows this pattern: + +1. **Agent calls `review_context`** with `runChecks: false` to get a condensed briefing of all ADRs that apply to the current set of changed files. + +2. **Agent reads the briefings** and identifies which architectural constraints apply to its task. + +3. **Agent reads a full ADR** via `adr://ARCH-002` (for example) when it needs the complete rationale or implementation examples beyond the condensed briefing. + +4. **Agent writes code** following the constraints from the applicable ADRs. + +5. **Agent calls `check`** with `staged: true` to validate compliance. If violations are found, the response includes file paths and line numbers so the agent can fix them. + +6. **Agent iterates** until `check` reports zero violations. diff --git a/docs/src/content/docs/guides/pre-commit-hooks.mdx b/docs/src/content/docs/guides/pre-commit-hooks.mdx new file mode 100644 index 00000000..0fbfcbcc --- /dev/null +++ b/docs/src/content/docs/guides/pre-commit-hooks.mdx @@ -0,0 +1,92 @@ +--- +title: Pre-commit Hooks +description: Run Archgate checks automatically before every commit. +--- + +## Overview + +The `archgate check --staged` command checks only git-staged files against your ADR rules. Because it skips unstaged and untracked files, it runs fast enough to use as a pre-commit hook without slowing down your workflow. + +When a check fails, the commit is blocked. Violations are printed to stderr with file paths and line numbers so you can locate and fix them immediately. + +## Lefthook + +[Lefthook](https://github.com/evilmartians/lefthook) is a fast, cross-platform git hooks manager. Add the following to your `lefthook.yml`: + +```yaml +# lefthook.yml +pre-commit: + commands: + adr-check: + run: archgate check --staged +``` + +Install the hook with: + +```bash +lefthook install +``` + +## Husky + +[Husky](https://typicode.github.io/husky/) is a popular git hooks tool for Node.js projects. Add the check to your pre-commit hook: + +```bash +# .husky/pre-commit +archgate check --staged +``` + +Make sure the hook file is executable: + +```bash +chmod +x .husky/pre-commit +``` + +## What happens when checks fail + +When `archgate check --staged` finds violations, it exits with code 1. This blocks the commit. The output includes: + +- The ADR ID and rule name that was violated +- The file path where the violation was found +- The line number (when available) +- A description of what the rule expects + +Fix the violations, re-stage the files with `git add`, and commit again. + +## Performance + +The `--staged` flag restricts checks to only the files in the git staging area. This means: + +- A project with hundreds of source files but only three staged files will only check those three files. +- Rules that do not match any staged files are skipped entirely. +- Typical pre-commit checks complete in under a second. + +Without `--staged`, `archgate check` scans all files matched by each ADR's `files` glob pattern, which is useful for CI but slower for interactive use. + +## Useful flags + +| Flag | Purpose | +| ------------ | -------------------------------------------------------------------------------------------------------------------------- | +| `--staged` | Only check git-staged files (required for pre-commit) | +| `--verbose` | Show passing rules and timing information -- helpful when debugging why a check is slow or which rules are being evaluated | +| `--json` | Output results as JSON -- useful for piping to other tools or custom reporting scripts | +| `--adr ` | Only check rules from a specific ADR -- useful for isolating a single rule during debugging | +| `--ci` | Output GitHub Actions annotations -- use this in CI workflows instead of pre-commit hooks | + +## Combining with other hooks + +Pre-commit hooks can run multiple commands. For example, with Lefthook: + +```yaml +# lefthook.yml +pre-commit: + commands: + lint: + run: npm run lint + typecheck: + run: npm run typecheck + adr-check: + run: archgate check --staged +``` + +Each command runs independently. If any command exits with a non-zero code, the commit is blocked. diff --git a/docs/src/content/docs/guides/writing-adrs.mdx b/docs/src/content/docs/guides/writing-adrs.mdx new file mode 100644 index 00000000..e9a7cf30 --- /dev/null +++ b/docs/src/content/docs/guides/writing-adrs.mdx @@ -0,0 +1,306 @@ +--- +title: Writing ADRs +description: A complete guide to writing effective Architecture Decision Records. +--- + +## Creating an ADR + +Use `archgate adr create` to generate a new ADR with the standard template. The command supports both interactive and non-interactive modes. + +### Interactive mode + +Run the command with no arguments to get guided prompts: + +```bash +archgate adr create +``` + +You will be prompted for: + +1. **Domain** -- one of `backend`, `frontend`, `data`, `architecture`, or `general` +2. **Title** -- a short, descriptive name for the decision +3. **File patterns** -- optional comma-separated globs that scope rule checking (e.g., `src/commands/**/*.ts`) + +The CLI assigns a sequential ID based on the domain prefix (`ARCH-001`, `FE-002`, `BE-003`, etc.) and writes the file to `.archgate/adrs/`. + +### Non-interactive mode + +Pass `--title` and `--domain` to skip prompts: + +```bash +archgate adr create --title "API Response Format" --domain backend --files "src/api/**/*.ts" +``` + +Available flags: + +| Flag | Description | +| ----------------- | ------------------------------------------------------ | +| `--title ` | ADR title (required for non-interactive mode) | +| `--domain <name>` | Domain: backend, frontend, data, architecture, general | +| `--files <globs>` | Comma-separated file patterns for rule scoping | +| `--rules` | Set `rules: true` in frontmatter | +| `--body <md>` | Full ADR body markdown (skip template) | +| `--json` | Output the result as JSON | + +## The generated template + +When you create an ADR without `--body`, the CLI generates a template with all standard sections: + +```markdown +--- +id: BE-001 +title: API Response Format +domain: backend +rules: false +files: ["src/api/**/*.ts"] +--- + +# API Response Format + +## Context + +Describe the context and problem statement. + +## Decision + +Describe the decision that was made. + +## Do's and Don'ts + +### Do + +- + +### Don't + +- + +## Consequences + +### Positive + +- + +### Negative + +- + +### Risks + +- + +## Compliance and Enforcement + +Describe how this decision will be enforced. + +## References + +- +``` + +## Section-by-section writing guidance + +### Context + +Explain why this decision was needed. What problem prompted it? What alternatives were considered and why were they rejected? + +Good context sections include: + +- The problem or pain point that triggered the decision +- Alternatives that were evaluated, with brief trade-off analysis +- Any constraints that narrowed the options (team size, runtime, compatibility) + +```markdown +## Context + +The CLI needs a consistent pattern for defining and registering commands. As the +command surface grows (init, check, adr, mcp, upgrade, clean), the registration +mechanism must scale without introducing hidden coupling or making the dependency +graph opaque. + +**Alternatives considered:** + +- **Auto-discovery via `executableDir()`** -- Commander.js supports automatic + command discovery by scanning a directory. This hides the dependency graph and + makes dead command detection impossible. +- **Single-file command map** -- Simple but creates a monolithic file that grows + with every command. +``` + +### Decision + +State what was decided. Be specific and concrete -- this section should leave no ambiguity about what developers must do. + +Include numbered constraints when the decision has multiple facets: + +```markdown +## Decision + +Commands live in src/commands/ and export a register\*Command(program) function. +The main entry point (src/cli.ts) explicitly imports and calls each register +function. + +**Key constraints:** + +1. **One command per file** -- Each .ts file defines exactly one command +2. **Explicit registration** -- Every command must be manually imported in src/cli.ts +3. **Thin commands** -- Command files handle I/O only; no business logic +``` + +### Do's and Don'ts + +This is the section developers and AI agents reference most frequently. Write concrete examples of correct and incorrect patterns. Use real code when possible. + +```markdown +## Do's and Don'ts + +### Do + +- Export a register\*Command function from each command module +- Keep commands thin: parse args, call helpers/engine, format output +- Use src/commands/<name>.ts for top-level commands + +### Don't + +- Don't put business logic in command files -- move it to src/engine/ or src/helpers/ +- Don't use executableDir() for command discovery +- Don't call .parse() in command files -- the entry point handles parsing +``` + +### Consequences + +Break consequences into three categories: + +- **Positive** -- benefits the team gains from this decision +- **Negative** -- trade-offs the team accepts (every decision has them) +- **Risks** -- what could go wrong, and how you plan to mitigate it + +```markdown +## Consequences + +### Positive + +- In-process execution enables testing without spawning subprocesses +- Explicit imports make all commands visible at a glance in src/cli.ts + +### Negative + +- Manual import bookkeeping -- each new command requires adding an import + +### Risks + +- Stale imports when commands are removed. Mitigation: TypeScript catches + missing modules at compile time. +``` + +### Compliance and Enforcement + +Describe how this decision is enforced. There are two enforcement mechanisms: + +1. **Automated rules** -- companion `.rules.ts` files that run during `archgate check` +2. **Manual enforcement** -- what code reviewers should verify + +```markdown +## Compliance and Enforcement + +### Automated Enforcement + +- **Archgate rule** ARCH-001/register-function-export: Scans all command files + and verifies each exports a register\*Command function. Severity: error. + +### Manual Enforcement + +Code reviewers MUST verify: + +1. New commands are imported and registered in src/cli.ts +2. Command files delegate to engine/helpers for business logic +``` + +### References + +Link to related ADRs, external documentation, or relevant discussions: + +```markdown +## References + +- [Commander.js documentation](https://github.com/tj/commander.js) +- [ARCH-004 -- No Barrel Files](./ARCH-004-no-barrel-files.md) +- [ARCH-002 -- Error Handling](./ARCH-002-error-handling.md) +``` + +## Scoping rules with `files` + +The `files` field in the frontmatter is an array of glob patterns. When set, `archgate check` only passes matching files to the rule's `ctx.scopedFiles`. This keeps rules focused on the code they govern. + +```yaml +--- +id: ARCH-001 +title: Command Structure +domain: architecture +rules: true +files: ["src/commands/**/*.ts"] +--- +``` + +If `files` is omitted, `ctx.scopedFiles` includes all project files. This is appropriate for project-wide rules like dependency policies. + +Common patterns: + +| Pattern | Matches | +| ---------------------- | -------------------------------- | +| `src/commands/**/*.ts` | All TypeScript files in commands | +| `src/**/*.ts` | All TypeScript source files | +| `package.json` | Only the root package.json | +| `src/api/**/*.ts` | API layer files | +| `tests/**/*.test.ts` | Test files | + +## When to set `rules: true` vs `rules: false` + +Set `rules: true` when you have a companion `.rules.ts` file with automated checks. The file must be named identically to the ADR markdown file but with a `.rules.ts` extension: + +``` +.archgate/adrs/ + ARCH-001-command-structure.md # rules: true + ARCH-001-command-structure.rules.ts # companion rules file + ARCH-002-error-handling.md # rules: true + ARCH-002-error-handling.rules.ts # companion rules file + GEN-001-code-review-process.md # rules: false (no automated checks) +``` + +Set `rules: false` for decisions that are enforced through code review alone -- process decisions, team agreements, or guidelines that are difficult to check programmatically. + +## Updating ADRs + +Use `archgate adr update` to modify an existing ADR: + +```bash +archgate adr update --id ARCH-001 --body "## Context\n\nUpdated context..." --title "New Title" +``` + +The `--id` and `--body` flags are required. All other frontmatter fields (`--title`, `--domain`, `--files`, `--rules`) are optional and preserve their existing values when omitted. + +| Flag | Description | +| ----------------- | ------------------------------------------------- | +| `--id <id>` | ADR ID to update (required) | +| `--body <md>` | Full replacement body markdown (required) | +| `--title <title>` | New title (preserves existing if omitted) | +| `--domain <name>` | New domain (preserves existing if omitted) | +| `--files <globs>` | New file patterns (preserves existing if omitted) | +| `--rules` | Set `rules: true` | +| `--json` | Output the result as JSON | + +## Tips for effective ADRs + +1. **Keep each ADR focused on a single decision.** If you find yourself writing about two unrelated topics, split them into separate ADRs. + +2. **Be specific in Do's and Don'ts.** Vague guidelines like "write clean code" are not actionable. Show concrete code patterns. + +3. **Include real code examples.** The Do's and Don'ts section is where developers and AI agents look first. Annotated code examples make the decision unambiguous. + +4. **Document alternatives you rejected.** Future contributors will ask "why didn't we use X?" The Context section should answer that question. + +5. **State trade-offs honestly.** Every decision has negative consequences. Documenting them builds trust and helps the team understand what was traded away. + +6. **Write rules for decisions that can be checked automatically.** If a rule can catch a violation before code review, set `rules: true` and write a companion `.rules.ts` file. See the [Writing Rules](/guides/writing-rules/) guide. + +7. **Use domain prefixes to organize.** The domain field (`backend`, `frontend`, `data`, `architecture`, `general`) determines the ID prefix and helps filter ADRs by area. diff --git a/docs/src/content/docs/guides/writing-rules.mdx b/docs/src/content/docs/guides/writing-rules.mdx new file mode 100644 index 00000000..f6495e6a --- /dev/null +++ b/docs/src/content/docs/guides/writing-rules.mdx @@ -0,0 +1,447 @@ +--- +title: Writing Rules +description: Learn to write automated rules that enforce your ADR decisions. +--- + +Rules are TypeScript functions that check your codebase for ADR compliance. They live in companion `.rules.ts` files next to ADR markdown files and run when you execute `archgate check`. + +``` +.archgate/adrs/ + ARCH-001-command-structure.md # The decision + ARCH-001-command-structure.rules.ts # The automated checks +``` + +## Basic setup + +Every rules file exports a default `defineRules()` call. Each key becomes a rule ID, and each rule has a `description` and an async `check` function that receives a context object. + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "my-rule-id": { + description: "What this rule checks", + async check(ctx) { + // Your check logic here + }, + }, +}); +``` + +A single rules file can define multiple rules: + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "first-rule": { + description: "Checks one thing", + async check(ctx) { + // ... + }, + }, + "second-rule": { + description: "Checks another thing", + async check(ctx) { + // ... + }, + }, +}); +``` + +## The Context API + +The `ctx` object passed to every `check` function provides file reading, searching, and reporting capabilities. Here is a detailed reference with examples. + +### ctx.scopedFiles + +An array of file paths matching the ADR's `files` glob from its frontmatter. If the ADR has no `files` field, this includes all project files. + +```typescript +for (const file of ctx.scopedFiles) { + const content = await ctx.readFile(file); + // Check content... +} +``` + +Use `ctx.scopedFiles` when your rule should only apply to files the ADR governs. For example, a command structure rule scoped to `src/commands/**/*.ts` will only receive command files. + +### ctx.changedFiles + +An array of file paths that have been modified (git staged or changed). Useful for incremental checking -- only validate files that were actually touched. + +```typescript +const filesToCheck = ctx.scopedFiles.filter((f) => + ctx.changedFiles.includes(f) +); +for (const file of filesToCheck) { + // Only check changed files +} +``` + +### ctx.readFile(path) + +Read a file's content as a string. The path is relative to the project root. + +```typescript +const content = await ctx.readFile("src/cli.ts"); +``` + +### ctx.readJSON(path) + +Read and parse a JSON file. Returns `unknown` -- cast it to the expected shape. + +```typescript +const pkg = (await ctx.readJSON("package.json")) as { + dependencies?: Record<string, string>; +}; +``` + +### ctx.grep(file, pattern) + +Search a single file with a regular expression. Returns an array of `GrepMatch` objects, each with `file`, `line`, `column`, and `content` properties. + +```typescript +const matches = await ctx.grep(file, /console\.error\(/); +for (const match of matches) { + ctx.report.violation({ + message: "Use logError() instead of console.error()", + file: match.file, + line: match.line, + }); +} +``` + +### ctx.grepFiles(pattern, fileGlob) + +Search across multiple files matching a glob pattern. Returns a flat array of `GrepMatch` objects from all matching files. + +```typescript +const matches = await ctx.grepFiles(/TODO:/, "src/**/*.ts"); +for (const match of matches) { + ctx.report.warning({ + message: "TODO comment found", + file: match.file, + line: match.line, + }); +} +``` + +### ctx.glob(pattern) + +Find files by glob pattern. Returns an array of file paths relative to the project root. + +```typescript +const testFiles = await ctx.glob("tests/**/*.test.ts"); +``` + +### ctx.report + +The reporting interface with three severity methods: + +- `ctx.report.violation(detail)` -- error severity (exit code 1, blocks CI) +- `ctx.report.warning(detail)` -- warning severity (logged but does not block) +- `ctx.report.info(detail)` -- informational (logged for visibility) + +Each method accepts an object with: + +| Field | Type | Required | Description | +| --------- | -------- | -------- | -------------------------------------- | +| `message` | `string` | Yes | What the violation is | +| `file` | `string` | No | Path to the offending file | +| `line` | `number` | No | Line number of the violation | +| `fix` | `string` | No | Suggested fix (shown to the developer) | + +```typescript +ctx.report.violation({ + message: "Command file must export a register*Command function", + file: "src/commands/check.ts", + line: 5, + fix: "Add: export function registerCheckCommand(program: Command) { ... }", +}); +``` + +### ctx.projectRoot + +The absolute path to the project root directory. Useful when you need to construct absolute paths. + +## Complete worked examples + +### Example 1: Dependency allowlist + +Check that all production dependencies are on an approved list. This is the rule Archgate uses for its own ARCH-006 dependency policy. + +```typescript +import { defineRules } from "archgate/rules"; + +const APPROVED_DEPS = [ + "@commander-js/extra-typings", + "inquirer", + "@modelcontextprotocol/sdk", + "zod", +]; + +export default defineRules({ + "no-unapproved-deps": { + description: "Production dependencies must be on the approved list", + async check(ctx) { + let pkg: { dependencies?: Record<string, string> }; + try { + pkg = (await ctx.readJSON("package.json")) as typeof pkg; + } catch { + return; + } + + const deps = Object.keys(pkg.dependencies ?? {}); + for (const dep of deps) { + if (!APPROVED_DEPS.includes(dep)) { + ctx.report.violation({ + message: `Unapproved production dependency: "${dep}". Approved: ${APPROVED_DEPS.join(", ")}`, + file: "package.json", + fix: `Either add "${dep}" to the approved list in the ADR or move it to devDependencies`, + }); + } + } + }, + }, +}); +``` + +### Example 2: Required export pattern + +Verify that every command file exports a `register*Command` function. This is the rule Archgate uses for its own ARCH-001 command structure. + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "register-function-export": { + description: "Command files must export a register*Command function", + async check(ctx) { + const files = ctx.scopedFiles.filter((f) => !f.endsWith("index.ts")); + const checks = files.map(async (file) => { + const content = await ctx.readFile(file); + if (!/export\s+function\s+register\w+Command/.test(content)) { + ctx.report.violation({ + message: "Command file must export a register*Command function", + file, + }); + } + }); + await Promise.all(checks); + }, + }, +}); +``` + +### Example 3: Banned import pattern + +Prevent importing a specific library when native alternatives exist. + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "no-lodash": { + description: "Do not use lodash -- use native array methods instead", + async check(ctx) { + const matches = await ctx.grepFiles( + /import\s+.*from\s+['"]lodash/, + "src/**/*.ts" + ); + for (const match of matches) { + ctx.report.violation({ + message: "Do not import lodash. Use native array methods instead.", + file: match.file, + line: match.line, + fix: "Replace lodash usage with native Array.prototype methods", + }); + } + }, + }, +}); +``` + +### Example 4: File naming convention + +Enforce kebab-case naming for source files. + +```typescript +import { defineRules } from "archgate/rules"; +import { basename } from "node:path"; + +export default defineRules({ + "kebab-case-files": { + description: "Source files must use kebab-case naming", + async check(ctx) { + for (const file of ctx.scopedFiles) { + const name = basename(file).replace(/\.(ts|tsx|js|jsx)$/, ""); + if (name !== name.toLowerCase() || name.includes("_")) { + ctx.report.violation({ + message: `File name "${basename(file)}" must be kebab-case (lowercase with hyphens)`, + file, + fix: `Rename to ${name.toLowerCase().replace(/_/g, "-")}`, + }); + } + } + }, + }, +}); +``` + +### Example 5: Maximum file length + +Warn when files exceed a line count threshold. + +```typescript +import { defineRules } from "archgate/rules"; + +const MAX_LINES = 300; + +export default defineRules({ + "max-file-length": { + description: `Source files should not exceed ${MAX_LINES} lines`, + async check(ctx) { + const checks = ctx.scopedFiles.map(async (file) => { + const content = await ctx.readFile(file); + const lineCount = content.split("\n").length; + if (lineCount > MAX_LINES) { + ctx.report.warning({ + message: `File has ${lineCount} lines (max: ${MAX_LINES}). Consider splitting it.`, + file, + fix: "Extract related functions into separate modules", + }); + } + }); + await Promise.all(checks); + }, + }, +}); +``` + +### Example 6: Required test coverage + +Verify that every source file has a corresponding test file. + +```typescript +import { defineRules } from "archgate/rules"; +import { basename } from "node:path"; + +export default defineRules({ + "test-file-exists": { + description: "Every source module must have a corresponding test file", + async check(ctx) { + const testFiles = await ctx.glob("tests/**/*.test.ts"); + const testBaseNames = new Set( + testFiles.map((f) => basename(f).replace(".test.ts", "")) + ); + + for (const file of ctx.scopedFiles) { + const name = basename(file).replace(/\.ts$/, ""); + if (!testBaseNames.has(name)) { + ctx.report.warning({ + message: `No test file found for ${basename(file)}`, + file, + fix: `Create tests/${name}.test.ts`, + }); + } + } + }, + }, +}); +``` + +## Severity levels + +Each rule can set a default severity in its configuration. The severity determines how violations are treated: + +| Severity | Exit code | Behavior | +| --------- | --------- | ------------------------------------ | +| `error` | 1 | Blocks CI, must be fixed | +| `warning` | 0 | Logged but does not block | +| `info` | 0 | Informational, logged for visibility | + +Set the severity in the rule definition: + +```typescript +export default defineRules({ + "my-rule": { + description: "...", + severity: "warning", + async check(ctx) { + // Violations from this rule are warnings, not errors + ctx.report.violation({ message: "..." }); + }, + }, +}); +``` + +If `severity` is omitted, it defaults to `error`. + +You can also report at different severities within the same rule using `ctx.report.violation()`, `ctx.report.warning()`, and `ctx.report.info()` directly. + +## Rule timeout + +Each rule has a 30-second execution timeout. If a rule exceeds this limit, it is treated as an error. This prevents runaway checks from blocking the pipeline. + +Keep rules fast by: + +- Using `ctx.grepFiles()` instead of reading every file manually +- Using `Promise.all()` to check files in parallel +- Scoping rules with the `files` frontmatter field to limit the number of files processed + +## The `fix` field + +The `fix` field is an optional string shown to the developer alongside the violation message. It describes what action to take to resolve the issue. Fixes are not auto-applied -- they are guidance. + +```typescript +ctx.report.violation({ + message: `Unapproved dependency: "chalk"`, + file: "package.json", + fix: "Use styleText() from node:util instead of chalk", +}); +``` + +When displayed, the fix appears below the violation message: + +``` +ARCH-006/no-unapproved-deps + package.json + Unapproved dependency: "chalk" + Fix: Use styleText() from node:util instead of chalk +``` + +## Tips for writing rules + +1. **Use `Promise.all()` for parallel file checks.** When checking multiple files independently, process them in parallel instead of sequentially. + + ```typescript + // Good: parallel + const checks = files.map(async (file) => { + const content = await ctx.readFile(file); + // ... + }); + await Promise.all(checks); + + // Avoid: sequential + for (const file of files) { + const content = await ctx.readFile(file); + // ... + } + ``` + +2. **Use `ctx.changedFiles` for incremental checking.** When running `archgate check --staged`, `ctx.changedFiles` contains only the git-staged files. Filter `ctx.scopedFiles` against it to check only what changed. + +3. **Keep rules focused on one concern.** A rule that checks both naming conventions and import patterns should be split into two rules with separate IDs. + +4. **Use `ctx.grepFiles()` over manual iteration.** When searching for a pattern across many files, `ctx.grepFiles()` is more efficient than reading each file and running a regex. + +5. **Provide actionable `fix` messages.** A fix like "Don't do this" is not helpful. Tell the developer exactly what to do instead. + +6. **Filter out non-applicable files early.** If your rule only applies to certain files within the scope, filter `ctx.scopedFiles` before processing: + + ```typescript + const commandFiles = ctx.scopedFiles.filter((f) => !f.endsWith("index.ts")); + ``` + +7. **Handle missing files gracefully.** If your rule reads a specific file like `package.json`, wrap the read in a try/catch and return early if the file does not exist. diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx new file mode 100644 index 00000000..f05ba08e --- /dev/null +++ b/docs/src/content/docs/index.mdx @@ -0,0 +1,63 @@ +--- +title: Archgate +description: Enforce Architecture Decision Records as executable rules — for both humans and AI agents. +template: splash +hero: + tagline: Write an ADR once. Enforce it everywhere. Feed it to AI agents automatically. + actions: + - text: Get Started + link: /getting-started/installation/ + icon: right-arrow + variant: primary + - text: View on GitHub + link: https://github.com/archgate/cli + icon: external + variant: minimal +--- + +import { Card, CardGrid } from "@astrojs/starlight/components"; + +## How it works + +Archgate has two layers that work together: + +1. **ADRs as documents** — Markdown files with YAML frontmatter that describe architectural decisions in plain language. Humans read them. AI agents read them. Everyone stays aligned. + +2. **ADRs as rules** — Companion `.rules.ts` files with automated checks written in TypeScript. They run against your codebase and report violations with file paths and line numbers. + +``` +.archgate/ + adrs/ + ARCH-001-command-structure.md # The decision (human + AI readable) + ARCH-001-command-structure.rules.ts # The checks (machine executable) + ARCH-002-error-handling.md + ARCH-002-error-handling.rules.ts + lint/ + archgate.config.ts # Archgate configuration +``` + +When you run `archgate check`, the CLI loads every ADR that has `rules: true` in its frontmatter, executes the companion rules file, and reports any violations. Exit code 0 means your code complies. Exit code 1 means it does not. + +## Key Features + +<CardGrid> + <Card title="Executable Rules" icon="seti:typescript"> + Write rules in TypeScript. Archgate runs them against your codebase and + reports violations with file paths and line numbers. Rules live next to the + decisions they enforce. + </Card> + <Card title="CI Integration" icon="seti:pipeline"> + Wire `archgate check` into your pipeline. Exit code 1 blocks merges when + rules are violated. Works with GitHub Actions, GitLab CI, or any CI system + that respects exit codes. + </Card> + <Card title="AI-Aware Governance" icon="star"> + The MCP server gives AI agents live access to your ADRs. They read decisions + before writing code and validate after. No copy-pasting rules into prompts. + </Card> + <Card title="Self-Governance" icon="approve-check-circle"> + Archgate governs its own development. The same tool that checks your code + checks ours. Six ADRs enforce command structure, error handling, output + formatting, testing, and more. + </Card> +</CardGrid> diff --git a/docs/src/content/docs/reference/adr-schema.mdx b/docs/src/content/docs/reference/adr-schema.mdx new file mode 100644 index 00000000..b107c55b --- /dev/null +++ b/docs/src/content/docs/reference/adr-schema.mdx @@ -0,0 +1,281 @@ +--- +title: ADR Schema +description: YAML frontmatter schema and markdown structure for Archgate ADRs. +--- + +Every Archgate ADR is a Markdown file stored in `.archgate/adrs/` with YAML frontmatter that defines the decision's identity and scope. This page documents the frontmatter schema, markdown section structure, and validation behavior. + +## Frontmatter Schema + +The YAML frontmatter block sits between `---` delimiters at the top of the file. + +```yaml +--- +id: ARCH-001 +title: Command Structure +domain: architecture +rules: true +files: ["src/commands/**/*.ts"] +--- +``` + +### Fields + +| Field | Type | Required | Description | +| -------- | ---------- | -------- | ---------------------------------------------------------------------------------- | +| `id` | `string` | Yes | Unique identifier. Must be non-empty. Convention: `PREFIX-NNN` (e.g., `ARCH-001`). | +| `title` | `string` | Yes | Human-readable title of the decision. Must be non-empty. | +| `domain` | `enum` | Yes | Domain category. One of: `backend`, `frontend`, `data`, `architecture`, `general`. | +| `rules` | `boolean` | Yes | Whether this ADR has a companion `.rules.ts` file with automated checks. | +| `files` | `string[]` | No | Glob patterns that scope which files the rules apply to. | + +### id + +The ADR identifier. By convention, it uses the domain prefix followed by a zero-padded sequence number (e.g., `ARCH-001`, `BE-003`). The `archgate adr create` command generates IDs automatically. + +Any non-empty string is valid, but following the prefix convention keeps ADRs organized and sortable. + +### title + +A short, descriptive name for the architectural decision. Displayed in `archgate adr list` output and used as the heading when AI agents reference the ADR. + +### domain + +Groups related ADRs together. The domain also determines the ID prefix used by `archgate adr create`. + +### rules + +Set to `true` when this ADR has a companion `.rules.ts` file. When `archgate check` runs, it skips ADRs where `rules` is `false`. + +### files + +An optional array of glob patterns that scope the rule's file coverage. When present, `ctx.scopedFiles` in the rules file only contains files matching these patterns. When absent, all project files are in scope. + +```yaml +files: ["src/commands/**/*.ts"] +``` + +Multiple patterns can be specified: + +```yaml +files: ["src/api/**/*.ts", "src/middleware/**/*.ts"] +``` + +--- + +## Domain Prefixes + +Each domain maps to a prefix used in the ADR ID convention. + +| Domain | Prefix | Example ID | +| -------------- | ------ | ---------- | +| `backend` | `BE` | `BE-001` | +| `frontend` | `FE` | `FE-001` | +| `data` | `DATA` | `DATA-001` | +| `architecture` | `ARCH` | `ARCH-001` | +| `general` | `GEN` | `GEN-001` | + +The `archgate adr create` command uses this mapping to auto-generate IDs. + +--- + +## File Naming Convention + +ADR files follow a naming convention that encodes the ID and a human-readable slug: + +``` +{ID}-{slug}.md # The document +{ID}-{slug}.rules.ts # The companion rules file (optional) +``` + +For example: + +``` +ARCH-001-command-structure.md +ARCH-001-command-structure.rules.ts +``` + +The slug is a kebab-case version of the title, auto-generated by `archgate adr create`. + +--- + +## Markdown Sections + +After the frontmatter, the ADR body follows a standard section structure. While Archgate does not enforce specific sections, the following structure is recommended for consistency. + +### Context + +Describes the problem or situation that prompted the decision. Include alternatives that were considered and why they were rejected. + +```markdown +## Context + +The CLI returns errors in inconsistent formats. Some commands print raw +stack traces, others print nothing, and a few use `console.error()` with +custom formatting. + +**Alternatives considered:** + +- **No standard** -- Let each command handle errors its own way. Simple + but leads to an inconsistent user experience. +- **Try/catch wrapper** -- A global try/catch at the CLI entry point. + Loses context about which command failed. +``` + +### Decision + +States the decision itself and its key constraints. This is the primary section AI agents read before writing code. + +```markdown +## Decision + +All commands MUST use `logError()` from `src/helpers/log.ts` for error +output. Commands MUST NOT call `console.error()` directly. +``` + +### Do's and Don'ts + +Concrete, actionable guidance split into two sub-sections. These act as a quick-reference checklist for developers and AI agents. + +```markdown +## Do's and Don'ts + +### Do + +- Use `logError(message, detail?)` for all error output +- Include a suggested fix in the detail parameter when possible +- Exit with code 1 for user errors, code 2 for internal errors + +### Don't + +- Don't call `console.error()` directly in command files +- Don't print stack traces to users +- Don't exit without printing an error message first +``` + +### Consequences + +Split into three sub-sections that document trade-offs. + +```markdown +## Consequences + +### Positive + +- Consistent error formatting across all commands +- Machine-parseable error output when combined with `--json` + +### Negative + +- Requires importing `logError` in every command file +- Cannot use built-in error formatting from libraries + +### Risks + +- New contributors may use `console.error()` by habit. Mitigated by the + automated rule that scans for direct `console.error()` calls. +``` + +### Compliance and Enforcement + +Describes how the decision is enforced through automated rules and manual review. + +```markdown +## Compliance and Enforcement + +### Automated Enforcement + +- **Archgate rule** ARCH-002/no-console-error: Scans command files for + `console.error()` calls. Severity: error. + +### Manual Enforcement + +Code reviewers MUST verify: + +1. Error messages are actionable and include context +2. Exit codes match the error type (1 for user, 2 for internal) +``` + +### References + +Links to related ADRs, external documentation, or design documents. + +```markdown +## References + +- [ARCH-001 -- Command Structure](./ARCH-001-command-structure.md) +- [Node.js process.exit documentation](https://nodejs.org/api/process.html#processexitcode) +``` + +--- + +## Companion Rules File + +When `rules: true`, Archgate looks for a companion file with the same name but `.rules.ts` extension. + +``` +ARCH-002-error-handling.md # rules: true in frontmatter +ARCH-002-error-handling.rules.ts # companion rules file +``` + +The rules file must export a default `RuleSet` created via `defineRules()`: + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "no-console-error": { + description: "Use logError() instead of console.error()", + async check(ctx) { + for (const file of ctx.scopedFiles) { + const matches = await ctx.grep(file, /console\.error\(/); + for (const match of matches) { + ctx.report.violation({ + message: "Use logError() instead of console.error()", + file: match.file, + line: match.line, + fix: "Import logError from src/helpers/log and use it instead", + }); + } + } + }, + }, +}); +``` + +See the [Rule API](/reference/rule-api/) for the complete TypeScript API reference. + +--- + +## Validation + +The YAML frontmatter is validated at parse time using a Zod schema. Invalid frontmatter causes a parse error with a descriptive message. + +### Required fields + +If a required field is missing, the ADR fails to parse: + +``` +Invalid ADR frontmatter in ARCH-001-example.md: + - domain: Required +``` + +### Invalid enum values + +If `domain` is not one of the valid values: + +``` +Invalid ADR frontmatter in ARCH-001-example.md: + - domain: Invalid enum value. Expected 'backend' | 'frontend' | 'data' | 'architecture' | 'general', received 'security' +``` + +### Type mismatches + +If `rules` is a string instead of a boolean: + +``` +Invalid ADR frontmatter in ARCH-001-example.md: + - rules: Expected boolean, received string +``` + +ADRs that fail validation are skipped by `archgate check` and reported as errors. diff --git a/docs/src/content/docs/reference/cli-commands.mdx b/docs/src/content/docs/reference/cli-commands.mdx new file mode 100644 index 00000000..72605fbf --- /dev/null +++ b/docs/src/content/docs/reference/cli-commands.mdx @@ -0,0 +1,355 @@ +--- +title: CLI Commands +description: Complete reference for all Archgate CLI commands. +--- + +## archgate init + +Initialize Archgate governance in the current project. + +```bash +archgate init [--editor <editor>] +``` + +Creates the `.archgate/` directory with an example ADR, companion rules file, and linter configuration. Optionally configures editor integration for AI agent workflows. + +### Options + +| Option | Default | Description | +| ------------------- | -------- | ---------------------------------------------------- | +| `--editor <editor>` | `claude` | Editor integration to configure (`claude`, `cursor`) | + +### Output + +``` +Initialized Archgate governance in /path/to/project + adrs/ - architecture decision records + lint/ - linter-specific rules + .claude/ - Claude Code settings configured +``` + +When `--editor cursor` is used, the output shows `.cursor/` instead of `.claude/`. + +### Generated structure + +``` +.archgate/ + adrs/ + ARCH-001-example.md # Example ADR + ARCH-001-example.rules.ts # Example rules file + lint/ + archgate.config.ts # Archgate configuration +``` + +--- + +## archgate check + +Run all automated ADR compliance checks against the codebase. + +```bash +archgate check [options] +``` + +Loads every ADR with `rules: true` in its frontmatter, executes the companion `.rules.ts` file, and reports violations with file paths and line numbers. + +### Options + +| Option | Description | +| ------------ | --------------------------------------------------------- | +| `--staged` | Only check git-staged files (useful for pre-commit hooks) | +| `--json` | Machine-readable JSON output | +| `--ci` | GitHub Actions annotation format | +| `--adr <id>` | Only check rules from a specific ADR | +| `--verbose` | Show passing rules and timing info | + +### Exit codes + +| Code | Meaning | +| ---- | --------------------------------------------- | +| 0 | All rules pass. No violations found. | +| 1 | One or more violations detected. | +| 2 | Internal error (e.g., malformed ADR or rule). | + +### Examples + +Check the entire project: + +```bash +archgate check +``` + +Check only staged files before committing: + +```bash +archgate check --staged +``` + +Check a single ADR: + +```bash +archgate check --adr ARCH-001 +``` + +Get JSON output for CI integration: + +```bash +archgate check --json +``` + +Get GitHub Actions annotations: + +```bash +archgate check --ci +``` + +### JSON output format + +When `--json` is used, the output is a single JSON object: + +```json +{ + "pass": false, + "total": 4, + "passed": 3, + "failed": 1, + "warnings": 0, + "errors": 1, + "infos": 0, + "ruleErrors": 0, + "results": [ + { + "adrId": "ARCH-001", + "ruleId": "register-function-export", + "violations": [ + { + "message": "Command file must export a register*Command function", + "file": "src/commands/broken.ts", + "severity": "error" + } + ] + } + ], + "durationMs": 42 +} +``` + +--- + +## archgate adr create + +Create a new ADR interactively or via flags. + +```bash +archgate adr create [options] +``` + +When run without `--title` and `--domain`, the command prompts interactively for the domain, title, and optional file patterns. When both `--title` and `--domain` are provided, it runs non-interactively. + +The ADR ID is auto-generated with the domain prefix and the next available sequence number (e.g., `ARCH-002`, `BE-001`). + +### Options + +| Option | Description | +| -------------------- | --------------------------------------------------------------------- | +| `--title <title>` | ADR title (skip interactive prompt) | +| `--domain <domain>` | ADR domain (`backend`, `frontend`, `data`, `architecture`, `general`) | +| `--files <patterns>` | File patterns, comma-separated | +| `--body <markdown>` | Full ADR body markdown (skip template) | +| `--rules` | Set `rules: true` in frontmatter | +| `--json` | Output as JSON | + +### Examples + +Interactive mode: + +```bash +archgate adr create +``` + +Non-interactive mode: + +```bash +archgate adr create \ + --title "API Response Envelope" \ + --domain backend \ + --files "src/api/**/*.ts" \ + --rules +``` + +--- + +## archgate adr list + +List all ADRs in the project. + +```bash +archgate adr list [options] +``` + +### Options + +| Option | Description | +| ------------------- | ---------------- | +| `--json` | Output as JSON | +| `--domain <domain>` | Filter by domain | + +### Examples + +List all ADRs in table format: + +```bash +archgate adr list +``` + +``` +ID Domain Rules Title +──────────────────────────────────────────────────────── +ARCH-001 architecture true Command Structure +ARCH-002 architecture true Error Handling +BE-001 backend true API Response Envelope +``` + +List ADRs as JSON: + +```bash +archgate adr list --json +``` + +Filter by domain: + +```bash +archgate adr list --domain backend +``` + +--- + +## archgate adr show + +Print a specific ADR by ID. + +```bash +archgate adr show <id> +``` + +Prints the full ADR content (frontmatter and body) to stdout. + +### Arguments + +| Argument | Description | +| -------- | ----------------------------------- | +| `<id>` | ADR ID (e.g., `ARCH-001`, `BE-003`) | + +### Example + +```bash +archgate adr show ARCH-001 +``` + +--- + +## archgate adr update + +Update an existing ADR by ID. + +```bash +archgate adr update --id <id> --body <markdown> [options] +``` + +Replaces the ADR body with the provided markdown. Frontmatter fields (`--title`, `--domain`, `--files`, `--rules`) are updated only when explicitly passed; otherwise the existing values are preserved. + +### Options + +| Option | Required | Description | +| -------------------- | -------- | --------------------------------------------------------------------- | +| `--id <id>` | Yes | ADR ID to update (e.g., `ARCH-001`) | +| `--body <markdown>` | Yes | Full replacement ADR body markdown | +| `--title <title>` | No | New ADR title (preserves existing if omitted) | +| `--domain <domain>` | No | New domain (`backend`, `frontend`, `data`, `architecture`, `general`) | +| `--files <patterns>` | No | New file patterns, comma-separated (preserves existing if omitted) | +| `--rules` | No | Set `rules: true` in frontmatter | +| `--json` | No | Output as JSON | + +### Example + +```bash +archgate adr update \ + --id ARCH-001 \ + --title "Updated Command Structure" \ + --body "## Context\n\nUpdated context..." +``` + +--- + +## archgate mcp + +Start the MCP server for AI agent integration. + +```bash +archgate mcp +``` + +Launches an MCP server using stdio transport. The server exposes tools for checking ADR compliance, listing ADRs, and retrieving review context. See the [MCP Tools](/reference/mcp-tools/) reference for the full list of available tools and resources. + +The server starts even when no `.archgate/` directory is found. In that case, tools return guidance directing the agent to initialize governance first. + +### Configuration + +Add to your Claude Code MCP configuration (`.claude/settings.json`): + +```json +{ + "mcpServers": { + "archgate": { + "command": "archgate", + "args": ["mcp"] + } + } +} +``` + +--- + +## archgate upgrade + +Upgrade Archgate to the latest version via npm. + +```bash +archgate upgrade +``` + +Checks the npm registry for the latest published version. If a newer version is available, runs `npm install -g archgate@latest` to upgrade. If already up-to-date, prints a message and exits. + +### Example + +```bash +archgate upgrade +``` + +``` +Checking for latest Archgate release... +Upgrading 0.3.0 -> 0.4.0... +Archgate upgraded to 0.4.0 successfully. +``` + +--- + +## archgate clean + +Remove the CLI cache directory. + +```bash +archgate clean +``` + +Removes `~/.archgate/`, which stores cached data such as update check timestamps. Safe to run at any time -- the directory is recreated automatically when needed. + +### Example + +```bash +archgate clean +``` + +``` +/home/user/.archgate cleaned up +``` diff --git a/docs/src/content/docs/reference/mcp-tools.mdx b/docs/src/content/docs/reference/mcp-tools.mdx new file mode 100644 index 00000000..293bdcfc --- /dev/null +++ b/docs/src/content/docs/reference/mcp-tools.mdx @@ -0,0 +1,189 @@ +--- +title: MCP Tools +description: Reference for all MCP tools and resources exposed by the Archgate server. +--- + +The Archgate MCP server exposes tools and resources that AI coding agents use to read ADRs, validate code against rules, and access review context. Start the server with `archgate mcp`. + +## Tools + +### check + +Run ADR compliance checks against the codebase. + +**Parameters:** + +| Name | Type | Required | Description | +| -------- | ------- | -------- | ------------------------------- | +| `adrId` | string | No | Only check a specific ADR by ID | +| `staged` | boolean | No | Only check git-staged files | + +**Returns** a JSON object with check results: + +```json +{ + "pass": false, + "total": 4, + "passed": 3, + "failed": 1, + "warnings": 0, + "errors": 1, + "infos": 0, + "ruleErrors": 0, + "results": [ + { + "adrId": "ARCH-001", + "ruleId": "register-function-export", + "violations": [ + { + "message": "Command file must export a register*Command function", + "file": "src/commands/broken.ts", + "severity": "error" + } + ] + } + ], + "durationMs": 42 +} +``` + +When no rules are found, returns `{ "pass": true, "total": 0, "results": [] }`. + +Violations are capped at 20 per rule to keep responses concise. + +--- + +### list_adrs + +List all ADRs in the project with their metadata. + +**Parameters:** + +| Name | Type | Required | Description | +| -------- | ------ | -------- | --------------------------------------------------------------------------- | +| `domain` | string | No | Filter by domain (`backend`, `frontend`, `data`, `architecture`, `general`) | + +**Returns** a JSON array of ADR objects: + +```json +[ + { + "id": "ARCH-001", + "title": "Command Structure", + "domain": "architecture", + "rules": true + }, + { + "id": "BE-001", + "title": "API Response Envelope", + "domain": "backend", + "rules": true + } +] +``` + +--- + +### review_context + +Get changed files grouped by domain with applicable ADR briefings. This is the primary tool agents use before writing code -- it provides a condensed view of all relevant ADR decisions and constraints without reading each ADR file individually. + +**Parameters:** + +| Name | Type | Required | Description | +| ----------- | ------- | -------- | ------------------------------------------------------------------------------------- | +| `staged` | boolean | No | When `true`, only include git-staged files. Default: `false` (all changed files). | +| `runChecks` | boolean | No | When `true`, run compliance checks and include results. Default: `false`. | +| `domain` | string | No | Filter to a single domain (`backend`, `frontend`, `data`, `architecture`, `general`). | + +**Returns** a JSON object with domain-grouped briefings. Each briefing includes the **Decision** and **Do's and Don'ts** sections extracted from the applicable ADR, along with the list of changed files in that domain. + +When `runChecks` is `true`, the response also includes the check results for each domain. + +--- + +### claude_code_session_context + +Read the current Claude Code session transcript for the project. Useful for recovering session context that may have been compacted from the conversation. + +**Parameters:** + +| Name | Type | Required | Default | Description | +| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------------------ | +| `maxEntries` | number | No | 200 | Maximum number of relevant entries to return. Returns the most recent entries. | + +**Returns** a JSON object with session metadata and filtered transcript: + +```json +{ + "sessionFile": "abc123.jsonl", + "totalEntries": 450, + "relevantEntries": 180, + "transcript": [ + { + "type": "user", + "role": "user", + "contentPreview": "Add a dark mode toggle..." + }, + { + "type": "assistant", + "role": "assistant", + "contentPreview": "[tool_use: edit_file] | Updated styles..." + } + ] +} +``` + +Only `user` and `assistant` message types are included. Content previews are truncated to 500 characters for user messages and 300 characters per content block for assistant messages. + +--- + +### cursor_session_context + +Read Cursor agent session transcripts for the project. Works the same way as `claude_code_session_context` but reads from Cursor's `agent-transcripts` directory. + +**Parameters:** + +| Name | Type | Required | Default | Description | +| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------------- | +| `maxEntries` | number | No | 200 | Maximum number of relevant entries to return. | +| `sessionId` | string | No | -- | Specific session UUID to read. If omitted, reads the most recent session. | + +**Returns** a JSON object with session metadata and filtered transcript: + +```json +{ + "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "sessionFile": "a1b2c3d4-e5f6-7890-abcd-ef1234567890.jsonl", + "totalEntries": 320, + "relevantEntries": 140, + "transcript": [ + { + "role": "user", + "contentPreview": "Fix the build error..." + }, + { + "role": "assistant", + "contentPreview": "The error is caused by..." + } + ] +} +``` + +If the specified `sessionId` is not found, the response includes a list of available session IDs. + +--- + +## Resources + +### adr://\{id\} + +Read the full content of an ADR by its ID. Returns the complete markdown including YAML frontmatter and body. + +**URI format:** `adr://\{id\}` where `\{id\}` is the ADR identifier (e.g., `ARCH-001`, `BE-003`). + +**Example:** + +Requesting `adr://ARCH-001` returns the full markdown content of the ARCH-001 ADR file with MIME type `text/markdown`. + +If the requested ADR is not found, the resource returns a plain text message: `ADR ARCH-001 not found`. diff --git a/docs/src/content/docs/reference/rule-api.mdx b/docs/src/content/docs/reference/rule-api.mdx new file mode 100644 index 00000000..ec282bdd --- /dev/null +++ b/docs/src/content/docs/reference/rule-api.mdx @@ -0,0 +1,300 @@ +--- +title: Rule API +description: TypeScript API reference for writing Archgate rules. +--- + +Archgate rules are TypeScript files that export automated checks via `defineRules()`. Each rule receives a `RuleContext` with utilities for searching files, reading content, and reporting violations. + +## defineRules + +```typescript +import { defineRules } from "archgate/rules"; + +export default defineRules({ + "my-rule-id": { + description: "Human-readable description of what this rule checks", + severity: "error", // optional, defaults to "error" + async check(ctx) { + // Rule logic here + }, + }, +}); +``` + +The `defineRules` function takes a record of rule configurations keyed by rule ID. Keys become the rule IDs that appear in check output and violation reports. The function returns a `RuleSet` object. + +```typescript +function defineRules(rules: Record<string, RuleConfig>): RuleSet; +``` + +--- + +## RuleConfig + +Each rule in the record must conform to the `RuleConfig` interface. + +```typescript +interface RuleConfig { + description: string; + severity?: Severity; + check: (ctx: RuleContext) => Promise<void>; +} +``` + +| Field | Type | Required | Description | +| ------------- | ------------------------------------- | -------- | ------------------------------------------------------ | +| `description` | `string` | Yes | Human-readable description shown in check output | +| `severity` | `Severity` | No | Default severity for violations. Defaults to `"error"` | +| `check` | `(ctx: RuleContext) => Promise<void>` | Yes | Async function containing the rule logic | + +--- + +## RuleContext + +The `check` function receives a `RuleContext` object with the project state and utility methods. + +```typescript +interface RuleContext { + projectRoot: string; + scopedFiles: string[]; + changedFiles: string[]; + glob(pattern: string): Promise<string[]>; + grep(file: string, pattern: RegExp): Promise<GrepMatch[]>; + grepFiles(pattern: RegExp, fileGlob: string): Promise<GrepMatch[]>; + readFile(path: string): Promise<string>; + readJSON(path: string): Promise<unknown>; + report: RuleReport; +} +``` + +### Properties + +#### projectRoot + +```typescript +projectRoot: string; +``` + +Absolute path to the project root directory (where `.archgate/` lives). + +#### scopedFiles + +```typescript +scopedFiles: string[]; +``` + +Files matching the ADR's `files` glob patterns from its frontmatter. If the ADR has no `files` field, this contains all project files. Use this as the primary file list for your rule checks. + +#### changedFiles + +```typescript +changedFiles: string[]; +``` + +Files that have been modified according to git. When `--staged` is used, this contains only staged files. When running without `--staged`, this contains all changed files (staged and unstaged). Empty when no git changes are detected. + +#### report + +```typescript +report: RuleReport; +``` + +The reporting interface for recording violations, warnings, and informational messages. See [RuleReport](#rulereport) below. + +### Methods + +#### glob + +```typescript +glob(pattern: string): Promise<string[]>; +``` + +Find files matching a glob pattern relative to the project root. Returns an array of absolute file paths. + +```typescript +const testFiles = await ctx.glob("tests/**/*.test.ts"); +``` + +#### grep + +```typescript +grep(file: string, pattern: RegExp): Promise<GrepMatch[]>; +``` + +Search a single file for lines matching a regular expression. Returns an array of `GrepMatch` objects with file path, line number, column, and matched content. + +```typescript +const matches = await ctx.grep(file, /console\.error\(/); +``` + +#### grepFiles + +```typescript +grepFiles(pattern: RegExp, fileGlob: string): Promise<GrepMatch[]>; +``` + +Search multiple files matching a glob pattern for lines matching a regular expression. Combines `glob` and `grep` into a single call. + +```typescript +const matches = await ctx.grepFiles(/TODO:/i, "src/**/*.ts"); +``` + +#### readFile + +```typescript +readFile(path: string): Promise<string>; +``` + +Read the contents of a file as a string. The path is relative to the project root. + +```typescript +const content = await ctx.readFile("src/config.ts"); +``` + +#### readJSON + +```typescript +readJSON(path: string): Promise<unknown>; +``` + +Read and parse a JSON file. The path is relative to the project root. Returns the parsed value as `unknown` -- cast to the expected type in your rule. + +```typescript +const pkg = (await ctx.readJSON("package.json")) as { + dependencies?: Record<string, string>; +}; +``` + +--- + +## RuleReport + +The reporting interface for recording check results. Each method accepts a detail object describing the issue. + +```typescript +interface RuleReport { + violation(detail: ReportDetail): void; + warning(detail: ReportDetail): void; + info(detail: ReportDetail): void; +} +``` + +#### violation + +```typescript +report.violation(detail: ReportDetail): void; +``` + +Report a rule violation. Violations cause the check to fail with exit code 1. Use for hard constraints that must not be merged. + +#### warning + +```typescript +report.warning(detail: ReportDetail): void; +``` + +Report a warning. Warnings appear in check output but do not cause the check to fail. Use for non-blocking guidance. + +#### info + +```typescript +report.info(detail: ReportDetail): void; +``` + +Report an informational message. Does not affect the check exit code. Use for suggestions or notes. + +### ReportDetail + +The detail object passed to `violation`, `warning`, and `info`. + +```typescript +interface ReportDetail { + message: string; + file?: string; + line?: number; + fix?: string; +} +``` + +| Field | Type | Required | Description | +| --------- | -------- | -------- | --------------------------------------- | +| `message` | `string` | Yes | Human-readable description of the issue | +| `file` | `string` | No | File path where the issue was found | +| `line` | `number` | No | Line number in the file | +| `fix` | `string` | No | Suggested fix or remediation action | + +--- + +## GrepMatch + +Returned by `ctx.grep()` and `ctx.grepFiles()`. + +```typescript +interface GrepMatch { + file: string; + line: number; + column: number; + content: string; +} +``` + +| Field | Type | Description | +| --------- | -------- | ------------------------------------ | +| `file` | `string` | Absolute path to the matched file | +| `line` | `number` | Line number of the match (1-based) | +| `column` | `number` | Column number of the match (1-based) | +| `content` | `string` | Full content of the matched line | + +--- + +## Severity + +```typescript +type Severity = "error" | "warning" | "info"; +``` + +| Value | Exit code impact | Description | +| ----------- | ---------------- | ------------------------------- | +| `"error"` | Causes exit 1 | Hard constraint, blocks merges | +| `"warning"` | No impact | Non-blocking guidance | +| `"info"` | No impact | Informational, suggestions only | + +--- + +## ViolationDetail + +The internal representation of a reported issue, used in check output and JSON results. + +```typescript +interface ViolationDetail { + ruleId: string; + adrId: string; + message: string; + file?: string; + line?: number; + fix?: string; + severity: Severity; +} +``` + +| Field | Type | Description | +| ---------- | ---------- | ------------------------------------ | +| `ruleId` | `string` | Rule ID from the `defineRules` key | +| `adrId` | `string` | ADR ID from the frontmatter | +| `message` | `string` | Human-readable description | +| `file` | `string?` | File path where the issue was found | +| `line` | `number?` | Line number in the file | +| `fix` | `string?` | Suggested fix | +| `severity` | `Severity` | Effective severity of this violation | + +--- + +## RuleSet + +The return type of `defineRules`. You do not construct this directly. + +```typescript +type RuleSet = { + rules: Record<string, RuleConfig>; +}; +``` diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 00000000..bcbf8b50 --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/strict" +} diff --git a/package.json b/package.json index f60bdde4..e48b51a2 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,10 @@ "build:check": "bun build src/cli.ts --compile --bytecode --outfile dist/.build-check && rm -f dist/.build-check dist/.build-check.exe", "validate": "bun run lint && bun run typecheck && bun run format:check && bun test && bun run check && bun run build:check", "commit": "cz", - "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0" + "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", + "docs:dev": "cd docs && bunx --bun astro dev", + "docs:build": "cd docs && bunx --bun astro build", + "docs:preview": "cd docs && bunx --bun astro preview" }, "type": "module", "devDependencies": { diff --git a/docs/01-strategic-plan.md b/plans/01-strategic-plan.md similarity index 100% rename from docs/01-strategic-plan.md rename to plans/01-strategic-plan.md diff --git a/docs/02-tactical-plan.md b/plans/02-tactical-plan.md similarity index 100% rename from docs/02-tactical-plan.md rename to plans/02-tactical-plan.md diff --git a/docs/03-technical-plan.md b/plans/03-technical-plan.md similarity index 100% rename from docs/03-technical-plan.md rename to plans/03-technical-plan.md diff --git a/docs/04-distribution-plan.md b/plans/04-distribution-plan.md similarity index 100% rename from docs/04-distribution-plan.md rename to plans/04-distribution-plan.md diff --git a/docs/05-plugin-distribution-plan.md b/plans/05-plugin-distribution-plan.md similarity index 100% rename from docs/05-plugin-distribution-plan.md rename to plans/05-plugin-distribution-plan.md diff --git a/docs/06-cursor-integration-plan.md b/plans/06-cursor-integration-plan.md similarity index 100% rename from docs/06-cursor-integration-plan.md rename to plans/06-cursor-integration-plan.md diff --git a/docs/06-launch-plan.md b/plans/06-launch-plan.md similarity index 100% rename from docs/06-launch-plan.md rename to plans/06-launch-plan.md