From bcbedffece452333d3c4da1e93eb72fe2daa4651 Mon Sep 17 00:00:00 2001 From: LadyBluenotes Date: Thu, 5 Mar 2026 08:44:07 -0800 Subject: [PATCH 1/6] feat: update interview phases with mandatory interactive rules and feedback collection --- .../playbooks/meta/domain-discovery/SKILL.md | 131 ++++++++++++++++-- 1 file changed, 121 insertions(+), 10 deletions(-) diff --git a/packages/playbooks/meta/domain-discovery/SKILL.md b/packages/playbooks/meta/domain-discovery/SKILL.md index b53b3918..f64269d9 100644 --- a/packages/playbooks/meta/domain-discovery/SKILL.md +++ b/packages/playbooks/meta/domain-discovery/SKILL.md @@ -39,6 +39,42 @@ There are five phases. Always run them in order. 4. **Detail interview** — gap-targeted questions, AI-agent failures 5. **Finalize artifacts** +### Hard rules — interview phases are mandatory and interactive + +These rules override any other reasoning. No exceptions. + +1. **Phases 2 and 4 are interactive interviews conducted with the + maintainer.** You must ask the questions specified in each sub-section + and wait for the maintainer's response before continuing. Documentation, + source code, and other automated analysis are NOT substitutes for the + maintainer's answers. +2. **Every question in Phases 2 and 4 must be asked as an open-ended + question and sent as a message to the maintainer.** You must then + STOP and WAIT for their reply. Do not answer your own questions. Do + not infer answers from documentation. Do not skip questions because + you believe you already know the answer. +3. **Do not convert open-ended questions into multiple-choice, + yes/no, or confirmation prompts.** The question templates in each + sub-section are open-ended by design. Present them as open-ended + questions. The maintainer's unprompted answers surface knowledge that + pre-structured options suppress. +4. **Minimum question counts are enforced.** Each sub-section specifies + a question count range (e.g. "2–4 questions"). You must ask at least + the minimum number. Asking zero questions in any sub-section is a + protocol violation. +5. **STOP gates are mandatory.** At the boundaries marked `── STOP ──` + below, you must halt execution and wait for the maintainer's response + or acknowledgment before proceeding. Do not continue past a STOP gate + in the same message. +6. **If the maintainer asks to skip an interview phase**, explain the + value of the phase and what will be lost. Proceed with skipping only + if they confirm a second time. +7. **Rich documentation makes interviews MORE valuable, not less.** + When docs are comprehensive, the interview surfaces what docs miss: + implicit knowledge, AI-specific failure modes, undocumented tradeoffs, + and the maintainer's prioritization of what matters most. Never + rationalize skipping interviews because documentation is thorough. + --- ## Phase 1 — Quick scan (autonomous, ~10 minutes) @@ -66,20 +102,37 @@ Log (but do not group yet): - Which frameworks it supports - Any existing skill files, agent configs, or playbooks - Whether the library is a monorepo and which packages matter +- Peer dependency constraints — read `peerDependencies` and + `peerDependenciesMeta` from each client-facing package.json to + understand version ranges and optional integrations early + +Present your initial impressions to the maintainer as a brief summary +(3–5 bullets). This orients them on what you found and primes them for +the interview. + +**── STOP ── Do not proceed to Phase 2 until the maintainer has +acknowledged your summary or responded.** --- -## Phase 2 — High-level interview +## Phase 2 — High-level interview (interactive — requires maintainer) The maintainer's mental model of developer tasks IS the skill map. Your job in this phase is to extract it — not to propose your own structure. +You must ask the questions below to the maintainer and wait for their +responses. Do not infer answers from documentation or source code. + ### Rules for Phase 2 1. One topic per message for open-ended questions. You may batch 2–3 yes/no or short-confirmation questions together. -2. Take notes silently. Do not summarize back unless asked. -3. If the maintainer gives a short answer, probe deeper before moving on. +2. Ask each question as written (you may adapt phrasing to context, but + keep questions open-ended — never convert to multiple-choice). +3. Wait for the maintainer's response after each question before asking + the next. +4. Take notes silently. Do not summarize back unless asked. +5. If the maintainer gives a short answer, probe deeper before moving on. ### 2a — Developer tasks (2–4 questions) @@ -96,6 +149,13 @@ Follow up to enumerate distinct tasks: > things like 'set up the client', 'implement auth', 'debug sync issues' > — each one a separate moment where they'd want focused guidance." +For monorepo libraries, also ask about cross-package tasks: + +> "Are there tasks that touch multiple packages in your monorepo? For +> example, a getting-started flow that requires imports from both the +> client and server packages? I want to make sure skills that span +> package boundaries are captured correctly." + ### 2b — Developer journeys (1–2 questions) Surface lifecycle/journey skills that cross-cut task areas: @@ -119,6 +179,9 @@ Synthesize what you heard into a proposed skill list and present it: > [enumerate skills with one-line descriptions]. Does this match how > you think about your library? What would you add, remove, or rename?" +**── STOP ── Do not proceed to Phase 3 until the maintainer has +reviewed and confirmed (or corrected) the skill list.** + --- ## Phase 3 — Deep read (autonomous) @@ -131,7 +194,12 @@ gotchas. Read in this order. Each step builds context for the next. -1. **Every narrative guide** — the how-to content, not API reference tables +Before starting, list every file in the docs directory (and subdirectories). +Use this list as a checklist — every narrative file must be read. Do not +sample a subset and extrapolate. + +1. **Every narrative guide** — the how-to content, not API reference tables. + Read every guide file, not a representative sample. 2. **Migration guides** — highest-yield source for failure modes; every breaking change is exactly what agents trained on older versions produce 3. **API reference** — scan for exports, type signatures, option shapes @@ -335,20 +403,35 @@ Present the draft to the maintainer before starting Phase 4: > [N] skills and [M] failure modes. I've flagged [K] specific gaps where > I need your input." +Include the full draft domain_map.yaml in your message so the maintainer +can review it. Also include a checklist of all docs files you read. + +**── STOP ── Do not proceed to Phase 4 until the maintainer has +reviewed the draft and responded. Their feedback on the draft informs +the detail interview questions.** + --- -## Phase 4 — Detail interview (builds on Phase 1–3) +## Phase 4 — Detail interview (interactive — requires maintainer) You have the maintainer's task map and a deep read. The interview now fills gaps, validates your understanding, and surfaces implicit knowledge. +You must ask the questions below to the maintainer and wait for their +responses. Do not infer answers from documentation or source code — +even for gaps you think you can answer from your reading. + ### Rules for Phase 4 1. One topic per message for open-ended questions. You may batch 2–3 yes/no or short-confirmation questions together. -2. Each question must reference something specific from your reading. -3. If the maintainer gives a short answer, probe deeper before moving on. -4. Take notes silently. Do not summarize back unless asked. +2. Ask each question as written (you may adapt phrasing to context, but + keep questions open-ended — never convert to multiple-choice). +3. Each question must reference something specific from your reading. +4. Wait for the maintainer's response after each question before asking + the next. +5. If the maintainer gives a short answer, probe deeper before moving on. +6. Take notes silently. Do not summarize back unless asked. ### 4a — Draft review (2–3 questions) @@ -493,6 +576,9 @@ skills: domain: '[parent domain slug]' description: '[what a developer is doing — matches a specific task/moment]' type: '[core | framework | lifecycle | composition]' + packages: # required for monorepo; omit for single-package libraries + - '[primary package name]' + - '[secondary package name, if skill spans multiple packages]' covers: - '[API/hook/concept 1]' - '[API/hook/concept 2]' @@ -608,6 +694,11 @@ not promotional.] | ------------------------------------- | -------------------------------------------------------------------------- | | Quick scan before interview | Never interview without at least reading README and package structure | | High-level interview before deep read | The maintainer's task map informs what you read deeply | +| **Interview phases are interactive** | Phases 2 and 4 require sending questions to the maintainer and waiting | +| **Docs are not a substitute** | Documentation cannot replace maintainer answers — even comprehensive docs | +| **Open-ended questions stay open** | Never convert interview questions to multiple-choice or yes/no | +| **Minimum question counts enforced** | Each sub-section's minimum count must be met; zero questions = violation | +| **STOP gates are mandatory** | Do not proceed past a STOP gate without maintainer response | | Batch only confirmations | Yes/no questions may batch 2–3; open-ended questions get their own message | | Questions reference findings | No generic questions — cite what you found | | Skills are task-focused | Each skill matches a developer moment, not a conceptual area | @@ -617,6 +708,7 @@ not promotional.] | No marketing prose | Library description is factual, not promotional | | domain_map.yaml is valid YAML | Parseable by any YAML parser | | Draft before detail interview | Present draft for review before Phase 4 | +| **Draft reviewed before Phase 4** | Maintainer must acknowledge or respond to draft before detail interview | | Agent-specific failures probed | Always ask AI-agent-specific questions in Phase 4c | | Compositions discovered from code | Scan peer deps and examples before asking composition questions | | Cross-skill failure modes tagged | Failure modes spanning skills list all relevant slugs | @@ -624,6 +716,7 @@ not promotional.] | Subsystems flagged | Skills with 3+ adapters/backends list them as subsystems | | Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates | | Lifecycle skills considered | Suggest journey skills when docs have the material | +| **All docs files read** | List docs directory contents and read every narrative file — no sampling | --- @@ -633,6 +726,13 @@ This skill is designed to produce consistent results across Claude, GPT-4+, Gemini, and open-source models. To achieve this: - All instructions use imperative sentences, not suggestions +- Interview phases use explicit STOP gates to prevent models from + continuing autonomously past interactive checkpoints +- Hard rules at the top override any model tendency to rationalize + skipping interactive phases when documentation is available +- Open-ended questions are explicitly protected from conversion to + multiple-choice or confirmation prompts, which models default to + when they have enough context to pre-populate answers - Output formats use YAML (universally parsed) and Markdown tables (universally rendered) - Examples use concrete values, not placeholders like "[your value here]" @@ -642,9 +742,20 @@ Gemini, and open-source models. To achieve this: --- -## Meta-skill feedback (alpha default) +## Meta-skill feedback (mandatory — do not skip) + +**This step is required.** Agents routinely skip feedback collection +because it appears at the end of the skill. You must complete this step +before the domain discovery process is considered finished. + +After finalizing artifacts, ask the maintainer for feedback on the domain +discovery process. Do not silently create the feedback template — present +it to the maintainer and ask them to fill in the Domain Discovery section. + +**── STOP ── Ask the maintainer to provide feedback. Wait for their +response before writing the feedback file.** -After finalizing artifacts, create or update a single Markdown feedback draft +Create or update a single Markdown feedback draft for all three meta skills used in scaffolding. Use this exact template and fill only the **Domain Discovery** section now. Leave the other sections in place for later steps to complete. From 54555c42ad909ce20ab1016c356e1a5f3c646922 Mon Sep 17 00:00:00 2001 From: LadyBluenotes Date: Thu, 5 Mar 2026 08:56:47 -0800 Subject: [PATCH 2/6] feat: enhance SKILL.md with clarifications on package ownership and skill generation process --- .../playbooks/meta/domain-discovery/SKILL.md | 9 +-- .../playbooks/meta/generate-skill/SKILL.md | 34 ++++++++-- .../playbooks/meta/tree-generator/SKILL.md | 66 +++++++++++++++++-- 3 files changed, 95 insertions(+), 14 deletions(-) diff --git a/packages/playbooks/meta/domain-discovery/SKILL.md b/packages/playbooks/meta/domain-discovery/SKILL.md index f64269d9..d35e3426 100644 --- a/packages/playbooks/meta/domain-discovery/SKILL.md +++ b/packages/playbooks/meta/domain-discovery/SKILL.md @@ -153,8 +153,9 @@ For monorepo libraries, also ask about cross-package tasks: > "Are there tasks that touch multiple packages in your monorepo? For > example, a getting-started flow that requires imports from both the -> client and server packages? I want to make sure skills that span -> package boundaries are captured correctly." +> client and server packages? Since skills ship inside each package, +> I need to know which package should own cross-cutting skills and +> which other packages they reference." ### 2b — Developer journeys (1–2 questions) @@ -577,8 +578,8 @@ skills: description: '[what a developer is doing — matches a specific task/moment]' type: '[core | framework | lifecycle | composition]' packages: # required for monorepo; omit for single-package libraries - - '[primary package name]' - - '[secondary package name, if skill spans multiple packages]' + - '[package where this skill ships]' + - '[additional package, if skill is relevant to multiple packages]' covers: - '[API/hook/concept 1]' - '[API/hook/concept 2]' diff --git a/packages/playbooks/meta/generate-skill/SKILL.md b/packages/playbooks/meta/generate-skill/SKILL.md index 8a5bf8df..6cec988d 100644 --- a/packages/playbooks/meta/generate-skill/SKILL.md +++ b/packages/playbooks/meta/generate-skill/SKILL.md @@ -47,8 +47,15 @@ You will receive: If the maintainer uses a custom skills root, replace `skills/` in any paths below with their chosen directory. +For monorepo libraries, skills ship inside the package they belong to. +Each package has its own `skills/` directory so that when a developer +installs a package (e.g. `@tanstack/react-router`), the skills are +available locally. Cross-package skills live in whichever package is the +primary entry point for that task, with references to the other packages. + 1. **Skill name** — format `library-group/skill-name` (e.g. `tanstack-query/core`, - `tanstack-router/loaders`, `db/core/live-queries`) + `tanstack-router/loaders`, `db/core/live-queries`). The name determines the + output file path: `skills/[name]/SKILL.md` relative to the package root. 2. **Skill description** — what the skill covers and when an agent should load it 3. **Source documentation** — the docs, guides, API references, and/or source files to distill from @@ -117,6 +124,9 @@ description: > type: core library: [library] library_version: "[version this targets]" +packages: # required for monorepo; omit for single-package libraries + - "[package where this skill ships]" + - "[additional package, if skill is relevant to multiple packages]" sources: - "[Owner/repo]:docs/[path].md" - "[Owner/repo]:src/[path].ts" @@ -314,9 +324,17 @@ Output the complete SKILL.md file content. If reference files are needed, output those as well with their relative paths. If generating multiple skills in a batch (e.g. all skills for a library), -output in this order: +generate and present the first core overview SKILL.md to the maintainer +before writing the rest. + +**── STOP ── Wait for the maintainer to review the first generated skill. +Their feedback on structure, tone, and detail level applies to every +subsequent skill. Catching issues early avoids rewriting the entire batch.** -1. Core overview SKILL.md +After the maintainer confirms (or provides corrections), generate the +remaining skills in this order: + +1. Core overview SKILL.md (already reviewed above) 2. Core sub-skills in domain order 3. Framework overview SKILL.md for each framework 4. Framework sub-skills @@ -347,6 +365,7 @@ updates preserve review effort and reduce diff noise. | Rule | Detail | |------|--------| +| **First skill reviewed before batch** | In batch mode, present the first core skill for maintainer review before generating the rest | | React adapter only (Phase 1) | No Vue, Solid, Svelte, Angular examples unless generating a framework skill for that adapter | | All imports use real package names | `@tanstack/react-query`, not `react-query` | | No placeholder code | No `// ...`, `[your value]`, or `...rest` | @@ -372,9 +391,14 @@ Output is consumed by all major AI coding agents. To ensure consistency: --- -## Meta-skill feedback (alpha default) +## Meta-skill feedback (alpha — temporary) + +During the alpha period, collect feedback from the maintainer on the +skill generation process. Ask if they'd like to share what worked well, +what was confusing, or suggestions for improvement. If they decline or +want to move on, that's fine. -After generating the first iteration of skills, complete a single Markdown +Complete a single Markdown feedback draft for all three meta skills used in scaffolding. If a draft exists from previous steps, keep it and fill the **Generate Skill** section. If no draft exists, create it using this exact template. diff --git a/packages/playbooks/meta/tree-generator/SKILL.md b/packages/playbooks/meta/tree-generator/SKILL.md index d7ed5a6d..f48dcdcb 100644 --- a/packages/playbooks/meta/tree-generator/SKILL.md +++ b/packages/playbooks/meta/tree-generator/SKILL.md @@ -63,8 +63,13 @@ You need one of: discovery first) If starting from raw docs without a domain map, run a compressed -discovery. This produces lower-fidelity output than the full -skill-domain-discovery skill — prefer running that when time permits. +discovery. **Warning:** This produces significantly lower-fidelity +output than the full skill-domain-discovery skill. The maintainer +interview in domain discovery surfaces implicit knowledge, failure +modes, and prioritization that cannot be inferred from docs alone. +Always prefer running the full discovery when possible. Only use +compressed discovery when the maintainer has explicitly confirmed +they want to skip domain discovery. 1. Build a concept inventory (every export, config key, constraint, warning) 2. Group into 4–7 capability domains using work-oriented names @@ -107,6 +112,9 @@ skills: domain: '[domain slug]' path: 'skills/[path]/SKILL.md' description: '[1–2 sentence agent-facing routing key]' + packages: # required for monorepo; omit for single-package libraries + - '[package where this skill ships]' + - '[additional package, if skill is relevant to multiple packages]' requires: - '[other skill slugs]' # omit if none sources: @@ -122,7 +130,18 @@ skills: From the domain map, each entry in the `skills` list becomes a SKILL.md file. The `type` field on each skill (`core`, `framework`, `lifecycle`, -`composition`) determines where it goes. Determine the file tree: +`composition`) determines where it goes. Determine the file tree. + +Present the planned file tree to the maintainer before writing any files. +Include the full `skill_tree.yaml` content and explain any structural +decisions (flat vs nested, which skills get reference files, how +cross-package skills are handled). + +**── STOP ── Wait for the maintainer to review and approve the file tree +before proceeding to Step 2. A bad tree means rewriting every generated +file.** + +Determine the file tree: **Core vs framework decision:** @@ -175,6 +194,31 @@ Both are valid. The domain map's `type` field and structure will signal which fits. When in doubt, prefer flat — it's simpler and each skill is independently discoverable. +**Monorepo placement:** Skills ship inside each package so they are +available when developers install the package. Each package has its +own `skills/` directory. Cross-package skills live in whichever +package is the primary entry point for that task. For example: + +``` +packages/ +├── react-router/ +│ └── skills/ +│ ├── router-core/ +│ │ ├── SKILL.md +│ │ └── navigation/ +│ │ └── SKILL.md +│ └── react-router/ +│ └── SKILL.md +├── start/ +│ └── skills/ +│ ├── start-core/ +│ │ └── SKILL.md +│ └── start-server-functions/ +│ └── SKILL.md +``` + +The examples below show the `skills/` tree within a single package. + **Nested structure:** ``` @@ -637,6 +681,11 @@ The key differences from the standard body: ### Step 8 — Validate the complete tree Run every check before outputting. Fix any failures before proceeding. +Present the validation results to the maintainer — list any checks that +required fixes and what was changed. + +**── STOP ── Wait for the maintainer to acknowledge the validation +results before proceeding to the feedback step.** | Check | Rule | |-------|------| @@ -762,6 +811,8 @@ current_skills: | Check | Rule | | ------------------------------------------- | ----------------------------------------------------------------------------------- | +| **File tree reviewed by maintainer** | Present skill_tree.yaml for approval before writing SKILL.md files | +| **Validation results presented** | Show check results to maintainer before finalizing | | Under 500 lines per SKILL.md | Move excess to references/; also create references for content depth | | Real imports in every code block | Exact package, correct adapter | | No external concept explanations | No "TypeScript is...", no "React hooks are..." — library-specific concepts are fine | @@ -820,9 +871,14 @@ When updating: --- -## Meta-skill feedback (alpha default) +## Meta-skill feedback (alpha — temporary) + +During the alpha period, collect feedback from the maintainer on the +tree generation process. Ask if they'd like to share what worked well, +what was confusing, or suggestions for improvement. If they decline or +want to move on, that's fine — proceed to the next step. -After producing the skill tree artifact, update a single Markdown feedback +Update the single Markdown feedback draft for all three meta skills used in scaffolding. If a draft exists from Domain Discovery, keep it and fill only the **Tree Generator** section. If no draft exists, create it using this exact template. From d7659ca6f0a64f32f937b4975f8a4de8e92102b1 Mon Sep 17 00:00:00 2001 From: LadyBluenotes Date: Thu, 5 Mar 2026 09:00:55 -0800 Subject: [PATCH 3/6] changset --- .changeset/whole-rocks-wait.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .changeset/whole-rocks-wait.md diff --git a/.changeset/whole-rocks-wait.md b/.changeset/whole-rocks-wait.md new file mode 100644 index 00000000..27fb6f0d --- /dev/null +++ b/.changeset/whole-rocks-wait.md @@ -0,0 +1,32 @@ +--- +'@tanstack/playbooks': patch +--- + +3 files changed in packages/playbooks/meta/ + +domain-discovery/SKILL.md (681 → ~792 lines) +- Added "Hard rules" section: 7 mandatory rules enforcing interactive interviews, prohibiting docs-as-substitute, question collapsing, and interview skipping +- Added 3 STOP gates between phases (1→2, 3→4, and after Phase 2d skill list confirmation) +- Strengthened Phase 2 & 4 headers with explicit interactivity requirements and "wait for response" instructions +- Added Phase 3 thoroughness: file checklist before reading, read-all enforcement, peer dependency analysis in Phase 1b +- Added 7 new constraint table rows for interview interactivity +- Updated cross-model compatibility notes with STOP gate and question protection rationale +- Added cross-package monorepo question in Phase 2a +- Added packages field to domain_map.yaml schema (package-relative ownership model) +- Softened feedback section to alpha-temporary + +- tree-generator/SKILL.md (859 → ~898 lines) +- Strengthened compressed discovery warning (requires maintainer confirmation to skip) +- Added packages field to skill_tree.yaml schema +- Added monorepo placement section with concrete directory tree example showing skills inside each package +- Added STOP gate after Step 1 (file tree review before writing) +- Added STOP gate after Step 8 (validation results review) +- Added 2 new constraint rows (file tree reviewed, validation presented) +- Softened feedback section to alpha-temporary + +- generate-skill/SKILL.md (419 → ~441 lines) +- Added packages field to frontmatter template +- Added monorepo path guidance: skills ship inside each package, not repo root +- Added STOP gate in Step 6: first skill reviewed before generating batch +- Added first-skill-reviewed constraint row +- Softened feedback section to alpha-temporary From 04208d7e7761404a25bf4507ba9cc60d9a2e057e Mon Sep 17 00:00:00 2001 From: LadyBluenotes Date: Thu, 5 Mar 2026 08:44:07 -0800 Subject: [PATCH 4/6] feat: update interview phases with mandatory interactive rules and feedback collection --- .changeset/config.json | 34 +- .prettierignore | 24 +- CONTRIBUTING.md | 110 +- LICENSE | 42 +- README.md | 176 +- docs/intent/functions/checkStaleness.md | 52 +- docs/intent/functions/containsSecrets.md | 44 +- docs/intent/functions/findSkillFiles.md | 48 +- docs/intent/functions/hasGhCli.md | 32 +- docs/intent/functions/metaToMarkdown.md | 44 +- docs/intent/functions/parseFrontmatter.md | 48 +- docs/intent/functions/resolveFrequency.md | 44 +- docs/intent/functions/runSetup.md | 66 +- docs/intent/functions/scanForIntents.md | 44 +- docs/intent/functions/submitFeedback.md | 78 +- docs/intent/functions/submitMetaFeedback.md | 64 +- docs/intent/functions/toMarkdown.md | 44 +- docs/intent/functions/validateMetaPayload.md | 68 +- docs/intent/functions/validatePayload.md | 68 +- docs/intent/index.md | 80 +- docs/intent/interfaces/FeedbackPayload.md | 216 +- docs/intent/interfaces/IntentConfig.md | 96 +- docs/intent/interfaces/IntentPackage.md | 96 +- docs/intent/interfaces/IntentProjectConfig.md | 48 +- docs/intent/interfaces/MetaFeedbackPayload.md | 216 +- docs/intent/interfaces/ScanResult.md | 76 +- docs/intent/interfaces/SkillEntry.md | 116 +- docs/intent/interfaces/SkillStaleness.md | 76 +- docs/intent/interfaces/StalenessReport.md | 116 +- docs/intent/type-aliases/AgentName.md | 24 +- docs/intent/type-aliases/MetaSkillName.md | 32 +- knip.json | 26 +- package.json | 138 +- packages/intent/CHANGELOG.md | 14 +- packages/intent/README.md | 176 +- .../intent/meta/domain-discovery/SKILL.md | 1678 +-- .../intent/meta/feedback-collection/SKILL.md | 376 +- packages/intent/meta/generate-skill/SKILL.md | 856 +- .../meta/skill-staleness-check/SKILL.md | 564 +- .../meta/templates/workflows/check-skills.yml | 286 +- .../templates/workflows/notify-playbooks.yml | 104 +- .../templates/workflows/validate-skills.yml | 104 +- packages/intent/meta/tree-generator/SKILL.md | 1784 +-- packages/intent/package.json | 80 +- packages/intent/src/cli.ts | 1100 +- packages/intent/src/display.ts | 196 +- packages/intent/src/feedback.ts | 748 +- packages/intent/src/index.ts | 56 +- packages/intent/src/intent-library.ts | 294 +- packages/intent/src/library-scanner.ts | 318 +- packages/intent/src/scanner.ts | 570 +- packages/intent/src/setup.ts | 450 +- packages/intent/src/staleness.ts | 316 +- packages/intent/src/types.ts | 210 +- packages/intent/src/utils.ts | 82 +- packages/intent/tests/cli.test.ts | 188 +- packages/intent/tests/feedback.test.ts | 550 +- packages/intent/tests/library-scanner.test.ts | 538 +- packages/intent/tests/meta-feedback.test.ts | 398 +- packages/intent/tests/scanner.test.ts | 476 +- packages/intent/tests/setup.test.ts | 180 +- packages/intent/tests/skills.test.ts | 260 +- packages/intent/tests/staleness.test.ts | 572 +- packages/intent/tsconfig.json | 18 +- packages/intent/vitest.config.ts | 16 +- pnpm-lock.yaml | 10762 ++++++++-------- scripts/generate-docs.ts | 40 +- scripts/validate-skills.ts | 406 +- tsconfig.json | 58 +- vitest.workspace.js | 14 +- 70 files changed, 13717 insertions(+), 13607 deletions(-) diff --git a/.changeset/config.json b/.changeset/config.json index bd439093..9ea24c24 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,17 +1,17 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json", - "changelog": [ - "@svitejs/changesets-changelog-github-compact", - { "repo": "TanStack/intent" } - ], - "commit": false, - "access": "public", - "baseBranch": "main", - "updateInternalDependencies": "patch", - "fixed": [], - "linked": [], - "ignore": [], - "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { - "onlyUpdatePeerDependentsWhenOutOfRange": true - } -} +{ + "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json", + "changelog": [ + "@svitejs/changesets-changelog-github-compact", + { "repo": "TanStack/intent" } + ], + "commit": false, + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "fixed": [], + "linked": [], + "ignore": [], + "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { + "onlyUpdatePeerDependentsWhenOutOfRange": true + } +} diff --git a/.prettierignore b/.prettierignore index f215b787..5b3091d4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,12 +1,12 @@ -.github -**/.nx/ -**/.nx/cache -**/.svelte-kit -**/build -**/coverage -**/dist -**/docs -**/old-examples -pnpm-lock.yaml - -.angular +.github +**/.nx/ +**/.nx/cache +**/.svelte-kit +**/build +**/coverage +**/dist +**/docs +**/old-examples +pnpm-lock.yaml + +.angular diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 316e7a2b..2ebbdb45 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,55 +1,55 @@ ---- -title: Contributing -id: contributing ---- - -# Contributing - -## Questions - -If you have questions about implementation details, help or support, then please use our dedicated community forum at [Github Discussions](https://github.com/tanstack/intent/discussions) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum. - -## Reporting Issues - -If you have found what you think is a bug, please [file an issue](https://github.com/tanstack/intent/issues/new). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [Github Discussions](https://github.com/tanstack/intent/discussions) - -## Suggesting new features - -If you are here to suggest a feature, first create an issue if it does not already exist. From there, we will discuss use-cases for the feature and then finally discuss how it could be implemented. - -## Development - -Before proceeding with development, ensure you match one of the following criteria: - -- Fixing a small bug -- Fixing a larger issue that has been previously discussed and agreed-upon by maintainers -- Adding a new feature that has been previously discussed and agreed-upon by maintainers - -## Development Workflow - -- Fork this repository, we prefer the `feat-*` branch name style -- Ensure you have `pnpm` installed -- Install projects dependencies and linkages by running `pnpm install` -- Auto-build and auto-test files as you edit by running `pnpm dev` -- Implement your changes and tests -- To run examples, follow their individual directions. Usually this includes: - - cd into the example directory - - Do NOT install dependencies again or do any linking. Nx already handles this for you. Only run install from the project root. - - Starting the dev server with `pnpm dev` or `pnpm start` (from the example directory) -- To test in your own projects: - - Build/watch for changes with `pnpm build`/`pnpm dev` -- Document your changes in the appropriate documentation website markdown pages -- Run `pnpm test` to ensure all tests pass before committing -- Create a changeset (changelog entry) for your changes by running `pnpm changeset` -- Commit your work and open a pull request -- Submit PR for review - -## Adding a new example - -- Clone an existing example into the appropriate `examples` directory -- Name it the example name in kebab-case -- Update the new example's package.json to match the new example name and any other details -- Check dependencies for unused packages -- Install any additional packages to the example that you may need -- Update the docs/config.json file to include the new example in the navigation sidebar -- Commit the example eg. `docs: Add example-name` +--- +title: Contributing +id: contributing +--- + +# Contributing + +## Questions + +If you have questions about implementation details, help or support, then please use our dedicated community forum at [Github Discussions](https://github.com/tanstack/intent/discussions) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum. + +## Reporting Issues + +If you have found what you think is a bug, please [file an issue](https://github.com/tanstack/intent/issues/new). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [Github Discussions](https://github.com/tanstack/intent/discussions) + +## Suggesting new features + +If you are here to suggest a feature, first create an issue if it does not already exist. From there, we will discuss use-cases for the feature and then finally discuss how it could be implemented. + +## Development + +Before proceeding with development, ensure you match one of the following criteria: + +- Fixing a small bug +- Fixing a larger issue that has been previously discussed and agreed-upon by maintainers +- Adding a new feature that has been previously discussed and agreed-upon by maintainers + +## Development Workflow + +- Fork this repository, we prefer the `feat-*` branch name style +- Ensure you have `pnpm` installed +- Install projects dependencies and linkages by running `pnpm install` +- Auto-build and auto-test files as you edit by running `pnpm dev` +- Implement your changes and tests +- To run examples, follow their individual directions. Usually this includes: + - cd into the example directory + - Do NOT install dependencies again or do any linking. Nx already handles this for you. Only run install from the project root. + - Starting the dev server with `pnpm dev` or `pnpm start` (from the example directory) +- To test in your own projects: + - Build/watch for changes with `pnpm build`/`pnpm dev` +- Document your changes in the appropriate documentation website markdown pages +- Run `pnpm test` to ensure all tests pass before committing +- Create a changeset (changelog entry) for your changes by running `pnpm changeset` +- Commit your work and open a pull request +- Submit PR for review + +## Adding a new example + +- Clone an existing example into the appropriate `examples` directory +- Name it the example name in kebab-case +- Update the new example's package.json to match the new example name and any other details +- Check dependencies for unused packages +- Install any additional packages to the example that you may need +- Update the docs/config.json file to include the new example in the navigation sidebar +- Commit the example eg. `docs: Add example-name` diff --git a/LICENSE b/LICENSE index f6948992..2e8dc24f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2025-present Tanner Linsley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2025-present Tanner Linsley + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 449db8af..70d1ba49 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,88 @@ -# @tanstack/intent - -Ship compositional knowledge for AI coding agents alongside your npm packages. - -## The problem - -Your docs are good. Your types are solid. Your agent still gets it wrong. - -Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions without flagging which applies. Once a breaking change ships, models contain _both_ versions forever with no way to disambiguate. - -The ecosystem already moves toward agent-readable knowledge — Cursor rules, CLAUDE.md files, skills directories. But delivery is stuck in copy-paste: hunt for a community-maintained rules file, paste it into your config, repeat for every tool. No versioning, no update path, no staleness signal. - -## Skills: the fourth artifact - -You ship code, docs, and types. Skills are the fourth artifact — knowledge encoded for the thing writing most of your code. - -Skills are npm packages of knowledge — encoding how tools compose, which patterns fit which goals, and what to avoid. When a library ships skills using `@tanstack/intent`, that knowledge travels with the tool via `npm update` — not the model's training cutoff. Versioned knowledge the maintainer owns, updated when the package updates. - -Each skill declares its source docs. When those docs change, the CLI flags the skill for review. One source of truth, one derived artifact that stays in sync. - -## Quick Start - -### For library consumers - -Set up skill-to-task mappings in your project's agent config files (CLAUDE.md, .cursorrules, etc.): - -```bash -npx @tanstack/intent install -``` - -No per-library setup. No hunting for rules files. Install the package, run `intent install`, and the agent understands the tool. Update the package, and skills update too. - -List available skills from installed packages: - -```bash -npx @tanstack/intent list -``` - -### For library maintainers - -Generate skills for your library by telling your AI coding agent to run: - -```bash -npx @tanstack/intent scaffold -``` - -This prints a prompt that walks the agent through domain discovery, skill tree generation, and skill creation — one step at a time with your review at each stage. - -Validate your skill files: - -```bash -npx @tanstack/intent validate -``` - -Check for skills that have fallen behind their sources: - -```bash -npx @tanstack/intent stale -``` - -Copy CI workflow templates into your repo so validation and staleness checks run on every push: - -```bash -npx @tanstack/intent setup -``` - -## Keeping skills current - -The real risk with any derived artifact is staleness. `intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships. - -The feedback loop runs both directions. `intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`. - -## CLI Commands - -| Command | Description | -| ----------------------- | --------------------------------------------------- | -| `intent install` | Set up skill-to-task mappings in agent config files | -| `intent list [--json]` | Discover intent-enabled packages | -| `intent meta` | List meta-skills for library maintainers | -| `intent scaffold` | Print the guided skill generation prompt | -| `intent validate [dir]` | Validate SKILL.md files | -| `intent setup` | Copy CI templates, generate shim, create labels | -| `intent stale [--json]` | Check skills for version drift | -| `intent feedback` | Submit skill feedback | - -## License - -[MIT](./LICENSE) +# @tanstack/intent + +Ship compositional knowledge for AI coding agents alongside your npm packages. + +## The problem + +Your docs are good. Your types are solid. Your agent still gets it wrong. + +Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions without flagging which applies. Once a breaking change ships, models contain _both_ versions forever with no way to disambiguate. + +The ecosystem already moves toward agent-readable knowledge — Cursor rules, CLAUDE.md files, skills directories. But delivery is stuck in copy-paste: hunt for a community-maintained rules file, paste it into your config, repeat for every tool. No versioning, no update path, no staleness signal. + +## Skills: the fourth artifact + +You ship code, docs, and types. Skills are the fourth artifact — knowledge encoded for the thing writing most of your code. + +Skills are npm packages of knowledge — encoding how tools compose, which patterns fit which goals, and what to avoid. When a library ships skills using `@tanstack/intent`, that knowledge travels with the tool via `npm update` — not the model's training cutoff. Versioned knowledge the maintainer owns, updated when the package updates. + +Each skill declares its source docs. When those docs change, the CLI flags the skill for review. One source of truth, one derived artifact that stays in sync. + +## Quick Start + +### For library consumers + +Set up skill-to-task mappings in your project's agent config files (CLAUDE.md, .cursorrules, etc.): + +```bash +npx @tanstack/intent install +``` + +No per-library setup. No hunting for rules files. Install the package, run `intent install`, and the agent understands the tool. Update the package, and skills update too. + +List available skills from installed packages: + +```bash +npx @tanstack/intent list +``` + +### For library maintainers + +Generate skills for your library by telling your AI coding agent to run: + +```bash +npx @tanstack/intent scaffold +``` + +This prints a prompt that walks the agent through domain discovery, skill tree generation, and skill creation — one step at a time with your review at each stage. + +Validate your skill files: + +```bash +npx @tanstack/intent validate +``` + +Check for skills that have fallen behind their sources: + +```bash +npx @tanstack/intent stale +``` + +Copy CI workflow templates into your repo so validation and staleness checks run on every push: + +```bash +npx @tanstack/intent setup +``` + +## Keeping skills current + +The real risk with any derived artifact is staleness. `intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships. + +The feedback loop runs both directions. `intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`. + +## CLI Commands + +| Command | Description | +| ----------------------- | --------------------------------------------------- | +| `intent install` | Set up skill-to-task mappings in agent config files | +| `intent list [--json]` | Discover intent-enabled packages | +| `intent meta` | List meta-skills for library maintainers | +| `intent scaffold` | Print the guided skill generation prompt | +| `intent validate [dir]` | Validate SKILL.md files | +| `intent setup` | Copy CI templates, generate shim, create labels | +| `intent stale [--json]` | Check skills for version drift | +| `intent feedback` | Submit skill feedback | + +## License + +[MIT](./LICENSE) diff --git a/docs/intent/functions/checkStaleness.md b/docs/intent/functions/checkStaleness.md index ac01981a..08ece52d 100644 --- a/docs/intent/functions/checkStaleness.md +++ b/docs/intent/functions/checkStaleness.md @@ -1,26 +1,26 @@ ---- -id: checkStaleness -title: checkStaleness ---- - -# Function: checkStaleness() - -```ts -function checkStaleness(packageDir, packageName?): Promise; -``` - -Defined in: [staleness.ts:75](https://github.com/TanStack/intent/blob/main/packages/intent/src/staleness.ts#L75) - -## Parameters - -### packageDir - -`string` - -### packageName? - -`string` - -## Returns - -`Promise`\<[`StalenessReport`](../interfaces/StalenessReport.md)\> +--- +id: checkStaleness +title: checkStaleness +--- + +# Function: checkStaleness() + +```ts +function checkStaleness(packageDir, packageName?): Promise; +``` + +Defined in: [staleness.ts:75](https://github.com/TanStack/intent/blob/main/packages/intent/src/staleness.ts#L75) + +## Parameters + +### packageDir + +`string` + +### packageName? + +`string` + +## Returns + +`Promise`\<[`StalenessReport`](../interfaces/StalenessReport.md)\> diff --git a/docs/intent/functions/containsSecrets.md b/docs/intent/functions/containsSecrets.md index 93acabe4..a19eea4b 100644 --- a/docs/intent/functions/containsSecrets.md +++ b/docs/intent/functions/containsSecrets.md @@ -1,22 +1,22 @@ ---- -id: containsSecrets -title: containsSecrets ---- - -# Function: containsSecrets() - -```ts -function containsSecrets(text): boolean; -``` - -Defined in: [feedback.ts:26](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L26) - -## Parameters - -### text - -`string` - -## Returns - -`boolean` +--- +id: containsSecrets +title: containsSecrets +--- + +# Function: containsSecrets() + +```ts +function containsSecrets(text): boolean; +``` + +Defined in: [feedback.ts:26](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L26) + +## Parameters + +### text + +`string` + +## Returns + +`boolean` diff --git a/docs/intent/functions/findSkillFiles.md b/docs/intent/functions/findSkillFiles.md index d06d76b4..28f86538 100644 --- a/docs/intent/functions/findSkillFiles.md +++ b/docs/intent/functions/findSkillFiles.md @@ -1,24 +1,24 @@ ---- -id: findSkillFiles -title: findSkillFiles ---- - -# Function: findSkillFiles() - -```ts -function findSkillFiles(dir): string[]; -``` - -Defined in: [utils.ts:8](https://github.com/TanStack/intent/blob/main/packages/intent/src/utils.ts#L8) - -Recursively find all SKILL.md files under a directory. - -## Parameters - -### dir - -`string` - -## Returns - -`string`[] +--- +id: findSkillFiles +title: findSkillFiles +--- + +# Function: findSkillFiles() + +```ts +function findSkillFiles(dir): string[]; +``` + +Defined in: [utils.ts:8](https://github.com/TanStack/intent/blob/main/packages/intent/src/utils.ts#L8) + +Recursively find all SKILL.md files under a directory. + +## Parameters + +### dir + +`string` + +## Returns + +`string`[] diff --git a/docs/intent/functions/hasGhCli.md b/docs/intent/functions/hasGhCli.md index 6265d151..d9bb14f2 100644 --- a/docs/intent/functions/hasGhCli.md +++ b/docs/intent/functions/hasGhCli.md @@ -1,16 +1,16 @@ ---- -id: hasGhCli -title: hasGhCli ---- - -# Function: hasGhCli() - -```ts -function hasGhCli(): boolean; -``` - -Defined in: [feedback.ts:34](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L34) - -## Returns - -`boolean` +--- +id: hasGhCli +title: hasGhCli +--- + +# Function: hasGhCli() + +```ts +function hasGhCli(): boolean; +``` + +Defined in: [feedback.ts:34](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L34) + +## Returns + +`boolean` diff --git a/docs/intent/functions/metaToMarkdown.md b/docs/intent/functions/metaToMarkdown.md index a0185850..336aaf88 100644 --- a/docs/intent/functions/metaToMarkdown.md +++ b/docs/intent/functions/metaToMarkdown.md @@ -1,22 +1,22 @@ ---- -id: metaToMarkdown -title: metaToMarkdown ---- - -# Function: metaToMarkdown() - -```ts -function metaToMarkdown(payload): string; -``` - -Defined in: [feedback.ts:222](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L222) - -## Parameters - -### payload - -[`MetaFeedbackPayload`](../interfaces/MetaFeedbackPayload.md) - -## Returns - -`string` +--- +id: metaToMarkdown +title: metaToMarkdown +--- + +# Function: metaToMarkdown() + +```ts +function metaToMarkdown(payload): string; +``` + +Defined in: [feedback.ts:222](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L222) + +## Parameters + +### payload + +[`MetaFeedbackPayload`](../interfaces/MetaFeedbackPayload.md) + +## Returns + +`string` diff --git a/docs/intent/functions/parseFrontmatter.md b/docs/intent/functions/parseFrontmatter.md index 45dd5aaf..b40ba6dc 100644 --- a/docs/intent/functions/parseFrontmatter.md +++ b/docs/intent/functions/parseFrontmatter.md @@ -1,24 +1,24 @@ ---- -id: parseFrontmatter -title: parseFrontmatter ---- - -# Function: parseFrontmatter() - -```ts -function parseFrontmatter(filePath): Record; -``` - -Defined in: [utils.ts:25](https://github.com/TanStack/intent/blob/main/packages/intent/src/utils.ts#L25) - -Parse YAML frontmatter from a file. Returns null if no frontmatter or on error. - -## Parameters - -### filePath - -`string` - -## Returns - -`Record`\<`string`, `unknown`\> +--- +id: parseFrontmatter +title: parseFrontmatter +--- + +# Function: parseFrontmatter() + +```ts +function parseFrontmatter(filePath): Record; +``` + +Defined in: [utils.ts:25](https://github.com/TanStack/intent/blob/main/packages/intent/src/utils.ts#L25) + +Parse YAML frontmatter from a file. Returns null if no frontmatter or on error. + +## Parameters + +### filePath + +`string` + +## Returns + +`Record`\<`string`, `unknown`\> diff --git a/docs/intent/functions/resolveFrequency.md b/docs/intent/functions/resolveFrequency.md index 2f7f9f5a..567e4e0a 100644 --- a/docs/intent/functions/resolveFrequency.md +++ b/docs/intent/functions/resolveFrequency.md @@ -1,22 +1,22 @@ ---- -id: resolveFrequency -title: resolveFrequency ---- - -# Function: resolveFrequency() - -```ts -function resolveFrequency(root): string; -``` - -Defined in: [feedback.ts:54](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L54) - -## Parameters - -### root - -`string` - -## Returns - -`string` +--- +id: resolveFrequency +title: resolveFrequency +--- + +# Function: resolveFrequency() + +```ts +function resolveFrequency(root): string; +``` + +Defined in: [feedback.ts:54](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L54) + +## Parameters + +### root + +`string` + +## Returns + +`string` diff --git a/docs/intent/functions/runSetup.md b/docs/intent/functions/runSetup.md index bbfe125b..aa86aa99 100644 --- a/docs/intent/functions/runSetup.md +++ b/docs/intent/functions/runSetup.md @@ -1,33 +1,33 @@ ---- -id: runSetup -title: runSetup ---- - -# Function: runSetup() - -```ts -function runSetup( - root, - metaDir, - args): SetupResult; -``` - -Defined in: [setup.ts:164](https://github.com/TanStack/intent/blob/main/packages/intent/src/setup.ts#L164) - -## Parameters - -### root - -`string` - -### metaDir - -`string` - -### args - -`string`[] - -## Returns - -`SetupResult` +--- +id: runSetup +title: runSetup +--- + +# Function: runSetup() + +```ts +function runSetup( + root, + metaDir, + args): SetupResult; +``` + +Defined in: [setup.ts:164](https://github.com/TanStack/intent/blob/main/packages/intent/src/setup.ts#L164) + +## Parameters + +### root + +`string` + +### metaDir + +`string` + +### args + +`string`[] + +## Returns + +`SetupResult` diff --git a/docs/intent/functions/scanForIntents.md b/docs/intent/functions/scanForIntents.md index a337ce54..617a1f40 100644 --- a/docs/intent/functions/scanForIntents.md +++ b/docs/intent/functions/scanForIntents.md @@ -1,22 +1,22 @@ ---- -id: scanForIntents -title: scanForIntents ---- - -# Function: scanForIntents() - -```ts -function scanForIntents(root?): Promise; -``` - -Defined in: [scanner.ts:190](https://github.com/TanStack/intent/blob/main/packages/intent/src/scanner.ts#L190) - -## Parameters - -### root? - -`string` - -## Returns - -`Promise`\<[`ScanResult`](../interfaces/ScanResult.md)\> +--- +id: scanForIntents +title: scanForIntents +--- + +# Function: scanForIntents() + +```ts +function scanForIntents(root?): Promise; +``` + +Defined in: [scanner.ts:190](https://github.com/TanStack/intent/blob/main/packages/intent/src/scanner.ts#L190) + +## Parameters + +### root? + +`string` + +## Returns + +`Promise`\<[`ScanResult`](../interfaces/ScanResult.md)\> diff --git a/docs/intent/functions/submitFeedback.md b/docs/intent/functions/submitFeedback.md index c023ce16..45aeabf1 100644 --- a/docs/intent/functions/submitFeedback.md +++ b/docs/intent/functions/submitFeedback.md @@ -1,39 +1,39 @@ ---- -id: submitFeedback -title: submitFeedback ---- - -# Function: submitFeedback() - -```ts -function submitFeedback( - payload, - repo, - opts): SubmitResult; -``` - -Defined in: [feedback.ts:294](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L294) - -## Parameters - -### payload - -[`FeedbackPayload`](../interfaces/FeedbackPayload.md) - -### repo - -`string` - -### opts - -#### ghAvailable - -`boolean` - -#### outputPath? - -`string` - -## Returns - -`SubmitResult` +--- +id: submitFeedback +title: submitFeedback +--- + +# Function: submitFeedback() + +```ts +function submitFeedback( + payload, + repo, + opts): SubmitResult; +``` + +Defined in: [feedback.ts:294](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L294) + +## Parameters + +### payload + +[`FeedbackPayload`](../interfaces/FeedbackPayload.md) + +### repo + +`string` + +### opts + +#### ghAvailable + +`boolean` + +#### outputPath? + +`string` + +## Returns + +`SubmitResult` diff --git a/docs/intent/functions/submitMetaFeedback.md b/docs/intent/functions/submitMetaFeedback.md index 4a261fa5..a5687994 100644 --- a/docs/intent/functions/submitMetaFeedback.md +++ b/docs/intent/functions/submitMetaFeedback.md @@ -1,32 +1,32 @@ ---- -id: submitMetaFeedback -title: submitMetaFeedback ---- - -# Function: submitMetaFeedback() - -```ts -function submitMetaFeedback(payload, opts): SubmitResult; -``` - -Defined in: [feedback.ts:332](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L332) - -## Parameters - -### payload - -[`MetaFeedbackPayload`](../interfaces/MetaFeedbackPayload.md) - -### opts - -#### ghAvailable - -`boolean` - -#### outputPath? - -`string` - -## Returns - -`SubmitResult` +--- +id: submitMetaFeedback +title: submitMetaFeedback +--- + +# Function: submitMetaFeedback() + +```ts +function submitMetaFeedback(payload, opts): SubmitResult; +``` + +Defined in: [feedback.ts:332](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L332) + +## Parameters + +### payload + +[`MetaFeedbackPayload`](../interfaces/MetaFeedbackPayload.md) + +### opts + +#### ghAvailable + +`boolean` + +#### outputPath? + +`string` + +## Returns + +`SubmitResult` diff --git a/docs/intent/functions/toMarkdown.md b/docs/intent/functions/toMarkdown.md index a1bb7e31..809a040c 100644 --- a/docs/intent/functions/toMarkdown.md +++ b/docs/intent/functions/toMarkdown.md @@ -1,22 +1,22 @@ ---- -id: toMarkdown -title: toMarkdown ---- - -# Function: toMarkdown() - -```ts -function toMarkdown(payload): string; -``` - -Defined in: [feedback.ts:254](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L254) - -## Parameters - -### payload - -[`FeedbackPayload`](../interfaces/FeedbackPayload.md) - -## Returns - -`string` +--- +id: toMarkdown +title: toMarkdown +--- + +# Function: toMarkdown() + +```ts +function toMarkdown(payload): string; +``` + +Defined in: [feedback.ts:254](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L254) + +## Parameters + +### payload + +[`FeedbackPayload`](../interfaces/FeedbackPayload.md) + +## Returns + +`string` diff --git a/docs/intent/functions/validateMetaPayload.md b/docs/intent/functions/validateMetaPayload.md index be4f2e64..f6909f28 100644 --- a/docs/intent/functions/validateMetaPayload.md +++ b/docs/intent/functions/validateMetaPayload.md @@ -1,34 +1,34 @@ ---- -id: validateMetaPayload -title: validateMetaPayload ---- - -# Function: validateMetaPayload() - -```ts -function validateMetaPayload(payload): object; -``` - -Defined in: [feedback.ts:163](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L163) - -## Parameters - -### payload - -`unknown` - -## Returns - -`object` - -### errors - -```ts -errors: string[]; -``` - -### valid - -```ts -valid: boolean; -``` +--- +id: validateMetaPayload +title: validateMetaPayload +--- + +# Function: validateMetaPayload() + +```ts +function validateMetaPayload(payload): object; +``` + +Defined in: [feedback.ts:163](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L163) + +## Parameters + +### payload + +`unknown` + +## Returns + +`object` + +### errors + +```ts +errors: string[]; +``` + +### valid + +```ts +valid: boolean; +``` diff --git a/docs/intent/functions/validatePayload.md b/docs/intent/functions/validatePayload.md index 07ad18dc..b1303e72 100644 --- a/docs/intent/functions/validatePayload.md +++ b/docs/intent/functions/validatePayload.md @@ -1,34 +1,34 @@ ---- -id: validatePayload -title: validatePayload ---- - -# Function: validatePayload() - -```ts -function validatePayload(payload): object; -``` - -Defined in: [feedback.ts:97](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L97) - -## Parameters - -### payload - -`unknown` - -## Returns - -`object` - -### errors - -```ts -errors: string[]; -``` - -### valid - -```ts -valid: boolean; -``` +--- +id: validatePayload +title: validatePayload +--- + +# Function: validatePayload() + +```ts +function validatePayload(payload): object; +``` + +Defined in: [feedback.ts:97](https://github.com/TanStack/intent/blob/main/packages/intent/src/feedback.ts#L97) + +## Parameters + +### payload + +`unknown` + +## Returns + +`object` + +### errors + +```ts +errors: string[]; +``` + +### valid + +```ts +valid: boolean; +``` diff --git a/docs/intent/index.md b/docs/intent/index.md index 8affefe1..3d184ef7 100644 --- a/docs/intent/index.md +++ b/docs/intent/index.md @@ -1,40 +1,40 @@ ---- -id: "@tanstack/intent" -title: "@tanstack/intent" ---- - -# @tanstack/intent - -## Interfaces - -- [FeedbackPayload](interfaces/FeedbackPayload.md) -- [IntentConfig](interfaces/IntentConfig.md) -- [IntentPackage](interfaces/IntentPackage.md) -- [IntentProjectConfig](interfaces/IntentProjectConfig.md) -- [MetaFeedbackPayload](interfaces/MetaFeedbackPayload.md) -- [ScanResult](interfaces/ScanResult.md) -- [SkillEntry](interfaces/SkillEntry.md) -- [SkillStaleness](interfaces/SkillStaleness.md) -- [StalenessReport](interfaces/StalenessReport.md) - -## Type Aliases - -- [AgentName](type-aliases/AgentName.md) -- [MetaSkillName](type-aliases/MetaSkillName.md) - -## Functions - -- [checkStaleness](functions/checkStaleness.md) -- [containsSecrets](functions/containsSecrets.md) -- [findSkillFiles](functions/findSkillFiles.md) -- [hasGhCli](functions/hasGhCli.md) -- [metaToMarkdown](functions/metaToMarkdown.md) -- [parseFrontmatter](functions/parseFrontmatter.md) -- [resolveFrequency](functions/resolveFrequency.md) -- [runSetup](functions/runSetup.md) -- [scanForIntents](functions/scanForIntents.md) -- [submitFeedback](functions/submitFeedback.md) -- [submitMetaFeedback](functions/submitMetaFeedback.md) -- [toMarkdown](functions/toMarkdown.md) -- [validateMetaPayload](functions/validateMetaPayload.md) -- [validatePayload](functions/validatePayload.md) +--- +id: "@tanstack/intent" +title: "@tanstack/intent" +--- + +# @tanstack/intent + +## Interfaces + +- [FeedbackPayload](interfaces/FeedbackPayload.md) +- [IntentConfig](interfaces/IntentConfig.md) +- [IntentPackage](interfaces/IntentPackage.md) +- [IntentProjectConfig](interfaces/IntentProjectConfig.md) +- [MetaFeedbackPayload](interfaces/MetaFeedbackPayload.md) +- [ScanResult](interfaces/ScanResult.md) +- [SkillEntry](interfaces/SkillEntry.md) +- [SkillStaleness](interfaces/SkillStaleness.md) +- [StalenessReport](interfaces/StalenessReport.md) + +## Type Aliases + +- [AgentName](type-aliases/AgentName.md) +- [MetaSkillName](type-aliases/MetaSkillName.md) + +## Functions + +- [checkStaleness](functions/checkStaleness.md) +- [containsSecrets](functions/containsSecrets.md) +- [findSkillFiles](functions/findSkillFiles.md) +- [hasGhCli](functions/hasGhCli.md) +- [metaToMarkdown](functions/metaToMarkdown.md) +- [parseFrontmatter](functions/parseFrontmatter.md) +- [resolveFrequency](functions/resolveFrequency.md) +- [runSetup](functions/runSetup.md) +- [scanForIntents](functions/scanForIntents.md) +- [submitFeedback](functions/submitFeedback.md) +- [submitMetaFeedback](functions/submitMetaFeedback.md) +- [toMarkdown](functions/toMarkdown.md) +- [validateMetaPayload](functions/validateMetaPayload.md) +- [validatePayload](functions/validatePayload.md) diff --git a/docs/intent/interfaces/FeedbackPayload.md b/docs/intent/interfaces/FeedbackPayload.md index 9fa2a679..6c7865d8 100644 --- a/docs/intent/interfaces/FeedbackPayload.md +++ b/docs/intent/interfaces/FeedbackPayload.md @@ -1,108 +1,108 @@ ---- -id: FeedbackPayload -title: FeedbackPayload ---- - -# Interface: FeedbackPayload - -Defined in: [types.ts:59](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L59) - -## Properties - -### missing - -```ts -missing: string; -``` - -Defined in: [types.ts:66](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L66) - -*** - -### package - -```ts -package: string; -``` - -Defined in: [types.ts:61](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L61) - -*** - -### selfCorrections - -```ts -selfCorrections: string; -``` - -Defined in: [types.ts:67](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L67) - -*** - -### skill - -```ts -skill: string; -``` - -Defined in: [types.ts:60](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L60) - -*** - -### skillVersion - -```ts -skillVersion: string; -``` - -Defined in: [types.ts:62](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L62) - -*** - -### task - -```ts -task: string; -``` - -Defined in: [types.ts:63](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L63) - -*** - -### userComments? - -```ts -optional userComments: string; -``` - -Defined in: [types.ts:69](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L69) - -*** - -### userRating - -```ts -userRating: "good" | "mixed" | "bad"; -``` - -Defined in: [types.ts:68](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L68) - -*** - -### whatFailed - -```ts -whatFailed: string; -``` - -Defined in: [types.ts:65](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L65) - -*** - -### whatWorked - -```ts -whatWorked: string; -``` - -Defined in: [types.ts:64](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L64) +--- +id: FeedbackPayload +title: FeedbackPayload +--- + +# Interface: FeedbackPayload + +Defined in: [types.ts:59](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L59) + +## Properties + +### missing + +```ts +missing: string; +``` + +Defined in: [types.ts:66](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L66) + +*** + +### package + +```ts +package: string; +``` + +Defined in: [types.ts:61](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L61) + +*** + +### selfCorrections + +```ts +selfCorrections: string; +``` + +Defined in: [types.ts:67](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L67) + +*** + +### skill + +```ts +skill: string; +``` + +Defined in: [types.ts:60](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L60) + +*** + +### skillVersion + +```ts +skillVersion: string; +``` + +Defined in: [types.ts:62](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L62) + +*** + +### task + +```ts +task: string; +``` + +Defined in: [types.ts:63](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L63) + +*** + +### userComments? + +```ts +optional userComments: string; +``` + +Defined in: [types.ts:69](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L69) + +*** + +### userRating + +```ts +userRating: "good" | "mixed" | "bad"; +``` + +Defined in: [types.ts:68](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L68) + +*** + +### whatFailed + +```ts +whatFailed: string; +``` + +Defined in: [types.ts:65](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L65) + +*** + +### whatWorked + +```ts +whatWorked: string; +``` + +Defined in: [types.ts:64](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L64) diff --git a/docs/intent/interfaces/IntentConfig.md b/docs/intent/interfaces/IntentConfig.md index d1856351..c2e91053 100644 --- a/docs/intent/interfaces/IntentConfig.md +++ b/docs/intent/interfaces/IntentConfig.md @@ -1,48 +1,48 @@ ---- -id: IntentConfig -title: IntentConfig ---- - -# Interface: IntentConfig - -Defined in: [types.ts:5](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L5) - -## Properties - -### docs - -```ts -docs: string; -``` - -Defined in: [types.ts:8](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L8) - -*** - -### repo - -```ts -repo: string; -``` - -Defined in: [types.ts:7](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L7) - -*** - -### requires? - -```ts -optional requires: string[]; -``` - -Defined in: [types.ts:9](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L9) - -*** - -### version - -```ts -version: number; -``` - -Defined in: [types.ts:6](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L6) +--- +id: IntentConfig +title: IntentConfig +--- + +# Interface: IntentConfig + +Defined in: [types.ts:5](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L5) + +## Properties + +### docs + +```ts +docs: string; +``` + +Defined in: [types.ts:8](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L8) + +*** + +### repo + +```ts +repo: string; +``` + +Defined in: [types.ts:7](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L7) + +*** + +### requires? + +```ts +optional requires: string[]; +``` + +Defined in: [types.ts:9](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L9) + +*** + +### version + +```ts +version: number; +``` + +Defined in: [types.ts:6](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L6) diff --git a/docs/intent/interfaces/IntentPackage.md b/docs/intent/interfaces/IntentPackage.md index 68aa89fc..ca9dfa3b 100644 --- a/docs/intent/interfaces/IntentPackage.md +++ b/docs/intent/interfaces/IntentPackage.md @@ -1,48 +1,48 @@ ---- -id: IntentPackage -title: IntentPackage ---- - -# Interface: IntentPackage - -Defined in: [types.ts:22](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L22) - -## Properties - -### intent - -```ts -intent: IntentConfig; -``` - -Defined in: [types.ts:25](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L25) - -*** - -### name - -```ts -name: string; -``` - -Defined in: [types.ts:23](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L23) - -*** - -### skills - -```ts -skills: SkillEntry[]; -``` - -Defined in: [types.ts:26](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L26) - -*** - -### version - -```ts -version: string; -``` - -Defined in: [types.ts:24](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L24) +--- +id: IntentPackage +title: IntentPackage +--- + +# Interface: IntentPackage + +Defined in: [types.ts:22](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L22) + +## Properties + +### intent + +```ts +intent: IntentConfig; +``` + +Defined in: [types.ts:25](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L25) + +*** + +### name + +```ts +name: string; +``` + +Defined in: [types.ts:23](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L23) + +*** + +### skills + +```ts +skills: SkillEntry[]; +``` + +Defined in: [types.ts:26](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L26) + +*** + +### version + +```ts +version: string; +``` + +Defined in: [types.ts:24](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L24) diff --git a/docs/intent/interfaces/IntentProjectConfig.md b/docs/intent/interfaces/IntentProjectConfig.md index da6bca86..bc3b5a39 100644 --- a/docs/intent/interfaces/IntentProjectConfig.md +++ b/docs/intent/interfaces/IntentProjectConfig.md @@ -1,24 +1,24 @@ ---- -id: IntentProjectConfig -title: IntentProjectConfig ---- - -# Interface: IntentProjectConfig - -Defined in: [types.ts:101](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L101) - -## Properties - -### feedback - -```ts -feedback: object; -``` - -Defined in: [types.ts:102](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L102) - -#### frequency - -```ts -frequency: string; -``` +--- +id: IntentProjectConfig +title: IntentProjectConfig +--- + +# Interface: IntentProjectConfig + +Defined in: [types.ts:101](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L101) + +## Properties + +### feedback + +```ts +feedback: object; +``` + +Defined in: [types.ts:102](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L102) + +#### frequency + +```ts +frequency: string; +``` diff --git a/docs/intent/interfaces/MetaFeedbackPayload.md b/docs/intent/interfaces/MetaFeedbackPayload.md index 6550fb99..89e12c93 100644 --- a/docs/intent/interfaces/MetaFeedbackPayload.md +++ b/docs/intent/interfaces/MetaFeedbackPayload.md @@ -1,108 +1,108 @@ ---- -id: MetaFeedbackPayload -title: MetaFeedbackPayload ---- - -# Interface: MetaFeedbackPayload - -Defined in: [types.ts:84](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L84) - -## Properties - -### agentUsed - -```ts -agentUsed: AgentName; -``` - -Defined in: [types.ts:87](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L87) - -*** - -### artifactQuality - -```ts -artifactQuality: "good" | "mixed" | "bad"; -``` - -Defined in: [types.ts:88](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L88) - -*** - -### failureModeQuality? - -```ts -optional failureModeQuality: "good" | "mixed" | "bad" | "not-applicable"; -``` - -Defined in: [types.ts:90](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L90) - -*** - -### interviewQuality? - -```ts -optional interviewQuality: "skipped" | "good" | "mixed" | "bad"; -``` - -Defined in: [types.ts:89](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L89) - -*** - -### library - -```ts -library: string; -``` - -Defined in: [types.ts:86](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L86) - -*** - -### metaSkill - -```ts -metaSkill: MetaSkillName; -``` - -Defined in: [types.ts:85](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L85) - -*** - -### suggestions - -```ts -suggestions: string; -``` - -Defined in: [types.ts:93](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L93) - -*** - -### userRating - -```ts -userRating: "good" | "mixed" | "bad"; -``` - -Defined in: [types.ts:94](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L94) - -*** - -### whatFailed - -```ts -whatFailed: string; -``` - -Defined in: [types.ts:92](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L92) - -*** - -### whatWorked - -```ts -whatWorked: string; -``` - -Defined in: [types.ts:91](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L91) +--- +id: MetaFeedbackPayload +title: MetaFeedbackPayload +--- + +# Interface: MetaFeedbackPayload + +Defined in: [types.ts:84](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L84) + +## Properties + +### agentUsed + +```ts +agentUsed: AgentName; +``` + +Defined in: [types.ts:87](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L87) + +*** + +### artifactQuality + +```ts +artifactQuality: "good" | "mixed" | "bad"; +``` + +Defined in: [types.ts:88](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L88) + +*** + +### failureModeQuality? + +```ts +optional failureModeQuality: "good" | "mixed" | "bad" | "not-applicable"; +``` + +Defined in: [types.ts:90](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L90) + +*** + +### interviewQuality? + +```ts +optional interviewQuality: "skipped" | "good" | "mixed" | "bad"; +``` + +Defined in: [types.ts:89](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L89) + +*** + +### library + +```ts +library: string; +``` + +Defined in: [types.ts:86](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L86) + +*** + +### metaSkill + +```ts +metaSkill: MetaSkillName; +``` + +Defined in: [types.ts:85](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L85) + +*** + +### suggestions + +```ts +suggestions: string; +``` + +Defined in: [types.ts:93](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L93) + +*** + +### userRating + +```ts +userRating: "good" | "mixed" | "bad"; +``` + +Defined in: [types.ts:94](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L94) + +*** + +### whatFailed + +```ts +whatFailed: string; +``` + +Defined in: [types.ts:92](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L92) + +*** + +### whatWorked + +```ts +whatWorked: string; +``` + +Defined in: [types.ts:91](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L91) diff --git a/docs/intent/interfaces/ScanResult.md b/docs/intent/interfaces/ScanResult.md index 7db217fa..fc409af1 100644 --- a/docs/intent/interfaces/ScanResult.md +++ b/docs/intent/interfaces/ScanResult.md @@ -1,38 +1,38 @@ ---- -id: ScanResult -title: ScanResult ---- - -# Interface: ScanResult - -Defined in: [types.ts:16](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L16) - -## Properties - -### packageManager - -```ts -packageManager: "unknown" | "npm" | "pnpm" | "yarn" | "bun"; -``` - -Defined in: [types.ts:17](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L17) - -*** - -### packages - -```ts -packages: IntentPackage[]; -``` - -Defined in: [types.ts:18](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L18) - -*** - -### warnings - -```ts -warnings: string[]; -``` - -Defined in: [types.ts:19](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L19) +--- +id: ScanResult +title: ScanResult +--- + +# Interface: ScanResult + +Defined in: [types.ts:16](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L16) + +## Properties + +### packageManager + +```ts +packageManager: "unknown" | "npm" | "pnpm" | "yarn" | "bun"; +``` + +Defined in: [types.ts:17](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L17) + +*** + +### packages + +```ts +packages: IntentPackage[]; +``` + +Defined in: [types.ts:18](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L18) + +*** + +### warnings + +```ts +warnings: string[]; +``` + +Defined in: [types.ts:19](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L19) diff --git a/docs/intent/interfaces/SkillEntry.md b/docs/intent/interfaces/SkillEntry.md index d801101c..3a25260a 100644 --- a/docs/intent/interfaces/SkillEntry.md +++ b/docs/intent/interfaces/SkillEntry.md @@ -1,58 +1,58 @@ ---- -id: SkillEntry -title: SkillEntry ---- - -# Interface: SkillEntry - -Defined in: [types.ts:29](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L29) - -## Properties - -### description - -```ts -description: string; -``` - -Defined in: [types.ts:32](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L32) - -*** - -### framework? - -```ts -optional framework: string; -``` - -Defined in: [types.ts:34](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L34) - -*** - -### name - -```ts -name: string; -``` - -Defined in: [types.ts:30](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L30) - -*** - -### path - -```ts -path: string; -``` - -Defined in: [types.ts:31](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L31) - -*** - -### type? - -```ts -optional type: string; -``` - -Defined in: [types.ts:33](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L33) +--- +id: SkillEntry +title: SkillEntry +--- + +# Interface: SkillEntry + +Defined in: [types.ts:29](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L29) + +## Properties + +### description + +```ts +description: string; +``` + +Defined in: [types.ts:32](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L32) + +*** + +### framework? + +```ts +optional framework: string; +``` + +Defined in: [types.ts:34](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L34) + +*** + +### name + +```ts +name: string; +``` + +Defined in: [types.ts:30](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L30) + +*** + +### path + +```ts +path: string; +``` + +Defined in: [types.ts:31](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L31) + +*** + +### type? + +```ts +optional type: string; +``` + +Defined in: [types.ts:33](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L33) diff --git a/docs/intent/interfaces/SkillStaleness.md b/docs/intent/interfaces/SkillStaleness.md index 29324cc9..c9eed7b2 100644 --- a/docs/intent/interfaces/SkillStaleness.md +++ b/docs/intent/interfaces/SkillStaleness.md @@ -1,38 +1,38 @@ ---- -id: SkillStaleness -title: SkillStaleness ---- - -# Interface: SkillStaleness - -Defined in: [types.ts:49](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L49) - -## Properties - -### name - -```ts -name: string; -``` - -Defined in: [types.ts:50](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L50) - -*** - -### needsReview - -```ts -needsReview: boolean; -``` - -Defined in: [types.ts:52](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L52) - -*** - -### reasons - -```ts -reasons: string[]; -``` - -Defined in: [types.ts:51](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L51) +--- +id: SkillStaleness +title: SkillStaleness +--- + +# Interface: SkillStaleness + +Defined in: [types.ts:49](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L49) + +## Properties + +### name + +```ts +name: string; +``` + +Defined in: [types.ts:50](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L50) + +*** + +### needsReview + +```ts +needsReview: boolean; +``` + +Defined in: [types.ts:52](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L52) + +*** + +### reasons + +```ts +reasons: string[]; +``` + +Defined in: [types.ts:51](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L51) diff --git a/docs/intent/interfaces/StalenessReport.md b/docs/intent/interfaces/StalenessReport.md index 40057b4c..ca04ba0b 100644 --- a/docs/intent/interfaces/StalenessReport.md +++ b/docs/intent/interfaces/StalenessReport.md @@ -1,58 +1,58 @@ ---- -id: StalenessReport -title: StalenessReport ---- - -# Interface: StalenessReport - -Defined in: [types.ts:41](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L41) - -## Properties - -### currentVersion - -```ts -currentVersion: string; -``` - -Defined in: [types.ts:43](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L43) - -*** - -### library - -```ts -library: string; -``` - -Defined in: [types.ts:42](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L42) - -*** - -### skills - -```ts -skills: SkillStaleness[]; -``` - -Defined in: [types.ts:46](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L46) - -*** - -### skillVersion - -```ts -skillVersion: string; -``` - -Defined in: [types.ts:44](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L44) - -*** - -### versionDrift - -```ts -versionDrift: "major" | "minor" | "patch"; -``` - -Defined in: [types.ts:45](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L45) +--- +id: StalenessReport +title: StalenessReport +--- + +# Interface: StalenessReport + +Defined in: [types.ts:41](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L41) + +## Properties + +### currentVersion + +```ts +currentVersion: string; +``` + +Defined in: [types.ts:43](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L43) + +*** + +### library + +```ts +library: string; +``` + +Defined in: [types.ts:42](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L42) + +*** + +### skills + +```ts +skills: SkillStaleness[]; +``` + +Defined in: [types.ts:46](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L46) + +*** + +### skillVersion + +```ts +skillVersion: string; +``` + +Defined in: [types.ts:44](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L44) + +*** + +### versionDrift + +```ts +versionDrift: "major" | "minor" | "patch"; +``` + +Defined in: [types.ts:45](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L45) diff --git a/docs/intent/type-aliases/AgentName.md b/docs/intent/type-aliases/AgentName.md index 0f3a56c4..76519b81 100644 --- a/docs/intent/type-aliases/AgentName.md +++ b/docs/intent/type-aliases/AgentName.md @@ -1,12 +1,12 @@ ---- -id: AgentName -title: AgentName ---- - -# Type Alias: AgentName - -```ts -type AgentName = "claude-code" | "cursor" | "copilot" | "codex" | "other"; -``` - -Defined in: [types.ts:82](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L82) +--- +id: AgentName +title: AgentName +--- + +# Type Alias: AgentName + +```ts +type AgentName = "claude-code" | "cursor" | "copilot" | "codex" | "other"; +``` + +Defined in: [types.ts:82](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L82) diff --git a/docs/intent/type-aliases/MetaSkillName.md b/docs/intent/type-aliases/MetaSkillName.md index 570dd16b..8e534b90 100644 --- a/docs/intent/type-aliases/MetaSkillName.md +++ b/docs/intent/type-aliases/MetaSkillName.md @@ -1,16 +1,16 @@ ---- -id: MetaSkillName -title: MetaSkillName ---- - -# Type Alias: MetaSkillName - -```ts -type MetaSkillName = - | "domain-discovery" - | "tree-generator" - | "generate-skill" - | "skill-staleness-check"; -``` - -Defined in: [types.ts:76](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L76) +--- +id: MetaSkillName +title: MetaSkillName +--- + +# Type Alias: MetaSkillName + +```ts +type MetaSkillName = + | "domain-discovery" + | "tree-generator" + | "generate-skill" + | "skill-staleness-check"; +``` + +Defined in: [types.ts:76](https://github.com/TanStack/intent/blob/main/packages/intent/src/types.ts#L76) diff --git a/knip.json b/knip.json index 023c5fdf..b31558b4 100644 --- a/knip.json +++ b/knip.json @@ -1,13 +1,13 @@ -{ - "$schema": "https://unpkg.com/knip@5/schema.json", - "ignoreDependencies": ["@faker-js/faker"], - "ignoreBinaries": ["tsx"], - "workspaces": { - ".": { - "entry": ["scripts/*.ts"] - }, - "packages/intent": { - "ignore": ["meta/**"] - } - } -} +{ + "$schema": "https://unpkg.com/knip@5/schema.json", + "ignoreDependencies": ["@faker-js/faker"], + "ignoreBinaries": ["tsx"], + "workspaces": { + ".": { + "entry": ["scripts/*.ts"] + }, + "packages/intent": { + "ignore": ["meta/**"] + } + } +} diff --git a/package.json b/package.json index 54cc6177..ec16cbb5 100644 --- a/package.json +++ b/package.json @@ -1,69 +1,69 @@ -{ - "name": "root", - "private": true, - "repository": { - "type": "git", - "url": "git+https://github.com/TanStack/intent.git" - }, - "packageManager": "pnpm@10.26.1", - "type": "module", - "scripts": { - "build": "nx affected --skip-nx-cache --targets=build --exclude=examples/**", - "build:all": "nx run-many --targets=build --exclude=examples/**", - "build:core": "nx run-many --targets=build --projects=packages/agents", - "changeset": "changeset", - "changeset:publish": "changeset publish", - "changeset:version": "changeset version && pnpm install --no-frozen-lockfile && pnpm format", - "clean": "find agents -name 'dist' -type d -prune -exec rm -rf {} +", - "clean:node_modules": "find agents -name 'node_modules' -type d -prune -exec rm -rf {} +", - "clean:all": "pnpm run clean && pnpm run clean:node_modules", - "copy:readme": "cp README.md packages/intent/README.md", - "dev": "pnpm run watch", - "format": "prettier --experimental-cli --ignore-unknown '**/*' --write", - "lint:fix": "nx affected --target=lint:fix --exclude=examples/**", - "lint:fix:all": "nx run-many --targets=lint --fix", - "test": "pnpm run test:ci", - "test:ci": "tsc --noEmit && nx run-many --targets=test:eslint,test:sherif,test:knip,test:docs,test:lib,test:types,build", - "generate-docs": "node scripts/generate-docs.ts", - "test:docs": "node scripts/verify-links.ts", - "test:eslint": "nx affected --target=test:eslint --exclude=examples/**", - "test:knip": "knip", - "test:lib": "nx affected --targets=test:lib --exclude=examples/**", - "test:lib:dev": "pnpm test:lib && nx watch --all -- pnpm test:lib", - "test:pr": "tsc --noEmit && nx affected --targets=test:eslint,test:sherif,test:knip,test:docs,test:lib,test:types,build", - "test:sherif": "sherif", - "test:types": "nx affected --targets=test:types --exclude=examples/**", - "watch": "pnpm run build:all && nx watch --all -- pnpm run build:all" - }, - "nx": { - "includedScripts": [ - "test:docs", - "test:knip", - "test:sherif" - ] - }, - "devDependencies": { - "@changesets/cli": "^2.29.8", - "@faker-js/faker": "^10.2.0", - "@svitejs/changesets-changelog-github-compact": "^1.2.0", - "@tanstack/eslint-config": "0.3.4", - "@types/node": "^25.0.7", - "eslint": "^9.39.2", - "eslint-plugin-unused-imports": "^4.3.0", - "happy-dom": "^20.1.0", - "knip": "^5.80.2", - "markdown-link-extractor": "^4.0.3", - "nx": "^22.3.3", - "prettier": "^3.7.4", - "prettier-plugin-svelte": "^3.4.1", - "sherif": "^1.9.0", - "tinyglobby": "^0.2.15", - "typescript": "5.9.3", - "vitest": "^4.0.17", - "yaml": "^2.7.0" - }, - "overrides": {}, - "dependencies": { - "@tanstack/typedoc-config": "^0.3.3" - } -} +{ + "name": "root", + "private": true, + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/intent.git" + }, + "packageManager": "pnpm@10.26.1", + "type": "module", + "scripts": { + "build": "nx affected --skip-nx-cache --targets=build --exclude=examples/**", + "build:all": "nx run-many --targets=build --exclude=examples/**", + "build:core": "nx run-many --targets=build --projects=packages/agents", + "changeset": "changeset", + "changeset:publish": "changeset publish", + "changeset:version": "changeset version && pnpm install --no-frozen-lockfile && pnpm format", + "clean": "find agents -name 'dist' -type d -prune -exec rm -rf {} +", + "clean:node_modules": "find agents -name 'node_modules' -type d -prune -exec rm -rf {} +", + "clean:all": "pnpm run clean && pnpm run clean:node_modules", + "copy:readme": "cp README.md packages/intent/README.md", + "dev": "pnpm run watch", + "format": "prettier --experimental-cli --ignore-unknown '**/*' --write", + "lint:fix": "nx affected --target=lint:fix --exclude=examples/**", + "lint:fix:all": "nx run-many --targets=lint --fix", + "test": "pnpm run test:ci", + "test:ci": "tsc --noEmit && nx run-many --targets=test:eslint,test:sherif,test:knip,test:docs,test:lib,test:types,build", + "generate-docs": "node scripts/generate-docs.ts", + "test:docs": "node scripts/verify-links.ts", + "test:eslint": "nx affected --target=test:eslint --exclude=examples/**", + "test:knip": "knip", + "test:lib": "nx affected --targets=test:lib --exclude=examples/**", + "test:lib:dev": "pnpm test:lib && nx watch --all -- pnpm test:lib", + "test:pr": "tsc --noEmit && nx affected --targets=test:eslint,test:sherif,test:knip,test:docs,test:lib,test:types,build", + "test:sherif": "sherif", + "test:types": "nx affected --targets=test:types --exclude=examples/**", + "watch": "pnpm run build:all && nx watch --all -- pnpm run build:all" + }, + "nx": { + "includedScripts": [ + "test:docs", + "test:knip", + "test:sherif" + ] + }, + "devDependencies": { + "@changesets/cli": "^2.29.8", + "@faker-js/faker": "^10.2.0", + "@svitejs/changesets-changelog-github-compact": "^1.2.0", + "@tanstack/eslint-config": "0.3.4", + "@types/node": "^25.0.7", + "eslint": "^9.39.2", + "eslint-plugin-unused-imports": "^4.3.0", + "happy-dom": "^20.1.0", + "knip": "^5.80.2", + "markdown-link-extractor": "^4.0.3", + "nx": "^22.3.3", + "prettier": "^3.7.4", + "prettier-plugin-svelte": "^3.4.1", + "sherif": "^1.9.0", + "tinyglobby": "^0.2.15", + "typescript": "5.9.3", + "vitest": "^4.0.17", + "yaml": "^2.7.0" + }, + "overrides": {}, + "dependencies": { + "@tanstack/typedoc-config": "^0.3.3" + } +} diff --git a/packages/intent/CHANGELOG.md b/packages/intent/CHANGELOG.md index 17e41f3c..1d54b8a4 100644 --- a/packages/intent/CHANGELOG.md +++ b/packages/intent/CHANGELOG.md @@ -1,7 +1,7 @@ -# @tanstack/intent - -## 0.1.0 - -### Patch Changes - -- Add `intent-library` end-user CLI for library consumers. Libraries wire it up via a generated shim (`intent setup --shim`) to expose an `intent` bin. Running `intent list` recursively discovers skills across the library's dependency tree; `intent install` prints an agent-driven prompt to map skills to project tasks in CLAUDE.md. ([#9](https://github.com/TanStack/intent/pull/9)) +# @tanstack/intent + +## 0.1.0 + +### Patch Changes + +- Add `intent-library` end-user CLI for library consumers. Libraries wire it up via a generated shim (`intent setup --shim`) to expose an `intent` bin. Running `intent list` recursively discovers skills across the library's dependency tree; `intent install` prints an agent-driven prompt to map skills to project tasks in CLAUDE.md. ([#9](https://github.com/TanStack/intent/pull/9)) diff --git a/packages/intent/README.md b/packages/intent/README.md index 449db8af..70d1ba49 100644 --- a/packages/intent/README.md +++ b/packages/intent/README.md @@ -1,88 +1,88 @@ -# @tanstack/intent - -Ship compositional knowledge for AI coding agents alongside your npm packages. - -## The problem - -Your docs are good. Your types are solid. Your agent still gets it wrong. - -Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions without flagging which applies. Once a breaking change ships, models contain _both_ versions forever with no way to disambiguate. - -The ecosystem already moves toward agent-readable knowledge — Cursor rules, CLAUDE.md files, skills directories. But delivery is stuck in copy-paste: hunt for a community-maintained rules file, paste it into your config, repeat for every tool. No versioning, no update path, no staleness signal. - -## Skills: the fourth artifact - -You ship code, docs, and types. Skills are the fourth artifact — knowledge encoded for the thing writing most of your code. - -Skills are npm packages of knowledge — encoding how tools compose, which patterns fit which goals, and what to avoid. When a library ships skills using `@tanstack/intent`, that knowledge travels with the tool via `npm update` — not the model's training cutoff. Versioned knowledge the maintainer owns, updated when the package updates. - -Each skill declares its source docs. When those docs change, the CLI flags the skill for review. One source of truth, one derived artifact that stays in sync. - -## Quick Start - -### For library consumers - -Set up skill-to-task mappings in your project's agent config files (CLAUDE.md, .cursorrules, etc.): - -```bash -npx @tanstack/intent install -``` - -No per-library setup. No hunting for rules files. Install the package, run `intent install`, and the agent understands the tool. Update the package, and skills update too. - -List available skills from installed packages: - -```bash -npx @tanstack/intent list -``` - -### For library maintainers - -Generate skills for your library by telling your AI coding agent to run: - -```bash -npx @tanstack/intent scaffold -``` - -This prints a prompt that walks the agent through domain discovery, skill tree generation, and skill creation — one step at a time with your review at each stage. - -Validate your skill files: - -```bash -npx @tanstack/intent validate -``` - -Check for skills that have fallen behind their sources: - -```bash -npx @tanstack/intent stale -``` - -Copy CI workflow templates into your repo so validation and staleness checks run on every push: - -```bash -npx @tanstack/intent setup -``` - -## Keeping skills current - -The real risk with any derived artifact is staleness. `intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships. - -The feedback loop runs both directions. `intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`. - -## CLI Commands - -| Command | Description | -| ----------------------- | --------------------------------------------------- | -| `intent install` | Set up skill-to-task mappings in agent config files | -| `intent list [--json]` | Discover intent-enabled packages | -| `intent meta` | List meta-skills for library maintainers | -| `intent scaffold` | Print the guided skill generation prompt | -| `intent validate [dir]` | Validate SKILL.md files | -| `intent setup` | Copy CI templates, generate shim, create labels | -| `intent stale [--json]` | Check skills for version drift | -| `intent feedback` | Submit skill feedback | - -## License - -[MIT](./LICENSE) +# @tanstack/intent + +Ship compositional knowledge for AI coding agents alongside your npm packages. + +## The problem + +Your docs are good. Your types are solid. Your agent still gets it wrong. + +Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions without flagging which applies. Once a breaking change ships, models contain _both_ versions forever with no way to disambiguate. + +The ecosystem already moves toward agent-readable knowledge — Cursor rules, CLAUDE.md files, skills directories. But delivery is stuck in copy-paste: hunt for a community-maintained rules file, paste it into your config, repeat for every tool. No versioning, no update path, no staleness signal. + +## Skills: the fourth artifact + +You ship code, docs, and types. Skills are the fourth artifact — knowledge encoded for the thing writing most of your code. + +Skills are npm packages of knowledge — encoding how tools compose, which patterns fit which goals, and what to avoid. When a library ships skills using `@tanstack/intent`, that knowledge travels with the tool via `npm update` — not the model's training cutoff. Versioned knowledge the maintainer owns, updated when the package updates. + +Each skill declares its source docs. When those docs change, the CLI flags the skill for review. One source of truth, one derived artifact that stays in sync. + +## Quick Start + +### For library consumers + +Set up skill-to-task mappings in your project's agent config files (CLAUDE.md, .cursorrules, etc.): + +```bash +npx @tanstack/intent install +``` + +No per-library setup. No hunting for rules files. Install the package, run `intent install`, and the agent understands the tool. Update the package, and skills update too. + +List available skills from installed packages: + +```bash +npx @tanstack/intent list +``` + +### For library maintainers + +Generate skills for your library by telling your AI coding agent to run: + +```bash +npx @tanstack/intent scaffold +``` + +This prints a prompt that walks the agent through domain discovery, skill tree generation, and skill creation — one step at a time with your review at each stage. + +Validate your skill files: + +```bash +npx @tanstack/intent validate +``` + +Check for skills that have fallen behind their sources: + +```bash +npx @tanstack/intent stale +``` + +Copy CI workflow templates into your repo so validation and staleness checks run on every push: + +```bash +npx @tanstack/intent setup +``` + +## Keeping skills current + +The real risk with any derived artifact is staleness. `intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships. + +The feedback loop runs both directions. `intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`. + +## CLI Commands + +| Command | Description | +| ----------------------- | --------------------------------------------------- | +| `intent install` | Set up skill-to-task mappings in agent config files | +| `intent list [--json]` | Discover intent-enabled packages | +| `intent meta` | List meta-skills for library maintainers | +| `intent scaffold` | Print the guided skill generation prompt | +| `intent validate [dir]` | Validate SKILL.md files | +| `intent setup` | Copy CI templates, generate shim, create labels | +| `intent stale [--json]` | Check skills for version drift | +| `intent feedback` | Submit skill feedback | + +## License + +[MIT](./LICENSE) diff --git a/packages/intent/meta/domain-discovery/SKILL.md b/packages/intent/meta/domain-discovery/SKILL.md index 35480741..3321bd3d 100644 --- a/packages/intent/meta/domain-discovery/SKILL.md +++ b/packages/intent/meta/domain-discovery/SKILL.md @@ -1,784 +1,894 @@ ---- -name: skill-domain-discovery -description: > - Analyze library documentation and source code, then interview maintainers - to discover capability domains and task-focused skills for AI coding - agents. Activate when creating skills for a new library, organizing - existing documentation into skill categories, or when a maintainer wants - help deciding how to structure their library's agent-facing knowledge. - Produces a domain_map.yaml and skill_spec.md that feed directly into - the skill-tree-generator skill. -metadata: - version: '3.0' - category: meta-tooling - output_artifacts: - - skills/_artifacts/domain_map.yaml - - skills/_artifacts/skill_spec.md - skills: - - tree-generator ---- - -# Domain Discovery & Maintainer Interview - -You are extracting domain knowledge for a library to produce a structured -domain map. Your job is not to summarize documentation — it is to build a -deep understanding of the library first, then use that understanding to -surface the implicit knowledge that maintainers carry but docs miss. - -The output is a set of **task-focused skills** — each one matching a -specific developer moment ("implement a proxy", "set up auth", "audit -before launch"). Domains are an intermediate conceptual grouping you use -during analysis; the final skills emerge from the intersection of domains -and developer tasks. - -There are five phases. Always run them in order — unless the lightweight -path applies (see below). - -1. **Quick scan** — orient yourself (autonomous) -2. **High-level interview** — extract the maintainer's task map -3. **Deep read** — fill in failure modes and detail (autonomous) -4. **Detail interview** — gap-targeted questions, AI-agent failures -5. **Finalize artifacts** - -### Lightweight path (small libraries) - -After Phase 1, if the library has **fewer than 5 client-facing skill -areas** (e.g. a focused utility library, a single-purpose tool, or a -library with only 2–3 distinct developer tasks), use a compressed flow: - -1. **Phase 1** — Quick scan (same as full flow) -2. **Phase 2+4 combined** — Single interview round. Combine the - high-level task map questions (Phase 2) with gap-targeted and - AI-agent-specific questions (Phase 4) into one interview session - of 4–8 questions total. Skip the draft-review step since the skill - set is small enough to confirm in one pass. -3. **Phase 3** — Deep read (same as full flow, but scope is smaller) -4. **Phase 5** — Finalize artifacts (same as full flow) - -The lightweight path produces identical output artifacts (domain_map.yaml -and skill_spec.md). It just avoids two separate interview rounds when the -library is small enough that one round covers everything. - ---- - -## Phase 1 — Quick scan (autonomous, ~10 minutes) - -Orient yourself in the library. You are building a structural map, not -reading exhaustively yet. - -### 1a — Read orientation material - -1. **README** — vocabulary, mental model, what the library does -2. **Getting started / quickstart** — the happy path -3. **Package structure** — if monorepo, identify which packages are - client-facing vs internal. Focus on the 2–3 packages most relevant - to skill consumers (usually client SDKs and primary framework adapters) -4. **AGENTS.md or .cursorrules** — if the library already has agent - guidance, read it. This is high-signal for what the maintainer - considers important - -### 1b — Read peer dependency constraints - -Check `package.json` for `peerDependencies` and `peerDependenciesMeta`. -For each major peer dependency (React, Vue, Svelte, Next.js, etc.): - -1. Note the version range required -2. Read the peer's docs for integration constraints that affect this - library: SSR/hydration rules, component lifecycle boundaries, - browser-only APIs, singleton patterns, connection limits -3. Log framework-specific failure modes — these are the highest-impact - failure modes and cannot be discovered from the library's own source - -Examples of peer-dependency-driven failure modes: - -- SSR: calling browser-only APIs during server render -- React: breaking hook rules in library wrapper components -- Connection limits: opening multiple WebSocket connections per tab -- Singleton patterns: creating multiple client instances in dev mode - -### 1c — Note initial impressions - -Log (but do not group yet): - -- What the library does in one sentence -- The core abstractions a developer interacts with -- Which frameworks it supports -- Any existing skill files, agent configs, or intents -- Whether the library is a monorepo and which packages matter - ---- - -## Phase 2 — High-level interview - -The maintainer's mental model of developer tasks IS the skill map. Your -job in this phase is to extract it — not to propose your own structure. - -### Rules for Phase 2 - -1. One topic per message for open-ended questions. You may batch 2–3 - yes/no or short-confirmation questions together. -2. Take notes silently. Do not summarize back unless asked. -3. If the maintainer gives a short answer, probe deeper before moving on. - -### 2a — Developer tasks (2–4 questions) - -Start with the maintainer's view of what developers do: - -> "Walk me through what a developer actually does with your library — -> not the elevator pitch, but the tasks they come to you for help with, -> from first install through production." - -Follow up to enumerate distinct tasks: - -> "If you listed every distinct thing a developer asks an agent to help -> with using your library, what would that list look like? I'm thinking -> things like 'set up the client', 'implement auth', 'debug sync issues' -> — each one a separate moment where they'd want focused guidance." - -### 2b — Developer journeys (1–2 questions) - -Surface lifecycle/journey skills that cross-cut task areas: - -> "Are there developer journeys that cut across multiple features? -> For example: a getting-started guide, a go-to-production checklist, -> a migrate-from-v4 walkthrough. Which of these exist in your docs -> or would be valuable as standalone skills?" - -### 2c — Composition and ecosystem (1–2 questions) - -> "Which other libraries does yours compose with most often? Are there -> integration patterns important enough to warrant their own skill — -> for example, using your library with [framework/ORM/router]?" - -### 2d — Confirm initial skill map - -Synthesize what you heard into a proposed skill list and present it: - -> "Based on what you've told me, here's my proposed skill list: -> [enumerate skills with one-line descriptions]. Does this match how -> you think about your library? What would you add, remove, or rename?" - ---- - -## Phase 3 — Deep read (autonomous) - -You now have the maintainer's task map. Read docs and source to fill -each skill area with concrete content — failure modes, code patterns, -gotchas. - -### Reading order - -Read in this order. Each step builds context for the next. - -1. **Every narrative guide** — the how-to content, not API reference tables -2. **Migration guides** — highest-yield source for failure modes; every - breaking change is exactly what agents trained on older versions produce -3. **API reference** — scan for exports, type signatures, option shapes -4. **Changelog for major versions** — API renames, removed exports, - behavioral changes -5. **GitHub issues and discussions** — scan for frequently reported - confusion, common misunderstandings, recurring questions. Also look - for what users are implicitly arguing for architecturally — not just - "people are confused about X" but "users keep expecting X to work - like Y, which reveals a tension between [design force] and [design force]." - If no web access, check for FAQ.md, TROUBLESHOOTING.md, or docs/faq - as proxies. -6. **Source code** — verify ambiguities from docs, check defaults, find - assertions and invariant checks. For monorepos, read the 2–3 core - packages deeply. For adapter packages, read one representative adapter - deeply, then scan others for deviations from the pattern. - -### What to log - -Produce a flat concept inventory. One item per line. No grouping yet. - -Log every: - -- Named concept, abstraction, or lifecycle stage -- Public export: function, hook, class, type, constant -- Configuration key, its type, and its default value -- Constraint or invariant (especially any enforced by `throw` or assertion) -- Doc callout: any "note", "warning", "caution", "important", "avoid", "do not" -- Dual API: any place the library has two ways to do the same thing (old/new, - verbose/shorthand, lower-level/higher-level) -- Environment branch: any place behavior depends on SSR/CSR, dev/prod, - framework, bundler, or config flag -- Type gap: any type documented as accepting X but source shows X | Y or - rejects a subtype of X -- Source assertion: any `if (!x) throw`, `invariant()`, or `assert()` with - the error message text - -### What to extract from migration guides specifically - -For each breaking change between major versions: - -``` -Old pattern: [code that agents trained on older versions will produce] -New pattern: [current correct code] -What changed: [one sentence — the specific mechanism] -Version boundary: [e.g. "v4 → v5"] -``` - -These become high-priority failure modes. - -### 3a — Group concepts into domains - -Move concept inventory items into groups. Two items belong together when: - -- A developer reasons about them together when solving a problem -- Solving one correctly requires understanding how the other works -- They share a lifecycle, configuration scope, or architectural tradeoff -- Getting one wrong tends to produce bugs in the other - -Let library complexity drive the domain count — a focused library may need -only 2–3 domains, while a large framework may need 7+. Validate by asking: -"Would a developer working on a single feature need to load skills from -multiple domains? If so, merge those domains." These are conceptual -groupings, not the final skills. - -Do not create a group for: - -- A single hook, function, or class -- A single doc or reference page -- "Miscellaneous", "Advanced", or "Other" -- Configuration knobs that only affect another group's behavior - -Name each domain as work being performed, not what the library provides. - -**Validation step:** After grouping, check each domain by asking: -"Would a developer working on a single feature need to load skills from -multiple domains?" If yes, merge those domains. Group by developer tasks -(what they're trying to accomplish), not by architecture (how the library -is organized internally). For example, prefer "writing data" over -"producer lifecycle" — the former matches a developer's intent, the latter -matches the codebase structure. - -### 3b — Map domains × tasks → skills - -Merge your conceptual domains with the maintainer's task list from -Phase 2. Each skill should match a specific developer moment while -carrying the conceptual depth of its parent domain(s). - -A skill is well-shaped when: - -- A developer would ask for it by name ("help me set up sync") -- It covers enough for the agent to complete the task end-to-end -- It doesn't require loading 3 other skills to be useful - -Some domains produce multiple skills (a broad domain like "data access" -might yield "live-queries", "mutations", "offline-sync"). Some tasks -span domains (a "go-live" checklist touches security, performance, and -configuration). Both are fine. - -Also consider: - -- **Lifecycle/journey skills** — if the library's docs include a - quickstart guide, go-to-production checklist, or migration path, - suggest these as standalone skills. Don't force them if the docs - don't have the material. -- **Composition skills** — when peer deps or examples show consistent - co-usage with another library, output a full skill for the - integration, not a footnote on a domain. - -### 3c — Flag subsystems within skills - -Check each skill area for internal diversity. A skill may be -conceptually unified but contain multiple independent subsystems with -distinct config interfaces — for example, 5 sync adapters that all -solve "connectivity" but each with unique setup, options, and failure -modes. - -For each skill, ask: "Does this cover 3+ backends, adapters, drivers, -or providers with distinct configuration surfaces?" If yes, list them -as `subsystems`. These tell the skill-tree-generator to produce -per-subsystem reference files. - -Also flag dense API surfaces — if a topic has >10 distinct operators, -option shapes, or patterns (e.g. query operators, schema validation -rules), note it as a `reference_candidates` entry. - -### 3d — Extract failure modes - -For each skill, extract failure modes that pass all three tests: - -- **Plausible** — An agent would generate this because it looks correct - based on the library's design, a similar API, or an older version -- **Silent** — No immediate crash; fails at runtime or under specific conditions -- **Grounded** — Traceable to a specific doc page, source location, or issue - -**Where to find them:** - -| Source | What to extract | -| -------------------- | ------------------------------------------------------------------ | -| Migration guides | Every breaking change → old pattern is the wrong code | -| Doc callouts | Any "note", "warning", "avoid" with surrounding context | -| Source assertions | `throw` and `invariant()` messages describe the failure | -| Default values | Undocumented or surprising defaults that cause wrong behavior | -| Type precision | Source type more restrictive than docs imply | -| Environment branches | `typeof window`, SSR flags, `NODE_ENV` — behavior differs silently | - -Target 3 failure modes per skill minimum. Complex skills target 5–6. - -**Code patterns.** Every failure mode should include `wrong_pattern` and -`correct_pattern` fields with short code snippets (3–10 lines each). -The wrong pattern is what an agent would generate; the correct pattern -is the fix. These feed directly into SKILL.md Common Mistakes sections -as wrong/correct code pairs. If the failure mode is purely conceptual -(e.g. an architectural choice) rather than a code pattern, omit both -fields and explain in `mechanism` instead. - -**Cross-skill failure modes.** Some failure modes belong to multiple -skills. A developer doing SSR work and a developer doing state management -both need to know about "stale state during hydration" — they load -different skills but need the same advice. When a failure mode spans -skills, list all relevant skill slugs in its `skills` field. The -skill-tree-generator will write it into every corresponding SKILL file. - -List a cross-skill failure mode once, under its primary skill. Set -the `skills` field to all skill slugs it applies to. Do not duplicate -the entry in the YAML — the skill-tree-generator handles duplication -into multiple SKILL files at generation time. - -### 3e — Identify cross-skill tensions - -Look for places where design forces between skills conflict. A tension -is not a failure mode — it's a structural pull where optimizing for one -task makes another harder. Examples: - -- "Getting-started simplicity conflicts with production operational safety" -- "Type-safety strictness conflicts with rapid prototyping flexibility" -- "SSR correctness requires patterns that hurt client-side performance" - -Tensions are where agents fail most because they optimize for one task -without seeing the tradeoff. Each tension should name the skills in -conflict, describe the pull, and state what an agent gets wrong when it -only considers one side. - -Target 2–4 tensions. If you find none, the skills may be too isolated — -revisit whether you're missing cross-connections. - -### 3f — Map cross-references - -Beyond tensions (conflicts) and shared failure modes, identify skills -that illuminate each other without conflicting. A cross-reference means: -"an agent loading skill A would produce better code if it knew about -skill B." These become "See also" pointers in the generated SKILL.md -files. - -For each pair, note: - -- Which skill references which (can be bidirectional) -- Why awareness of the other skill improves output - -Examples: - -- A quickstart skill references the security checklist ("after setup, audit") -- A state management skill references an SSR skill ("state hydration - requires understanding SSR lifecycle") -- A data writing skill references a data reading skill ("writes affect - how queries invalidate") - -Output these in the `cross_references` section of domain_map.yaml. - -### 3g — Identify gaps - -For each skill, explicitly list what you could NOT determine from docs -and source alone. These become interview questions in Phase 4. - -Common gaps: - -- "Docs describe X but don't explain when you'd choose X over Y" -- "Migration guide mentions this changed but doesn't say what the old - behavior was" -- "Source has an assertion here but no doc explains what triggers it" -- "GitHub issues show confusion about X but docs don't address it" -- "I found two patterns for doing X — unclear which is current/preferred" - -### 3h — Discover composition targets - -Scan `package.json` for peer dependencies, optional dependencies, and -`peerDependenciesMeta`. Scan example directories and integration tests -for import patterns. For each frequently co-used library, log: - -- Library name and which features interact -- Whether it's a required or optional integration -- Any example code showing the integration pattern - -These become targeted composition questions in Phase 4e. - -### 3i — Produce the draft - -Write the full `domain_map.yaml` (format in Output Artifacts below) with -a `status: draft` field. Flag every gap in the `gaps` section. - -Present the draft to the maintainer before starting Phase 4: - -> "I've read the docs and source for [library] and produced a draft with -> [N] skills and [M] failure modes. I've flagged [K] specific gaps where -> I need your input." - ---- - -## Phase 4 — Detail interview (builds on Phase 1–3) - -You have the maintainer's task map and a deep read. The interview now -fills gaps, validates your understanding, and surfaces implicit knowledge. - -### Rules for Phase 4 - -1. One topic per message for open-ended questions. You may batch 2–3 - yes/no or short-confirmation questions together. -2. Each question must reference something specific from your reading. -3. If the maintainer gives a short answer, probe deeper before moving on. -4. Take notes silently. Do not summarize back unless asked. - -### 4a — Draft review (2–3 questions) - -Start by confirming or correcting your skill list and failure modes: - -> "Here's the skill list I've built from our earlier conversation plus -> the deep read: [list skills with brief descriptions]. Does this still -> match your thinking? Anything to add, remove, or rename?" - -Follow up on any corrections. Then: - -> "I identified [M] failure modes from the docs and migration guides. Are -> there important ones I missed — especially patterns that look correct -> but fail silently?" - -### 4b — Gap-targeted questions (3–8 questions) - -For each gap flagged in Phase 3g, ask a specific question. These are not -generic — they reference what you found: - -**Instead of:** "What do developers get wrong?" -**Ask:** "I noticed the migration guide from v4 to v5 changed how [X] works, -but the docs don't show the old pattern. Do agents still commonly generate -the v4 pattern? What does it look like?" - -**Instead of:** "Are there surprising interactions?" -**Ask:** "The source throws an invariant error if [X] is called before [Y], -but the docs don't mention ordering. How often do developers hit this?" - -**Instead of:** "What's different in SSR vs client?" -**Ask:** "I found a `typeof window` check in [file] that changes behavior -for [feature]. What goes wrong when developers test only in the browser -and deploy with SSR?" - -Adapt from this bank of gap-targeted question templates: - -- "I found two patterns for [X] in the docs — [pattern A] and [pattern B]. - Which is current, and does the old one still work?" -- "The source defaults [config option] to [value], which seems surprising - for [reason]. Is this intentional? Do developers need to override it?" -- "GitHub issues show [N] reports of confusion about [X]. What's the - underlying misunderstanding?" -- "I couldn't find docs for how [feature A] interacts with [feature B]. - What should an agent know about using them together?" -- "The API reference shows [type signature], but the guide examples use - a different shape. Which is accurate?" - -### 4c — AI-agent-specific failure modes (2–4 questions) - -These target mistakes that AI coding agents make but human developers -typically don't. Agent-specific failures are often the highest-value -findings — in testing, maintainer answers to these questions produced -the most critical failure modes. - -- "What mistakes would an AI coding agent make that a human developer - wouldn't? Think about: hallucinating APIs that don't exist, defaulting - to language primitives instead of library abstractions, choosing the - wrong adapter or integration path." -- "When an agent generates code using your library, what's the first - thing you'd check? What pattern would make you immediately say - 'an AI wrote this'?" -- "Are there parts of your API where the naming or design is misleading - enough that an agent with no prior context would pick the wrong - approach? What would it pick, and what should it pick instead?" -- "Are there features where the docs are comprehensive for human - developers but would still mislead an agent? For example, features - that require understanding unstated context, or where the 'obvious' - approach from reading the API surface is wrong." - -### 4d — Implicit knowledge extraction (3–5 questions) - -These surface knowledge that doesn't appear in any docs: - -- "What does a senior developer using your library know that a mid-level - developer doesn't — something that isn't written down anywhere?" -- "Are there patterns that work fine for prototyping but are dangerous - in production? What makes them dangerous?" -- "What question do you answer most often in Discord or GitHub issues - that the docs technically cover but people still miss?" -- "Is there anything you'd change about the API design if you could break - backwards compatibility? What's the current workaround?" - -### 4e — Composition questions (if library interacts with others) - -Use what you discovered in Phase 3h. For each integration target -identified from peer dependencies and example code, ask targeted -questions: - -- "I see [library] is a peer dependency and [N] examples import it - alongside yours. What's the most common integration mistake?" -- "When developers use [your library] with [other library], are there - patterns that only matter when both are present?" -- "I found [specific integration pattern] in the examples. Is this the - recommended approach, or is there a better way that isn't documented?" - ---- - -## Phase 5 — Finalize artifacts - -Merge interview findings into the draft. For each interview answer: - -1. If it confirms a skill or failure mode — no action needed -2. If it corrects something — update the map -3. If it adds a new failure mode — add it with source "maintainer interview" -4. If it reveals a new skill — add it -5. If it fills a gap — remove from gaps section - -Update `status: draft` to `status: reviewed`. - ---- - -## Output artifacts - -If the maintainer uses a custom skills root, replace `skills/` in the paths -below with their chosen directory. - -**Monorepo layout:** For monorepos, domain map artifacts go at the REPO ROOT -(e.g. `_artifacts/domain_map.yaml`) since they describe the whole library. -Skills are generated per-package later by the tree-generator and generate-skill -steps. - -### 1. skills/\_artifacts/domain_map.yaml - -```yaml -# domain_map.yaml -# Generated by skill-domain-discovery -# Library: [name] -# Version: [version this map targets] -# Date: [ISO date] -# Status: [draft | reviewed] - -library: - name: '[package-name]' - version: '[version]' - repository: '[repo URL]' - description: '[one line]' - primary_framework: '[React | Vue | Svelte | framework-agnostic]' - -domains: - - name: '[work-oriented domain name]' - slug: '[kebab-case]' - description: '[conceptual grouping — what a developer is reasoning about]' - -skills: - - name: '[task-focused skill name]' - slug: '[kebab-case]' - domain: '[parent domain slug]' - description: '[what a developer is doing — matches a specific task/moment]' - type: '[core | framework | lifecycle | composition]' - covers: - - '[API/hook/concept 1]' - - '[API/hook/concept 2]' - tasks: - - '[example task 1]' - - '[example task 2]' - - '[example task 3]' - subsystems: # omit if skill has no independent subsystems - - name: '[adapter/backend name]' - package: '[npm package if separate]' - config_surface: '[brief description of unique config]' - reference_candidates: # omit if no dense API surfaces - - topic: '[e.g. query operators, schema validation]' - reason: '[e.g. >10 distinct operators with signatures]' - failure_modes: - - mistake: '[5-10 word phrase]' - mechanism: '[one sentence]' - wrong_pattern: | # the code an agent would incorrectly generate - [short code snippet showing the mistake] - correct_pattern: | # the code that should be generated instead - [short code snippet showing the fix] - source: '[doc page, source file, issue link, or maintainer interview]' - priority: '[CRITICAL | HIGH | MEDIUM]' - status: '[active | fixed-but-legacy-risk | removed]' - version_context: "[e.g. 'Fixed in v5.2 but agents trained on older code still generate this']" - skills: ['[this-skill-slug]'] # list all skills this belongs to; omit if single-skill - compositions: - - library: '[other library name]' - skill: '[composition skill name if applicable]' - -tensions: - - name: '[short phrase describing the pull]' - skills: ['[skill-slug-a]', '[skill-slug-b]'] - description: '[what conflicts — one sentence]' - implication: '[what an agent gets wrong when it only considers one side]' - -cross_references: - - from: '[skill-slug]' - to: '[skill-slug]' - reason: '[why loading one skill benefits from awareness of the other]' - -gaps: - - skill: '[skill slug]' - question: '[what still needs input]' - context: '[why this matters]' - status: '[open | resolved]' -``` - -### 2. skills/\_artifacts/skill_spec.md - -A human-readable companion document. Follow this structure: - -```markdown -# [Library Name] — Skill Spec - -[2–3 sentences: what this library is, what problem it solves. Factual, -not promotional.] - -## Domains - -| Domain | Description | Skills | -| ------ | --------------------- | ----------------------- | -| [name] | [conceptual grouping] | [skill-1, skill-2, ...] | - -## Skill Inventory - -| Skill | Type | Domain | What it covers | Failure modes | -| ------ | -------------------------------------- | -------- | -------------- | ------------- | -| [name] | [core/framework/lifecycle/composition] | [domain] | [list] | [count] | - -## Failure Mode Inventory - -### [Skill name] ([count] failure modes) - -| # | Mistake | Priority | Source | Cross-skill? | -| --- | -------- | -------- | ---------------------- | ------------------------ | -| 1 | [phrase] | CRITICAL | [doc/source/interview] | [other skill slugs or —] | - -[Repeat table for each skill.] - -## Tensions - -| Tension | Skills | Agent implication | -| -------------- | ------------------- | ----------------------- | -| [short phrase] | [slug-a] ↔ [slug-b] | [what agents get wrong] | - -## Cross-References - -| From | To | Reason | -| ------ | ------ | ----------------------------------------- | -| [slug] | [slug] | [why awareness of one improves the other] | - -## Subsystems & Reference Candidates - -| Skill | Subsystems | Reference candidates | -| ------ | ------------------------------ | -------------------------- | -| [slug] | [adapter1, adapter2, ...] or — | [topic needing depth] or — | - -## Remaining Gaps - -| Skill | Question | Status | -| ------ | ------------------------ | ------ | -| [slug] | [what still needs input] | open | - -[Omit this section if all gaps were resolved in the interview.] - -## Recommended Skill File Structure - -- **Core skills:** [list which skills are framework-agnostic] -- **Framework skills:** [list per-framework skills needed] -- **Lifecycle skills:** [list journey/lifecycle skills if applicable] -- **Composition skills:** [list integration seams needing composition skills] -- **Reference files:** [list skills needing references/ based on subsystems - or dense API surfaces] - -## Composition Opportunities - -| Library | Integration points | Composition skill needed? | -| ------- | ------------------ | ----------------------------- | -| [name] | [what interacts] | [yes/no — if yes, skill name] | -``` - ---- - -## Constraints - -| Check | Rule | -| ------------------------------------- | -------------------------------------------------------------------------- | -| Quick scan before interview | Never interview without at least reading README and package structure | -| High-level interview before deep read | The maintainer's task map informs what you read deeply | -| Batch only confirmations | Yes/no questions may batch 2–3; open-ended questions get their own message | -| Questions reference findings | No generic questions — cite what you found | -| Skills are task-focused | Each skill matches a developer moment, not a conceptual area | -| 3+ failure modes per skill | Complex skills target 5–6 | -| Every failure mode sourced | Doc page, source file, issue link, or maintainer interview | -| Gaps are explicit | Unknown areas flagged, not guessed | -| No marketing prose | Library description is factual, not promotional | -| domain_map.yaml is valid YAML | Parseable by any YAML parser | -| Draft before detail interview | Present draft for review before Phase 4 | -| Agent-specific failures probed | Always ask AI-agent-specific questions in Phase 4c | -| Compositions discovered from code | Scan peer deps and examples before asking composition questions | -| Cross-skill failure modes tagged | Failure modes spanning skills list all relevant slugs | -| Tensions identified | 2–4 cross-skill tensions; if none found, revisit skill boundaries | -| Subsystems flagged | Skills with 3+ adapters/backends list them as subsystems | -| Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates | -| Lifecycle skills considered | Suggest journey skills when docs have the material | -| Cross-references mapped | Skills that illuminate each other get "See also" pointers | - ---- - -## Cross-model compatibility notes - -This skill is designed to produce consistent results across Claude, GPT-4+, -Gemini, and open-source models. To achieve this: - -- All instructions use imperative sentences, not suggestions -- Output formats use YAML (universally parsed) and Markdown tables - (universally rendered) -- Examples use concrete values, not placeholders like "[your value here]" -- Section boundaries use Markdown headers (##) for navigation and --- for - phase separation -- No model-specific features (no XML tags in output, no tool_use assumptions) - ---- - -## Meta-skill feedback (alpha default) - -After finalizing artifacts, create or update a single Markdown feedback draft -for all three meta skills used in scaffolding. Use this exact template and -fill only the **Domain Discovery** section now. Leave the other sections in -place for later steps to complete. - -``` -# Intent Meta Skill Feedback - -## Domain Discovery -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Tree Generator -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Generate Skill -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Context (optional) -- Library: -- Repo: -- Docs: -- Notes: -``` - -Do not submit feedback yet. Tell the maintainer to carry this draft forward -to the next meta skill step. +--- +name: skill-domain-discovery +description: > + Analyze library documentation and source code, then interview maintainers + to discover capability domains and task-focused skills for AI coding + agents. Activate when creating skills for a new library, organizing + existing documentation into skill categories, or when a maintainer wants + help deciding how to structure their library's agent-facing knowledge. + Produces a domain_map.yaml and skill_spec.md that feed directly into + the skill-tree-generator skill. +metadata: + version: '3.0' + category: meta-tooling + output_artifacts: + - skills/_artifacts/domain_map.yaml + - skills/_artifacts/skill_spec.md + skills: + - tree-generator +--- + +# Domain Discovery & Maintainer Interview + +You are extracting domain knowledge for a library to produce a structured +domain map. Your job is not to summarize documentation — it is to build a +deep understanding of the library first, then use that understanding to +surface the implicit knowledge that maintainers carry but docs miss. + +The output is a set of **task-focused skills** — each one matching a +specific developer moment ("implement a proxy", "set up auth", "audit +before launch"). Domains are an intermediate conceptual grouping you use +during analysis; the final skills emerge from the intersection of domains +and developer tasks. + +There are five phases. Always run them in order — unless the lightweight +path applies (see below). + +1. **Quick scan** — orient yourself (autonomous) +2. **High-level interview** — extract the maintainer's task map +3. **Deep read** — fill in failure modes and detail (autonomous) +4. **Detail interview** — gap-targeted questions, AI-agent failures +5. **Finalize artifacts** + +### Lightweight path (small libraries) + +After Phase 1, if the library has **fewer than 5 client-facing skill +areas** (e.g. a focused utility library, a single-purpose tool, or a +library with only 2–3 distinct developer tasks), use a compressed flow: + +1. **Phase 1** — Quick scan (same as full flow) +2. **Phase 2+4 combined** — Single interview round. Combine the + high-level task map questions (Phase 2) with gap-targeted and + AI-agent-specific questions (Phase 4) into one interview session + of 4–8 questions total. Skip the draft-review step since the skill + set is small enough to confirm in one pass. +3. **Phase 3** — Deep read (same as full flow, but scope is smaller) +4. **Phase 5** — Finalize artifacts (same as full flow) + +The lightweight path produces identical output artifacts (domain_map.yaml +and skill_spec.md). It just avoids two separate interview rounds when the +library is small enough that one round covers everything. +### Hard rules — interview phases are mandatory and interactive + +These rules override any other reasoning. No exceptions. + +1. **Phases 2 and 4 are interactive interviews conducted with the + maintainer.** You must ask the questions specified in each sub-section + and wait for the maintainer's response before continuing. Documentation, + source code, and other automated analysis are NOT substitutes for the + maintainer's answers. +2. **Every question in Phases 2 and 4 must be asked as an open-ended + question and sent as a message to the maintainer.** You must then + STOP and WAIT for their reply. Do not answer your own questions. Do + not infer answers from documentation. Do not skip questions because + you believe you already know the answer. +3. **Do not convert open-ended questions into multiple-choice, + yes/no, or confirmation prompts.** The question templates in each + sub-section are open-ended by design. Present them as open-ended + questions. The maintainer's unprompted answers surface knowledge that + pre-structured options suppress. +4. **Minimum question counts are enforced.** Each sub-section specifies + a question count range (e.g. "2–4 questions"). You must ask at least + the minimum number. Asking zero questions in any sub-section is a + protocol violation. +5. **STOP gates are mandatory.** At the boundaries marked `── STOP ──` + below, you must halt execution and wait for the maintainer's response + or acknowledgment before proceeding. Do not continue past a STOP gate + in the same message. +6. **If the maintainer asks to skip an interview phase**, explain the + value of the phase and what will be lost. Proceed with skipping only + if they confirm a second time. +7. **Rich documentation makes interviews MORE valuable, not less.** + When docs are comprehensive, the interview surfaces what docs miss: + implicit knowledge, AI-specific failure modes, undocumented tradeoffs, + and the maintainer's prioritization of what matters most. Never + rationalize skipping interviews because documentation is thorough. + +--- + +## Phase 1 — Quick scan (autonomous, ~10 minutes) + +Orient yourself in the library. You are building a structural map, not +reading exhaustively yet. + +### 1a — Read orientation material + +1. **README** — vocabulary, mental model, what the library does +2. **Getting started / quickstart** — the happy path +3. **Package structure** — if monorepo, identify which packages are + client-facing vs internal. Focus on the 2–3 packages most relevant + to skill consumers (usually client SDKs and primary framework adapters) +4. **AGENTS.md or .cursorrules** — if the library already has agent + guidance, read it. This is high-signal for what the maintainer + considers important + +### 1b — Read peer dependency constraints + +Check `package.json` for `peerDependencies` and `peerDependenciesMeta`. +For each major peer dependency (React, Vue, Svelte, Next.js, etc.): + +1. Note the version range required +2. Read the peer's docs for integration constraints that affect this + library: SSR/hydration rules, component lifecycle boundaries, + browser-only APIs, singleton patterns, connection limits +3. Log framework-specific failure modes — these are the highest-impact + failure modes and cannot be discovered from the library's own source + +Examples of peer-dependency-driven failure modes: + +- SSR: calling browser-only APIs during server render +- React: breaking hook rules in library wrapper components +- Connection limits: opening multiple WebSocket connections per tab +- Singleton patterns: creating multiple client instances in dev mode + +### 1c — Note initial impressions + +Log (but do not group yet): + +- What the library does in one sentence +- The core abstractions a developer interacts with +- Which frameworks it supports +- Any existing skill files, agent configs, or intents +- Whether the library is a monorepo and which packages matter +- Peer dependency constraints — read `peerDependencies` and + `peerDependenciesMeta` from each client-facing package.json to + understand version ranges and optional integrations early + +Present your initial impressions to the maintainer as a brief summary +(3–5 bullets). This orients them on what you found and primes them for +the interview. + +**── STOP ── Do not proceed to Phase 2 until the maintainer has +acknowledged your summary or responded.** + +--- + +## Phase 2 — High-level interview (interactive — requires maintainer) + +The maintainer's mental model of developer tasks IS the skill map. Your +job in this phase is to extract it — not to propose your own structure. + +You must ask the questions below to the maintainer and wait for their +responses. Do not infer answers from documentation or source code. + +### Rules for Phase 2 + +1. One topic per message for open-ended questions. You may batch 2–3 + yes/no or short-confirmation questions together. +2. Ask each question as written (you may adapt phrasing to context, but + keep questions open-ended — never convert to multiple-choice). +3. Wait for the maintainer's response after each question before asking + the next. +4. Take notes silently. Do not summarize back unless asked. +5. If the maintainer gives a short answer, probe deeper before moving on. + +### 2a — Developer tasks (2–4 questions) + +Start with the maintainer's view of what developers do: + +> "Walk me through what a developer actually does with your library — +> not the elevator pitch, but the tasks they come to you for help with, +> from first install through production." + +Follow up to enumerate distinct tasks: + +> "If you listed every distinct thing a developer asks an agent to help +> with using your library, what would that list look like? I'm thinking +> things like 'set up the client', 'implement auth', 'debug sync issues' +> — each one a separate moment where they'd want focused guidance." + +For monorepo libraries, also ask about cross-package tasks: + +> "Are there tasks that touch multiple packages in your monorepo? For +> example, a getting-started flow that requires imports from both the +> client and server packages? I want to make sure skills that span +> package boundaries are captured correctly." + +### 2b — Developer journeys (1–2 questions) + +Surface lifecycle/journey skills that cross-cut task areas: + +> "Are there developer journeys that cut across multiple features? +> For example: a getting-started guide, a go-to-production checklist, +> a migrate-from-v4 walkthrough. Which of these exist in your docs +> or would be valuable as standalone skills?" + +### 2c — Composition and ecosystem (1–2 questions) + +> "Which other libraries does yours compose with most often? Are there +> integration patterns important enough to warrant their own skill — +> for example, using your library with [framework/ORM/router]?" + +### 2d — Confirm initial skill map + +Synthesize what you heard into a proposed skill list and present it: + +> "Based on what you've told me, here's my proposed skill list: +> [enumerate skills with one-line descriptions]. Does this match how +> you think about your library? What would you add, remove, or rename?" + +**── STOP ── Do not proceed to Phase 3 until the maintainer has +reviewed and confirmed (or corrected) the skill list.** + +--- + +## Phase 3 — Deep read (autonomous) + +You now have the maintainer's task map. Read docs and source to fill +each skill area with concrete content — failure modes, code patterns, +gotchas. + +### Reading order + +Read in this order. Each step builds context for the next. + +Before starting, list every file in the docs directory (and subdirectories). +Use this list as a checklist — every narrative file must be read. Do not +sample a subset and extrapolate. + +1. **Every narrative guide** — the how-to content, not API reference tables. + Read every guide file, not a representative sample. +2. **Migration guides** — highest-yield source for failure modes; every + breaking change is exactly what agents trained on older versions produce +3. **API reference** — scan for exports, type signatures, option shapes +4. **Changelog for major versions** — API renames, removed exports, + behavioral changes +5. **GitHub issues and discussions** — scan for frequently reported + confusion, common misunderstandings, recurring questions. Also look + for what users are implicitly arguing for architecturally — not just + "people are confused about X" but "users keep expecting X to work + like Y, which reveals a tension between [design force] and [design force]." + If no web access, check for FAQ.md, TROUBLESHOOTING.md, or docs/faq + as proxies. +6. **Source code** — verify ambiguities from docs, check defaults, find + assertions and invariant checks. For monorepos, read the 2–3 core + packages deeply. For adapter packages, read one representative adapter + deeply, then scan others for deviations from the pattern. + +### What to log + +Produce a flat concept inventory. One item per line. No grouping yet. + +Log every: + +- Named concept, abstraction, or lifecycle stage +- Public export: function, hook, class, type, constant +- Configuration key, its type, and its default value +- Constraint or invariant (especially any enforced by `throw` or assertion) +- Doc callout: any "note", "warning", "caution", "important", "avoid", "do not" +- Dual API: any place the library has two ways to do the same thing (old/new, + verbose/shorthand, lower-level/higher-level) +- Environment branch: any place behavior depends on SSR/CSR, dev/prod, + framework, bundler, or config flag +- Type gap: any type documented as accepting X but source shows X | Y or + rejects a subtype of X +- Source assertion: any `if (!x) throw`, `invariant()`, or `assert()` with + the error message text + +### What to extract from migration guides specifically + +For each breaking change between major versions: + +``` +Old pattern: [code that agents trained on older versions will produce] +New pattern: [current correct code] +What changed: [one sentence — the specific mechanism] +Version boundary: [e.g. "v4 → v5"] +``` + +These become high-priority failure modes. + +### 3a — Group concepts into domains + +Move concept inventory items into groups. Two items belong together when: + +- A developer reasons about them together when solving a problem +- Solving one correctly requires understanding how the other works +- They share a lifecycle, configuration scope, or architectural tradeoff +- Getting one wrong tends to produce bugs in the other + +Let library complexity drive the domain count — a focused library may need +only 2–3 domains, while a large framework may need 7+. Validate by asking: +"Would a developer working on a single feature need to load skills from +multiple domains? If so, merge those domains." These are conceptual +groupings, not the final skills. + +Do not create a group for: + +- A single hook, function, or class +- A single doc or reference page +- "Miscellaneous", "Advanced", or "Other" +- Configuration knobs that only affect another group's behavior + +Name each domain as work being performed, not what the library provides. + +**Validation step:** After grouping, check each domain by asking: +"Would a developer working on a single feature need to load skills from +multiple domains?" If yes, merge those domains. Group by developer tasks +(what they're trying to accomplish), not by architecture (how the library +is organized internally). For example, prefer "writing data" over +"producer lifecycle" — the former matches a developer's intent, the latter +matches the codebase structure. + +### 3b — Map domains × tasks → skills + +Merge your conceptual domains with the maintainer's task list from +Phase 2. Each skill should match a specific developer moment while +carrying the conceptual depth of its parent domain(s). + +A skill is well-shaped when: + +- A developer would ask for it by name ("help me set up sync") +- It covers enough for the agent to complete the task end-to-end +- It doesn't require loading 3 other skills to be useful + +Some domains produce multiple skills (a broad domain like "data access" +might yield "live-queries", "mutations", "offline-sync"). Some tasks +span domains (a "go-live" checklist touches security, performance, and +configuration). Both are fine. + +Also consider: + +- **Lifecycle/journey skills** — if the library's docs include a + quickstart guide, go-to-production checklist, or migration path, + suggest these as standalone skills. Don't force them if the docs + don't have the material. +- **Composition skills** — when peer deps or examples show consistent + co-usage with another library, output a full skill for the + integration, not a footnote on a domain. + +### 3c — Flag subsystems within skills + +Check each skill area for internal diversity. A skill may be +conceptually unified but contain multiple independent subsystems with +distinct config interfaces — for example, 5 sync adapters that all +solve "connectivity" but each with unique setup, options, and failure +modes. + +For each skill, ask: "Does this cover 3+ backends, adapters, drivers, +or providers with distinct configuration surfaces?" If yes, list them +as `subsystems`. These tell the skill-tree-generator to produce +per-subsystem reference files. + +Also flag dense API surfaces — if a topic has >10 distinct operators, +option shapes, or patterns (e.g. query operators, schema validation +rules), note it as a `reference_candidates` entry. + +### 3d — Extract failure modes + +For each skill, extract failure modes that pass all three tests: + +- **Plausible** — An agent would generate this because it looks correct + based on the library's design, a similar API, or an older version +- **Silent** — No immediate crash; fails at runtime or under specific conditions +- **Grounded** — Traceable to a specific doc page, source location, or issue + +**Where to find them:** + +| Source | What to extract | +| -------------------- | ------------------------------------------------------------------ | +| Migration guides | Every breaking change → old pattern is the wrong code | +| Doc callouts | Any "note", "warning", "avoid" with surrounding context | +| Source assertions | `throw` and `invariant()` messages describe the failure | +| Default values | Undocumented or surprising defaults that cause wrong behavior | +| Type precision | Source type more restrictive than docs imply | +| Environment branches | `typeof window`, SSR flags, `NODE_ENV` — behavior differs silently | + +Target 3 failure modes per skill minimum. Complex skills target 5–6. + +**Code patterns.** Every failure mode should include `wrong_pattern` and +`correct_pattern` fields with short code snippets (3–10 lines each). +The wrong pattern is what an agent would generate; the correct pattern +is the fix. These feed directly into SKILL.md Common Mistakes sections +as wrong/correct code pairs. If the failure mode is purely conceptual +(e.g. an architectural choice) rather than a code pattern, omit both +fields and explain in `mechanism` instead. + +**Cross-skill failure modes.** Some failure modes belong to multiple +skills. A developer doing SSR work and a developer doing state management +both need to know about "stale state during hydration" — they load +different skills but need the same advice. When a failure mode spans +skills, list all relevant skill slugs in its `skills` field. The +skill-tree-generator will write it into every corresponding SKILL file. + +List a cross-skill failure mode once, under its primary skill. Set +the `skills` field to all skill slugs it applies to. Do not duplicate +the entry in the YAML — the skill-tree-generator handles duplication +into multiple SKILL files at generation time. + +### 3e — Identify cross-skill tensions + +Look for places where design forces between skills conflict. A tension +is not a failure mode — it's a structural pull where optimizing for one +task makes another harder. Examples: + +- "Getting-started simplicity conflicts with production operational safety" +- "Type-safety strictness conflicts with rapid prototyping flexibility" +- "SSR correctness requires patterns that hurt client-side performance" + +Tensions are where agents fail most because they optimize for one task +without seeing the tradeoff. Each tension should name the skills in +conflict, describe the pull, and state what an agent gets wrong when it +only considers one side. + +Target 2–4 tensions. If you find none, the skills may be too isolated — +revisit whether you're missing cross-connections. + +### 3f — Map cross-references + +Beyond tensions (conflicts) and shared failure modes, identify skills +that illuminate each other without conflicting. A cross-reference means: +"an agent loading skill A would produce better code if it knew about +skill B." These become "See also" pointers in the generated SKILL.md +files. + +For each pair, note: + +- Which skill references which (can be bidirectional) +- Why awareness of the other skill improves output + +Examples: + +- A quickstart skill references the security checklist ("after setup, audit") +- A state management skill references an SSR skill ("state hydration + requires understanding SSR lifecycle") +- A data writing skill references a data reading skill ("writes affect + how queries invalidate") + +Output these in the `cross_references` section of domain_map.yaml. + +### 3g — Identify gaps + +For each skill, explicitly list what you could NOT determine from docs +and source alone. These become interview questions in Phase 4. + +Common gaps: + +- "Docs describe X but don't explain when you'd choose X over Y" +- "Migration guide mentions this changed but doesn't say what the old + behavior was" +- "Source has an assertion here but no doc explains what triggers it" +- "GitHub issues show confusion about X but docs don't address it" +- "I found two patterns for doing X — unclear which is current/preferred" + +### 3h — Discover composition targets + +Scan `package.json` for peer dependencies, optional dependencies, and +`peerDependenciesMeta`. Scan example directories and integration tests +for import patterns. For each frequently co-used library, log: + +- Library name and which features interact +- Whether it's a required or optional integration +- Any example code showing the integration pattern + +These become targeted composition questions in Phase 4e. + +### 3i — Produce the draft + +Write the full `domain_map.yaml` (format in Output Artifacts below) with +a `status: draft` field. Flag every gap in the `gaps` section. + +Present the draft to the maintainer before starting Phase 4: + +> "I've read the docs and source for [library] and produced a draft with +> [N] skills and [M] failure modes. I've flagged [K] specific gaps where +> I need your input." + +Include the full draft domain_map.yaml in your message so the maintainer +can review it. Also include a checklist of all docs files you read. + +**── STOP ── Do not proceed to Phase 4 until the maintainer has +reviewed the draft and responded. Their feedback on the draft informs +the detail interview questions.** + +--- + +## Phase 4 — Detail interview (interactive — requires maintainer) + +You have the maintainer's task map and a deep read. The interview now +fills gaps, validates your understanding, and surfaces implicit knowledge. + +You must ask the questions below to the maintainer and wait for their +responses. Do not infer answers from documentation or source code — +even for gaps you think you can answer from your reading. + +### Rules for Phase 4 + +1. One topic per message for open-ended questions. You may batch 2–3 + yes/no or short-confirmation questions together. +2. Ask each question as written (you may adapt phrasing to context, but + keep questions open-ended — never convert to multiple-choice). +3. Each question must reference something specific from your reading. +4. Wait for the maintainer's response after each question before asking + the next. +5. If the maintainer gives a short answer, probe deeper before moving on. +6. Take notes silently. Do not summarize back unless asked. + +### 4a — Draft review (2–3 questions) + +Start by confirming or correcting your skill list and failure modes: + +> "Here's the skill list I've built from our earlier conversation plus +> the deep read: [list skills with brief descriptions]. Does this still +> match your thinking? Anything to add, remove, or rename?" + +Follow up on any corrections. Then: + +> "I identified [M] failure modes from the docs and migration guides. Are +> there important ones I missed — especially patterns that look correct +> but fail silently?" + +### 4b — Gap-targeted questions (3–8 questions) + +For each gap flagged in Phase 3g, ask a specific question. These are not +generic — they reference what you found: + +**Instead of:** "What do developers get wrong?" +**Ask:** "I noticed the migration guide from v4 to v5 changed how [X] works, +but the docs don't show the old pattern. Do agents still commonly generate +the v4 pattern? What does it look like?" + +**Instead of:** "Are there surprising interactions?" +**Ask:** "The source throws an invariant error if [X] is called before [Y], +but the docs don't mention ordering. How often do developers hit this?" + +**Instead of:** "What's different in SSR vs client?" +**Ask:** "I found a `typeof window` check in [file] that changes behavior +for [feature]. What goes wrong when developers test only in the browser +and deploy with SSR?" + +Adapt from this bank of gap-targeted question templates: + +- "I found two patterns for [X] in the docs — [pattern A] and [pattern B]. + Which is current, and does the old one still work?" +- "The source defaults [config option] to [value], which seems surprising + for [reason]. Is this intentional? Do developers need to override it?" +- "GitHub issues show [N] reports of confusion about [X]. What's the + underlying misunderstanding?" +- "I couldn't find docs for how [feature A] interacts with [feature B]. + What should an agent know about using them together?" +- "The API reference shows [type signature], but the guide examples use + a different shape. Which is accurate?" + +### 4c — AI-agent-specific failure modes (2–4 questions) + +These target mistakes that AI coding agents make but human developers +typically don't. Agent-specific failures are often the highest-value +findings — in testing, maintainer answers to these questions produced +the most critical failure modes. + +- "What mistakes would an AI coding agent make that a human developer + wouldn't? Think about: hallucinating APIs that don't exist, defaulting + to language primitives instead of library abstractions, choosing the + wrong adapter or integration path." +- "When an agent generates code using your library, what's the first + thing you'd check? What pattern would make you immediately say + 'an AI wrote this'?" +- "Are there parts of your API where the naming or design is misleading + enough that an agent with no prior context would pick the wrong + approach? What would it pick, and what should it pick instead?" +- "Are there features where the docs are comprehensive for human + developers but would still mislead an agent? For example, features + that require understanding unstated context, or where the 'obvious' + approach from reading the API surface is wrong." + +### 4d — Implicit knowledge extraction (3–5 questions) + +These surface knowledge that doesn't appear in any docs: + +- "What does a senior developer using your library know that a mid-level + developer doesn't — something that isn't written down anywhere?" +- "Are there patterns that work fine for prototyping but are dangerous + in production? What makes them dangerous?" +- "What question do you answer most often in Discord or GitHub issues + that the docs technically cover but people still miss?" +- "Is there anything you'd change about the API design if you could break + backwards compatibility? What's the current workaround?" + +### 4e — Composition questions (if library interacts with others) + +Use what you discovered in Phase 3h. For each integration target +identified from peer dependencies and example code, ask targeted +questions: + +- "I see [library] is a peer dependency and [N] examples import it + alongside yours. What's the most common integration mistake?" +- "When developers use [your library] with [other library], are there + patterns that only matter when both are present?" +- "I found [specific integration pattern] in the examples. Is this the + recommended approach, or is there a better way that isn't documented?" + +--- + +## Phase 5 — Finalize artifacts + +Merge interview findings into the draft. For each interview answer: + +1. If it confirms a skill or failure mode — no action needed +2. If it corrects something — update the map +3. If it adds a new failure mode — add it with source "maintainer interview" +4. If it reveals a new skill — add it +5. If it fills a gap — remove from gaps section + +Update `status: draft` to `status: reviewed`. + +--- + +## Output artifacts + +If the maintainer uses a custom skills root, replace `skills/` in the paths +below with their chosen directory. + +**Monorepo layout:** For monorepos, domain map artifacts go at the REPO ROOT +(e.g. `_artifacts/domain_map.yaml`) since they describe the whole library. +Skills are generated per-package later by the tree-generator and generate-skill +steps. + +### 1. skills/\_artifacts/domain_map.yaml + +```yaml +# domain_map.yaml +# Generated by skill-domain-discovery +# Library: [name] +# Version: [version this map targets] +# Date: [ISO date] +# Status: [draft | reviewed] + +library: + name: '[package-name]' + version: '[version]' + repository: '[repo URL]' + description: '[one line]' + primary_framework: '[React | Vue | Svelte | framework-agnostic]' + +domains: + - name: '[work-oriented domain name]' + slug: '[kebab-case]' + description: '[conceptual grouping — what a developer is reasoning about]' + +skills: + - name: '[task-focused skill name]' + slug: '[kebab-case]' + domain: '[parent domain slug]' + description: '[what a developer is doing — matches a specific task/moment]' + type: '[core | framework | lifecycle | composition]' + packages: # required for monorepo; omit for single-package libraries + - '[primary package name]' + - '[secondary package name, if skill spans multiple packages]' + covers: + - '[API/hook/concept 1]' + - '[API/hook/concept 2]' + tasks: + - '[example task 1]' + - '[example task 2]' + - '[example task 3]' + subsystems: # omit if skill has no independent subsystems + - name: '[adapter/backend name]' + package: '[npm package if separate]' + config_surface: '[brief description of unique config]' + reference_candidates: # omit if no dense API surfaces + - topic: '[e.g. query operators, schema validation]' + reason: '[e.g. >10 distinct operators with signatures]' + failure_modes: + - mistake: '[5-10 word phrase]' + mechanism: '[one sentence]' + wrong_pattern: | # the code an agent would incorrectly generate + [short code snippet showing the mistake] + correct_pattern: | # the code that should be generated instead + [short code snippet showing the fix] + source: '[doc page, source file, issue link, or maintainer interview]' + priority: '[CRITICAL | HIGH | MEDIUM]' + status: '[active | fixed-but-legacy-risk | removed]' + version_context: "[e.g. 'Fixed in v5.2 but agents trained on older code still generate this']" + skills: ['[this-skill-slug]'] # list all skills this belongs to; omit if single-skill + compositions: + - library: '[other library name]' + skill: '[composition skill name if applicable]' + +tensions: + - name: '[short phrase describing the pull]' + skills: ['[skill-slug-a]', '[skill-slug-b]'] + description: '[what conflicts — one sentence]' + implication: '[what an agent gets wrong when it only considers one side]' + +cross_references: + - from: '[skill-slug]' + to: '[skill-slug]' + reason: '[why loading one skill benefits from awareness of the other]' + +gaps: + - skill: '[skill slug]' + question: '[what still needs input]' + context: '[why this matters]' + status: '[open | resolved]' +``` + +### 2. skills/\_artifacts/skill_spec.md + +A human-readable companion document. Follow this structure: + +```markdown +# [Library Name] — Skill Spec + +[2–3 sentences: what this library is, what problem it solves. Factual, +not promotional.] + +## Domains + +| Domain | Description | Skills | +| ------ | --------------------- | ----------------------- | +| [name] | [conceptual grouping] | [skill-1, skill-2, ...] | + +## Skill Inventory + +| Skill | Type | Domain | What it covers | Failure modes | +| ------ | -------------------------------------- | -------- | -------------- | ------------- | +| [name] | [core/framework/lifecycle/composition] | [domain] | [list] | [count] | + +## Failure Mode Inventory + +### [Skill name] ([count] failure modes) + +| # | Mistake | Priority | Source | Cross-skill? | +| --- | -------- | -------- | ---------------------- | ------------------------ | +| 1 | [phrase] | CRITICAL | [doc/source/interview] | [other skill slugs or —] | + +[Repeat table for each skill.] + +## Tensions + +| Tension | Skills | Agent implication | +| -------------- | ------------------- | ----------------------- | +| [short phrase] | [slug-a] ↔ [slug-b] | [what agents get wrong] | + +## Cross-References + +| From | To | Reason | +| ------ | ------ | ----------------------------------------- | +| [slug] | [slug] | [why awareness of one improves the other] | + +## Subsystems & Reference Candidates + +| Skill | Subsystems | Reference candidates | +| ------ | ------------------------------ | -------------------------- | +| [slug] | [adapter1, adapter2, ...] or — | [topic needing depth] or — | + +## Remaining Gaps + +| Skill | Question | Status | +| ------ | ------------------------ | ------ | +| [slug] | [what still needs input] | open | + +[Omit this section if all gaps were resolved in the interview.] + +## Recommended Skill File Structure + +- **Core skills:** [list which skills are framework-agnostic] +- **Framework skills:** [list per-framework skills needed] +- **Lifecycle skills:** [list journey/lifecycle skills if applicable] +- **Composition skills:** [list integration seams needing composition skills] +- **Reference files:** [list skills needing references/ based on subsystems + or dense API surfaces] + +## Composition Opportunities + +| Library | Integration points | Composition skill needed? | +| ------- | ------------------ | ----------------------------- | +| [name] | [what interacts] | [yes/no — if yes, skill name] | +``` + +--- + +## Constraints + +| Check | Rule | +| ------------------------------------- | -------------------------------------------------------------------------- | +| Quick scan before interview | Never interview without at least reading README and package structure | +| High-level interview before deep read | The maintainer's task map informs what you read deeply | +| **Interview phases are interactive** | Phases 2 and 4 require sending questions to the maintainer and waiting | +| **Docs are not a substitute** | Documentation cannot replace maintainer answers — even comprehensive docs | +| **Open-ended questions stay open** | Never convert interview questions to multiple-choice or yes/no | +| **Minimum question counts enforced** | Each sub-section's minimum count must be met; zero questions = violation | +| **STOP gates are mandatory** | Do not proceed past a STOP gate without maintainer response | +| Batch only confirmations | Yes/no questions may batch 2–3; open-ended questions get their own message | +| Questions reference findings | No generic questions — cite what you found | +| Skills are task-focused | Each skill matches a developer moment, not a conceptual area | +| 3+ failure modes per skill | Complex skills target 5–6 | +| Every failure mode sourced | Doc page, source file, issue link, or maintainer interview | +| Gaps are explicit | Unknown areas flagged, not guessed | +| No marketing prose | Library description is factual, not promotional | +| domain_map.yaml is valid YAML | Parseable by any YAML parser | +| Draft before detail interview | Present draft for review before Phase 4 | +| **Draft reviewed before Phase 4** | Maintainer must acknowledge or respond to draft before detail interview | +| Agent-specific failures probed | Always ask AI-agent-specific questions in Phase 4c | +| Compositions discovered from code | Scan peer deps and examples before asking composition questions | +| Cross-skill failure modes tagged | Failure modes spanning skills list all relevant slugs | +| Tensions identified | 2–4 cross-skill tensions; if none found, revisit skill boundaries | +| Subsystems flagged | Skills with 3+ adapters/backends list them as subsystems | +| Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates | +| Lifecycle skills considered | Suggest journey skills when docs have the material | +| Cross-references mapped | Skills that illuminate each other get "See also" pointers | +| **All docs files read** | List docs directory contents and read every narrative file — no sampling | + +--- + +## Cross-model compatibility notes + +This skill is designed to produce consistent results across Claude, GPT-4+, +Gemini, and open-source models. To achieve this: + +- All instructions use imperative sentences, not suggestions +- Interview phases use explicit STOP gates to prevent models from + continuing autonomously past interactive checkpoints +- Hard rules at the top override any model tendency to rationalize + skipping interactive phases when documentation is available +- Open-ended questions are explicitly protected from conversion to + multiple-choice or confirmation prompts, which models default to + when they have enough context to pre-populate answers +- Output formats use YAML (universally parsed) and Markdown tables + (universally rendered) +- Examples use concrete values, not placeholders like "[your value here]" +- Section boundaries use Markdown headers (##) for navigation and --- for + phase separation +- No model-specific features (no XML tags in output, no tool_use assumptions) + +--- + +## Meta-skill feedback (mandatory — do not skip) + +**This step is required.** Agents routinely skip feedback collection +because it appears at the end of the skill. You must complete this step +before the domain discovery process is considered finished. + +After finalizing artifacts, ask the maintainer for feedback on the domain +discovery process. Do not silently create the feedback template — present +it to the maintainer and ask them to fill in the Domain Discovery section. + +**── STOP ── Ask the maintainer to provide feedback. Wait for their +response before writing the feedback file.** + +Create or update a single Markdown feedback draft +for all three meta skills used in scaffolding. Use this exact template and +fill only the **Domain Discovery** section now. Leave the other sections in +place for later steps to complete. + +``` +# Intent Meta Skill Feedback + +## Domain Discovery +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Tree Generator +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Generate Skill +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Context (optional) +- Library: +- Repo: +- Docs: +- Notes: +``` + +Do not submit feedback yet. Tell the maintainer to carry this draft forward +to the next meta skill step. diff --git a/packages/intent/meta/feedback-collection/SKILL.md b/packages/intent/meta/feedback-collection/SKILL.md index d3704a74..d426aabd 100644 --- a/packages/intent/meta/feedback-collection/SKILL.md +++ b/packages/intent/meta/feedback-collection/SKILL.md @@ -1,188 +1,188 @@ ---- -name: skill-feedback-collection -description: > - Collect structured feedback about skill usage after completing a coding task. - Activate at the end of any session where one or more SKILL.md files were - loaded. Captures agent signals (gaps, errors, corrections, human interventions) - and brief human input, then submits directly via gh CLI or provides manual - submission instructions. -metadata: - version: '2.0' - category: meta-tooling ---- - -# Skill Feedback Collection - -Run this at the end of any session where you loaded one or more SKILL.md files. -The goal is to capture what worked, what didn't, and what was missing — so skill -maintainers can improve future versions. - ---- - -## Phase 1 — Automated Signal Collection - -Review your own session transcript. No human interaction needed yet. - -### 1a: Gap detection - -Identify moments where the skill was silent and you had to bridge the gap -yourself — via code reading, search, trial-and-error, or general knowledge. - -For each gap, note: - -- What you needed to do -- What the skill should have told you -- How you solved it (code reading, web search, guessing) - -### 1b: Error/correction tracking - -Identify moments where the skill prescribed an approach that produced an error. - -For each error, note: - -- What the skill said to do -- The error or incorrect behavior that resulted -- The fix you applied - -### 1c: Human intervention events - -Identify moments where the human clarified, corrected, or overrode your approach. - -For each intervention, note: - -- What you were doing when the human intervened -- What the human said or changed -- Whether the skill could have prevented this - -### 1d: Step duration anomalies - -Identify steps that consumed disproportionate effort compared to their apparent -complexity. These signal that the skill should provide a template, snippet, or -more detailed guidance. - ---- - -## Phase 2 — Human Interview - -Ask the human up to 4 questions. Keep it brief — skip questions if the session -already provided clear answers. Respect if they decline. - -1. "Was anything unclear about what was happening during the task?" -2. "Did anything feel frustrating or take longer than expected?" -3. "Were you uncertain about the output quality at any point?" -4. "Anything you'd want done differently next time?" - -Derive `userRating` from overall sentiment: - -- Mostly positive → `good` -- Mixed signals → `mixed` -- Mostly negative → `bad` - -If the human gives an explicit rating, use that instead. - ---- - -## Phase 3 — Build the Feedback - -Write one Markdown feedback file per skill used. Only include skills that were -actually used during the session — skip any that were loaded but never -referenced. - -### Template - -```markdown -# Skill Feedback: [skill name from SKILL.md frontmatter] - -**Package:** [npm package name that contains the skill] -**Skill version:** [metadata.version or library_version from frontmatter] -**Rating:** [good | mixed | bad] - -## Task - -[one-sentence summary of what the human asked you to do] - -## What Worked - -[patterns/instructions from the skill that were accurate and helpful] - -## What Failed - -[from 1b — skill instructions that produced errors] - -## Missing - -[from 1a — gaps where the skill should have covered] - -## Self-Corrections - -[from 1b fixes + 1c human interventions, combined] - -## User Comments - -[optional — direct quotes or paraphrased human input from Phase 2] -``` - -### Field derivation guide - -| Field | Source | -| ---------------- | ------------------------------------------------------------------ | -| Skill name | Frontmatter `name` field of the SKILL.md you loaded | -| Package | The npm package the skill lives in (e.g. `@tanstack/query-intent`) | -| Skill version | Frontmatter `metadata.version` or `library_version` | -| Task | Summarize the human's original request in one sentence | -| What Worked | List skill sections/patterns that were correct and useful | -| What Failed | From 1b — skill instructions that produced errors | -| Missing | From 1a — gaps where the skill was silent | -| Self-Corrections | From 1b fixes + 1c human interventions, combined | -| Rating | From Phase 2 sentiment analysis or explicit rating | -| User Comments | From Phase 2 answers, keep brief | - ---- - -## Phase 4 — Submit - -Determine the target repo from the skill's package. The repo is typically -derivable from the `repository` field in the package's `package.json`, or -from the `sources` field in the SKILL.md frontmatter. - -### Privacy check - -Before submitting, determine whether the user's project is public or private. -Check with `gh repo view --json visibility` or look for a `private` field in -the project's `package.json`. If you can't determine visibility, assume private. - -**Private repos:** Feedback is submitted to a public issue tracker, so it must -not contain project-specific details. Before submission: - -1. Strip any project-specific code, file paths, internal API names, service - URLs, or business logic from all fields -2. Rewrite the "Task" field to describe the _type_ of task generically - (e.g. "set up authenticated data fetching" not "set up auth for our - internal billing API at api.acme.corp/billing") -3. Rewrite "What Failed" and "Missing" entries to reference only the - skill's own APIs and patterns, not the user's code -4. Show the sanitized feedback to the user and ask them to confirm it's - safe to submit before proceeding - -**Public repos:** No sanitization needed. Proceed directly to submission. - -### If `gh` CLI is available - -Submit directly as a GitHub issue: - -```bash -gh issue create --repo [owner/repo] --title "Skill Feedback: [skill-name] ([rating])" --label "feedback:[skill-name]" --body-file intent-feedback.md -``` - -If the label doesn't exist, omit the `--label` flag — don't let a missing -label block submission. - -If submission succeeds, delete the feedback file. - -### If `gh` CLI is not available - -Tell the human: - -> "I've written skill feedback to `intent-feedback.md`. To submit it, -> open an issue at https://github.com/[owner/repo]/issues and paste the -> contents." +--- +name: skill-feedback-collection +description: > + Collect structured feedback about skill usage after completing a coding task. + Activate at the end of any session where one or more SKILL.md files were + loaded. Captures agent signals (gaps, errors, corrections, human interventions) + and brief human input, then submits directly via gh CLI or provides manual + submission instructions. +metadata: + version: '2.0' + category: meta-tooling +--- + +# Skill Feedback Collection + +Run this at the end of any session where you loaded one or more SKILL.md files. +The goal is to capture what worked, what didn't, and what was missing — so skill +maintainers can improve future versions. + +--- + +## Phase 1 — Automated Signal Collection + +Review your own session transcript. No human interaction needed yet. + +### 1a: Gap detection + +Identify moments where the skill was silent and you had to bridge the gap +yourself — via code reading, search, trial-and-error, or general knowledge. + +For each gap, note: + +- What you needed to do +- What the skill should have told you +- How you solved it (code reading, web search, guessing) + +### 1b: Error/correction tracking + +Identify moments where the skill prescribed an approach that produced an error. + +For each error, note: + +- What the skill said to do +- The error or incorrect behavior that resulted +- The fix you applied + +### 1c: Human intervention events + +Identify moments where the human clarified, corrected, or overrode your approach. + +For each intervention, note: + +- What you were doing when the human intervened +- What the human said or changed +- Whether the skill could have prevented this + +### 1d: Step duration anomalies + +Identify steps that consumed disproportionate effort compared to their apparent +complexity. These signal that the skill should provide a template, snippet, or +more detailed guidance. + +--- + +## Phase 2 — Human Interview + +Ask the human up to 4 questions. Keep it brief — skip questions if the session +already provided clear answers. Respect if they decline. + +1. "Was anything unclear about what was happening during the task?" +2. "Did anything feel frustrating or take longer than expected?" +3. "Were you uncertain about the output quality at any point?" +4. "Anything you'd want done differently next time?" + +Derive `userRating` from overall sentiment: + +- Mostly positive → `good` +- Mixed signals → `mixed` +- Mostly negative → `bad` + +If the human gives an explicit rating, use that instead. + +--- + +## Phase 3 — Build the Feedback + +Write one Markdown feedback file per skill used. Only include skills that were +actually used during the session — skip any that were loaded but never +referenced. + +### Template + +```markdown +# Skill Feedback: [skill name from SKILL.md frontmatter] + +**Package:** [npm package name that contains the skill] +**Skill version:** [metadata.version or library_version from frontmatter] +**Rating:** [good | mixed | bad] + +## Task + +[one-sentence summary of what the human asked you to do] + +## What Worked + +[patterns/instructions from the skill that were accurate and helpful] + +## What Failed + +[from 1b — skill instructions that produced errors] + +## Missing + +[from 1a — gaps where the skill should have covered] + +## Self-Corrections + +[from 1b fixes + 1c human interventions, combined] + +## User Comments + +[optional — direct quotes or paraphrased human input from Phase 2] +``` + +### Field derivation guide + +| Field | Source | +| ---------------- | ------------------------------------------------------------------ | +| Skill name | Frontmatter `name` field of the SKILL.md you loaded | +| Package | The npm package the skill lives in (e.g. `@tanstack/query-intent`) | +| Skill version | Frontmatter `metadata.version` or `library_version` | +| Task | Summarize the human's original request in one sentence | +| What Worked | List skill sections/patterns that were correct and useful | +| What Failed | From 1b — skill instructions that produced errors | +| Missing | From 1a — gaps where the skill was silent | +| Self-Corrections | From 1b fixes + 1c human interventions, combined | +| Rating | From Phase 2 sentiment analysis or explicit rating | +| User Comments | From Phase 2 answers, keep brief | + +--- + +## Phase 4 — Submit + +Determine the target repo from the skill's package. The repo is typically +derivable from the `repository` field in the package's `package.json`, or +from the `sources` field in the SKILL.md frontmatter. + +### Privacy check + +Before submitting, determine whether the user's project is public or private. +Check with `gh repo view --json visibility` or look for a `private` field in +the project's `package.json`. If you can't determine visibility, assume private. + +**Private repos:** Feedback is submitted to a public issue tracker, so it must +not contain project-specific details. Before submission: + +1. Strip any project-specific code, file paths, internal API names, service + URLs, or business logic from all fields +2. Rewrite the "Task" field to describe the _type_ of task generically + (e.g. "set up authenticated data fetching" not "set up auth for our + internal billing API at api.acme.corp/billing") +3. Rewrite "What Failed" and "Missing" entries to reference only the + skill's own APIs and patterns, not the user's code +4. Show the sanitized feedback to the user and ask them to confirm it's + safe to submit before proceeding + +**Public repos:** No sanitization needed. Proceed directly to submission. + +### If `gh` CLI is available + +Submit directly as a GitHub issue: + +```bash +gh issue create --repo [owner/repo] --title "Skill Feedback: [skill-name] ([rating])" --label "feedback:[skill-name]" --body-file intent-feedback.md +``` + +If the label doesn't exist, omit the `--label` flag — don't let a missing +label block submission. + +If submission succeeds, delete the feedback file. + +### If `gh` CLI is not available + +Tell the human: + +> "I've written skill feedback to `intent-feedback.md`. To submit it, +> open an issue at https://github.com/[owner/repo]/issues and paste the +> contents." diff --git a/packages/intent/meta/generate-skill/SKILL.md b/packages/intent/meta/generate-skill/SKILL.md index fb69eaae..c5e97968 100644 --- a/packages/intent/meta/generate-skill/SKILL.md +++ b/packages/intent/meta/generate-skill/SKILL.md @@ -1,428 +1,428 @@ ---- -name: skill-generate -description: > - Generate a complete SKILL.md file for a library from source documentation - and skill tree artifacts. Activate when bootstrapping skills for a new - library, regenerating a stale skill after source changes, or producing a - skill from a skill_tree.yaml entry. Takes a skill name, description, and - source docs as inputs; outputs a validated SKILL.md that conforms to the - tree-generator spec. -metadata: - version: '1.0' - category: meta-tooling - input_artifacts: - - skills/_artifacts/skill_tree.yaml - - skills/_artifacts/domain_map.yaml - - skills/_artifacts/skill_spec.md - - source documentation - output_artifacts: - - SKILL.md - skills: - - skill-tree-generator - - skill-domain-discovery ---- - -# Skill Generation - -You are generating a SKILL.md file for the `@tanstack/intent` agent skills -repo. Skills in this repo are written for coding agents (Claude Code, Cursor, -Copilot, Warp Oz, Codex), not for human readers. Your output will be loaded -into an agent's context window and used to guide code generation. - -There are two modes. Detect which applies. - -**Mode A — Generate from domain map:** A `domain_map.yaml` and `skill_spec.md` -exist. Generate the skill specified by name from these artifacts plus the -source documentation they reference. - -**Mode B — Generate from raw docs:** No domain map exists. Generate directly -from source documentation provided as input. - ---- - -## Inputs - -You will receive: - -If the maintainer uses a custom skills root, replace `skills/` in any paths -below with their chosen directory. - -**Monorepo:** When the skill tree entry has a `package` field, write the -SKILL.md into that package's skills directory (e.g. -`packages/client/skills/core/SKILL.md`), not a shared root. - -1. **Skill name** — format `library-group/skill-name` (e.g. `tanstack-query/core`, - `tanstack-router/loaders`, `db/core/live-queries`) -2. **Skill description** — what the skill covers and when an agent should load it -3. **Source documentation** — the docs, guides, API references, and/or source - files to distill from -4. **Domain map entry** (Mode A only) — the skill's entry from `domain_map.yaml` - including failure modes, subsystems, compositions, and source references - ---- - -## Step 1 — Determine skill type - -Read the inputs and classify the skill type: - -| Type | When to use | -| ------------- | ---------------------------------------------------------- | -| `core` | Framework-agnostic concepts, configuration, patterns | -| `sub-skill` | A focused sub-topic within a core or framework skill | -| `framework` | Framework-specific bindings, hooks, components | -| `lifecycle` | Cross-cutting developer journey (getting started, go-live) | -| `composition` | Integration between two or more libraries | -| `security` | Audit checklist or security validation | - -The skill type determines the frontmatter and body structure. See -skill-tree-generator for the full spec of each type. - ---- - -## Step 2 — Extract content from sources - -**Line budget:** Each SKILL.md must stay under 500 lines. Before writing, -estimate the content size. If a skill has 5+ failure modes, 3+ primary -patterns, and subsystem details, proactively plan reference files during -extraction — don't wait until the skill exceeds the limit. - -Read through the source documentation. Extract only what a coding agent -cannot already know: - -### What to extract - -- **API shapes** — function signatures, hook parameters, option objects, - return types. Use the actual TypeScript types from source. -- **Setup patterns** — minimum viable initialization code -- **Primary patterns** — the 2–4 most important usage patterns -- **Configuration** — defaults that matter, options that change behavior -- **Failure modes** — patterns that look correct but break. Prioritize: - - Migration-boundary mistakes (old API that agents trained on older data produce) - - Silent failures (no crash, wrong behavior) - - Framework-specific gotchas (hydration, hook rules, provider ordering) -- **Constraints and invariants** — ordering requirements, lifecycle rules, - things enforced by runtime assertions - -### What NOT to extract - -- TypeScript basics, React hooks concepts, general web dev knowledge -- Marketing copy, motivational prose, "why this library is great" -- Exhaustive API tables (move these to `references/` if needed) -- Content that duplicates another skill (reference it instead) - ---- - -## Step 3 — Write the frontmatter - -### Core skill frontmatter - -```yaml ---- -name: [library]/[skill-name] -description: > - [1–3 sentences. What this skill covers and exactly when an agent should - load it. Written for the agent — include the keywords an agent would - encounter when it needs this skill. Dense routing key.] -type: core -library: [library] -library_version: "[version this targets]" -sources: - - "[Owner/repo]:docs/[path].md" - - "[Owner/repo]:src/[path].ts" ---- -``` - -### Sub-skill frontmatter - -```yaml ---- -name: [library]/[parent]/[skill-name] -description: > - [1–3 sentences. What this sub-topic covers and when to load it.] -type: sub-skill -library: [library] -library_version: "[version]" -sources: - - "[Owner/repo]:docs/[path].md" ---- -``` - -### Framework skill frontmatter - -```yaml ---- -name: [library]/[framework] -description: > - [1–3 sentences. Framework-specific bindings. Name the hooks, components, - providers.] -type: framework -library: [library] -framework: [react | vue | solid | svelte | angular] -library_version: "[version]" -requires: - - [library]/core -sources: - - "[Owner/repo]:docs/framework/[framework]/[path].md" ---- -``` - -### Frontmatter rules - -- `description` must be written so the agent loads this skill at the right - time — not too broad (triggers on everything) and not too narrow (never - triggers). Pack with function names, option names, concept keywords. -- `sources` uses the format `Owner/repo:relative-path`. Glob patterns are - supported (e.g. `TanStack/query:docs/framework/react/guides/*.md`). -- `library_version` is the version of the source library this skill targets. -- `requires` lists skills that must be loaded before this one. - ---- - -## Step 4 — Write the body - -### Standard body (core, sub-skill, framework) - -Follow this section order exactly: - -**1. Dependency note** (framework and sub-skills only) - -```markdown -This skill builds on [parent-skill]. Read it first for foundational concepts. -``` - -**2. Setup** - -A complete, copy-pasteable code block showing minimum viable usage. - -- Real package imports with exact names (`@tanstack/react-query`, not `react-query`) -- No `// ...` or `[your code here]` — complete and runnable -- No unnecessary boilerplate — include exactly the context needed -- For framework skills: framework-specific setup (provider, hook wiring) -- For core skills: framework-agnostic setup (no hooks, no components) - -**3. Core Patterns** (or "Hooks and Components" for framework skills) - -2–4 patterns. For each: - -- One-line heading: what it accomplishes -- Complete code block -- One sentence of explanation only if not self-explanatory - -**4. Common Mistakes** - -Minimum 3 entries. Complex skills target 5–6. Format: - -````markdown -### [PRIORITY] [What goes wrong — 5–8 word phrase] - -Wrong: - -```[lang] -// code that looks correct but isn't -``` -```` - -Correct: - -```[lang] -// code that works -``` - -[One sentence: the specific mechanism by which the wrong version fails.] - -Source: [doc page or source file:line] - -```` - -Priority levels: -- **CRITICAL** — Breaks in production. Security risk or data loss. -- **HIGH** — Incorrect behavior under common conditions. -- **MEDIUM** — Incorrect under specific conditions or edge cases. - -Every mistake must be: -- **Plausible** — an agent would generate it -- **Silent** — no immediate crash -- **Grounded** — traceable to a doc page, source file, or issue - -If the domain map includes failure modes with a `skills` list naming -multiple skills, include those failure modes in every SKILL file listed. - -**5. References** (only when needed) - -```markdown -## References - -- [Full option reference](references/options.md) -```` - -Create reference files when the skill would exceed 500 lines, when the -domain covers 3+ independent adapters/backends, or when a topic has >10 -distinct API patterns. - -### Checklist body (security, go-live, audit) - -Use when the primary action is "check these things" not "learn patterns": - -````markdown -# [Library Name] — [Security | Go-Live] Checklist - -Run through each section before [deploying | releasing]. - -## [Category] Checks - -### Check: [what to verify] - -Expected: - -```[lang] -// correct configuration -``` -```` - -Fail condition: [what indicates this check failed] -Fix: [one-line remediation] - -## Common Security Mistakes - -[Wrong/correct pairs, same format as standard Common Mistakes] - -## Pre-Deploy Summary - -- [ ] [Verification 1] -- [ ] [Verification 2] - -``` - ---- - -## Step 5 — Validate - -Run every check before outputting. Fix any failures. - -| Check | Rule | -|-------|------| -| Under 500 lines | Move excess to references/ | -| Real imports in every code block | Exact package name, correct adapter | -| No external concept explanations | No "TypeScript is...", no "React hooks are..." | -| No marketing prose | No "powerful", "elegant", "best-in-class" | -| Every code block is complete | Works without modification when pasted | -| Common Mistakes are silent | Not obvious compile errors | -| Common Mistakes are library-specific | Not generic TS/React mistakes | -| Common Mistakes are sourced | Traceable to doc or source | -| `name` matches expected directory path | `db/core/live-queries` → `db/core/live-queries/SKILL.md` | -| `sources` filled for sub-skills | At least one Owner/repo:path | -| Framework skills have `requires` | Lists core dependency | -| Framework skills open with dependency note | First prose line references core | -| Description is a dense routing key | Not a human summary — agent-facing | - ---- - -## Step 6 — Output - -Output the complete SKILL.md file content. If reference files are needed, -output those as well with their relative paths. - -If generating multiple skills in a batch (e.g. all skills for a library), -output in this order: - -1. Core overview SKILL.md -2. Core sub-skills in domain order -3. Framework overview SKILL.md for each framework -4. Framework sub-skills -5. Composition skills -6. Security/checklist skills -7. Reference files - ---- - -## Regeneration mode - -When regenerating a stale skill (triggered by skill-staleness-check): - -1. Read the existing SKILL.md and the source diff that triggered staleness -2. Determine which sections are affected by the change -3. Update only affected sections — preserve all other content -4. If a breaking change occurred, add the old pattern as a new Common - Mistake entry (wrong/correct pair) -5. Bump `library_version` in frontmatter -6. Validate the complete file against Step 5 checks - -Do not rewrite the entire skill for a minor source change. Surgical -updates preserve review effort and reduce diff noise. - ---- - -## Constraints - -| Rule | Detail | -|------|--------| -| Match the library's framework support | Generate framework skills only for adapters the library actually provides. If the library supports only React, only generate React examples. If it supports multiple frameworks, generate one skill per adapter. | -| All imports use real package names | `@tanstack/react-query`, not `react-query` | -| No placeholder code | No `// ...`, `[your value]`, or `...rest`. Idiomatic framework patterns like `{children}` or `{props.title}` in JSX are not placeholders — they are real code and are acceptable. | -| Agent-first writing | Only write what the agent cannot already know | -| Examples are minimal | No unnecessary boilerplate or wrapper components | -| Failure modes are high-value | Focus on plausible-but-broken, not obvious errors | - ---- - -## Cross-model compatibility - -Output is consumed by all major AI coding agents. To ensure consistency: - -- Markdown with YAML frontmatter — universally parsed -- No XML tags in generated skill content -- Code blocks use triple backticks with language annotation -- Section boundaries use ## headers -- Descriptions are keyword-packed for routing -- Examples show concrete values, never placeholders -- Positive instructions ("Use X") over negative ("Don't use Y") -- Critical info at start or end of sections (not buried in middle) -- Each SKILL.md is self-contained except for declared `requires` - ---- - -## Meta-skill feedback (alpha default) - -After generating the first iteration of skills, complete a single Markdown -feedback draft for all three meta skills used in scaffolding. If a draft -exists from previous steps, keep it and fill the **Generate Skill** section. -If no draft exists, create it using this exact template. - -``` - -# Intent Meta Skill Feedback - -## Domain Discovery - -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Tree Generator - -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Generate Skill - -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Context (optional) - -- Library: -- Repo: -- Docs: -- Notes: - -``` - -Ask the maintainer if they want to edit the feedback. Then ask if you should -send it as a GitHub issue to TanStack/intent. Use the issue title: -`[meta-feedback] intent meta skill`. Only submit if they confirm. -``` +--- +name: skill-generate +description: > + Generate a complete SKILL.md file for a library from source documentation + and skill tree artifacts. Activate when bootstrapping skills for a new + library, regenerating a stale skill after source changes, or producing a + skill from a skill_tree.yaml entry. Takes a skill name, description, and + source docs as inputs; outputs a validated SKILL.md that conforms to the + tree-generator spec. +metadata: + version: '1.0' + category: meta-tooling + input_artifacts: + - skills/_artifacts/skill_tree.yaml + - skills/_artifacts/domain_map.yaml + - skills/_artifacts/skill_spec.md + - source documentation + output_artifacts: + - SKILL.md + skills: + - skill-tree-generator + - skill-domain-discovery +--- + +# Skill Generation + +You are generating a SKILL.md file for the `@tanstack/intent` agent skills +repo. Skills in this repo are written for coding agents (Claude Code, Cursor, +Copilot, Warp Oz, Codex), not for human readers. Your output will be loaded +into an agent's context window and used to guide code generation. + +There are two modes. Detect which applies. + +**Mode A — Generate from domain map:** A `domain_map.yaml` and `skill_spec.md` +exist. Generate the skill specified by name from these artifacts plus the +source documentation they reference. + +**Mode B — Generate from raw docs:** No domain map exists. Generate directly +from source documentation provided as input. + +--- + +## Inputs + +You will receive: + +If the maintainer uses a custom skills root, replace `skills/` in any paths +below with their chosen directory. + +**Monorepo:** When the skill tree entry has a `package` field, write the +SKILL.md into that package's skills directory (e.g. +`packages/client/skills/core/SKILL.md`), not a shared root. + +1. **Skill name** — format `library-group/skill-name` (e.g. `tanstack-query/core`, + `tanstack-router/loaders`, `db/core/live-queries`) +2. **Skill description** — what the skill covers and when an agent should load it +3. **Source documentation** — the docs, guides, API references, and/or source + files to distill from +4. **Domain map entry** (Mode A only) — the skill's entry from `domain_map.yaml` + including failure modes, subsystems, compositions, and source references + +--- + +## Step 1 — Determine skill type + +Read the inputs and classify the skill type: + +| Type | When to use | +| ------------- | ---------------------------------------------------------- | +| `core` | Framework-agnostic concepts, configuration, patterns | +| `sub-skill` | A focused sub-topic within a core or framework skill | +| `framework` | Framework-specific bindings, hooks, components | +| `lifecycle` | Cross-cutting developer journey (getting started, go-live) | +| `composition` | Integration between two or more libraries | +| `security` | Audit checklist or security validation | + +The skill type determines the frontmatter and body structure. See +skill-tree-generator for the full spec of each type. + +--- + +## Step 2 — Extract content from sources + +**Line budget:** Each SKILL.md must stay under 500 lines. Before writing, +estimate the content size. If a skill has 5+ failure modes, 3+ primary +patterns, and subsystem details, proactively plan reference files during +extraction — don't wait until the skill exceeds the limit. + +Read through the source documentation. Extract only what a coding agent +cannot already know: + +### What to extract + +- **API shapes** — function signatures, hook parameters, option objects, + return types. Use the actual TypeScript types from source. +- **Setup patterns** — minimum viable initialization code +- **Primary patterns** — the 2–4 most important usage patterns +- **Configuration** — defaults that matter, options that change behavior +- **Failure modes** — patterns that look correct but break. Prioritize: + - Migration-boundary mistakes (old API that agents trained on older data produce) + - Silent failures (no crash, wrong behavior) + - Framework-specific gotchas (hydration, hook rules, provider ordering) +- **Constraints and invariants** — ordering requirements, lifecycle rules, + things enforced by runtime assertions + +### What NOT to extract + +- TypeScript basics, React hooks concepts, general web dev knowledge +- Marketing copy, motivational prose, "why this library is great" +- Exhaustive API tables (move these to `references/` if needed) +- Content that duplicates another skill (reference it instead) + +--- + +## Step 3 — Write the frontmatter + +### Core skill frontmatter + +```yaml +--- +name: [library]/[skill-name] +description: > + [1–3 sentences. What this skill covers and exactly when an agent should + load it. Written for the agent — include the keywords an agent would + encounter when it needs this skill. Dense routing key.] +type: core +library: [library] +library_version: "[version this targets]" +sources: + - "[Owner/repo]:docs/[path].md" + - "[Owner/repo]:src/[path].ts" +--- +``` + +### Sub-skill frontmatter + +```yaml +--- +name: [library]/[parent]/[skill-name] +description: > + [1–3 sentences. What this sub-topic covers and when to load it.] +type: sub-skill +library: [library] +library_version: "[version]" +sources: + - "[Owner/repo]:docs/[path].md" +--- +``` + +### Framework skill frontmatter + +```yaml +--- +name: [library]/[framework] +description: > + [1–3 sentences. Framework-specific bindings. Name the hooks, components, + providers.] +type: framework +library: [library] +framework: [react | vue | solid | svelte | angular] +library_version: "[version]" +requires: + - [library]/core +sources: + - "[Owner/repo]:docs/framework/[framework]/[path].md" +--- +``` + +### Frontmatter rules + +- `description` must be written so the agent loads this skill at the right + time — not too broad (triggers on everything) and not too narrow (never + triggers). Pack with function names, option names, concept keywords. +- `sources` uses the format `Owner/repo:relative-path`. Glob patterns are + supported (e.g. `TanStack/query:docs/framework/react/guides/*.md`). +- `library_version` is the version of the source library this skill targets. +- `requires` lists skills that must be loaded before this one. + +--- + +## Step 4 — Write the body + +### Standard body (core, sub-skill, framework) + +Follow this section order exactly: + +**1. Dependency note** (framework and sub-skills only) + +```markdown +This skill builds on [parent-skill]. Read it first for foundational concepts. +``` + +**2. Setup** + +A complete, copy-pasteable code block showing minimum viable usage. + +- Real package imports with exact names (`@tanstack/react-query`, not `react-query`) +- No `// ...` or `[your code here]` — complete and runnable +- No unnecessary boilerplate — include exactly the context needed +- For framework skills: framework-specific setup (provider, hook wiring) +- For core skills: framework-agnostic setup (no hooks, no components) + +**3. Core Patterns** (or "Hooks and Components" for framework skills) + +2–4 patterns. For each: + +- One-line heading: what it accomplishes +- Complete code block +- One sentence of explanation only if not self-explanatory + +**4. Common Mistakes** + +Minimum 3 entries. Complex skills target 5–6. Format: + +````markdown +### [PRIORITY] [What goes wrong — 5–8 word phrase] + +Wrong: + +```[lang] +// code that looks correct but isn't +``` +```` + +Correct: + +```[lang] +// code that works +``` + +[One sentence: the specific mechanism by which the wrong version fails.] + +Source: [doc page or source file:line] + +```` + +Priority levels: +- **CRITICAL** — Breaks in production. Security risk or data loss. +- **HIGH** — Incorrect behavior under common conditions. +- **MEDIUM** — Incorrect under specific conditions or edge cases. + +Every mistake must be: +- **Plausible** — an agent would generate it +- **Silent** — no immediate crash +- **Grounded** — traceable to a doc page, source file, or issue + +If the domain map includes failure modes with a `skills` list naming +multiple skills, include those failure modes in every SKILL file listed. + +**5. References** (only when needed) + +```markdown +## References + +- [Full option reference](references/options.md) +```` + +Create reference files when the skill would exceed 500 lines, when the +domain covers 3+ independent adapters/backends, or when a topic has >10 +distinct API patterns. + +### Checklist body (security, go-live, audit) + +Use when the primary action is "check these things" not "learn patterns": + +````markdown +# [Library Name] — [Security | Go-Live] Checklist + +Run through each section before [deploying | releasing]. + +## [Category] Checks + +### Check: [what to verify] + +Expected: + +```[lang] +// correct configuration +``` +```` + +Fail condition: [what indicates this check failed] +Fix: [one-line remediation] + +## Common Security Mistakes + +[Wrong/correct pairs, same format as standard Common Mistakes] + +## Pre-Deploy Summary + +- [ ] [Verification 1] +- [ ] [Verification 2] + +``` + +--- + +## Step 5 — Validate + +Run every check before outputting. Fix any failures. + +| Check | Rule | +|-------|------| +| Under 500 lines | Move excess to references/ | +| Real imports in every code block | Exact package name, correct adapter | +| No external concept explanations | No "TypeScript is...", no "React hooks are..." | +| No marketing prose | No "powerful", "elegant", "best-in-class" | +| Every code block is complete | Works without modification when pasted | +| Common Mistakes are silent | Not obvious compile errors | +| Common Mistakes are library-specific | Not generic TS/React mistakes | +| Common Mistakes are sourced | Traceable to doc or source | +| `name` matches expected directory path | `db/core/live-queries` → `db/core/live-queries/SKILL.md` | +| `sources` filled for sub-skills | At least one Owner/repo:path | +| Framework skills have `requires` | Lists core dependency | +| Framework skills open with dependency note | First prose line references core | +| Description is a dense routing key | Not a human summary — agent-facing | + +--- + +## Step 6 — Output + +Output the complete SKILL.md file content. If reference files are needed, +output those as well with their relative paths. + +If generating multiple skills in a batch (e.g. all skills for a library), +output in this order: + +1. Core overview SKILL.md +2. Core sub-skills in domain order +3. Framework overview SKILL.md for each framework +4. Framework sub-skills +5. Composition skills +6. Security/checklist skills +7. Reference files + +--- + +## Regeneration mode + +When regenerating a stale skill (triggered by skill-staleness-check): + +1. Read the existing SKILL.md and the source diff that triggered staleness +2. Determine which sections are affected by the change +3. Update only affected sections — preserve all other content +4. If a breaking change occurred, add the old pattern as a new Common + Mistake entry (wrong/correct pair) +5. Bump `library_version` in frontmatter +6. Validate the complete file against Step 5 checks + +Do not rewrite the entire skill for a minor source change. Surgical +updates preserve review effort and reduce diff noise. + +--- + +## Constraints + +| Rule | Detail | +|------|--------| +| Match the library's framework support | Generate framework skills only for adapters the library actually provides. If the library supports only React, only generate React examples. If it supports multiple frameworks, generate one skill per adapter. | +| All imports use real package names | `@tanstack/react-query`, not `react-query` | +| No placeholder code | No `// ...`, `[your value]`, or `...rest`. Idiomatic framework patterns like `{children}` or `{props.title}` in JSX are not placeholders — they are real code and are acceptable. | +| Agent-first writing | Only write what the agent cannot already know | +| Examples are minimal | No unnecessary boilerplate or wrapper components | +| Failure modes are high-value | Focus on plausible-but-broken, not obvious errors | + +--- + +## Cross-model compatibility + +Output is consumed by all major AI coding agents. To ensure consistency: + +- Markdown with YAML frontmatter — universally parsed +- No XML tags in generated skill content +- Code blocks use triple backticks with language annotation +- Section boundaries use ## headers +- Descriptions are keyword-packed for routing +- Examples show concrete values, never placeholders +- Positive instructions ("Use X") over negative ("Don't use Y") +- Critical info at start or end of sections (not buried in middle) +- Each SKILL.md is self-contained except for declared `requires` + +--- + +## Meta-skill feedback (alpha default) + +After generating the first iteration of skills, complete a single Markdown +feedback draft for all three meta skills used in scaffolding. If a draft +exists from previous steps, keep it and fill the **Generate Skill** section. +If no draft exists, create it using this exact template. + +``` + +# Intent Meta Skill Feedback + +## Domain Discovery + +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Tree Generator + +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Generate Skill + +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Context (optional) + +- Library: +- Repo: +- Docs: +- Notes: + +``` + +Ask the maintainer if they want to edit the feedback. Then ask if you should +send it as a GitHub issue to TanStack/intent. Use the issue title: +`[meta-feedback] intent meta skill`. Only submit if they confirm. +``` diff --git a/packages/intent/meta/skill-staleness-check/SKILL.md b/packages/intent/meta/skill-staleness-check/SKILL.md index 0e36f6a2..9155becd 100644 --- a/packages/intent/meta/skill-staleness-check/SKILL.md +++ b/packages/intent/meta/skill-staleness-check/SKILL.md @@ -1,282 +1,282 @@ ---- -name: skill-staleness-check -description: > - Evaluate intent skills for staleness when source files change in upstream - TanStack package repos. Matches changed files against metadata.sources, - evaluates whether diffs affect documented behavior, rewrites stale skills - using skill-generate, checks cross-skill references, and opens PRs. - Silent when nothing needs updating. -metadata: - version: '1.0' - category: meta-tooling - input_artifacts: - - webhook payload (package name, commit SHA, changed files) - output_artifacts: - - updated SKILL.md files - - pull requests - skills: - - skill-generate - - skill-tree-generator ---- - -# Skill Staleness Check - -You are a coding agent. Your job is to evaluate whether intent skills are -stale after upstream source changes, and if so, update them and open PRs. -You act autonomously end-to-end. PRs contain already-updated skill -content, not suggestions. - -If nothing needs updating, exit silently. No PR, no notification. - ---- - -## Inputs - -Webhook payload from an upstream package repo merge to main: - -```json -{ - "package": "@tanstack/query", - "sha": "abc123", - "changed_files": ["docs/framework/react/guides/queries.md", "src/query.ts"] -} -``` - ---- - -## Step 1 — Match changed files to skills - -Read all SKILL.md files under `packages/intent/skills/`. For each skill, -extract `sources` from the frontmatter. - -Match `changed_files` from the webhook against `sources` entries across all -skills. Source references use the format `Owner/repo:relative-path` and -support glob patterns. - -A skill is a **candidate** if any of its `sources` entries match a changed -file. - -If no skills match, exit silently. - -### Using sync-skills.mjs - -The repo includes `scripts/sync-skills.mjs` for programmatic staleness -detection. For a given library: - -```bash -node scripts/sync-skills.mjs -``` - -This checks: - -- Source file SHA drift (compares stored SHAs in `sync-state.json` against - current remote SHAs via GitHub API) -- Library version drift (frontmatter `library_version` vs current published - version) -- Tree-generator changes (whether the meta skill has been updated since - last sync) - -Use `--report` to write a structured `staleness_report.yaml`: - -```bash -node scripts/sync-skills.mjs --report -``` - -The report classifies skills as needing regeneration (source changed) or -version bump only. - ---- - -## Step 2 — Evaluate each candidate - -For each matched skill: - -1. Read the current SKILL.md content -2. Fetch the file diff from the triggering commit in the source repo -3. Classify the change: - -| Classification | Criteria | Action | -| --------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------- | -| **No impact** | Diff is typo fix, comment change, test-only, or internal refactor with no API/behavior change | Skip — no update needed | -| **Version bump only** | Diff changes version numbers, dependency ranges, or metadata but no documented behavior | Bump `library_version` in frontmatter | -| **Content update** | Diff changes API shape, behavior, defaults, types, or patterns that the skill documents | Rewrite affected sections | -| **Breaking change** | Diff removes, renames, or fundamentally changes an API the skill documents | Rewrite + add old pattern as Common Mistake | - -### Two-pass classification - -**Pass 1 — Quick scan:** Read the diff summary (files changed, insertions, -deletions). Identify which skill sections could be affected. - -**Pass 2 — Detail evaluation:** For each potentially affected section, read -the full diff hunks and compare against the skill content. Determine if the -change actually affects what the skill documents. - -This prevents over-updating. A 200-line diff to a source file may only -affect one line of one skill, or none at all. - ---- - -## Step 3 — Update stale skills - -For skills classified as needing content updates: - -1. Load the skill-generate meta skill -2. Provide it with: - - The existing SKILL.md content - - The source diff - - The current source documentation (fetch the updated file) -3. Use regeneration mode (surgical update, not full rewrite) -4. Validate the updated skill against all checks - -For version bump only: - -```bash -node scripts/sync-skills.mjs --bump-version -``` - -This updates `library_version` in all frontmatter for the library and -records the new version in `sync-state.json`. - ---- - -## Step 4 — Check cross-skill references - -After updating skills in Step 3, check for cross-skill staleness: - -1. For each skill that was updated, read its `name` -2. Scan all other skills for `requires` entries or `sources` that reference - the updated skill -3. For each skill that references an updated skill, evaluate whether the - update makes the referencing skill stale or inconsistent -4. If stale → update using the same process as Step 3 -5. If not → skip - -This cascade is bounded to **one level**. Skills that reference a -second-order dependency are not automatically re-checked. - ---- - -## Step 5 — Mark skills as synced - -After updating, mark the affected skills as synced so future staleness -checks have a clean baseline: - -```bash -# Mark specific skills -node scripts/sync-skills.mjs --mark-synced - -# Mark all skills for a library -node scripts/sync-skills.mjs --mark-synced --all -``` - -This updates `sync-state.json` with current source file SHAs, the -tree-generator SHA, and the sync timestamp. - ---- - -## Step 6 — Open PRs - -For each skill (or group of skills) that was updated: - -1. Create branch: `skill-update/-` -2. Commit updated SKILL.md file(s) -3. Open PR with structured body - -### PR format - -**Title:** `skill: update (@)` - -**Body:** - -```markdown -### Triggered by - -Changes to: - -### What changed in the source - - - -### What changed in the skill - - - -### Cross-skill impact - - - -### Review checklist - -- [ ] Skill content is accurate -- [ ] Code examples are complete and copy-pasteable -- [ ] No other skills need corresponding updates -- [ ] Under 500 lines -``` - -### Grouping PRs - -- If multiple skills for the same library are affected by the same commit, - group them in a single PR -- If a cross-skill update is needed (Step 4), open a separate PR for the - downstream skill to keep review scopes clean -- Never mix skills from different libraries in the same PR - ---- - -## No-op behavior - -Exit silently (no PR, no notification, no issue) when ANY of these are true: - -- No changed files match any skill's `sources` -- All matched diffs are classified as "no impact" in Step 2 -- The sync-skills.mjs report shows all skills are current - ---- - -## Operational notes - -### GitHub API usage - -The `sync-skills.mjs` script uses the `gh` CLI for GitHub API access. It -requires: - -- `gh` CLI installed and authenticated -- Read access to upstream TanStack package repos (query, router, db, form, - table) -- Write access to the intent repo for creating branches and PRs - -### Rate limiting - -When checking multiple libraries or many source files, the script makes -one API call per source file per skill. For large batches, the GitHub API -rate limit (5000 requests/hour for authenticated users) may apply. The -script does not currently batch or cache API responses — if this becomes -an issue, add caching at the `getRemoteFileSha` level. - -### Manual triggering - -Maintainers can run staleness detection manually: - -```bash -# Check a specific library -node scripts/sync-skills.mjs db - -# Check and write a report -node scripts/sync-skills.mjs db --report - -# After reviewing and regenerating, mark as synced -node scripts/sync-skills.mjs db --mark-synced --all -``` - ---- - -## Constraints - -| Rule | Detail | -| ----------------------------------------------- | --------------------------------------------------- | -| Silent when nothing changes | No noise — exit cleanly if no updates needed | -| Surgical updates over full rewrites | Only change sections affected by the diff | -| One cascade level | Cross-skill checks go one level deep, not recursive | -| PRs scoped to one library | Never mix libraries in a single PR | -| Version bumps are separate from content updates | A version-only bump doesn't require regeneration | -| Commit messages include co-author | Include the coding agent's co-author tag | +--- +name: skill-staleness-check +description: > + Evaluate intent skills for staleness when source files change in upstream + TanStack package repos. Matches changed files against metadata.sources, + evaluates whether diffs affect documented behavior, rewrites stale skills + using skill-generate, checks cross-skill references, and opens PRs. + Silent when nothing needs updating. +metadata: + version: '1.0' + category: meta-tooling + input_artifacts: + - webhook payload (package name, commit SHA, changed files) + output_artifacts: + - updated SKILL.md files + - pull requests + skills: + - skill-generate + - skill-tree-generator +--- + +# Skill Staleness Check + +You are a coding agent. Your job is to evaluate whether intent skills are +stale after upstream source changes, and if so, update them and open PRs. +You act autonomously end-to-end. PRs contain already-updated skill +content, not suggestions. + +If nothing needs updating, exit silently. No PR, no notification. + +--- + +## Inputs + +Webhook payload from an upstream package repo merge to main: + +```json +{ + "package": "@tanstack/query", + "sha": "abc123", + "changed_files": ["docs/framework/react/guides/queries.md", "src/query.ts"] +} +``` + +--- + +## Step 1 — Match changed files to skills + +Read all SKILL.md files under `packages/intent/skills/`. For each skill, +extract `sources` from the frontmatter. + +Match `changed_files` from the webhook against `sources` entries across all +skills. Source references use the format `Owner/repo:relative-path` and +support glob patterns. + +A skill is a **candidate** if any of its `sources` entries match a changed +file. + +If no skills match, exit silently. + +### Using sync-skills.mjs + +The repo includes `scripts/sync-skills.mjs` for programmatic staleness +detection. For a given library: + +```bash +node scripts/sync-skills.mjs +``` + +This checks: + +- Source file SHA drift (compares stored SHAs in `sync-state.json` against + current remote SHAs via GitHub API) +- Library version drift (frontmatter `library_version` vs current published + version) +- Tree-generator changes (whether the meta skill has been updated since + last sync) + +Use `--report` to write a structured `staleness_report.yaml`: + +```bash +node scripts/sync-skills.mjs --report +``` + +The report classifies skills as needing regeneration (source changed) or +version bump only. + +--- + +## Step 2 — Evaluate each candidate + +For each matched skill: + +1. Read the current SKILL.md content +2. Fetch the file diff from the triggering commit in the source repo +3. Classify the change: + +| Classification | Criteria | Action | +| --------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------- | +| **No impact** | Diff is typo fix, comment change, test-only, or internal refactor with no API/behavior change | Skip — no update needed | +| **Version bump only** | Diff changes version numbers, dependency ranges, or metadata but no documented behavior | Bump `library_version` in frontmatter | +| **Content update** | Diff changes API shape, behavior, defaults, types, or patterns that the skill documents | Rewrite affected sections | +| **Breaking change** | Diff removes, renames, or fundamentally changes an API the skill documents | Rewrite + add old pattern as Common Mistake | + +### Two-pass classification + +**Pass 1 — Quick scan:** Read the diff summary (files changed, insertions, +deletions). Identify which skill sections could be affected. + +**Pass 2 — Detail evaluation:** For each potentially affected section, read +the full diff hunks and compare against the skill content. Determine if the +change actually affects what the skill documents. + +This prevents over-updating. A 200-line diff to a source file may only +affect one line of one skill, or none at all. + +--- + +## Step 3 — Update stale skills + +For skills classified as needing content updates: + +1. Load the skill-generate meta skill +2. Provide it with: + - The existing SKILL.md content + - The source diff + - The current source documentation (fetch the updated file) +3. Use regeneration mode (surgical update, not full rewrite) +4. Validate the updated skill against all checks + +For version bump only: + +```bash +node scripts/sync-skills.mjs --bump-version +``` + +This updates `library_version` in all frontmatter for the library and +records the new version in `sync-state.json`. + +--- + +## Step 4 — Check cross-skill references + +After updating skills in Step 3, check for cross-skill staleness: + +1. For each skill that was updated, read its `name` +2. Scan all other skills for `requires` entries or `sources` that reference + the updated skill +3. For each skill that references an updated skill, evaluate whether the + update makes the referencing skill stale or inconsistent +4. If stale → update using the same process as Step 3 +5. If not → skip + +This cascade is bounded to **one level**. Skills that reference a +second-order dependency are not automatically re-checked. + +--- + +## Step 5 — Mark skills as synced + +After updating, mark the affected skills as synced so future staleness +checks have a clean baseline: + +```bash +# Mark specific skills +node scripts/sync-skills.mjs --mark-synced + +# Mark all skills for a library +node scripts/sync-skills.mjs --mark-synced --all +``` + +This updates `sync-state.json` with current source file SHAs, the +tree-generator SHA, and the sync timestamp. + +--- + +## Step 6 — Open PRs + +For each skill (or group of skills) that was updated: + +1. Create branch: `skill-update/-` +2. Commit updated SKILL.md file(s) +3. Open PR with structured body + +### PR format + +**Title:** `skill: update (@)` + +**Body:** + +```markdown +### Triggered by + +Changes to: + +### What changed in the source + + + +### What changed in the skill + + + +### Cross-skill impact + + + +### Review checklist + +- [ ] Skill content is accurate +- [ ] Code examples are complete and copy-pasteable +- [ ] No other skills need corresponding updates +- [ ] Under 500 lines +``` + +### Grouping PRs + +- If multiple skills for the same library are affected by the same commit, + group them in a single PR +- If a cross-skill update is needed (Step 4), open a separate PR for the + downstream skill to keep review scopes clean +- Never mix skills from different libraries in the same PR + +--- + +## No-op behavior + +Exit silently (no PR, no notification, no issue) when ANY of these are true: + +- No changed files match any skill's `sources` +- All matched diffs are classified as "no impact" in Step 2 +- The sync-skills.mjs report shows all skills are current + +--- + +## Operational notes + +### GitHub API usage + +The `sync-skills.mjs` script uses the `gh` CLI for GitHub API access. It +requires: + +- `gh` CLI installed and authenticated +- Read access to upstream TanStack package repos (query, router, db, form, + table) +- Write access to the intent repo for creating branches and PRs + +### Rate limiting + +When checking multiple libraries or many source files, the script makes +one API call per source file per skill. For large batches, the GitHub API +rate limit (5000 requests/hour for authenticated users) may apply. The +script does not currently batch or cache API responses — if this becomes +an issue, add caching at the `getRemoteFileSha` level. + +### Manual triggering + +Maintainers can run staleness detection manually: + +```bash +# Check a specific library +node scripts/sync-skills.mjs db + +# Check and write a report +node scripts/sync-skills.mjs db --report + +# After reviewing and regenerating, mark as synced +node scripts/sync-skills.mjs db --mark-synced --all +``` + +--- + +## Constraints + +| Rule | Detail | +| ----------------------------------------------- | --------------------------------------------------- | +| Silent when nothing changes | No noise — exit cleanly if no updates needed | +| Surgical updates over full rewrites | Only change sections affected by the diff | +| One cascade level | Cross-skill checks go one level deep, not recursive | +| PRs scoped to one library | Never mix libraries in a single PR | +| Version bumps are separate from content updates | A version-only bump doesn't require regeneration | +| Commit messages include co-author | Include the coding agent's co-author tag | diff --git a/packages/intent/meta/templates/workflows/check-skills.yml b/packages/intent/meta/templates/workflows/check-skills.yml index 602d01e1..8445d931 100644 --- a/packages/intent/meta/templates/workflows/check-skills.yml +++ b/packages/intent/meta/templates/workflows/check-skills.yml @@ -1,143 +1,143 @@ -# check-skills.yml — Drop this into your library repo's .github/workflows/ -# -# Checks for stale intent skills after a release and opens a review PR -# if any skills need attention. The PR body includes a prompt you can -# paste into Claude Code, Cursor, or any coding agent to update them. -# -# Triggers: new release published, or manual workflow_dispatch. -# -# Template variables (replaced by `intent setup`): -# {{PACKAGE_NAME}} — e.g. @tanstack/query - -name: Check Skills - -on: - release: - types: [published] - workflow_dispatch: {} - -permissions: - contents: write - pull-requests: write - -jobs: - check: - name: Check for stale skills - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install intent - run: npm install {{PACKAGE_NAME}} - - - name: Check staleness - id: stale - run: | - OUTPUT=$(npx @tanstack/intent stale --json 2>&1) || true - echo "$OUTPUT" - - # Check if any skills need review - NEEDS_REVIEW=$(echo "$OUTPUT" | node -e " - const input = require('fs').readFileSync('/dev/stdin','utf8'); - try { - const reports = JSON.parse(input); - const stale = reports.flatMap(r => - r.skills.filter(s => s.needsReview).map(s => ({ library: r.library, skill: s.name, reasons: s.reasons })) - ); - if (stale.length > 0) { - console.log(JSON.stringify(stale)); - } - } catch {} - ") - - if [ -z "$NEEDS_REVIEW" ]; then - echo "has_stale=false" >> "$GITHUB_OUTPUT" - else - echo "has_stale=true" >> "$GITHUB_OUTPUT" - # Escape for multiline GH output - EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) - echo "stale_json<<$EOF" >> "$GITHUB_OUTPUT" - echo "$NEEDS_REVIEW" >> "$GITHUB_OUTPUT" - echo "$EOF" >> "$GITHUB_OUTPUT" - fi - - - name: Build summary - if: steps.stale.outputs.has_stale == 'true' - id: summary - run: | - node -e " - const stale = JSON.parse(process.env.STALE_JSON); - const lines = stale.map(s => - '- **' + s.skill + '** (' + s.library + '): ' + s.reasons.join(', ') - ); - const summary = lines.join('\n'); - - const prompt = [ - 'Review and update the following stale intent skills for {{PACKAGE_NAME}}:', - '', - ...stale.map(s => '- ' + s.skill + ': ' + s.reasons.join(', ')), - '', - 'For each stale skill:', - '1. Read the current SKILL.md file', - '2. Check what changed in the library since the skill was last updated', - '3. Update the skill content to reflect current APIs and behavior', - '4. Run \`npx @tanstack/intent validate\` to verify the updated skill', - ].join('\n'); - - // Write outputs - const fs = require('fs'); - const env = fs.readFileSync(process.env.GITHUB_OUTPUT, 'utf8'); - const eof = require('crypto').randomBytes(15).toString('base64'); - fs.appendFileSync(process.env.GITHUB_OUTPUT, - 'summary<<' + eof + '\n' + summary + '\n' + eof + '\n' + - 'prompt<<' + eof + '\n' + prompt + '\n' + eof + '\n' - ); - " - env: - STALE_JSON: ${{ steps.stale.outputs.stale_json }} - - - name: Open review PR - if: steps.stale.outputs.has_stale == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION="${{ github.event.release.tag_name || 'manual' }}" - BRANCH="skills/review-${VERSION}" - - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git checkout -b "$BRANCH" - git commit --allow-empty -m "chore: review stale skills for ${VERSION}" - git push origin "$BRANCH" - - gh pr create \ - --title "Review stale skills (${VERSION})" \ - --body "$(cat <<'PREOF' - ## Stale Skills Detected - - The following skills may need updates after the latest release: - - ${{ steps.summary.outputs.summary }} - - --- - - ### Update Prompt - - Paste this into your coding agent (Claude Code, Cursor, etc.): - - ~~~ - ${{ steps.summary.outputs.prompt }} - ~~~ - - PREOF - )" \ - --head "$BRANCH" \ - --base main +# check-skills.yml — Drop this into your library repo's .github/workflows/ +# +# Checks for stale intent skills after a release and opens a review PR +# if any skills need attention. The PR body includes a prompt you can +# paste into Claude Code, Cursor, or any coding agent to update them. +# +# Triggers: new release published, or manual workflow_dispatch. +# +# Template variables (replaced by `intent setup`): +# {{PACKAGE_NAME}} — e.g. @tanstack/query + +name: Check Skills + +on: + release: + types: [published] + workflow_dispatch: {} + +permissions: + contents: write + pull-requests: write + +jobs: + check: + name: Check for stale skills + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install intent + run: npm install {{PACKAGE_NAME}} + + - name: Check staleness + id: stale + run: | + OUTPUT=$(npx @tanstack/intent stale --json 2>&1) || true + echo "$OUTPUT" + + # Check if any skills need review + NEEDS_REVIEW=$(echo "$OUTPUT" | node -e " + const input = require('fs').readFileSync('/dev/stdin','utf8'); + try { + const reports = JSON.parse(input); + const stale = reports.flatMap(r => + r.skills.filter(s => s.needsReview).map(s => ({ library: r.library, skill: s.name, reasons: s.reasons })) + ); + if (stale.length > 0) { + console.log(JSON.stringify(stale)); + } + } catch {} + ") + + if [ -z "$NEEDS_REVIEW" ]; then + echo "has_stale=false" >> "$GITHUB_OUTPUT" + else + echo "has_stale=true" >> "$GITHUB_OUTPUT" + # Escape for multiline GH output + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) + echo "stale_json<<$EOF" >> "$GITHUB_OUTPUT" + echo "$NEEDS_REVIEW" >> "$GITHUB_OUTPUT" + echo "$EOF" >> "$GITHUB_OUTPUT" + fi + + - name: Build summary + if: steps.stale.outputs.has_stale == 'true' + id: summary + run: | + node -e " + const stale = JSON.parse(process.env.STALE_JSON); + const lines = stale.map(s => + '- **' + s.skill + '** (' + s.library + '): ' + s.reasons.join(', ') + ); + const summary = lines.join('\n'); + + const prompt = [ + 'Review and update the following stale intent skills for {{PACKAGE_NAME}}:', + '', + ...stale.map(s => '- ' + s.skill + ': ' + s.reasons.join(', ')), + '', + 'For each stale skill:', + '1. Read the current SKILL.md file', + '2. Check what changed in the library since the skill was last updated', + '3. Update the skill content to reflect current APIs and behavior', + '4. Run \`npx @tanstack/intent validate\` to verify the updated skill', + ].join('\n'); + + // Write outputs + const fs = require('fs'); + const env = fs.readFileSync(process.env.GITHUB_OUTPUT, 'utf8'); + const eof = require('crypto').randomBytes(15).toString('base64'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, + 'summary<<' + eof + '\n' + summary + '\n' + eof + '\n' + + 'prompt<<' + eof + '\n' + prompt + '\n' + eof + '\n' + ); + " + env: + STALE_JSON: ${{ steps.stale.outputs.stale_json }} + + - name: Open review PR + if: steps.stale.outputs.has_stale == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${{ github.event.release.tag_name || 'manual' }}" + BRANCH="skills/review-${VERSION}" + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git checkout -b "$BRANCH" + git commit --allow-empty -m "chore: review stale skills for ${VERSION}" + git push origin "$BRANCH" + + gh pr create \ + --title "Review stale skills (${VERSION})" \ + --body "$(cat <<'PREOF' + ## Stale Skills Detected + + The following skills may need updates after the latest release: + + ${{ steps.summary.outputs.summary }} + + --- + + ### Update Prompt + + Paste this into your coding agent (Claude Code, Cursor, etc.): + + ~~~ + ${{ steps.summary.outputs.prompt }} + ~~~ + + PREOF + )" \ + --head "$BRANCH" \ + --base main diff --git a/packages/intent/meta/templates/workflows/notify-playbooks.yml b/packages/intent/meta/templates/workflows/notify-playbooks.yml index cc186856..edc4b5b2 100644 --- a/packages/intent/meta/templates/workflows/notify-playbooks.yml +++ b/packages/intent/meta/templates/workflows/notify-playbooks.yml @@ -1,52 +1,52 @@ -# notify-intent.yml — Drop this into your library repo's .github/workflows/ -# -# Fires a repository_dispatch event to TanStack/intent whenever docs or -# source files change on merge to main. This triggers the skill staleness -# check workflow in the intent repo. -# -# Requirements: -# - A fine-grained PAT with contents:write on TanStack/intent stored -# as the INTENT_NOTIFY_TOKEN repository secret. -# -# Template variables (replaced by `intent setup`): -# {{PACKAGE_NAME}} — e.g. @tanstack/query -# {{DOCS_PATH}} — e.g. docs/** -# {{SRC_PATH}} — e.g. packages/query-core/src/** - -name: Notify Intent - -on: - push: - branches: [main] - paths: - - '{{DOCS_PATH}}' - - '{{SRC_PATH}}' - -jobs: - notify: - name: Notify TanStack Intent - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - - name: Collect changed files - id: changes - run: | - FILES=$(git diff --name-only HEAD~1 HEAD | jq -R -s -c 'split("\n") | map(select(length > 0))') - echo "files=$FILES" >> "$GITHUB_OUTPUT" - - - name: Dispatch to intent repo - uses: peter-evans/repository-dispatch@v3 - with: - token: ${{ secrets.INTENT_NOTIFY_TOKEN }} - repository: TanStack/intent - event-type: skill-check - client-payload: | - { - "package": "{{PACKAGE_NAME}}", - "sha": "${{ github.sha }}", - "changed_files": ${{ steps.changes.outputs.files }} - } +# notify-intent.yml — Drop this into your library repo's .github/workflows/ +# +# Fires a repository_dispatch event to TanStack/intent whenever docs or +# source files change on merge to main. This triggers the skill staleness +# check workflow in the intent repo. +# +# Requirements: +# - A fine-grained PAT with contents:write on TanStack/intent stored +# as the INTENT_NOTIFY_TOKEN repository secret. +# +# Template variables (replaced by `intent setup`): +# {{PACKAGE_NAME}} — e.g. @tanstack/query +# {{DOCS_PATH}} — e.g. docs/** +# {{SRC_PATH}} — e.g. packages/query-core/src/** + +name: Notify Intent + +on: + push: + branches: [main] + paths: + - '{{DOCS_PATH}}' + - '{{SRC_PATH}}' + +jobs: + notify: + name: Notify TanStack Intent + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Collect changed files + id: changes + run: | + FILES=$(git diff --name-only HEAD~1 HEAD | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "files=$FILES" >> "$GITHUB_OUTPUT" + + - name: Dispatch to intent repo + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ secrets.INTENT_NOTIFY_TOKEN }} + repository: TanStack/intent + event-type: skill-check + client-payload: | + { + "package": "{{PACKAGE_NAME}}", + "sha": "${{ github.sha }}", + "changed_files": ${{ steps.changes.outputs.files }} + } diff --git a/packages/intent/meta/templates/workflows/validate-skills.yml b/packages/intent/meta/templates/workflows/validate-skills.yml index 8f39716a..ac6a1eae 100644 --- a/packages/intent/meta/templates/workflows/validate-skills.yml +++ b/packages/intent/meta/templates/workflows/validate-skills.yml @@ -1,52 +1,52 @@ -# validate-skills.yml — Drop this into your library repo's .github/workflows/ -# -# Validates skill files on PRs that touch the skills/ directory. -# Ensures frontmatter is correct, names match paths, and files stay under -# the 500-line limit. - -name: Validate Skills - -on: - pull_request: - paths: - - 'skills/**' - - '**/skills/**' - -jobs: - validate: - name: Validate skill files - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install intent CLI - run: npm install -g @tanstack/intent - - - name: Find and validate skills - run: | - # Find all directories containing SKILL.md files - SKILLS_DIR="" - if [ -d "skills" ]; then - SKILLS_DIR="skills" - elif [ -d "packages" ]; then - # Monorepo — find skills/ under packages - for dir in packages/*/skills; do - if [ -d "$dir" ]; then - echo "Validating $dir..." - intent validate "$dir" - fi - done - exit 0 - fi - - if [ -n "$SKILLS_DIR" ]; then - intent validate "$SKILLS_DIR" - else - echo "No skills/ directory found — skipping validation." - fi +# validate-skills.yml — Drop this into your library repo's .github/workflows/ +# +# Validates skill files on PRs that touch the skills/ directory. +# Ensures frontmatter is correct, names match paths, and files stay under +# the 500-line limit. + +name: Validate Skills + +on: + pull_request: + paths: + - 'skills/**' + - '**/skills/**' + +jobs: + validate: + name: Validate skill files + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install intent CLI + run: npm install -g @tanstack/intent + + - name: Find and validate skills + run: | + # Find all directories containing SKILL.md files + SKILLS_DIR="" + if [ -d "skills" ]; then + SKILLS_DIR="skills" + elif [ -d "packages" ]; then + # Monorepo — find skills/ under packages + for dir in packages/*/skills; do + if [ -d "$dir" ]; then + echo "Validating $dir..." + intent validate "$dir" + fi + done + exit 0 + fi + + if [ -n "$SKILLS_DIR" ]; then + intent validate "$SKILLS_DIR" + else + echo "No skills/ directory found — skipping validation." + fi diff --git a/packages/intent/meta/tree-generator/SKILL.md b/packages/intent/meta/tree-generator/SKILL.md index 1954a705..a82a3b97 100644 --- a/packages/intent/meta/tree-generator/SKILL.md +++ b/packages/intent/meta/tree-generator/SKILL.md @@ -1,892 +1,892 @@ ---- -name: skill-tree-generator -description: > - Generate, update, and version a complete skill tree (collection of SKILL.md - files) for any JavaScript or TypeScript library. Produces core skills - (framework-agnostic) and framework skills (React, Solid, Vue bindings) - with dependency linking. Activate when producing skill files from a domain - map, updating existing skills after a library version change, or auditing - skill accuracy. Takes domain_map.yaml and skill_spec.md from - skill-domain-discovery as primary inputs. -metadata: - version: '3.0' - category: meta-tooling - input_artifacts: - - skills/_artifacts/domain_map.yaml - - skills/_artifacts/skill_spec.md - output_artifacts: - - skills/_artifacts/skill_tree.yaml - skills: - - skill-domain-discovery ---- - -# Skill Tree Generator - -You produce and maintain a tree of SKILL.md files for a library. Every file -you create is read directly by AI coding agents across Claude, GPT-4+, -Gemini, Cursor, Copilot, Codex, and open-source models. Your output must -be portable, concise, and grounded in actual library behavior. - -### Skill types - -Every skill has a `type` field in its frontmatter. Valid types: - -| Type | Purpose | Example | -| ------------- | ---------------------------------------------------------- | ------------------------- | -| `core` | Framework-agnostic concepts, configuration, patterns | `db-core` | -| `sub-skill` | A focused sub-topic within a core or framework skill | `db-core/live-queries` | -| `framework` | Framework-specific bindings, hooks, components | `react-db` | -| `lifecycle` | Cross-cutting developer journey (getting started, go-live) | `electric-quickstart` | -| `composition` | Integration between two or more libraries | `electric-drizzle` | -| `security` | Audit checklist or security validation | `electric-security-check` | - -Agents discover skills via `tanstack intent list` and read them directly -from `node_modules`. Framework skills declare a `requires` dependency on -their core skill so agents load them in the right order. - -There are two workflows. Detect which applies. - -**Workflow A — Generate:** Build a complete skill tree from a domain map. -**Workflow B — Update:** Diff a library version change and update skills. - ---- - -## Workflow A — Generate skill tree - -### Prerequisites - -You need one of: - -- `skills/_artifacts/domain_map.yaml` and `skills/_artifacts/skill_spec.md` - from skill-domain-discovery -- Raw library documentation and source code (run a compressed domain - discovery first) - -If starting from raw docs without a domain map, run a compressed -discovery. This produces lower-fidelity output than the full -skill-domain-discovery skill — prefer running that when time permits. - -1. Build a concept inventory (every export, config key, constraint, warning) -2. Group into capability domains using work-oriented names (let library complexity drive the count — 2–3 for focused libraries, more for large frameworks) -3. Enumerate 10–20 task-focused skills from the intersection of domains - and developer tasks -4. Extract 3+ failure modes per skill (plausible, silent, grounded) -5. Proceed to Step 1 below - -### Scaffold flow output - -If the maintainer uses a custom skills root, replace `skills/` in the paths -below with their chosen directory. - -For the scaffold workflow, produce a single artifact before writing any -SKILL.md files: - -- `skills/_artifacts/skill_tree.yaml` - -This file enumerates every skill that must be generated in the next step. -Do not write SKILL.md files yet unless explicitly asked. - -Use this format: - -```yaml -# skills/_artifacts/skill_tree.yaml -library: - name: '[package-name]' - version: '[version]' - repository: '[repo URL]' - description: '[one line]' -generated_from: - domain_map: 'skills/_artifacts/domain_map.yaml' - skill_spec: 'skills/_artifacts/skill_spec.md' -generated_at: '[ISO date]' - -skills: - - name: '[task-focused skill name]' - slug: '[kebab-case]' - type: 'core | sub-skill | framework | lifecycle | composition | security' - domain: '[domain slug]' - path: 'skills/[path]/SKILL.md' - package: '[package directory, e.g. packages/client]' # monorepo only — which package this skill belongs to - description: '[1–2 sentence agent-facing routing key]' - requires: - - '[other skill slugs]' # omit if none - sources: - - '[Owner/repo]:docs/[path].md' - - '[Owner/repo]:src/[path].ts' - subsystems: - - '[adapter/backend name]' # omit if none - references: - - 'references/[file].md' # omit if none -``` - -**Monorepo layout:** For monorepos, each skill's `path` is relative to its -package directory (e.g. `packages/client/skills/core/SKILL.md`). Set the -`package` field so generate-skill knows where to write the file. The domain -map artifacts stay at the repo root. - -### Minimal library fast path - -If the domain map contains **fewer than 5 skills** and no framework -adapter packages, skip the core overview + sub-skill registry pattern. -Instead: - -- Use **flat structure** — each skill gets its own `skills/[skill-name]/SKILL.md` -- **No router skill** — the intent CLI `list` command is sufficient for discovery -- **No core overview skill** — go directly to individual skill files -- Each skill is type `core` (not `sub-skill`) and stands alone without - a parent registry -- Skip Step 2 (core overview) and Step 3 (sub-skills) — go directly to - writing individual skills as standalone core skills using Step 3's body - format - -This avoids unnecessary scaffolding for focused libraries where the -overhead of a hierarchical skill tree exceeds the navigation benefit. - -### Step 1 — Plan the file tree - -From the domain map, each entry in the `skills` list becomes a SKILL.md -file. The `type` field on each skill (`core`, `framework`, `lifecycle`, -`composition`) determines where it goes. Determine the file tree: - -**Core vs framework decision:** - -| Content | Goes in... | -| ---------------------------------------------- | ---------- | -| Mental models, concepts, lifecycle | Core | -| Configuration options and their effects | Core | -| Type system, generics, inference | Core | -| Common mistakes that apply to all frameworks | Core | -| Hooks (`useX`, `createX`) | Framework | -| Components (``, ``) | Framework | -| Provider setup and wiring | Framework | -| SSR/hydration patterns specific to a framework | Framework | -| Framework-specific gotchas | Framework | - -If a library has no framework adapters (e.g. Store, DB), produce only -core skills. - -**Framework-integration domain decomposition:** If the domain map from -skill-domain-discovery contains a single "Framework Integration" domain -and the library has separate framework adapter packages, decompose it -into per-framework skills co-located with each adapter package. Do not -produce a single monolithic framework-integration skill that covers -React, Vue, Solid, etc. in one file. - -**Adapter-heavy domains:** When a domain covers multiple backends or -adapters with distinct config interfaces (e.g. 5 sync adapters, 3 -database drivers), keep one SKILL.md for the shared patterns but -produce one reference file per adapter with its specific config, -setup, and gotchas. The SKILL.md covers what's common; each -`references/[adapter].md` covers what's unique. - -**Flat vs nested structure:** - -Choose the structure that matches how the domain map's skills are shaped. - -Use **nested** (`[lib]-core/[domain]/SKILL.md`) when: - -- Developer tasks cluster cleanly into 3–5 conceptual domains -- The library has a clear core + framework adapter split -- Skills build on each other in a layered way - -Use **flat** (`skills/[skill-name]/SKILL.md`) when: - -- Developer tasks are task-focused and don't nest into domains -- The domain discovery process recommended task-focused skills -- Skills map 1:1 to distinct developer intents with minimal overlap - -Both are valid. The domain map's `type` field and structure will signal -which fits. When in doubt, prefer flat — it's simpler and each skill -is independently discoverable. - -**Nested structure:** - -``` -skills/ -├── [lib]-core/ # Core skill for the library -│ ├── SKILL.md # Core overview + sub-skill registry -│ ├── [domain-1]/ -│ │ └── SKILL.md # Core sub-skill -│ ├── [domain-2]/ -│ │ └── SKILL.md -│ └── references/ # Optional overflow content -│ └── options.md -├── react-[lib]/ # React framework skill -│ ├── SKILL.md # React overview + sub-skill registry -│ ├── [domain-1]/ -│ │ └── SKILL.md # React-specific sub-skill -│ └── references/ -├── solid-[lib]/ # Solid framework skill (if applicable) -│ └── SKILL.md -├── vue-[lib]/ # Vue framework skill (if applicable) -│ └── SKILL.md -``` - -**Flat structure:** - -``` -skills/ -├── [lib]-shapes/ # Task-focused skill -│ ├── SKILL.md -│ └── references/ -│ └── shape-options.md -├── [lib]-auth/ # Another task skill -│ └── SKILL.md -├── [lib]-proxy/ -│ └── SKILL.md -├── [lib]-quickstart/ # Lifecycle skill -│ └── SKILL.md -├── [lib]-go-live/ # Lifecycle skill -│ └── SKILL.md -├── [lib]-drizzle/ # Composition skill -│ └── SKILL.md -``` - -**Router skill:** A router skill (lightweight entry point with a decision -table) is optional. If the intent CLI provides `list` and `show` -commands, agents can discover skills directly without a router. Only -create a router skill if the skill set is large enough (15+) that -browsing the list is insufficient, or if the nested structure needs -an entry point to guide agents to the right sub-skill. Libraries with -fewer than 5 skills should never have a router skill. - -**Source repository layout for npm distribution:** - -Skills must ship with their respective packages so they're available in -`node_modules` after install. In a monorepo, co-locate skills with the -package they document: - -``` -packages/ -├── [lib]/ # Core package -│ ├── src/ -│ ├── skills/ # Core skills live here -│ │ ├── [lib]-core/ -│ │ │ ├── SKILL.md -│ │ │ └── [domain]/SKILL.md -│ │ └── compositions/ # Composition skills with co-used libs -│ └── package.json # Add "skills" to files array -├── react-[lib]/ # React adapter package -│ ├── src/ -│ ├── skills/ # React framework skills live here -│ │ └── react-[lib]/ -│ │ └── SKILL.md -│ └── package.json # Add "skills" to files array -``` - -Add `"skills"` to each package's `files` array in `package.json` so -skill files are included in the published npm tarball: - -```json -{ - "files": ["dist", "src", "skills"] -} -``` - -### Step 2 — Write the core skill - -The core skill is the foundational overview for the library. It covers -framework-agnostic concepts and contains the sub-skill registry. - -**Frontmatter:** - -```yaml ---- -name: [lib]-core -description: > - [1–3 sentences. What this library does and the framework-agnostic - concepts it provides. Pack with keywords: function names, config - options, concepts. This is a routing key, not a human summary.] -type: core -library: [lib] -library_version: "[version this targets]" ---- -``` - -**Body template:** - -```markdown -# [Library Name] — Core Concepts - -[One paragraph: what this library is, what problem it solves. Factual, -not promotional. Framework-agnostic.] - -## Sub-Skills - -| Need to... | Read | -| ---------- | ------------------------------ | -| [task 1] | [lib]-core/[domain-1]/SKILL.md | -| [task 2] | [lib]-core/[domain-2]/SKILL.md | - -## Quick Decision Tree - -- Setting up for the first time? → [lib]-core/[setup-domain] -- Working with [concept]? → [lib]-core/[concept-domain] -- Debugging [issue]? → [lib]-core/[domain] § Common Mistakes - -## Version - -Targets [library] v[X.Y.Z]. -``` - -### Step 3 — Write core sub-skills - -One SKILL.md per domain. Follow this structure exactly. - -**Frontmatter:** - -```yaml ---- -name: [lib]-core/[domain-slug] -description: > - [1–3 sentences. What this domain covers AND when to load it. Name - specific functions, options, or APIs. Dense routing key.] -type: sub-skill -library: [lib] -library_version: "[version]" -sources: - - "[repo]:docs/[path].md" - - "[repo]:src/[path].ts" ---- -``` - -**Body sections — in this order:** - -**1. Setup** - -Minimum working example for this domain. - -- Use the library's core API, not framework-specific hooks -- Real package imports with exact names -- No `// ...` or `[your code here]` — complete and copy-pasteable -- If a concept is better explained with a framework hook, reference the - framework skill: "For React usage, see `react-[lib]/SKILL.md`" - -**2. Core Patterns** - -2–4 patterns. For each: - -- One-line heading: what it accomplishes -- Complete code block using core API -- One sentence of explanation only if not self-explanatory -- No framework-specific code — use core abstractions - -**3. Common Mistakes** - -Each `failure_mode` entry from the domain map becomes a Common Mistake -entry in the SKILL file. Minimum 3 entries. Complex domains target 5–6. - -**Cross-skill failure modes:** The domain map may contain failure modes -with a `skills` list naming multiple skill slugs. Write these into -every SKILL file whose skill is listed. A developer loading the SSR -skill and a developer loading the state management skill both need to -see "stale state during hydration" — the same advice must appear in -both files. Do not deduplicate across skills at the cost of coverage. - -Format: - -````markdown -### [PRIORITY] [What goes wrong — 5–8 word phrase] - -Wrong: - -```[lang] -// code that looks correct but isn't -``` -```` - -Correct: - -```[lang] -// code that works -``` - -[One sentence: the specific mechanism by which the wrong version fails.] - -Source: [doc page or source file:line] - -```` - -Priority levels: -- **CRITICAL** — Breaks in production. Security risk or data loss. -- **HIGH** — Incorrect behavior under common conditions. -- **MEDIUM** — Incorrect under specific conditions or edge cases. - -Every mistake must be plausible (an agent would generate it), silent -(no immediate crash), and grounded (traceable to doc or source). - -**Failure mode status from domain map:** The domain map may include a -`status` field on failure modes. Handle as follows: -- `active` — Include as a normal Common Mistake entry -- `fixed-but-legacy-risk` — Include with a note: "Fixed in v[X] but - agents trained on older code may still generate this pattern" -- `removed` — Do not include. The bug is fixed and the pattern is no - longer relevant. - -**4. References** (only when needed) - -```markdown -## References - -- [Complete option reference](references/options.md) -```` - -Create reference files when any of these apply — not just length overflow: - -- **Length:** The skill would exceed 500 lines without them -- **Multiple subsystems:** The domain covers 3+ independent backends, - adapters, or providers with distinct config interfaces. Create one - reference file per subsystem (e.g. `references/electric-adapter.md`, - `references/query-adapter.md`) -- **Dense API surface:** A topic has >10 distinct API patterns, operators, - or option shapes that agents need for implementation. Move the full - reference to `references/` and keep only the most common 2–3 in the - SKILL.md -- **Deep validation/schema patterns:** If the library has schema - validation, type transforms (TInput/TOutput), or similar deep - configuration surfaces, give them a dedicated reference file even if - they technically fit in the parent skill - -### Step 4 — Write framework skills - -Framework skills build on their core skill. They cover only what is -specific to the framework — hooks, components, providers, and -framework-specific patterns and mistakes. - -**Frontmatter:** - -```yaml ---- -name: react-[lib] -description: > - [1–3 sentences. React-specific bindings for [library]. Name the hooks, - components, and providers. Mention React-specific patterns like SSR - hydration if applicable.] -type: framework -library: [lib] -framework: react -library_version: "[version]" -requires: - - [lib]-core ---- -``` - -**Body template:** - -```markdown -This skill builds on [lib]-core. Read [lib]-core first for foundational -concepts before applying React-specific patterns. - -# [Library Name] — React - -## Setup - -[React-specific setup: provider, hook wiring, app entry point] - -## Hooks and Components - -[React hooks and components with complete examples] - -## React-Specific Patterns - -[Patterns that only apply in React: concurrent features, Suspense -integration, SSR/hydration, etc.] - -## Common Mistakes - -[Only React-specific mistakes. Do not repeat core mistakes. Examples: -calling hooks outside provider, missing Suspense boundary, hydration -mismatch, etc.] -``` - -**Framework sub-skills** follow the same pattern as core sub-skills but -with the framework frontmatter: - -```yaml ---- -name: react-[lib]/[domain-slug] -description: > - [React-specific description for this domain.] -type: sub-skill -library: [lib] -framework: react -library_version: "[version]" -requires: - - [lib]-core - - [lib]-core/[domain-slug] ---- - -This skill builds on [lib]-core/[domain-slug]. Read the core skill first. -``` - -### Step 5 — Write cross-domain tension notes - -The domain map may contain a `tensions` section listing design conflicts -between domains. For each tension, add a brief note to the Common -Mistakes section of every SKILL file whose domain is involved. Format: - -```markdown -### HIGH Tension: [short phrase] - -This domain's patterns conflict with [other domain]. [One sentence -describing the pull.] Agents optimizing for [this domain's goal] -tend to [specific mistake] because they don't account for [other -domain's constraint]. - -See also: [lib]-core/[other-domain]/SKILL.md § Common Mistakes -``` - -The cross-reference ensures agents that load one skill are pointed -toward the related skill where the other side of the tension lives. - -Also check the domain map's `cross_references` section for non-tension -relationships between skills. For each cross-reference, add a "See also" -line at the end of the relevant skill's body: - -```markdown -See also: [other-skill]/SKILL.md — [reason] -``` - -### Step 6 — Write composition skills (if applicable) - -Use the `compositions` entries from `domain_map.yaml` (populated during -skill-domain-discovery Phase 3h) to identify which composition skills -to produce. - -Composition skills cover how two or more libraries work together. These -are framework-specific by default (the integration patterns depend on -framework hooks and providers). - -**Frontmatter:** - -```yaml ---- -name: compositions/[lib-a]-[lib-b] -description: > - [How lib-a and lib-b wire together. Name the specific integration - points: functions, hooks, patterns.] -type: composition -library_version: "[version of primary lib]" -requires: - - [lib-a]-core - - react-[lib-a] - - [lib-b]-core - - react-[lib-b] ---- - -This skill requires familiarity with both [lib-a] and [lib-b]. -Read their core and framework skills first. -``` - -**Body structure:** - -1. **Integration Setup** — How to wire the two libraries together -2. **Core Integration Patterns** — 2–4 patterns showing them working in concert -3. **Common Mistakes** — Mistakes that only occur at the integration boundary - -Do not duplicate content from either library's individual skills. Focus -exclusively on the seam between them. - -### Step 7 — Write checklist/audit skills (where applicable) - -Some skills don't fit the standard body structure (Setup → Core Patterns -→ Common Mistakes). Security, go-live, and some lifecycle skills are -audit-oriented — the agent runs through a checklist to verify correctness -rather than learning patterns. Use the alternative body structure below -for these skill types. - -**When to use the checklist body:** - -- `security` type skills — pre-deploy security validation -- `lifecycle` type skills focused on verification (go-live, migration) -- Any skill where the primary action is "check these things" not "learn - these patterns" - -**Frontmatter:** - -```yaml ---- -name: react-[lib]/security -description: > - Go-live security validation for [library]. Checks [specific concerns]. -type: security -library: [lib] -framework: react -library_version: '[version]' -requires: - - react-[lib] ---- -``` - -**Alternative body template (checklist/audit):** - -````markdown -# [Library Name] — [Security | Go-Live | Migration] Checklist - -Run through each section before [deploying | releasing | migrating]. - -## [Category 1] Checks - -### Check: [what to verify] - -Expected: - -```[lang] -// correct configuration or code -``` -```` - -Fail condition: [what indicates this check failed] -Fix: [one-line remediation] - -### Check: [what to verify] - -[same structure] - -## [Category 2] Checks - -[same structure] - -## Common Security Mistakes - -[Wrong/correct pairs specific to this library, same format as -Common Mistakes in standard skills] - -## Pre-Deploy Summary - -- [ ] [Verification 1] -- [ ] [Verification 2] -- [ ] [Verification 3] - -```` - -The key differences from the standard body: -- No "Setup" section — the agent already has the app running -- Checks replace "Core Patterns" — each check is a verification, not a - teaching pattern -- The summary checklist at the end gives agents a quick pass/fail list -- Common Mistakes section is still present for wrong/correct pairs - -### Step 8 — Validate the complete tree - -Run every check before outputting. Fix any failures before proceeding. - -| Check | Rule | -|-------|------| -| Every skill from domain_map has a SKILL.md | No orphaned skills | -| Core/framework split is clean | No framework hooks in core skills | -| Every framework skill has `requires` | Links to its core skill | -| Framework skill opens with dependency note | "builds on [core]" prose line | -| Every skill under 500 lines | Move excess to references/ | -| Every code block has real imports | Exact package name, correct adapter | -| No concept explanations | No "TypeScript is...", no "React hooks are..." | -| No marketing prose | First body line is heading or dependency note | -| Every code block is complete | Works without modification when pasted | -| Common Mistakes are silent | Not obvious compile errors | -| Common Mistakes are library-specific | Not generic TS/React mistakes | -| Common Mistakes are sourced | Every mistake traceable to doc or source | -| Core skills reference framework skills | "For React usage, see..." | -| Framework skills don't repeat core content | Only framework-specific | -| Composition skills don't repeat individual skills | Only the seam | -| `name` matches directory path | `router-core/search-params` → `router-core/search-params/SKILL.md` | -| `sources` filled in sub-skills | At least one repo:path per sub-skill | -| Cross-skill failures in all relevant files | Failure modes with multiple `skills` appear in each listed SKILL.md | -| Tensions noted in affected skills | Each tension has notes in all involved domain skills | -| Framework domains decomposed per-package | No single skill covering multiple framework adapters | -| Adapter-heavy domains have references | 3+ adapters/backends → one reference file per adapter | -| Dense API surfaces in references | >10 distinct patterns → reference file, not inline | -| Checklist skills use audit body | Security/go-live skills use checklist template, not Setup → Core Patterns → Common Mistakes | - ---- - -## Workflow B — Update existing skills - -### Trigger conditions - -Run when: -- The library has released a new version -- A maintainer reports skills produce outdated code -- A changelog or migration guide has been published since skill creation -- Feedback reports indicate skill content is inaccurate - -### Step 1 — Detect staleness - -Compare each skill's `library_version` against the current library version. - -1. Read changelog entries between the two versions -2. Read migration guide (if one exists) -3. For each skill, check if its `sources` files have changed - -Produce a staleness report: - -```yaml -# staleness_report.yaml -library: "[name]" -library_version_in_skills: "[old]" -library_version_current: "[new]" - -stale_skills: - - skill: "[skill name]" - reason: "[what changed]" - severity: "[BREAKING | DEPRECATION | BEHAVIORAL | ADDITIVE]" - changelog_entry: "[relevant entry]" - affected_sections: - - "[Setup | Core Patterns | Common Mistakes]" - -current_skills: - - skill: "[skill name]" - reason: "[no changes affect this domain]" -```` - -### Step 2 — Update stale skills - -**BREAKING changes:** - -1. Old pattern becomes a new Common Mistake entry (wrong/correct pair) -2. Update Setup if initialization changed -3. Update Core Patterns if idiomatic approach changed -4. Bump `library_version` in frontmatter -5. Check both core AND framework skills — breaking changes may affect both - -**DEPRECATION changes:** - -1. Add Common Mistake: deprecated API as wrong, replacement as correct -2. Update Core Patterns to use non-deprecated API -3. Bump `library_version` - -**BEHAVIORAL changes:** - -1. Default value changed → add Common Mistake entry -2. Type signature more restrictive → add Common Mistake entry -3. Update affected code blocks -4. Bump `library_version` - -**ADDITIVE changes:** - -1. Evaluate if new feature belongs in existing domain or needs a new skill -2. If existing: add to Core Patterns or references/ -3. If new skill needed: create it and update the parent skill's sub-skill - registry -4. Bump `library_version` - -### Step 3 — Produce a changelog entry - -```markdown -## [date] - -### Updated for [library] v[new version] - -**Breaking changes:** - -- [skill name]: [what changed and why] - -**Deprecation updates:** - -- [skill name]: [old API] → [new API] - -**New skills:** - -- [skill name]: [what it covers] -``` - ---- - -## Constraints — verify for every file - -| Check | Rule | -| ------------------------------------------- | ----------------------------------------------------------------------------------- | -| Under 500 lines per SKILL.md | Move excess to references/; also create references for content depth | -| Real imports in every code block | Exact package, correct adapter | -| No external concept explanations | No "TypeScript is...", no "React hooks are..." — library-specific concepts are fine | -| No marketing prose | First body line is heading, code, or dependency note | -| Complete code blocks | Every block works without modification | -| Common Mistakes are silent | Not obvious compile errors | -| Common Mistakes are library-specific | Not generic TS/React mistakes | -| Common Mistakes are sourced | Traceable to doc or source | -| Core skills are framework-agnostic | No hooks, no components, no providers | -| Framework skills have `requires` | Lists core dependency | -| Framework skills open with dependency note | First prose line references core | -| Composition skills require all dependencies | Lists all core + framework skills | -| `name` matches directory | `router-core/search-params` → file at that path | -| `library_version` in every frontmatter | Which version the skill targets | -| Cross-skill failures duplicated | Each listed skill gets the failure mode | -| Tensions cross-referenced | Tension notes in each involved skill point to the other | -| Skills ship with packages | `"skills"` in package.json `files` array | -| Checklist skills use audit template | Security/go-live skills use checklist body, not standard body | - ---- - -## Cross-model compatibility - -Output is consumed by all major AI coding agents. To ensure consistency: - -- Markdown with YAML frontmatter — universally parsed -- No XML tags in generated skill content -- Code blocks use triple backticks with language annotation -- Section boundaries use ## headers -- Descriptions are keyword-packed for routing -- Examples show concrete values, never placeholders -- Positive instructions ("Use X") over negative ("Don't use Y") -- Critical info at start or end of sections (not buried in middle) -- Each SKILL.md is self-contained except for declared `requires` - ---- - -## Output order - -When generating a complete skill tree: - -1. Core overview SKILL.md — entry point for the library -2. Core sub-skills in domain order -3. Framework overview SKILL.md for each framework -4. Framework sub-skills -5. Composition skills (if applicable) -6. Security skills (if applicable) -7. references/ files for any skill that needs them -8. CHANGELOG.md entry - -When updating: - -1. staleness_report.yaml -2. Updated SKILL.md files (core then framework) -3. CHANGELOG.md entry - ---- - -## Meta-skill feedback (alpha default) - -After producing the skill tree artifact, update a single Markdown feedback -draft for all three meta skills used in scaffolding. If a draft exists from -Domain Discovery, keep it and fill only the **Tree Generator** section. If -no draft exists, create it using this exact template. - -``` -# Intent Meta Skill Feedback - -## Domain Discovery -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Tree Generator -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Generate Skill -- What worked well: -- What was confusing or missing: -- Suggestions for improvement: -- Overall rating: good | mixed | bad - -## Context (optional) -- Library: -- Repo: -- Docs: -- Notes: -``` - -Do not submit feedback yet. Carry this draft forward to the generate-skill -step. +--- +name: skill-tree-generator +description: > + Generate, update, and version a complete skill tree (collection of SKILL.md + files) for any JavaScript or TypeScript library. Produces core skills + (framework-agnostic) and framework skills (React, Solid, Vue bindings) + with dependency linking. Activate when producing skill files from a domain + map, updating existing skills after a library version change, or auditing + skill accuracy. Takes domain_map.yaml and skill_spec.md from + skill-domain-discovery as primary inputs. +metadata: + version: '3.0' + category: meta-tooling + input_artifacts: + - skills/_artifacts/domain_map.yaml + - skills/_artifacts/skill_spec.md + output_artifacts: + - skills/_artifacts/skill_tree.yaml + skills: + - skill-domain-discovery +--- + +# Skill Tree Generator + +You produce and maintain a tree of SKILL.md files for a library. Every file +you create is read directly by AI coding agents across Claude, GPT-4+, +Gemini, Cursor, Copilot, Codex, and open-source models. Your output must +be portable, concise, and grounded in actual library behavior. + +### Skill types + +Every skill has a `type` field in its frontmatter. Valid types: + +| Type | Purpose | Example | +| ------------- | ---------------------------------------------------------- | ------------------------- | +| `core` | Framework-agnostic concepts, configuration, patterns | `db-core` | +| `sub-skill` | A focused sub-topic within a core or framework skill | `db-core/live-queries` | +| `framework` | Framework-specific bindings, hooks, components | `react-db` | +| `lifecycle` | Cross-cutting developer journey (getting started, go-live) | `electric-quickstart` | +| `composition` | Integration between two or more libraries | `electric-drizzle` | +| `security` | Audit checklist or security validation | `electric-security-check` | + +Agents discover skills via `tanstack intent list` and read them directly +from `node_modules`. Framework skills declare a `requires` dependency on +their core skill so agents load them in the right order. + +There are two workflows. Detect which applies. + +**Workflow A — Generate:** Build a complete skill tree from a domain map. +**Workflow B — Update:** Diff a library version change and update skills. + +--- + +## Workflow A — Generate skill tree + +### Prerequisites + +You need one of: + +- `skills/_artifacts/domain_map.yaml` and `skills/_artifacts/skill_spec.md` + from skill-domain-discovery +- Raw library documentation and source code (run a compressed domain + discovery first) + +If starting from raw docs without a domain map, run a compressed +discovery. This produces lower-fidelity output than the full +skill-domain-discovery skill — prefer running that when time permits. + +1. Build a concept inventory (every export, config key, constraint, warning) +2. Group into capability domains using work-oriented names (let library complexity drive the count — 2–3 for focused libraries, more for large frameworks) +3. Enumerate 10–20 task-focused skills from the intersection of domains + and developer tasks +4. Extract 3+ failure modes per skill (plausible, silent, grounded) +5. Proceed to Step 1 below + +### Scaffold flow output + +If the maintainer uses a custom skills root, replace `skills/` in the paths +below with their chosen directory. + +For the scaffold workflow, produce a single artifact before writing any +SKILL.md files: + +- `skills/_artifacts/skill_tree.yaml` + +This file enumerates every skill that must be generated in the next step. +Do not write SKILL.md files yet unless explicitly asked. + +Use this format: + +```yaml +# skills/_artifacts/skill_tree.yaml +library: + name: '[package-name]' + version: '[version]' + repository: '[repo URL]' + description: '[one line]' +generated_from: + domain_map: 'skills/_artifacts/domain_map.yaml' + skill_spec: 'skills/_artifacts/skill_spec.md' +generated_at: '[ISO date]' + +skills: + - name: '[task-focused skill name]' + slug: '[kebab-case]' + type: 'core | sub-skill | framework | lifecycle | composition | security' + domain: '[domain slug]' + path: 'skills/[path]/SKILL.md' + package: '[package directory, e.g. packages/client]' # monorepo only — which package this skill belongs to + description: '[1–2 sentence agent-facing routing key]' + requires: + - '[other skill slugs]' # omit if none + sources: + - '[Owner/repo]:docs/[path].md' + - '[Owner/repo]:src/[path].ts' + subsystems: + - '[adapter/backend name]' # omit if none + references: + - 'references/[file].md' # omit if none +``` + +**Monorepo layout:** For monorepos, each skill's `path` is relative to its +package directory (e.g. `packages/client/skills/core/SKILL.md`). Set the +`package` field so generate-skill knows where to write the file. The domain +map artifacts stay at the repo root. + +### Minimal library fast path + +If the domain map contains **fewer than 5 skills** and no framework +adapter packages, skip the core overview + sub-skill registry pattern. +Instead: + +- Use **flat structure** — each skill gets its own `skills/[skill-name]/SKILL.md` +- **No router skill** — the intent CLI `list` command is sufficient for discovery +- **No core overview skill** — go directly to individual skill files +- Each skill is type `core` (not `sub-skill`) and stands alone without + a parent registry +- Skip Step 2 (core overview) and Step 3 (sub-skills) — go directly to + writing individual skills as standalone core skills using Step 3's body + format + +This avoids unnecessary scaffolding for focused libraries where the +overhead of a hierarchical skill tree exceeds the navigation benefit. + +### Step 1 — Plan the file tree + +From the domain map, each entry in the `skills` list becomes a SKILL.md +file. The `type` field on each skill (`core`, `framework`, `lifecycle`, +`composition`) determines where it goes. Determine the file tree: + +**Core vs framework decision:** + +| Content | Goes in... | +| ---------------------------------------------- | ---------- | +| Mental models, concepts, lifecycle | Core | +| Configuration options and their effects | Core | +| Type system, generics, inference | Core | +| Common mistakes that apply to all frameworks | Core | +| Hooks (`useX`, `createX`) | Framework | +| Components (``, ``) | Framework | +| Provider setup and wiring | Framework | +| SSR/hydration patterns specific to a framework | Framework | +| Framework-specific gotchas | Framework | + +If a library has no framework adapters (e.g. Store, DB), produce only +core skills. + +**Framework-integration domain decomposition:** If the domain map from +skill-domain-discovery contains a single "Framework Integration" domain +and the library has separate framework adapter packages, decompose it +into per-framework skills co-located with each adapter package. Do not +produce a single monolithic framework-integration skill that covers +React, Vue, Solid, etc. in one file. + +**Adapter-heavy domains:** When a domain covers multiple backends or +adapters with distinct config interfaces (e.g. 5 sync adapters, 3 +database drivers), keep one SKILL.md for the shared patterns but +produce one reference file per adapter with its specific config, +setup, and gotchas. The SKILL.md covers what's common; each +`references/[adapter].md` covers what's unique. + +**Flat vs nested structure:** + +Choose the structure that matches how the domain map's skills are shaped. + +Use **nested** (`[lib]-core/[domain]/SKILL.md`) when: + +- Developer tasks cluster cleanly into 3–5 conceptual domains +- The library has a clear core + framework adapter split +- Skills build on each other in a layered way + +Use **flat** (`skills/[skill-name]/SKILL.md`) when: + +- Developer tasks are task-focused and don't nest into domains +- The domain discovery process recommended task-focused skills +- Skills map 1:1 to distinct developer intents with minimal overlap + +Both are valid. The domain map's `type` field and structure will signal +which fits. When in doubt, prefer flat — it's simpler and each skill +is independently discoverable. + +**Nested structure:** + +``` +skills/ +├── [lib]-core/ # Core skill for the library +│ ├── SKILL.md # Core overview + sub-skill registry +│ ├── [domain-1]/ +│ │ └── SKILL.md # Core sub-skill +│ ├── [domain-2]/ +│ │ └── SKILL.md +│ └── references/ # Optional overflow content +│ └── options.md +├── react-[lib]/ # React framework skill +│ ├── SKILL.md # React overview + sub-skill registry +│ ├── [domain-1]/ +│ │ └── SKILL.md # React-specific sub-skill +│ └── references/ +├── solid-[lib]/ # Solid framework skill (if applicable) +│ └── SKILL.md +├── vue-[lib]/ # Vue framework skill (if applicable) +│ └── SKILL.md +``` + +**Flat structure:** + +``` +skills/ +├── [lib]-shapes/ # Task-focused skill +│ ├── SKILL.md +│ └── references/ +│ └── shape-options.md +├── [lib]-auth/ # Another task skill +│ └── SKILL.md +├── [lib]-proxy/ +│ └── SKILL.md +├── [lib]-quickstart/ # Lifecycle skill +│ └── SKILL.md +├── [lib]-go-live/ # Lifecycle skill +│ └── SKILL.md +├── [lib]-drizzle/ # Composition skill +│ └── SKILL.md +``` + +**Router skill:** A router skill (lightweight entry point with a decision +table) is optional. If the intent CLI provides `list` and `show` +commands, agents can discover skills directly without a router. Only +create a router skill if the skill set is large enough (15+) that +browsing the list is insufficient, or if the nested structure needs +an entry point to guide agents to the right sub-skill. Libraries with +fewer than 5 skills should never have a router skill. + +**Source repository layout for npm distribution:** + +Skills must ship with their respective packages so they're available in +`node_modules` after install. In a monorepo, co-locate skills with the +package they document: + +``` +packages/ +├── [lib]/ # Core package +│ ├── src/ +│ ├── skills/ # Core skills live here +│ │ ├── [lib]-core/ +│ │ │ ├── SKILL.md +│ │ │ └── [domain]/SKILL.md +│ │ └── compositions/ # Composition skills with co-used libs +│ └── package.json # Add "skills" to files array +├── react-[lib]/ # React adapter package +│ ├── src/ +│ ├── skills/ # React framework skills live here +│ │ └── react-[lib]/ +│ │ └── SKILL.md +│ └── package.json # Add "skills" to files array +``` + +Add `"skills"` to each package's `files` array in `package.json` so +skill files are included in the published npm tarball: + +```json +{ + "files": ["dist", "src", "skills"] +} +``` + +### Step 2 — Write the core skill + +The core skill is the foundational overview for the library. It covers +framework-agnostic concepts and contains the sub-skill registry. + +**Frontmatter:** + +```yaml +--- +name: [lib]-core +description: > + [1–3 sentences. What this library does and the framework-agnostic + concepts it provides. Pack with keywords: function names, config + options, concepts. This is a routing key, not a human summary.] +type: core +library: [lib] +library_version: "[version this targets]" +--- +``` + +**Body template:** + +```markdown +# [Library Name] — Core Concepts + +[One paragraph: what this library is, what problem it solves. Factual, +not promotional. Framework-agnostic.] + +## Sub-Skills + +| Need to... | Read | +| ---------- | ------------------------------ | +| [task 1] | [lib]-core/[domain-1]/SKILL.md | +| [task 2] | [lib]-core/[domain-2]/SKILL.md | + +## Quick Decision Tree + +- Setting up for the first time? → [lib]-core/[setup-domain] +- Working with [concept]? → [lib]-core/[concept-domain] +- Debugging [issue]? → [lib]-core/[domain] § Common Mistakes + +## Version + +Targets [library] v[X.Y.Z]. +``` + +### Step 3 — Write core sub-skills + +One SKILL.md per domain. Follow this structure exactly. + +**Frontmatter:** + +```yaml +--- +name: [lib]-core/[domain-slug] +description: > + [1–3 sentences. What this domain covers AND when to load it. Name + specific functions, options, or APIs. Dense routing key.] +type: sub-skill +library: [lib] +library_version: "[version]" +sources: + - "[repo]:docs/[path].md" + - "[repo]:src/[path].ts" +--- +``` + +**Body sections — in this order:** + +**1. Setup** + +Minimum working example for this domain. + +- Use the library's core API, not framework-specific hooks +- Real package imports with exact names +- No `// ...` or `[your code here]` — complete and copy-pasteable +- If a concept is better explained with a framework hook, reference the + framework skill: "For React usage, see `react-[lib]/SKILL.md`" + +**2. Core Patterns** + +2–4 patterns. For each: + +- One-line heading: what it accomplishes +- Complete code block using core API +- One sentence of explanation only if not self-explanatory +- No framework-specific code — use core abstractions + +**3. Common Mistakes** + +Each `failure_mode` entry from the domain map becomes a Common Mistake +entry in the SKILL file. Minimum 3 entries. Complex domains target 5–6. + +**Cross-skill failure modes:** The domain map may contain failure modes +with a `skills` list naming multiple skill slugs. Write these into +every SKILL file whose skill is listed. A developer loading the SSR +skill and a developer loading the state management skill both need to +see "stale state during hydration" — the same advice must appear in +both files. Do not deduplicate across skills at the cost of coverage. + +Format: + +````markdown +### [PRIORITY] [What goes wrong — 5–8 word phrase] + +Wrong: + +```[lang] +// code that looks correct but isn't +``` +```` + +Correct: + +```[lang] +// code that works +``` + +[One sentence: the specific mechanism by which the wrong version fails.] + +Source: [doc page or source file:line] + +```` + +Priority levels: +- **CRITICAL** — Breaks in production. Security risk or data loss. +- **HIGH** — Incorrect behavior under common conditions. +- **MEDIUM** — Incorrect under specific conditions or edge cases. + +Every mistake must be plausible (an agent would generate it), silent +(no immediate crash), and grounded (traceable to doc or source). + +**Failure mode status from domain map:** The domain map may include a +`status` field on failure modes. Handle as follows: +- `active` — Include as a normal Common Mistake entry +- `fixed-but-legacy-risk` — Include with a note: "Fixed in v[X] but + agents trained on older code may still generate this pattern" +- `removed` — Do not include. The bug is fixed and the pattern is no + longer relevant. + +**4. References** (only when needed) + +```markdown +## References + +- [Complete option reference](references/options.md) +```` + +Create reference files when any of these apply — not just length overflow: + +- **Length:** The skill would exceed 500 lines without them +- **Multiple subsystems:** The domain covers 3+ independent backends, + adapters, or providers with distinct config interfaces. Create one + reference file per subsystem (e.g. `references/electric-adapter.md`, + `references/query-adapter.md`) +- **Dense API surface:** A topic has >10 distinct API patterns, operators, + or option shapes that agents need for implementation. Move the full + reference to `references/` and keep only the most common 2–3 in the + SKILL.md +- **Deep validation/schema patterns:** If the library has schema + validation, type transforms (TInput/TOutput), or similar deep + configuration surfaces, give them a dedicated reference file even if + they technically fit in the parent skill + +### Step 4 — Write framework skills + +Framework skills build on their core skill. They cover only what is +specific to the framework — hooks, components, providers, and +framework-specific patterns and mistakes. + +**Frontmatter:** + +```yaml +--- +name: react-[lib] +description: > + [1–3 sentences. React-specific bindings for [library]. Name the hooks, + components, and providers. Mention React-specific patterns like SSR + hydration if applicable.] +type: framework +library: [lib] +framework: react +library_version: "[version]" +requires: + - [lib]-core +--- +``` + +**Body template:** + +```markdown +This skill builds on [lib]-core. Read [lib]-core first for foundational +concepts before applying React-specific patterns. + +# [Library Name] — React + +## Setup + +[React-specific setup: provider, hook wiring, app entry point] + +## Hooks and Components + +[React hooks and components with complete examples] + +## React-Specific Patterns + +[Patterns that only apply in React: concurrent features, Suspense +integration, SSR/hydration, etc.] + +## Common Mistakes + +[Only React-specific mistakes. Do not repeat core mistakes. Examples: +calling hooks outside provider, missing Suspense boundary, hydration +mismatch, etc.] +``` + +**Framework sub-skills** follow the same pattern as core sub-skills but +with the framework frontmatter: + +```yaml +--- +name: react-[lib]/[domain-slug] +description: > + [React-specific description for this domain.] +type: sub-skill +library: [lib] +framework: react +library_version: "[version]" +requires: + - [lib]-core + - [lib]-core/[domain-slug] +--- + +This skill builds on [lib]-core/[domain-slug]. Read the core skill first. +``` + +### Step 5 — Write cross-domain tension notes + +The domain map may contain a `tensions` section listing design conflicts +between domains. For each tension, add a brief note to the Common +Mistakes section of every SKILL file whose domain is involved. Format: + +```markdown +### HIGH Tension: [short phrase] + +This domain's patterns conflict with [other domain]. [One sentence +describing the pull.] Agents optimizing for [this domain's goal] +tend to [specific mistake] because they don't account for [other +domain's constraint]. + +See also: [lib]-core/[other-domain]/SKILL.md § Common Mistakes +``` + +The cross-reference ensures agents that load one skill are pointed +toward the related skill where the other side of the tension lives. + +Also check the domain map's `cross_references` section for non-tension +relationships between skills. For each cross-reference, add a "See also" +line at the end of the relevant skill's body: + +```markdown +See also: [other-skill]/SKILL.md — [reason] +``` + +### Step 6 — Write composition skills (if applicable) + +Use the `compositions` entries from `domain_map.yaml` (populated during +skill-domain-discovery Phase 3h) to identify which composition skills +to produce. + +Composition skills cover how two or more libraries work together. These +are framework-specific by default (the integration patterns depend on +framework hooks and providers). + +**Frontmatter:** + +```yaml +--- +name: compositions/[lib-a]-[lib-b] +description: > + [How lib-a and lib-b wire together. Name the specific integration + points: functions, hooks, patterns.] +type: composition +library_version: "[version of primary lib]" +requires: + - [lib-a]-core + - react-[lib-a] + - [lib-b]-core + - react-[lib-b] +--- + +This skill requires familiarity with both [lib-a] and [lib-b]. +Read their core and framework skills first. +``` + +**Body structure:** + +1. **Integration Setup** — How to wire the two libraries together +2. **Core Integration Patterns** — 2–4 patterns showing them working in concert +3. **Common Mistakes** — Mistakes that only occur at the integration boundary + +Do not duplicate content from either library's individual skills. Focus +exclusively on the seam between them. + +### Step 7 — Write checklist/audit skills (where applicable) + +Some skills don't fit the standard body structure (Setup → Core Patterns +→ Common Mistakes). Security, go-live, and some lifecycle skills are +audit-oriented — the agent runs through a checklist to verify correctness +rather than learning patterns. Use the alternative body structure below +for these skill types. + +**When to use the checklist body:** + +- `security` type skills — pre-deploy security validation +- `lifecycle` type skills focused on verification (go-live, migration) +- Any skill where the primary action is "check these things" not "learn + these patterns" + +**Frontmatter:** + +```yaml +--- +name: react-[lib]/security +description: > + Go-live security validation for [library]. Checks [specific concerns]. +type: security +library: [lib] +framework: react +library_version: '[version]' +requires: + - react-[lib] +--- +``` + +**Alternative body template (checklist/audit):** + +````markdown +# [Library Name] — [Security | Go-Live | Migration] Checklist + +Run through each section before [deploying | releasing | migrating]. + +## [Category 1] Checks + +### Check: [what to verify] + +Expected: + +```[lang] +// correct configuration or code +``` +```` + +Fail condition: [what indicates this check failed] +Fix: [one-line remediation] + +### Check: [what to verify] + +[same structure] + +## [Category 2] Checks + +[same structure] + +## Common Security Mistakes + +[Wrong/correct pairs specific to this library, same format as +Common Mistakes in standard skills] + +## Pre-Deploy Summary + +- [ ] [Verification 1] +- [ ] [Verification 2] +- [ ] [Verification 3] + +```` + +The key differences from the standard body: +- No "Setup" section — the agent already has the app running +- Checks replace "Core Patterns" — each check is a verification, not a + teaching pattern +- The summary checklist at the end gives agents a quick pass/fail list +- Common Mistakes section is still present for wrong/correct pairs + +### Step 8 — Validate the complete tree + +Run every check before outputting. Fix any failures before proceeding. + +| Check | Rule | +|-------|------| +| Every skill from domain_map has a SKILL.md | No orphaned skills | +| Core/framework split is clean | No framework hooks in core skills | +| Every framework skill has `requires` | Links to its core skill | +| Framework skill opens with dependency note | "builds on [core]" prose line | +| Every skill under 500 lines | Move excess to references/ | +| Every code block has real imports | Exact package name, correct adapter | +| No concept explanations | No "TypeScript is...", no "React hooks are..." | +| No marketing prose | First body line is heading or dependency note | +| Every code block is complete | Works without modification when pasted | +| Common Mistakes are silent | Not obvious compile errors | +| Common Mistakes are library-specific | Not generic TS/React mistakes | +| Common Mistakes are sourced | Every mistake traceable to doc or source | +| Core skills reference framework skills | "For React usage, see..." | +| Framework skills don't repeat core content | Only framework-specific | +| Composition skills don't repeat individual skills | Only the seam | +| `name` matches directory path | `router-core/search-params` → `router-core/search-params/SKILL.md` | +| `sources` filled in sub-skills | At least one repo:path per sub-skill | +| Cross-skill failures in all relevant files | Failure modes with multiple `skills` appear in each listed SKILL.md | +| Tensions noted in affected skills | Each tension has notes in all involved domain skills | +| Framework domains decomposed per-package | No single skill covering multiple framework adapters | +| Adapter-heavy domains have references | 3+ adapters/backends → one reference file per adapter | +| Dense API surfaces in references | >10 distinct patterns → reference file, not inline | +| Checklist skills use audit body | Security/go-live skills use checklist template, not Setup → Core Patterns → Common Mistakes | + +--- + +## Workflow B — Update existing skills + +### Trigger conditions + +Run when: +- The library has released a new version +- A maintainer reports skills produce outdated code +- A changelog or migration guide has been published since skill creation +- Feedback reports indicate skill content is inaccurate + +### Step 1 — Detect staleness + +Compare each skill's `library_version` against the current library version. + +1. Read changelog entries between the two versions +2. Read migration guide (if one exists) +3. For each skill, check if its `sources` files have changed + +Produce a staleness report: + +```yaml +# staleness_report.yaml +library: "[name]" +library_version_in_skills: "[old]" +library_version_current: "[new]" + +stale_skills: + - skill: "[skill name]" + reason: "[what changed]" + severity: "[BREAKING | DEPRECATION | BEHAVIORAL | ADDITIVE]" + changelog_entry: "[relevant entry]" + affected_sections: + - "[Setup | Core Patterns | Common Mistakes]" + +current_skills: + - skill: "[skill name]" + reason: "[no changes affect this domain]" +```` + +### Step 2 — Update stale skills + +**BREAKING changes:** + +1. Old pattern becomes a new Common Mistake entry (wrong/correct pair) +2. Update Setup if initialization changed +3. Update Core Patterns if idiomatic approach changed +4. Bump `library_version` in frontmatter +5. Check both core AND framework skills — breaking changes may affect both + +**DEPRECATION changes:** + +1. Add Common Mistake: deprecated API as wrong, replacement as correct +2. Update Core Patterns to use non-deprecated API +3. Bump `library_version` + +**BEHAVIORAL changes:** + +1. Default value changed → add Common Mistake entry +2. Type signature more restrictive → add Common Mistake entry +3. Update affected code blocks +4. Bump `library_version` + +**ADDITIVE changes:** + +1. Evaluate if new feature belongs in existing domain or needs a new skill +2. If existing: add to Core Patterns or references/ +3. If new skill needed: create it and update the parent skill's sub-skill + registry +4. Bump `library_version` + +### Step 3 — Produce a changelog entry + +```markdown +## [date] + +### Updated for [library] v[new version] + +**Breaking changes:** + +- [skill name]: [what changed and why] + +**Deprecation updates:** + +- [skill name]: [old API] → [new API] + +**New skills:** + +- [skill name]: [what it covers] +``` + +--- + +## Constraints — verify for every file + +| Check | Rule | +| ------------------------------------------- | ----------------------------------------------------------------------------------- | +| Under 500 lines per SKILL.md | Move excess to references/; also create references for content depth | +| Real imports in every code block | Exact package, correct adapter | +| No external concept explanations | No "TypeScript is...", no "React hooks are..." — library-specific concepts are fine | +| No marketing prose | First body line is heading, code, or dependency note | +| Complete code blocks | Every block works without modification | +| Common Mistakes are silent | Not obvious compile errors | +| Common Mistakes are library-specific | Not generic TS/React mistakes | +| Common Mistakes are sourced | Traceable to doc or source | +| Core skills are framework-agnostic | No hooks, no components, no providers | +| Framework skills have `requires` | Lists core dependency | +| Framework skills open with dependency note | First prose line references core | +| Composition skills require all dependencies | Lists all core + framework skills | +| `name` matches directory | `router-core/search-params` → file at that path | +| `library_version` in every frontmatter | Which version the skill targets | +| Cross-skill failures duplicated | Each listed skill gets the failure mode | +| Tensions cross-referenced | Tension notes in each involved skill point to the other | +| Skills ship with packages | `"skills"` in package.json `files` array | +| Checklist skills use audit template | Security/go-live skills use checklist body, not standard body | + +--- + +## Cross-model compatibility + +Output is consumed by all major AI coding agents. To ensure consistency: + +- Markdown with YAML frontmatter — universally parsed +- No XML tags in generated skill content +- Code blocks use triple backticks with language annotation +- Section boundaries use ## headers +- Descriptions are keyword-packed for routing +- Examples show concrete values, never placeholders +- Positive instructions ("Use X") over negative ("Don't use Y") +- Critical info at start or end of sections (not buried in middle) +- Each SKILL.md is self-contained except for declared `requires` + +--- + +## Output order + +When generating a complete skill tree: + +1. Core overview SKILL.md — entry point for the library +2. Core sub-skills in domain order +3. Framework overview SKILL.md for each framework +4. Framework sub-skills +5. Composition skills (if applicable) +6. Security skills (if applicable) +7. references/ files for any skill that needs them +8. CHANGELOG.md entry + +When updating: + +1. staleness_report.yaml +2. Updated SKILL.md files (core then framework) +3. CHANGELOG.md entry + +--- + +## Meta-skill feedback (alpha default) + +After producing the skill tree artifact, update a single Markdown feedback +draft for all three meta skills used in scaffolding. If a draft exists from +Domain Discovery, keep it and fill only the **Tree Generator** section. If +no draft exists, create it using this exact template. + +``` +# Intent Meta Skill Feedback + +## Domain Discovery +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Tree Generator +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Generate Skill +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Context (optional) +- Library: +- Repo: +- Docs: +- Notes: +``` + +Do not submit feedback yet. Carry this draft forward to the generate-skill +step. diff --git a/packages/intent/package.json b/packages/intent/package.json index eee10b22..88361074 100644 --- a/packages/intent/package.json +++ b/packages/intent/package.json @@ -1,40 +1,40 @@ -{ - "name": "@tanstack/intent", - "version": "0.0.9", - "description": "Ship compositional knowledge for AI coding agents alongside your npm packages", - "license": "MIT", - "type": "module", - "repository": { - "type": "git", - "url": "https://github.com/tanstack/intent" - }, - "exports": { - ".": { - "import": "./dist/index.mjs", - "types": "./dist/index.d.mts" - }, - "./intent-library": { - "import": "./dist/intent-library.mjs" - } - }, - "bin": { - "intent": "dist/cli.mjs", - "intent-library": "dist/intent-library.mjs" - }, - "files": [ - "dist", - "meta" - ], - "dependencies": { - "yaml": "^2.7.0" - }, - "devDependencies": { - "tsdown": "^0.19.0" - }, - "scripts": { - "prepack": "pnpm run build", - "build": "tsdown src/index.ts src/cli.ts src/setup.ts src/intent-library.ts src/library-scanner.ts --format esm --dts", - "test:lib": "vitest run", - "test:types": "tsc --noEmit" - } -} +{ + "name": "@tanstack/intent", + "version": "0.0.9", + "description": "Ship compositional knowledge for AI coding agents alongside your npm packages", + "license": "MIT", + "type": "module", + "repository": { + "type": "git", + "url": "https://github.com/tanstack/intent" + }, + "exports": { + ".": { + "import": "./dist/index.mjs", + "types": "./dist/index.d.mts" + }, + "./intent-library": { + "import": "./dist/intent-library.mjs" + } + }, + "bin": { + "intent": "dist/cli.mjs", + "intent-library": "dist/intent-library.mjs" + }, + "files": [ + "dist", + "meta" + ], + "dependencies": { + "yaml": "^2.7.0" + }, + "devDependencies": { + "tsdown": "^0.19.0" + }, + "scripts": { + "prepack": "pnpm run build", + "build": "tsdown src/index.ts src/cli.ts src/setup.ts src/intent-library.ts src/library-scanner.ts --format esm --dts", + "test:lib": "vitest run", + "test:types": "tsc --noEmit" + } +} diff --git a/packages/intent/src/cli.ts b/packages/intent/src/cli.ts index 3a5fbe87..e95fa9e6 100644 --- a/packages/intent/src/cli.ts +++ b/packages/intent/src/cli.ts @@ -1,550 +1,550 @@ -#!/usr/bin/env node - -import { existsSync, readdirSync, readFileSync } from 'node:fs' -import { dirname, join, relative, sep } from 'node:path' -import { fileURLToPath } from 'node:url' -import { parse as parseYaml } from 'yaml' -import { computeSkillNameWidth, printSkillTree, printTable } from './display.js' -import { scanForIntents } from './scanner.js' -import type { ScanResult } from './types.js' -import { findSkillFiles, parseFrontmatter } from './utils.js' - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -function getMetaDir(): string { - const thisDir = dirname(fileURLToPath(import.meta.url)) - return join(thisDir, '..', 'meta') -} - -// --------------------------------------------------------------------------- -// Commands -// --------------------------------------------------------------------------- - -async function cmdList(args: string[]): Promise { - const jsonOutput = args.includes('--json') - - let result: ScanResult - try { - result = await scanForIntents() - } catch (err) { - console.error((err as Error).message) - process.exit(1) - } - - if (jsonOutput) { - console.log(JSON.stringify(result, null, 2)) - return - } - - if (result.packages.length === 0) { - console.log('No intent-enabled packages found.') - if (result.warnings.length > 0) { - console.log(`\nWarnings:`) - for (const w of result.warnings) console.log(` ⚠ ${w}`) - } - return - } - - const totalSkills = result.packages.reduce( - (sum, p) => sum + p.skills.length, - 0, - ) - console.log( - `\n${result.packages.length} intent-enabled packages, ${totalSkills} skills (${result.packageManager})\n`, - ) - - // Summary table - const rows = result.packages.map((pkg) => [ - pkg.name, - pkg.version, - String(pkg.skills.length), - pkg.intent.requires?.join(', ') || '–', - ]) - printTable(['PACKAGE', 'VERSION', 'SKILLS', 'REQUIRES'], rows) - - // Skills detail - const allSkills = result.packages.map((p) => p.skills) - const nameWidth = computeSkillNameWidth(allSkills) - const showTypes = result.packages.some((p) => p.skills.some((s) => s.type)) - - console.log(`\nSkills:\n`) - for (const pkg of result.packages) { - console.log(` ${pkg.name}`) - printSkillTree(pkg.skills, { nameWidth, showTypes }) - console.log() - } - - console.log(`Feedback:`) - console.log( - ` Submit feedback on skill usage to help maintainers improve the skills.`, - ) - console.log( - ` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`, - ) - console.log() - - if (result.warnings.length > 0) { - console.log(`Warnings:`) - for (const w of result.warnings) console.log(` ⚠ ${w}`) - } -} - -function cmdMeta(): void { - const metaDir = getMetaDir() - - if (!existsSync(metaDir)) { - console.error('Meta-skills directory not found.') - process.exit(1) - } - - const entries = readdirSync(metaDir, { withFileTypes: true }) - .filter((e) => e.isDirectory()) - .filter((e) => existsSync(join(metaDir, e.name, 'SKILL.md'))) - - if (entries.length === 0) { - console.log('No meta-skills found.') - return - } - - console.log('Meta-skills (for library maintainers):\n') - - for (const entry of entries) { - const skillFile = join(metaDir, entry.name, 'SKILL.md') - const fm = parseFrontmatter(skillFile) - let description = '' - if (typeof fm?.description === 'string') { - description = fm.description.replace(/\s+/g, ' ').trim() - } - - const shortDesc = - description.length > 60 ? description.slice(0, 57) + '...' : description - console.log(` ${entry.name.padEnd(28)} ${shortDesc}`) - } - - console.log(`\nUsage: load the SKILL.md into your AI agent conversation.`) - console.log(`Path: node_modules/@tanstack/intent/meta//SKILL.md`) -} - -function collectPackagingWarnings(root: string): string[] { - const pkgJsonPath = join(root, 'package.json') - if (!existsSync(pkgJsonPath)) return [] - - let pkgJson: Record - try { - pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8')) - } catch (err) { - const msg = err instanceof Error ? err.message : String(err) - return [`Could not parse package.json: ${msg}`] - } - - const warnings: string[] = [] - - const devDeps = pkgJson.devDependencies as Record | undefined - if (!devDeps?.['@tanstack/intent']) { - warnings.push('@tanstack/intent is not in devDependencies') - } - - const bin = pkgJson.bin as Record | undefined - if (!bin?.intent) { - warnings.push('Missing "bin": { "intent": ... } entry in package.json') - } - - const shimJs = join(root, 'bin', 'intent.js') - const shimMjs = join(root, 'bin', 'intent.mjs') - if (!existsSync(shimJs) && !existsSync(shimMjs)) { - warnings.push( - 'No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent setup --shim)', - ) - } - - const files = pkgJson.files as string[] | undefined - if (Array.isArray(files)) { - if (!files.includes('skills')) { - warnings.push( - '"skills" is not in the "files" array — skills won\'t be published', - ) - } - if (!files.includes('bin')) { - warnings.push( - '"bin" is not in the "files" array — shim won\'t be published', - ) - } - if (!files.includes('!skills/_artifacts')) { - warnings.push( - '"!skills/_artifacts" is not in the "files" array — artifacts will be published unnecessarily', - ) - } - } - - return warnings -} - -function cmdValidate(args: string[]): void { - const targetDir = args[0] ?? 'skills' - const skillsDir = join(process.cwd(), targetDir) - - if (!existsSync(skillsDir)) { - console.error(`Skills directory not found: ${skillsDir}`) - process.exit(1) - } - - interface ValidationError { - file: string - message: string - } - - const errors: ValidationError[] = [] - const skillFiles = findSkillFiles(skillsDir) - - if (skillFiles.length === 0) { - console.error('No SKILL.md files found') - process.exit(1) - } - - for (const filePath of skillFiles) { - const rel = relative(process.cwd(), filePath) - const content = readFileSync(filePath, 'utf8') - const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/) - - if (!match) { - errors.push({ file: rel, message: 'Missing or invalid frontmatter' }) - continue - } - - if (!match[1]) { - errors.push({ file: rel, message: 'Missing YAML frontmatter' }) - continue - } - - let fm: Record - try { - fm = parseYaml(match[1]) as Record - } catch { - errors.push({ file: rel, message: 'Invalid YAML frontmatter' }) - continue - } - - if (!fm.name) - errors.push({ file: rel, message: 'Missing required field: name' }) - if (!fm.description) - errors.push({ file: rel, message: 'Missing required field: description' }) - - // Validate name matches directory path - if (typeof fm.name === 'string') { - const expectedPath = relative(skillsDir, filePath) - .replace(/[/\\]SKILL\.md$/, '') - .split(sep) - .join('/') - if (fm.name !== expectedPath) { - errors.push({ - file: rel, - message: `name "${fm.name}" does not match directory path "${expectedPath}"`, - }) - } - } - - // Description character limit - if (typeof fm.description === 'string' && fm.description.length > 1024) { - errors.push({ - file: rel, - message: `Description exceeds 1024 character limit (${fm.description.length} chars)`, - }) - } - - // Framework skills must have requires - if (fm.type === 'framework' && !Array.isArray(fm.requires)) { - errors.push({ - file: rel, - message: 'Framework skills must have a "requires" field', - }) - } - - // Line count - const lineCount = content.split(/\r?\n/).length - if (lineCount > 500) { - errors.push({ - file: rel, - message: `Exceeds 500 line limit (${lineCount} lines). Rewrite for conciseness: move API tables to references/, trim verbose examples, and remove content an agent already knows. Do not simply raise the limit.`, - }) - } - } - - const artifactsDir = join(skillsDir, '_artifacts') - if (existsSync(artifactsDir)) { - const requiredArtifacts = [ - 'domain_map.yaml', - 'skill_spec.md', - 'skill_tree.yaml', - ] - - for (const fileName of requiredArtifacts) { - const artifactPath = join(artifactsDir, fileName) - if (!existsSync(artifactPath)) { - errors.push({ - file: relative(process.cwd(), artifactPath), - message: 'Missing required artifact', - }) - continue - } - - const content = readFileSync(artifactPath, 'utf8') - if (content.trim().length === 0) { - errors.push({ - file: relative(process.cwd(), artifactPath), - message: 'Artifact file is empty', - }) - continue - } - - if (fileName.endsWith('.yaml')) { - try { - parseYaml(content) - } catch { - errors.push({ - file: relative(process.cwd(), artifactPath), - message: 'Invalid YAML in artifact file', - }) - } - } - } - } - - const warnings = collectPackagingWarnings(process.cwd()) - - const printWarnings = (log: (...args: unknown[]) => void): void => { - if (warnings.length === 0) return - log(`\n⚠ Packaging warnings:`) - for (const w of warnings) log(` ${w}`) - } - - if (errors.length > 0) { - console.error(`\n❌ Validation failed with ${errors.length} error(s):\n`) - for (const { file, message } of errors) { - console.error(` ${file}: ${message}`) - } - printWarnings(console.error) - process.exit(1) - } - - console.log(`✅ Validated ${skillFiles.length} skill files — all passed`) - printWarnings(console.log) -} - -function cmdScaffold(): void { - const metaDir = getMetaDir() - const metaSkillPath = (name: string) => join(metaDir, name, 'SKILL.md') - - const prompt = `You are helping a library maintainer scaffold Intent skills. - -Run the three meta skills below **one at a time, in order**. For each step: -1. Load the SKILL.md file specified -2. Follow its instructions completely -3. Present outputs to the maintainer for review -4. Do NOT proceed to the next step until the maintainer confirms - -## Before you start - -Gather this context yourself (do not ask the maintainer — agents should never -ask for information they can discover): -1. Read package.json for library name, repository URL, and homepage/docs URL -2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json) -3. Use skills/ as the default skills root -4. For monorepos: - - Domain map artifacts go at the REPO ROOT: _artifacts/ - - Skills go INSIDE EACH PACKAGE: packages//skills/ - - Identify which packages are client-facing (usually client SDKs and primary framework adapters) - ---- - -## Step 1 — Domain Discovery - -Load and follow: ${metaSkillPath('domain-discovery')} - -This produces: domain_map.yaml and skill_spec.md in the artifacts directory. -Domain discovery covers the WHOLE library (one domain map even for monorepos). - -**STOP. Review outputs with the maintainer before continuing.** - ---- - -## Step 2 — Tree Generator - -Load and follow: ${metaSkillPath('tree-generator')} - -This produces: skill_tree.yaml in the artifacts directory. -For monorepos, each skill entry should include a \`package\` field. - -**STOP. Review outputs with the maintainer before continuing.** - ---- - -## Step 3 — Generate Skills - -Load and follow: ${metaSkillPath('generate-skill')} - -This produces: individual SKILL.md files. -- Single-repo: skills///SKILL.md -- Monorepo: packages//skills///SKILL.md - ---- - -## After all skills are generated - -1. Run \`npx @tanstack/intent validate\` in each package directory -2. Commit skills/ and artifacts -3. For each publishable package, run: \`npx @tanstack/intent setup --shim\` -4. Ensure each package has \`@tanstack/intent\` as a devDependency -5. Add \`"skills"\`, \`"bin"\` to the \`"files"\` array in each package.json -6. Add \`"!skills/_artifacts"\` to exclude artifacts from publishing -7. Create a \`feedback:\` label on the GitHub repo for each skill (use \`gh label create\`) -8. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`" -` - - console.log(prompt) -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -const USAGE = `TanStack Intent CLI - -Usage: - intent list [--json] Discover intent-enabled packages - intent meta List meta-skills for maintainers - intent validate [] Validate skill files (default: skills/) - intent install Print a skill that guides your coding agent to set up skill-to-task mappings - intent scaffold Print maintainer scaffold prompt - intent setup [--workflows] [--shim] [--all] Copy CI templates and generate shim - intent stale Check skills for staleness` - -const command = process.argv[2] -const commandArgs = process.argv.slice(3) - -switch (command) { - case 'list': - await cmdList(commandArgs) - break - case 'meta': - cmdMeta() - break - case 'validate': - cmdValidate(commandArgs) - break - case 'install': { - const prompt = `You are an AI assistant helping a developer set up skill-to-task mappings for their project. - -Follow these steps in order: - -1. CHECK FOR EXISTING MAPPINGS - Search the project's agent config files (CLAUDE.md, AGENTS.md, .cursorrules, - .github/copilot-instructions.md) for a block delimited by: - - - - If found: show the user the current mappings and ask "What would you like to update?" - Then skip to step 4 with their requested changes. - - If not found: continue to step 2. - -2. DISCOVER AVAILABLE SKILLS - Run: intent list - This outputs each skill's name, description, and full path — grouped by package. - -3. SCAN THE REPOSITORY - Build a picture of the project's structure and patterns: - - Read package.json for library dependencies - - Survey the directory layout (src/, app/, routes/, components/, api/, etc.) - - Note recurring patterns (routing, data fetching, auth, UI components, etc.) - - Based on this, propose 3–5 skill-to-task mappings. For each one explain: - - The task or code area (in plain language the user would recognise) - - Which skill applies and why - - Then ask: "What other tasks do you commonly use AI coding agents for? - I'll create mappings for those too." - -4. WRITE THE MAPPINGS BLOCK - Once you have the full set of mappings, write or update the agent config file - (prefer CLAUDE.md; create it if none exists) with this exact block: - - -# Skill mappings — when working in these areas, load the linked skill file into context. -skills: - - task: "describe the task or code area here" - load: "node_modules/package-name/skills/skill-name/SKILL.md" - - - Rules: - - Use the user's own words for task descriptions - - Include the exact path from \`intent list\` output so agents can load it directly - - Keep entries concise — this block is read on every agent task - - Preserve all content outside the block tags unchanged` - - console.log(prompt) - break - } - case 'scaffold': { - cmdScaffold() - break - } - case 'stale': { - const { checkStaleness } = await import('./staleness.js') - const { scanForIntents: scanStale } = await import('./scanner.js') - let staleResult - try { - staleResult = await scanStale() - } catch (err) { - console.error((err as Error).message) - process.exit(1) - } - - if (staleResult.packages.length === 0) { - console.log('No intent-enabled packages found.') - break - } - - const jsonStale = commandArgs.includes('--json') - const reports = await Promise.all( - staleResult.packages.map((pkg) => { - const pkgDir = join(process.cwd(), 'node_modules', pkg.name) - return checkStaleness(pkgDir, pkg.name) - }), - ) - - if (jsonStale) { - console.log(JSON.stringify(reports, null, 2)) - break - } - - for (const report of reports) { - const driftLabel = report.versionDrift - ? ` [${report.versionDrift} drift]` - : '' - const vLabel = - report.skillVersion && report.currentVersion - ? ` (${report.skillVersion} → ${report.currentVersion})` - : '' - console.log(`${report.library}${vLabel}${driftLabel}`) - - const stale = report.skills.filter((s) => s.needsReview) - if (stale.length === 0) { - console.log(' All skills up-to-date') - } else { - for (const skill of stale) { - console.log(` ⚠ ${skill.name}: ${skill.reasons.join(', ')}`) - } - } - console.log() - } - break - } - case 'setup': { - const { runSetup } = await import('./setup.js') - runSetup(process.cwd(), getMetaDir(), commandArgs) - break - } - default: - console.log(USAGE) - process.exit(command ? 1 : 0) -} +#!/usr/bin/env node + +import { existsSync, readdirSync, readFileSync } from 'node:fs' +import { dirname, join, relative, sep } from 'node:path' +import { fileURLToPath } from 'node:url' +import { parse as parseYaml } from 'yaml' +import { computeSkillNameWidth, printSkillTree, printTable } from './display.js' +import { scanForIntents } from './scanner.js' +import type { ScanResult } from './types.js' +import { findSkillFiles, parseFrontmatter } from './utils.js' + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function getMetaDir(): string { + const thisDir = dirname(fileURLToPath(import.meta.url)) + return join(thisDir, '..', 'meta') +} + +// --------------------------------------------------------------------------- +// Commands +// --------------------------------------------------------------------------- + +async function cmdList(args: string[]): Promise { + const jsonOutput = args.includes('--json') + + let result: ScanResult + try { + result = await scanForIntents() + } catch (err) { + console.error((err as Error).message) + process.exit(1) + } + + if (jsonOutput) { + console.log(JSON.stringify(result, null, 2)) + return + } + + if (result.packages.length === 0) { + console.log('No intent-enabled packages found.') + if (result.warnings.length > 0) { + console.log(`\nWarnings:`) + for (const w of result.warnings) console.log(` ⚠ ${w}`) + } + return + } + + const totalSkills = result.packages.reduce( + (sum, p) => sum + p.skills.length, + 0, + ) + console.log( + `\n${result.packages.length} intent-enabled packages, ${totalSkills} skills (${result.packageManager})\n`, + ) + + // Summary table + const rows = result.packages.map((pkg) => [ + pkg.name, + pkg.version, + String(pkg.skills.length), + pkg.intent.requires?.join(', ') || '–', + ]) + printTable(['PACKAGE', 'VERSION', 'SKILLS', 'REQUIRES'], rows) + + // Skills detail + const allSkills = result.packages.map((p) => p.skills) + const nameWidth = computeSkillNameWidth(allSkills) + const showTypes = result.packages.some((p) => p.skills.some((s) => s.type)) + + console.log(`\nSkills:\n`) + for (const pkg of result.packages) { + console.log(` ${pkg.name}`) + printSkillTree(pkg.skills, { nameWidth, showTypes }) + console.log() + } + + console.log(`Feedback:`) + console.log( + ` Submit feedback on skill usage to help maintainers improve the skills.`, + ) + console.log( + ` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`, + ) + console.log() + + if (result.warnings.length > 0) { + console.log(`Warnings:`) + for (const w of result.warnings) console.log(` ⚠ ${w}`) + } +} + +function cmdMeta(): void { + const metaDir = getMetaDir() + + if (!existsSync(metaDir)) { + console.error('Meta-skills directory not found.') + process.exit(1) + } + + const entries = readdirSync(metaDir, { withFileTypes: true }) + .filter((e) => e.isDirectory()) + .filter((e) => existsSync(join(metaDir, e.name, 'SKILL.md'))) + + if (entries.length === 0) { + console.log('No meta-skills found.') + return + } + + console.log('Meta-skills (for library maintainers):\n') + + for (const entry of entries) { + const skillFile = join(metaDir, entry.name, 'SKILL.md') + const fm = parseFrontmatter(skillFile) + let description = '' + if (typeof fm?.description === 'string') { + description = fm.description.replace(/\s+/g, ' ').trim() + } + + const shortDesc = + description.length > 60 ? description.slice(0, 57) + '...' : description + console.log(` ${entry.name.padEnd(28)} ${shortDesc}`) + } + + console.log(`\nUsage: load the SKILL.md into your AI agent conversation.`) + console.log(`Path: node_modules/@tanstack/intent/meta//SKILL.md`) +} + +function collectPackagingWarnings(root: string): string[] { + const pkgJsonPath = join(root, 'package.json') + if (!existsSync(pkgJsonPath)) return [] + + let pkgJson: Record + try { + pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8')) + } catch (err) { + const msg = err instanceof Error ? err.message : String(err) + return [`Could not parse package.json: ${msg}`] + } + + const warnings: string[] = [] + + const devDeps = pkgJson.devDependencies as Record | undefined + if (!devDeps?.['@tanstack/intent']) { + warnings.push('@tanstack/intent is not in devDependencies') + } + + const bin = pkgJson.bin as Record | undefined + if (!bin?.intent) { + warnings.push('Missing "bin": { "intent": ... } entry in package.json') + } + + const shimJs = join(root, 'bin', 'intent.js') + const shimMjs = join(root, 'bin', 'intent.mjs') + if (!existsSync(shimJs) && !existsSync(shimMjs)) { + warnings.push( + 'No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent setup --shim)', + ) + } + + const files = pkgJson.files as string[] | undefined + if (Array.isArray(files)) { + if (!files.includes('skills')) { + warnings.push( + '"skills" is not in the "files" array — skills won\'t be published', + ) + } + if (!files.includes('bin')) { + warnings.push( + '"bin" is not in the "files" array — shim won\'t be published', + ) + } + if (!files.includes('!skills/_artifacts')) { + warnings.push( + '"!skills/_artifacts" is not in the "files" array — artifacts will be published unnecessarily', + ) + } + } + + return warnings +} + +function cmdValidate(args: string[]): void { + const targetDir = args[0] ?? 'skills' + const skillsDir = join(process.cwd(), targetDir) + + if (!existsSync(skillsDir)) { + console.error(`Skills directory not found: ${skillsDir}`) + process.exit(1) + } + + interface ValidationError { + file: string + message: string + } + + const errors: ValidationError[] = [] + const skillFiles = findSkillFiles(skillsDir) + + if (skillFiles.length === 0) { + console.error('No SKILL.md files found') + process.exit(1) + } + + for (const filePath of skillFiles) { + const rel = relative(process.cwd(), filePath) + const content = readFileSync(filePath, 'utf8') + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/) + + if (!match) { + errors.push({ file: rel, message: 'Missing or invalid frontmatter' }) + continue + } + + if (!match[1]) { + errors.push({ file: rel, message: 'Missing YAML frontmatter' }) + continue + } + + let fm: Record + try { + fm = parseYaml(match[1]) as Record + } catch { + errors.push({ file: rel, message: 'Invalid YAML frontmatter' }) + continue + } + + if (!fm.name) + errors.push({ file: rel, message: 'Missing required field: name' }) + if (!fm.description) + errors.push({ file: rel, message: 'Missing required field: description' }) + + // Validate name matches directory path + if (typeof fm.name === 'string') { + const expectedPath = relative(skillsDir, filePath) + .replace(/[/\\]SKILL\.md$/, '') + .split(sep) + .join('/') + if (fm.name !== expectedPath) { + errors.push({ + file: rel, + message: `name "${fm.name}" does not match directory path "${expectedPath}"`, + }) + } + } + + // Description character limit + if (typeof fm.description === 'string' && fm.description.length > 1024) { + errors.push({ + file: rel, + message: `Description exceeds 1024 character limit (${fm.description.length} chars)`, + }) + } + + // Framework skills must have requires + if (fm.type === 'framework' && !Array.isArray(fm.requires)) { + errors.push({ + file: rel, + message: 'Framework skills must have a "requires" field', + }) + } + + // Line count + const lineCount = content.split(/\r?\n/).length + if (lineCount > 500) { + errors.push({ + file: rel, + message: `Exceeds 500 line limit (${lineCount} lines). Rewrite for conciseness: move API tables to references/, trim verbose examples, and remove content an agent already knows. Do not simply raise the limit.`, + }) + } + } + + const artifactsDir = join(skillsDir, '_artifacts') + if (existsSync(artifactsDir)) { + const requiredArtifacts = [ + 'domain_map.yaml', + 'skill_spec.md', + 'skill_tree.yaml', + ] + + for (const fileName of requiredArtifacts) { + const artifactPath = join(artifactsDir, fileName) + if (!existsSync(artifactPath)) { + errors.push({ + file: relative(process.cwd(), artifactPath), + message: 'Missing required artifact', + }) + continue + } + + const content = readFileSync(artifactPath, 'utf8') + if (content.trim().length === 0) { + errors.push({ + file: relative(process.cwd(), artifactPath), + message: 'Artifact file is empty', + }) + continue + } + + if (fileName.endsWith('.yaml')) { + try { + parseYaml(content) + } catch { + errors.push({ + file: relative(process.cwd(), artifactPath), + message: 'Invalid YAML in artifact file', + }) + } + } + } + } + + const warnings = collectPackagingWarnings(process.cwd()) + + const printWarnings = (log: (...args: unknown[]) => void): void => { + if (warnings.length === 0) return + log(`\n⚠ Packaging warnings:`) + for (const w of warnings) log(` ${w}`) + } + + if (errors.length > 0) { + console.error(`\n❌ Validation failed with ${errors.length} error(s):\n`) + for (const { file, message } of errors) { + console.error(` ${file}: ${message}`) + } + printWarnings(console.error) + process.exit(1) + } + + console.log(`✅ Validated ${skillFiles.length} skill files — all passed`) + printWarnings(console.log) +} + +function cmdScaffold(): void { + const metaDir = getMetaDir() + const metaSkillPath = (name: string) => join(metaDir, name, 'SKILL.md') + + const prompt = `You are helping a library maintainer scaffold Intent skills. + +Run the three meta skills below **one at a time, in order**. For each step: +1. Load the SKILL.md file specified +2. Follow its instructions completely +3. Present outputs to the maintainer for review +4. Do NOT proceed to the next step until the maintainer confirms + +## Before you start + +Gather this context yourself (do not ask the maintainer — agents should never +ask for information they can discover): +1. Read package.json for library name, repository URL, and homepage/docs URL +2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json) +3. Use skills/ as the default skills root +4. For monorepos: + - Domain map artifacts go at the REPO ROOT: _artifacts/ + - Skills go INSIDE EACH PACKAGE: packages//skills/ + - Identify which packages are client-facing (usually client SDKs and primary framework adapters) + +--- + +## Step 1 — Domain Discovery + +Load and follow: ${metaSkillPath('domain-discovery')} + +This produces: domain_map.yaml and skill_spec.md in the artifacts directory. +Domain discovery covers the WHOLE library (one domain map even for monorepos). + +**STOP. Review outputs with the maintainer before continuing.** + +--- + +## Step 2 — Tree Generator + +Load and follow: ${metaSkillPath('tree-generator')} + +This produces: skill_tree.yaml in the artifacts directory. +For monorepos, each skill entry should include a \`package\` field. + +**STOP. Review outputs with the maintainer before continuing.** + +--- + +## Step 3 — Generate Skills + +Load and follow: ${metaSkillPath('generate-skill')} + +This produces: individual SKILL.md files. +- Single-repo: skills///SKILL.md +- Monorepo: packages//skills///SKILL.md + +--- + +## After all skills are generated + +1. Run \`npx @tanstack/intent validate\` in each package directory +2. Commit skills/ and artifacts +3. For each publishable package, run: \`npx @tanstack/intent setup --shim\` +4. Ensure each package has \`@tanstack/intent\` as a devDependency +5. Add \`"skills"\`, \`"bin"\` to the \`"files"\` array in each package.json +6. Add \`"!skills/_artifacts"\` to exclude artifacts from publishing +7. Create a \`feedback:\` label on the GitHub repo for each skill (use \`gh label create\`) +8. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`" +` + + console.log(prompt) +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +const USAGE = `TanStack Intent CLI + +Usage: + intent list [--json] Discover intent-enabled packages + intent meta List meta-skills for maintainers + intent validate [] Validate skill files (default: skills/) + intent install Print a skill that guides your coding agent to set up skill-to-task mappings + intent scaffold Print maintainer scaffold prompt + intent setup [--workflows] [--shim] [--all] Copy CI templates and generate shim + intent stale Check skills for staleness` + +const command = process.argv[2] +const commandArgs = process.argv.slice(3) + +switch (command) { + case 'list': + await cmdList(commandArgs) + break + case 'meta': + cmdMeta() + break + case 'validate': + cmdValidate(commandArgs) + break + case 'install': { + const prompt = `You are an AI assistant helping a developer set up skill-to-task mappings for their project. + +Follow these steps in order: + +1. CHECK FOR EXISTING MAPPINGS + Search the project's agent config files (CLAUDE.md, AGENTS.md, .cursorrules, + .github/copilot-instructions.md) for a block delimited by: + + + - If found: show the user the current mappings and ask "What would you like to update?" + Then skip to step 4 with their requested changes. + - If not found: continue to step 2. + +2. DISCOVER AVAILABLE SKILLS + Run: intent list + This outputs each skill's name, description, and full path — grouped by package. + +3. SCAN THE REPOSITORY + Build a picture of the project's structure and patterns: + - Read package.json for library dependencies + - Survey the directory layout (src/, app/, routes/, components/, api/, etc.) + - Note recurring patterns (routing, data fetching, auth, UI components, etc.) + + Based on this, propose 3–5 skill-to-task mappings. For each one explain: + - The task or code area (in plain language the user would recognise) + - Which skill applies and why + + Then ask: "What other tasks do you commonly use AI coding agents for? + I'll create mappings for those too." + +4. WRITE THE MAPPINGS BLOCK + Once you have the full set of mappings, write or update the agent config file + (prefer CLAUDE.md; create it if none exists) with this exact block: + + +# Skill mappings — when working in these areas, load the linked skill file into context. +skills: + - task: "describe the task or code area here" + load: "node_modules/package-name/skills/skill-name/SKILL.md" + + + Rules: + - Use the user's own words for task descriptions + - Include the exact path from \`intent list\` output so agents can load it directly + - Keep entries concise — this block is read on every agent task + - Preserve all content outside the block tags unchanged` + + console.log(prompt) + break + } + case 'scaffold': { + cmdScaffold() + break + } + case 'stale': { + const { checkStaleness } = await import('./staleness.js') + const { scanForIntents: scanStale } = await import('./scanner.js') + let staleResult + try { + staleResult = await scanStale() + } catch (err) { + console.error((err as Error).message) + process.exit(1) + } + + if (staleResult.packages.length === 0) { + console.log('No intent-enabled packages found.') + break + } + + const jsonStale = commandArgs.includes('--json') + const reports = await Promise.all( + staleResult.packages.map((pkg) => { + const pkgDir = join(process.cwd(), 'node_modules', pkg.name) + return checkStaleness(pkgDir, pkg.name) + }), + ) + + if (jsonStale) { + console.log(JSON.stringify(reports, null, 2)) + break + } + + for (const report of reports) { + const driftLabel = report.versionDrift + ? ` [${report.versionDrift} drift]` + : '' + const vLabel = + report.skillVersion && report.currentVersion + ? ` (${report.skillVersion} → ${report.currentVersion})` + : '' + console.log(`${report.library}${vLabel}${driftLabel}`) + + const stale = report.skills.filter((s) => s.needsReview) + if (stale.length === 0) { + console.log(' All skills up-to-date') + } else { + for (const skill of stale) { + console.log(` ⚠ ${skill.name}: ${skill.reasons.join(', ')}`) + } + } + console.log() + } + break + } + case 'setup': { + const { runSetup } = await import('./setup.js') + runSetup(process.cwd(), getMetaDir(), commandArgs) + break + } + default: + console.log(USAGE) + process.exit(command ? 1 : 0) +} diff --git a/packages/intent/src/display.ts b/packages/intent/src/display.ts index 1ace4191..85f2f87b 100644 --- a/packages/intent/src/display.ts +++ b/packages/intent/src/display.ts @@ -1,98 +1,98 @@ -// --------------------------------------------------------------------------- -// Shared display helpers for CLI output -// --------------------------------------------------------------------------- - -export interface SkillDisplay { - name: string - description: string - type?: string - path?: string -} - -function padColumn(text: string, width: number): string { - return text.length >= width ? text + ' ' : text.padEnd(width) -} - -export function printTable(headers: string[], rows: string[][]): void { - const widths = headers.map( - (h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? '').length)) + 2, - ) - - const headerLine = headers.map((h, i) => padColumn(h, widths[i]!)).join('') - const separator = widths.map((w) => '─'.repeat(w)).join('') - - console.log(headerLine) - console.log(separator) - for (const row of rows) { - console.log(row.map((cell, i) => padColumn(cell, widths[i]!)).join('')) - } -} - -function printSkillLine( - displayName: string, - skill: SkillDisplay, - indent: number, - opts: { nameWidth: number; showTypes: boolean }, -): void { - const nameStr = ' '.repeat(indent) + displayName - const padding = ' '.repeat(Math.max(2, opts.nameWidth - nameStr.length)) - const typeCol = opts.showTypes - ? (skill.type ? `[${skill.type}]` : '').padEnd(14) - : '' - console.log(`${nameStr}${padding}${typeCol}${skill.description}`) - if (skill.path) { - console.log(`${' '.repeat(indent + 2)}${skill.path}`) - } -} - -export function printSkillTree( - skills: SkillDisplay[], - opts: { nameWidth: number; showTypes: boolean }, -): void { - const roots: string[] = [] - const children = new Map() - - for (const skill of skills) { - const slashIdx = skill.name.indexOf('/') - if (slashIdx === -1) { - roots.push(skill.name) - } else { - const parent = skill.name.slice(0, slashIdx) - if (!children.has(parent)) children.set(parent, []) - children.get(parent)!.push(skill) - } - } - - if (roots.length === 0) { - for (const skill of skills) { - if (!roots.includes(skill.name)) roots.push(skill.name) - } - } - - for (const rootName of roots) { - const rootSkill = skills.find((s) => s.name === rootName) - if (!rootSkill) continue - - printSkillLine(rootName, rootSkill, 4, opts) - - for (const sub of children.get(rootName) ?? []) { - const childName = sub.name.slice(sub.name.indexOf('/') + 1) - printSkillLine(childName, sub, 6, opts) - } - } -} - -export function computeSkillNameWidth( - allPackageSkills: SkillDisplay[][], -): number { - let max = 0 - for (const skills of allPackageSkills) { - for (const s of skills) { - const slashIdx = s.name.indexOf('/') - const displayName = slashIdx === -1 ? s.name : s.name.slice(slashIdx + 1) - const indent = slashIdx === -1 ? 4 : 6 - max = Math.max(max, indent + displayName.length) - } - } - return max + 2 -} +// --------------------------------------------------------------------------- +// Shared display helpers for CLI output +// --------------------------------------------------------------------------- + +export interface SkillDisplay { + name: string + description: string + type?: string + path?: string +} + +function padColumn(text: string, width: number): string { + return text.length >= width ? text + ' ' : text.padEnd(width) +} + +export function printTable(headers: string[], rows: string[][]): void { + const widths = headers.map( + (h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? '').length)) + 2, + ) + + const headerLine = headers.map((h, i) => padColumn(h, widths[i]!)).join('') + const separator = widths.map((w) => '─'.repeat(w)).join('') + + console.log(headerLine) + console.log(separator) + for (const row of rows) { + console.log(row.map((cell, i) => padColumn(cell, widths[i]!)).join('')) + } +} + +function printSkillLine( + displayName: string, + skill: SkillDisplay, + indent: number, + opts: { nameWidth: number; showTypes: boolean }, +): void { + const nameStr = ' '.repeat(indent) + displayName + const padding = ' '.repeat(Math.max(2, opts.nameWidth - nameStr.length)) + const typeCol = opts.showTypes + ? (skill.type ? `[${skill.type}]` : '').padEnd(14) + : '' + console.log(`${nameStr}${padding}${typeCol}${skill.description}`) + if (skill.path) { + console.log(`${' '.repeat(indent + 2)}${skill.path}`) + } +} + +export function printSkillTree( + skills: SkillDisplay[], + opts: { nameWidth: number; showTypes: boolean }, +): void { + const roots: string[] = [] + const children = new Map() + + for (const skill of skills) { + const slashIdx = skill.name.indexOf('/') + if (slashIdx === -1) { + roots.push(skill.name) + } else { + const parent = skill.name.slice(0, slashIdx) + if (!children.has(parent)) children.set(parent, []) + children.get(parent)!.push(skill) + } + } + + if (roots.length === 0) { + for (const skill of skills) { + if (!roots.includes(skill.name)) roots.push(skill.name) + } + } + + for (const rootName of roots) { + const rootSkill = skills.find((s) => s.name === rootName) + if (!rootSkill) continue + + printSkillLine(rootName, rootSkill, 4, opts) + + for (const sub of children.get(rootName) ?? []) { + const childName = sub.name.slice(sub.name.indexOf('/') + 1) + printSkillLine(childName, sub, 6, opts) + } + } +} + +export function computeSkillNameWidth( + allPackageSkills: SkillDisplay[][], +): number { + let max = 0 + for (const skills of allPackageSkills) { + for (const s of skills) { + const slashIdx = s.name.indexOf('/') + const displayName = slashIdx === -1 ? s.name : s.name.slice(slashIdx + 1) + const indent = slashIdx === -1 ? 4 : 6 + max = Math.max(max, indent + displayName.length) + } + } + return max + 2 +} diff --git a/packages/intent/src/feedback.ts b/packages/intent/src/feedback.ts index a0c9d85c..a0d43e58 100644 --- a/packages/intent/src/feedback.ts +++ b/packages/intent/src/feedback.ts @@ -1,374 +1,374 @@ -import { execFileSync, execSync } from 'node:child_process' -import { readFileSync, writeFileSync } from 'node:fs' -import { join } from 'node:path' -import type { - FeedbackPayload, - IntentProjectConfig, - MetaFeedbackPayload, -} from './types.js' - -const META_FEEDBACK_REPO = 'TanStack/intent' - -// --------------------------------------------------------------------------- -// Secret detection -// --------------------------------------------------------------------------- - -const SECRET_PATTERNS = [ - /(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}/, // GitHub tokens - /(?:sk|pk)[-_](?:live|test)[-_][A-Za-z0-9]{24,}/, // Stripe keys - /AKIA[0-9A-Z]{16}/, // AWS access keys - /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, // PEM private keys - /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, // JWT-like tokens - /(?:Bearer|token)\s+[A-Za-z0-9_\-.~+/]{20,}/i, // Bearer tokens - /[A-Za-z0-9]{32,}(?=.*(?:key|secret|token|password))/i, // Generic secrets near keywords -] - -export function containsSecrets(text: string): boolean { - return SECRET_PATTERNS.some((pattern) => pattern.test(text)) -} - -// --------------------------------------------------------------------------- -// `gh` CLI detection -// --------------------------------------------------------------------------- - -export function hasGhCli(): boolean { - try { - execSync('gh --version', { stdio: 'ignore' }) - return true - } catch { - return false - } -} - -// --------------------------------------------------------------------------- -// Config resolution -// --------------------------------------------------------------------------- - -function getHomeConfigDir(): string { - return ( - process.env.XDG_CONFIG_HOME ?? - join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.config') - ) -} - -export function resolveFrequency(root: string): string { - // 1. User override (~/.config/intent/config.json) - const userConfigPath = join(getHomeConfigDir(), 'intent', 'config.json') - try { - const userCfg = JSON.parse( - readFileSync(userConfigPath, 'utf8'), - ) as Partial - if (userCfg.feedback?.frequency) return userCfg.feedback.frequency - } catch { - /* fallback */ - } - - // 2. Project config - const projectConfigPath = join(root, 'intent.config.json') - try { - const projCfg = JSON.parse( - readFileSync(projectConfigPath, 'utf8'), - ) as Partial - if (projCfg.feedback?.frequency) return projCfg.feedback.frequency - } catch { - /* fallback */ - } - - // 3. Default - return 'every-5' -} - -// --------------------------------------------------------------------------- -// Feedback payload validation -// --------------------------------------------------------------------------- - -const REQUIRED_FIELDS: (keyof FeedbackPayload)[] = [ - 'skill', - 'package', - 'skillVersion', - 'task', - 'whatWorked', - 'whatFailed', - 'missing', - 'selfCorrections', - 'userRating', -] - -export function validatePayload(payload: unknown): { - valid: boolean - errors: string[] -} { - const errors: string[] = [] - if (!payload || typeof payload !== 'object') { - return { valid: false, errors: ['Payload must be a JSON object'] } - } - const obj = payload as Record - - for (const field of REQUIRED_FIELDS) { - if ( - typeof obj[field] !== 'string' || - (obj[field] as string).trim() === '' - ) { - errors.push(`Missing or empty required field: ${field}`) - } - } - - if ( - obj.userRating && - !['good', 'mixed', 'bad'].includes(obj.userRating as string) - ) { - errors.push('userRating must be one of: good, mixed, bad') - } - - // Secret scan across all string values - const allText = Object.values(obj) - .filter((v) => typeof v === 'string') - .join('\n') - - if (containsSecrets(allText)) { - errors.push( - 'Payload appears to contain secrets or tokens — submission rejected', - ) - } - - return { valid: errors.length === 0, errors } -} - -// --------------------------------------------------------------------------- -// Meta-feedback payload validation -// --------------------------------------------------------------------------- - -const META_REQUIRED_FIELDS: (keyof MetaFeedbackPayload)[] = [ - 'metaSkill', - 'library', - 'agentUsed', - 'artifactQuality', - 'whatWorked', - 'whatFailed', - 'suggestions', - 'userRating', -] - -const VALID_META_SKILLS = [ - 'domain-discovery', - 'tree-generator', - 'generate-skill', - 'skill-staleness-check', -] - -const VALID_AGENTS = ['claude-code', 'cursor', 'copilot', 'codex', 'other'] - -const VALID_QUALITY_RATINGS = ['good', 'mixed', 'bad'] - -export function validateMetaPayload(payload: unknown): { - valid: boolean - errors: string[] -} { - const errors: string[] = [] - if (!payload || typeof payload !== 'object') { - return { valid: false, errors: ['Payload must be a JSON object'] } - } - const obj = payload as Record - - for (const field of META_REQUIRED_FIELDS) { - if ( - typeof obj[field] !== 'string' || - (obj[field] as string).trim() === '' - ) { - errors.push(`Missing or empty required field: ${field}`) - } - } - - if (obj.metaSkill && !VALID_META_SKILLS.includes(obj.metaSkill as string)) { - errors.push(`metaSkill must be one of: ${VALID_META_SKILLS.join(', ')}`) - } - - if (obj.agentUsed && !VALID_AGENTS.includes(obj.agentUsed as string)) { - errors.push(`agentUsed must be one of: ${VALID_AGENTS.join(', ')}`) - } - - if ( - obj.artifactQuality && - !VALID_QUALITY_RATINGS.includes(obj.artifactQuality as string) - ) { - errors.push('artifactQuality must be one of: good, mixed, bad') - } - - if ( - obj.userRating && - !VALID_QUALITY_RATINGS.includes(obj.userRating as string) - ) { - errors.push('userRating must be one of: good, mixed, bad') - } - - // Secret scan - const allText = Object.values(obj) - .filter((v) => typeof v === 'string') - .join('\n') - - if (containsSecrets(allText)) { - errors.push( - 'Payload appears to contain secrets or tokens — submission rejected', - ) - } - - return { valid: errors.length === 0, errors } -} - -// --------------------------------------------------------------------------- -// Markdown conversion -// --------------------------------------------------------------------------- - -export function metaToMarkdown(payload: MetaFeedbackPayload): string { - const lines = [ - `# Meta-Skill Feedback: ${payload.metaSkill}`, - '', - `**Library:** ${payload.library}`, - `**Agent:** ${payload.agentUsed}`, - `**Artifact quality:** ${payload.artifactQuality}`, - `**Rating:** ${payload.userRating}`, - ] - - if (payload.interviewQuality) { - lines.push(`**Interview quality:** ${payload.interviewQuality}`) - } - if (payload.failureModeQuality) { - lines.push(`**Failure mode quality:** ${payload.failureModeQuality}`) - } - - lines.push( - '', - '## What Worked', - payload.whatWorked, - '', - '## What Failed', - payload.whatFailed, - '', - '## Suggestions', - payload.suggestions, - ) - - return lines.join('\n') + '\n' -} - -export function toMarkdown(payload: FeedbackPayload): string { - const lines = [ - `# Skill Feedback: ${payload.skill}`, - '', - `**Package:** ${payload.package}`, - `**Skill version:** ${payload.skillVersion}`, - `**Rating:** ${payload.userRating}`, - '', - '## Task', - payload.task, - '', - '## What Worked', - payload.whatWorked, - '', - '## What Failed', - payload.whatFailed, - '', - '## Missing', - payload.missing, - '', - '## Self-Corrections', - payload.selfCorrections, - ] - - if (payload.userComments) { - lines.push('', '## User Comments', payload.userComments) - } - - return lines.join('\n') + '\n' -} - -// --------------------------------------------------------------------------- -// Submission -// --------------------------------------------------------------------------- - -export interface SubmitResult { - method: 'gh' | 'file' | 'stdout' - detail: string -} - -export function submitFeedback( - payload: FeedbackPayload, - repo: string, - opts: { ghAvailable: boolean; outputPath?: string }, -): SubmitResult { - const md = toMarkdown(payload) - - // Try gh - if (opts.ghAvailable) { - try { - const title = `Skill Feedback: ${payload.skill} (${payload.userRating})` - execFileSync( - 'gh', - ['issue', 'create', '--repo', repo, '--title', title, '--body', '-'], - { input: md, stdio: ['pipe', 'pipe', 'pipe'] }, - ) - return { method: 'gh', detail: `Submitted issue to ${repo}` } - } catch (err) { - const msg = err instanceof Error ? err.message : String(err) - console.error(`GitHub submission failed: ${msg}`) - console.error('Falling back to file output.') - } - } - - // File fallback - if (opts.outputPath) { - writeFileSync(opts.outputPath, md, 'utf8') - return { method: 'file', detail: `Saved to ${opts.outputPath}` } - } - - // Stdout fallback - return { method: 'stdout', detail: md } -} - -// --------------------------------------------------------------------------- -// Meta-feedback submission -// --------------------------------------------------------------------------- - -export function submitMetaFeedback( - payload: MetaFeedbackPayload, - opts: { ghAvailable: boolean; outputPath?: string }, -): SubmitResult { - const md = metaToMarkdown(payload) - - if (opts.ghAvailable) { - try { - const title = `Meta-Skill Feedback: ${payload.metaSkill} (${payload.userRating})` - execFileSync( - 'gh', - [ - 'issue', - 'create', - '--repo', - META_FEEDBACK_REPO, - '--title', - title, - '--label', - `feedback:${payload.metaSkill}`, - '--body', - '-', - ], - { input: md, stdio: ['pipe', 'pipe', 'pipe'] }, - ) - return { - method: 'gh', - detail: `Submitted issue to ${META_FEEDBACK_REPO}`, - } - } catch (err) { - const msg = err instanceof Error ? err.message : String(err) - console.error(`GitHub submission failed: ${msg}`) - console.error('Falling back to file output.') - } - } - - if (opts.outputPath) { - writeFileSync(opts.outputPath, md, 'utf8') - return { method: 'file', detail: `Saved to ${opts.outputPath}` } - } - - return { method: 'stdout', detail: md } -} +import { execFileSync, execSync } from 'node:child_process' +import { readFileSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' +import type { + FeedbackPayload, + IntentProjectConfig, + MetaFeedbackPayload, +} from './types.js' + +const META_FEEDBACK_REPO = 'TanStack/intent' + +// --------------------------------------------------------------------------- +// Secret detection +// --------------------------------------------------------------------------- + +const SECRET_PATTERNS = [ + /(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}/, // GitHub tokens + /(?:sk|pk)[-_](?:live|test)[-_][A-Za-z0-9]{24,}/, // Stripe keys + /AKIA[0-9A-Z]{16}/, // AWS access keys + /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, // PEM private keys + /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, // JWT-like tokens + /(?:Bearer|token)\s+[A-Za-z0-9_\-.~+/]{20,}/i, // Bearer tokens + /[A-Za-z0-9]{32,}(?=.*(?:key|secret|token|password))/i, // Generic secrets near keywords +] + +export function containsSecrets(text: string): boolean { + return SECRET_PATTERNS.some((pattern) => pattern.test(text)) +} + +// --------------------------------------------------------------------------- +// `gh` CLI detection +// --------------------------------------------------------------------------- + +export function hasGhCli(): boolean { + try { + execSync('gh --version', { stdio: 'ignore' }) + return true + } catch { + return false + } +} + +// --------------------------------------------------------------------------- +// Config resolution +// --------------------------------------------------------------------------- + +function getHomeConfigDir(): string { + return ( + process.env.XDG_CONFIG_HOME ?? + join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.config') + ) +} + +export function resolveFrequency(root: string): string { + // 1. User override (~/.config/intent/config.json) + const userConfigPath = join(getHomeConfigDir(), 'intent', 'config.json') + try { + const userCfg = JSON.parse( + readFileSync(userConfigPath, 'utf8'), + ) as Partial + if (userCfg.feedback?.frequency) return userCfg.feedback.frequency + } catch { + /* fallback */ + } + + // 2. Project config + const projectConfigPath = join(root, 'intent.config.json') + try { + const projCfg = JSON.parse( + readFileSync(projectConfigPath, 'utf8'), + ) as Partial + if (projCfg.feedback?.frequency) return projCfg.feedback.frequency + } catch { + /* fallback */ + } + + // 3. Default + return 'every-5' +} + +// --------------------------------------------------------------------------- +// Feedback payload validation +// --------------------------------------------------------------------------- + +const REQUIRED_FIELDS: (keyof FeedbackPayload)[] = [ + 'skill', + 'package', + 'skillVersion', + 'task', + 'whatWorked', + 'whatFailed', + 'missing', + 'selfCorrections', + 'userRating', +] + +export function validatePayload(payload: unknown): { + valid: boolean + errors: string[] +} { + const errors: string[] = [] + if (!payload || typeof payload !== 'object') { + return { valid: false, errors: ['Payload must be a JSON object'] } + } + const obj = payload as Record + + for (const field of REQUIRED_FIELDS) { + if ( + typeof obj[field] !== 'string' || + (obj[field] as string).trim() === '' + ) { + errors.push(`Missing or empty required field: ${field}`) + } + } + + if ( + obj.userRating && + !['good', 'mixed', 'bad'].includes(obj.userRating as string) + ) { + errors.push('userRating must be one of: good, mixed, bad') + } + + // Secret scan across all string values + const allText = Object.values(obj) + .filter((v) => typeof v === 'string') + .join('\n') + + if (containsSecrets(allText)) { + errors.push( + 'Payload appears to contain secrets or tokens — submission rejected', + ) + } + + return { valid: errors.length === 0, errors } +} + +// --------------------------------------------------------------------------- +// Meta-feedback payload validation +// --------------------------------------------------------------------------- + +const META_REQUIRED_FIELDS: (keyof MetaFeedbackPayload)[] = [ + 'metaSkill', + 'library', + 'agentUsed', + 'artifactQuality', + 'whatWorked', + 'whatFailed', + 'suggestions', + 'userRating', +] + +const VALID_META_SKILLS = [ + 'domain-discovery', + 'tree-generator', + 'generate-skill', + 'skill-staleness-check', +] + +const VALID_AGENTS = ['claude-code', 'cursor', 'copilot', 'codex', 'other'] + +const VALID_QUALITY_RATINGS = ['good', 'mixed', 'bad'] + +export function validateMetaPayload(payload: unknown): { + valid: boolean + errors: string[] +} { + const errors: string[] = [] + if (!payload || typeof payload !== 'object') { + return { valid: false, errors: ['Payload must be a JSON object'] } + } + const obj = payload as Record + + for (const field of META_REQUIRED_FIELDS) { + if ( + typeof obj[field] !== 'string' || + (obj[field] as string).trim() === '' + ) { + errors.push(`Missing or empty required field: ${field}`) + } + } + + if (obj.metaSkill && !VALID_META_SKILLS.includes(obj.metaSkill as string)) { + errors.push(`metaSkill must be one of: ${VALID_META_SKILLS.join(', ')}`) + } + + if (obj.agentUsed && !VALID_AGENTS.includes(obj.agentUsed as string)) { + errors.push(`agentUsed must be one of: ${VALID_AGENTS.join(', ')}`) + } + + if ( + obj.artifactQuality && + !VALID_QUALITY_RATINGS.includes(obj.artifactQuality as string) + ) { + errors.push('artifactQuality must be one of: good, mixed, bad') + } + + if ( + obj.userRating && + !VALID_QUALITY_RATINGS.includes(obj.userRating as string) + ) { + errors.push('userRating must be one of: good, mixed, bad') + } + + // Secret scan + const allText = Object.values(obj) + .filter((v) => typeof v === 'string') + .join('\n') + + if (containsSecrets(allText)) { + errors.push( + 'Payload appears to contain secrets or tokens — submission rejected', + ) + } + + return { valid: errors.length === 0, errors } +} + +// --------------------------------------------------------------------------- +// Markdown conversion +// --------------------------------------------------------------------------- + +export function metaToMarkdown(payload: MetaFeedbackPayload): string { + const lines = [ + `# Meta-Skill Feedback: ${payload.metaSkill}`, + '', + `**Library:** ${payload.library}`, + `**Agent:** ${payload.agentUsed}`, + `**Artifact quality:** ${payload.artifactQuality}`, + `**Rating:** ${payload.userRating}`, + ] + + if (payload.interviewQuality) { + lines.push(`**Interview quality:** ${payload.interviewQuality}`) + } + if (payload.failureModeQuality) { + lines.push(`**Failure mode quality:** ${payload.failureModeQuality}`) + } + + lines.push( + '', + '## What Worked', + payload.whatWorked, + '', + '## What Failed', + payload.whatFailed, + '', + '## Suggestions', + payload.suggestions, + ) + + return lines.join('\n') + '\n' +} + +export function toMarkdown(payload: FeedbackPayload): string { + const lines = [ + `# Skill Feedback: ${payload.skill}`, + '', + `**Package:** ${payload.package}`, + `**Skill version:** ${payload.skillVersion}`, + `**Rating:** ${payload.userRating}`, + '', + '## Task', + payload.task, + '', + '## What Worked', + payload.whatWorked, + '', + '## What Failed', + payload.whatFailed, + '', + '## Missing', + payload.missing, + '', + '## Self-Corrections', + payload.selfCorrections, + ] + + if (payload.userComments) { + lines.push('', '## User Comments', payload.userComments) + } + + return lines.join('\n') + '\n' +} + +// --------------------------------------------------------------------------- +// Submission +// --------------------------------------------------------------------------- + +export interface SubmitResult { + method: 'gh' | 'file' | 'stdout' + detail: string +} + +export function submitFeedback( + payload: FeedbackPayload, + repo: string, + opts: { ghAvailable: boolean; outputPath?: string }, +): SubmitResult { + const md = toMarkdown(payload) + + // Try gh + if (opts.ghAvailable) { + try { + const title = `Skill Feedback: ${payload.skill} (${payload.userRating})` + execFileSync( + 'gh', + ['issue', 'create', '--repo', repo, '--title', title, '--body', '-'], + { input: md, stdio: ['pipe', 'pipe', 'pipe'] }, + ) + return { method: 'gh', detail: `Submitted issue to ${repo}` } + } catch (err) { + const msg = err instanceof Error ? err.message : String(err) + console.error(`GitHub submission failed: ${msg}`) + console.error('Falling back to file output.') + } + } + + // File fallback + if (opts.outputPath) { + writeFileSync(opts.outputPath, md, 'utf8') + return { method: 'file', detail: `Saved to ${opts.outputPath}` } + } + + // Stdout fallback + return { method: 'stdout', detail: md } +} + +// --------------------------------------------------------------------------- +// Meta-feedback submission +// --------------------------------------------------------------------------- + +export function submitMetaFeedback( + payload: MetaFeedbackPayload, + opts: { ghAvailable: boolean; outputPath?: string }, +): SubmitResult { + const md = metaToMarkdown(payload) + + if (opts.ghAvailable) { + try { + const title = `Meta-Skill Feedback: ${payload.metaSkill} (${payload.userRating})` + execFileSync( + 'gh', + [ + 'issue', + 'create', + '--repo', + META_FEEDBACK_REPO, + '--title', + title, + '--label', + `feedback:${payload.metaSkill}`, + '--body', + '-', + ], + { input: md, stdio: ['pipe', 'pipe', 'pipe'] }, + ) + return { + method: 'gh', + detail: `Submitted issue to ${META_FEEDBACK_REPO}`, + } + } catch (err) { + const msg = err instanceof Error ? err.message : String(err) + console.error(`GitHub submission failed: ${msg}`) + console.error('Falling back to file output.') + } + } + + if (opts.outputPath) { + writeFileSync(opts.outputPath, md, 'utf8') + return { method: 'file', detail: `Saved to ${opts.outputPath}` } + } + + return { method: 'stdout', detail: md } +} diff --git a/packages/intent/src/index.ts b/packages/intent/src/index.ts index 3d22fde8..0436cbf9 100644 --- a/packages/intent/src/index.ts +++ b/packages/intent/src/index.ts @@ -1,28 +1,28 @@ -export { scanForIntents } from './scanner.js' -export { checkStaleness } from './staleness.js' -export { - containsSecrets, - hasGhCli, - metaToMarkdown, - resolveFrequency, - submitFeedback, - submitMetaFeedback, - toMarkdown, - validateMetaPayload, - validatePayload, -} from './feedback.js' -export { findSkillFiles, parseFrontmatter } from './utils.js' -export { runSetup } from './setup.js' -export type { - AgentName, - FeedbackPayload, - IntentConfig, - IntentPackage, - IntentProjectConfig, - MetaFeedbackPayload, - MetaSkillName, - ScanResult, - SkillEntry, - StalenessReport, - SkillStaleness, -} from './types.js' +export { scanForIntents } from './scanner.js' +export { checkStaleness } from './staleness.js' +export { + containsSecrets, + hasGhCli, + metaToMarkdown, + resolveFrequency, + submitFeedback, + submitMetaFeedback, + toMarkdown, + validateMetaPayload, + validatePayload, +} from './feedback.js' +export { findSkillFiles, parseFrontmatter } from './utils.js' +export { runSetup } from './setup.js' +export type { + AgentName, + FeedbackPayload, + IntentConfig, + IntentPackage, + IntentProjectConfig, + MetaFeedbackPayload, + MetaSkillName, + ScanResult, + SkillEntry, + StalenessReport, + SkillStaleness, +} from './types.js' diff --git a/packages/intent/src/intent-library.ts b/packages/intent/src/intent-library.ts index 8f930435..916f3bd6 100644 --- a/packages/intent/src/intent-library.ts +++ b/packages/intent/src/intent-library.ts @@ -1,147 +1,147 @@ -#!/usr/bin/env node - -import { computeSkillNameWidth, printSkillTree, printTable } from './display.js' -import type { LibraryScanResult } from './library-scanner.js' -import { scanLibrary } from './library-scanner.js' - -// --------------------------------------------------------------------------- -// Commands -// --------------------------------------------------------------------------- - -async function cmdList(): Promise { - let result: LibraryScanResult - try { - result = await scanLibrary(process.argv[1]!) - } catch (err) { - console.error((err as Error).message) - process.exit(1) - } - - if (result.packages.length === 0) { - console.log('No intent-enabled packages found.') - if (result.warnings.length > 0) { - console.log('\nWarnings:') - for (const w of result.warnings) console.log(` ⚠ ${w}`) - } - return - } - - const totalSkills = result.packages.reduce( - (sum, p) => sum + p.skills.length, - 0, - ) - console.log( - `\n${result.packages.length} intent-enabled packages, ${totalSkills} skills\n`, - ) - - // Summary table - const rows = result.packages.map((pkg) => [ - pkg.name, - pkg.version, - String(pkg.skills.length), - ]) - printTable(['PACKAGE', 'VERSION', 'SKILLS'], rows) - - // Skills detail - const allSkills = result.packages.map((p) => p.skills) - const nameWidth = computeSkillNameWidth(allSkills) - const showTypes = result.packages.some((p) => p.skills.some((s) => s.type)) - - console.log(`\nSkills:\n`) - for (const pkg of result.packages) { - console.log(` ${pkg.name}`) - printSkillTree(pkg.skills, { nameWidth, showTypes }) - console.log() - } - - console.log(`Feedback:`) - console.log( - ` Submit feedback on skill usage to help maintainers improve the skills.`, - ) - console.log( - ` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`, - ) - console.log() - - if (result.warnings.length > 0) { - console.log(`Warnings:`) - for (const w of result.warnings) console.log(` ⚠ ${w}`) - } -} - -function cmdInstall(): void { - const prompt = `You are an AI assistant helping a developer set up skill-to-task mappings for their project. - -Follow these steps in order: - -1. CHECK FOR EXISTING MAPPINGS - Search the project's agent config files (CLAUDE.md, AGENTS.md, .cursorrules, - .github/copilot-instructions.md) for a block delimited by: - - - - If found: show the user the current mappings and ask "What would you like to update?" - Then skip to step 4 with their requested changes. - - If not found: continue to step 2. - -2. DISCOVER AVAILABLE SKILLS - Run: intent list - This outputs each skill's name, description, and full path — grouped by package. - -3. SCAN THE REPOSITORY - Build a picture of the project's structure and patterns: - - Read package.json for library dependencies - - Survey the directory layout (src/, app/, routes/, components/, api/, etc.) - - Note recurring patterns (routing, data fetching, auth, UI components, etc.) - - Based on this, propose 3–5 skill-to-task mappings. For each one explain: - - The task or code area (in plain language the user would recognise) - - Which skill applies and why - - Then ask: "What other tasks do you commonly use AI coding agents for? - I'll create mappings for those too." - -4. WRITE THE MAPPINGS BLOCK - Once you have the full set of mappings, write or update the agent config file - (prefer CLAUDE.md; create it if none exists) with this exact block: - - -# Skill mappings — when working in these areas, load the linked skill file into context. -skills: - - task: "describe the task or code area here" - load: "node_modules/package-name/skills/skill-name/SKILL.md" - - - Rules: - - Use the user's own words for task descriptions - - Include the exact path from \`intent list\` output so agents can load it directly - - Keep entries concise — this block is read on every agent task - - Preserve all content outside the block tags unchanged` - - console.log(prompt) -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -const USAGE = `TanStack Intent - -Usage: - intent list List all available skills from this library and its dependencies - intent install Print a skill that guides your coding agent to scan the project - and set up skill-to-task mappings in your agent config` - -const command = process.argv[2] - -switch (command) { - case 'list': - case undefined: - await cmdList() - break - case 'install': - cmdInstall() - break - default: - console.log(USAGE) - process.exit(command ? 1 : 0) -} +#!/usr/bin/env node + +import { computeSkillNameWidth, printSkillTree, printTable } from './display.js' +import type { LibraryScanResult } from './library-scanner.js' +import { scanLibrary } from './library-scanner.js' + +// --------------------------------------------------------------------------- +// Commands +// --------------------------------------------------------------------------- + +async function cmdList(): Promise { + let result: LibraryScanResult + try { + result = await scanLibrary(process.argv[1]!) + } catch (err) { + console.error((err as Error).message) + process.exit(1) + } + + if (result.packages.length === 0) { + console.log('No intent-enabled packages found.') + if (result.warnings.length > 0) { + console.log('\nWarnings:') + for (const w of result.warnings) console.log(` ⚠ ${w}`) + } + return + } + + const totalSkills = result.packages.reduce( + (sum, p) => sum + p.skills.length, + 0, + ) + console.log( + `\n${result.packages.length} intent-enabled packages, ${totalSkills} skills\n`, + ) + + // Summary table + const rows = result.packages.map((pkg) => [ + pkg.name, + pkg.version, + String(pkg.skills.length), + ]) + printTable(['PACKAGE', 'VERSION', 'SKILLS'], rows) + + // Skills detail + const allSkills = result.packages.map((p) => p.skills) + const nameWidth = computeSkillNameWidth(allSkills) + const showTypes = result.packages.some((p) => p.skills.some((s) => s.type)) + + console.log(`\nSkills:\n`) + for (const pkg of result.packages) { + console.log(` ${pkg.name}`) + printSkillTree(pkg.skills, { nameWidth, showTypes }) + console.log() + } + + console.log(`Feedback:`) + console.log( + ` Submit feedback on skill usage to help maintainers improve the skills.`, + ) + console.log( + ` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`, + ) + console.log() + + if (result.warnings.length > 0) { + console.log(`Warnings:`) + for (const w of result.warnings) console.log(` ⚠ ${w}`) + } +} + +function cmdInstall(): void { + const prompt = `You are an AI assistant helping a developer set up skill-to-task mappings for their project. + +Follow these steps in order: + +1. CHECK FOR EXISTING MAPPINGS + Search the project's agent config files (CLAUDE.md, AGENTS.md, .cursorrules, + .github/copilot-instructions.md) for a block delimited by: + + + - If found: show the user the current mappings and ask "What would you like to update?" + Then skip to step 4 with their requested changes. + - If not found: continue to step 2. + +2. DISCOVER AVAILABLE SKILLS + Run: intent list + This outputs each skill's name, description, and full path — grouped by package. + +3. SCAN THE REPOSITORY + Build a picture of the project's structure and patterns: + - Read package.json for library dependencies + - Survey the directory layout (src/, app/, routes/, components/, api/, etc.) + - Note recurring patterns (routing, data fetching, auth, UI components, etc.) + + Based on this, propose 3–5 skill-to-task mappings. For each one explain: + - The task or code area (in plain language the user would recognise) + - Which skill applies and why + + Then ask: "What other tasks do you commonly use AI coding agents for? + I'll create mappings for those too." + +4. WRITE THE MAPPINGS BLOCK + Once you have the full set of mappings, write or update the agent config file + (prefer CLAUDE.md; create it if none exists) with this exact block: + + +# Skill mappings — when working in these areas, load the linked skill file into context. +skills: + - task: "describe the task or code area here" + load: "node_modules/package-name/skills/skill-name/SKILL.md" + + + Rules: + - Use the user's own words for task descriptions + - Include the exact path from \`intent list\` output so agents can load it directly + - Keep entries concise — this block is read on every agent task + - Preserve all content outside the block tags unchanged` + + console.log(prompt) +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +const USAGE = `TanStack Intent + +Usage: + intent list List all available skills from this library and its dependencies + intent install Print a skill that guides your coding agent to scan the project + and set up skill-to-task mappings in your agent config` + +const command = process.argv[2] + +switch (command) { + case 'list': + case undefined: + await cmdList() + break + case 'install': + cmdInstall() + break + default: + console.log(USAGE) + process.exit(command ? 1 : 0) +} diff --git a/packages/intent/src/library-scanner.ts b/packages/intent/src/library-scanner.ts index 4ca7beea..0ff96507 100644 --- a/packages/intent/src/library-scanner.ts +++ b/packages/intent/src/library-scanner.ts @@ -1,159 +1,159 @@ -import type { Dirent } from 'node:fs' -import { existsSync, readdirSync, readFileSync } from 'node:fs' -import { dirname, join, relative, sep } from 'node:path' -import type { SkillEntry } from './types.js' -import { parseFrontmatter } from './utils.js' - -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- - -export interface LibraryPackage { - name: string - version: string - description: string - skills: SkillEntry[] -} - -export interface LibraryScanResult { - packages: LibraryPackage[] - warnings: string[] -} - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -function readPkgJson(dir: string): Record | null { - try { - return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) - } catch { - return null - } -} - -function findHomeDir(scriptPath: string): string | null { - let dir = dirname(scriptPath) - while (true) { - if (existsSync(join(dir, 'package.json'))) return dir - const parent = dirname(dir) - if (parent === dir) return null - dir = parent - } -} - -function hasIntentBin(pkg: Record): boolean { - const bin = pkg.bin - if (!bin || typeof bin !== 'object') return false - return 'intent' in (bin as Record) -} - -function getDeps(pkg: Record): string[] { - const seen = new Set() - for (const field of ['dependencies', 'peerDependencies']) { - const d = pkg[field] - if (d && typeof d === 'object') { - for (const name of Object.keys(d as Record)) { - seen.add(name) - } - } - } - return [...seen] -} - -function discoverSkills(skillsDir: string): SkillEntry[] { - const skills: SkillEntry[] = [] - - function walk(dir: string): void { - let entries: Dirent[] - try { - entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' }) - } catch { - return - } - for (const entry of entries) { - if (!entry.isDirectory()) continue - const childDir = join(dir, entry.name) - const skillFile = join(childDir, 'SKILL.md') - if (existsSync(skillFile)) { - const fm = parseFrontmatter(skillFile) - const relName = relative(skillsDir, childDir).split(sep).join('/') - skills.push({ - name: typeof fm?.name === 'string' ? fm.name : relName, - path: skillFile, - description: - typeof fm?.description === 'string' - ? fm.description.replace(/\s+/g, ' ').trim() - : '', - type: typeof fm?.type === 'string' ? fm.type : undefined, - framework: - typeof fm?.framework === 'string' ? fm.framework : undefined, - }) - walk(childDir) - } - } - } - - walk(skillsDir) - return skills -} - -// --------------------------------------------------------------------------- -// Main scanner -// --------------------------------------------------------------------------- - -export async function scanLibrary( - scriptPath: string, - projectRoot?: string, -): Promise { - const nodeModulesDir = join(projectRoot ?? process.cwd(), 'node_modules') - const packages: LibraryPackage[] = [] - const warnings: string[] = [] - const visited = new Set() - - const homeDir = findHomeDir(scriptPath) - if (!homeDir) { - return { - packages, - warnings: ['Could not determine home package directory'], - } - } - - const homePkg = readPkgJson(homeDir) - if (!homePkg) { - return { packages, warnings: ['Could not read home package.json'] } - } - - const homeName = typeof homePkg.name === 'string' ? homePkg.name : '' - - function processPackage(name: string, dir: string): void { - if (visited.has(name)) return - visited.add(name) - - const pkg = readPkgJson(dir) - if (!pkg) { - warnings.push(`Could not read package.json for ${name}`) - return - } - - const skillsDir = join(dir, 'skills') - packages.push({ - name, - version: typeof pkg.version === 'string' ? pkg.version : '0.0.0', - description: typeof pkg.description === 'string' ? pkg.description : '', - skills: existsSync(skillsDir) ? discoverSkills(skillsDir) : [], - }) - - for (const depName of getDeps(pkg)) { - const depDir = join(nodeModulesDir, depName) - if (!existsSync(depDir)) continue - const depPkg = readPkgJson(depDir) - if (depPkg && hasIntentBin(depPkg)) { - processPackage(depName, depDir) - } - } - } - - processPackage(homeName, homeDir) - return { packages, warnings } -} +import type { Dirent } from 'node:fs' +import { existsSync, readdirSync, readFileSync } from 'node:fs' +import { dirname, join, relative, sep } from 'node:path' +import type { SkillEntry } from './types.js' +import { parseFrontmatter } from './utils.js' + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +export interface LibraryPackage { + name: string + version: string + description: string + skills: SkillEntry[] +} + +export interface LibraryScanResult { + packages: LibraryPackage[] + warnings: string[] +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function readPkgJson(dir: string): Record | null { + try { + return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) + } catch { + return null + } +} + +function findHomeDir(scriptPath: string): string | null { + let dir = dirname(scriptPath) + while (true) { + if (existsSync(join(dir, 'package.json'))) return dir + const parent = dirname(dir) + if (parent === dir) return null + dir = parent + } +} + +function hasIntentBin(pkg: Record): boolean { + const bin = pkg.bin + if (!bin || typeof bin !== 'object') return false + return 'intent' in (bin as Record) +} + +function getDeps(pkg: Record): string[] { + const seen = new Set() + for (const field of ['dependencies', 'peerDependencies']) { + const d = pkg[field] + if (d && typeof d === 'object') { + for (const name of Object.keys(d as Record)) { + seen.add(name) + } + } + } + return [...seen] +} + +function discoverSkills(skillsDir: string): SkillEntry[] { + const skills: SkillEntry[] = [] + + function walk(dir: string): void { + let entries: Dirent[] + try { + entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' }) + } catch { + return + } + for (const entry of entries) { + if (!entry.isDirectory()) continue + const childDir = join(dir, entry.name) + const skillFile = join(childDir, 'SKILL.md') + if (existsSync(skillFile)) { + const fm = parseFrontmatter(skillFile) + const relName = relative(skillsDir, childDir).split(sep).join('/') + skills.push({ + name: typeof fm?.name === 'string' ? fm.name : relName, + path: skillFile, + description: + typeof fm?.description === 'string' + ? fm.description.replace(/\s+/g, ' ').trim() + : '', + type: typeof fm?.type === 'string' ? fm.type : undefined, + framework: + typeof fm?.framework === 'string' ? fm.framework : undefined, + }) + walk(childDir) + } + } + } + + walk(skillsDir) + return skills +} + +// --------------------------------------------------------------------------- +// Main scanner +// --------------------------------------------------------------------------- + +export async function scanLibrary( + scriptPath: string, + projectRoot?: string, +): Promise { + const nodeModulesDir = join(projectRoot ?? process.cwd(), 'node_modules') + const packages: LibraryPackage[] = [] + const warnings: string[] = [] + const visited = new Set() + + const homeDir = findHomeDir(scriptPath) + if (!homeDir) { + return { + packages, + warnings: ['Could not determine home package directory'], + } + } + + const homePkg = readPkgJson(homeDir) + if (!homePkg) { + return { packages, warnings: ['Could not read home package.json'] } + } + + const homeName = typeof homePkg.name === 'string' ? homePkg.name : '' + + function processPackage(name: string, dir: string): void { + if (visited.has(name)) return + visited.add(name) + + const pkg = readPkgJson(dir) + if (!pkg) { + warnings.push(`Could not read package.json for ${name}`) + return + } + + const skillsDir = join(dir, 'skills') + packages.push({ + name, + version: typeof pkg.version === 'string' ? pkg.version : '0.0.0', + description: typeof pkg.description === 'string' ? pkg.description : '', + skills: existsSync(skillsDir) ? discoverSkills(skillsDir) : [], + }) + + for (const depName of getDeps(pkg)) { + const depDir = join(nodeModulesDir, depName) + if (!existsSync(depDir)) continue + const depPkg = readPkgJson(depDir) + if (depPkg && hasIntentBin(depPkg)) { + processPackage(depName, depDir) + } + } + } + + processPackage(homeName, homeDir) + return { packages, warnings } +} diff --git a/packages/intent/src/scanner.ts b/packages/intent/src/scanner.ts index 7985fcaf..a5ec4520 100644 --- a/packages/intent/src/scanner.ts +++ b/packages/intent/src/scanner.ts @@ -1,285 +1,285 @@ -import type { Dirent } from 'node:fs' -import { existsSync, readdirSync, readFileSync } from 'node:fs' -import { join, relative, sep } from 'node:path' -import type { - IntentConfig, - IntentPackage, - ScanResult, - SkillEntry, -} from './types.js' -import { parseFrontmatter } from './utils.js' - -// --------------------------------------------------------------------------- -// Package manager detection -// --------------------------------------------------------------------------- - -type PackageManager = ScanResult['packageManager'] - -function detectPackageManager(root: string): PackageManager { - // Check for unsupported environments first - if (existsSync(join(root, '.pnp.cjs')) || existsSync(join(root, '.pnp.js'))) { - throw new Error( - 'Yarn PnP is not yet supported. Add `nodeLinker: node-modules` to your .yarnrc.yml to use intent.', - ) - } - if ( - existsSync(join(root, 'deno.json')) && - !existsSync(join(root, 'node_modules')) - ) { - throw new Error( - 'Deno without node_modules is not yet supported. Add `"nodeModulesDir": "auto"` to your deno.json to use intent.', - ) - } - - if (existsSync(join(root, 'pnpm-lock.yaml'))) return 'pnpm' - if (existsSync(join(root, 'bun.lockb')) || existsSync(join(root, 'bun.lock'))) - return 'bun' - if (existsSync(join(root, 'yarn.lock'))) return 'yarn' - if (existsSync(join(root, 'package-lock.json'))) return 'npm' - return 'unknown' -} - -// --------------------------------------------------------------------------- -// Intent field validation -// --------------------------------------------------------------------------- - -function validateIntentField( - _pkgName: string, - intent: unknown, -): IntentConfig | null { - if (!intent || typeof intent !== 'object') return null - const pb = intent as Record - - if (pb.version !== 1) return null - if (typeof pb.repo !== 'string' || !pb.repo) return null - if (typeof pb.docs !== 'string' || !pb.docs) return null - - const requires = Array.isArray(pb.requires) - ? pb.requires.filter((r): r is string => typeof r === 'string') - : undefined - - return { - version: 1, - repo: pb.repo, - docs: pb.docs, - requires, - } -} - -/** - * Derive an IntentConfig from standard package.json fields when no explicit - * `intent` field is present. A package with a `skills/` directory signals - * intent support; `repo` and `docs` are derived from `repository` and - * `homepage`. - */ -function deriveIntentConfig( - pkgJson: Record, -): IntentConfig | null { - // Derive repo from repository field - let repo: string | null = null - if (typeof pkgJson.repository === 'string') { - repo = pkgJson.repository - } else if ( - pkgJson.repository && - typeof pkgJson.repository === 'object' && - typeof (pkgJson.repository as Record).url === 'string' - ) { - repo = (pkgJson.repository as Record).url as string - // Normalize git+https://github.com/foo/bar.git → foo/bar - repo = repo - .replace(/^git\+/, '') - .replace(/\.git$/, '') - .replace(/^https?:\/\/github\.com\//, '') - } - - // Derive docs from homepage field - const docs = - typeof pkgJson.homepage === 'string' ? pkgJson.homepage : undefined - - // Need at least a repo to be useful - if (!repo) return null - - // Derive requires from intent.requires if partially present - const intentPartial = pkgJson.intent as Record | undefined - const requires = - intentPartial && Array.isArray(intentPartial.requires) - ? intentPartial.requires.filter((r): r is string => typeof r === 'string') - : undefined - - return { - version: 1, - repo, - docs: docs ?? '', - requires, - } -} - -// --------------------------------------------------------------------------- -// Skill discovery within a package -// --------------------------------------------------------------------------- - -function discoverSkills(skillsDir: string, _baseName: string): SkillEntry[] { - const skills: SkillEntry[] = [] - - function walk(dir: string): void { - let entries: Dirent[] - try { - entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' }) - } catch { - return - } - for (const entry of entries) { - if (!entry.isDirectory()) continue - const childDir = join(dir, entry.name) - const skillFile = join(childDir, 'SKILL.md') - if (existsSync(skillFile)) { - const fm = parseFrontmatter(skillFile) - const relName = relative(skillsDir, childDir).split(sep).join('/') - const desc = - typeof fm?.description === 'string' - ? fm.description.replace(/\s+/g, ' ').trim() - : '' - skills.push({ - name: typeof fm?.name === 'string' ? fm.name : relName, - path: skillFile, - description: desc, - type: typeof fm?.type === 'string' ? fm.type : undefined, - framework: - typeof fm?.framework === 'string' ? fm.framework : undefined, - }) - // Recurse for sub-skills - walk(childDir) - } - } - } - - walk(skillsDir) - return skills -} - -// --------------------------------------------------------------------------- -// Topological sort on requires -// --------------------------------------------------------------------------- - -function topoSort(packages: IntentPackage[]): IntentPackage[] { - const byName = new Map(packages.map((p) => [p.name, p])) - const visited = new Set() - const sorted: IntentPackage[] = [] - - function visit(name: string): void { - if (visited.has(name)) return - visited.add(name) - const pkg = byName.get(name) - if (!pkg) return - for (const dep of pkg.intent.requires ?? []) { - visit(dep) - } - sorted.push(pkg) - } - - for (const pkg of packages) { - visit(pkg.name) - } - return sorted -} - -// --------------------------------------------------------------------------- -// Main scanner -// --------------------------------------------------------------------------- - -export async function scanForIntents(root?: string): Promise { - const projectRoot = root ?? process.cwd() - const packageManager = detectPackageManager(projectRoot) - const nodeModulesDir = join(projectRoot, 'node_modules') - - const packages: IntentPackage[] = [] - const warnings: string[] = [] - - if (!existsSync(nodeModulesDir)) { - return { packageManager, packages, warnings } - } - - // Collect all package directories to check - const packageDirs: Array<{ dirPath: string }> = [] - - let topEntries: Dirent[] - try { - topEntries = readdirSync(nodeModulesDir, { - withFileTypes: true, - encoding: 'utf8', - }) - } catch { - return { packageManager, packages, warnings } - } - - for (const entry of topEntries) { - if (!entry.isDirectory()) continue - const dirPath = join(nodeModulesDir, entry.name) - - if (entry.name.startsWith('@')) { - // Scoped package — check children - let scopedEntries: Dirent[] - try { - scopedEntries = readdirSync(dirPath, { - withFileTypes: true, - encoding: 'utf8', - }) - } catch { - continue - } - for (const scoped of scopedEntries) { - if (!scoped.isDirectory()) continue - packageDirs.push({ dirPath: join(dirPath, scoped.name) }) - } - } else if (!entry.name.startsWith('.')) { - packageDirs.push({ dirPath }) - } - } - - // Check each package for skills/ - for (const { dirPath } of packageDirs) { - const skillsDir = join(dirPath, 'skills') - if (!existsSync(skillsDir)) continue - - // Has skills/ — read package.json - const pkgJsonPath = join(dirPath, 'package.json') - let pkgJson: Record - try { - pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8')) - } catch { - warnings.push(`Could not read package.json for ${dirPath}`) - continue - } - - const pkgName = typeof pkgJson.name === 'string' ? pkgJson.name : 'unknown' - const pkgVersion = - typeof pkgJson.version === 'string' ? pkgJson.version : '0.0.0' - - // Validate intent field — explicit config takes priority, then derive from - // standard package.json fields (repository, homepage) - const intent = - validateIntentField(pkgName, pkgJson.intent) ?? - deriveIntentConfig(pkgJson) - if (!intent) { - warnings.push( - `${pkgName} has a skills/ directory but could not determine repo/docs from package.json (add a "repository" field or explicit "intent" config)`, - ) - continue - } - - // Discover skills - const skills = discoverSkills(skillsDir, pkgName) - - packages.push({ - name: pkgName, - version: pkgVersion, - intent, - skills, - }) - } - - // Sort by dependency order - const sorted = topoSort(packages) - - return { packageManager, packages: sorted, warnings } -} +import type { Dirent } from 'node:fs' +import { existsSync, readdirSync, readFileSync } from 'node:fs' +import { join, relative, sep } from 'node:path' +import type { + IntentConfig, + IntentPackage, + ScanResult, + SkillEntry, +} from './types.js' +import { parseFrontmatter } from './utils.js' + +// --------------------------------------------------------------------------- +// Package manager detection +// --------------------------------------------------------------------------- + +type PackageManager = ScanResult['packageManager'] + +function detectPackageManager(root: string): PackageManager { + // Check for unsupported environments first + if (existsSync(join(root, '.pnp.cjs')) || existsSync(join(root, '.pnp.js'))) { + throw new Error( + 'Yarn PnP is not yet supported. Add `nodeLinker: node-modules` to your .yarnrc.yml to use intent.', + ) + } + if ( + existsSync(join(root, 'deno.json')) && + !existsSync(join(root, 'node_modules')) + ) { + throw new Error( + 'Deno without node_modules is not yet supported. Add `"nodeModulesDir": "auto"` to your deno.json to use intent.', + ) + } + + if (existsSync(join(root, 'pnpm-lock.yaml'))) return 'pnpm' + if (existsSync(join(root, 'bun.lockb')) || existsSync(join(root, 'bun.lock'))) + return 'bun' + if (existsSync(join(root, 'yarn.lock'))) return 'yarn' + if (existsSync(join(root, 'package-lock.json'))) return 'npm' + return 'unknown' +} + +// --------------------------------------------------------------------------- +// Intent field validation +// --------------------------------------------------------------------------- + +function validateIntentField( + _pkgName: string, + intent: unknown, +): IntentConfig | null { + if (!intent || typeof intent !== 'object') return null + const pb = intent as Record + + if (pb.version !== 1) return null + if (typeof pb.repo !== 'string' || !pb.repo) return null + if (typeof pb.docs !== 'string' || !pb.docs) return null + + const requires = Array.isArray(pb.requires) + ? pb.requires.filter((r): r is string => typeof r === 'string') + : undefined + + return { + version: 1, + repo: pb.repo, + docs: pb.docs, + requires, + } +} + +/** + * Derive an IntentConfig from standard package.json fields when no explicit + * `intent` field is present. A package with a `skills/` directory signals + * intent support; `repo` and `docs` are derived from `repository` and + * `homepage`. + */ +function deriveIntentConfig( + pkgJson: Record, +): IntentConfig | null { + // Derive repo from repository field + let repo: string | null = null + if (typeof pkgJson.repository === 'string') { + repo = pkgJson.repository + } else if ( + pkgJson.repository && + typeof pkgJson.repository === 'object' && + typeof (pkgJson.repository as Record).url === 'string' + ) { + repo = (pkgJson.repository as Record).url as string + // Normalize git+https://github.com/foo/bar.git → foo/bar + repo = repo + .replace(/^git\+/, '') + .replace(/\.git$/, '') + .replace(/^https?:\/\/github\.com\//, '') + } + + // Derive docs from homepage field + const docs = + typeof pkgJson.homepage === 'string' ? pkgJson.homepage : undefined + + // Need at least a repo to be useful + if (!repo) return null + + // Derive requires from intent.requires if partially present + const intentPartial = pkgJson.intent as Record | undefined + const requires = + intentPartial && Array.isArray(intentPartial.requires) + ? intentPartial.requires.filter((r): r is string => typeof r === 'string') + : undefined + + return { + version: 1, + repo, + docs: docs ?? '', + requires, + } +} + +// --------------------------------------------------------------------------- +// Skill discovery within a package +// --------------------------------------------------------------------------- + +function discoverSkills(skillsDir: string, _baseName: string): SkillEntry[] { + const skills: SkillEntry[] = [] + + function walk(dir: string): void { + let entries: Dirent[] + try { + entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' }) + } catch { + return + } + for (const entry of entries) { + if (!entry.isDirectory()) continue + const childDir = join(dir, entry.name) + const skillFile = join(childDir, 'SKILL.md') + if (existsSync(skillFile)) { + const fm = parseFrontmatter(skillFile) + const relName = relative(skillsDir, childDir).split(sep).join('/') + const desc = + typeof fm?.description === 'string' + ? fm.description.replace(/\s+/g, ' ').trim() + : '' + skills.push({ + name: typeof fm?.name === 'string' ? fm.name : relName, + path: skillFile, + description: desc, + type: typeof fm?.type === 'string' ? fm.type : undefined, + framework: + typeof fm?.framework === 'string' ? fm.framework : undefined, + }) + // Recurse for sub-skills + walk(childDir) + } + } + } + + walk(skillsDir) + return skills +} + +// --------------------------------------------------------------------------- +// Topological sort on requires +// --------------------------------------------------------------------------- + +function topoSort(packages: IntentPackage[]): IntentPackage[] { + const byName = new Map(packages.map((p) => [p.name, p])) + const visited = new Set() + const sorted: IntentPackage[] = [] + + function visit(name: string): void { + if (visited.has(name)) return + visited.add(name) + const pkg = byName.get(name) + if (!pkg) return + for (const dep of pkg.intent.requires ?? []) { + visit(dep) + } + sorted.push(pkg) + } + + for (const pkg of packages) { + visit(pkg.name) + } + return sorted +} + +// --------------------------------------------------------------------------- +// Main scanner +// --------------------------------------------------------------------------- + +export async function scanForIntents(root?: string): Promise { + const projectRoot = root ?? process.cwd() + const packageManager = detectPackageManager(projectRoot) + const nodeModulesDir = join(projectRoot, 'node_modules') + + const packages: IntentPackage[] = [] + const warnings: string[] = [] + + if (!existsSync(nodeModulesDir)) { + return { packageManager, packages, warnings } + } + + // Collect all package directories to check + const packageDirs: Array<{ dirPath: string }> = [] + + let topEntries: Dirent[] + try { + topEntries = readdirSync(nodeModulesDir, { + withFileTypes: true, + encoding: 'utf8', + }) + } catch { + return { packageManager, packages, warnings } + } + + for (const entry of topEntries) { + if (!entry.isDirectory()) continue + const dirPath = join(nodeModulesDir, entry.name) + + if (entry.name.startsWith('@')) { + // Scoped package — check children + let scopedEntries: Dirent[] + try { + scopedEntries = readdirSync(dirPath, { + withFileTypes: true, + encoding: 'utf8', + }) + } catch { + continue + } + for (const scoped of scopedEntries) { + if (!scoped.isDirectory()) continue + packageDirs.push({ dirPath: join(dirPath, scoped.name) }) + } + } else if (!entry.name.startsWith('.')) { + packageDirs.push({ dirPath }) + } + } + + // Check each package for skills/ + for (const { dirPath } of packageDirs) { + const skillsDir = join(dirPath, 'skills') + if (!existsSync(skillsDir)) continue + + // Has skills/ — read package.json + const pkgJsonPath = join(dirPath, 'package.json') + let pkgJson: Record + try { + pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8')) + } catch { + warnings.push(`Could not read package.json for ${dirPath}`) + continue + } + + const pkgName = typeof pkgJson.name === 'string' ? pkgJson.name : 'unknown' + const pkgVersion = + typeof pkgJson.version === 'string' ? pkgJson.version : '0.0.0' + + // Validate intent field — explicit config takes priority, then derive from + // standard package.json fields (repository, homepage) + const intent = + validateIntentField(pkgName, pkgJson.intent) ?? + deriveIntentConfig(pkgJson) + if (!intent) { + warnings.push( + `${pkgName} has a skills/ directory but could not determine repo/docs from package.json (add a "repository" field or explicit "intent" config)`, + ) + continue + } + + // Discover skills + const skills = discoverSkills(skillsDir, pkgName) + + packages.push({ + name: pkgName, + version: pkgVersion, + intent, + skills, + }) + } + + // Sort by dependency order + const sorted = topoSort(packages) + + return { packageManager, packages: sorted, warnings } +} diff --git a/packages/intent/src/setup.ts b/packages/intent/src/setup.ts index f1a50e83..b6b64f5c 100644 --- a/packages/intent/src/setup.ts +++ b/packages/intent/src/setup.ts @@ -1,225 +1,225 @@ -import { - existsSync, - mkdirSync, - readFileSync, - readdirSync, - writeFileSync, -} from 'node:fs' -import { join } from 'node:path' - -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- - -export interface SetupResult { - workflows: string[] - skipped: string[] - shim: string | null -} - -interface TemplateVars { - PACKAGE_NAME: string - REPO: string - DOCS_PATH: string - SRC_PATH: string -} - -// --------------------------------------------------------------------------- -// Variable detection from package.json -// --------------------------------------------------------------------------- - -function detectVars(root: string): TemplateVars { - const pkgPath = join(root, 'package.json') - let pkgJson: Record = {} - try { - pkgJson = JSON.parse(readFileSync(pkgPath, 'utf8')) - } catch { - /* fallback to defaults */ - } - - const name = typeof pkgJson.name === 'string' ? pkgJson.name : 'unknown' - const intent = pkgJson.intent as Record | undefined - - const repo = - typeof intent?.repo === 'string' - ? intent.repo - : name.replace(/^@/, '').replace(/\//, '/') - - const docs = typeof intent?.docs === 'string' ? intent.docs : 'docs/' - - // Best-guess src path from common monorepo patterns - const shortName = name.replace(/^@[^/]+\//, '') - let srcPath = `packages/${shortName}/src/**` - if (existsSync(join(root, 'src'))) { - srcPath = 'src/**' - } - - return { - PACKAGE_NAME: name, - REPO: repo, - DOCS_PATH: docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**', - SRC_PATH: srcPath, - } -} - -// --------------------------------------------------------------------------- -// Template variable substitution -// --------------------------------------------------------------------------- - -function applyVars(content: string, vars: TemplateVars): string { - return content - .replace(/\{\{PACKAGE_NAME\}\}/g, vars.PACKAGE_NAME) - .replace(/\{\{REPO\}\}/g, vars.REPO) - .replace(/\{\{DOCS_PATH\}\}/g, vars.DOCS_PATH) - .replace(/\{\{SRC_PATH\}\}/g, vars.SRC_PATH) -} - -// --------------------------------------------------------------------------- -// Copy helpers -// --------------------------------------------------------------------------- - -function copyTemplates( - srcDir: string, - destDir: string, - vars: TemplateVars, -): { copied: string[]; skipped: string[] } { - const copied: string[] = [] - const skipped: string[] = [] - - if (!existsSync(srcDir)) return { copied, skipped } - - mkdirSync(destDir, { recursive: true }) - - for (const entry of readdirSync(srcDir)) { - const srcPath = join(srcDir, entry) - const destPath = join(destDir, entry) - - if (existsSync(destPath)) { - skipped.push(destPath) - continue - } - - const content = readFileSync(srcPath, 'utf8') - const substituted = applyVars(content, vars) - writeFileSync(destPath, substituted) - copied.push(destPath) - } - - return { copied, skipped } -} - -// --------------------------------------------------------------------------- -// Shim generation -// --------------------------------------------------------------------------- - -function getShimContent(ext: string): string { - return `#!/usr/bin/env node -// Auto-generated by @tanstack/intent setup -// Exposes the intent end-user CLI for consumers of this library. -// Commit this file, then add to your package.json: -// "bin": { "intent": "./bin/intent.${ext}" } -await import('@tanstack/intent/intent-library') -` -} - -function detectShimExtension(root: string): string { - try { - const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) - if (pkg.type === 'module') return 'js' - } catch { - // default to .mjs when package.json is unreadable - } - return 'mjs' -} - -function findExistingShim(root: string): string | null { - const shimJs = join(root, 'bin', 'intent.js') - if (existsSync(shimJs)) return shimJs - - const shimMjs = join(root, 'bin', 'intent.mjs') - if (existsSync(shimMjs)) return shimMjs - - return null -} - -function generateShim(root: string, result: SetupResult): void { - const existingShim = findExistingShim(root) - - if (existingShim) { - result.skipped.push(existingShim) - return - } - - const ext = detectShimExtension(root) - const shimPath = join(root, 'bin', `intent.${ext}`) - mkdirSync(join(root, 'bin'), { recursive: true }) - writeFileSync(shimPath, getShimContent(ext)) - result.shim = shimPath -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -export function runSetup( - root: string, - metaDir: string, - args: string[], -): SetupResult { - const doAll = args.includes('--all') - const doWorkflows = doAll || args.includes('--workflows') - const doShim = doAll || args.includes('--shim') - - const noFlagsGiven = !doWorkflows && !doShim - const installWorkflows = doWorkflows || noFlagsGiven - const installShim = doShim || noFlagsGiven - - const vars = detectVars(root) - const result: SetupResult = { - workflows: [], - skipped: [], - shim: null, - } - - const templatesDir = join(metaDir, 'templates') - - if (installWorkflows) { - const srcDir = join(templatesDir, 'workflows') - const destDir = join(root, '.github', 'workflows') - const { copied, skipped } = copyTemplates(srcDir, destDir, vars) - result.workflows = copied - result.skipped.push(...skipped) - } - - if (installShim) { - generateShim(root, result) - } - - // Print results - for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`) - for (const f of result.skipped) console.log(` Already exists: ${f}`) - - if (result.shim) { - const shimRelative = result.shim.replace(root + '/', './') - console.log(`✓ Generated intent shim: ${result.shim}`) - console.log(`\n Add to your package.json:`) - console.log(` "bin": { "intent": "${shimRelative}" }`) - console.log(`\n Add "bin" to your package.json "files" array.`) - } - - if ( - result.workflows.length === 0 && - result.shim === null && - result.skipped.length === 0 - ) { - console.log('No templates directory found. Is @tanstack/intent installed?') - } else if (result.workflows.length > 0) { - console.log(`\nTemplate variables applied:`) - console.log(` Package: ${vars.PACKAGE_NAME}`) - console.log(` Repo: ${vars.REPO}`) - console.log(` Docs: ${vars.DOCS_PATH}`) - console.log(` Src: ${vars.SRC_PATH}`) - } - - return result -} +import { + existsSync, + mkdirSync, + readFileSync, + readdirSync, + writeFileSync, +} from 'node:fs' +import { join } from 'node:path' + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +export interface SetupResult { + workflows: string[] + skipped: string[] + shim: string | null +} + +interface TemplateVars { + PACKAGE_NAME: string + REPO: string + DOCS_PATH: string + SRC_PATH: string +} + +// --------------------------------------------------------------------------- +// Variable detection from package.json +// --------------------------------------------------------------------------- + +function detectVars(root: string): TemplateVars { + const pkgPath = join(root, 'package.json') + let pkgJson: Record = {} + try { + pkgJson = JSON.parse(readFileSync(pkgPath, 'utf8')) + } catch { + /* fallback to defaults */ + } + + const name = typeof pkgJson.name === 'string' ? pkgJson.name : 'unknown' + const intent = pkgJson.intent as Record | undefined + + const repo = + typeof intent?.repo === 'string' + ? intent.repo + : name.replace(/^@/, '').replace(/\//, '/') + + const docs = typeof intent?.docs === 'string' ? intent.docs : 'docs/' + + // Best-guess src path from common monorepo patterns + const shortName = name.replace(/^@[^/]+\//, '') + let srcPath = `packages/${shortName}/src/**` + if (existsSync(join(root, 'src'))) { + srcPath = 'src/**' + } + + return { + PACKAGE_NAME: name, + REPO: repo, + DOCS_PATH: docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**', + SRC_PATH: srcPath, + } +} + +// --------------------------------------------------------------------------- +// Template variable substitution +// --------------------------------------------------------------------------- + +function applyVars(content: string, vars: TemplateVars): string { + return content + .replace(/\{\{PACKAGE_NAME\}\}/g, vars.PACKAGE_NAME) + .replace(/\{\{REPO\}\}/g, vars.REPO) + .replace(/\{\{DOCS_PATH\}\}/g, vars.DOCS_PATH) + .replace(/\{\{SRC_PATH\}\}/g, vars.SRC_PATH) +} + +// --------------------------------------------------------------------------- +// Copy helpers +// --------------------------------------------------------------------------- + +function copyTemplates( + srcDir: string, + destDir: string, + vars: TemplateVars, +): { copied: string[]; skipped: string[] } { + const copied: string[] = [] + const skipped: string[] = [] + + if (!existsSync(srcDir)) return { copied, skipped } + + mkdirSync(destDir, { recursive: true }) + + for (const entry of readdirSync(srcDir)) { + const srcPath = join(srcDir, entry) + const destPath = join(destDir, entry) + + if (existsSync(destPath)) { + skipped.push(destPath) + continue + } + + const content = readFileSync(srcPath, 'utf8') + const substituted = applyVars(content, vars) + writeFileSync(destPath, substituted) + copied.push(destPath) + } + + return { copied, skipped } +} + +// --------------------------------------------------------------------------- +// Shim generation +// --------------------------------------------------------------------------- + +function getShimContent(ext: string): string { + return `#!/usr/bin/env node +// Auto-generated by @tanstack/intent setup +// Exposes the intent end-user CLI for consumers of this library. +// Commit this file, then add to your package.json: +// "bin": { "intent": "./bin/intent.${ext}" } +await import('@tanstack/intent/intent-library') +` +} + +function detectShimExtension(root: string): string { + try { + const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) + if (pkg.type === 'module') return 'js' + } catch { + // default to .mjs when package.json is unreadable + } + return 'mjs' +} + +function findExistingShim(root: string): string | null { + const shimJs = join(root, 'bin', 'intent.js') + if (existsSync(shimJs)) return shimJs + + const shimMjs = join(root, 'bin', 'intent.mjs') + if (existsSync(shimMjs)) return shimMjs + + return null +} + +function generateShim(root: string, result: SetupResult): void { + const existingShim = findExistingShim(root) + + if (existingShim) { + result.skipped.push(existingShim) + return + } + + const ext = detectShimExtension(root) + const shimPath = join(root, 'bin', `intent.${ext}`) + mkdirSync(join(root, 'bin'), { recursive: true }) + writeFileSync(shimPath, getShimContent(ext)) + result.shim = shimPath +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +export function runSetup( + root: string, + metaDir: string, + args: string[], +): SetupResult { + const doAll = args.includes('--all') + const doWorkflows = doAll || args.includes('--workflows') + const doShim = doAll || args.includes('--shim') + + const noFlagsGiven = !doWorkflows && !doShim + const installWorkflows = doWorkflows || noFlagsGiven + const installShim = doShim || noFlagsGiven + + const vars = detectVars(root) + const result: SetupResult = { + workflows: [], + skipped: [], + shim: null, + } + + const templatesDir = join(metaDir, 'templates') + + if (installWorkflows) { + const srcDir = join(templatesDir, 'workflows') + const destDir = join(root, '.github', 'workflows') + const { copied, skipped } = copyTemplates(srcDir, destDir, vars) + result.workflows = copied + result.skipped.push(...skipped) + } + + if (installShim) { + generateShim(root, result) + } + + // Print results + for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`) + for (const f of result.skipped) console.log(` Already exists: ${f}`) + + if (result.shim) { + const shimRelative = result.shim.replace(root + '/', './') + console.log(`✓ Generated intent shim: ${result.shim}`) + console.log(`\n Add to your package.json:`) + console.log(` "bin": { "intent": "${shimRelative}" }`) + console.log(`\n Add "bin" to your package.json "files" array.`) + } + + if ( + result.workflows.length === 0 && + result.shim === null && + result.skipped.length === 0 + ) { + console.log('No templates directory found. Is @tanstack/intent installed?') + } else if (result.workflows.length > 0) { + console.log(`\nTemplate variables applied:`) + console.log(` Package: ${vars.PACKAGE_NAME}`) + console.log(` Repo: ${vars.REPO}`) + console.log(` Docs: ${vars.DOCS_PATH}`) + console.log(` Src: ${vars.SRC_PATH}`) + } + + return result +} diff --git a/packages/intent/src/staleness.ts b/packages/intent/src/staleness.ts index f2c25120..2b04668d 100644 --- a/packages/intent/src/staleness.ts +++ b/packages/intent/src/staleness.ts @@ -1,158 +1,158 @@ -import { readFileSync } from 'node:fs' -import { join, relative, sep } from 'node:path' -import type { StalenessReport, SkillStaleness } from './types.js' -import { findSkillFiles, parseFrontmatter } from './utils.js' - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -interface SkillMeta { - name: string - filePath: string - libraryVersion?: string - sources?: string[] -} - -function classifyVersionDrift( - oldVer: string, - newVer: string, -): 'major' | 'minor' | 'patch' | null { - if (oldVer === newVer) return null - const oldParts = oldVer - .replace(/[^0-9.]/g, '') - .split('.') - .map(Number) - const newParts = newVer - .replace(/[^0-9.]/g, '') - .split('.') - .map(Number) - if ((newParts[0] ?? 0) > (oldParts[0] ?? 0)) return 'major' - if ((newParts[1] ?? 0) > (oldParts[1] ?? 0)) return 'minor' - if ((newParts[2] ?? 0) > (oldParts[2] ?? 0)) return 'patch' - return null -} - -// --------------------------------------------------------------------------- -// npm version fetching -// --------------------------------------------------------------------------- - -async function fetchNpmVersion(packageName: string): Promise { - try { - const res = await fetch( - `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, - ) - if (!res.ok) return null - const data = (await res.json()) as Record - return typeof data.version === 'string' ? data.version : null - } catch { - return null - } -} - -// --------------------------------------------------------------------------- -// Sync state -// --------------------------------------------------------------------------- - -interface SyncState { - library_version?: string - skills?: Record }> -} - -function readSyncState(packageDir: string): SyncState | null { - const statePath = join(packageDir, 'skills', 'sync-state.json') - try { - return JSON.parse(readFileSync(statePath, 'utf8')) as SyncState - } catch { - return null - } -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -export async function checkStaleness( - packageDir: string, - packageName?: string, -): Promise { - const skillsDir = join(packageDir, 'skills') - const library = packageName ?? 'unknown' - - // Find all skills - const skillFiles = findSkillFiles(skillsDir) - const skillMetas: SkillMeta[] = skillFiles.map((filePath) => { - const fm = parseFrontmatter(filePath) - const relName = relative(skillsDir, filePath) - .replace(/[/\\]SKILL\.md$/, '') - .split(sep) - .join('/') - return { - name: (fm?.name as string) ?? relName, - filePath, - libraryVersion: fm?.library_version as string | undefined, - sources: Array.isArray(fm?.sources) - ? (fm.sources as string[]) - : undefined, - } - }) - - // Get the version from frontmatter (use first skill that has it) - const skillVersion = - skillMetas.find((s) => s.libraryVersion)?.libraryVersion ?? null - - // Fetch current npm version - const currentVersion = await fetchNpmVersion(library) - - // Classify drift - const versionDrift = - skillVersion && currentVersion - ? classifyVersionDrift(skillVersion, currentVersion) - : null - - // Read sync state - const syncState = readSyncState(packageDir) - - // Build per-skill staleness - const skills: SkillStaleness[] = skillMetas.map((skill) => { - const reasons: string[] = [] - - // Version drift - if ( - currentVersion && - skill.libraryVersion && - skill.libraryVersion !== currentVersion - ) { - reasons.push( - `version drift (${skill.libraryVersion} → ${currentVersion})`, - ) - } - - // Source SHA changes (from sync-state) - const storedShas = syncState?.skills?.[skill.name]?.sources_sha ?? {} - // We only flag if there are stored SHAs but we can't check remote - // (actual remote checking requires GitHub API — deferred to agent) - if (skill.sources && Object.keys(storedShas).length > 0) { - // Mark sources as needing review — agent will do the actual comparison - for (const source of skill.sources) { - if (!storedShas[source]) { - reasons.push(`new source (${source})`) - } - } - } - - return { - name: skill.name, - reasons, - needsReview: reasons.length > 0, - } - }) - - return { - library, - currentVersion, - skillVersion, - versionDrift, - skills, - } -} +import { readFileSync } from 'node:fs' +import { join, relative, sep } from 'node:path' +import type { StalenessReport, SkillStaleness } from './types.js' +import { findSkillFiles, parseFrontmatter } from './utils.js' + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +interface SkillMeta { + name: string + filePath: string + libraryVersion?: string + sources?: string[] +} + +function classifyVersionDrift( + oldVer: string, + newVer: string, +): 'major' | 'minor' | 'patch' | null { + if (oldVer === newVer) return null + const oldParts = oldVer + .replace(/[^0-9.]/g, '') + .split('.') + .map(Number) + const newParts = newVer + .replace(/[^0-9.]/g, '') + .split('.') + .map(Number) + if ((newParts[0] ?? 0) > (oldParts[0] ?? 0)) return 'major' + if ((newParts[1] ?? 0) > (oldParts[1] ?? 0)) return 'minor' + if ((newParts[2] ?? 0) > (oldParts[2] ?? 0)) return 'patch' + return null +} + +// --------------------------------------------------------------------------- +// npm version fetching +// --------------------------------------------------------------------------- + +async function fetchNpmVersion(packageName: string): Promise { + try { + const res = await fetch( + `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, + ) + if (!res.ok) return null + const data = (await res.json()) as Record + return typeof data.version === 'string' ? data.version : null + } catch { + return null + } +} + +// --------------------------------------------------------------------------- +// Sync state +// --------------------------------------------------------------------------- + +interface SyncState { + library_version?: string + skills?: Record }> +} + +function readSyncState(packageDir: string): SyncState | null { + const statePath = join(packageDir, 'skills', 'sync-state.json') + try { + return JSON.parse(readFileSync(statePath, 'utf8')) as SyncState + } catch { + return null + } +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +export async function checkStaleness( + packageDir: string, + packageName?: string, +): Promise { + const skillsDir = join(packageDir, 'skills') + const library = packageName ?? 'unknown' + + // Find all skills + const skillFiles = findSkillFiles(skillsDir) + const skillMetas: SkillMeta[] = skillFiles.map((filePath) => { + const fm = parseFrontmatter(filePath) + const relName = relative(skillsDir, filePath) + .replace(/[/\\]SKILL\.md$/, '') + .split(sep) + .join('/') + return { + name: (fm?.name as string) ?? relName, + filePath, + libraryVersion: fm?.library_version as string | undefined, + sources: Array.isArray(fm?.sources) + ? (fm.sources as string[]) + : undefined, + } + }) + + // Get the version from frontmatter (use first skill that has it) + const skillVersion = + skillMetas.find((s) => s.libraryVersion)?.libraryVersion ?? null + + // Fetch current npm version + const currentVersion = await fetchNpmVersion(library) + + // Classify drift + const versionDrift = + skillVersion && currentVersion + ? classifyVersionDrift(skillVersion, currentVersion) + : null + + // Read sync state + const syncState = readSyncState(packageDir) + + // Build per-skill staleness + const skills: SkillStaleness[] = skillMetas.map((skill) => { + const reasons: string[] = [] + + // Version drift + if ( + currentVersion && + skill.libraryVersion && + skill.libraryVersion !== currentVersion + ) { + reasons.push( + `version drift (${skill.libraryVersion} → ${currentVersion})`, + ) + } + + // Source SHA changes (from sync-state) + const storedShas = syncState?.skills?.[skill.name]?.sources_sha ?? {} + // We only flag if there are stored SHAs but we can't check remote + // (actual remote checking requires GitHub API — deferred to agent) + if (skill.sources && Object.keys(storedShas).length > 0) { + // Mark sources as needing review — agent will do the actual comparison + for (const source of skill.sources) { + if (!storedShas[source]) { + reasons.push(`new source (${source})`) + } + } + } + + return { + name: skill.name, + reasons, + needsReview: reasons.length > 0, + } + }) + + return { + library, + currentVersion, + skillVersion, + versionDrift, + skills, + } +} diff --git a/packages/intent/src/types.ts b/packages/intent/src/types.ts index eda3ab9f..e268225b 100644 --- a/packages/intent/src/types.ts +++ b/packages/intent/src/types.ts @@ -1,105 +1,105 @@ -// --------------------------------------------------------------------------- -// Intent config (lives in library package.json under "intent" key) -// --------------------------------------------------------------------------- - -export interface IntentConfig { - version: number - repo: string - docs: string - requires?: string[] -} - -// --------------------------------------------------------------------------- -// Scanner types -// --------------------------------------------------------------------------- - -export interface ScanResult { - packageManager: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'unknown' - packages: IntentPackage[] - warnings: string[] -} - -export interface IntentPackage { - name: string - version: string - intent: IntentConfig - skills: SkillEntry[] -} - -export interface SkillEntry { - name: string - path: string - description: string - type?: string - framework?: string -} - -// --------------------------------------------------------------------------- -// Staleness types -// --------------------------------------------------------------------------- - -export interface StalenessReport { - library: string - currentVersion: string | null - skillVersion: string | null - versionDrift: 'major' | 'minor' | 'patch' | null - skills: SkillStaleness[] -} - -export interface SkillStaleness { - name: string - reasons: string[] - needsReview: boolean -} - -// --------------------------------------------------------------------------- -// Feedback types -// --------------------------------------------------------------------------- - -export interface FeedbackPayload { - skill: string - package: string - skillVersion: string - task: string - whatWorked: string - whatFailed: string - missing: string - selfCorrections: string - userRating: 'good' | 'mixed' | 'bad' - userComments?: string -} - -// --------------------------------------------------------------------------- -// Meta-skill feedback types -// --------------------------------------------------------------------------- - -export type MetaSkillName = - | 'domain-discovery' - | 'tree-generator' - | 'generate-skill' - | 'skill-staleness-check' - -export type AgentName = 'claude-code' | 'cursor' | 'copilot' | 'codex' | 'other' - -export interface MetaFeedbackPayload { - metaSkill: MetaSkillName - library: string - agentUsed: AgentName - artifactQuality: 'good' | 'mixed' | 'bad' - interviewQuality?: 'good' | 'mixed' | 'bad' | 'skipped' - failureModeQuality?: 'good' | 'mixed' | 'bad' | 'not-applicable' - whatWorked: string - whatFailed: string - suggestions: string - userRating: 'good' | 'mixed' | 'bad' -} - -// --------------------------------------------------------------------------- -// Config types -// --------------------------------------------------------------------------- - -export interface IntentProjectConfig { - feedback: { - frequency: string // "always" | "every-N" | "never" - } -} +// --------------------------------------------------------------------------- +// Intent config (lives in library package.json under "intent" key) +// --------------------------------------------------------------------------- + +export interface IntentConfig { + version: number + repo: string + docs: string + requires?: string[] +} + +// --------------------------------------------------------------------------- +// Scanner types +// --------------------------------------------------------------------------- + +export interface ScanResult { + packageManager: 'npm' | 'pnpm' | 'yarn' | 'bun' | 'unknown' + packages: IntentPackage[] + warnings: string[] +} + +export interface IntentPackage { + name: string + version: string + intent: IntentConfig + skills: SkillEntry[] +} + +export interface SkillEntry { + name: string + path: string + description: string + type?: string + framework?: string +} + +// --------------------------------------------------------------------------- +// Staleness types +// --------------------------------------------------------------------------- + +export interface StalenessReport { + library: string + currentVersion: string | null + skillVersion: string | null + versionDrift: 'major' | 'minor' | 'patch' | null + skills: SkillStaleness[] +} + +export interface SkillStaleness { + name: string + reasons: string[] + needsReview: boolean +} + +// --------------------------------------------------------------------------- +// Feedback types +// --------------------------------------------------------------------------- + +export interface FeedbackPayload { + skill: string + package: string + skillVersion: string + task: string + whatWorked: string + whatFailed: string + missing: string + selfCorrections: string + userRating: 'good' | 'mixed' | 'bad' + userComments?: string +} + +// --------------------------------------------------------------------------- +// Meta-skill feedback types +// --------------------------------------------------------------------------- + +export type MetaSkillName = + | 'domain-discovery' + | 'tree-generator' + | 'generate-skill' + | 'skill-staleness-check' + +export type AgentName = 'claude-code' | 'cursor' | 'copilot' | 'codex' | 'other' + +export interface MetaFeedbackPayload { + metaSkill: MetaSkillName + library: string + agentUsed: AgentName + artifactQuality: 'good' | 'mixed' | 'bad' + interviewQuality?: 'good' | 'mixed' | 'bad' | 'skipped' + failureModeQuality?: 'good' | 'mixed' | 'bad' | 'not-applicable' + whatWorked: string + whatFailed: string + suggestions: string + userRating: 'good' | 'mixed' | 'bad' +} + +// --------------------------------------------------------------------------- +// Config types +// --------------------------------------------------------------------------- + +export interface IntentProjectConfig { + feedback: { + frequency: string // "always" | "every-N" | "never" + } +} diff --git a/packages/intent/src/utils.ts b/packages/intent/src/utils.ts index 4c2dadbd..ad1214f0 100644 --- a/packages/intent/src/utils.ts +++ b/packages/intent/src/utils.ts @@ -1,41 +1,41 @@ -import { existsSync, readdirSync, readFileSync } from 'node:fs' -import { join } from 'node:path' -import { parse as parseYaml } from 'yaml' - -/** - * Recursively find all SKILL.md files under a directory. - */ -export function findSkillFiles(dir: string): string[] { - const files: string[] = [] - if (!existsSync(dir)) return files - for (const entry of readdirSync(dir, { withFileTypes: true })) { - const fullPath = join(dir, entry.name) - if (entry.isDirectory()) { - files.push(...findSkillFiles(fullPath)) - } else if (entry.name === 'SKILL.md') { - files.push(fullPath) - } - } - return files -} - -/** - * Parse YAML frontmatter from a file. Returns null if no frontmatter or on error. - */ -export function parseFrontmatter( - filePath: string, -): Record | null { - let content: string - try { - content = readFileSync(filePath, 'utf8') - } catch { - return null - } - const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/) - if (!match?.[1]) return null - try { - return parseYaml(match[1]) as Record - } catch { - return null - } -} +import { existsSync, readdirSync, readFileSync } from 'node:fs' +import { join } from 'node:path' +import { parse as parseYaml } from 'yaml' + +/** + * Recursively find all SKILL.md files under a directory. + */ +export function findSkillFiles(dir: string): string[] { + const files: string[] = [] + if (!existsSync(dir)) return files + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const fullPath = join(dir, entry.name) + if (entry.isDirectory()) { + files.push(...findSkillFiles(fullPath)) + } else if (entry.name === 'SKILL.md') { + files.push(fullPath) + } + } + return files +} + +/** + * Parse YAML frontmatter from a file. Returns null if no frontmatter or on error. + */ +export function parseFrontmatter( + filePath: string, +): Record | null { + let content: string + try { + content = readFileSync(filePath, 'utf8') + } catch { + return null + } + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/) + if (!match?.[1]) return null + try { + return parseYaml(match[1]) as Record + } catch { + return null + } +} diff --git a/packages/intent/tests/cli.test.ts b/packages/intent/tests/cli.test.ts index 8bd3a9f6..d2547199 100644 --- a/packages/intent/tests/cli.test.ts +++ b/packages/intent/tests/cli.test.ts @@ -1,94 +1,94 @@ -import { existsSync, readdirSync, readFileSync } from 'node:fs' -import { join, dirname } from 'node:path' -import { fileURLToPath } from 'node:url' -import { describe, expect, it } from 'vitest' -import { parse as parseYaml } from 'yaml' - -// ── Meta-skills tests (intent meta) ── - -const thisDir = dirname(fileURLToPath(import.meta.url)) -const metaDir = join(thisDir, '..', 'meta') - -describe('intent meta', () => { - it('meta directory exists', () => { - expect(existsSync(metaDir)).toBe(true) - }) - - it('contains expected meta-skills', () => { - const entries = readdirSync(metaDir, { withFileTypes: true }) - .filter((e) => e.isDirectory()) - .filter((e) => existsSync(join(metaDir, e.name, 'SKILL.md'))) - .map((e) => e.name) - - expect(entries).toContain('domain-discovery') - expect(entries).toContain('tree-generator') - expect(entries).toContain('generate-skill') - expect(entries).toContain('skill-staleness-check') - }) - - it('each meta-skill has a description in frontmatter', () => { - const entries = readdirSync(metaDir, { withFileTypes: true }) - .filter((e) => e.isDirectory()) - .filter((e) => existsSync(join(metaDir, e.name, 'SKILL.md'))) - - for (const entry of entries) { - const content = readFileSync( - join(metaDir, entry.name, 'SKILL.md'), - 'utf8', - ) - const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/) - expect(match, `${entry.name} should have frontmatter`).not.toBeNull() - - const fm = parseYaml(match![1]) as Record - expect( - fm.description, - `${entry.name} should have a description`, - ).toBeTruthy() - } - }) -}) - -// ── Validate command logic ── - -describe('intent validate', () => { - it('finds SKILL.md files in meta directory', () => { - function findSkillFiles(dir: string): string[] { - const files: string[] = [] - for (const entry of readdirSync(dir, { withFileTypes: true })) { - const fullPath = join(dir, entry.name) - if (entry.isDirectory()) { - files.push(...findSkillFiles(fullPath)) - } else if (entry.name === 'SKILL.md') { - files.push(fullPath) - } - } - return files - } - - const files = findSkillFiles(metaDir) - expect(files.length).toBeGreaterThan(0) - }) -}) - -// ── Scanner JSON output shape ── - -describe('intent list --json shape', () => { - it('scanForIntents returns correct shape', async () => { - const { scanForIntents } = await import('../src/scanner.js') - // Run against a dir with no node_modules — should return valid shape - const { mkdtempSync } = await import('node:fs') - const { tmpdir } = await import('node:os') - const root = mkdtempSync(join(tmpdir(), 'cli-test-')) - - const result = await scanForIntents(root) - expect(result).toHaveProperty('packageManager') - expect(result).toHaveProperty('packages') - expect(result).toHaveProperty('warnings') - expect(Array.isArray(result.packages)).toBe(true) - expect(Array.isArray(result.warnings)).toBe(true) - - // Cleanup - const { rmSync } = await import('node:fs') - rmSync(root, { recursive: true, force: true }) - }) -}) +import { existsSync, readdirSync, readFileSync } from 'node:fs' +import { join, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' +import { describe, expect, it } from 'vitest' +import { parse as parseYaml } from 'yaml' + +// ── Meta-skills tests (intent meta) ── + +const thisDir = dirname(fileURLToPath(import.meta.url)) +const metaDir = join(thisDir, '..', 'meta') + +describe('intent meta', () => { + it('meta directory exists', () => { + expect(existsSync(metaDir)).toBe(true) + }) + + it('contains expected meta-skills', () => { + const entries = readdirSync(metaDir, { withFileTypes: true }) + .filter((e) => e.isDirectory()) + .filter((e) => existsSync(join(metaDir, e.name, 'SKILL.md'))) + .map((e) => e.name) + + expect(entries).toContain('domain-discovery') + expect(entries).toContain('tree-generator') + expect(entries).toContain('generate-skill') + expect(entries).toContain('skill-staleness-check') + }) + + it('each meta-skill has a description in frontmatter', () => { + const entries = readdirSync(metaDir, { withFileTypes: true }) + .filter((e) => e.isDirectory()) + .filter((e) => existsSync(join(metaDir, e.name, 'SKILL.md'))) + + for (const entry of entries) { + const content = readFileSync( + join(metaDir, entry.name, 'SKILL.md'), + 'utf8', + ) + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/) + expect(match, `${entry.name} should have frontmatter`).not.toBeNull() + + const fm = parseYaml(match![1]) as Record + expect( + fm.description, + `${entry.name} should have a description`, + ).toBeTruthy() + } + }) +}) + +// ── Validate command logic ── + +describe('intent validate', () => { + it('finds SKILL.md files in meta directory', () => { + function findSkillFiles(dir: string): string[] { + const files: string[] = [] + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const fullPath = join(dir, entry.name) + if (entry.isDirectory()) { + files.push(...findSkillFiles(fullPath)) + } else if (entry.name === 'SKILL.md') { + files.push(fullPath) + } + } + return files + } + + const files = findSkillFiles(metaDir) + expect(files.length).toBeGreaterThan(0) + }) +}) + +// ── Scanner JSON output shape ── + +describe('intent list --json shape', () => { + it('scanForIntents returns correct shape', async () => { + const { scanForIntents } = await import('../src/scanner.js') + // Run against a dir with no node_modules — should return valid shape + const { mkdtempSync } = await import('node:fs') + const { tmpdir } = await import('node:os') + const root = mkdtempSync(join(tmpdir(), 'cli-test-')) + + const result = await scanForIntents(root) + expect(result).toHaveProperty('packageManager') + expect(result).toHaveProperty('packages') + expect(result).toHaveProperty('warnings') + expect(Array.isArray(result.packages)).toBe(true) + expect(Array.isArray(result.warnings)).toBe(true) + + // Cleanup + const { rmSync } = await import('node:fs') + rmSync(root, { recursive: true, force: true }) + }) +}) diff --git a/packages/intent/tests/feedback.test.ts b/packages/intent/tests/feedback.test.ts index d2ea1581..35cd4e45 100644 --- a/packages/intent/tests/feedback.test.ts +++ b/packages/intent/tests/feedback.test.ts @@ -1,275 +1,275 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { - existsSync, - mkdirSync, - readFileSync, - rmSync, - writeFileSync, -} from 'node:fs' -import { join } from 'node:path' -import { tmpdir } from 'node:os' -import { - containsSecrets, - resolveFrequency, - submitFeedback, - toMarkdown, - validatePayload, -} from '../src/feedback.js' -import type { FeedbackPayload } from '../src/types.js' - -// --------------------------------------------------------------------------- -// Fixture helpers -// --------------------------------------------------------------------------- - -let tmpDir: string - -function setupDir(): string { - const dir = join( - tmpdir(), - `intent-fb-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, - ) - mkdirSync(dir, { recursive: true }) - return dir -} - -function validPayload( - overrides: Partial = {}, -): FeedbackPayload { - return { - skill: 'db-core/live-queries', - package: '@tanstack/db', - skillVersion: '0.5.0', - task: 'Set up a live query subscription', - whatWorked: 'Query builder syntax was great', - whatFailed: 'Collection creation missed an import', - missing: 'No examples for nested joins', - selfCorrections: 'Had to add missing import manually', - userRating: 'good', - ...overrides, - } -} - -beforeEach(() => { - tmpDir = setupDir() -}) - -afterEach(() => { - if (existsSync(tmpDir)) { - rmSync(tmpDir, { recursive: true, force: true }) - } -}) - -// --------------------------------------------------------------------------- -// containsSecrets -// --------------------------------------------------------------------------- - -describe('containsSecrets', () => { - it('detects GitHub tokens', () => { - expect(containsSecrets('token: ghp_' + 'A'.repeat(36))).toBe(true) - }) - - it('detects AWS access keys', () => { - expect(containsSecrets('key: AKIA' + '0'.repeat(16))).toBe(true) - }) - - it('detects PEM private keys', () => { - expect(containsSecrets('-----BEGIN RSA PRIVATE KEY-----')).toBe(true) - }) - - it('detects Stripe keys', () => { - expect(containsSecrets('sk-live-' + 'a'.repeat(24))).toBe(true) - }) - - it('detects Bearer tokens', () => { - expect(containsSecrets('Bearer ' + 'a'.repeat(30))).toBe(true) - }) - - it('does not flag normal text', () => { - expect( - containsSecrets( - 'This is a perfectly normal feedback message about queries.', - ), - ).toBe(false) - }) - - it('does not flag short strings', () => { - expect(containsSecrets('key=abc123')).toBe(false) - }) -}) - -// --------------------------------------------------------------------------- -// validatePayload -// --------------------------------------------------------------------------- - -describe('validatePayload', () => { - it('accepts a valid payload', () => { - const result = validatePayload(validPayload()) - expect(result.valid).toBe(true) - expect(result.errors).toHaveLength(0) - }) - - it('rejects non-object input', () => { - const result = validatePayload('not an object') - expect(result.valid).toBe(false) - expect(result.errors[0]).toContain('JSON object') - }) - - it('rejects null', () => { - const result = validatePayload(null) - expect(result.valid).toBe(false) - }) - - it('reports missing required fields', () => { - const result = validatePayload({ skill: 'test' }) - expect(result.valid).toBe(false) - expect(result.errors.length).toBeGreaterThan(1) - expect(result.errors.some((e) => e.includes('package'))).toBe(true) - }) - - it('rejects empty string fields', () => { - const result = validatePayload(validPayload({ task: '' })) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('task'))).toBe(true) - }) - - it('rejects invalid userRating', () => { - const result = validatePayload( - validPayload({ userRating: 'excellent' as 'good' }), - ) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('userRating'))).toBe(true) - }) - - it('rejects payloads containing secrets', () => { - const result = validatePayload( - validPayload({ - whatFailed: 'Used token ghp_' + 'A'.repeat(36) + ' and it failed', - }), - ) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('secrets'))).toBe(true) - }) -}) - -// --------------------------------------------------------------------------- -// toMarkdown -// --------------------------------------------------------------------------- - -describe('toMarkdown', () => { - it('converts payload to markdown', () => { - const md = toMarkdown(validPayload()) - expect(md).toContain('# Skill Feedback: db-core/live-queries') - expect(md).toContain('**Package:** @tanstack/db') - expect(md).toContain('**Rating:** good') - expect(md).toContain('## Task') - expect(md).toContain('## What Worked') - expect(md).toContain('## What Failed') - expect(md).toContain('## Missing') - expect(md).toContain('## Self-Corrections') - }) - - it('includes user comments when present', () => { - const md = toMarkdown(validPayload({ userComments: 'Great overall!' })) - expect(md).toContain('## User Comments') - expect(md).toContain('Great overall!') - }) - - it('omits user comments section when not present', () => { - const md = toMarkdown(validPayload()) - expect(md).not.toContain('## User Comments') - }) -}) - -// --------------------------------------------------------------------------- -// submitFeedback -// --------------------------------------------------------------------------- - -describe('submitFeedback', () => { - it('saves to file when gh not available and outputPath given', () => { - const outPath = join(tmpDir, 'feedback.md') - const result = submitFeedback(validPayload(), 'tanstack/db', { - ghAvailable: false, - outputPath: outPath, - }) - expect(result.method).toBe('file') - expect(result.detail).toContain(outPath) - expect(existsSync(outPath)).toBe(true) - const content = readFileSync(outPath, 'utf8') - expect(content).toContain('# Skill Feedback') - }) - - it('returns stdout when no gh and no outputPath', () => { - const result = submitFeedback(validPayload(), 'tanstack/db', { - ghAvailable: false, - }) - expect(result.method).toBe('stdout') - expect(result.detail).toContain('# Skill Feedback') - }) -}) - -// --------------------------------------------------------------------------- -// resolveFrequency -// --------------------------------------------------------------------------- - -describe('resolveFrequency', () => { - it('returns project config frequency when set', () => { - writeFileSync( - join(tmpDir, 'intent.config.json'), - JSON.stringify({ feedback: { frequency: 'always' } }), - ) - expect(resolveFrequency(tmpDir)).toBe('always') - }) - - it('returns default when no config exists', () => { - expect(resolveFrequency(tmpDir)).toBe('every-5') - }) - - it('reads user override via XDG_CONFIG_HOME', () => { - const configDir = join(tmpDir, 'xdg') - mkdirSync(join(configDir, 'intent'), { recursive: true }) - writeFileSync( - join(configDir, 'intent', 'config.json'), - JSON.stringify({ feedback: { frequency: 'never' } }), - ) - - const originalXdg = process.env.XDG_CONFIG_HOME - process.env.XDG_CONFIG_HOME = configDir - try { - expect(resolveFrequency(tmpDir)).toBe('never') - } finally { - if (originalXdg !== undefined) { - process.env.XDG_CONFIG_HOME = originalXdg - } else { - delete process.env.XDG_CONFIG_HOME - } - } - }) - - it('user override takes precedence over project config', () => { - // Project says "always" - writeFileSync( - join(tmpDir, 'intent.config.json'), - JSON.stringify({ feedback: { frequency: 'always' } }), - ) - - // User override says "never" - const configDir = join(tmpDir, 'xdg2') - mkdirSync(join(configDir, 'intent'), { recursive: true }) - writeFileSync( - join(configDir, 'intent', 'config.json'), - JSON.stringify({ feedback: { frequency: 'never' } }), - ) - - const originalXdg = process.env.XDG_CONFIG_HOME - process.env.XDG_CONFIG_HOME = configDir - try { - expect(resolveFrequency(tmpDir)).toBe('never') - } finally { - if (originalXdg !== undefined) { - process.env.XDG_CONFIG_HOME = originalXdg - } else { - delete process.env.XDG_CONFIG_HOME - } - } - }) -}) +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { + existsSync, + mkdirSync, + readFileSync, + rmSync, + writeFileSync, +} from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { + containsSecrets, + resolveFrequency, + submitFeedback, + toMarkdown, + validatePayload, +} from '../src/feedback.js' +import type { FeedbackPayload } from '../src/types.js' + +// --------------------------------------------------------------------------- +// Fixture helpers +// --------------------------------------------------------------------------- + +let tmpDir: string + +function setupDir(): string { + const dir = join( + tmpdir(), + `intent-fb-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + mkdirSync(dir, { recursive: true }) + return dir +} + +function validPayload( + overrides: Partial = {}, +): FeedbackPayload { + return { + skill: 'db-core/live-queries', + package: '@tanstack/db', + skillVersion: '0.5.0', + task: 'Set up a live query subscription', + whatWorked: 'Query builder syntax was great', + whatFailed: 'Collection creation missed an import', + missing: 'No examples for nested joins', + selfCorrections: 'Had to add missing import manually', + userRating: 'good', + ...overrides, + } +} + +beforeEach(() => { + tmpDir = setupDir() +}) + +afterEach(() => { + if (existsSync(tmpDir)) { + rmSync(tmpDir, { recursive: true, force: true }) + } +}) + +// --------------------------------------------------------------------------- +// containsSecrets +// --------------------------------------------------------------------------- + +describe('containsSecrets', () => { + it('detects GitHub tokens', () => { + expect(containsSecrets('token: ghp_' + 'A'.repeat(36))).toBe(true) + }) + + it('detects AWS access keys', () => { + expect(containsSecrets('key: AKIA' + '0'.repeat(16))).toBe(true) + }) + + it('detects PEM private keys', () => { + expect(containsSecrets('-----BEGIN RSA PRIVATE KEY-----')).toBe(true) + }) + + it('detects Stripe keys', () => { + expect(containsSecrets('sk-live-' + 'a'.repeat(24))).toBe(true) + }) + + it('detects Bearer tokens', () => { + expect(containsSecrets('Bearer ' + 'a'.repeat(30))).toBe(true) + }) + + it('does not flag normal text', () => { + expect( + containsSecrets( + 'This is a perfectly normal feedback message about queries.', + ), + ).toBe(false) + }) + + it('does not flag short strings', () => { + expect(containsSecrets('key=abc123')).toBe(false) + }) +}) + +// --------------------------------------------------------------------------- +// validatePayload +// --------------------------------------------------------------------------- + +describe('validatePayload', () => { + it('accepts a valid payload', () => { + const result = validatePayload(validPayload()) + expect(result.valid).toBe(true) + expect(result.errors).toHaveLength(0) + }) + + it('rejects non-object input', () => { + const result = validatePayload('not an object') + expect(result.valid).toBe(false) + expect(result.errors[0]).toContain('JSON object') + }) + + it('rejects null', () => { + const result = validatePayload(null) + expect(result.valid).toBe(false) + }) + + it('reports missing required fields', () => { + const result = validatePayload({ skill: 'test' }) + expect(result.valid).toBe(false) + expect(result.errors.length).toBeGreaterThan(1) + expect(result.errors.some((e) => e.includes('package'))).toBe(true) + }) + + it('rejects empty string fields', () => { + const result = validatePayload(validPayload({ task: '' })) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('task'))).toBe(true) + }) + + it('rejects invalid userRating', () => { + const result = validatePayload( + validPayload({ userRating: 'excellent' as 'good' }), + ) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('userRating'))).toBe(true) + }) + + it('rejects payloads containing secrets', () => { + const result = validatePayload( + validPayload({ + whatFailed: 'Used token ghp_' + 'A'.repeat(36) + ' and it failed', + }), + ) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('secrets'))).toBe(true) + }) +}) + +// --------------------------------------------------------------------------- +// toMarkdown +// --------------------------------------------------------------------------- + +describe('toMarkdown', () => { + it('converts payload to markdown', () => { + const md = toMarkdown(validPayload()) + expect(md).toContain('# Skill Feedback: db-core/live-queries') + expect(md).toContain('**Package:** @tanstack/db') + expect(md).toContain('**Rating:** good') + expect(md).toContain('## Task') + expect(md).toContain('## What Worked') + expect(md).toContain('## What Failed') + expect(md).toContain('## Missing') + expect(md).toContain('## Self-Corrections') + }) + + it('includes user comments when present', () => { + const md = toMarkdown(validPayload({ userComments: 'Great overall!' })) + expect(md).toContain('## User Comments') + expect(md).toContain('Great overall!') + }) + + it('omits user comments section when not present', () => { + const md = toMarkdown(validPayload()) + expect(md).not.toContain('## User Comments') + }) +}) + +// --------------------------------------------------------------------------- +// submitFeedback +// --------------------------------------------------------------------------- + +describe('submitFeedback', () => { + it('saves to file when gh not available and outputPath given', () => { + const outPath = join(tmpDir, 'feedback.md') + const result = submitFeedback(validPayload(), 'tanstack/db', { + ghAvailable: false, + outputPath: outPath, + }) + expect(result.method).toBe('file') + expect(result.detail).toContain(outPath) + expect(existsSync(outPath)).toBe(true) + const content = readFileSync(outPath, 'utf8') + expect(content).toContain('# Skill Feedback') + }) + + it('returns stdout when no gh and no outputPath', () => { + const result = submitFeedback(validPayload(), 'tanstack/db', { + ghAvailable: false, + }) + expect(result.method).toBe('stdout') + expect(result.detail).toContain('# Skill Feedback') + }) +}) + +// --------------------------------------------------------------------------- +// resolveFrequency +// --------------------------------------------------------------------------- + +describe('resolveFrequency', () => { + it('returns project config frequency when set', () => { + writeFileSync( + join(tmpDir, 'intent.config.json'), + JSON.stringify({ feedback: { frequency: 'always' } }), + ) + expect(resolveFrequency(tmpDir)).toBe('always') + }) + + it('returns default when no config exists', () => { + expect(resolveFrequency(tmpDir)).toBe('every-5') + }) + + it('reads user override via XDG_CONFIG_HOME', () => { + const configDir = join(tmpDir, 'xdg') + mkdirSync(join(configDir, 'intent'), { recursive: true }) + writeFileSync( + join(configDir, 'intent', 'config.json'), + JSON.stringify({ feedback: { frequency: 'never' } }), + ) + + const originalXdg = process.env.XDG_CONFIG_HOME + process.env.XDG_CONFIG_HOME = configDir + try { + expect(resolveFrequency(tmpDir)).toBe('never') + } finally { + if (originalXdg !== undefined) { + process.env.XDG_CONFIG_HOME = originalXdg + } else { + delete process.env.XDG_CONFIG_HOME + } + } + }) + + it('user override takes precedence over project config', () => { + // Project says "always" + writeFileSync( + join(tmpDir, 'intent.config.json'), + JSON.stringify({ feedback: { frequency: 'always' } }), + ) + + // User override says "never" + const configDir = join(tmpDir, 'xdg2') + mkdirSync(join(configDir, 'intent'), { recursive: true }) + writeFileSync( + join(configDir, 'intent', 'config.json'), + JSON.stringify({ feedback: { frequency: 'never' } }), + ) + + const originalXdg = process.env.XDG_CONFIG_HOME + process.env.XDG_CONFIG_HOME = configDir + try { + expect(resolveFrequency(tmpDir)).toBe('never') + } finally { + if (originalXdg !== undefined) { + process.env.XDG_CONFIG_HOME = originalXdg + } else { + delete process.env.XDG_CONFIG_HOME + } + } + }) +}) diff --git a/packages/intent/tests/library-scanner.test.ts b/packages/intent/tests/library-scanner.test.ts index 19ac7faf..38904e15 100644 --- a/packages/intent/tests/library-scanner.test.ts +++ b/packages/intent/tests/library-scanner.test.ts @@ -1,269 +1,269 @@ -import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' -import { join } from 'node:path' -import { tmpdir } from 'node:os' -import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { scanLibrary } from '../src/library-scanner.js' - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -function createDir(...segments: string[]): string { - const dir = join(...segments) - mkdirSync(dir, { recursive: true }) - return dir -} - -function writeJson(filePath: string, data: unknown): void { - writeFileSync(filePath, JSON.stringify(data, null, 2)) -} - -function writeSkillMd(dir: string, frontmatter: Record): void { - const yamlLines = Object.entries(frontmatter) - .map(([k, v]) => `${k}: ${typeof v === 'string' ? `"${v}"` : v}`) - .join('\n') - writeFileSync( - join(dir, 'SKILL.md'), - `---\n${yamlLines}\n---\n\nSkill content here.\n`, - ) -} - -// Simulate the script path as it would appear in a library's bin/intent.js shim. -// findHomeDir walks up from dirname(scriptPath) to find the nearest package.json. -function shimPath(pkgDir: string): string { - return join(pkgDir, 'bin', 'intent.js') -} - -// --------------------------------------------------------------------------- -// Setup / Teardown -// --------------------------------------------------------------------------- - -let root: string - -beforeEach(() => { - root = mkdtempSync(join(tmpdir(), 'library-scanner-test-')) -}) - -afterEach(() => { - rmSync(root, { recursive: true, force: true }) -}) - -// --------------------------------------------------------------------------- -// Tests -// --------------------------------------------------------------------------- - -describe('scanLibrary', () => { - it('returns the home package with its skills', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/router', - version: '1.2.0', - description: 'Type-safe router for React', - bin: { intent: './bin/intent.js' }, - }) - const skillDir = createDir(pkgDir, 'skills', 'routing') - writeSkillMd(skillDir, { - name: 'routing', - description: 'File-based route definitions', - }) - - const result = await scanLibrary(shimPath(pkgDir), root) - - expect(result.warnings).toEqual([]) - expect(result.packages).toHaveLength(1) - expect(result.packages[0]!.name).toBe('@tanstack/router') - expect(result.packages[0]!.version).toBe('1.2.0') - expect(result.packages[0]!.description).toBe('Type-safe router for React') - expect(result.packages[0]!.skills).toHaveLength(1) - expect(result.packages[0]!.skills[0]!.name).toBe('routing') - expect(result.packages[0]!.skills[0]!.description).toBe( - 'File-based route definitions', - ) - }) - - it('includes the full path to each SKILL.md', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - bin: { intent: './bin/intent.js' }, - }) - const skillDir = createDir(pkgDir, 'skills', 'routing') - writeSkillMd(skillDir, { name: 'routing', description: 'Routing patterns' }) - - const result = await scanLibrary(shimPath(pkgDir), root) - - const skill = result.packages[0]!.skills[0]! - expect(skill.path).toBe(join(pkgDir, 'skills', 'routing', 'SKILL.md')) - }) - - it('recursively discovers deps with bin.intent', async () => { - // Home package: @tanstack/router, depends on @tanstack/query - const routerDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(routerDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - description: 'Router', - bin: { intent: './bin/intent.js' }, - dependencies: { '@tanstack/query': '^5.0.0' }, - }) - const routerSkill = createDir(routerDir, 'skills', 'routing') - writeSkillMd(routerSkill, { - name: 'routing', - description: 'Route definitions', - }) - - // Dep package: @tanstack/query - const queryDir = createDir(root, 'node_modules', '@tanstack', 'query') - writeJson(join(queryDir, 'package.json'), { - name: '@tanstack/query', - version: '5.0.0', - description: 'Async state management', - bin: { intent: './bin/intent.js' }, - }) - const querySkill = createDir(queryDir, 'skills', 'fetching') - writeSkillMd(querySkill, { - name: 'fetching', - description: 'Query and mutation patterns', - }) - - const result = await scanLibrary(shimPath(routerDir), root) - - expect(result.warnings).toEqual([]) - expect(result.packages).toHaveLength(2) - - const names = result.packages.map((p) => p.name) - expect(names).toContain('@tanstack/router') - expect(names).toContain('@tanstack/query') - - const query = result.packages.find((p) => p.name === '@tanstack/query')! - expect(query.skills[0]!.name).toBe('fetching') - expect(query.skills[0]!.description).toBe('Query and mutation patterns') - }) - - it('discovers deps via peerDependencies', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - bin: { intent: './bin/intent.js' }, - peerDependencies: { '@tanstack/query': '^5.0.0' }, - }) - - const queryDir = createDir(root, 'node_modules', '@tanstack', 'query') - writeJson(join(queryDir, 'package.json'), { - name: '@tanstack/query', - version: '5.0.0', - bin: { intent: './bin/intent.js' }, - }) - const querySkill = createDir(queryDir, 'skills', 'fetching') - writeSkillMd(querySkill, { name: 'fetching', description: 'Fetching' }) - - const result = await scanLibrary(shimPath(pkgDir), root) - - const names = result.packages.map((p) => p.name) - expect(names).toContain('@tanstack/query') - }) - - it('skips deps without bin.intent', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - bin: { intent: './bin/intent.js' }, - dependencies: { react: '^18.0.0' }, - }) - - const reactDir = createDir(root, 'node_modules', 'react') - writeJson(join(reactDir, 'package.json'), { - name: 'react', - version: '18.0.0', - // no bin.intent - }) - const reactSkill = createDir(reactDir, 'skills', 'hooks') - writeSkillMd(reactSkill, { name: 'hooks', description: 'React hooks' }) - - const result = await scanLibrary(shimPath(pkgDir), root) - - const names = result.packages.map((p) => p.name) - expect(names).not.toContain('react') - }) - - it('handles packages with no skills/ directory', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - bin: { intent: './bin/intent.js' }, - }) - // No skills/ directory - - const result = await scanLibrary(shimPath(pkgDir), root) - - expect(result.packages).toHaveLength(1) - expect(result.packages[0]!.skills).toEqual([]) - }) - - it('does not visit the same package twice (cycle detection)', async () => { - // router -> query -> router (circular) - const routerDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(routerDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - bin: { intent: './bin/intent.js' }, - dependencies: { '@tanstack/query': '^5.0.0' }, - }) - - const queryDir = createDir(root, 'node_modules', '@tanstack', 'query') - writeJson(join(queryDir, 'package.json'), { - name: '@tanstack/query', - version: '5.0.0', - bin: { intent: './bin/intent.js' }, - dependencies: { '@tanstack/router': '^1.0.0' }, // circular back - }) - - const result = await scanLibrary(shimPath(routerDir), root) - - // Each package appears exactly once - const names = result.packages.map((p) => p.name) - expect(names).toHaveLength(2) - expect(new Set(names).size).toBe(2) - }) - - it('discovers sub-skills within a package', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/router', - version: '1.0.0', - bin: { intent: './bin/intent.js' }, - }) - const routingDir = createDir(pkgDir, 'skills', 'routing') - writeSkillMd(routingDir, { - name: 'routing', - description: 'Routing overview', - }) - const nestedDir = createDir(routingDir, 'nested-routes') - writeSkillMd(nestedDir, { - name: 'routing/nested-routes', - description: 'Nested route patterns', - }) - - const result = await scanLibrary(shimPath(pkgDir), root) - - const skills = result.packages[0]!.skills - expect(skills).toHaveLength(2) - const names = skills.map((s) => s.name) - expect(names).toContain('routing') - expect(names).toContain('routing/nested-routes') - }) - - it('returns a warning when home package.json cannot be found', async () => { - const fakeScript = join(root, 'nowhere', 'bin', 'intent.js') - - const result = await scanLibrary(fakeScript, root) - - expect(result.packages).toEqual([]) - expect(result.warnings).toHaveLength(1) - expect(result.warnings[0]).toMatch(/home package/i) - }) -}) +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { scanLibrary } from '../src/library-scanner.js' + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function createDir(...segments: string[]): string { + const dir = join(...segments) + mkdirSync(dir, { recursive: true }) + return dir +} + +function writeJson(filePath: string, data: unknown): void { + writeFileSync(filePath, JSON.stringify(data, null, 2)) +} + +function writeSkillMd(dir: string, frontmatter: Record): void { + const yamlLines = Object.entries(frontmatter) + .map(([k, v]) => `${k}: ${typeof v === 'string' ? `"${v}"` : v}`) + .join('\n') + writeFileSync( + join(dir, 'SKILL.md'), + `---\n${yamlLines}\n---\n\nSkill content here.\n`, + ) +} + +// Simulate the script path as it would appear in a library's bin/intent.js shim. +// findHomeDir walks up from dirname(scriptPath) to find the nearest package.json. +function shimPath(pkgDir: string): string { + return join(pkgDir, 'bin', 'intent.js') +} + +// --------------------------------------------------------------------------- +// Setup / Teardown +// --------------------------------------------------------------------------- + +let root: string + +beforeEach(() => { + root = mkdtempSync(join(tmpdir(), 'library-scanner-test-')) +}) + +afterEach(() => { + rmSync(root, { recursive: true, force: true }) +}) + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +describe('scanLibrary', () => { + it('returns the home package with its skills', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/router', + version: '1.2.0', + description: 'Type-safe router for React', + bin: { intent: './bin/intent.js' }, + }) + const skillDir = createDir(pkgDir, 'skills', 'routing') + writeSkillMd(skillDir, { + name: 'routing', + description: 'File-based route definitions', + }) + + const result = await scanLibrary(shimPath(pkgDir), root) + + expect(result.warnings).toEqual([]) + expect(result.packages).toHaveLength(1) + expect(result.packages[0]!.name).toBe('@tanstack/router') + expect(result.packages[0]!.version).toBe('1.2.0') + expect(result.packages[0]!.description).toBe('Type-safe router for React') + expect(result.packages[0]!.skills).toHaveLength(1) + expect(result.packages[0]!.skills[0]!.name).toBe('routing') + expect(result.packages[0]!.skills[0]!.description).toBe( + 'File-based route definitions', + ) + }) + + it('includes the full path to each SKILL.md', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + bin: { intent: './bin/intent.js' }, + }) + const skillDir = createDir(pkgDir, 'skills', 'routing') + writeSkillMd(skillDir, { name: 'routing', description: 'Routing patterns' }) + + const result = await scanLibrary(shimPath(pkgDir), root) + + const skill = result.packages[0]!.skills[0]! + expect(skill.path).toBe(join(pkgDir, 'skills', 'routing', 'SKILL.md')) + }) + + it('recursively discovers deps with bin.intent', async () => { + // Home package: @tanstack/router, depends on @tanstack/query + const routerDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(routerDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + description: 'Router', + bin: { intent: './bin/intent.js' }, + dependencies: { '@tanstack/query': '^5.0.0' }, + }) + const routerSkill = createDir(routerDir, 'skills', 'routing') + writeSkillMd(routerSkill, { + name: 'routing', + description: 'Route definitions', + }) + + // Dep package: @tanstack/query + const queryDir = createDir(root, 'node_modules', '@tanstack', 'query') + writeJson(join(queryDir, 'package.json'), { + name: '@tanstack/query', + version: '5.0.0', + description: 'Async state management', + bin: { intent: './bin/intent.js' }, + }) + const querySkill = createDir(queryDir, 'skills', 'fetching') + writeSkillMd(querySkill, { + name: 'fetching', + description: 'Query and mutation patterns', + }) + + const result = await scanLibrary(shimPath(routerDir), root) + + expect(result.warnings).toEqual([]) + expect(result.packages).toHaveLength(2) + + const names = result.packages.map((p) => p.name) + expect(names).toContain('@tanstack/router') + expect(names).toContain('@tanstack/query') + + const query = result.packages.find((p) => p.name === '@tanstack/query')! + expect(query.skills[0]!.name).toBe('fetching') + expect(query.skills[0]!.description).toBe('Query and mutation patterns') + }) + + it('discovers deps via peerDependencies', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + bin: { intent: './bin/intent.js' }, + peerDependencies: { '@tanstack/query': '^5.0.0' }, + }) + + const queryDir = createDir(root, 'node_modules', '@tanstack', 'query') + writeJson(join(queryDir, 'package.json'), { + name: '@tanstack/query', + version: '5.0.0', + bin: { intent: './bin/intent.js' }, + }) + const querySkill = createDir(queryDir, 'skills', 'fetching') + writeSkillMd(querySkill, { name: 'fetching', description: 'Fetching' }) + + const result = await scanLibrary(shimPath(pkgDir), root) + + const names = result.packages.map((p) => p.name) + expect(names).toContain('@tanstack/query') + }) + + it('skips deps without bin.intent', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + bin: { intent: './bin/intent.js' }, + dependencies: { react: '^18.0.0' }, + }) + + const reactDir = createDir(root, 'node_modules', 'react') + writeJson(join(reactDir, 'package.json'), { + name: 'react', + version: '18.0.0', + // no bin.intent + }) + const reactSkill = createDir(reactDir, 'skills', 'hooks') + writeSkillMd(reactSkill, { name: 'hooks', description: 'React hooks' }) + + const result = await scanLibrary(shimPath(pkgDir), root) + + const names = result.packages.map((p) => p.name) + expect(names).not.toContain('react') + }) + + it('handles packages with no skills/ directory', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + bin: { intent: './bin/intent.js' }, + }) + // No skills/ directory + + const result = await scanLibrary(shimPath(pkgDir), root) + + expect(result.packages).toHaveLength(1) + expect(result.packages[0]!.skills).toEqual([]) + }) + + it('does not visit the same package twice (cycle detection)', async () => { + // router -> query -> router (circular) + const routerDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(routerDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + bin: { intent: './bin/intent.js' }, + dependencies: { '@tanstack/query': '^5.0.0' }, + }) + + const queryDir = createDir(root, 'node_modules', '@tanstack', 'query') + writeJson(join(queryDir, 'package.json'), { + name: '@tanstack/query', + version: '5.0.0', + bin: { intent: './bin/intent.js' }, + dependencies: { '@tanstack/router': '^1.0.0' }, // circular back + }) + + const result = await scanLibrary(shimPath(routerDir), root) + + // Each package appears exactly once + const names = result.packages.map((p) => p.name) + expect(names).toHaveLength(2) + expect(new Set(names).size).toBe(2) + }) + + it('discovers sub-skills within a package', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/router', + version: '1.0.0', + bin: { intent: './bin/intent.js' }, + }) + const routingDir = createDir(pkgDir, 'skills', 'routing') + writeSkillMd(routingDir, { + name: 'routing', + description: 'Routing overview', + }) + const nestedDir = createDir(routingDir, 'nested-routes') + writeSkillMd(nestedDir, { + name: 'routing/nested-routes', + description: 'Nested route patterns', + }) + + const result = await scanLibrary(shimPath(pkgDir), root) + + const skills = result.packages[0]!.skills + expect(skills).toHaveLength(2) + const names = skills.map((s) => s.name) + expect(names).toContain('routing') + expect(names).toContain('routing/nested-routes') + }) + + it('returns a warning when home package.json cannot be found', async () => { + const fakeScript = join(root, 'nowhere', 'bin', 'intent.js') + + const result = await scanLibrary(fakeScript, root) + + expect(result.packages).toEqual([]) + expect(result.warnings).toHaveLength(1) + expect(result.warnings[0]).toMatch(/home package/i) + }) +}) diff --git a/packages/intent/tests/meta-feedback.test.ts b/packages/intent/tests/meta-feedback.test.ts index 54227cc3..8be8c676 100644 --- a/packages/intent/tests/meta-feedback.test.ts +++ b/packages/intent/tests/meta-feedback.test.ts @@ -1,199 +1,199 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { - existsSync, - mkdirSync, - readFileSync, - rmSync, - writeFileSync, -} from 'node:fs' -import { join } from 'node:path' -import { tmpdir } from 'node:os' -import { - validateMetaPayload, - metaToMarkdown, - submitMetaFeedback, -} from '../src/feedback.js' -import type { MetaFeedbackPayload } from '../src/types.js' - -// --------------------------------------------------------------------------- -// Fixtures -// --------------------------------------------------------------------------- - -let tmpDir: string - -function setupDir(): string { - const dir = join( - tmpdir(), - `intent-meta-fb-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, - ) - mkdirSync(dir, { recursive: true }) - return dir -} - -function validMetaPayload( - overrides: Partial = {}, -): MetaFeedbackPayload { - return { - metaSkill: 'domain-discovery', - library: '@tanstack/query', - agentUsed: 'claude-code', - artifactQuality: 'good', - whatWorked: 'Interview questions surfaced real failure modes', - whatFailed: 'Missed some SSR-specific gotchas', - suggestions: 'Add more framework-specific probing', - userRating: 'mixed', - ...overrides, - } -} - -beforeEach(() => { - tmpDir = setupDir() -}) - -afterEach(() => { - if (existsSync(tmpDir)) { - rmSync(tmpDir, { recursive: true, force: true }) - } -}) - -// --------------------------------------------------------------------------- -// validateMetaPayload -// --------------------------------------------------------------------------- - -describe('validateMetaPayload', () => { - it('accepts a valid payload', () => { - const result = validateMetaPayload(validMetaPayload()) - expect(result.valid).toBe(true) - expect(result.errors).toHaveLength(0) - }) - - it('rejects non-object input', () => { - const result = validateMetaPayload('not an object') - expect(result.valid).toBe(false) - expect(result.errors[0]).toContain('JSON object') - }) - - it('rejects null', () => { - const result = validateMetaPayload(null) - expect(result.valid).toBe(false) - }) - - it('reports missing required fields', () => { - const result = validateMetaPayload({ metaSkill: 'domain-discovery' }) - expect(result.valid).toBe(false) - expect(result.errors.length).toBeGreaterThan(1) - expect(result.errors.some((e) => e.includes('library'))).toBe(true) - }) - - it('rejects empty string fields', () => { - const result = validateMetaPayload(validMetaPayload({ whatWorked: '' })) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('whatWorked'))).toBe(true) - }) - - it('rejects invalid metaSkill', () => { - const result = validateMetaPayload( - validMetaPayload({ metaSkill: 'not-a-skill' as any }), - ) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('metaSkill'))).toBe(true) - }) - - it('rejects invalid agentUsed', () => { - const result = validateMetaPayload( - validMetaPayload({ agentUsed: 'chatgpt' as any }), - ) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('agentUsed'))).toBe(true) - }) - - it('rejects invalid userRating', () => { - const result = validateMetaPayload( - validMetaPayload({ userRating: 'excellent' as any }), - ) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('userRating'))).toBe(true) - }) - - it('rejects payloads containing secrets', () => { - const result = validateMetaPayload( - validMetaPayload({ - whatFailed: 'Used token ghp_' + 'A'.repeat(36) + ' and it failed', - }), - ) - expect(result.valid).toBe(false) - expect(result.errors.some((e) => e.includes('secrets'))).toBe(true) - }) - - it('accepts optional fields', () => { - const result = validateMetaPayload( - validMetaPayload({ - interviewQuality: 'good', - failureModeQuality: 'mixed', - }), - ) - expect(result.valid).toBe(true) - }) -}) - -// --------------------------------------------------------------------------- -// metaToMarkdown -// --------------------------------------------------------------------------- - -describe('metaToMarkdown', () => { - it('converts payload to markdown', () => { - const md = metaToMarkdown(validMetaPayload()) - expect(md).toContain('# Meta-Skill Feedback: domain-discovery') - expect(md).toContain('**Library:** @tanstack/query') - expect(md).toContain('**Agent:** claude-code') - expect(md).toContain('**Artifact quality:** good') - expect(md).toContain('**Rating:** mixed') - expect(md).toContain('## What Worked') - expect(md).toContain('## What Failed') - expect(md).toContain('## Suggestions') - }) - - it('includes optional quality fields when present', () => { - const md = metaToMarkdown( - validMetaPayload({ - interviewQuality: 'good', - failureModeQuality: 'bad', - }), - ) - expect(md).toContain('**Interview quality:** good') - expect(md).toContain('**Failure mode quality:** bad') - }) - - it('omits optional quality fields when not present', () => { - const md = metaToMarkdown(validMetaPayload()) - expect(md).not.toContain('Interview quality') - expect(md).not.toContain('Failure mode quality') - }) -}) - -// --------------------------------------------------------------------------- -// submitMetaFeedback -// --------------------------------------------------------------------------- - -describe('submitMetaFeedback', () => { - it('saves to file when gh not available and outputPath given', () => { - const outPath = join(tmpDir, 'meta-feedback.md') - const result = submitMetaFeedback(validMetaPayload(), { - ghAvailable: false, - outputPath: outPath, - }) - expect(result.method).toBe('file') - expect(result.detail).toContain(outPath) - expect(existsSync(outPath)).toBe(true) - const content = readFileSync(outPath, 'utf8') - expect(content).toContain('# Meta-Skill Feedback') - }) - - it('returns stdout when no gh and no outputPath', () => { - const result = submitMetaFeedback(validMetaPayload(), { - ghAvailable: false, - }) - expect(result.method).toBe('stdout') - expect(result.detail).toContain('# Meta-Skill Feedback') - }) -}) +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { + existsSync, + mkdirSync, + readFileSync, + rmSync, + writeFileSync, +} from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { + validateMetaPayload, + metaToMarkdown, + submitMetaFeedback, +} from '../src/feedback.js' +import type { MetaFeedbackPayload } from '../src/types.js' + +// --------------------------------------------------------------------------- +// Fixtures +// --------------------------------------------------------------------------- + +let tmpDir: string + +function setupDir(): string { + const dir = join( + tmpdir(), + `intent-meta-fb-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + mkdirSync(dir, { recursive: true }) + return dir +} + +function validMetaPayload( + overrides: Partial = {}, +): MetaFeedbackPayload { + return { + metaSkill: 'domain-discovery', + library: '@tanstack/query', + agentUsed: 'claude-code', + artifactQuality: 'good', + whatWorked: 'Interview questions surfaced real failure modes', + whatFailed: 'Missed some SSR-specific gotchas', + suggestions: 'Add more framework-specific probing', + userRating: 'mixed', + ...overrides, + } +} + +beforeEach(() => { + tmpDir = setupDir() +}) + +afterEach(() => { + if (existsSync(tmpDir)) { + rmSync(tmpDir, { recursive: true, force: true }) + } +}) + +// --------------------------------------------------------------------------- +// validateMetaPayload +// --------------------------------------------------------------------------- + +describe('validateMetaPayload', () => { + it('accepts a valid payload', () => { + const result = validateMetaPayload(validMetaPayload()) + expect(result.valid).toBe(true) + expect(result.errors).toHaveLength(0) + }) + + it('rejects non-object input', () => { + const result = validateMetaPayload('not an object') + expect(result.valid).toBe(false) + expect(result.errors[0]).toContain('JSON object') + }) + + it('rejects null', () => { + const result = validateMetaPayload(null) + expect(result.valid).toBe(false) + }) + + it('reports missing required fields', () => { + const result = validateMetaPayload({ metaSkill: 'domain-discovery' }) + expect(result.valid).toBe(false) + expect(result.errors.length).toBeGreaterThan(1) + expect(result.errors.some((e) => e.includes('library'))).toBe(true) + }) + + it('rejects empty string fields', () => { + const result = validateMetaPayload(validMetaPayload({ whatWorked: '' })) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('whatWorked'))).toBe(true) + }) + + it('rejects invalid metaSkill', () => { + const result = validateMetaPayload( + validMetaPayload({ metaSkill: 'not-a-skill' as any }), + ) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('metaSkill'))).toBe(true) + }) + + it('rejects invalid agentUsed', () => { + const result = validateMetaPayload( + validMetaPayload({ agentUsed: 'chatgpt' as any }), + ) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('agentUsed'))).toBe(true) + }) + + it('rejects invalid userRating', () => { + const result = validateMetaPayload( + validMetaPayload({ userRating: 'excellent' as any }), + ) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('userRating'))).toBe(true) + }) + + it('rejects payloads containing secrets', () => { + const result = validateMetaPayload( + validMetaPayload({ + whatFailed: 'Used token ghp_' + 'A'.repeat(36) + ' and it failed', + }), + ) + expect(result.valid).toBe(false) + expect(result.errors.some((e) => e.includes('secrets'))).toBe(true) + }) + + it('accepts optional fields', () => { + const result = validateMetaPayload( + validMetaPayload({ + interviewQuality: 'good', + failureModeQuality: 'mixed', + }), + ) + expect(result.valid).toBe(true) + }) +}) + +// --------------------------------------------------------------------------- +// metaToMarkdown +// --------------------------------------------------------------------------- + +describe('metaToMarkdown', () => { + it('converts payload to markdown', () => { + const md = metaToMarkdown(validMetaPayload()) + expect(md).toContain('# Meta-Skill Feedback: domain-discovery') + expect(md).toContain('**Library:** @tanstack/query') + expect(md).toContain('**Agent:** claude-code') + expect(md).toContain('**Artifact quality:** good') + expect(md).toContain('**Rating:** mixed') + expect(md).toContain('## What Worked') + expect(md).toContain('## What Failed') + expect(md).toContain('## Suggestions') + }) + + it('includes optional quality fields when present', () => { + const md = metaToMarkdown( + validMetaPayload({ + interviewQuality: 'good', + failureModeQuality: 'bad', + }), + ) + expect(md).toContain('**Interview quality:** good') + expect(md).toContain('**Failure mode quality:** bad') + }) + + it('omits optional quality fields when not present', () => { + const md = metaToMarkdown(validMetaPayload()) + expect(md).not.toContain('Interview quality') + expect(md).not.toContain('Failure mode quality') + }) +}) + +// --------------------------------------------------------------------------- +// submitMetaFeedback +// --------------------------------------------------------------------------- + +describe('submitMetaFeedback', () => { + it('saves to file when gh not available and outputPath given', () => { + const outPath = join(tmpDir, 'meta-feedback.md') + const result = submitMetaFeedback(validMetaPayload(), { + ghAvailable: false, + outputPath: outPath, + }) + expect(result.method).toBe('file') + expect(result.detail).toContain(outPath) + expect(existsSync(outPath)).toBe(true) + const content = readFileSync(outPath, 'utf8') + expect(content).toContain('# Meta-Skill Feedback') + }) + + it('returns stdout when no gh and no outputPath', () => { + const result = submitMetaFeedback(validMetaPayload(), { + ghAvailable: false, + }) + expect(result.method).toBe('stdout') + expect(result.detail).toContain('# Meta-Skill Feedback') + }) +}) diff --git a/packages/intent/tests/scanner.test.ts b/packages/intent/tests/scanner.test.ts index 7942ee39..1378c180 100644 --- a/packages/intent/tests/scanner.test.ts +++ b/packages/intent/tests/scanner.test.ts @@ -1,238 +1,238 @@ -import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' -import { join } from 'node:path' -import { tmpdir } from 'node:os' -import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { scanForIntents } from '../src/scanner.js' - -// ── Helpers ── - -function createDir(...segments: string[]): string { - const dir = join(...segments) - mkdirSync(dir, { recursive: true }) - return dir -} - -function writeJson(filePath: string, data: unknown): void { - writeFileSync(filePath, JSON.stringify(data, null, 2)) -} - -function writeSkillMd(dir: string, frontmatter: Record): void { - const yamlLines = Object.entries(frontmatter) - .map(([k, v]) => `${k}: ${typeof v === 'string' ? `"${v}"` : v}`) - .join('\n') - writeFileSync( - join(dir, 'SKILL.md'), - `---\n${yamlLines}\n---\n\nSkill content here.\n`, - ) -} - -// ── Setup / Teardown ── - -let root: string - -beforeEach(() => { - root = mkdtempSync(join(tmpdir(), 'intent-test-')) -}) - -afterEach(() => { - rmSync(root, { recursive: true, force: true }) -}) - -// ── Tests ── - -describe('scanForIntents', () => { - it('returns empty packages when no node_modules exists', async () => { - const result = await scanForIntents(root) - expect(result.packages).toEqual([]) - expect(result.warnings).toEqual([]) - }) - - it('returns empty packages when node_modules has no intent packages', async () => { - createDir(root, 'node_modules', 'some-lib') - writeJson(join(root, 'node_modules', 'some-lib', 'package.json'), { - name: 'some-lib', - version: '1.0.0', - }) - const result = await scanForIntents(root) - expect(result.packages).toEqual([]) - }) - - it('discovers an intent-enabled package with skills', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'db') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/db', - version: '0.5.2', - intent: { - version: 1, - repo: 'TanStack/db', - docs: 'docs/', - }, - }) - const skillDir = createDir(pkgDir, 'skills', 'db-core') - writeSkillMd(skillDir, { - name: 'db-core', - description: 'Core database concepts', - type: 'core', - }) - - const result = await scanForIntents(root) - expect(result.packages).toHaveLength(1) - expect(result.packages[0]!.name).toBe('@tanstack/db') - expect(result.packages[0]!.version).toBe('0.5.2') - expect(result.packages[0]!.skills).toHaveLength(1) - expect(result.packages[0]!.skills[0]!.name).toBe('db-core') - expect(result.packages[0]!.skills[0]!.description).toBe( - 'Core database concepts', - ) - }) - - it('discovers sub-skills', async () => { - const pkgDir = createDir(root, 'node_modules', '@tanstack', 'db') - writeJson(join(pkgDir, 'package.json'), { - name: '@tanstack/db', - version: '0.5.2', - intent: { version: 1, repo: 'TanStack/db', docs: 'docs/' }, - }) - const coreDir = createDir(pkgDir, 'skills', 'db-core') - writeSkillMd(coreDir, { name: 'db-core', description: 'Core' }) - const subDir = createDir(coreDir, 'live-queries') - writeSkillMd(subDir, { - name: 'db-core/live-queries', - description: 'Queries', - }) - - const result = await scanForIntents(root) - expect(result.packages[0]!.skills).toHaveLength(2) - const names = result.packages[0]!.skills.map((s) => s.name) - expect(names).toContain('db-core') - expect(names).toContain('db-core/live-queries') - }) - - it('warns on skills/ dir without valid intent field', async () => { - const pkgDir = createDir(root, 'node_modules', 'bad-pkg') - writeJson(join(pkgDir, 'package.json'), { - name: 'bad-pkg', - version: '1.0.0', - // no intent field - }) - createDir(pkgDir, 'skills', 'some-skill') - - const result = await scanForIntents(root) - expect(result.packages).toHaveLength(0) - expect(result.warnings).toHaveLength(1) - expect(result.warnings[0]).toContain('bad-pkg') - }) - - it('warns on invalid intent version', async () => { - const pkgDir = createDir(root, 'node_modules', 'wrong-ver') - writeJson(join(pkgDir, 'package.json'), { - name: 'wrong-ver', - version: '1.0.0', - intent: { version: 99, repo: 'foo/bar', docs: 'docs/' }, - }) - createDir(pkgDir, 'skills', 'some-skill') - - const result = await scanForIntents(root) - expect(result.packages).toHaveLength(0) - expect(result.warnings).toHaveLength(1) - }) - - it('sorts packages by dependency order (requires)', async () => { - // Create core package (no requires) - const coreDir = createDir(root, 'node_modules', '@tanstack', 'db') - writeJson(join(coreDir, 'package.json'), { - name: '@tanstack/db', - version: '0.5.0', - intent: { version: 1, repo: 'TanStack/db', docs: 'docs/' }, - }) - const coreSkill = createDir(coreDir, 'skills', 'db-core') - writeSkillMd(coreSkill, { name: 'db-core', description: 'Core' }) - - // Create framework package (requires core) - const reactDir = createDir(root, 'node_modules', '@tanstack', 'react-db') - writeJson(join(reactDir, 'package.json'), { - name: '@tanstack/react-db', - version: '0.5.0', - intent: { - version: 1, - repo: 'TanStack/db', - docs: 'docs/', - requires: ['@tanstack/db'], - }, - }) - const reactSkill = createDir(reactDir, 'skills', 'react-db') - writeSkillMd(reactSkill, { - name: 'react-db', - description: 'React bindings', - }) - - const result = await scanForIntents(root) - expect(result.packages).toHaveLength(2) - // Core should come first - expect(result.packages[0]!.name).toBe('@tanstack/db') - expect(result.packages[1]!.name).toBe('@tanstack/react-db') - }) - - it('skips packages without skills/ directory', async () => { - const pkgDir = createDir(root, 'node_modules', 'no-skills') - writeJson(join(pkgDir, 'package.json'), { - name: 'no-skills', - version: '1.0.0', - intent: { version: 1, repo: 'foo/bar', docs: 'docs/' }, - }) - // No skills/ directory - - const result = await scanForIntents(root) - expect(result.packages).toHaveLength(0) - expect(result.warnings).toHaveLength(0) - }) -}) - -describe('package manager detection', () => { - it('detects npm from package-lock.json', async () => { - writeFileSync(join(root, 'package-lock.json'), '{}') - createDir(root, 'node_modules') - const result = await scanForIntents(root) - expect(result.packageManager).toBe('npm') - }) - - it('detects pnpm from pnpm-lock.yaml', async () => { - writeFileSync(join(root, 'pnpm-lock.yaml'), '') - createDir(root, 'node_modules') - const result = await scanForIntents(root) - expect(result.packageManager).toBe('pnpm') - }) - - it('detects yarn from yarn.lock', async () => { - writeFileSync(join(root, 'yarn.lock'), '') - createDir(root, 'node_modules') - const result = await scanForIntents(root) - expect(result.packageManager).toBe('yarn') - }) - - it('detects bun from bun.lockb', async () => { - writeFileSync(join(root, 'bun.lockb'), '') - createDir(root, 'node_modules') - const result = await scanForIntents(root) - expect(result.packageManager).toBe('bun') - }) - - it('returns unknown when no lockfile found', async () => { - createDir(root, 'node_modules') - const result = await scanForIntents(root) - expect(result.packageManager).toBe('unknown') - }) - - it('throws for Yarn PnP', async () => { - writeFileSync(join(root, '.pnp.cjs'), '') - await expect(scanForIntents(root)).rejects.toThrow('Yarn PnP') - }) - - it('throws for Deno without node_modules', async () => { - writeFileSync(join(root, 'deno.json'), '{}') - // No node_modules dir - await expect(scanForIntents(root)).rejects.toThrow( - 'Deno without node_modules', - ) - }) -}) +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { scanForIntents } from '../src/scanner.js' + +// ── Helpers ── + +function createDir(...segments: string[]): string { + const dir = join(...segments) + mkdirSync(dir, { recursive: true }) + return dir +} + +function writeJson(filePath: string, data: unknown): void { + writeFileSync(filePath, JSON.stringify(data, null, 2)) +} + +function writeSkillMd(dir: string, frontmatter: Record): void { + const yamlLines = Object.entries(frontmatter) + .map(([k, v]) => `${k}: ${typeof v === 'string' ? `"${v}"` : v}`) + .join('\n') + writeFileSync( + join(dir, 'SKILL.md'), + `---\n${yamlLines}\n---\n\nSkill content here.\n`, + ) +} + +// ── Setup / Teardown ── + +let root: string + +beforeEach(() => { + root = mkdtempSync(join(tmpdir(), 'intent-test-')) +}) + +afterEach(() => { + rmSync(root, { recursive: true, force: true }) +}) + +// ── Tests ── + +describe('scanForIntents', () => { + it('returns empty packages when no node_modules exists', async () => { + const result = await scanForIntents(root) + expect(result.packages).toEqual([]) + expect(result.warnings).toEqual([]) + }) + + it('returns empty packages when node_modules has no intent packages', async () => { + createDir(root, 'node_modules', 'some-lib') + writeJson(join(root, 'node_modules', 'some-lib', 'package.json'), { + name: 'some-lib', + version: '1.0.0', + }) + const result = await scanForIntents(root) + expect(result.packages).toEqual([]) + }) + + it('discovers an intent-enabled package with skills', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'db') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/db', + version: '0.5.2', + intent: { + version: 1, + repo: 'TanStack/db', + docs: 'docs/', + }, + }) + const skillDir = createDir(pkgDir, 'skills', 'db-core') + writeSkillMd(skillDir, { + name: 'db-core', + description: 'Core database concepts', + type: 'core', + }) + + const result = await scanForIntents(root) + expect(result.packages).toHaveLength(1) + expect(result.packages[0]!.name).toBe('@tanstack/db') + expect(result.packages[0]!.version).toBe('0.5.2') + expect(result.packages[0]!.skills).toHaveLength(1) + expect(result.packages[0]!.skills[0]!.name).toBe('db-core') + expect(result.packages[0]!.skills[0]!.description).toBe( + 'Core database concepts', + ) + }) + + it('discovers sub-skills', async () => { + const pkgDir = createDir(root, 'node_modules', '@tanstack', 'db') + writeJson(join(pkgDir, 'package.json'), { + name: '@tanstack/db', + version: '0.5.2', + intent: { version: 1, repo: 'TanStack/db', docs: 'docs/' }, + }) + const coreDir = createDir(pkgDir, 'skills', 'db-core') + writeSkillMd(coreDir, { name: 'db-core', description: 'Core' }) + const subDir = createDir(coreDir, 'live-queries') + writeSkillMd(subDir, { + name: 'db-core/live-queries', + description: 'Queries', + }) + + const result = await scanForIntents(root) + expect(result.packages[0]!.skills).toHaveLength(2) + const names = result.packages[0]!.skills.map((s) => s.name) + expect(names).toContain('db-core') + expect(names).toContain('db-core/live-queries') + }) + + it('warns on skills/ dir without valid intent field', async () => { + const pkgDir = createDir(root, 'node_modules', 'bad-pkg') + writeJson(join(pkgDir, 'package.json'), { + name: 'bad-pkg', + version: '1.0.0', + // no intent field + }) + createDir(pkgDir, 'skills', 'some-skill') + + const result = await scanForIntents(root) + expect(result.packages).toHaveLength(0) + expect(result.warnings).toHaveLength(1) + expect(result.warnings[0]).toContain('bad-pkg') + }) + + it('warns on invalid intent version', async () => { + const pkgDir = createDir(root, 'node_modules', 'wrong-ver') + writeJson(join(pkgDir, 'package.json'), { + name: 'wrong-ver', + version: '1.0.0', + intent: { version: 99, repo: 'foo/bar', docs: 'docs/' }, + }) + createDir(pkgDir, 'skills', 'some-skill') + + const result = await scanForIntents(root) + expect(result.packages).toHaveLength(0) + expect(result.warnings).toHaveLength(1) + }) + + it('sorts packages by dependency order (requires)', async () => { + // Create core package (no requires) + const coreDir = createDir(root, 'node_modules', '@tanstack', 'db') + writeJson(join(coreDir, 'package.json'), { + name: '@tanstack/db', + version: '0.5.0', + intent: { version: 1, repo: 'TanStack/db', docs: 'docs/' }, + }) + const coreSkill = createDir(coreDir, 'skills', 'db-core') + writeSkillMd(coreSkill, { name: 'db-core', description: 'Core' }) + + // Create framework package (requires core) + const reactDir = createDir(root, 'node_modules', '@tanstack', 'react-db') + writeJson(join(reactDir, 'package.json'), { + name: '@tanstack/react-db', + version: '0.5.0', + intent: { + version: 1, + repo: 'TanStack/db', + docs: 'docs/', + requires: ['@tanstack/db'], + }, + }) + const reactSkill = createDir(reactDir, 'skills', 'react-db') + writeSkillMd(reactSkill, { + name: 'react-db', + description: 'React bindings', + }) + + const result = await scanForIntents(root) + expect(result.packages).toHaveLength(2) + // Core should come first + expect(result.packages[0]!.name).toBe('@tanstack/db') + expect(result.packages[1]!.name).toBe('@tanstack/react-db') + }) + + it('skips packages without skills/ directory', async () => { + const pkgDir = createDir(root, 'node_modules', 'no-skills') + writeJson(join(pkgDir, 'package.json'), { + name: 'no-skills', + version: '1.0.0', + intent: { version: 1, repo: 'foo/bar', docs: 'docs/' }, + }) + // No skills/ directory + + const result = await scanForIntents(root) + expect(result.packages).toHaveLength(0) + expect(result.warnings).toHaveLength(0) + }) +}) + +describe('package manager detection', () => { + it('detects npm from package-lock.json', async () => { + writeFileSync(join(root, 'package-lock.json'), '{}') + createDir(root, 'node_modules') + const result = await scanForIntents(root) + expect(result.packageManager).toBe('npm') + }) + + it('detects pnpm from pnpm-lock.yaml', async () => { + writeFileSync(join(root, 'pnpm-lock.yaml'), '') + createDir(root, 'node_modules') + const result = await scanForIntents(root) + expect(result.packageManager).toBe('pnpm') + }) + + it('detects yarn from yarn.lock', async () => { + writeFileSync(join(root, 'yarn.lock'), '') + createDir(root, 'node_modules') + const result = await scanForIntents(root) + expect(result.packageManager).toBe('yarn') + }) + + it('detects bun from bun.lockb', async () => { + writeFileSync(join(root, 'bun.lockb'), '') + createDir(root, 'node_modules') + const result = await scanForIntents(root) + expect(result.packageManager).toBe('bun') + }) + + it('returns unknown when no lockfile found', async () => { + createDir(root, 'node_modules') + const result = await scanForIntents(root) + expect(result.packageManager).toBe('unknown') + }) + + it('throws for Yarn PnP', async () => { + writeFileSync(join(root, '.pnp.cjs'), '') + await expect(scanForIntents(root)).rejects.toThrow('Yarn PnP') + }) + + it('throws for Deno without node_modules', async () => { + writeFileSync(join(root, 'deno.json'), '{}') + // No node_modules dir + await expect(scanForIntents(root)).rejects.toThrow( + 'Deno without node_modules', + ) + }) +}) diff --git a/packages/intent/tests/setup.test.ts b/packages/intent/tests/setup.test.ts index 2144ea20..06aee6c6 100644 --- a/packages/intent/tests/setup.test.ts +++ b/packages/intent/tests/setup.test.ts @@ -1,90 +1,90 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { - existsSync, - mkdirSync, - mkdtempSync, - readFileSync, - rmSync, - writeFileSync, -} from 'node:fs' -import { join } from 'node:path' -import { tmpdir } from 'node:os' -import { runSetup } from '../src/setup.js' - -let root: string -let metaDir: string - -beforeEach(() => { - root = mkdtempSync(join(tmpdir(), 'setup-test-')) - metaDir = join(root, 'meta') - - // Create mock templates - mkdirSync(join(metaDir, 'templates', 'workflows'), { recursive: true }) - - writeFileSync( - join(metaDir, 'templates', 'workflows', 'notify-intent.yml'), - 'package: {{PACKAGE_NAME}}\nrepo: {{REPO}}\ndocs: {{DOCS_PATH}}\nsrc: {{SRC_PATH}}', - ) -}) - -afterEach(() => { - rmSync(root, { recursive: true, force: true }) -}) - -describe('runSetup', () => { - it('copies workflow templates with defaults', () => { - const result = runSetup(root, metaDir, []) - expect(result.workflows).toHaveLength(1) - expect(result.skipped).toHaveLength(0) - - const wfPath = join(root, '.github', 'workflows', 'notify-intent.yml') - expect(existsSync(wfPath)).toBe(true) - const content = readFileSync(wfPath, 'utf8') - expect(content).toContain('package: unknown') - }) - - it('substitutes variables from package.json intent field', () => { - writeFileSync( - join(root, 'package.json'), - JSON.stringify({ - name: '@tanstack/query', - intent: { repo: 'TanStack/query', docs: 'docs/' }, - }), - ) - - const result = runSetup(root, metaDir, []) - const wfContent = readFileSync( - join(root, '.github', 'workflows', 'notify-intent.yml'), - 'utf8', - ) - expect(wfContent).toContain('package: @tanstack/query') - expect(wfContent).toContain('repo: TanStack/query') - expect(wfContent).toContain('docs: docs/**') - }) - - it('only copies workflows with --workflows flag', () => { - const result = runSetup(root, metaDir, ['--workflows']) - expect(result.workflows).toHaveLength(1) - }) - - it('copies all with --all flag', () => { - const result = runSetup(root, metaDir, ['--all']) - expect(result.workflows).toHaveLength(1) - }) - - it('skips existing files', () => { - // First run - runSetup(root, metaDir, []) - // Second run - const result = runSetup(root, metaDir, []) - expect(result.workflows).toHaveLength(0) - expect(result.skipped).toHaveLength(2) - }) - - it('handles missing templates directory gracefully', () => { - const emptyMeta = join(root, 'empty-meta') - mkdirSync(emptyMeta) - const result = runSetup(root, emptyMeta, []) - expect(result.workflows).toHaveLength(0) - }) -}) +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { + existsSync, + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + writeFileSync, +} from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { runSetup } from '../src/setup.js' + +let root: string +let metaDir: string + +beforeEach(() => { + root = mkdtempSync(join(tmpdir(), 'setup-test-')) + metaDir = join(root, 'meta') + + // Create mock templates + mkdirSync(join(metaDir, 'templates', 'workflows'), { recursive: true }) + + writeFileSync( + join(metaDir, 'templates', 'workflows', 'notify-intent.yml'), + 'package: {{PACKAGE_NAME}}\nrepo: {{REPO}}\ndocs: {{DOCS_PATH}}\nsrc: {{SRC_PATH}}', + ) +}) + +afterEach(() => { + rmSync(root, { recursive: true, force: true }) +}) + +describe('runSetup', () => { + it('copies workflow templates with defaults', () => { + const result = runSetup(root, metaDir, []) + expect(result.workflows).toHaveLength(1) + expect(result.skipped).toHaveLength(0) + + const wfPath = join(root, '.github', 'workflows', 'notify-intent.yml') + expect(existsSync(wfPath)).toBe(true) + const content = readFileSync(wfPath, 'utf8') + expect(content).toContain('package: unknown') + }) + + it('substitutes variables from package.json intent field', () => { + writeFileSync( + join(root, 'package.json'), + JSON.stringify({ + name: '@tanstack/query', + intent: { repo: 'TanStack/query', docs: 'docs/' }, + }), + ) + + const result = runSetup(root, metaDir, []) + const wfContent = readFileSync( + join(root, '.github', 'workflows', 'notify-intent.yml'), + 'utf8', + ) + expect(wfContent).toContain('package: @tanstack/query') + expect(wfContent).toContain('repo: TanStack/query') + expect(wfContent).toContain('docs: docs/**') + }) + + it('only copies workflows with --workflows flag', () => { + const result = runSetup(root, metaDir, ['--workflows']) + expect(result.workflows).toHaveLength(1) + }) + + it('copies all with --all flag', () => { + const result = runSetup(root, metaDir, ['--all']) + expect(result.workflows).toHaveLength(1) + }) + + it('skips existing files', () => { + // First run + runSetup(root, metaDir, []) + // Second run + const result = runSetup(root, metaDir, []) + expect(result.workflows).toHaveLength(0) + expect(result.skipped).toHaveLength(2) + }) + + it('handles missing templates directory gracefully', () => { + const emptyMeta = join(root, 'empty-meta') + mkdirSync(emptyMeta) + const result = runSetup(root, emptyMeta, []) + expect(result.workflows).toHaveLength(0) + }) +}) diff --git a/packages/intent/tests/skills.test.ts b/packages/intent/tests/skills.test.ts index 66015eb8..e9a279ae 100644 --- a/packages/intent/tests/skills.test.ts +++ b/packages/intent/tests/skills.test.ts @@ -1,130 +1,130 @@ -import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs' -import { join, relative, sep } from 'node:path' -import { describe, expect, it } from 'vitest' -import { parse as parseYaml } from 'yaml' - -// ── Types ── - -interface SkillFrontmatter { - name: string - description: string - type?: string - library?: string - framework?: string - library_version?: string - requires?: Array - sources?: Array -} - -// ── Helpers ── - -const META_DIR = join(__dirname, '..', 'meta') -const MAX_META_SKILL_LINES = 1000 - -function findSkillFiles(dir: string): Array { - const files: Array = [] - if (!existsSync(dir)) return files - - for (const entry of readdirSync(dir)) { - const fullPath = join(dir, entry) - const stat = statSync(fullPath) - if (stat.isDirectory()) { - files.push(...findSkillFiles(fullPath)) - } else if (entry === 'SKILL.md') { - files.push(fullPath) - } - } - return files -} - -function extractFrontmatter( - content: string, -): { frontmatter: SkillFrontmatter; body: string } | null { - const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/) - if (!match) return null - - try { - const frontmatter = parseYaml(match[1]) as SkillFrontmatter - return { frontmatter, body: match[2] } - } catch { - return null - } -} - -function skillPathFromFile(baseDir: string, filePath: string): string { - return relative(baseDir, filePath) - .replace(/[/\\]SKILL\.md$/, '') - .split(sep) - .join('/') -} - -// ── Collect meta-skills ── - -const metaSkillFiles = findSkillFiles(META_DIR) -const metaSkills = metaSkillFiles.map((filePath) => { - const content = readFileSync(filePath, 'utf-8') - const parsed = extractFrontmatter(content) - const relPath = skillPathFromFile(META_DIR, filePath) - return { filePath, content, parsed, relPath } -}) - -// ── Tests ── - -describe('meta-skill discovery', () => { - it('should find meta-skill files', () => { - expect(metaSkillFiles.length).toBeGreaterThan(0) - }) - - it('should include domain-discovery', () => { - expect( - metaSkills.find((s) => s.relPath === 'domain-discovery'), - ).toBeDefined() - }) - - it('should include tree-generator', () => { - expect(metaSkills.find((s) => s.relPath === 'tree-generator')).toBeDefined() - }) - - it('should include generate-skill', () => { - expect(metaSkills.find((s) => s.relPath === 'generate-skill')).toBeDefined() - }) - - it('should include skill-staleness-check', () => { - expect( - metaSkills.find((s) => s.relPath === 'skill-staleness-check'), - ).toBeDefined() - }) -}) - -describe('meta-skill frontmatter', () => { - for (const skill of metaSkills) { - describe(skill.relPath, () => { - it('should have valid frontmatter', () => { - expect(skill.parsed).not.toBeNull() - }) - - if (!skill.parsed) return - - const { frontmatter } = skill.parsed - - it('should have a name', () => { - expect(frontmatter.name).toBeTruthy() - }) - - it('should have a description', () => { - expect(frontmatter.description).toBeTruthy() - }) - }) - } -}) - -describe('meta-skill content', () => { - for (const skill of metaSkills) { - describe(skill.relPath, () => { - it(`should not exceed ${MAX_META_SKILL_LINES} lines`, () => { - const lineCount = skill.content.split(/\r?\n/).length - expect(lineCount).toBeLessThanOrEqual(MAX_META_SKILL_LINES) - }) - }) - } -}) +import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs' +import { join, relative, sep } from 'node:path' +import { describe, expect, it } from 'vitest' +import { parse as parseYaml } from 'yaml' + +// ── Types ── + +interface SkillFrontmatter { + name: string + description: string + type?: string + library?: string + framework?: string + library_version?: string + requires?: Array + sources?: Array +} + +// ── Helpers ── + +const META_DIR = join(__dirname, '..', 'meta') +const MAX_META_SKILL_LINES = 1000 + +function findSkillFiles(dir: string): Array { + const files: Array = [] + if (!existsSync(dir)) return files + + for (const entry of readdirSync(dir)) { + const fullPath = join(dir, entry) + const stat = statSync(fullPath) + if (stat.isDirectory()) { + files.push(...findSkillFiles(fullPath)) + } else if (entry === 'SKILL.md') { + files.push(fullPath) + } + } + return files +} + +function extractFrontmatter( + content: string, +): { frontmatter: SkillFrontmatter; body: string } | null { + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/) + if (!match) return null + + try { + const frontmatter = parseYaml(match[1]) as SkillFrontmatter + return { frontmatter, body: match[2] } + } catch { + return null + } +} + +function skillPathFromFile(baseDir: string, filePath: string): string { + return relative(baseDir, filePath) + .replace(/[/\\]SKILL\.md$/, '') + .split(sep) + .join('/') +} + +// ── Collect meta-skills ── + +const metaSkillFiles = findSkillFiles(META_DIR) +const metaSkills = metaSkillFiles.map((filePath) => { + const content = readFileSync(filePath, 'utf-8') + const parsed = extractFrontmatter(content) + const relPath = skillPathFromFile(META_DIR, filePath) + return { filePath, content, parsed, relPath } +}) + +// ── Tests ── + +describe('meta-skill discovery', () => { + it('should find meta-skill files', () => { + expect(metaSkillFiles.length).toBeGreaterThan(0) + }) + + it('should include domain-discovery', () => { + expect( + metaSkills.find((s) => s.relPath === 'domain-discovery'), + ).toBeDefined() + }) + + it('should include tree-generator', () => { + expect(metaSkills.find((s) => s.relPath === 'tree-generator')).toBeDefined() + }) + + it('should include generate-skill', () => { + expect(metaSkills.find((s) => s.relPath === 'generate-skill')).toBeDefined() + }) + + it('should include skill-staleness-check', () => { + expect( + metaSkills.find((s) => s.relPath === 'skill-staleness-check'), + ).toBeDefined() + }) +}) + +describe('meta-skill frontmatter', () => { + for (const skill of metaSkills) { + describe(skill.relPath, () => { + it('should have valid frontmatter', () => { + expect(skill.parsed).not.toBeNull() + }) + + if (!skill.parsed) return + + const { frontmatter } = skill.parsed + + it('should have a name', () => { + expect(frontmatter.name).toBeTruthy() + }) + + it('should have a description', () => { + expect(frontmatter.description).toBeTruthy() + }) + }) + } +}) + +describe('meta-skill content', () => { + for (const skill of metaSkills) { + describe(skill.relPath, () => { + it(`should not exceed ${MAX_META_SKILL_LINES} lines`, () => { + const lineCount = skill.content.split(/\r?\n/).length + expect(lineCount).toBeLessThanOrEqual(MAX_META_SKILL_LINES) + }) + }) + } +}) diff --git a/packages/intent/tests/staleness.test.ts b/packages/intent/tests/staleness.test.ts index 32d37488..646c293d 100644 --- a/packages/intent/tests/staleness.test.ts +++ b/packages/intent/tests/staleness.test.ts @@ -1,286 +1,286 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs' -import { join } from 'node:path' -import { tmpdir } from 'node:os' -import { checkStaleness } from '../src/staleness.js' - -// --------------------------------------------------------------------------- -// Fixture helpers -// --------------------------------------------------------------------------- - -let tmpDir: string - -function setupDir(): string { - const dir = join( - tmpdir(), - `intent-stale-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, - ) - mkdirSync(dir, { recursive: true }) - return dir -} - -function writeSkill( - dir: string, - name: string, - fm: Record, - body = '# Skill\n', -): void { - const skillDir = join(dir, 'skills', ...name.split('/')) - mkdirSync(skillDir, { recursive: true }) - - const fmStr = Object.entries(fm) - .map(([k, v]) => { - if (Array.isArray(v)) { - return `${k}:\n${v.map((i) => ` - ${i}`).join('\n')}` - } - return `${k}: ${v}` - }) - .join('\n') - - writeFileSync(join(skillDir, 'SKILL.md'), `---\n${fmStr}\n---\n${body}`) -} - -function writeSyncState(dir: string, state: Record): void { - const skillsDir = join(dir, 'skills') - mkdirSync(skillsDir, { recursive: true }) - writeFileSync(join(skillsDir, 'sync-state.json'), JSON.stringify(state)) -} - -// --------------------------------------------------------------------------- -// Mock fetch for npm registry -// --------------------------------------------------------------------------- - -const originalFetch = globalThis.fetch - -beforeEach(() => { - tmpDir = setupDir() -}) - -afterEach(() => { - globalThis.fetch = originalFetch - if (existsSync(tmpDir)) { - rmSync(tmpDir, { recursive: true, force: true }) - } -}) - -// --------------------------------------------------------------------------- -// Tests -// --------------------------------------------------------------------------- - -describe('checkStaleness', () => { - it('returns empty skills when no skills directory exists', async () => { - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.library).toBe('@example/lib') - expect(report.skills).toHaveLength(0) - expect(report.currentVersion).toBeNull() - expect(report.skillVersion).toBeNull() - expect(report.versionDrift).toBeNull() - }) - - it('defaults library to "unknown" when no name provided', async () => { - const report = await checkStaleness(tmpDir) - expect(report.library).toBe('unknown') - }) - - it('detects skills from SKILL.md files', async () => { - writeSkill(tmpDir, 'basics', { - name: 'basics', - description: 'Core concepts', - }) - writeSkill(tmpDir, 'advanced', { - name: 'advanced', - description: 'Advanced usage', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skills).toHaveLength(2) - expect(report.skills.map((s) => s.name).sort()).toEqual([ - 'advanced', - 'basics', - ]) - }) - - it('detects major version drift', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - library_version: '1.2.3', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ version: '2.0.0' }), - } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skillVersion).toBe('1.2.3') - expect(report.currentVersion).toBe('2.0.0') - expect(report.versionDrift).toBe('major') - expect(report.skills[0].needsReview).toBe(true) - expect(report.skills[0].reasons[0]).toContain('version drift') - }) - - it('detects minor version drift', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - library_version: '1.2.3', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ version: '1.4.0' }), - } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.versionDrift).toBe('minor') - }) - - it('detects patch version drift', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - library_version: '1.2.3', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ version: '1.2.5' }), - } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.versionDrift).toBe('patch') - }) - - it('reports no drift when versions match', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - library_version: '1.2.3', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ version: '1.2.3' }), - } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.versionDrift).toBeNull() - expect(report.skills[0].needsReview).toBe(false) - }) - - it('handles npm fetch failure gracefully', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - library_version: '1.0.0', - }) - - globalThis.fetch = vi.fn().mockRejectedValue(new Error('Network error')) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.currentVersion).toBeNull() - expect(report.versionDrift).toBeNull() - }) - - it('flags new sources not present in sync-state', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - sources: ['docs/api.md', 'docs/guide.md'], - }) - - writeSyncState(tmpDir, { - skills: { - core: { - sources_sha: { - 'docs/api.md': 'abc123', - // docs/guide.md intentionally missing - }, - }, - }, - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skills[0].needsReview).toBe(true) - expect(report.skills[0].reasons).toEqual( - expect.arrayContaining([expect.stringContaining('new source')]), - ) - }) - - it('does not flag sources when no sync-state exists', async () => { - writeSkill(tmpDir, 'core', { - name: 'core', - description: 'Core', - sources: ['docs/api.md'], - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skills[0].needsReview).toBe(false) - }) - - it('handles nested skill directories', async () => { - writeSkill(tmpDir, 'react/hooks', { - name: 'react/hooks', - description: 'React hooks', - library_version: '1.0.0', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ version: '2.0.0' }), - } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skills).toHaveLength(1) - expect(report.skills[0].name).toBe('react/hooks') - expect(report.skills[0].needsReview).toBe(true) - }) - - it('uses directory name when frontmatter has no name', async () => { - writeSkill(tmpDir, 'my-skill', { - description: 'A skill with no name field', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skills[0].name).toBe('my-skill') - }) - - it('uses skillVersion from first skill that has library_version', async () => { - writeSkill(tmpDir, 'a', { name: 'a', description: 'No version' }) - writeSkill(tmpDir, 'b', { - name: 'b', - description: 'Has version', - library_version: '3.5.0', - }) - - globalThis.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => ({ version: '4.0.0' }), - } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skillVersion).toBe('3.5.0') - expect(report.versionDrift).toBe('major') - }) - - it('handles malformed SKILL.md without crashing', async () => { - const skillDir = join(tmpDir, 'skills', 'broken') - mkdirSync(skillDir, { recursive: true }) - writeFileSync(join(skillDir, 'SKILL.md'), 'no frontmatter here') - - globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) - - const report = await checkStaleness(tmpDir, '@example/lib') - expect(report.skills).toHaveLength(1) - expect(report.skills[0].needsReview).toBe(false) - }) -}) +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { checkStaleness } from '../src/staleness.js' + +// --------------------------------------------------------------------------- +// Fixture helpers +// --------------------------------------------------------------------------- + +let tmpDir: string + +function setupDir(): string { + const dir = join( + tmpdir(), + `intent-stale-test-${Date.now()}-${Math.random().toString(36).slice(2)}`, + ) + mkdirSync(dir, { recursive: true }) + return dir +} + +function writeSkill( + dir: string, + name: string, + fm: Record, + body = '# Skill\n', +): void { + const skillDir = join(dir, 'skills', ...name.split('/')) + mkdirSync(skillDir, { recursive: true }) + + const fmStr = Object.entries(fm) + .map(([k, v]) => { + if (Array.isArray(v)) { + return `${k}:\n${v.map((i) => ` - ${i}`).join('\n')}` + } + return `${k}: ${v}` + }) + .join('\n') + + writeFileSync(join(skillDir, 'SKILL.md'), `---\n${fmStr}\n---\n${body}`) +} + +function writeSyncState(dir: string, state: Record): void { + const skillsDir = join(dir, 'skills') + mkdirSync(skillsDir, { recursive: true }) + writeFileSync(join(skillsDir, 'sync-state.json'), JSON.stringify(state)) +} + +// --------------------------------------------------------------------------- +// Mock fetch for npm registry +// --------------------------------------------------------------------------- + +const originalFetch = globalThis.fetch + +beforeEach(() => { + tmpDir = setupDir() +}) + +afterEach(() => { + globalThis.fetch = originalFetch + if (existsSync(tmpDir)) { + rmSync(tmpDir, { recursive: true, force: true }) + } +}) + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +describe('checkStaleness', () => { + it('returns empty skills when no skills directory exists', async () => { + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.library).toBe('@example/lib') + expect(report.skills).toHaveLength(0) + expect(report.currentVersion).toBeNull() + expect(report.skillVersion).toBeNull() + expect(report.versionDrift).toBeNull() + }) + + it('defaults library to "unknown" when no name provided', async () => { + const report = await checkStaleness(tmpDir) + expect(report.library).toBe('unknown') + }) + + it('detects skills from SKILL.md files', async () => { + writeSkill(tmpDir, 'basics', { + name: 'basics', + description: 'Core concepts', + }) + writeSkill(tmpDir, 'advanced', { + name: 'advanced', + description: 'Advanced usage', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skills).toHaveLength(2) + expect(report.skills.map((s) => s.name).sort()).toEqual([ + 'advanced', + 'basics', + ]) + }) + + it('detects major version drift', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + library_version: '1.2.3', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ version: '2.0.0' }), + } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skillVersion).toBe('1.2.3') + expect(report.currentVersion).toBe('2.0.0') + expect(report.versionDrift).toBe('major') + expect(report.skills[0].needsReview).toBe(true) + expect(report.skills[0].reasons[0]).toContain('version drift') + }) + + it('detects minor version drift', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + library_version: '1.2.3', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ version: '1.4.0' }), + } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.versionDrift).toBe('minor') + }) + + it('detects patch version drift', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + library_version: '1.2.3', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ version: '1.2.5' }), + } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.versionDrift).toBe('patch') + }) + + it('reports no drift when versions match', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + library_version: '1.2.3', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ version: '1.2.3' }), + } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.versionDrift).toBeNull() + expect(report.skills[0].needsReview).toBe(false) + }) + + it('handles npm fetch failure gracefully', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + library_version: '1.0.0', + }) + + globalThis.fetch = vi.fn().mockRejectedValue(new Error('Network error')) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.currentVersion).toBeNull() + expect(report.versionDrift).toBeNull() + }) + + it('flags new sources not present in sync-state', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + sources: ['docs/api.md', 'docs/guide.md'], + }) + + writeSyncState(tmpDir, { + skills: { + core: { + sources_sha: { + 'docs/api.md': 'abc123', + // docs/guide.md intentionally missing + }, + }, + }, + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skills[0].needsReview).toBe(true) + expect(report.skills[0].reasons).toEqual( + expect.arrayContaining([expect.stringContaining('new source')]), + ) + }) + + it('does not flag sources when no sync-state exists', async () => { + writeSkill(tmpDir, 'core', { + name: 'core', + description: 'Core', + sources: ['docs/api.md'], + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skills[0].needsReview).toBe(false) + }) + + it('handles nested skill directories', async () => { + writeSkill(tmpDir, 'react/hooks', { + name: 'react/hooks', + description: 'React hooks', + library_version: '1.0.0', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ version: '2.0.0' }), + } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skills).toHaveLength(1) + expect(report.skills[0].name).toBe('react/hooks') + expect(report.skills[0].needsReview).toBe(true) + }) + + it('uses directory name when frontmatter has no name', async () => { + writeSkill(tmpDir, 'my-skill', { + description: 'A skill with no name field', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skills[0].name).toBe('my-skill') + }) + + it('uses skillVersion from first skill that has library_version', async () => { + writeSkill(tmpDir, 'a', { name: 'a', description: 'No version' }) + writeSkill(tmpDir, 'b', { + name: 'b', + description: 'Has version', + library_version: '3.5.0', + }) + + globalThis.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ version: '4.0.0' }), + } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skillVersion).toBe('3.5.0') + expect(report.versionDrift).toBe('major') + }) + + it('handles malformed SKILL.md without crashing', async () => { + const skillDir = join(tmpDir, 'skills', 'broken') + mkdirSync(skillDir, { recursive: true }) + writeFileSync(join(skillDir, 'SKILL.md'), 'no frontmatter here') + + globalThis.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) + + const report = await checkStaleness(tmpDir, '@example/lib') + expect(report.skills).toHaveLength(1) + expect(report.skills[0].needsReview).toBe(false) + }) +}) diff --git a/packages/intent/tsconfig.json b/packages/intent/tsconfig.json index 7ed40a9d..2696e251 100644 --- a/packages/intent/tsconfig.json +++ b/packages/intent/tsconfig.json @@ -1,9 +1,9 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "noEmit": false, - "declaration": true - }, - "include": ["src"] -} +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "noEmit": false, + "declaration": true + }, + "include": ["src"] +} diff --git a/packages/intent/vitest.config.ts b/packages/intent/vitest.config.ts index d38b74e7..052d46bc 100644 --- a/packages/intent/vitest.config.ts +++ b/packages/intent/vitest.config.ts @@ -1,8 +1,8 @@ -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - name: 'intent', - include: ['tests/**/*.test.ts'], - }, -}) +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + name: 'intent', + include: ['tests/**/*.test.ts'], + }, +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5aa7ba8c..50fdd4d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5381 +1,5381 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@tanstack/typedoc-config': - specifier: ^0.3.3 - version: 0.3.3(typescript@5.9.3) - devDependencies: - '@changesets/cli': - specifier: ^2.29.8 - version: 2.29.8(@types/node@25.0.9) - '@faker-js/faker': - specifier: ^10.2.0 - version: 10.2.0 - '@svitejs/changesets-changelog-github-compact': - specifier: ^1.2.0 - version: 1.2.0 - '@tanstack/eslint-config': - specifier: 0.3.4 - version: 0.3.4(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@types/node': - specifier: ^25.0.7 - version: 25.0.9 - eslint: - specifier: ^9.39.2 - version: 9.39.2(jiti@2.6.1) - eslint-plugin-unused-imports: - specifier: ^4.3.0 - version: 4.3.0(@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) - happy-dom: - specifier: ^20.1.0 - version: 20.3.1 - knip: - specifier: ^5.80.2 - version: 5.81.0(@types/node@25.0.9)(typescript@5.9.3) - markdown-link-extractor: - specifier: ^4.0.3 - version: 4.0.3 - nx: - specifier: ^22.3.3 - version: 22.3.3 - prettier: - specifier: ^3.7.4 - version: 3.8.0 - prettier-plugin-svelte: - specifier: ^3.4.1 - version: 3.4.1(prettier@3.8.0)(svelte@5.46.4) - sherif: - specifier: ^1.9.0 - version: 1.10.0 - tinyglobby: - specifier: ^0.2.15 - version: 0.2.15 - typescript: - specifier: 5.9.3 - version: 5.9.3 - vitest: - specifier: ^4.0.17 - version: 4.0.17(@types/node@25.0.9)(happy-dom@20.3.1)(jiti@2.6.1)(yaml@2.8.2) - yaml: - specifier: ^2.7.0 - version: 2.8.2 - - packages/intent: - dependencies: - yaml: - specifier: ^2.7.0 - version: 2.8.2 - devDependencies: - tsdown: - specifier: ^0.19.0 - version: 0.19.0(oxc-resolver@11.16.3)(typescript@5.9.3) - -packages: - - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/runtime@7.28.6': - resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - - '@changesets/apply-release-plan@7.0.14': - resolution: {integrity: sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==} - - '@changesets/assemble-release-plan@6.0.9': - resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} - - '@changesets/changelog-git@0.2.1': - resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - - '@changesets/cli@2.29.8': - resolution: {integrity: sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==} - hasBin: true - - '@changesets/config@3.1.2': - resolution: {integrity: sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==} - - '@changesets/errors@0.2.0': - resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - - '@changesets/get-dependents-graph@2.1.3': - resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} - - '@changesets/get-github-info@0.6.0': - resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - - '@changesets/get-release-plan@4.0.14': - resolution: {integrity: sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==} - - '@changesets/get-version-range-type@0.4.0': - resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - - '@changesets/git@3.0.4': - resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} - - '@changesets/logger@0.1.1': - resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} - - '@changesets/parse@0.4.2': - resolution: {integrity: sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==} - - '@changesets/pre@2.0.2': - resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} - - '@changesets/read@0.6.6': - resolution: {integrity: sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==} - - '@changesets/should-skip-package@0.1.2': - resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} - - '@changesets/types@4.1.0': - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - - '@changesets/types@6.1.0': - resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} - - '@changesets/write@0.4.0': - resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - - '@emnapi/core@1.8.1': - resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} - - '@emnapi/runtime@1.8.1': - resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} - - '@emnapi/wasi-threads@1.1.0': - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@faker-js/faker@10.2.0': - resolution: {integrity: sha512-rTXwAsIxpCqzUnZvrxVh3L0QA0NzToqWBLAhV+zDV3MIIwiQhAZHMdPCIaj5n/yADu/tyk12wIPgL6YHGXJP+g==} - engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} - - '@gerrit0/mini-shiki@3.23.0': - resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} - - '@inquirer/external-editor@1.0.3': - resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} - - '@jest/diff-sequences@30.0.1': - resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/get-type@30.1.0': - resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/schemas@30.0.5': - resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@manypkg/find-root@1.1.0': - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} - - '@manypkg/get-packages@1.1.3': - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - - '@napi-rs/wasm-runtime@0.2.12': - resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - - '@napi-rs/wasm-runtime@0.2.4': - resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} - - '@napi-rs/wasm-runtime@1.1.1': - resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@nx/nx-darwin-arm64@22.3.3': - resolution: {integrity: sha512-zBAGFGLal09CxhQkdMpOVwcwa9Y01aFm88jTTn35s/DdIWsfngmPzz0t4mG7u2D05q7TJfGQ31pIf5GkNUjo6g==} - cpu: [arm64] - os: [darwin] - - '@nx/nx-darwin-x64@22.3.3': - resolution: {integrity: sha512-6ZQ6rMqH8NY4Jz+Gc89D5bIH2NxZb5S/vaA4yJ9RrqAfl4QWchNFD5na+aRivSd+UdsYLPKKl6qohet5SE6vOg==} - cpu: [x64] - os: [darwin] - - '@nx/nx-freebsd-x64@22.3.3': - resolution: {integrity: sha512-J/PP5pIOQtR7ZzrFwP6d6h0yfY7r9EravG2m940GsgzGbtZGYIDqnh5Wdt+4uBWPH8VpdNOwFqH0afELtJA3MA==} - cpu: [x64] - os: [freebsd] - - '@nx/nx-linux-arm-gnueabihf@22.3.3': - resolution: {integrity: sha512-/zn0altzM15S7qAgXMaB41vHkEn18HyTVUvRrjmmwaVqk9WfmDmqOQlGWoJ6XCbpvKQ8bh14RyhR9LGw1JJkNA==} - cpu: [arm] - os: [linux] - - '@nx/nx-linux-arm64-gnu@22.3.3': - resolution: {integrity: sha512-NmPeCexWIZHW9RM3lDdFENN9C3WtlQ5L4RSNFESIjreS921rgePhulsszYdGnHdcnKPYlBBJnX/NxVsfioBbnQ==} - cpu: [arm64] - os: [linux] - - '@nx/nx-linux-arm64-musl@22.3.3': - resolution: {integrity: sha512-K02U88Q0dpvCfmSXXvY7KbYQSa1m+mkYeqDBRHp11yHk1GoIqaHp8oEWda7FV4gsriNExPSS5tX1/QGVoLZrCw==} - cpu: [arm64] - os: [linux] - - '@nx/nx-linux-x64-gnu@22.3.3': - resolution: {integrity: sha512-04TEbvgwRaB9ifr39YwJmWh3RuXb4Ry4m84SOJyjNXAfPrepcWgfIQn1VL2ul1Ybq+P023dLO9ME8uqFh6j1YQ==} - cpu: [x64] - os: [linux] - - '@nx/nx-linux-x64-musl@22.3.3': - resolution: {integrity: sha512-uxBXx5q+S5OGatbYDxnamsKXRKlYn+Eq1nrCAHaf8rIfRoHlDiRV2PqtWuF+O2pxR5FWKpvr+/sZtt9rAf7KMw==} - cpu: [x64] - os: [linux] - - '@nx/nx-win32-arm64-msvc@22.3.3': - resolution: {integrity: sha512-aOwlfD6ZA1K6hjZtbhBSp7s1yi3sHbMpLCa4stXzfhCCpKUv46HU/EdiWdE1N8AsyNFemPZFq81k1VTowcACdg==} - cpu: [arm64] - os: [win32] - - '@nx/nx-win32-x64-msvc@22.3.3': - resolution: {integrity: sha512-EDR8BtqeDvVNQ+kPwnfeSfmerYetitU3tDkxOMIybjKJDh69U2JwTB8n9ARwNaZQbNk7sCGNRUSZFTbAAUKvuQ==} - cpu: [x64] - os: [win32] - - '@oxc-project/types@0.107.0': - resolution: {integrity: sha512-QFDRbYfV2LVx8tyqtyiah3jQPUj1mK2+RYwxyFWyGoys6XJnwTdlzO6rdNNHOPorHAu5Uo34oWRKcvNpbJarmQ==} - - '@oxc-project/types@0.112.0': - resolution: {integrity: sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==} - - '@oxc-resolver/binding-android-arm-eabi@11.16.3': - resolution: {integrity: sha512-CVyWHu6ACDqDcJxR4nmGiG8vDF4TISJHqRNzac5z/gPQycs/QrP/1pDsJBy0MD7jSw8nVq2E5WqeHQKabBG/Jg==} - cpu: [arm] - os: [android] - - '@oxc-resolver/binding-android-arm64@11.16.3': - resolution: {integrity: sha512-tTIoB7plLeh2o6Ay7NnV5CJb6QUXdxI7Shnsp2ECrLSV81k+oVE3WXYrQSh4ltWL75i0OgU5Bj3bsuyg5SMepw==} - cpu: [arm64] - os: [android] - - '@oxc-resolver/binding-darwin-arm64@11.16.3': - resolution: {integrity: sha512-OXKVH7uwYd3Rbw1s2yJZd6/w+6b01iaokZubYhDAq4tOYArr+YCS+lr81q1hsTPPRZeIsWE+rJLulmf1qHdYZA==} - cpu: [arm64] - os: [darwin] - - '@oxc-resolver/binding-darwin-x64@11.16.3': - resolution: {integrity: sha512-WwjQ4WdnCxVYZYd3e3oY5XbV3JeLy9pPMK+eQQ2m8DtqUtbxnvPpAYC2Knv/2bS6q5JiktqOVJ2Hfia3OSo0/A==} - cpu: [x64] - os: [darwin] - - '@oxc-resolver/binding-freebsd-x64@11.16.3': - resolution: {integrity: sha512-4OHKFGJBBfOnuJnelbCS4eBorI6cj54FUxcZJwEXPeoLc8yzORBoJ2w+fQbwjlQcUUZLEg92uGhKCRiUoqznjg==} - cpu: [x64] - os: [freebsd] - - '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': - resolution: {integrity: sha512-OM3W0NLt9u7uKwG/yZbeXABansZC0oZeDF1nKgvcZoRw4/Yak6/l4S0onBfDFeYMY94eYeAt2bl60e30lgsb5A==} - cpu: [arm] - os: [linux] - - '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': - resolution: {integrity: sha512-MRs7D7i1t7ACsAdTuP81gLZES918EpBmiUyEl8fu302yQB+4L7L7z0Ui8BWnthUTQd3nAU9dXvENLK/SqRVH8A==} - cpu: [arm] - os: [linux] - - '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': - resolution: {integrity: sha512-0eVYZxSceNqGADzhlV4ZRqkHF0fjWxRXQOB7Qwl5y1gN/XYUDvMfip+ngtzj4dM7zQT4U97hUhJ7PUKSy/JIGQ==} - cpu: [arm64] - os: [linux] - - '@oxc-resolver/binding-linux-arm64-musl@11.16.3': - resolution: {integrity: sha512-B1BvLeZbgDdVN0FvU40l5Q7lej8310WlabCBaouk8jY7H7xbI8phtomTtk3Efmevgfy5hImaQJu6++OmcFb2NQ==} - cpu: [arm64] - os: [linux] - - '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': - resolution: {integrity: sha512-q7khglic3Jqak7uDgA3MFnjDeI7krQT595GDZpvFq785fmFYSx8rlTkoHzmhQtUisYtl4XG7WUscwsoidFUI4w==} - cpu: [ppc64] - os: [linux] - - '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': - resolution: {integrity: sha512-aFRNmQNPzDgQEbw2s3c8yJYRimacSDI+u9df8rn5nSKzTVitHmbEpZqfxpwNLCKIuLSNmozHR1z1OT+oZVeYqg==} - cpu: [riscv64] - os: [linux] - - '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': - resolution: {integrity: sha512-vZI85SvSMADcEL9G1TIrV0Rlkc1fY5Mup0DdlVC5EHPysZB4hXXHpr+h09pjlK5y+5om5foIzDRxE1baUCaWOA==} - cpu: [riscv64] - os: [linux] - - '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': - resolution: {integrity: sha512-xiLBnaUlddFEzRHiHiSGEMbkg8EwZY6VD8F+3GfnFsiK3xg/4boaUV2bwXd+nUzl3UDQOMW1QcZJ4jJSb0qiJA==} - cpu: [s390x] - os: [linux] - - '@oxc-resolver/binding-linux-x64-gnu@11.16.3': - resolution: {integrity: sha512-6y0b05wIazJJgwu7yU/AYGFswzQQudYJBOb/otDhiDacp1+6ye8egoxx63iVo9lSpDbipL++54AJQFlcOHCB+g==} - cpu: [x64] - os: [linux] - - '@oxc-resolver/binding-linux-x64-musl@11.16.3': - resolution: {integrity: sha512-RmMgwuMa42c9logS7Pjprf5KCp8J1a1bFiuBFtG9/+yMu0BhY2t+0VR/um7pwtkNFvIQqAVh6gDOg/PnoKRcdQ==} - cpu: [x64] - os: [linux] - - '@oxc-resolver/binding-openharmony-arm64@11.16.3': - resolution: {integrity: sha512-/7AYRkjjW7xu1nrHgWUFy99Duj4/ydOBVaHtODie9/M6fFngo+8uQDFFnzmr4q//sd/cchIerISp/8CQ5TsqIA==} - cpu: [arm64] - os: [openharmony] - - '@oxc-resolver/binding-wasm32-wasi@11.16.3': - resolution: {integrity: sha512-urM6aIPbi5di4BSlnpd/TWtDJgG6RD06HvLBuNM+qOYuFtY1/xPbzQ2LanBI2ycpqIoIZwsChyplALwAMdyfCQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': - resolution: {integrity: sha512-QuvLqGKf7frxWHQ5TnrcY0C/hJpANsaez99Q4dAk1hen7lDTD4FBPtBzPnntLFXeaVG3PnSmnVjlv0vMILwU7Q==} - cpu: [arm64] - os: [win32] - - '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': - resolution: {integrity: sha512-QR/witXK6BmYTlEP8CCjC5fxeG5U9A6a50pNpC1nLnhAcJjtzFG8KcQ5etVy/XvCLiDc7fReaAWRNWtCaIhM8Q==} - cpu: [ia32] - os: [win32] - - '@oxc-resolver/binding-win32-x64-msvc@11.16.3': - resolution: {integrity: sha512-bFuJRKOscsDAEZ/a8BezcTMAe2BQ/OBRfuMLFUuINfTR5qGVcm4a3xBIrQVepBaPxFj16SJdRjGe05vDiwZmFw==} - cpu: [x64] - os: [win32] - - '@quansync/fs@1.0.0': - resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - - '@rolldown/binding-android-arm64@1.0.0-beta.59': - resolution: {integrity: sha512-6yLLgyswYwiCfls9+hoNFY9F8TQdwo15hpXDHzlAR0X/GojeKF+AuNcXjYNbOJ4zjl/5D6lliE8CbpB5t1OWIQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - - '@rolldown/binding-android-arm64@1.0.0-rc.3': - resolution: {integrity: sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - - '@rolldown/binding-darwin-arm64@1.0.0-beta.59': - resolution: {integrity: sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - - '@rolldown/binding-darwin-arm64@1.0.0-rc.3': - resolution: {integrity: sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - - '@rolldown/binding-darwin-x64@1.0.0-beta.59': - resolution: {integrity: sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - - '@rolldown/binding-darwin-x64@1.0.0-rc.3': - resolution: {integrity: sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - - '@rolldown/binding-freebsd-x64@1.0.0-beta.59': - resolution: {integrity: sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - - '@rolldown/binding-freebsd-x64@1.0.0-rc.3': - resolution: {integrity: sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': - resolution: {integrity: sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': - resolution: {integrity: sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': - resolution: {integrity: sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': - resolution: {integrity: sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': - resolution: {integrity: sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': - resolution: {integrity: sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': - resolution: {integrity: sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': - resolution: {integrity: sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - - '@rolldown/binding-linux-x64-musl@1.0.0-beta.59': - resolution: {integrity: sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - - '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': - resolution: {integrity: sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - - '@rolldown/binding-openharmony-arm64@1.0.0-beta.59': - resolution: {integrity: sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - - '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': - resolution: {integrity: sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - - '@rolldown/binding-wasm32-wasi@1.0.0-beta.59': - resolution: {integrity: sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': - resolution: {integrity: sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59': - resolution: {integrity: sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': - resolution: {integrity: sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': - resolution: {integrity: sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': - resolution: {integrity: sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - - '@rolldown/pluginutils@1.0.0-beta.59': - resolution: {integrity: sha512-aoh6LAJRyhtazs98ydgpNOYstxUlsOV1KJXcpf/0c0vFcUA8uyd/hwKRhqE/AAPNqAho9RliGsvitCoOzREoVA==} - - '@rolldown/pluginutils@1.0.0-rc.3': - resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} - - '@rollup/rollup-android-arm-eabi@4.55.1': - resolution: {integrity: sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.55.1': - resolution: {integrity: sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.55.1': - resolution: {integrity: sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.55.1': - resolution: {integrity: sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.55.1': - resolution: {integrity: sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.55.1': - resolution: {integrity: sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.55.1': - resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.55.1': - resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.55.1': - resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.55.1': - resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-loong64-gnu@4.55.1': - resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==} - cpu: [loong64] - os: [linux] - - '@rollup/rollup-linux-loong64-musl@4.55.1': - resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==} - cpu: [loong64] - os: [linux] - - '@rollup/rollup-linux-ppc64-gnu@4.55.1': - resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-ppc64-musl@4.55.1': - resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.55.1': - resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-riscv64-musl@4.55.1': - resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.55.1': - resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.55.1': - resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.55.1': - resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-openbsd-x64@4.55.1': - resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.55.1': - resolution: {integrity: sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.55.1': - resolution: {integrity: sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.55.1': - resolution: {integrity: sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.55.1': - resolution: {integrity: sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.55.1': - resolution: {integrity: sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==} - cpu: [x64] - os: [win32] - - '@shikijs/engine-oniguruma@3.23.0': - resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} - - '@shikijs/langs@3.23.0': - resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} - - '@shikijs/themes@3.23.0': - resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} - - '@shikijs/types@3.23.0': - resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} - - '@shikijs/vscode-textmate@10.0.2': - resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - - '@sinclair/typebox@0.34.47': - resolution: {integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@stylistic/eslint-plugin@5.7.0': - resolution: {integrity: sha512-PsSugIf9ip1H/mWKj4bi/BlEoerxXAda9ByRFsYuwsmr6af9NxJL0AaiNXs8Le7R21QR5KMiD/KdxZZ71LjAxQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: '>=9.0.0' - - '@sveltejs/acorn-typescript@1.0.8': - resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==} - peerDependencies: - acorn: ^8.9.0 - - '@svitejs/changesets-changelog-github-compact@1.2.0': - resolution: {integrity: sha512-08eKiDAjj4zLug1taXSIJ0kGL5cawjVCyJkBb6EWSg5fEPX6L+Wtr0CH2If4j5KYylz85iaZiFlUItvgJvll5g==} - engines: {node: ^14.13.1 || ^16.0.0 || >=18} - - '@tanstack/eslint-config@0.3.4': - resolution: {integrity: sha512-5Ou1XWJRCTx5G8WoCbT7+6nQ4iNdsISzBAc4lXpFy2fEOO7xioOSPvcPIv+r9V0drPPETou2tr6oLGZZ909FKg==} - engines: {node: '>=18'} - peerDependencies: - eslint: ^8.0.0 || ^9.0.0 - - '@tanstack/typedoc-config@0.3.3': - resolution: {integrity: sha512-wVT2YfKDSpd+4f7fk6UaPIP3a2J7LSovlyVuFF1PH2yQb7gjqehod5zdFiwFyEXgvI9XGuFvvs1OehkKNYcr6A==} - engines: {node: '>=18'} - - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - - '@tybys/wasm-util@0.9.0': - resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} - - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/hast@3.0.4': - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/node@12.20.55': - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - - '@types/node@20.19.30': - resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==} - - '@types/node@25.0.9': - resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==} - - '@types/unist@3.0.3': - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - - '@types/whatwg-mimetype@3.0.2': - resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} - - '@types/ws@8.18.1': - resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - - '@typescript-eslint/eslint-plugin@8.53.0': - resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.53.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/parser@8.53.0': - resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/project-service@8.53.0': - resolution: {integrity: sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/scope-manager@8.53.0': - resolution: {integrity: sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.53.0': - resolution: {integrity: sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/type-utils@8.53.0': - resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/types@8.53.0': - resolution: {integrity: sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.53.0': - resolution: {integrity: sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/utils@8.53.0': - resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/visitor-keys@8.53.0': - resolution: {integrity: sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} - cpu: [arm] - os: [android] - - '@unrs/resolver-binding-android-arm64@1.11.1': - resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} - cpu: [arm64] - os: [android] - - '@unrs/resolver-binding-darwin-arm64@1.11.1': - resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} - cpu: [arm64] - os: [darwin] - - '@unrs/resolver-binding-darwin-x64@1.11.1': - resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} - cpu: [x64] - os: [darwin] - - '@unrs/resolver-binding-freebsd-x64@1.11.1': - resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} - cpu: [x64] - os: [freebsd] - - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} - cpu: [arm] - os: [linux] - - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} - cpu: [arm] - os: [linux] - - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} - cpu: [arm64] - os: [linux] - - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} - cpu: [arm64] - os: [linux] - - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} - cpu: [ppc64] - os: [linux] - - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} - cpu: [riscv64] - os: [linux] - - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} - cpu: [riscv64] - os: [linux] - - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} - cpu: [s390x] - os: [linux] - - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} - cpu: [x64] - os: [linux] - - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} - cpu: [x64] - os: [linux] - - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} - cpu: [arm64] - os: [win32] - - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} - cpu: [ia32] - os: [win32] - - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} - cpu: [x64] - os: [win32] - - '@vitest/expect@4.0.17': - resolution: {integrity: sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==} - - '@vitest/mocker@4.0.17': - resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==} - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@4.0.17': - resolution: {integrity: sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==} - - '@vitest/runner@4.0.17': - resolution: {integrity: sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ==} - - '@vitest/snapshot@4.0.17': - resolution: {integrity: sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ==} - - '@vitest/spy@4.0.17': - resolution: {integrity: sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==} - - '@vitest/utils@4.0.17': - resolution: {integrity: sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==} - - '@yarnpkg/lockfile@1.1.0': - resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} - - '@yarnpkg/parsers@3.0.2': - resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} - engines: {node: '>=18.12.0'} - - '@zkochan/js-yaml@0.0.7': - resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} - hasBin: true - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - ansis@4.2.0: - resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} - engines: {node: '>=14'} - - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - - ast-kit@2.2.0: - resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} - engines: {node: '>=20.19.0'} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - axios@1.13.2: - resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} - - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - better-path-resolve@1.0.0: - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} - engines: {node: '>=4'} - - birpc@4.0.0: - resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - chai@6.2.2: - resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} - engines: {node: '>=18'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chardet@2.1.1: - resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - - cheerio-select@2.1.0: - resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} - - cheerio@1.1.2: - resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==} - engines: {node: '>=20.18.1'} - - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - - cli-spinners@2.6.1: - resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} - engines: {node: '>=6'} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - comment-parser@1.4.4: - resolution: {integrity: sha512-0D6qSQ5IkeRrGJFHRClzaMOenMeT0gErz3zIw3AprKMqhRN6LNU2jQOdkPG/FZ+8bCgXE1VidrgSzlBBDZRr8A==} - engines: {node: '>= 12.0.0'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} - - dataloader@1.4.0: - resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - - define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - - defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - - devalue@5.6.2: - resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==} - - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - - dotenv-expand@11.0.7: - resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} - engines: {node: '>=12'} - - dotenv@16.4.7: - resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} - engines: {node: '>=12'} - - dotenv@16.6.1: - resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} - engines: {node: '>=12'} - - dts-resolver@2.1.3: - resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} - engines: {node: '>=20.19.0'} - peerDependencies: - oxc-resolver: '>=11.0.0' - peerDependenciesMeta: - oxc-resolver: - optional: true - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - empathic@2.0.0: - resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} - engines: {node: '>=14'} - - encoding-sniffer@0.2.1: - resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} - - end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - - enhanced-resolve@5.18.4: - resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} - engines: {node: '>=10.13.0'} - - enquirer@2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} - - enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-compat-utils@0.5.1: - resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} - engines: {node: '>=12'} - peerDependencies: - eslint: '>=6.0.0' - - eslint-import-context@0.1.9: - resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - peerDependencies: - unrs-resolver: ^1.0.0 - peerDependenciesMeta: - unrs-resolver: - optional: true - - eslint-plugin-es-x@7.8.0: - resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - eslint: '>=8' - - eslint-plugin-import-x@4.16.1: - resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/utils': ^8.0.0 - eslint: ^8.57.0 || ^9.0.0 - eslint-import-resolver-node: '*' - peerDependenciesMeta: - '@typescript-eslint/utils': - optional: true - eslint-import-resolver-node: - optional: true - - eslint-plugin-n@17.23.2: - resolution: {integrity: sha512-RhWBeb7YVPmNa2eggvJooiuehdL76/bbfj/OJewyoGT80qn5PXdz8zMOTO6YHOsI7byPt7+Ighh/i/4a5/v7hw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: '>=8.23.0' - - eslint-plugin-unused-imports@4.3.0: - resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 - eslint: ^9.0.0 || ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - - eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.1: - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@5.0.0: - resolution: {integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - esm-env@1.2.2: - resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} - - espree@10.4.0: - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - espree@11.0.0: - resolution: {integrity: sha512-+gMeWRrIh/NsG+3NaLeWHuyeyk70p2tbvZIWBYcqQ4/7Xvars6GYTZNhF1sIeLcc6Wb11He5ffz3hsHyXFrw5A==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} - - esrap@2.2.1: - resolution: {integrity: sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} - engines: {node: '>=12.0.0'} - - extendable-error@0.1.7: - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} - - fd-package-json@2.0.0: - resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} - - formatly@0.3.0: - resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} - engines: {node: '>=18.3.0'} - hasBin: true - - front-matter@4.0.2: - resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} - - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - - fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} - - fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-tsconfig@4.13.0: - resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@15.15.0: - resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} - engines: {node: '>=18'} - - globals@16.5.0: - resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} - engines: {node: '>=18'} - - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - - globrex@0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - happy-dom@20.3.1: - resolution: {integrity: sha512-tLvsizNno05Hij0PoB0QN/S8xf0YU2AGvO11/JlJDw5McA/gzyn0Ni1RwbTI1/zteUbOekJH0t6q8HFvjbxsGg==} - engines: {node: '>=20.0.0'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - hookable@6.0.1: - resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} - - html-link-extractor@1.0.5: - resolution: {integrity: sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==} - - htmlparser2@10.0.0: - resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} - - human-id@4.1.3: - resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} - hasBin: true - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - iconv-lite@0.7.2: - resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - import-without-cache@0.2.5: - resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} - engines: {node: '>=20.19.0'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-reference@3.0.3: - resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - - is-subdir@1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - jest-diff@30.2.0: - resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - js-yaml@3.14.2: - resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} - hasBin: true - - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - - jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - knip@5.81.0: - resolution: {integrity: sha512-EM9YdNg6zU2DWMJuc9zD8kPUpj0wvPspa63Qe9DPGygzL956uYThfoUQk5aNpPmMr9hs/k+Xm7FLuWFKERFkrQ==} - engines: {node: '>=18.18.0'} - hasBin: true - peerDependencies: - '@types/node': '>=18' - typescript: '>=5.0.4 <7' - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lines-and-columns@2.0.3: - resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - linkify-it@5.0.0: - resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - - locate-character@3.0.0: - resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - lunr@2.3.9: - resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - markdown-it@14.1.1: - resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} - hasBin: true - - markdown-link-extractor@4.0.3: - resolution: {integrity: sha512-aEltJiQ4/oC0h6Jbw/uuATGSHZPkcH8DIunNH1A0e+GSFkvZ6BbBkdvBTVfIV8r6HapCU3yTd0eFdi3ZeM1eAQ==} - - marked@17.0.1: - resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==} - engines: {node: '>= 20'} - hasBin: true - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - minimatch@10.1.1: - resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} - engines: {node: 20 || >=22} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - napi-postinstall@0.3.4: - resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-machine-id@1.1.12: - resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - - nx@22.3.3: - resolution: {integrity: sha512-pOxtKWUfvf0oD8Geqs8D89Q2xpstRTaSY+F6Ut/Wd0GnEjUjO32SS1ymAM6WggGPHDZN4qpNrd5cfIxQmAbRLg==} - hasBin: true - peerDependencies: - '@swc-node/register': ^1.8.0 - '@swc/core': ^1.3.85 - peerDependenciesMeta: - '@swc-node/register': - optional: true - '@swc/core': - optional: true - - obug@2.1.1: - resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - ora@5.3.0: - resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} - engines: {node: '>=10'} - - outdent@0.5.0: - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - - oxc-resolver@11.16.3: - resolution: {integrity: sha512-goLOJH3x69VouGWGp5CgCIHyksmOZzXr36lsRmQz1APg3SPFORrvV2q7nsUHMzLVa6ZJgNwkgUSJFsbCpAWkCA==} - - p-filter@2.1.0: - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} - engines: {node: '>=8'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - package-manager-detector@0.2.11: - resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse5-htmlparser2-tree-adapter@7.1.0: - resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} - - parse5-parser-stream@7.1.2: - resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} - - parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} - - pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier-plugin-svelte@3.4.1: - resolution: {integrity: sha512-xL49LCloMoZRvSwa6IEdN2GV6cq2IqpYGstYtMT+5wmml1/dClEoI0MZR78MiVPpu6BdQFfN0/y73yO6+br5Pg==} - peerDependencies: - prettier: ^3.0.0 - svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 - - prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - - prettier@3.8.0: - resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==} - engines: {node: '>=14'} - hasBin: true - - pretty-format@30.2.0: - resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - quansync@0.2.11: - resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} - - quansync@1.0.0: - resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - read-yaml-file@1.1.0: - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} - engines: {node: '>=6'} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - - resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - - restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rolldown-plugin-dts@0.20.0: - resolution: {integrity: sha512-cLAY1kN2ilTYMfZcFlGWbXnu6Nb+8uwUBsi+Mjbh4uIx7IN8uMOmJ7RxrrRgPsO4H7eSz3E+JwGoL1gyugiyUA==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@ts-macro/tsc': ^0.3.6 - '@typescript/native-preview': '>=7.0.0-dev.20250601.1' - rolldown: ^1.0.0-beta.57 - typescript: ^5.0.0 - vue-tsc: ~3.2.0 - peerDependenciesMeta: - '@ts-macro/tsc': - optional: true - '@typescript/native-preview': - optional: true - typescript: - optional: true - vue-tsc: - optional: true - - rolldown@1.0.0-beta.59: - resolution: {integrity: sha512-Slm000Gd8/AO9z4Kxl4r8mp/iakrbAuJ1L+7ddpkNxgQ+Vf37WPvY63l3oeyZcfuPD1DRrUYBsRPIXSOhvOsmw==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - - rolldown@1.0.0-rc.3: - resolution: {integrity: sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - - rollup@4.55.1: - resolution: {integrity: sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} - engines: {node: '>=10'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - sherif-darwin-arm64@1.10.0: - resolution: {integrity: sha512-fHRg/fgyxHebCH9vuGEhImyGqmwlBq67BVyI8Ugda8GM+W+Ofj1cQnzDX82cYuCHU+KJ7hQFq8iPHkRizXWOrA==} - cpu: [arm64] - os: [darwin] - - sherif-darwin-x64@1.10.0: - resolution: {integrity: sha512-7rhayQ+jlIj3SscnHMi6JVCYR9od/HiqIGIBgOQeux31YRzc/XvfKjE9X+FrCRU+72qz7sqw5ZY7jl7bRxbOUg==} - cpu: [x64] - os: [darwin] - - sherif-linux-arm64-musl@1.10.0: - resolution: {integrity: sha512-TsaQSefkaIJ+oFGGaaPm5BzrjVRnvcquh4q3/e5LB6JdhPTveNPo3o2Pzmq6sKry9dzk3p7sKtzJpLz4q5V/+Q==} - cpu: [arm64] - os: [linux] - - sherif-linux-arm64@1.10.0: - resolution: {integrity: sha512-QtEju3eLPpEb7hv9QRVdsi2J3bhIFEBbRk0vjdnAEKyRb3q9MjyqEhps69JgaCv8olEiBjGcU1hGP7vl5QVG4A==} - cpu: [arm64] - os: [linux] - - sherif-linux-x64-musl@1.10.0: - resolution: {integrity: sha512-iSYRYEFE0xfOJVwPjsUN4o8CoNSEyxJHsSliBDxfEZQubN0rmE9f1hs83HPPAkEozGestI7PxKFKcyTgTxEoXg==} - cpu: [x64] - os: [linux] - - sherif-linux-x64@1.10.0: - resolution: {integrity: sha512-/1ydjgJxXbqnGWViAENHxlX9lEDhATO99qtFcMseUFkPpEAxQ9qFctWf3OB2rciPlHLuPzhphkJAt7ZkX1R5eA==} - cpu: [x64] - os: [linux] - - sherif-windows-arm64@1.10.0: - resolution: {integrity: sha512-CBNys+m7TsWD/1/5WQRJCNjfm08VhmBP9JSmecoHCsfDF+o0vt52NDrzVOOeai/c/yYunCBvAAx9EIFXBmgpHw==} - cpu: [arm64] - os: [win32] - - sherif-windows-x64@1.10.0: - resolution: {integrity: sha512-XRN4SuZQud0X4UKZZxLe4IyVkbo9qa8rvmFhgCoULaRScucNdJJ4r6hnjZ7DR0spl7zSPJNZUNcgnnJmxWfs1Q==} - cpu: [x64] - os: [win32] - - sherif@1.10.0: - resolution: {integrity: sha512-DHg6+Pj7ORhYyC+CaSAr8DeRxqf9GXB90yqLmUILPtY7WhZuJatMir3id2MNjuF5I/1313SbrTTItIDu//G4jg==} - hasBin: true - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - smol-toml@1.6.0: - resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} - engines: {node: '>= 18'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - spawndamnit@3.0.1: - resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} - - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - stable-hash-x@0.2.0: - resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} - engines: {node: '>=12.0.0'} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - strip-json-comments@5.0.3: - resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} - engines: {node: '>=14.16'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - svelte@5.46.4: - resolution: {integrity: sha512-VJwdXrmv9L8L7ZasJeWcCjoIuMRVbhuxbss0fpVnR8yorMmjNDwcjIH08vS6wmSzzzgAG5CADQ1JuXPS2nwt9w==} - engines: {node: '>=18'} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - - term-size@2.2.1: - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} - engines: {node: '>=8'} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} - engines: {node: '>=18'} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - tinyrainbow@3.0.3: - resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} - engines: {node: '>=14.0.0'} - - tmp@0.2.5: - resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} - engines: {node: '>=14.14'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - - ts-api-utils@2.4.0: - resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - ts-declaration-location@1.0.7: - resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==} - peerDependencies: - typescript: '>=4.0.0' - - tsconfig-paths@4.2.0: - resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} - engines: {node: '>=6'} - - tsdown@0.19.0: - resolution: {integrity: sha512-uqg8yzlS7GemFWcM6aCp/sptF4bJiJbWUibuHTRLLCBEsGCgJxuqxPhuVTqyHXqoEkh9ohwAdlyDKli5MEWCyQ==} - engines: {node: '>=20.19.0'} - hasBin: true - peerDependencies: - '@arethetypeswrong/core': ^0.18.1 - '@vitejs/devtools': '*' - publint: ^0.3.0 - typescript: ^5.0.0 - unplugin-lightningcss: ^0.4.0 - unplugin-unused: ^0.5.0 - peerDependenciesMeta: - '@arethetypeswrong/core': - optional: true - '@vitejs/devtools': - optional: true - publint: - optional: true - typescript: - optional: true - unplugin-lightningcss: - optional: true - unplugin-unused: - optional: true - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - typedoc-plugin-frontmatter@1.3.0: - resolution: {integrity: sha512-xYQFMAecMlsRUjmf9oM/Sq2FVz4zlgcbIeVFNLdO118CHTN06gIKJNSlyExh9+Xl8sK0YhIvoQwViUURxritWA==} - peerDependencies: - typedoc-plugin-markdown: '>=4.5.0' - - typedoc-plugin-markdown@4.9.0: - resolution: {integrity: sha512-9Uu4WR9L7ZBgAl60N/h+jqmPxxvnC9nQAlnnO/OujtG2ubjnKTVUFY1XDhcMY+pCqlX3N2HsQM2QTYZIU9tJuw==} - engines: {node: '>= 18'} - peerDependencies: - typedoc: 0.28.x - - typedoc@0.28.14: - resolution: {integrity: sha512-ftJYPvpVfQvFzpkoSfHLkJybdA/geDJ8BGQt/ZnkkhnBYoYW6lBgPQXu6vqLxO4X75dA55hX8Af847H5KXlEFA==} - engines: {node: '>= 18', pnpm: '>= 10'} - hasBin: true - peerDependencies: - typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x - - typescript-eslint@8.53.0: - resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - - unconfig-core@7.5.0: - resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} - - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - - undici@7.18.2: - resolution: {integrity: sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==} - engines: {node: '>=20.18.1'} - - universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - - unrs-resolver@1.11.1: - resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - - unrun@0.2.27: - resolution: {integrity: sha512-Mmur1UJpIbfxasLOhPRvox/QS4xBiDii71hMP7smfRthGcwFL2OAmYRgduLANOAU4LUkvVamuP+02U+c90jlrw==} - engines: {node: '>=20.19.0'} - hasBin: true - peerDependencies: - synckit: ^0.11.11 - peerDependenciesMeta: - synckit: - optional: true - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - vite@7.3.1: - resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@4.0.17: - resolution: {integrity: sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.17 - '@vitest/browser-preview': 4.0.17 - '@vitest/browser-webdriverio': 4.0.17 - '@vitest/ui': 4.0.17 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@opentelemetry/api': - optional: true - '@types/node': - optional: true - '@vitest/browser-playwright': - optional: true - '@vitest/browser-preview': - optional: true - '@vitest/browser-webdriverio': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - vue-eslint-parser@10.2.0: - resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - - walk-up-path@4.0.0: - resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} - engines: {node: 20 || >=22} - - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - - whatwg-mimetype@3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} - engines: {node: '>= 14.6'} - hasBin: true - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - zimmerframe@1.1.4: - resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} - - zod@4.3.5: - resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} - -snapshots: - - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/parser@7.29.0': - dependencies: - '@babel/types': 7.29.0 - - '@babel/runtime@7.28.6': {} - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@changesets/apply-release-plan@7.0.14': - dependencies: - '@changesets/config': 3.1.2 - '@changesets/get-version-range-type': 0.4.0 - '@changesets/git': 3.0.4 - '@changesets/should-skip-package': 0.1.2 - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - detect-indent: 6.1.0 - fs-extra: 7.0.1 - lodash.startcase: 4.4.0 - outdent: 0.5.0 - prettier: 2.8.8 - resolve-from: 5.0.0 - semver: 7.7.3 - - '@changesets/assemble-release-plan@6.0.9': - dependencies: - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.1.3 - '@changesets/should-skip-package': 0.1.2 - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - semver: 7.7.3 - - '@changesets/changelog-git@0.2.1': - dependencies: - '@changesets/types': 6.1.0 - - '@changesets/cli@2.29.8(@types/node@25.0.9)': - dependencies: - '@changesets/apply-release-plan': 7.0.14 - '@changesets/assemble-release-plan': 6.0.9 - '@changesets/changelog-git': 0.2.1 - '@changesets/config': 3.1.2 - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.1.3 - '@changesets/get-release-plan': 4.0.14 - '@changesets/git': 3.0.4 - '@changesets/logger': 0.1.1 - '@changesets/pre': 2.0.2 - '@changesets/read': 0.6.6 - '@changesets/should-skip-package': 0.1.2 - '@changesets/types': 6.1.0 - '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@25.0.9) - '@manypkg/get-packages': 1.1.3 - ansi-colors: 4.1.3 - ci-info: 3.9.0 - enquirer: 2.4.1 - fs-extra: 7.0.1 - mri: 1.2.0 - p-limit: 2.3.0 - package-manager-detector: 0.2.11 - picocolors: 1.1.1 - resolve-from: 5.0.0 - semver: 7.7.3 - spawndamnit: 3.0.1 - term-size: 2.2.1 - transitivePeerDependencies: - - '@types/node' - - '@changesets/config@3.1.2': - dependencies: - '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.1.3 - '@changesets/logger': 0.1.1 - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - micromatch: 4.0.8 - - '@changesets/errors@0.2.0': - dependencies: - extendable-error: 0.1.7 - - '@changesets/get-dependents-graph@2.1.3': - dependencies: - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - picocolors: 1.1.1 - semver: 7.7.3 - - '@changesets/get-github-info@0.6.0': - dependencies: - dataloader: 1.4.0 - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - '@changesets/get-release-plan@4.0.14': - dependencies: - '@changesets/assemble-release-plan': 6.0.9 - '@changesets/config': 3.1.2 - '@changesets/pre': 2.0.2 - '@changesets/read': 0.6.6 - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - - '@changesets/get-version-range-type@0.4.0': {} - - '@changesets/git@3.0.4': - dependencies: - '@changesets/errors': 0.2.0 - '@manypkg/get-packages': 1.1.3 - is-subdir: 1.2.0 - micromatch: 4.0.8 - spawndamnit: 3.0.1 - - '@changesets/logger@0.1.1': - dependencies: - picocolors: 1.1.1 - - '@changesets/parse@0.4.2': - dependencies: - '@changesets/types': 6.1.0 - js-yaml: 4.1.1 - - '@changesets/pre@2.0.2': - dependencies: - '@changesets/errors': 0.2.0 - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - fs-extra: 7.0.1 - - '@changesets/read@0.6.6': - dependencies: - '@changesets/git': 3.0.4 - '@changesets/logger': 0.1.1 - '@changesets/parse': 0.4.2 - '@changesets/types': 6.1.0 - fs-extra: 7.0.1 - p-filter: 2.1.0 - picocolors: 1.1.1 - - '@changesets/should-skip-package@0.1.2': - dependencies: - '@changesets/types': 6.1.0 - '@manypkg/get-packages': 1.1.3 - - '@changesets/types@4.1.0': {} - - '@changesets/types@6.1.0': {} - - '@changesets/write@0.4.0': - dependencies: - '@changesets/types': 6.1.0 - fs-extra: 7.0.1 - human-id: 4.1.3 - prettier: 2.8.8 - - '@emnapi/core@1.8.1': - dependencies: - '@emnapi/wasi-threads': 1.1.0 - tslib: 2.8.1 - - '@emnapi/runtime@1.8.1': - dependencies: - tslib: 2.8.1 - - '@emnapi/wasi-threads@1.1.0': - dependencies: - tslib: 2.8.1 - - '@esbuild/aix-ppc64@0.27.2': - optional: true - - '@esbuild/android-arm64@0.27.2': - optional: true - - '@esbuild/android-arm@0.27.2': - optional: true - - '@esbuild/android-x64@0.27.2': - optional: true - - '@esbuild/darwin-arm64@0.27.2': - optional: true - - '@esbuild/darwin-x64@0.27.2': - optional: true - - '@esbuild/freebsd-arm64@0.27.2': - optional: true - - '@esbuild/freebsd-x64@0.27.2': - optional: true - - '@esbuild/linux-arm64@0.27.2': - optional: true - - '@esbuild/linux-arm@0.27.2': - optional: true - - '@esbuild/linux-ia32@0.27.2': - optional: true - - '@esbuild/linux-loong64@0.27.2': - optional: true - - '@esbuild/linux-mips64el@0.27.2': - optional: true - - '@esbuild/linux-ppc64@0.27.2': - optional: true - - '@esbuild/linux-riscv64@0.27.2': - optional: true - - '@esbuild/linux-s390x@0.27.2': - optional: true - - '@esbuild/linux-x64@0.27.2': - optional: true - - '@esbuild/netbsd-arm64@0.27.2': - optional: true - - '@esbuild/netbsd-x64@0.27.2': - optional: true - - '@esbuild/openbsd-arm64@0.27.2': - optional: true - - '@esbuild/openbsd-x64@0.27.2': - optional: true - - '@esbuild/openharmony-arm64@0.27.2': - optional: true - - '@esbuild/sunos-x64@0.27.2': - optional: true - - '@esbuild/win32-arm64@0.27.2': - optional: true - - '@esbuild/win32-ia32@0.27.2': - optional: true - - '@esbuild/win32-x64@0.27.2': - optional: true - - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': - dependencies: - eslint: 9.39.2(jiti@2.6.1) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.2': {} - - '@eslint/config-array@0.21.1': - dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.3 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/config-helpers@0.4.2': - dependencies: - '@eslint/core': 0.17.0 - - '@eslint/core@0.17.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.3.3': - dependencies: - ajv: 6.12.6 - debug: 4.4.3 - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.39.2': {} - - '@eslint/object-schema@2.1.7': {} - - '@eslint/plugin-kit@0.4.1': - dependencies: - '@eslint/core': 0.17.0 - levn: 0.4.1 - - '@faker-js/faker@10.2.0': {} - - '@gerrit0/mini-shiki@3.23.0': - dependencies: - '@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 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.7': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.4.3 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.4.3': {} - - '@inquirer/external-editor@1.0.3(@types/node@25.0.9)': - dependencies: - chardet: 2.1.1 - iconv-lite: 0.7.2 - optionalDependencies: - '@types/node': 25.0.9 - - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': - dependencies: - '@isaacs/balanced-match': 4.0.1 - - '@jest/diff-sequences@30.0.1': {} - - '@jest/get-type@30.1.0': {} - - '@jest/schemas@30.0.5': - dependencies: - '@sinclair/typebox': 0.34.47 - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@manypkg/find-root@1.1.0': - dependencies: - '@babel/runtime': 7.28.6 - '@types/node': 12.20.55 - find-up: 4.1.0 - fs-extra: 8.1.0 - - '@manypkg/get-packages@1.1.3': - dependencies: - '@babel/runtime': 7.28.6 - '@changesets/types': 4.1.0 - '@manypkg/find-root': 1.1.0 - fs-extra: 8.1.0 - globby: 11.1.0 - read-yaml-file: 1.1.0 - - '@napi-rs/wasm-runtime@0.2.12': - dependencies: - '@emnapi/core': 1.8.1 - '@emnapi/runtime': 1.8.1 - '@tybys/wasm-util': 0.10.1 - optional: true - - '@napi-rs/wasm-runtime@0.2.4': - dependencies: - '@emnapi/core': 1.8.1 - '@emnapi/runtime': 1.8.1 - '@tybys/wasm-util': 0.9.0 - - '@napi-rs/wasm-runtime@1.1.1': - dependencies: - '@emnapi/core': 1.8.1 - '@emnapi/runtime': 1.8.1 - '@tybys/wasm-util': 0.10.1 - optional: true - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 - - '@nx/nx-darwin-arm64@22.3.3': - optional: true - - '@nx/nx-darwin-x64@22.3.3': - optional: true - - '@nx/nx-freebsd-x64@22.3.3': - optional: true - - '@nx/nx-linux-arm-gnueabihf@22.3.3': - optional: true - - '@nx/nx-linux-arm64-gnu@22.3.3': - optional: true - - '@nx/nx-linux-arm64-musl@22.3.3': - optional: true - - '@nx/nx-linux-x64-gnu@22.3.3': - optional: true - - '@nx/nx-linux-x64-musl@22.3.3': - optional: true - - '@nx/nx-win32-arm64-msvc@22.3.3': - optional: true - - '@nx/nx-win32-x64-msvc@22.3.3': - optional: true - - '@oxc-project/types@0.107.0': {} - - '@oxc-project/types@0.112.0': {} - - '@oxc-resolver/binding-android-arm-eabi@11.16.3': - optional: true - - '@oxc-resolver/binding-android-arm64@11.16.3': - optional: true - - '@oxc-resolver/binding-darwin-arm64@11.16.3': - optional: true - - '@oxc-resolver/binding-darwin-x64@11.16.3': - optional: true - - '@oxc-resolver/binding-freebsd-x64@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-arm64-musl@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-x64-gnu@11.16.3': - optional: true - - '@oxc-resolver/binding-linux-x64-musl@11.16.3': - optional: true - - '@oxc-resolver/binding-openharmony-arm64@11.16.3': - optional: true - - '@oxc-resolver/binding-wasm32-wasi@11.16.3': - dependencies: - '@napi-rs/wasm-runtime': 1.1.1 - optional: true - - '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': - optional: true - - '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': - optional: true - - '@oxc-resolver/binding-win32-x64-msvc@11.16.3': - optional: true - - '@quansync/fs@1.0.0': - dependencies: - quansync: 1.0.0 - - '@rolldown/binding-android-arm64@1.0.0-beta.59': - optional: true - - '@rolldown/binding-android-arm64@1.0.0-rc.3': - optional: true - - '@rolldown/binding-darwin-arm64@1.0.0-beta.59': - optional: true - - '@rolldown/binding-darwin-arm64@1.0.0-rc.3': - optional: true - - '@rolldown/binding-darwin-x64@1.0.0-beta.59': - optional: true - - '@rolldown/binding-darwin-x64@1.0.0-rc.3': - optional: true - - '@rolldown/binding-freebsd-x64@1.0.0-beta.59': - optional: true - - '@rolldown/binding-freebsd-x64@1.0.0-rc.3': - optional: true - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': - optional: true - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': - optional: true - - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': - optional: true - - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': - optional: true - - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': - optional: true - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': - optional: true - - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': - optional: true - - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': - optional: true - - '@rolldown/binding-linux-x64-musl@1.0.0-beta.59': - optional: true - - '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': - optional: true - - '@rolldown/binding-openharmony-arm64@1.0.0-beta.59': - optional: true - - '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': - optional: true - - '@rolldown/binding-wasm32-wasi@1.0.0-beta.59': - dependencies: - '@napi-rs/wasm-runtime': 1.1.1 - optional: true - - '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': - dependencies: - '@napi-rs/wasm-runtime': 1.1.1 - optional: true - - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59': - optional: true - - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': - optional: true - - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': - optional: true - - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': - optional: true - - '@rolldown/pluginutils@1.0.0-beta.59': {} - - '@rolldown/pluginutils@1.0.0-rc.3': {} - - '@rollup/rollup-android-arm-eabi@4.55.1': - optional: true - - '@rollup/rollup-android-arm64@4.55.1': - optional: true - - '@rollup/rollup-darwin-arm64@4.55.1': - optional: true - - '@rollup/rollup-darwin-x64@4.55.1': - optional: true - - '@rollup/rollup-freebsd-arm64@4.55.1': - optional: true - - '@rollup/rollup-freebsd-x64@4.55.1': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.55.1': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.55.1': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.55.1': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.55.1': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.55.1': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.55.1': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.55.1': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.55.1': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.55.1': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.55.1': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.55.1': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.55.1': - optional: true - - '@rollup/rollup-linux-x64-musl@4.55.1': - optional: true - - '@rollup/rollup-openbsd-x64@4.55.1': - optional: true - - '@rollup/rollup-openharmony-arm64@4.55.1': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.55.1': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.55.1': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.55.1': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.55.1': - optional: true - - '@shikijs/engine-oniguruma@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - - '@shikijs/langs@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - - '@shikijs/themes@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - - '@shikijs/types@3.23.0': - dependencies: - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - - '@shikijs/vscode-textmate@10.0.2': {} - - '@sinclair/typebox@0.34.47': {} - - '@standard-schema/spec@1.1.0': {} - - '@stylistic/eslint-plugin@5.7.0(eslint@9.39.2(jiti@2.6.1))': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@typescript-eslint/types': 8.53.0 - eslint: 9.39.2(jiti@2.6.1) - eslint-visitor-keys: 5.0.0 - espree: 11.0.0 - estraverse: 5.3.0 - picomatch: 4.0.3 - - '@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)': - dependencies: - acorn: 8.15.0 - - '@svitejs/changesets-changelog-github-compact@1.2.0': - dependencies: - '@changesets/get-github-info': 0.6.0 - dotenv: 16.6.1 - transitivePeerDependencies: - - encoding - - '@tanstack/eslint-config@0.3.4(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint/js': 9.39.2 - '@stylistic/eslint-plugin': 5.7.0(eslint@9.39.2(jiti@2.6.1)) - eslint: 9.39.2(jiti@2.6.1) - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-n: 17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - globals: 16.5.0 - typescript-eslint: 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - vue-eslint-parser: 10.2.0(eslint@9.39.2(jiti@2.6.1)) - transitivePeerDependencies: - - '@typescript-eslint/utils' - - eslint-import-resolver-node - - supports-color - - typescript - - '@tanstack/typedoc-config@0.3.3(typescript@5.9.3)': - dependencies: - typedoc: 0.28.14(typescript@5.9.3) - typedoc-plugin-frontmatter: 1.3.0(typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3))) - typedoc-plugin-markdown: 4.9.0(typedoc@0.28.14(typescript@5.9.3)) - transitivePeerDependencies: - - typescript - - '@tybys/wasm-util@0.10.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@tybys/wasm-util@0.9.0': - dependencies: - tslib: 2.8.1 - - '@types/chai@5.2.3': - dependencies: - '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 - - '@types/deep-eql@4.0.2': {} - - '@types/estree@1.0.8': {} - - '@types/hast@3.0.4': - dependencies: - '@types/unist': 3.0.3 - - '@types/json-schema@7.0.15': {} - - '@types/node@12.20.55': {} - - '@types/node@20.19.30': - dependencies: - undici-types: 6.21.0 - - '@types/node@25.0.9': - dependencies: - undici-types: 7.16.0 - - '@types/unist@3.0.3': {} - - '@types/whatwg-mimetype@3.0.2': {} - - '@types/ws@8.18.1': - dependencies: - '@types/node': 25.0.9 - - '@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/type-utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.53.0 - eslint: 9.39.2(jiti@2.6.1) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.53.0 - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.53.0(typescript@5.9.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.3) - '@typescript-eslint/types': 8.53.0 - debug: 4.4.3 - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.53.0': - dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 - - '@typescript-eslint/tsconfig-utils@8.53.0(typescript@5.9.3)': - dependencies: - typescript: 5.9.3 - - '@typescript-eslint/type-utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.53.0': {} - - '@typescript-eslint/typescript-estree@8.53.0(typescript@5.9.3)': - dependencies: - '@typescript-eslint/project-service': 8.53.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.3) - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 - debug: 4.4.3 - minimatch: 9.0.5 - semver: 7.7.3 - tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.53.0': - dependencies: - '@typescript-eslint/types': 8.53.0 - eslint-visitor-keys: 4.2.1 - - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - optional: true - - '@unrs/resolver-binding-android-arm64@1.11.1': - optional: true - - '@unrs/resolver-binding-darwin-arm64@1.11.1': - optional: true - - '@unrs/resolver-binding-darwin-x64@1.11.1': - optional: true - - '@unrs/resolver-binding-freebsd-x64@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - optional: true - - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - dependencies: - '@napi-rs/wasm-runtime': 0.2.12 - optional: true - - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - optional: true - - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - optional: true - - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - optional: true - - '@vitest/expect@4.0.17': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.0.17 - '@vitest/utils': 4.0.17 - chai: 6.2.2 - tinyrainbow: 3.0.3 - - '@vitest/mocker@4.0.17(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2))': - dependencies: - '@vitest/spy': 4.0.17 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2) - - '@vitest/pretty-format@4.0.17': - dependencies: - tinyrainbow: 3.0.3 - - '@vitest/runner@4.0.17': - dependencies: - '@vitest/utils': 4.0.17 - pathe: 2.0.3 - - '@vitest/snapshot@4.0.17': - dependencies: - '@vitest/pretty-format': 4.0.17 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.0.17': {} - - '@vitest/utils@4.0.17': - dependencies: - '@vitest/pretty-format': 4.0.17 - tinyrainbow: 3.0.3 - - '@yarnpkg/lockfile@1.1.0': {} - - '@yarnpkg/parsers@3.0.2': - dependencies: - js-yaml: 3.14.2 - tslib: 2.8.1 - - '@zkochan/js-yaml@0.0.7': - dependencies: - argparse: 2.0.1 - - acorn-jsx@5.3.2(acorn@8.15.0): - dependencies: - acorn: 8.15.0 - - acorn@8.15.0: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-colors@4.1.3: {} - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - ansis@4.2.0: {} - - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - - argparse@2.0.1: {} - - aria-query@5.3.2: {} - - array-union@2.1.0: {} - - assertion-error@2.0.1: {} - - ast-kit@2.2.0: - dependencies: - '@babel/parser': 7.29.0 - pathe: 2.0.3 - - asynckit@0.4.0: {} - - axios@1.13.2: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.5 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - axobject-query@4.1.0: {} - - balanced-match@1.0.2: {} - - base64-js@1.5.1: {} - - better-path-resolve@1.0.0: - dependencies: - is-windows: 1.0.2 - - birpc@4.0.0: {} - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - boolbase@1.0.0: {} - - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - cac@6.7.14: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - callsites@3.1.0: {} - - chai@6.2.2: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chardet@2.1.1: {} - - cheerio-select@2.1.0: - dependencies: - boolbase: 1.0.0 - css-select: 5.2.2 - css-what: 6.2.2 - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - - cheerio@1.1.2: - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.2.2 - encoding-sniffer: 0.2.1 - htmlparser2: 10.0.0 - parse5: 7.3.0 - parse5-htmlparser2-tree-adapter: 7.1.0 - parse5-parser-stream: 7.1.2 - undici: 7.18.2 - whatwg-mimetype: 4.0.0 - - ci-info@3.9.0: {} - - cli-cursor@3.1.0: - dependencies: - restore-cursor: 3.1.0 - - cli-spinners@2.6.1: {} - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - clone@1.0.4: {} - - clsx@2.1.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - comment-parser@1.4.4: {} - - concat-map@0.0.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-what@6.2.2: {} - - dataloader@1.4.0: {} - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - deep-is@0.1.4: {} - - defaults@1.0.4: - dependencies: - clone: 1.0.4 - - define-lazy-prop@2.0.0: {} - - defu@6.1.4: {} - - delayed-stream@1.0.0: {} - - detect-indent@6.1.0: {} - - devalue@5.6.2: {} - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - dotenv-expand@11.0.7: - dependencies: - dotenv: 16.4.7 - - dotenv@16.4.7: {} - - dotenv@16.6.1: {} - - dts-resolver@2.1.3(oxc-resolver@11.16.3): - optionalDependencies: - oxc-resolver: 11.16.3 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - emoji-regex@8.0.0: {} - - empathic@2.0.0: {} - - encoding-sniffer@0.2.1: - dependencies: - iconv-lite: 0.6.3 - whatwg-encoding: 3.1.1 - - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - - enhanced-resolve@5.18.4: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - - enquirer@2.3.6: - dependencies: - ansi-colors: 4.1.3 - - enquirer@2.4.1: - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - - entities@4.5.0: {} - - entities@6.0.1: {} - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-module-lexer@1.7.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - esbuild@0.27.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 - - escalade@3.2.0: {} - - escape-string-regexp@1.0.5: {} - - escape-string-regexp@4.0.0: {} - - eslint-compat-utils@0.5.1(eslint@9.39.2(jiti@2.6.1)): - dependencies: - eslint: 9.39.2(jiti@2.6.1) - semver: 7.7.3 - - eslint-import-context@0.1.9(unrs-resolver@1.11.1): - dependencies: - get-tsconfig: 4.13.0 - stable-hash-x: 0.2.0 - optionalDependencies: - unrs-resolver: 1.11.1 - - eslint-plugin-es-x@7.8.0(eslint@9.39.2(jiti@2.6.1)): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - eslint: 9.39.2(jiti@2.6.1) - eslint-compat-utils: 0.5.1(eslint@9.39.2(jiti@2.6.1)) - - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): - dependencies: - '@typescript-eslint/types': 8.53.0 - comment-parser: 1.4.4 - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - is-glob: 4.0.3 - minimatch: 10.1.1 - semver: 7.7.3 - stable-hash-x: 0.2.0 - unrs-resolver: 1.11.1 - optionalDependencies: - '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - eslint-plugin-n@17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - enhanced-resolve: 5.18.4 - eslint: 9.39.2(jiti@2.6.1) - eslint-plugin-es-x: 7.8.0(eslint@9.39.2(jiti@2.6.1)) - get-tsconfig: 4.13.0 - globals: 15.15.0 - globrex: 0.1.2 - ignore: 5.3.2 - semver: 7.7.3 - ts-declaration-location: 1.0.7(typescript@5.9.3) - transitivePeerDependencies: - - typescript - - eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): - dependencies: - eslint: 9.39.2(jiti@2.6.1) - optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - - eslint-scope@8.4.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.1: {} - - eslint-visitor-keys@5.0.0: {} - - eslint@9.39.2(jiti@2.6.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - - esm-env@1.2.2: {} - - espree@10.4.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 4.2.1 - - espree@11.0.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 5.0.0 - - esprima@4.0.1: {} - - esquery@1.7.0: - dependencies: - estraverse: 5.3.0 - - esrap@2.2.1: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.8 - - esutils@2.0.3: {} - - expect-type@1.3.0: {} - - extendable-error@0.1.7: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.20.1: - dependencies: - reusify: 1.1.0 - - fd-package-json@2.0.0: - dependencies: - walk-up-path: 4.0.0 - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - figures@3.2.0: - dependencies: - escape-string-regexp: 1.0.5 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - - flat@5.0.2: {} - - flatted@3.3.3: {} - - follow-redirects@1.15.11: {} - - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - - formatly@0.3.0: - dependencies: - fd-package-json: 2.0.0 - - front-matter@4.0.2: - dependencies: - js-yaml: 3.14.2 - - fs-constants@1.0.0: {} - - fs-extra@7.0.1: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fs-extra@8.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - get-caller-file@2.0.5: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-tsconfig@4.13.0: - dependencies: - resolve-pkg-maps: 1.0.0 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - globals@14.0.0: {} - - globals@15.15.0: {} - - globals@16.5.0: {} - - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - - globrex@0.1.2: {} - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - happy-dom@20.3.1: - dependencies: - '@types/node': 20.19.30 - '@types/whatwg-mimetype': 3.0.2 - '@types/ws': 8.18.1 - whatwg-mimetype: 3.0.0 - ws: 8.19.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - has-flag@4.0.0: {} - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - hookable@6.0.1: {} - - html-link-extractor@1.0.5: - dependencies: - cheerio: 1.1.2 - - htmlparser2@10.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.2.2 - entities: 6.0.1 - - human-id@4.1.3: {} - - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - - iconv-lite@0.7.2: - dependencies: - safer-buffer: 2.1.2 - - ieee754@1.2.1: {} - - ignore@5.3.2: {} - - ignore@7.0.5: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - import-without-cache@0.2.5: {} - - imurmurhash@0.1.4: {} - - inherits@2.0.4: {} - - is-docker@2.2.1: {} - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-interactive@1.0.0: {} - - is-number@7.0.0: {} - - is-reference@3.0.3: - dependencies: - '@types/estree': 1.0.8 - - is-subdir@1.2.0: - dependencies: - better-path-resolve: 1.0.0 - - is-unicode-supported@0.1.0: {} - - is-windows@1.0.2: {} - - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - - isexe@2.0.0: {} - - jest-diff@30.2.0: - dependencies: - '@jest/diff-sequences': 30.0.1 - '@jest/get-type': 30.1.0 - chalk: 4.1.2 - pretty-format: 30.2.0 - - jiti@2.6.1: {} - - js-yaml@3.14.2: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - jsesc@3.1.0: {} - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@2.2.3: {} - - jsonc-parser@3.2.0: {} - - jsonfile@4.0.0: - optionalDependencies: - graceful-fs: 4.2.11 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - knip@5.81.0(@types/node@25.0.9)(typescript@5.9.3): - dependencies: - '@nodelib/fs.walk': 1.2.8 - '@types/node': 25.0.9 - fast-glob: 3.3.3 - formatly: 0.3.0 - jiti: 2.6.1 - js-yaml: 4.1.1 - minimist: 1.2.8 - oxc-resolver: 11.16.3 - picocolors: 1.1.1 - picomatch: 4.0.3 - smol-toml: 1.6.0 - strip-json-comments: 5.0.3 - typescript: 5.9.3 - zod: 4.3.5 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lines-and-columns@2.0.3: {} - - linkify-it@5.0.0: - dependencies: - uc.micro: 2.1.0 - - locate-character@3.0.0: {} - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - lodash.startcase@4.4.0: {} - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - lunr@2.3.9: {} - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - markdown-it@14.1.1: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.0 - mdurl: 2.0.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 - - markdown-link-extractor@4.0.3: - dependencies: - html-link-extractor: 1.0.5 - marked: 17.0.1 - - marked@17.0.1: {} - - math-intrinsics@1.1.0: {} - - mdurl@2.0.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mimic-fn@2.1.0: {} - - minimatch@10.1.1: - dependencies: - '@isaacs/brace-expansion': 5.0.0 - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - - minimatch@9.0.3: - dependencies: - brace-expansion: 2.0.2 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - - minimist@1.2.8: {} - - mri@1.2.0: {} - - ms@2.1.3: {} - - nanoid@3.3.11: {} - - napi-postinstall@0.3.4: {} - - natural-compare@1.4.0: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-machine-id@1.1.12: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - - nx@22.3.3: - dependencies: - '@napi-rs/wasm-runtime': 0.2.4 - '@yarnpkg/lockfile': 1.1.0 - '@yarnpkg/parsers': 3.0.2 - '@zkochan/js-yaml': 0.0.7 - axios: 1.13.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - cliui: 8.0.1 - dotenv: 16.4.7 - dotenv-expand: 11.0.7 - enquirer: 2.3.6 - figures: 3.2.0 - flat: 5.0.2 - front-matter: 4.0.2 - ignore: 7.0.5 - jest-diff: 30.2.0 - jsonc-parser: 3.2.0 - lines-and-columns: 2.0.3 - minimatch: 9.0.3 - node-machine-id: 1.1.12 - npm-run-path: 4.0.1 - open: 8.4.2 - ora: 5.3.0 - resolve.exports: 2.0.3 - semver: 7.7.3 - string-width: 4.2.3 - tar-stream: 2.2.0 - tmp: 0.2.5 - tree-kill: 1.2.2 - tsconfig-paths: 4.2.0 - tslib: 2.8.1 - yaml: 2.8.2 - yargs: 17.7.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@nx/nx-darwin-arm64': 22.3.3 - '@nx/nx-darwin-x64': 22.3.3 - '@nx/nx-freebsd-x64': 22.3.3 - '@nx/nx-linux-arm-gnueabihf': 22.3.3 - '@nx/nx-linux-arm64-gnu': 22.3.3 - '@nx/nx-linux-arm64-musl': 22.3.3 - '@nx/nx-linux-x64-gnu': 22.3.3 - '@nx/nx-linux-x64-musl': 22.3.3 - '@nx/nx-win32-arm64-msvc': 22.3.3 - '@nx/nx-win32-x64-msvc': 22.3.3 - transitivePeerDependencies: - - debug - - obug@2.1.1: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - open@8.4.2: - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - ora@5.3.0: - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - is-interactive: 1.0.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - outdent@0.5.0: {} - - oxc-resolver@11.16.3: - optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.16.3 - '@oxc-resolver/binding-android-arm64': 11.16.3 - '@oxc-resolver/binding-darwin-arm64': 11.16.3 - '@oxc-resolver/binding-darwin-x64': 11.16.3 - '@oxc-resolver/binding-freebsd-x64': 11.16.3 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.16.3 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.16.3 - '@oxc-resolver/binding-linux-arm64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-arm64-musl': 11.16.3 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-riscv64-musl': 11.16.3 - '@oxc-resolver/binding-linux-s390x-gnu': 11.16.3 - '@oxc-resolver/binding-linux-x64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-x64-musl': 11.16.3 - '@oxc-resolver/binding-openharmony-arm64': 11.16.3 - '@oxc-resolver/binding-wasm32-wasi': 11.16.3 - '@oxc-resolver/binding-win32-arm64-msvc': 11.16.3 - '@oxc-resolver/binding-win32-ia32-msvc': 11.16.3 - '@oxc-resolver/binding-win32-x64-msvc': 11.16.3 - - p-filter@2.1.0: - dependencies: - p-map: 2.1.0 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-map@2.1.0: {} - - p-try@2.2.0: {} - - package-manager-detector@0.2.11: - dependencies: - quansync: 0.2.11 - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse5-htmlparser2-tree-adapter@7.1.0: - dependencies: - domhandler: 5.0.3 - parse5: 7.3.0 - - parse5-parser-stream@7.1.2: - dependencies: - parse5: 7.3.0 - - parse5@7.3.0: - dependencies: - entities: 6.0.1 - - path-exists@4.0.0: {} - - path-key@3.1.1: {} - - path-type@4.0.0: {} - - pathe@2.0.3: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - - pify@4.0.1: {} - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prettier-plugin-svelte@3.4.1(prettier@3.8.0)(svelte@5.46.4): - dependencies: - prettier: 3.8.0 - svelte: 5.46.4 - - prettier@2.8.8: {} - - prettier@3.8.0: {} - - pretty-format@30.2.0: - dependencies: - '@jest/schemas': 30.0.5 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - proxy-from-env@1.1.0: {} - - punycode.js@2.3.1: {} - - punycode@2.3.1: {} - - quansync@0.2.11: {} - - quansync@1.0.0: {} - - queue-microtask@1.2.3: {} - - react-is@18.3.1: {} - - read-yaml-file@1.1.0: - dependencies: - graceful-fs: 4.2.11 - js-yaml: 3.14.2 - pify: 4.0.1 - strip-bom: 3.0.0 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - require-directory@2.1.1: {} - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - - resolve-pkg-maps@1.0.0: {} - - resolve.exports@2.0.3: {} - - restore-cursor@3.1.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - - reusify@1.1.0: {} - - rolldown-plugin-dts@0.20.0(oxc-resolver@11.16.3)(rolldown@1.0.0-beta.59)(typescript@5.9.3): - dependencies: - '@babel/generator': 7.29.1 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - ast-kit: 2.2.0 - birpc: 4.0.0 - dts-resolver: 2.1.3(oxc-resolver@11.16.3) - get-tsconfig: 4.13.0 - obug: 2.1.1 - rolldown: 1.0.0-beta.59 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - oxc-resolver - - rolldown@1.0.0-beta.59: - dependencies: - '@oxc-project/types': 0.107.0 - '@rolldown/pluginutils': 1.0.0-beta.59 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.59 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.59 - '@rolldown/binding-darwin-x64': 1.0.0-beta.59 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.59 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.59 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.59 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.59 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.59 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.59 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.59 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.59 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.59 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.59 - - rolldown@1.0.0-rc.3: - dependencies: - '@oxc-project/types': 0.112.0 - '@rolldown/pluginutils': 1.0.0-rc.3 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.3 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.3 - '@rolldown/binding-darwin-x64': 1.0.0-rc.3 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.3 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.3 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.3 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.3 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.3 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.3 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.3 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.3 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.3 - - rollup@4.55.1: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.55.1 - '@rollup/rollup-android-arm64': 4.55.1 - '@rollup/rollup-darwin-arm64': 4.55.1 - '@rollup/rollup-darwin-x64': 4.55.1 - '@rollup/rollup-freebsd-arm64': 4.55.1 - '@rollup/rollup-freebsd-x64': 4.55.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.55.1 - '@rollup/rollup-linux-arm-musleabihf': 4.55.1 - '@rollup/rollup-linux-arm64-gnu': 4.55.1 - '@rollup/rollup-linux-arm64-musl': 4.55.1 - '@rollup/rollup-linux-loong64-gnu': 4.55.1 - '@rollup/rollup-linux-loong64-musl': 4.55.1 - '@rollup/rollup-linux-ppc64-gnu': 4.55.1 - '@rollup/rollup-linux-ppc64-musl': 4.55.1 - '@rollup/rollup-linux-riscv64-gnu': 4.55.1 - '@rollup/rollup-linux-riscv64-musl': 4.55.1 - '@rollup/rollup-linux-s390x-gnu': 4.55.1 - '@rollup/rollup-linux-x64-gnu': 4.55.1 - '@rollup/rollup-linux-x64-musl': 4.55.1 - '@rollup/rollup-openbsd-x64': 4.55.1 - '@rollup/rollup-openharmony-arm64': 4.55.1 - '@rollup/rollup-win32-arm64-msvc': 4.55.1 - '@rollup/rollup-win32-ia32-msvc': 4.55.1 - '@rollup/rollup-win32-x64-gnu': 4.55.1 - '@rollup/rollup-win32-x64-msvc': 4.55.1 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - semver@7.7.3: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - sherif-darwin-arm64@1.10.0: - optional: true - - sherif-darwin-x64@1.10.0: - optional: true - - sherif-linux-arm64-musl@1.10.0: - optional: true - - sherif-linux-arm64@1.10.0: - optional: true - - sherif-linux-x64-musl@1.10.0: - optional: true - - sherif-linux-x64@1.10.0: - optional: true - - sherif-windows-arm64@1.10.0: - optional: true - - sherif-windows-x64@1.10.0: - optional: true - - sherif@1.10.0: - optionalDependencies: - sherif-darwin-arm64: 1.10.0 - sherif-darwin-x64: 1.10.0 - sherif-linux-arm64: 1.10.0 - sherif-linux-arm64-musl: 1.10.0 - sherif-linux-x64: 1.10.0 - sherif-linux-x64-musl: 1.10.0 - sherif-windows-arm64: 1.10.0 - sherif-windows-x64: 1.10.0 - - siginfo@2.0.0: {} - - signal-exit@3.0.7: {} - - signal-exit@4.1.0: {} - - slash@3.0.0: {} - - smol-toml@1.6.0: {} - - source-map-js@1.2.1: {} - - spawndamnit@3.0.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - sprintf-js@1.0.3: {} - - stable-hash-x@0.2.0: {} - - stackback@0.0.2: {} - - std-env@3.10.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@3.0.0: {} - - strip-json-comments@3.1.1: {} - - strip-json-comments@5.0.3: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - svelte@5.46.4: - dependencies: - '@jridgewell/remapping': 2.3.5 - '@jridgewell/sourcemap-codec': 1.5.5 - '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) - '@types/estree': 1.0.8 - acorn: 8.15.0 - aria-query: 5.3.2 - axobject-query: 4.1.0 - clsx: 2.1.1 - devalue: 5.6.2 - esm-env: 1.2.2 - esrap: 2.2.1 - is-reference: 3.0.3 - locate-character: 3.0.0 - magic-string: 0.30.21 - zimmerframe: 1.1.4 - - tapable@2.3.0: {} - - tar-stream@2.2.0: - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.5 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - - term-size@2.2.1: {} - - tinybench@2.9.0: {} - - tinyexec@1.0.2: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinyrainbow@3.0.3: {} - - tmp@0.2.5: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - tr46@0.0.3: {} - - tree-kill@1.2.2: {} - - ts-api-utils@2.4.0(typescript@5.9.3): - dependencies: - typescript: 5.9.3 - - ts-declaration-location@1.0.7(typescript@5.9.3): - dependencies: - picomatch: 4.0.3 - typescript: 5.9.3 - - tsconfig-paths@4.2.0: - dependencies: - json5: 2.2.3 - minimist: 1.2.8 - strip-bom: 3.0.0 - - tsdown@0.19.0(oxc-resolver@11.16.3)(typescript@5.9.3): - dependencies: - ansis: 4.2.0 - cac: 6.7.14 - defu: 6.1.4 - empathic: 2.0.0 - hookable: 6.0.1 - import-without-cache: 0.2.5 - obug: 2.1.1 - picomatch: 4.0.3 - rolldown: 1.0.0-beta.59 - rolldown-plugin-dts: 0.20.0(oxc-resolver@11.16.3)(rolldown@1.0.0-beta.59)(typescript@5.9.3) - semver: 7.7.3 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tree-kill: 1.2.2 - unconfig-core: 7.5.0 - unrun: 0.2.27 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - '@ts-macro/tsc' - - '@typescript/native-preview' - - oxc-resolver - - synckit - - vue-tsc - - tslib@2.8.1: {} - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - typedoc-plugin-frontmatter@1.3.0(typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3))): - dependencies: - typedoc-plugin-markdown: 4.9.0(typedoc@0.28.14(typescript@5.9.3)) - yaml: 2.8.2 - - typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3)): - dependencies: - typedoc: 0.28.14(typescript@5.9.3) - - typedoc@0.28.14(typescript@5.9.3): - dependencies: - '@gerrit0/mini-shiki': 3.23.0 - lunr: 2.3.9 - markdown-it: 14.1.1 - minimatch: 9.0.5 - typescript: 5.9.3 - yaml: 2.8.2 - - typescript-eslint@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - typescript@5.9.3: {} - - uc.micro@2.1.0: {} - - unconfig-core@7.5.0: - dependencies: - '@quansync/fs': 1.0.0 - quansync: 1.0.0 - - undici-types@6.21.0: {} - - undici-types@7.16.0: {} - - undici@7.18.2: {} - - universalify@0.1.2: {} - - unrs-resolver@1.11.1: - dependencies: - napi-postinstall: 0.3.4 - optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.11.1 - '@unrs/resolver-binding-android-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-x64': 1.11.1 - '@unrs/resolver-binding-freebsd-x64': 1.11.1 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 - '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-musl': 1.11.1 - '@unrs/resolver-binding-wasm32-wasi': 1.11.1 - '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 - '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 - '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - - unrun@0.2.27: - dependencies: - rolldown: 1.0.0-rc.3 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - util-deprecate@1.0.2: {} - - vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2): - dependencies: - esbuild: 0.27.2 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.55.1 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 25.0.9 - fsevents: 2.3.3 - jiti: 2.6.1 - yaml: 2.8.2 - - vitest@4.0.17(@types/node@25.0.9)(happy-dom@20.3.1)(jiti@2.6.1)(yaml@2.8.2): - dependencies: - '@vitest/expect': 4.0.17 - '@vitest/mocker': 4.0.17(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2)) - '@vitest/pretty-format': 4.0.17 - '@vitest/runner': 4.0.17 - '@vitest/snapshot': 4.0.17 - '@vitest/spy': 4.0.17 - '@vitest/utils': 4.0.17 - es-module-lexer: 1.7.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.3 - std-env: 3.10.0 - tinybench: 2.9.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 25.0.9 - happy-dom: 20.3.1 - transitivePeerDependencies: - - jiti - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml - - vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1)): - dependencies: - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.7.0 - semver: 7.7.3 - transitivePeerDependencies: - - supports-color - - walk-up-path@4.0.0: {} - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - - webidl-conversions@3.0.1: {} - - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@3.0.0: {} - - whatwg-mimetype@4.0.0: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - word-wrap@1.2.5: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@8.19.0: {} - - y18n@5.0.8: {} - - yaml@2.8.2: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yocto-queue@0.1.0: {} - - zimmerframe@1.1.4: {} - - zod@4.3.5: {} +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@tanstack/typedoc-config': + specifier: ^0.3.3 + version: 0.3.3(typescript@5.9.3) + devDependencies: + '@changesets/cli': + specifier: ^2.29.8 + version: 2.29.8(@types/node@25.0.9) + '@faker-js/faker': + specifier: ^10.2.0 + version: 10.2.0 + '@svitejs/changesets-changelog-github-compact': + specifier: ^1.2.0 + version: 1.2.0 + '@tanstack/eslint-config': + specifier: 0.3.4 + version: 0.3.4(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@types/node': + specifier: ^25.0.7 + version: 25.0.9 + eslint: + specifier: ^9.39.2 + version: 9.39.2(jiti@2.6.1) + eslint-plugin-unused-imports: + specifier: ^4.3.0 + version: 4.3.0(@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) + happy-dom: + specifier: ^20.1.0 + version: 20.3.1 + knip: + specifier: ^5.80.2 + version: 5.81.0(@types/node@25.0.9)(typescript@5.9.3) + markdown-link-extractor: + specifier: ^4.0.3 + version: 4.0.3 + nx: + specifier: ^22.3.3 + version: 22.3.3 + prettier: + specifier: ^3.7.4 + version: 3.8.0 + prettier-plugin-svelte: + specifier: ^3.4.1 + version: 3.4.1(prettier@3.8.0)(svelte@5.46.4) + sherif: + specifier: ^1.9.0 + version: 1.10.0 + tinyglobby: + specifier: ^0.2.15 + version: 0.2.15 + typescript: + specifier: 5.9.3 + version: 5.9.3 + vitest: + specifier: ^4.0.17 + version: 4.0.17(@types/node@25.0.9)(happy-dom@20.3.1)(jiti@2.6.1)(yaml@2.8.2) + yaml: + specifier: ^2.7.0 + version: 2.8.2 + + packages/intent: + dependencies: + yaml: + specifier: ^2.7.0 + version: 2.8.2 + devDependencies: + tsdown: + specifier: ^0.19.0 + version: 0.19.0(oxc-resolver@11.16.3)(typescript@5.9.3) + +packages: + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@changesets/apply-release-plan@7.0.14': + resolution: {integrity: sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==} + + '@changesets/assemble-release-plan@6.0.9': + resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/cli@2.29.8': + resolution: {integrity: sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==} + hasBin: true + + '@changesets/config@3.1.2': + resolution: {integrity: sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.3': + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} + + '@changesets/get-github-info@0.6.0': + resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} + + '@changesets/get-release-plan@4.0.14': + resolution: {integrity: sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.2': + resolution: {integrity: sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.6': + resolution: {integrity: sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@faker-js/faker@10.2.0': + resolution: {integrity: sha512-rTXwAsIxpCqzUnZvrxVh3L0QA0NzToqWBLAhV+zDV3MIIwiQhAZHMdPCIaj5n/yADu/tyk12wIPgL6YHGXJP+g==} + engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} + + '@gerrit0/mini-shiki@3.23.0': + resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@jest/diff-sequences@30.0.1': + resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@napi-rs/wasm-runtime@0.2.4': + resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nx/nx-darwin-arm64@22.3.3': + resolution: {integrity: sha512-zBAGFGLal09CxhQkdMpOVwcwa9Y01aFm88jTTn35s/DdIWsfngmPzz0t4mG7u2D05q7TJfGQ31pIf5GkNUjo6g==} + cpu: [arm64] + os: [darwin] + + '@nx/nx-darwin-x64@22.3.3': + resolution: {integrity: sha512-6ZQ6rMqH8NY4Jz+Gc89D5bIH2NxZb5S/vaA4yJ9RrqAfl4QWchNFD5na+aRivSd+UdsYLPKKl6qohet5SE6vOg==} + cpu: [x64] + os: [darwin] + + '@nx/nx-freebsd-x64@22.3.3': + resolution: {integrity: sha512-J/PP5pIOQtR7ZzrFwP6d6h0yfY7r9EravG2m940GsgzGbtZGYIDqnh5Wdt+4uBWPH8VpdNOwFqH0afELtJA3MA==} + cpu: [x64] + os: [freebsd] + + '@nx/nx-linux-arm-gnueabihf@22.3.3': + resolution: {integrity: sha512-/zn0altzM15S7qAgXMaB41vHkEn18HyTVUvRrjmmwaVqk9WfmDmqOQlGWoJ6XCbpvKQ8bh14RyhR9LGw1JJkNA==} + cpu: [arm] + os: [linux] + + '@nx/nx-linux-arm64-gnu@22.3.3': + resolution: {integrity: sha512-NmPeCexWIZHW9RM3lDdFENN9C3WtlQ5L4RSNFESIjreS921rgePhulsszYdGnHdcnKPYlBBJnX/NxVsfioBbnQ==} + cpu: [arm64] + os: [linux] + + '@nx/nx-linux-arm64-musl@22.3.3': + resolution: {integrity: sha512-K02U88Q0dpvCfmSXXvY7KbYQSa1m+mkYeqDBRHp11yHk1GoIqaHp8oEWda7FV4gsriNExPSS5tX1/QGVoLZrCw==} + cpu: [arm64] + os: [linux] + + '@nx/nx-linux-x64-gnu@22.3.3': + resolution: {integrity: sha512-04TEbvgwRaB9ifr39YwJmWh3RuXb4Ry4m84SOJyjNXAfPrepcWgfIQn1VL2ul1Ybq+P023dLO9ME8uqFh6j1YQ==} + cpu: [x64] + os: [linux] + + '@nx/nx-linux-x64-musl@22.3.3': + resolution: {integrity: sha512-uxBXx5q+S5OGatbYDxnamsKXRKlYn+Eq1nrCAHaf8rIfRoHlDiRV2PqtWuF+O2pxR5FWKpvr+/sZtt9rAf7KMw==} + cpu: [x64] + os: [linux] + + '@nx/nx-win32-arm64-msvc@22.3.3': + resolution: {integrity: sha512-aOwlfD6ZA1K6hjZtbhBSp7s1yi3sHbMpLCa4stXzfhCCpKUv46HU/EdiWdE1N8AsyNFemPZFq81k1VTowcACdg==} + cpu: [arm64] + os: [win32] + + '@nx/nx-win32-x64-msvc@22.3.3': + resolution: {integrity: sha512-EDR8BtqeDvVNQ+kPwnfeSfmerYetitU3tDkxOMIybjKJDh69U2JwTB8n9ARwNaZQbNk7sCGNRUSZFTbAAUKvuQ==} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.107.0': + resolution: {integrity: sha512-QFDRbYfV2LVx8tyqtyiah3jQPUj1mK2+RYwxyFWyGoys6XJnwTdlzO6rdNNHOPorHAu5Uo34oWRKcvNpbJarmQ==} + + '@oxc-project/types@0.112.0': + resolution: {integrity: sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==} + + '@oxc-resolver/binding-android-arm-eabi@11.16.3': + resolution: {integrity: sha512-CVyWHu6ACDqDcJxR4nmGiG8vDF4TISJHqRNzac5z/gPQycs/QrP/1pDsJBy0MD7jSw8nVq2E5WqeHQKabBG/Jg==} + cpu: [arm] + os: [android] + + '@oxc-resolver/binding-android-arm64@11.16.3': + resolution: {integrity: sha512-tTIoB7plLeh2o6Ay7NnV5CJb6QUXdxI7Shnsp2ECrLSV81k+oVE3WXYrQSh4ltWL75i0OgU5Bj3bsuyg5SMepw==} + cpu: [arm64] + os: [android] + + '@oxc-resolver/binding-darwin-arm64@11.16.3': + resolution: {integrity: sha512-OXKVH7uwYd3Rbw1s2yJZd6/w+6b01iaokZubYhDAq4tOYArr+YCS+lr81q1hsTPPRZeIsWE+rJLulmf1qHdYZA==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@11.16.3': + resolution: {integrity: sha512-WwjQ4WdnCxVYZYd3e3oY5XbV3JeLy9pPMK+eQQ2m8DtqUtbxnvPpAYC2Knv/2bS6q5JiktqOVJ2Hfia3OSo0/A==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@11.16.3': + resolution: {integrity: sha512-4OHKFGJBBfOnuJnelbCS4eBorI6cj54FUxcZJwEXPeoLc8yzORBoJ2w+fQbwjlQcUUZLEg92uGhKCRiUoqznjg==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': + resolution: {integrity: sha512-OM3W0NLt9u7uKwG/yZbeXABansZC0oZeDF1nKgvcZoRw4/Yak6/l4S0onBfDFeYMY94eYeAt2bl60e30lgsb5A==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': + resolution: {integrity: sha512-MRs7D7i1t7ACsAdTuP81gLZES918EpBmiUyEl8fu302yQB+4L7L7z0Ui8BWnthUTQd3nAU9dXvENLK/SqRVH8A==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': + resolution: {integrity: sha512-0eVYZxSceNqGADzhlV4ZRqkHF0fjWxRXQOB7Qwl5y1gN/XYUDvMfip+ngtzj4dM7zQT4U97hUhJ7PUKSy/JIGQ==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-musl@11.16.3': + resolution: {integrity: sha512-B1BvLeZbgDdVN0FvU40l5Q7lej8310WlabCBaouk8jY7H7xbI8phtomTtk3Efmevgfy5hImaQJu6++OmcFb2NQ==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': + resolution: {integrity: sha512-q7khglic3Jqak7uDgA3MFnjDeI7krQT595GDZpvFq785fmFYSx8rlTkoHzmhQtUisYtl4XG7WUscwsoidFUI4w==} + cpu: [ppc64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': + resolution: {integrity: sha512-aFRNmQNPzDgQEbw2s3c8yJYRimacSDI+u9df8rn5nSKzTVitHmbEpZqfxpwNLCKIuLSNmozHR1z1OT+oZVeYqg==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': + resolution: {integrity: sha512-vZI85SvSMADcEL9G1TIrV0Rlkc1fY5Mup0DdlVC5EHPysZB4hXXHpr+h09pjlK5y+5om5foIzDRxE1baUCaWOA==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': + resolution: {integrity: sha512-xiLBnaUlddFEzRHiHiSGEMbkg8EwZY6VD8F+3GfnFsiK3xg/4boaUV2bwXd+nUzl3UDQOMW1QcZJ4jJSb0qiJA==} + cpu: [s390x] + os: [linux] + + '@oxc-resolver/binding-linux-x64-gnu@11.16.3': + resolution: {integrity: sha512-6y0b05wIazJJgwu7yU/AYGFswzQQudYJBOb/otDhiDacp1+6ye8egoxx63iVo9lSpDbipL++54AJQFlcOHCB+g==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-linux-x64-musl@11.16.3': + resolution: {integrity: sha512-RmMgwuMa42c9logS7Pjprf5KCp8J1a1bFiuBFtG9/+yMu0BhY2t+0VR/um7pwtkNFvIQqAVh6gDOg/PnoKRcdQ==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-openharmony-arm64@11.16.3': + resolution: {integrity: sha512-/7AYRkjjW7xu1nrHgWUFy99Duj4/ydOBVaHtODie9/M6fFngo+8uQDFFnzmr4q//sd/cchIerISp/8CQ5TsqIA==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.16.3': + resolution: {integrity: sha512-urM6aIPbi5di4BSlnpd/TWtDJgG6RD06HvLBuNM+qOYuFtY1/xPbzQ2LanBI2ycpqIoIZwsChyplALwAMdyfCQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': + resolution: {integrity: sha512-QuvLqGKf7frxWHQ5TnrcY0C/hJpANsaez99Q4dAk1hen7lDTD4FBPtBzPnntLFXeaVG3PnSmnVjlv0vMILwU7Q==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': + resolution: {integrity: sha512-QR/witXK6BmYTlEP8CCjC5fxeG5U9A6a50pNpC1nLnhAcJjtzFG8KcQ5etVy/XvCLiDc7fReaAWRNWtCaIhM8Q==} + cpu: [ia32] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@11.16.3': + resolution: {integrity: sha512-bFuJRKOscsDAEZ/a8BezcTMAe2BQ/OBRfuMLFUuINfTR5qGVcm4a3xBIrQVepBaPxFj16SJdRjGe05vDiwZmFw==} + cpu: [x64] + os: [win32] + + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + + '@rolldown/binding-android-arm64@1.0.0-beta.59': + resolution: {integrity: sha512-6yLLgyswYwiCfls9+hoNFY9F8TQdwo15hpXDHzlAR0X/GojeKF+AuNcXjYNbOJ4zjl/5D6lliE8CbpB5t1OWIQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-android-arm64@1.0.0-rc.3': + resolution: {integrity: sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.59': + resolution: {integrity: sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.3': + resolution: {integrity: sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.59': + resolution: {integrity: sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.3': + resolution: {integrity: sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.59': + resolution: {integrity: sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.3': + resolution: {integrity: sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': + resolution: {integrity: sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': + resolution: {integrity: sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': + resolution: {integrity: sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': + resolution: {integrity: sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': + resolution: {integrity: sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': + resolution: {integrity: sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': + resolution: {integrity: sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': + resolution: {integrity: sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.59': + resolution: {integrity: sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': + resolution: {integrity: sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.59': + resolution: {integrity: sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': + resolution: {integrity: sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.59': + resolution: {integrity: sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': + resolution: {integrity: sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59': + resolution: {integrity: sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': + resolution: {integrity: sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': + resolution: {integrity: sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': + resolution: {integrity: sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.59': + resolution: {integrity: sha512-aoh6LAJRyhtazs98ydgpNOYstxUlsOV1KJXcpf/0c0vFcUA8uyd/hwKRhqE/AAPNqAho9RliGsvitCoOzREoVA==} + + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + + '@rollup/rollup-android-arm-eabi@4.55.1': + resolution: {integrity: sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.55.1': + resolution: {integrity: sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.55.1': + resolution: {integrity: sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.55.1': + resolution: {integrity: sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.55.1': + resolution: {integrity: sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.55.1': + resolution: {integrity: sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.55.1': + resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.55.1': + resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.55.1': + resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.55.1': + resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.55.1': + resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.55.1': + resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.55.1': + resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.55.1': + resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.55.1': + resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.55.1': + resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.55.1': + resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.55.1': + resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.55.1': + resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.55.1': + resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.55.1': + resolution: {integrity: sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.55.1': + resolution: {integrity: sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.55.1': + resolution: {integrity: sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.55.1': + resolution: {integrity: sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.55.1': + resolution: {integrity: sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==} + cpu: [x64] + os: [win32] + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@sinclair/typebox@0.34.47': + resolution: {integrity: sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@stylistic/eslint-plugin@5.7.0': + resolution: {integrity: sha512-PsSugIf9ip1H/mWKj4bi/BlEoerxXAda9ByRFsYuwsmr6af9NxJL0AaiNXs8Le7R21QR5KMiD/KdxZZ71LjAxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=9.0.0' + + '@sveltejs/acorn-typescript@1.0.8': + resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==} + peerDependencies: + acorn: ^8.9.0 + + '@svitejs/changesets-changelog-github-compact@1.2.0': + resolution: {integrity: sha512-08eKiDAjj4zLug1taXSIJ0kGL5cawjVCyJkBb6EWSg5fEPX6L+Wtr0CH2If4j5KYylz85iaZiFlUItvgJvll5g==} + engines: {node: ^14.13.1 || ^16.0.0 || >=18} + + '@tanstack/eslint-config@0.3.4': + resolution: {integrity: sha512-5Ou1XWJRCTx5G8WoCbT7+6nQ4iNdsISzBAc4lXpFy2fEOO7xioOSPvcPIv+r9V0drPPETou2tr6oLGZZ909FKg==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^8.0.0 || ^9.0.0 + + '@tanstack/typedoc-config@0.3.3': + resolution: {integrity: sha512-wVT2YfKDSpd+4f7fk6UaPIP3a2J7LSovlyVuFF1PH2yQb7gjqehod5zdFiwFyEXgvI9XGuFvvs1OehkKNYcr6A==} + engines: {node: '>=18'} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/node@20.19.30': + resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==} + + '@types/node@25.0.9': + resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/whatwg-mimetype@3.0.2': + resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@typescript-eslint/eslint-plugin@8.53.0': + resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.53.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.53.0': + resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.53.0': + resolution: {integrity: sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.53.0': + resolution: {integrity: sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.53.0': + resolution: {integrity: sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.53.0': + resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.53.0': + resolution: {integrity: sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.53.0': + resolution: {integrity: sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.53.0': + resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.53.0': + resolution: {integrity: sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + '@vitest/expect@4.0.17': + resolution: {integrity: sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==} + + '@vitest/mocker@4.0.17': + resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.17': + resolution: {integrity: sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==} + + '@vitest/runner@4.0.17': + resolution: {integrity: sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ==} + + '@vitest/snapshot@4.0.17': + resolution: {integrity: sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ==} + + '@vitest/spy@4.0.17': + resolution: {integrity: sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==} + + '@vitest/utils@4.0.17': + resolution: {integrity: sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==} + + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + '@yarnpkg/parsers@3.0.2': + resolution: {integrity: sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==} + engines: {node: '>=18.12.0'} + + '@zkochan/js-yaml@0.0.7': + resolution: {integrity: sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==} + hasBin: true + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + birpc@4.0.0: + resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + + cheerio@1.1.2: + resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==} + engines: {node: '>=20.18.1'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.6.1: + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comment-parser@1.4.4: + resolution: {integrity: sha512-0D6qSQ5IkeRrGJFHRClzaMOenMeT0gErz3zIw3AprKMqhRN6LNU2jQOdkPG/FZ+8bCgXE1VidrgSzlBBDZRr8A==} + engines: {node: '>= 12.0.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + devalue@5.6.2: + resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} + + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dts-resolver@2.1.3: + resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} + engines: {node: '>=20.19.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + encoding-sniffer@0.2.1: + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + enhanced-resolve@5.18.4: + resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} + engines: {node: '>=10.13.0'} + + enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-import-context@0.1.9: + resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-import-x@4.16.1: + resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/utils': ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 + eslint-import-resolver-node: '*' + peerDependenciesMeta: + '@typescript-eslint/utils': + optional: true + eslint-import-resolver-node: + optional: true + + eslint-plugin-n@17.23.2: + resolution: {integrity: sha512-RhWBeb7YVPmNa2eggvJooiuehdL76/bbfj/OJewyoGT80qn5PXdz8zMOTO6YHOsI7byPt7+Ighh/i/4a5/v7hw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.23.0' + + eslint-plugin-unused-imports@4.3.0: + resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.0: + resolution: {integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@11.0.0: + resolution: {integrity: sha512-+gMeWRrIh/NsG+3NaLeWHuyeyk70p2tbvZIWBYcqQ4/7Xvars6GYTZNhF1sIeLcc6Wb11He5ffz3hsHyXFrw5A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrap@2.2.1: + resolution: {integrity: sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formatly@0.3.0: + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} + hasBin: true + + front-matter@4.0.2: + resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + happy-dom@20.3.1: + resolution: {integrity: sha512-tLvsizNno05Hij0PoB0QN/S8xf0YU2AGvO11/JlJDw5McA/gzyn0Ni1RwbTI1/zteUbOekJH0t6q8HFvjbxsGg==} + engines: {node: '>=20.0.0'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hookable@6.0.1: + resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} + + html-link-extractor@1.0.5: + resolution: {integrity: sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==} + + htmlparser2@10.0.0: + resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} + + human-id@4.1.3: + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} + hasBin: true + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-without-cache@0.2.5: + resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} + engines: {node: '>=20.19.0'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jest-diff@30.2.0: + resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + knip@5.81.0: + resolution: {integrity: sha512-EM9YdNg6zU2DWMJuc9zD8kPUpj0wvPspa63Qe9DPGygzL956uYThfoUQk5aNpPmMr9hs/k+Xm7FLuWFKERFkrQ==} + engines: {node: '>=18.18.0'} + hasBin: true + peerDependencies: + '@types/node': '>=18' + typescript: '>=5.0.4 <7' + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@2.0.3: + resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} + hasBin: true + + markdown-link-extractor@4.0.3: + resolution: {integrity: sha512-aEltJiQ4/oC0h6Jbw/uuATGSHZPkcH8DIunNH1A0e+GSFkvZ6BbBkdvBTVfIV8r6HapCU3yTd0eFdi3ZeM1eAQ==} + + marked@17.0.1: + resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==} + engines: {node: '>= 20'} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@10.1.1: + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-machine-id@1.1.12: + resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nx@22.3.3: + resolution: {integrity: sha512-pOxtKWUfvf0oD8Geqs8D89Q2xpstRTaSY+F6Ut/Wd0GnEjUjO32SS1ymAM6WggGPHDZN4qpNrd5cfIxQmAbRLg==} + hasBin: true + peerDependencies: + '@swc-node/register': ^1.8.0 + '@swc/core': ^1.3.85 + peerDependenciesMeta: + '@swc-node/register': + optional: true + '@swc/core': + optional: true + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@5.3.0: + resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} + engines: {node: '>=10'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + oxc-resolver@11.16.3: + resolution: {integrity: sha512-goLOJH3x69VouGWGp5CgCIHyksmOZzXr36lsRmQz1APg3SPFORrvV2q7nsUHMzLVa6ZJgNwkgUSJFsbCpAWkCA==} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-plugin-svelte@3.4.1: + resolution: {integrity: sha512-xL49LCloMoZRvSwa6IEdN2GV6cq2IqpYGstYtMT+5wmml1/dClEoI0MZR78MiVPpu6BdQFfN0/y73yO6+br5Pg==} + peerDependencies: + prettier: ^3.0.0 + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.8.0: + resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@30.2.0: + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rolldown-plugin-dts@0.20.0: + resolution: {integrity: sha512-cLAY1kN2ilTYMfZcFlGWbXnu6Nb+8uwUBsi+Mjbh4uIx7IN8uMOmJ7RxrrRgPsO4H7eSz3E+JwGoL1gyugiyUA==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@ts-macro/tsc': ^0.3.6 + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-beta.57 + typescript: ^5.0.0 + vue-tsc: ~3.2.0 + peerDependenciesMeta: + '@ts-macro/tsc': + optional: true + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-beta.59: + resolution: {integrity: sha512-Slm000Gd8/AO9z4Kxl4r8mp/iakrbAuJ1L+7ddpkNxgQ+Vf37WPvY63l3oeyZcfuPD1DRrUYBsRPIXSOhvOsmw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rolldown@1.0.0-rc.3: + resolution: {integrity: sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.55.1: + resolution: {integrity: sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + sherif-darwin-arm64@1.10.0: + resolution: {integrity: sha512-fHRg/fgyxHebCH9vuGEhImyGqmwlBq67BVyI8Ugda8GM+W+Ofj1cQnzDX82cYuCHU+KJ7hQFq8iPHkRizXWOrA==} + cpu: [arm64] + os: [darwin] + + sherif-darwin-x64@1.10.0: + resolution: {integrity: sha512-7rhayQ+jlIj3SscnHMi6JVCYR9od/HiqIGIBgOQeux31YRzc/XvfKjE9X+FrCRU+72qz7sqw5ZY7jl7bRxbOUg==} + cpu: [x64] + os: [darwin] + + sherif-linux-arm64-musl@1.10.0: + resolution: {integrity: sha512-TsaQSefkaIJ+oFGGaaPm5BzrjVRnvcquh4q3/e5LB6JdhPTveNPo3o2Pzmq6sKry9dzk3p7sKtzJpLz4q5V/+Q==} + cpu: [arm64] + os: [linux] + + sherif-linux-arm64@1.10.0: + resolution: {integrity: sha512-QtEju3eLPpEb7hv9QRVdsi2J3bhIFEBbRk0vjdnAEKyRb3q9MjyqEhps69JgaCv8olEiBjGcU1hGP7vl5QVG4A==} + cpu: [arm64] + os: [linux] + + sherif-linux-x64-musl@1.10.0: + resolution: {integrity: sha512-iSYRYEFE0xfOJVwPjsUN4o8CoNSEyxJHsSliBDxfEZQubN0rmE9f1hs83HPPAkEozGestI7PxKFKcyTgTxEoXg==} + cpu: [x64] + os: [linux] + + sherif-linux-x64@1.10.0: + resolution: {integrity: sha512-/1ydjgJxXbqnGWViAENHxlX9lEDhATO99qtFcMseUFkPpEAxQ9qFctWf3OB2rciPlHLuPzhphkJAt7ZkX1R5eA==} + cpu: [x64] + os: [linux] + + sherif-windows-arm64@1.10.0: + resolution: {integrity: sha512-CBNys+m7TsWD/1/5WQRJCNjfm08VhmBP9JSmecoHCsfDF+o0vt52NDrzVOOeai/c/yYunCBvAAx9EIFXBmgpHw==} + cpu: [arm64] + os: [win32] + + sherif-windows-x64@1.10.0: + resolution: {integrity: sha512-XRN4SuZQud0X4UKZZxLe4IyVkbo9qa8rvmFhgCoULaRScucNdJJ4r6hnjZ7DR0spl7zSPJNZUNcgnnJmxWfs1Q==} + cpu: [x64] + os: [win32] + + sherif@1.10.0: + resolution: {integrity: sha512-DHg6+Pj7ORhYyC+CaSAr8DeRxqf9GXB90yqLmUILPtY7WhZuJatMir3id2MNjuF5I/1313SbrTTItIDu//G4jg==} + hasBin: true + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} + engines: {node: '>= 18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stable-hash-x@0.2.0: + resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} + engines: {node: '>=12.0.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + svelte@5.46.4: + resolution: {integrity: sha512-VJwdXrmv9L8L7ZasJeWcCjoIuMRVbhuxbss0fpVnR8yorMmjNDwcjIH08vS6wmSzzzgAG5CADQ1JuXPS2nwt9w==} + engines: {node: '>=18'} + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-declaration-location@1.0.7: + resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==} + peerDependencies: + typescript: '>=4.0.0' + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tsdown@0.19.0: + resolution: {integrity: sha512-uqg8yzlS7GemFWcM6aCp/sptF4bJiJbWUibuHTRLLCBEsGCgJxuqxPhuVTqyHXqoEkh9ohwAdlyDKli5MEWCyQ==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@vitejs/devtools': '*' + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@vitejs/devtools': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typedoc-plugin-frontmatter@1.3.0: + resolution: {integrity: sha512-xYQFMAecMlsRUjmf9oM/Sq2FVz4zlgcbIeVFNLdO118CHTN06gIKJNSlyExh9+Xl8sK0YhIvoQwViUURxritWA==} + peerDependencies: + typedoc-plugin-markdown: '>=4.5.0' + + typedoc-plugin-markdown@4.9.0: + resolution: {integrity: sha512-9Uu4WR9L7ZBgAl60N/h+jqmPxxvnC9nQAlnnO/OujtG2ubjnKTVUFY1XDhcMY+pCqlX3N2HsQM2QTYZIU9tJuw==} + engines: {node: '>= 18'} + peerDependencies: + typedoc: 0.28.x + + typedoc@0.28.14: + resolution: {integrity: sha512-ftJYPvpVfQvFzpkoSfHLkJybdA/geDJ8BGQt/ZnkkhnBYoYW6lBgPQXu6vqLxO4X75dA55hX8Af847H5KXlEFA==} + engines: {node: '>= 18', pnpm: '>= 10'} + hasBin: true + peerDependencies: + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x + + typescript-eslint@8.53.0: + resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + undici@7.18.2: + resolution: {integrity: sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==} + engines: {node: '>=20.18.1'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + unrun@0.2.27: + resolution: {integrity: sha512-Mmur1UJpIbfxasLOhPRvox/QS4xBiDii71hMP7smfRthGcwFL2OAmYRgduLANOAU4LUkvVamuP+02U+c90jlrw==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.0.17: + resolution: {integrity: sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.17 + '@vitest/browser-preview': 4.0.17 + '@vitest/browser-webdriverio': 4.0.17 + '@vitest/ui': 4.0.17 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vue-eslint-parser@10.2.0: + resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + + zod@4.3.5: + resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + +snapshots: + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.29.0': + dependencies: + '@babel/types': 7.29.0 + + '@babel/runtime@7.28.6': {} + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@changesets/apply-release-plan@7.0.14': + dependencies: + '@changesets/config': 3.1.2 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.3 + + '@changesets/assemble-release-plan@6.0.9': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.3 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/cli@2.29.8(@types/node@25.0.9)': + dependencies: + '@changesets/apply-release-plan': 7.0.14 + '@changesets/assemble-release-plan': 6.0.9 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.2 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/get-release-plan': 4.0.14 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.6 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@inquirer/external-editor': 1.0.3(@types/node@25.0.9) + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + ci-info: 3.9.0 + enquirer: 2.4.1 + fs-extra: 7.0.1 + mri: 1.2.0 + p-limit: 2.3.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.3 + spawndamnit: 3.0.1 + term-size: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@changesets/config@3.1.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/logger': 0.1.1 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.3': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.3 + + '@changesets/get-github-info@0.6.0': + dependencies: + dataloader: 1.4.0 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@changesets/get-release-plan@4.0.14': + dependencies: + '@changesets/assemble-release-plan': 6.0.9 + '@changesets/config': 3.1.2 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.6 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.2': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.1.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.6': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.2 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.3 + prettier: 2.8.8 + + '@emnapi/core@1.8.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + + '@emnapi/runtime@1.8.1': + dependencies: + tslib: 2.8.1 + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + + '@esbuild/aix-ppc64@0.27.2': + optional: true + + '@esbuild/android-arm64@0.27.2': + optional: true + + '@esbuild/android-arm@0.27.2': + optional: true + + '@esbuild/android-x64@0.27.2': + optional: true + + '@esbuild/darwin-arm64@0.27.2': + optional: true + + '@esbuild/darwin-x64@0.27.2': + optional: true + + '@esbuild/freebsd-arm64@0.27.2': + optional: true + + '@esbuild/freebsd-x64@0.27.2': + optional: true + + '@esbuild/linux-arm64@0.27.2': + optional: true + + '@esbuild/linux-arm@0.27.2': + optional: true + + '@esbuild/linux-ia32@0.27.2': + optional: true + + '@esbuild/linux-loong64@0.27.2': + optional: true + + '@esbuild/linux-mips64el@0.27.2': + optional: true + + '@esbuild/linux-ppc64@0.27.2': + optional: true + + '@esbuild/linux-riscv64@0.27.2': + optional: true + + '@esbuild/linux-s390x@0.27.2': + optional: true + + '@esbuild/linux-x64@0.27.2': + optional: true + + '@esbuild/netbsd-arm64@0.27.2': + optional: true + + '@esbuild/netbsd-x64@0.27.2': + optional: true + + '@esbuild/openbsd-arm64@0.27.2': + optional: true + + '@esbuild/openbsd-x64@0.27.2': + optional: true + + '@esbuild/openharmony-arm64@0.27.2': + optional: true + + '@esbuild/sunos-x64@0.27.2': + optional: true + + '@esbuild/win32-arm64@0.27.2': + optional: true + + '@esbuild/win32-ia32@0.27.2': + optional: true + + '@esbuild/win32-x64@0.27.2': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': + dependencies: + eslint: 9.39.2(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.3': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.2': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@faker-js/faker@10.2.0': {} + + '@gerrit0/mini-shiki@3.23.0': + dependencies: + '@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 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@inquirer/external-editor@1.0.3(@types/node@25.0.9)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 25.0.9 + + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + + '@jest/diff-sequences@30.0.1': {} + + '@jest/get-type@30.1.0': {} + + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.47 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.28.6 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.28.6 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@napi-rs/wasm-runtime@0.2.4': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.9.0 + + '@napi-rs/wasm-runtime@1.1.1': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@nx/nx-darwin-arm64@22.3.3': + optional: true + + '@nx/nx-darwin-x64@22.3.3': + optional: true + + '@nx/nx-freebsd-x64@22.3.3': + optional: true + + '@nx/nx-linux-arm-gnueabihf@22.3.3': + optional: true + + '@nx/nx-linux-arm64-gnu@22.3.3': + optional: true + + '@nx/nx-linux-arm64-musl@22.3.3': + optional: true + + '@nx/nx-linux-x64-gnu@22.3.3': + optional: true + + '@nx/nx-linux-x64-musl@22.3.3': + optional: true + + '@nx/nx-win32-arm64-msvc@22.3.3': + optional: true + + '@nx/nx-win32-x64-msvc@22.3.3': + optional: true + + '@oxc-project/types@0.107.0': {} + + '@oxc-project/types@0.112.0': {} + + '@oxc-resolver/binding-android-arm-eabi@11.16.3': + optional: true + + '@oxc-resolver/binding-android-arm64@11.16.3': + optional: true + + '@oxc-resolver/binding-darwin-arm64@11.16.3': + optional: true + + '@oxc-resolver/binding-darwin-x64@11.16.3': + optional: true + + '@oxc-resolver/binding-freebsd-x64@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@11.16.3': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@11.16.3': + optional: true + + '@oxc-resolver/binding-openharmony-arm64@11.16.3': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@11.16.3': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': + optional: true + + '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': + optional: true + + '@oxc-resolver/binding-win32-x64-msvc@11.16.3': + optional: true + + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + + '@rolldown/binding-android-arm64@1.0.0-beta.59': + optional: true + + '@rolldown/binding-android-arm64@1.0.0-rc.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.59': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.3': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.59': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.59': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.59': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.59': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.59': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.59': {} + + '@rolldown/pluginutils@1.0.0-rc.3': {} + + '@rollup/rollup-android-arm-eabi@4.55.1': + optional: true + + '@rollup/rollup-android-arm64@4.55.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.55.1': + optional: true + + '@rollup/rollup-darwin-x64@4.55.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.55.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.55.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.55.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.55.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.55.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.55.1': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.55.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.55.1': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.55.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.55.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.55.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.55.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.55.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.55.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.55.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.55.1': + optional: true + + '@rollup/rollup-openharmony-arm64@4.55.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.55.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.55.1': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.55.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.55.1': + optional: true + + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@sinclair/typebox@0.34.47': {} + + '@standard-schema/spec@1.1.0': {} + + '@stylistic/eslint-plugin@5.7.0(eslint@9.39.2(jiti@2.6.1))': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@typescript-eslint/types': 8.53.0 + eslint: 9.39.2(jiti@2.6.1) + eslint-visitor-keys: 5.0.0 + espree: 11.0.0 + estraverse: 5.3.0 + picomatch: 4.0.3 + + '@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)': + dependencies: + acorn: 8.15.0 + + '@svitejs/changesets-changelog-github-compact@1.2.0': + dependencies: + '@changesets/get-github-info': 0.6.0 + dotenv: 16.6.1 + transitivePeerDependencies: + - encoding + + '@tanstack/eslint-config@0.3.4(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint/js': 9.39.2 + '@stylistic/eslint-plugin': 5.7.0(eslint@9.39.2(jiti@2.6.1)) + eslint: 9.39.2(jiti@2.6.1) + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-n: 17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + globals: 16.5.0 + typescript-eslint: 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + vue-eslint-parser: 10.2.0(eslint@9.39.2(jiti@2.6.1)) + transitivePeerDependencies: + - '@typescript-eslint/utils' + - eslint-import-resolver-node + - supports-color + - typescript + + '@tanstack/typedoc-config@0.3.3(typescript@5.9.3)': + dependencies: + typedoc: 0.28.14(typescript@5.9.3) + typedoc-plugin-frontmatter: 1.3.0(typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3))) + typedoc-plugin-markdown: 4.9.0(typedoc@0.28.14(typescript@5.9.3)) + transitivePeerDependencies: + - typescript + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@tybys/wasm-util@0.9.0': + dependencies: + tslib: 2.8.1 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/json-schema@7.0.15': {} + + '@types/node@12.20.55': {} + + '@types/node@20.19.30': + dependencies: + undici-types: 6.21.0 + + '@types/node@25.0.9': + dependencies: + undici-types: 7.16.0 + + '@types/unist@3.0.3': {} + + '@types/whatwg-mimetype@3.0.2': {} + + '@types/ws@8.18.1': + dependencies: + '@types/node': 25.0.9 + + '@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.53.0 + '@typescript-eslint/type-utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.53.0 + eslint: 9.39.2(jiti@2.6.1) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.53.0 + '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.53.0 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.53.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.3) + '@typescript-eslint/types': 8.53.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.53.0': + dependencies: + '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/visitor-keys': 8.53.0 + + '@typescript-eslint/tsconfig-utils@8.53.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.53.0': {} + + '@typescript-eslint/typescript-estree@8.53.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.53.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.53.0(typescript@5.9.3) + '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/visitor-keys': 8.53.0 + debug: 4.4.3 + minimatch: 9.0.5 + semver: 7.7.3 + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.53.0 + '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.53.0': + dependencies: + '@typescript-eslint/types': 8.53.0 + eslint-visitor-keys: 4.2.1 + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + '@vitest/expect@4.0.17': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.17 + '@vitest/utils': 4.0.17 + chai: 6.2.2 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.17(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 4.0.17 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2) + + '@vitest/pretty-format@4.0.17': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.17': + dependencies: + '@vitest/utils': 4.0.17 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.17': + dependencies: + '@vitest/pretty-format': 4.0.17 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.17': {} + + '@vitest/utils@4.0.17': + dependencies: + '@vitest/pretty-format': 4.0.17 + tinyrainbow: 3.0.3 + + '@yarnpkg/lockfile@1.1.0': {} + + '@yarnpkg/parsers@3.0.2': + dependencies: + js-yaml: 3.14.2 + tslib: 2.8.1 + + '@zkochan/js-yaml@0.0.7': + dependencies: + argparse: 2.0.1 + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansis@4.2.0: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + array-union@2.1.0: {} + + assertion-error@2.0.1: {} + + ast-kit@2.2.0: + dependencies: + '@babel/parser': 7.29.0 + pathe: 2.0.3 + + asynckit@0.4.0: {} + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + axobject-query@4.1.0: {} + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + birpc@4.0.0: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + boolbase@1.0.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + callsites@3.1.0: {} + + chai@6.2.2: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chardet@2.1.1: {} + + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.2.2 + css-what: 6.2.2 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.1.2: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.1 + htmlparser2: 10.0.0 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 7.18.2 + whatwg-mimetype: 4.0.0 + + ci-info@3.9.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.6.1: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comment-parser@1.4.4: {} + + concat-map@0.0.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-what@6.2.2: {} + + dataloader@1.4.0: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-lazy-prop@2.0.0: {} + + defu@6.1.4: {} + + delayed-stream@1.0.0: {} + + detect-indent@6.1.0: {} + + devalue@5.6.2: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.4.7 + + dotenv@16.4.7: {} + + dotenv@16.6.1: {} + + dts-resolver@2.1.3(oxc-resolver@11.16.3): + optionalDependencies: + oxc-resolver: 11.16.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + emoji-regex@8.0.0: {} + + empathic@2.0.0: {} + + encoding-sniffer@0.2.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.18.4: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + enquirer@2.3.6: + dependencies: + ansi-colors: 4.1.3 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@4.5.0: {} + + entities@6.0.1: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-compat-utils@0.5.1(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + semver: 7.7.3 + + eslint-import-context@0.1.9(unrs-resolver@1.11.1): + dependencies: + get-tsconfig: 4.13.0 + stable-hash-x: 0.2.0 + optionalDependencies: + unrs-resolver: 1.11.1 + + eslint-plugin-es-x@7.8.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + eslint: 9.39.2(jiti@2.6.1) + eslint-compat-utils: 0.5.1(eslint@9.39.2(jiti@2.6.1)) + + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@typescript-eslint/types': 8.53.0 + comment-parser: 1.4.4 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + is-glob: 4.0.3 + minimatch: 10.1.1 + semver: 7.7.3 + stable-hash-x: 0.2.0 + unrs-resolver: 1.11.1 + optionalDependencies: + '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + + eslint-plugin-n@17.23.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + enhanced-resolve: 5.18.4 + eslint: 9.39.2(jiti@2.6.1) + eslint-plugin-es-x: 7.8.0(eslint@9.39.2(jiti@2.6.1)) + get-tsconfig: 4.13.0 + globals: 15.15.0 + globrex: 0.1.2 + ignore: 5.3.2 + semver: 7.7.3 + ts-declaration-location: 1.0.7(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.0: {} + + eslint@9.39.2(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + esm-env@1.2.2: {} + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + espree@11.0.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 5.0.0 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrap@2.2.1: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + esutils@2.0.3: {} + + expect-type@1.3.0: {} + + extendable-error@0.1.7: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat@5.0.2: {} + + flatted@3.3.3: {} + + follow-redirects@1.15.11: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formatly@0.3.0: + dependencies: + fd-package-json: 2.0.0 + + front-matter@4.0.2: + dependencies: + js-yaml: 3.14.2 + + fs-constants@1.0.0: {} + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-tsconfig@4.13.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@15.15.0: {} + + globals@16.5.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globrex@0.1.2: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + happy-dom@20.3.1: + dependencies: + '@types/node': 20.19.30 + '@types/whatwg-mimetype': 3.0.2 + '@types/ws': 8.18.1 + whatwg-mimetype: 3.0.0 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hookable@6.0.1: {} + + html-link-extractor@1.0.5: + dependencies: + cheerio: 1.1.2 + + htmlparser2@10.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 6.0.1 + + human-id@4.1.3: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-without-cache@0.2.5: {} + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-interactive@1.0.0: {} + + is-number@7.0.0: {} + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-unicode-supported@0.1.0: {} + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isexe@2.0.0: {} + + jest-diff@30.2.0: + dependencies: + '@jest/diff-sequences': 30.0.1 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + pretty-format: 30.2.0 + + jiti@2.6.1: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonc-parser@3.2.0: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + knip@5.81.0(@types/node@25.0.9)(typescript@5.9.3): + dependencies: + '@nodelib/fs.walk': 1.2.8 + '@types/node': 25.0.9 + fast-glob: 3.3.3 + formatly: 0.3.0 + jiti: 2.6.1 + js-yaml: 4.1.1 + minimist: 1.2.8 + oxc-resolver: 11.16.3 + picocolors: 1.1.1 + picomatch: 4.0.3 + smol-toml: 1.6.0 + strip-json-comments: 5.0.3 + typescript: 5.9.3 + zod: 4.3.5 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lines-and-columns@2.0.3: {} + + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + locate-character@3.0.0: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash.startcase@4.4.0: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + lunr@2.3.9: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + markdown-it@14.1.1: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + markdown-link-extractor@4.0.3: + dependencies: + html-link-extractor: 1.0.5 + marked: 17.0.1 + + marked@17.0.1: {} + + math-intrinsics@1.1.0: {} + + mdurl@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-fn@2.1.0: {} + + minimatch@10.1.1: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: {} + + mri@1.2.0: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + napi-postinstall@0.3.4: {} + + natural-compare@1.4.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-machine-id@1.1.12: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nx@22.3.3: + dependencies: + '@napi-rs/wasm-runtime': 0.2.4 + '@yarnpkg/lockfile': 1.1.0 + '@yarnpkg/parsers': 3.0.2 + '@zkochan/js-yaml': 0.0.7 + axios: 1.13.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + cliui: 8.0.1 + dotenv: 16.4.7 + dotenv-expand: 11.0.7 + enquirer: 2.3.6 + figures: 3.2.0 + flat: 5.0.2 + front-matter: 4.0.2 + ignore: 7.0.5 + jest-diff: 30.2.0 + jsonc-parser: 3.2.0 + lines-and-columns: 2.0.3 + minimatch: 9.0.3 + node-machine-id: 1.1.12 + npm-run-path: 4.0.1 + open: 8.4.2 + ora: 5.3.0 + resolve.exports: 2.0.3 + semver: 7.7.3 + string-width: 4.2.3 + tar-stream: 2.2.0 + tmp: 0.2.5 + tree-kill: 1.2.2 + tsconfig-paths: 4.2.0 + tslib: 2.8.1 + yaml: 2.8.2 + yargs: 17.7.2 + yargs-parser: 21.1.1 + optionalDependencies: + '@nx/nx-darwin-arm64': 22.3.3 + '@nx/nx-darwin-x64': 22.3.3 + '@nx/nx-freebsd-x64': 22.3.3 + '@nx/nx-linux-arm-gnueabihf': 22.3.3 + '@nx/nx-linux-arm64-gnu': 22.3.3 + '@nx/nx-linux-arm64-musl': 22.3.3 + '@nx/nx-linux-x64-gnu': 22.3.3 + '@nx/nx-linux-x64-musl': 22.3.3 + '@nx/nx-win32-arm64-msvc': 22.3.3 + '@nx/nx-win32-x64-msvc': 22.3.3 + transitivePeerDependencies: + - debug + + obug@2.1.1: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@5.3.0: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + is-interactive: 1.0.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + outdent@0.5.0: {} + + oxc-resolver@11.16.3: + optionalDependencies: + '@oxc-resolver/binding-android-arm-eabi': 11.16.3 + '@oxc-resolver/binding-android-arm64': 11.16.3 + '@oxc-resolver/binding-darwin-arm64': 11.16.3 + '@oxc-resolver/binding-darwin-x64': 11.16.3 + '@oxc-resolver/binding-freebsd-x64': 11.16.3 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.16.3 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.16.3 + '@oxc-resolver/binding-linux-arm64-gnu': 11.16.3 + '@oxc-resolver/binding-linux-arm64-musl': 11.16.3 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.16.3 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.16.3 + '@oxc-resolver/binding-linux-riscv64-musl': 11.16.3 + '@oxc-resolver/binding-linux-s390x-gnu': 11.16.3 + '@oxc-resolver/binding-linux-x64-gnu': 11.16.3 + '@oxc-resolver/binding-linux-x64-musl': 11.16.3 + '@oxc-resolver/binding-openharmony-arm64': 11.16.3 + '@oxc-resolver/binding-wasm32-wasi': 11.16.3 + '@oxc-resolver/binding-win32-arm64-msvc': 11.16.3 + '@oxc-resolver/binding-win32-ia32-msvc': 11.16.3 + '@oxc-resolver/binding-win32-x64-msvc': 11.16.3 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-try@2.2.0: {} + + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.11 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.3.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.3.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pify@4.0.1: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier-plugin-svelte@3.4.1(prettier@3.8.0)(svelte@5.46.4): + dependencies: + prettier: 3.8.0 + svelte: 5.46.4 + + prettier@2.8.8: {} + + prettier@3.8.0: {} + + pretty-format@30.2.0: + dependencies: + '@jest/schemas': 30.0.5 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + proxy-from-env@1.1.0: {} + + punycode.js@2.3.1: {} + + punycode@2.3.1: {} + + quansync@0.2.11: {} + + quansync@1.0.0: {} + + queue-microtask@1.2.3: {} + + react-is@18.3.1: {} + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.2 + pify: 4.0.1 + strip-bom: 3.0.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + require-directory@2.1.1: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve.exports@2.0.3: {} + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + reusify@1.1.0: {} + + rolldown-plugin-dts@0.20.0(oxc-resolver@11.16.3)(rolldown@1.0.0-beta.59)(typescript@5.9.3): + dependencies: + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + ast-kit: 2.2.0 + birpc: 4.0.0 + dts-resolver: 2.1.3(oxc-resolver@11.16.3) + get-tsconfig: 4.13.0 + obug: 2.1.1 + rolldown: 1.0.0-beta.59 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - oxc-resolver + + rolldown@1.0.0-beta.59: + dependencies: + '@oxc-project/types': 0.107.0 + '@rolldown/pluginutils': 1.0.0-beta.59 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.59 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.59 + '@rolldown/binding-darwin-x64': 1.0.0-beta.59 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.59 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.59 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.59 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.59 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.59 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.59 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.59 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.59 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.59 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.59 + + rolldown@1.0.0-rc.3: + dependencies: + '@oxc-project/types': 0.112.0 + '@rolldown/pluginutils': 1.0.0-rc.3 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.3 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.3 + '@rolldown/binding-darwin-x64': 1.0.0-rc.3 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.3 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.3 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.3 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.3 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.3 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.3 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.3 + + rollup@4.55.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.55.1 + '@rollup/rollup-android-arm64': 4.55.1 + '@rollup/rollup-darwin-arm64': 4.55.1 + '@rollup/rollup-darwin-x64': 4.55.1 + '@rollup/rollup-freebsd-arm64': 4.55.1 + '@rollup/rollup-freebsd-x64': 4.55.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.55.1 + '@rollup/rollup-linux-arm-musleabihf': 4.55.1 + '@rollup/rollup-linux-arm64-gnu': 4.55.1 + '@rollup/rollup-linux-arm64-musl': 4.55.1 + '@rollup/rollup-linux-loong64-gnu': 4.55.1 + '@rollup/rollup-linux-loong64-musl': 4.55.1 + '@rollup/rollup-linux-ppc64-gnu': 4.55.1 + '@rollup/rollup-linux-ppc64-musl': 4.55.1 + '@rollup/rollup-linux-riscv64-gnu': 4.55.1 + '@rollup/rollup-linux-riscv64-musl': 4.55.1 + '@rollup/rollup-linux-s390x-gnu': 4.55.1 + '@rollup/rollup-linux-x64-gnu': 4.55.1 + '@rollup/rollup-linux-x64-musl': 4.55.1 + '@rollup/rollup-openbsd-x64': 4.55.1 + '@rollup/rollup-openharmony-arm64': 4.55.1 + '@rollup/rollup-win32-arm64-msvc': 4.55.1 + '@rollup/rollup-win32-ia32-msvc': 4.55.1 + '@rollup/rollup-win32-x64-gnu': 4.55.1 + '@rollup/rollup-win32-x64-msvc': 4.55.1 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + semver@7.7.3: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + sherif-darwin-arm64@1.10.0: + optional: true + + sherif-darwin-x64@1.10.0: + optional: true + + sherif-linux-arm64-musl@1.10.0: + optional: true + + sherif-linux-arm64@1.10.0: + optional: true + + sherif-linux-x64-musl@1.10.0: + optional: true + + sherif-linux-x64@1.10.0: + optional: true + + sherif-windows-arm64@1.10.0: + optional: true + + sherif-windows-x64@1.10.0: + optional: true + + sherif@1.10.0: + optionalDependencies: + sherif-darwin-arm64: 1.10.0 + sherif-darwin-x64: 1.10.0 + sherif-linux-arm64: 1.10.0 + sherif-linux-arm64-musl: 1.10.0 + sherif-linux-x64: 1.10.0 + sherif-linux-x64-musl: 1.10.0 + sherif-windows-arm64: 1.10.0 + sherif-windows-x64: 1.10.0 + + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + slash@3.0.0: {} + + smol-toml@1.6.0: {} + + source-map-js@1.2.1: {} + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + sprintf-js@1.0.3: {} + + stable-hash-x@0.2.0: {} + + stackback@0.0.2: {} + + std-env@3.10.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@3.0.0: {} + + strip-json-comments@3.1.1: {} + + strip-json-comments@5.0.3: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + svelte@5.46.4: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) + '@types/estree': 1.0.8 + acorn: 8.15.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.6.2 + esm-env: 1.2.2 + esrap: 2.2.1 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + + tapable@2.3.0: {} + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + term-size@2.2.1: {} + + tinybench@2.9.0: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinyrainbow@3.0.3: {} + + tmp@0.2.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tr46@0.0.3: {} + + tree-kill@1.2.2: {} + + ts-api-utils@2.4.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + ts-declaration-location@1.0.7(typescript@5.9.3): + dependencies: + picomatch: 4.0.3 + typescript: 5.9.3 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tsdown@0.19.0(oxc-resolver@11.16.3)(typescript@5.9.3): + dependencies: + ansis: 4.2.0 + cac: 6.7.14 + defu: 6.1.4 + empathic: 2.0.0 + hookable: 6.0.1 + import-without-cache: 0.2.5 + obug: 2.1.1 + picomatch: 4.0.3 + rolldown: 1.0.0-beta.59 + rolldown-plugin-dts: 0.20.0(oxc-resolver@11.16.3)(rolldown@1.0.0-beta.59)(typescript@5.9.3) + semver: 7.7.3 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + unconfig-core: 7.5.0 + unrun: 0.2.27 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@ts-macro/tsc' + - '@typescript/native-preview' + - oxc-resolver + - synckit + - vue-tsc + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typedoc-plugin-frontmatter@1.3.0(typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3))): + dependencies: + typedoc-plugin-markdown: 4.9.0(typedoc@0.28.14(typescript@5.9.3)) + yaml: 2.8.2 + + typedoc-plugin-markdown@4.9.0(typedoc@0.28.14(typescript@5.9.3)): + dependencies: + typedoc: 0.28.14(typescript@5.9.3) + + typedoc@0.28.14(typescript@5.9.3): + dependencies: + '@gerrit0/mini-shiki': 3.23.0 + lunr: 2.3.9 + markdown-it: 14.1.1 + minimatch: 9.0.5 + typescript: 5.9.3 + yaml: 2.8.2 + + typescript-eslint@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.53.0(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.53.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + typescript@5.9.3: {} + + uc.micro@2.1.0: {} + + unconfig-core@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + + undici-types@6.21.0: {} + + undici-types@7.16.0: {} + + undici@7.18.2: {} + + universalify@0.1.2: {} + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + unrun@0.2.27: + dependencies: + rolldown: 1.0.0-rc.3 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.55.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.0.9 + fsevents: 2.3.3 + jiti: 2.6.1 + yaml: 2.8.2 + + vitest@4.0.17(@types/node@25.0.9)(happy-dom@20.3.1)(jiti@2.6.1)(yaml@2.8.2): + dependencies: + '@vitest/expect': 4.0.17 + '@vitest/mocker': 4.0.17(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2)) + '@vitest/pretty-format': 4.0.17 + '@vitest/runner': 4.0.17 + '@vitest/snapshot': 4.0.17 + '@vitest/spy': 4.0.17 + '@vitest/utils': 4.0.17 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.0.9 + happy-dom: 20.3.1 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + + walk-up-path@4.0.0: {} + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webidl-conversions@3.0.1: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@3.0.0: {} + + whatwg-mimetype@4.0.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + ws@8.19.0: {} + + y18n@5.0.8: {} + + yaml@2.8.2: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + zimmerframe@1.1.4: {} + + zod@4.3.5: {} diff --git a/scripts/generate-docs.ts b/scripts/generate-docs.ts index 91670a6c..8d9ccdae 100644 --- a/scripts/generate-docs.ts +++ b/scripts/generate-docs.ts @@ -1,20 +1,20 @@ -import { resolve } from 'node:path' -import { fileURLToPath } from 'node:url' -import { generateReferenceDocs } from '@tanstack/typedoc-config' - -const __dirname = fileURLToPath(new URL('.', import.meta.url)) - -await generateReferenceDocs({ - packages: [ - { - name: 'intent', - entryPoints: [resolve(__dirname, '../packages/intent/src/index.ts')], - tsconfig: resolve(__dirname, '../packages/intent/tsconfig.docs.json'), - outputDir: resolve(__dirname, '../docs/intent'), - }, - ], -}) - -console.log('\n✅ All markdown files have been processed!') - -process.exit(0) +import { resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import { generateReferenceDocs } from '@tanstack/typedoc-config' + +const __dirname = fileURLToPath(new URL('.', import.meta.url)) + +await generateReferenceDocs({ + packages: [ + { + name: 'intent', + entryPoints: [resolve(__dirname, '../packages/intent/src/index.ts')], + tsconfig: resolve(__dirname, '../packages/intent/tsconfig.docs.json'), + outputDir: resolve(__dirname, '../docs/intent'), + }, + ], +}) + +console.log('\n✅ All markdown files have been processed!') + +process.exit(0) diff --git a/scripts/validate-skills.ts b/scripts/validate-skills.ts index b90bd7c2..a4941c48 100644 --- a/scripts/validate-skills.ts +++ b/scripts/validate-skills.ts @@ -1,203 +1,203 @@ -import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs' -import { join, relative, sep } from 'node:path' -import { parse as parseYaml } from 'yaml' - -// ── Types ── - -interface SkillFrontmatter { - name: string - description: string - type?: string - library?: string - framework?: string - library_version?: string - requires?: Array - sources?: Array -} - -interface ValidationError { - file: string - message: string -} - -// ── Constants ── - -const skillsArg = process.argv[2] -const SKILLS_DIR = skillsArg - ? join(process.cwd(), skillsArg) - : join(process.cwd(), 'skills') -const MAX_LINES = 500 - -const PROHIBITED_PATTERNS: Array<{ pattern: RegExp; description: string }> = [ - { - pattern: /(?:npm|yarn|pnpm|bun)\s+(?:install|add|i)\s/i, - description: 'Install instructions', - }, - { - pattern: /(?:curl|wget|fetch)\s+https?:\/\//i, - description: 'Instructions to fetch external URLs at runtime', - }, -] - -const ALLOWED_SHELL_COMMANDS = [ - 'intent list', - 'intent feedback', - 'npm install @tanstack/', - 'npx intent', -] - -// ── Helpers ── - -function findSkillFiles(dir: string): Array { - const files: Array = [] - if (!existsSync(dir)) return files - - for (const entry of readdirSync(dir)) { - const fullPath = join(dir, entry) - const stat = statSync(fullPath) - if (stat.isDirectory()) { - files.push(...findSkillFiles(fullPath)) - } else if (entry === 'SKILL.md') { - files.push(fullPath) - } - } - return files -} - -function extractFrontmatter( - content: string, -): { frontmatter: SkillFrontmatter; body: string } | null { - const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/) - if (!match?.[1]) return null - - try { - const frontmatter = parseYaml(match[1]) as SkillFrontmatter - return { frontmatter, body: match[2] ?? '' } - } catch { - return null - } -} - -function skillPathFromFile(filePath: string): string { - const rel = relative(SKILLS_DIR, filePath) - return rel - .replace(/[/\\]SKILL\.md$/, '') - .split(sep) - .join('/') -} - -// ── Validators ── - -function validateFrontmatter( - filePath: string, - frontmatter: SkillFrontmatter, -): Array { - const errors: Array = [] - const rel = relative(process.cwd(), filePath) - - if (!frontmatter.name) { - errors.push({ file: rel, message: 'Missing required field: name' }) - } - - if (!frontmatter.description) { - errors.push({ file: rel, message: 'Missing required field: description' }) - } - - if (frontmatter.name) { - const expectedPath = skillPathFromFile(filePath) - if (frontmatter.name !== expectedPath) { - errors.push({ - file: rel, - message: `name "${frontmatter.name}" does not match directory path "${expectedPath}"`, - }) - } - } - - if (frontmatter.type === 'framework' && !frontmatter.requires?.length) { - errors.push({ - file: rel, - message: 'Framework skills must have a "requires" field', - }) - } - - return errors -} - -function validateContent( - filePath: string, - content: string, - body: string, -): Array { - const errors: Array = [] - const rel = relative(process.cwd(), filePath) - - const lineCount = content.split(/\r?\n/).length - if (lineCount > MAX_LINES) { - errors.push({ - file: rel, - message: `Exceeds ${MAX_LINES} line limit (${lineCount} lines)`, - }) - } - - for (const { pattern, description } of PROHIBITED_PATTERNS) { - for (const line of body.split(/\r?\n/)) { - if (pattern.test(line)) { - const isAllowed = ALLOWED_SHELL_COMMANDS.some((cmd) => - line.includes(cmd), - ) - if (!isAllowed) { - errors.push({ - file: rel, - message: `Prohibited content: ${description} — "${line.trim().slice(0, 80)}"`, - }) - break - } - } - } - } - - return errors -} - -// ── Main ── - -function main(): void { - const errors: Array = [] - - console.log(`Validating skills in: ${SKILLS_DIR}`) - - const skillFiles = findSkillFiles(SKILLS_DIR) - - if (skillFiles.length === 0) { - console.log('No SKILL.md files found — nothing to validate') - process.exit(0) - } - - for (const filePath of skillFiles) { - const content = readFileSync(filePath, 'utf-8') - const parsed = extractFrontmatter(content) - - const rel = relative(process.cwd(), filePath) - - if (!parsed) { - errors.push({ file: rel, message: 'Missing or invalid frontmatter' }) - continue - } - - errors.push(...validateFrontmatter(filePath, parsed.frontmatter)) - errors.push(...validateContent(filePath, content, parsed.body)) - } - - if (errors.length > 0) { - console.error(`\n❌ Validation failed with ${errors.length} error(s):\n`) - for (const { file, message } of errors) { - console.error(` ${file}: ${message}`) - } - console.error('') - process.exit(1) - } - - console.log(`✅ Validated ${skillFiles.length} skill files — all passed`) -} - -main() +import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs' +import { join, relative, sep } from 'node:path' +import { parse as parseYaml } from 'yaml' + +// ── Types ── + +interface SkillFrontmatter { + name: string + description: string + type?: string + library?: string + framework?: string + library_version?: string + requires?: Array + sources?: Array +} + +interface ValidationError { + file: string + message: string +} + +// ── Constants ── + +const skillsArg = process.argv[2] +const SKILLS_DIR = skillsArg + ? join(process.cwd(), skillsArg) + : join(process.cwd(), 'skills') +const MAX_LINES = 500 + +const PROHIBITED_PATTERNS: Array<{ pattern: RegExp; description: string }> = [ + { + pattern: /(?:npm|yarn|pnpm|bun)\s+(?:install|add|i)\s/i, + description: 'Install instructions', + }, + { + pattern: /(?:curl|wget|fetch)\s+https?:\/\//i, + description: 'Instructions to fetch external URLs at runtime', + }, +] + +const ALLOWED_SHELL_COMMANDS = [ + 'intent list', + 'intent feedback', + 'npm install @tanstack/', + 'npx intent', +] + +// ── Helpers ── + +function findSkillFiles(dir: string): Array { + const files: Array = [] + if (!existsSync(dir)) return files + + for (const entry of readdirSync(dir)) { + const fullPath = join(dir, entry) + const stat = statSync(fullPath) + if (stat.isDirectory()) { + files.push(...findSkillFiles(fullPath)) + } else if (entry === 'SKILL.md') { + files.push(fullPath) + } + } + return files +} + +function extractFrontmatter( + content: string, +): { frontmatter: SkillFrontmatter; body: string } | null { + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/) + if (!match?.[1]) return null + + try { + const frontmatter = parseYaml(match[1]) as SkillFrontmatter + return { frontmatter, body: match[2] ?? '' } + } catch { + return null + } +} + +function skillPathFromFile(filePath: string): string { + const rel = relative(SKILLS_DIR, filePath) + return rel + .replace(/[/\\]SKILL\.md$/, '') + .split(sep) + .join('/') +} + +// ── Validators ── + +function validateFrontmatter( + filePath: string, + frontmatter: SkillFrontmatter, +): Array { + const errors: Array = [] + const rel = relative(process.cwd(), filePath) + + if (!frontmatter.name) { + errors.push({ file: rel, message: 'Missing required field: name' }) + } + + if (!frontmatter.description) { + errors.push({ file: rel, message: 'Missing required field: description' }) + } + + if (frontmatter.name) { + const expectedPath = skillPathFromFile(filePath) + if (frontmatter.name !== expectedPath) { + errors.push({ + file: rel, + message: `name "${frontmatter.name}" does not match directory path "${expectedPath}"`, + }) + } + } + + if (frontmatter.type === 'framework' && !frontmatter.requires?.length) { + errors.push({ + file: rel, + message: 'Framework skills must have a "requires" field', + }) + } + + return errors +} + +function validateContent( + filePath: string, + content: string, + body: string, +): Array { + const errors: Array = [] + const rel = relative(process.cwd(), filePath) + + const lineCount = content.split(/\r?\n/).length + if (lineCount > MAX_LINES) { + errors.push({ + file: rel, + message: `Exceeds ${MAX_LINES} line limit (${lineCount} lines)`, + }) + } + + for (const { pattern, description } of PROHIBITED_PATTERNS) { + for (const line of body.split(/\r?\n/)) { + if (pattern.test(line)) { + const isAllowed = ALLOWED_SHELL_COMMANDS.some((cmd) => + line.includes(cmd), + ) + if (!isAllowed) { + errors.push({ + file: rel, + message: `Prohibited content: ${description} — "${line.trim().slice(0, 80)}"`, + }) + break + } + } + } + } + + return errors +} + +// ── Main ── + +function main(): void { + const errors: Array = [] + + console.log(`Validating skills in: ${SKILLS_DIR}`) + + const skillFiles = findSkillFiles(SKILLS_DIR) + + if (skillFiles.length === 0) { + console.log('No SKILL.md files found — nothing to validate') + process.exit(0) + } + + for (const filePath of skillFiles) { + const content = readFileSync(filePath, 'utf-8') + const parsed = extractFrontmatter(content) + + const rel = relative(process.cwd(), filePath) + + if (!parsed) { + errors.push({ file: rel, message: 'Missing or invalid frontmatter' }) + continue + } + + errors.push(...validateFrontmatter(filePath, parsed.frontmatter)) + errors.push(...validateContent(filePath, content, parsed.body)) + } + + if (errors.length > 0) { + console.error(`\n❌ Validation failed with ${errors.length} error(s):\n`) + for (const { file, message } of errors) { + console.error(` ${file}: ${message}`) + } + console.error('') + process.exit(1) + } + + console.log(`✅ Validated ${skillFiles.length} skill files — all passed`) +} + +main() diff --git a/tsconfig.json b/tsconfig.json index c62fbb91..9c64a438 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,29 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "allowJs": true, - "allowSyntheticDefaultImports": true, - "allowUnreachableCode": false, - "allowUnusedLabels": false, - "checkJs": true, - "declaration": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "isolatedModules": true, - "lib": ["DOM", "DOM.Iterable", "ES2022"], - "module": "ESNext", - "moduleResolution": "Bundler", - "noEmit": true, - "noImplicitReturns": true, - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2020", - "noErrorTruncation": true - }, - "include": ["scripts", "*.config.*", "vitest.workspace.js"], - "exclude": ["eslint.config.js"] -} +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "checkJs": true, + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true, + "noImplicitReturns": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2020", + "noErrorTruncation": true + }, + "include": ["scripts", "*.config.*", "vitest.workspace.js"], + "exclude": ["eslint.config.js"] +} diff --git a/vitest.workspace.js b/vitest.workspace.js index 70deda66..a861a380 100644 --- a/vitest.workspace.js +++ b/vitest.workspace.js @@ -1,7 +1,7 @@ -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - projects: ['./packages/intent/vitest.config.ts'], - }, -}) +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + projects: ['./packages/intent/vitest.config.ts'], + }, +}) From c35bae00a35698af13b1821515638438a475a87b Mon Sep 17 00:00:00 2001 From: LadyBluenotes Date: Thu, 5 Mar 2026 08:56:47 -0800 Subject: [PATCH 5/6] feat: enhance SKILL.md with clarifications on package ownership and skill generation process --- .../intent/meta/domain-discovery/SKILL.md | 796 +++++++++++++++ packages/intent/meta/generate-skill/SKILL.md | 446 +++++++++ packages/intent/meta/tree-generator/SKILL.md | 918 ++++++++++++++++++ 3 files changed, 2160 insertions(+) diff --git a/packages/intent/meta/domain-discovery/SKILL.md b/packages/intent/meta/domain-discovery/SKILL.md index 3321bd3d..470dfd8f 100644 --- a/packages/intent/meta/domain-discovery/SKILL.md +++ b/packages/intent/meta/domain-discovery/SKILL.md @@ -1,3 +1,4 @@ +<<<<<<< HEAD:packages/intent/meta/domain-discovery/SKILL.md --- name: skill-domain-discovery description: > @@ -892,3 +893,798 @@ place for later steps to complete. Do not submit feedback yet. Tell the maintainer to carry this draft forward to the next meta skill step. +======= +--- +name: skill-domain-discovery +description: > + Analyze library documentation and source code, then interview maintainers + to discover capability domains and task-focused skills for AI coding + agents. Activate when creating skills for a new library, organizing + existing documentation into skill categories, or when a maintainer wants + help deciding how to structure their library's agent-facing knowledge. + Produces a domain_map.yaml and skill_spec.md that feed directly into + the skill-tree-generator skill. +metadata: + version: '3.0' + category: meta-tooling + output_artifacts: + - skills/_artifacts/domain_map.yaml + - skills/_artifacts/skill_spec.md + skills: + - tree-generator +--- + +# Domain Discovery & Maintainer Interview + +You are extracting domain knowledge for a library to produce a structured +domain map. Your job is not to summarize documentation — it is to build a +deep understanding of the library first, then use that understanding to +surface the implicit knowledge that maintainers carry but docs miss. + +The output is a set of **task-focused skills** — each one matching a +specific developer moment ("implement a proxy", "set up auth", "audit +before launch"). Domains are an intermediate conceptual grouping you use +during analysis; the final skills emerge from the intersection of domains +and developer tasks. + +There are five phases. Always run them in order. + +1. **Quick scan** — orient yourself (autonomous) +2. **High-level interview** — extract the maintainer's task map +3. **Deep read** — fill in failure modes and detail (autonomous) +4. **Detail interview** — gap-targeted questions, AI-agent failures +5. **Finalize artifacts** + +### Hard rules — interview phases are mandatory and interactive + +These rules override any other reasoning. No exceptions. + +1. **Phases 2 and 4 are interactive interviews conducted with the + maintainer.** You must ask the questions specified in each sub-section + and wait for the maintainer's response before continuing. Documentation, + source code, and other automated analysis are NOT substitutes for the + maintainer's answers. +2. **Every question in Phases 2 and 4 must be asked as an open-ended + question and sent as a message to the maintainer.** You must then + STOP and WAIT for their reply. Do not answer your own questions. Do + not infer answers from documentation. Do not skip questions because + you believe you already know the answer. +3. **Do not convert open-ended questions into multiple-choice, + yes/no, or confirmation prompts.** The question templates in each + sub-section are open-ended by design. Present them as open-ended + questions. The maintainer's unprompted answers surface knowledge that + pre-structured options suppress. +4. **Minimum question counts are enforced.** Each sub-section specifies + a question count range (e.g. "2–4 questions"). You must ask at least + the minimum number. Asking zero questions in any sub-section is a + protocol violation. +5. **STOP gates are mandatory.** At the boundaries marked `── STOP ──` + below, you must halt execution and wait for the maintainer's response + or acknowledgment before proceeding. Do not continue past a STOP gate + in the same message. +6. **If the maintainer asks to skip an interview phase**, explain the + value of the phase and what will be lost. Proceed with skipping only + if they confirm a second time. +7. **Rich documentation makes interviews MORE valuable, not less.** + When docs are comprehensive, the interview surfaces what docs miss: + implicit knowledge, AI-specific failure modes, undocumented tradeoffs, + and the maintainer's prioritization of what matters most. Never + rationalize skipping interviews because documentation is thorough. + +--- + +## Phase 1 — Quick scan (autonomous, ~10 minutes) + +Orient yourself in the library. You are building a structural map, not +reading exhaustively yet. + +### 1a — Read orientation material + +1. **README** — vocabulary, mental model, what the library does +2. **Getting started / quickstart** — the happy path +3. **Package structure** — if monorepo, identify which packages are + client-facing vs internal. Focus on the 2–3 packages most relevant + to skill consumers (usually client SDKs and primary framework adapters) +4. **AGENTS.md or .cursorrules** — if the library already has agent + guidance, read it. This is high-signal for what the maintainer + considers important + +### 1b — Note initial impressions + +Log (but do not group yet): + +- What the library does in one sentence +- The core abstractions a developer interacts with +- Which frameworks it supports +- Any existing skill files, agent configs, or playbooks +- Whether the library is a monorepo and which packages matter +- Peer dependency constraints — read `peerDependencies` and + `peerDependenciesMeta` from each client-facing package.json to + understand version ranges and optional integrations early + +Present your initial impressions to the maintainer as a brief summary +(3–5 bullets). This orients them on what you found and primes them for +the interview. + +**── STOP ── Do not proceed to Phase 2 until the maintainer has +acknowledged your summary or responded.** + +--- + +## Phase 2 — High-level interview (interactive — requires maintainer) + +The maintainer's mental model of developer tasks IS the skill map. Your +job in this phase is to extract it — not to propose your own structure. + +You must ask the questions below to the maintainer and wait for their +responses. Do not infer answers from documentation or source code. + +### Rules for Phase 2 + +1. One topic per message for open-ended questions. You may batch 2–3 + yes/no or short-confirmation questions together. +2. Ask each question as written (you may adapt phrasing to context, but + keep questions open-ended — never convert to multiple-choice). +3. Wait for the maintainer's response after each question before asking + the next. +4. Take notes silently. Do not summarize back unless asked. +5. If the maintainer gives a short answer, probe deeper before moving on. + +### 2a — Developer tasks (2–4 questions) + +Start with the maintainer's view of what developers do: + +> "Walk me through what a developer actually does with your library — +> not the elevator pitch, but the tasks they come to you for help with, +> from first install through production." + +Follow up to enumerate distinct tasks: + +> "If you listed every distinct thing a developer asks an agent to help +> with using your library, what would that list look like? I'm thinking +> things like 'set up the client', 'implement auth', 'debug sync issues' +> — each one a separate moment where they'd want focused guidance." + +For monorepo libraries, also ask about cross-package tasks: + +> "Are there tasks that touch multiple packages in your monorepo? For +> example, a getting-started flow that requires imports from both the +> client and server packages? Since skills ship inside each package, +> I need to know which package should own cross-cutting skills and +> which other packages they reference." + +### 2b — Developer journeys (1–2 questions) + +Surface lifecycle/journey skills that cross-cut task areas: + +> "Are there developer journeys that cut across multiple features? +> For example: a getting-started guide, a go-to-production checklist, +> a migrate-from-v4 walkthrough. Which of these exist in your docs +> or would be valuable as standalone skills?" + +### 2c — Composition and ecosystem (1–2 questions) + +> "Which other libraries does yours compose with most often? Are there +> integration patterns important enough to warrant their own skill — +> for example, using your library with [framework/ORM/router]?" + +### 2d — Confirm initial skill map + +Synthesize what you heard into a proposed skill list and present it: + +> "Based on what you've told me, here's my proposed skill list: +> [enumerate skills with one-line descriptions]. Does this match how +> you think about your library? What would you add, remove, or rename?" + +**── STOP ── Do not proceed to Phase 3 until the maintainer has +reviewed and confirmed (or corrected) the skill list.** + +--- + +## Phase 3 — Deep read (autonomous) + +You now have the maintainer's task map. Read docs and source to fill +each skill area with concrete content — failure modes, code patterns, +gotchas. + +### Reading order + +Read in this order. Each step builds context for the next. + +Before starting, list every file in the docs directory (and subdirectories). +Use this list as a checklist — every narrative file must be read. Do not +sample a subset and extrapolate. + +1. **Every narrative guide** — the how-to content, not API reference tables. + Read every guide file, not a representative sample. +2. **Migration guides** — highest-yield source for failure modes; every + breaking change is exactly what agents trained on older versions produce +3. **API reference** — scan for exports, type signatures, option shapes +4. **Changelog for major versions** — API renames, removed exports, + behavioral changes +5. **GitHub issues and discussions** — scan for frequently reported + confusion, common misunderstandings, recurring questions. Also look + for what users are implicitly arguing for architecturally — not just + "people are confused about X" but "users keep expecting X to work + like Y, which reveals a tension between [design force] and [design force]." + If no web access, check for FAQ.md, TROUBLESHOOTING.md, or docs/faq + as proxies. +6. **Source code** — verify ambiguities from docs, check defaults, find + assertions and invariant checks. For monorepos, read the 2–3 core + packages deeply. For adapter packages, read one representative adapter + deeply, then scan others for deviations from the pattern. + +### What to log + +Produce a flat concept inventory. One item per line. No grouping yet. + +Log every: + +- Named concept, abstraction, or lifecycle stage +- Public export: function, hook, class, type, constant +- Configuration key, its type, and its default value +- Constraint or invariant (especially any enforced by `throw` or assertion) +- Doc callout: any "note", "warning", "caution", "important", "avoid", "do not" +- Dual API: any place the library has two ways to do the same thing (old/new, + verbose/shorthand, lower-level/higher-level) +- Environment branch: any place behavior depends on SSR/CSR, dev/prod, + framework, bundler, or config flag +- Type gap: any type documented as accepting X but source shows X | Y or + rejects a subtype of X +- Source assertion: any `if (!x) throw`, `invariant()`, or `assert()` with + the error message text + +### What to extract from migration guides specifically + +For each breaking change between major versions: + +``` +Old pattern: [code that agents trained on older versions will produce] +New pattern: [current correct code] +What changed: [one sentence — the specific mechanism] +Version boundary: [e.g. "v4 → v5"] +``` + +These become high-priority failure modes. + +### 3a — Group concepts into domains + +Move concept inventory items into groups. Two items belong together when: + +- A developer reasons about them together when solving a problem +- Solving one correctly requires understanding how the other works +- They share a lifecycle, configuration scope, or architectural tradeoff +- Getting one wrong tends to produce bugs in the other + +Target 4–7 domains. These are conceptual groupings, not the final skills. + +Do not create a group for: + +- A single hook, function, or class +- A single doc or reference page +- "Miscellaneous", "Advanced", or "Other" +- Configuration knobs that only affect another group's behavior + +Name each domain as work being performed, not what the library provides. + +### 3b — Map domains × tasks → skills + +Merge your conceptual domains with the maintainer's task list from +Phase 2. Each skill should match a specific developer moment while +carrying the conceptual depth of its parent domain(s). + +A skill is well-shaped when: + +- A developer would ask for it by name ("help me set up sync") +- It covers enough for the agent to complete the task end-to-end +- It doesn't require loading 3 other skills to be useful + +Some domains produce multiple skills (a broad domain like "data access" +might yield "live-queries", "mutations", "offline-sync"). Some tasks +span domains (a "go-live" checklist touches security, performance, and +configuration). Both are fine. + +Also consider: + +- **Lifecycle/journey skills** — if the library's docs include a + quickstart guide, go-to-production checklist, or migration path, + suggest these as standalone skills. Don't force them if the docs + don't have the material. +- **Composition skills** — when peer deps or examples show consistent + co-usage with another library, output a full skill for the + integration, not a footnote on a domain. + +### 3c — Flag subsystems within skills + +Check each skill area for internal diversity. A skill may be +conceptually unified but contain multiple independent subsystems with +distinct config interfaces — for example, 5 sync adapters that all +solve "connectivity" but each with unique setup, options, and failure +modes. + +For each skill, ask: "Does this cover 3+ backends, adapters, drivers, +or providers with distinct configuration surfaces?" If yes, list them +as `subsystems`. These tell the skill-tree-generator to produce +per-subsystem reference files. + +Also flag dense API surfaces — if a topic has >10 distinct operators, +option shapes, or patterns (e.g. query operators, schema validation +rules), note it as a `reference_candidates` entry. + +### 3d — Extract failure modes + +For each skill, extract failure modes that pass all three tests: + +- **Plausible** — An agent would generate this because it looks correct + based on the library's design, a similar API, or an older version +- **Silent** — No immediate crash; fails at runtime or under specific conditions +- **Grounded** — Traceable to a specific doc page, source location, or issue + +**Where to find them:** + +| Source | What to extract | +| -------------------- | ------------------------------------------------------------------ | +| Migration guides | Every breaking change → old pattern is the wrong code | +| Doc callouts | Any "note", "warning", "avoid" with surrounding context | +| Source assertions | `throw` and `invariant()` messages describe the failure | +| Default values | Undocumented or surprising defaults that cause wrong behavior | +| Type precision | Source type more restrictive than docs imply | +| Environment branches | `typeof window`, SSR flags, `NODE_ENV` — behavior differs silently | + +Target 3 failure modes per skill minimum. Complex skills target 5–6. + +**Cross-skill failure modes.** Some failure modes belong to multiple +skills. A developer doing SSR work and a developer doing state management +both need to know about "stale state during hydration" — they load +different skills but need the same advice. When a failure mode spans +skills, list all relevant skill slugs in its `skills` field. The +skill-tree-generator will write it into every corresponding SKILL file. + +List a cross-skill failure mode once, under its primary skill. Set +the `skills` field to all skill slugs it applies to. Do not duplicate +the entry in the YAML — the skill-tree-generator handles duplication +into multiple SKILL files at generation time. + +### 3e — Identify cross-skill tensions + +Look for places where design forces between skills conflict. A tension +is not a failure mode — it's a structural pull where optimizing for one +task makes another harder. Examples: + +- "Getting-started simplicity conflicts with production operational safety" +- "Type-safety strictness conflicts with rapid prototyping flexibility" +- "SSR correctness requires patterns that hurt client-side performance" + +Tensions are where agents fail most because they optimize for one task +without seeing the tradeoff. Each tension should name the skills in +conflict, describe the pull, and state what an agent gets wrong when it +only considers one side. + +Target 2–4 tensions. If you find none, the skills may be too isolated — +revisit whether you're missing cross-connections. + +### 3f — Identify gaps + +For each skill, explicitly list what you could NOT determine from docs +and source alone. These become interview questions in Phase 4. + +Common gaps: + +- "Docs describe X but don't explain when you'd choose X over Y" +- "Migration guide mentions this changed but doesn't say what the old + behavior was" +- "Source has an assertion here but no doc explains what triggers it" +- "GitHub issues show confusion about X but docs don't address it" +- "I found two patterns for doing X — unclear which is current/preferred" + +### 3g — Discover composition targets + +Scan `package.json` for peer dependencies, optional dependencies, and +`peerDependenciesMeta`. Scan example directories and integration tests +for import patterns. For each frequently co-used library, log: + +- Library name and which features interact +- Whether it's a required or optional integration +- Any example code showing the integration pattern + +These become targeted composition questions in Phase 4e. + +### 3h — Produce the draft + +Write the full `domain_map.yaml` (format in Output Artifacts below) with +a `status: draft` field. Flag every gap in the `gaps` section. + +Present the draft to the maintainer before starting Phase 4: + +> "I've read the docs and source for [library] and produced a draft with +> [N] skills and [M] failure modes. I've flagged [K] specific gaps where +> I need your input." + +Include the full draft domain_map.yaml in your message so the maintainer +can review it. Also include a checklist of all docs files you read. + +**── STOP ── Do not proceed to Phase 4 until the maintainer has +reviewed the draft and responded. Their feedback on the draft informs +the detail interview questions.** + +--- + +## Phase 4 — Detail interview (interactive — requires maintainer) + +You have the maintainer's task map and a deep read. The interview now +fills gaps, validates your understanding, and surfaces implicit knowledge. + +You must ask the questions below to the maintainer and wait for their +responses. Do not infer answers from documentation or source code — +even for gaps you think you can answer from your reading. + +### Rules for Phase 4 + +1. One topic per message for open-ended questions. You may batch 2–3 + yes/no or short-confirmation questions together. +2. Ask each question as written (you may adapt phrasing to context, but + keep questions open-ended — never convert to multiple-choice). +3. Each question must reference something specific from your reading. +4. Wait for the maintainer's response after each question before asking + the next. +5. If the maintainer gives a short answer, probe deeper before moving on. +6. Take notes silently. Do not summarize back unless asked. + +### 4a — Draft review (2–3 questions) + +Start by confirming or correcting your skill list and failure modes: + +> "Here's the skill list I've built from our earlier conversation plus +> the deep read: [list skills with brief descriptions]. Does this still +> match your thinking? Anything to add, remove, or rename?" + +Follow up on any corrections. Then: + +> "I identified [M] failure modes from the docs and migration guides. Are +> there important ones I missed — especially patterns that look correct +> but fail silently?" + +### 4b — Gap-targeted questions (3–8 questions) + +For each gap flagged in Phase 3f, ask a specific question. These are not +generic — they reference what you found: + +**Instead of:** "What do developers get wrong?" +**Ask:** "I noticed the migration guide from v4 to v5 changed how [X] works, +but the docs don't show the old pattern. Do agents still commonly generate +the v4 pattern? What does it look like?" + +**Instead of:** "Are there surprising interactions?" +**Ask:** "The source throws an invariant error if [X] is called before [Y], +but the docs don't mention ordering. How often do developers hit this?" + +**Instead of:** "What's different in SSR vs client?" +**Ask:** "I found a `typeof window` check in [file] that changes behavior +for [feature]. What goes wrong when developers test only in the browser +and deploy with SSR?" + +Adapt from this bank of gap-targeted question templates: + +- "I found two patterns for [X] in the docs — [pattern A] and [pattern B]. + Which is current, and does the old one still work?" +- "The source defaults [config option] to [value], which seems surprising + for [reason]. Is this intentional? Do developers need to override it?" +- "GitHub issues show [N] reports of confusion about [X]. What's the + underlying misunderstanding?" +- "I couldn't find docs for how [feature A] interacts with [feature B]. + What should an agent know about using them together?" +- "The API reference shows [type signature], but the guide examples use + a different shape. Which is accurate?" + +### 4c — AI-agent-specific failure modes (2–4 questions) + +These target mistakes that AI coding agents make but human developers +typically don't. Agent-specific failures are often the highest-value +findings — in testing, maintainer answers to these questions produced +the most critical failure modes. + +- "What mistakes would an AI coding agent make that a human developer + wouldn't? Think about: hallucinating APIs that don't exist, defaulting + to language primitives instead of library abstractions, choosing the + wrong adapter or integration path." +- "When an agent generates code using your library, what's the first + thing you'd check? What pattern would make you immediately say + 'an AI wrote this'?" +- "Are there parts of your API where the naming or design is misleading + enough that an agent with no prior context would pick the wrong + approach? What would it pick, and what should it pick instead?" +- "Are there features where the docs are comprehensive for human + developers but would still mislead an agent? For example, features + that require understanding unstated context, or where the 'obvious' + approach from reading the API surface is wrong." + +### 4d — Implicit knowledge extraction (3–5 questions) + +These surface knowledge that doesn't appear in any docs: + +- "What does a senior developer using your library know that a mid-level + developer doesn't — something that isn't written down anywhere?" +- "Are there patterns that work fine for prototyping but are dangerous + in production? What makes them dangerous?" +- "What question do you answer most often in Discord or GitHub issues + that the docs technically cover but people still miss?" +- "Is there anything you'd change about the API design if you could break + backwards compatibility? What's the current workaround?" + +### 4e — Composition questions (if library interacts with others) + +Use what you discovered in Phase 3g. For each integration target +identified from peer dependencies and example code, ask targeted +questions: + +- "I see [library] is a peer dependency and [N] examples import it + alongside yours. What's the most common integration mistake?" +- "When developers use [your library] with [other library], are there + patterns that only matter when both are present?" +- "I found [specific integration pattern] in the examples. Is this the + recommended approach, or is there a better way that isn't documented?" + +--- + +## Phase 5 — Finalize artifacts + +Merge interview findings into the draft. For each interview answer: + +1. If it confirms a skill or failure mode — no action needed +2. If it corrects something — update the map +3. If it adds a new failure mode — add it with source "maintainer interview" +4. If it reveals a new skill — add it +5. If it fills a gap — remove from gaps section + +Update `status: draft` to `status: reviewed`. + +--- + +## Output artifacts + +If the maintainer uses a custom skills root, replace `skills/` in the paths +below with their chosen directory. + +### 1. skills/\_artifacts/domain_map.yaml + +```yaml +# domain_map.yaml +# Generated by skill-domain-discovery +# Library: [name] +# Version: [version this map targets] +# Date: [ISO date] +# Status: [draft | reviewed] + +library: + name: '[package-name]' + version: '[version]' + repository: '[repo URL]' + description: '[one line]' + primary_framework: '[React | Vue | Svelte | framework-agnostic]' + +domains: + - name: '[work-oriented domain name]' + slug: '[kebab-case]' + description: '[conceptual grouping — what a developer is reasoning about]' + +skills: + - name: '[task-focused skill name]' + slug: '[kebab-case]' + domain: '[parent domain slug]' + description: '[what a developer is doing — matches a specific task/moment]' + type: '[core | framework | lifecycle | composition]' + packages: # required for monorepo; omit for single-package libraries + - '[package where this skill ships]' + - '[additional package, if skill is relevant to multiple packages]' + covers: + - '[API/hook/concept 1]' + - '[API/hook/concept 2]' + tasks: + - '[example task 1]' + - '[example task 2]' + - '[example task 3]' + subsystems: # omit if skill has no independent subsystems + - name: '[adapter/backend name]' + package: '[npm package if separate]' + config_surface: '[brief description of unique config]' + reference_candidates: # omit if no dense API surfaces + - topic: '[e.g. query operators, schema validation]' + reason: '[e.g. >10 distinct operators with signatures]' + failure_modes: + - mistake: '[5-10 word phrase]' + mechanism: '[one sentence]' + source: '[doc page, source file, issue link, or maintainer interview]' + priority: '[CRITICAL | HIGH | MEDIUM]' + status: '[active | fixed-but-legacy-risk | removed]' + version_context: "[e.g. 'Fixed in v5.2 but agents trained on older code still generate this']" + skills: ['[this-skill-slug]'] # list all skills this belongs to; omit if single-skill + compositions: + - library: '[other library name]' + skill: '[composition skill name if applicable]' + +tensions: + - name: '[short phrase describing the pull]' + skills: ['[skill-slug-a]', '[skill-slug-b]'] + description: '[what conflicts — one sentence]' + implication: '[what an agent gets wrong when it only considers one side]' + +gaps: + - skill: '[skill slug]' + question: '[what still needs input]' + context: '[why this matters]' + status: '[open | resolved]' +``` + +### 2. skills/\_artifacts/skill_spec.md + +A human-readable companion document. Follow this structure: + +```markdown +# [Library Name] — Skill Spec + +[2–3 sentences: what this library is, what problem it solves. Factual, +not promotional.] + +## Domains + +| Domain | Description | Skills | +| ------ | --------------------- | ----------------------- | +| [name] | [conceptual grouping] | [skill-1, skill-2, ...] | + +## Skill Inventory + +| Skill | Type | Domain | What it covers | Failure modes | +| ------ | -------------------------------------- | -------- | -------------- | ------------- | +| [name] | [core/framework/lifecycle/composition] | [domain] | [list] | [count] | + +## Failure Mode Inventory + +### [Skill name] ([count] failure modes) + +| # | Mistake | Priority | Source | Cross-skill? | +| --- | -------- | -------- | ---------------------- | ------------------------ | +| 1 | [phrase] | CRITICAL | [doc/source/interview] | [other skill slugs or —] | + +[Repeat table for each skill.] + +## Tensions + +| Tension | Skills | Agent implication | +| -------------- | ------------------- | ----------------------- | +| [short phrase] | [slug-a] ↔ [slug-b] | [what agents get wrong] | + +## Subsystems & Reference Candidates + +| Skill | Subsystems | Reference candidates | +| ------ | ------------------------------ | -------------------------- | +| [slug] | [adapter1, adapter2, ...] or — | [topic needing depth] or — | + +## Remaining Gaps + +| Skill | Question | Status | +| ------ | ------------------------ | ------ | +| [slug] | [what still needs input] | open | + +[Omit this section if all gaps were resolved in the interview.] + +## Recommended Skill File Structure + +- **Core skills:** [list which skills are framework-agnostic] +- **Framework skills:** [list per-framework skills needed] +- **Lifecycle skills:** [list journey/lifecycle skills if applicable] +- **Composition skills:** [list integration seams needing composition skills] +- **Reference files:** [list skills needing references/ based on subsystems + or dense API surfaces] + +## Composition Opportunities + +| Library | Integration points | Composition skill needed? | +| ------- | ------------------ | ----------------------------- | +| [name] | [what interacts] | [yes/no — if yes, skill name] | +``` + +--- + +## Constraints + +| Check | Rule | +| ------------------------------------- | -------------------------------------------------------------------------- | +| Quick scan before interview | Never interview without at least reading README and package structure | +| High-level interview before deep read | The maintainer's task map informs what you read deeply | +| **Interview phases are interactive** | Phases 2 and 4 require sending questions to the maintainer and waiting | +| **Docs are not a substitute** | Documentation cannot replace maintainer answers — even comprehensive docs | +| **Open-ended questions stay open** | Never convert interview questions to multiple-choice or yes/no | +| **Minimum question counts enforced** | Each sub-section's minimum count must be met; zero questions = violation | +| **STOP gates are mandatory** | Do not proceed past a STOP gate without maintainer response | +| Batch only confirmations | Yes/no questions may batch 2–3; open-ended questions get their own message | +| Questions reference findings | No generic questions — cite what you found | +| Skills are task-focused | Each skill matches a developer moment, not a conceptual area | +| 3+ failure modes per skill | Complex skills target 5–6 | +| Every failure mode sourced | Doc page, source file, issue link, or maintainer interview | +| Gaps are explicit | Unknown areas flagged, not guessed | +| No marketing prose | Library description is factual, not promotional | +| domain_map.yaml is valid YAML | Parseable by any YAML parser | +| Draft before detail interview | Present draft for review before Phase 4 | +| **Draft reviewed before Phase 4** | Maintainer must acknowledge or respond to draft before detail interview | +| Agent-specific failures probed | Always ask AI-agent-specific questions in Phase 4c | +| Compositions discovered from code | Scan peer deps and examples before asking composition questions | +| Cross-skill failure modes tagged | Failure modes spanning skills list all relevant slugs | +| Tensions identified | 2–4 cross-skill tensions; if none found, revisit skill boundaries | +| Subsystems flagged | Skills with 3+ adapters/backends list them as subsystems | +| Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates | +| Lifecycle skills considered | Suggest journey skills when docs have the material | +| **All docs files read** | List docs directory contents and read every narrative file — no sampling | + +--- + +## Cross-model compatibility notes + +This skill is designed to produce consistent results across Claude, GPT-4+, +Gemini, and open-source models. To achieve this: + +- All instructions use imperative sentences, not suggestions +- Interview phases use explicit STOP gates to prevent models from + continuing autonomously past interactive checkpoints +- Hard rules at the top override any model tendency to rationalize + skipping interactive phases when documentation is available +- Open-ended questions are explicitly protected from conversion to + multiple-choice or confirmation prompts, which models default to + when they have enough context to pre-populate answers +- Output formats use YAML (universally parsed) and Markdown tables + (universally rendered) +- Examples use concrete values, not placeholders like "[your value here]" +- Section boundaries use Markdown headers (##) for navigation and --- for + phase separation +- No model-specific features (no XML tags in output, no tool_use assumptions) + +--- + +## Meta-skill feedback (mandatory — do not skip) + +**This step is required.** Agents routinely skip feedback collection +because it appears at the end of the skill. You must complete this step +before the domain discovery process is considered finished. + +After finalizing artifacts, ask the maintainer for feedback on the domain +discovery process. Do not silently create the feedback template — present +it to the maintainer and ask them to fill in the Domain Discovery section. + +**── STOP ── Ask the maintainer to provide feedback. Wait for their +response before writing the feedback file.** + +Create or update a single Markdown feedback draft +for all three meta skills used in scaffolding. Use this exact template and +fill only the **Domain Discovery** section now. Leave the other sections in +place for later steps to complete. + +``` +# Playbook Meta Skill Feedback + +## Domain Discovery +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Tree Generator +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Generate Skill +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Context (optional) +- Library: +- Repo: +- Docs: +- Notes: +``` + +Do not submit feedback yet. Tell the maintainer to carry this draft forward +to the next meta skill step. +>>>>>>> 54555c4 (feat: enhance SKILL.md with clarifications on package ownership and skill generation process):packages/playbooks/meta/domain-discovery/SKILL.md diff --git a/packages/intent/meta/generate-skill/SKILL.md b/packages/intent/meta/generate-skill/SKILL.md index c5e97968..a4006460 100644 --- a/packages/intent/meta/generate-skill/SKILL.md +++ b/packages/intent/meta/generate-skill/SKILL.md @@ -1,3 +1,4 @@ +<<<<<<< HEAD:packages/intent/meta/generate-skill/SKILL.md --- name: skill-generate description: > @@ -426,3 +427,448 @@ Ask the maintainer if they want to edit the feedback. Then ask if you should send it as a GitHub issue to TanStack/intent. Use the issue title: `[meta-feedback] intent meta skill`. Only submit if they confirm. ``` +======= +--- +name: skill-generate +description: > + Generate a complete SKILL.md file for a library from source documentation + and skill tree artifacts. Activate when bootstrapping skills for a new + library, regenerating a stale skill after source changes, or producing a + skill from a skill_tree.yaml entry. Takes a skill name, description, and + source docs as inputs; outputs a validated SKILL.md that conforms to the + tree-generator spec. +metadata: + version: '1.0' + category: meta-tooling + input_artifacts: + - skills/_artifacts/skill_tree.yaml + - skills/_artifacts/domain_map.yaml + - skills/_artifacts/skill_spec.md + - source documentation + output_artifacts: + - SKILL.md + skills: + - skill-tree-generator + - skill-domain-discovery +--- + +# Skill Generation + +You are generating a SKILL.md file for the `@tanstack/playbooks` agent skills +repo. Skills in this repo are written for coding agents (Claude Code, Cursor, +Copilot, Warp Oz, Codex), not for human readers. Your output will be loaded +into an agent's context window and used to guide code generation. + +There are two modes. Detect which applies. + +**Mode A — Generate from domain map:** A `domain_map.yaml` and `skill_spec.md` +exist. Generate the skill specified by name from these artifacts plus the +source documentation they reference. + +**Mode B — Generate from raw docs:** No domain map exists. Generate directly +from source documentation provided as input. + +--- + +## Inputs + +You will receive: + +If the maintainer uses a custom skills root, replace `skills/` in any paths +below with their chosen directory. + +For monorepo libraries, skills ship inside the package they belong to. +Each package has its own `skills/` directory so that when a developer +installs a package (e.g. `@tanstack/react-router`), the skills are +available locally. Cross-package skills live in whichever package is the +primary entry point for that task, with references to the other packages. + +1. **Skill name** — format `library-group/skill-name` (e.g. `tanstack-query/core`, + `tanstack-router/loaders`, `db/core/live-queries`). The name determines the + output file path: `skills/[name]/SKILL.md` relative to the package root. +2. **Skill description** — what the skill covers and when an agent should load it +3. **Source documentation** — the docs, guides, API references, and/or source + files to distill from +4. **Domain map entry** (Mode A only) — the skill's entry from `domain_map.yaml` + including failure modes, subsystems, compositions, and source references + +--- + +## Step 1 — Determine skill type + +Read the inputs and classify the skill type: + +| Type | When to use | +| ------------- | ---------------------------------------------------------- | +| `core` | Framework-agnostic concepts, configuration, patterns | +| `sub-skill` | A focused sub-topic within a core or framework skill | +| `framework` | Framework-specific bindings, hooks, components | +| `lifecycle` | Cross-cutting developer journey (getting started, go-live) | +| `composition` | Integration between two or more libraries | +| `security` | Audit checklist or security validation | + +The skill type determines the frontmatter and body structure. See +skill-tree-generator for the full spec of each type. + +--- + +## Step 2 — Extract content from sources + +Read through the source documentation. Extract only what a coding agent +cannot already know: + +### What to extract + +- **API shapes** — function signatures, hook parameters, option objects, + return types. Use the actual TypeScript types from source. +- **Setup patterns** — minimum viable initialization code +- **Primary patterns** — the 2–4 most important usage patterns +- **Configuration** — defaults that matter, options that change behavior +- **Failure modes** — patterns that look correct but break. Prioritize: + - Migration-boundary mistakes (old API that agents trained on older data produce) + - Silent failures (no crash, wrong behavior) + - Framework-specific gotchas (hydration, hook rules, provider ordering) +- **Constraints and invariants** — ordering requirements, lifecycle rules, + things enforced by runtime assertions + +### What NOT to extract + +- TypeScript basics, React hooks concepts, general web dev knowledge +- Marketing copy, motivational prose, "why this library is great" +- Exhaustive API tables (move these to `references/` if needed) +- Content that duplicates another skill (reference it instead) + +--- + +## Step 3 — Write the frontmatter + +### Core skill frontmatter + +```yaml +--- +name: [library]/[skill-name] +description: > + [1–3 sentences. What this skill covers and exactly when an agent should + load it. Written for the agent — include the keywords an agent would + encounter when it needs this skill. Dense routing key.] +type: core +library: [library] +library_version: "[version this targets]" +packages: # required for monorepo; omit for single-package libraries + - "[package where this skill ships]" + - "[additional package, if skill is relevant to multiple packages]" +sources: + - "[Owner/repo]:docs/[path].md" + - "[Owner/repo]:src/[path].ts" +--- +``` + +### Sub-skill frontmatter + +```yaml +--- +name: [library]/[parent]/[skill-name] +description: > + [1–3 sentences. What this sub-topic covers and when to load it.] +type: sub-skill +library: [library] +library_version: "[version]" +sources: + - "[Owner/repo]:docs/[path].md" +--- +``` + +### Framework skill frontmatter + +```yaml +--- +name: [library]/[framework] +description: > + [1–3 sentences. Framework-specific bindings. Name the hooks, components, + providers.] +type: framework +library: [library] +framework: [react | vue | solid | svelte | angular] +library_version: "[version]" +requires: + - [library]/core +sources: + - "[Owner/repo]:docs/framework/[framework]/[path].md" +--- +``` + +### Frontmatter rules + +- `description` must be written so the agent loads this skill at the right + time — not too broad (triggers on everything) and not too narrow (never + triggers). Pack with function names, option names, concept keywords. +- `sources` uses the format `Owner/repo:relative-path`. Glob patterns are + supported (e.g. `TanStack/query:docs/framework/react/guides/*.md`). +- `library_version` is the version of the source library this skill targets. +- `requires` lists skills that must be loaded before this one. + +--- + +## Step 4 — Write the body + +### Standard body (core, sub-skill, framework) + +Follow this section order exactly: + +**1. Dependency note** (framework and sub-skills only) + +```markdown +This skill builds on [parent-skill]. Read it first for foundational concepts. +``` + +**2. Setup** + +A complete, copy-pasteable code block showing minimum viable usage. + +- Real package imports with exact names (`@tanstack/react-query`, not `react-query`) +- No `// ...` or `[your code here]` — complete and runnable +- No unnecessary boilerplate — include exactly the context needed +- For framework skills: framework-specific setup (provider, hook wiring) +- For core skills: framework-agnostic setup (no hooks, no components) + +**3. Core Patterns** (or "Hooks and Components" for framework skills) + +2–4 patterns. For each: + +- One-line heading: what it accomplishes +- Complete code block +- One sentence of explanation only if not self-explanatory + +**4. Common Mistakes** + +Minimum 3 entries. Complex skills target 5–6. Format: + +````markdown +### [PRIORITY] [What goes wrong — 5–8 word phrase] + +Wrong: + +```[lang] +// code that looks correct but isn't +``` +```` + +Correct: + +```[lang] +// code that works +``` + +[One sentence: the specific mechanism by which the wrong version fails.] + +Source: [doc page or source file:line] + +```` + +Priority levels: +- **CRITICAL** — Breaks in production. Security risk or data loss. +- **HIGH** — Incorrect behavior under common conditions. +- **MEDIUM** — Incorrect under specific conditions or edge cases. + +Every mistake must be: +- **Plausible** — an agent would generate it +- **Silent** — no immediate crash +- **Grounded** — traceable to a doc page, source file, or issue + +If the domain map includes failure modes with a `skills` list naming +multiple skills, include those failure modes in every SKILL file listed. + +**5. References** (only when needed) + +```markdown +## References + +- [Full option reference](references/options.md) +```` + +Create reference files when the skill would exceed 500 lines, when the +domain covers 3+ independent adapters/backends, or when a topic has >10 +distinct API patterns. + +### Checklist body (security, go-live, audit) + +Use when the primary action is "check these things" not "learn patterns": + +````markdown +# [Library Name] — [Security | Go-Live] Checklist + +Run through each section before [deploying | releasing]. + +## [Category] Checks + +### Check: [what to verify] + +Expected: + +```[lang] +// correct configuration +``` +```` + +Fail condition: [what indicates this check failed] +Fix: [one-line remediation] + +## Common Security Mistakes + +[Wrong/correct pairs, same format as standard Common Mistakes] + +## Pre-Deploy Summary + +- [ ] [Verification 1] +- [ ] [Verification 2] + +``` + +--- + +## Step 5 — Validate + +Run every check before outputting. Fix any failures. + +| Check | Rule | +|-------|------| +| Under 500 lines | Move excess to references/ | +| Real imports in every code block | Exact package name, correct adapter | +| No external concept explanations | No "TypeScript is...", no "React hooks are..." | +| No marketing prose | No "powerful", "elegant", "best-in-class" | +| Every code block is complete | Works without modification when pasted | +| Common Mistakes are silent | Not obvious compile errors | +| Common Mistakes are library-specific | Not generic TS/React mistakes | +| Common Mistakes are sourced | Traceable to doc or source | +| `name` matches expected directory path | `db/core/live-queries` → `db/core/live-queries/SKILL.md` | +| `sources` filled for sub-skills | At least one Owner/repo:path | +| Framework skills have `requires` | Lists core dependency | +| Framework skills open with dependency note | First prose line references core | +| Description is a dense routing key | Not a human summary — agent-facing | + +--- + +## Step 6 — Output + +Output the complete SKILL.md file content. If reference files are needed, +output those as well with their relative paths. + +If generating multiple skills in a batch (e.g. all skills for a library), +generate and present the first core overview SKILL.md to the maintainer +before writing the rest. + +**── STOP ── Wait for the maintainer to review the first generated skill. +Their feedback on structure, tone, and detail level applies to every +subsequent skill. Catching issues early avoids rewriting the entire batch.** + +After the maintainer confirms (or provides corrections), generate the +remaining skills in this order: + +1. Core overview SKILL.md (already reviewed above) +2. Core sub-skills in domain order +3. Framework overview SKILL.md for each framework +4. Framework sub-skills +5. Composition skills +6. Security/checklist skills +7. Reference files + +--- + +## Regeneration mode + +When regenerating a stale skill (triggered by skill-staleness-check): + +1. Read the existing SKILL.md and the source diff that triggered staleness +2. Determine which sections are affected by the change +3. Update only affected sections — preserve all other content +4. If a breaking change occurred, add the old pattern as a new Common + Mistake entry (wrong/correct pair) +5. Bump `library_version` in frontmatter +6. Validate the complete file against Step 5 checks + +Do not rewrite the entire skill for a minor source change. Surgical +updates preserve review effort and reduce diff noise. + +--- + +## Constraints + +| Rule | Detail | +|------|--------| +| **First skill reviewed before batch** | In batch mode, present the first core skill for maintainer review before generating the rest | +| React adapter only (Phase 1) | No Vue, Solid, Svelte, Angular examples unless generating a framework skill for that adapter | +| All imports use real package names | `@tanstack/react-query`, not `react-query` | +| No placeholder code | No `// ...`, `[your value]`, or `...rest` | +| Agent-first writing | Only write what the agent cannot already know | +| Examples are minimal | No unnecessary boilerplate or wrapper components | +| Failure modes are high-value | Focus on plausible-but-broken, not obvious errors | + +--- + +## Cross-model compatibility + +Output is consumed by all major AI coding agents. To ensure consistency: + +- Markdown with YAML frontmatter — universally parsed +- No XML tags in generated skill content +- Code blocks use triple backticks with language annotation +- Section boundaries use ## headers +- Descriptions are keyword-packed for routing +- Examples show concrete values, never placeholders +- Positive instructions ("Use X") over negative ("Don't use Y") +- Critical info at start or end of sections (not buried in middle) +- Each SKILL.md is self-contained except for declared `requires` + +--- + +## Meta-skill feedback (alpha — temporary) + +During the alpha period, collect feedback from the maintainer on the +skill generation process. Ask if they'd like to share what worked well, +what was confusing, or suggestions for improvement. If they decline or +want to move on, that's fine. + +Complete a single Markdown +feedback draft for all three meta skills used in scaffolding. If a draft +exists from previous steps, keep it and fill the **Generate Skill** section. +If no draft exists, create it using this exact template. + +``` + +# Playbook Meta Skill Feedback + +## Domain Discovery + +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Tree Generator + +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Generate Skill + +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Context (optional) + +- Library: +- Repo: +- Docs: +- Notes: + +``` + +Ask the maintainer if they want to edit the feedback. Then ask if you should +send it as a GitHub issue to TanStack/playbooks. Use the issue title: +`[meta-feedback] playbook meta skill`. Only submit if they confirm. +``` +>>>>>>> 54555c4 (feat: enhance SKILL.md with clarifications on package ownership and skill generation process):packages/playbooks/meta/generate-skill/SKILL.md diff --git a/packages/intent/meta/tree-generator/SKILL.md b/packages/intent/meta/tree-generator/SKILL.md index a82a3b97..6ab598e2 100644 --- a/packages/intent/meta/tree-generator/SKILL.md +++ b/packages/intent/meta/tree-generator/SKILL.md @@ -1,3 +1,4 @@ +<<<<<<< HEAD:packages/intent/meta/tree-generator/SKILL.md --- name: skill-tree-generator description: > @@ -890,3 +891,920 @@ no draft exists, create it using this exact template. Do not submit feedback yet. Carry this draft forward to the generate-skill step. +======= +--- +name: skill-tree-generator +description: > + Generate, update, and version a complete skill tree (collection of SKILL.md + files) for any JavaScript or TypeScript library. Produces core skills + (framework-agnostic) and framework skills (React, Solid, Vue bindings) + with dependency linking. Activate when producing skill files from a domain + map, updating existing skills after a library version change, or auditing + skill accuracy. Takes domain_map.yaml and skill_spec.md from + skill-domain-discovery as primary inputs. +metadata: + version: '3.0' + category: meta-tooling + input_artifacts: + - skills/_artifacts/domain_map.yaml + - skills/_artifacts/skill_spec.md + output_artifacts: + - skills/_artifacts/skill_tree.yaml + skills: + - skill-domain-discovery +--- + +# Skill Tree Generator + +You produce and maintain a tree of SKILL.md files for a library. Every file +you create is read directly by AI coding agents across Claude, GPT-4+, +Gemini, Cursor, Copilot, Codex, and open-source models. Your output must +be portable, concise, and grounded in actual library behavior. + +### Skill types + +Every skill has a `type` field in its frontmatter. Valid types: + +| Type | Purpose | Example | +| ------------- | ---------------------------------------------------------- | ------------------------- | +| `core` | Framework-agnostic concepts, configuration, patterns | `db-core` | +| `sub-skill` | A focused sub-topic within a core or framework skill | `db-core/live-queries` | +| `framework` | Framework-specific bindings, hooks, components | `react-db` | +| `lifecycle` | Cross-cutting developer journey (getting started, go-live) | `electric-quickstart` | +| `composition` | Integration between two or more libraries | `electric-drizzle` | +| `security` | Audit checklist or security validation | `electric-security-check` | + +Agents discover skills via `tanstack playbook list` and read them directly +from `node_modules`. Framework skills declare a `requires` dependency on +their core skill so agents load them in the right order. + +There are two workflows. Detect which applies. + +**Workflow A — Generate:** Build a complete skill tree from a domain map. +**Workflow B — Update:** Diff a library version change and update skills. + +--- + +## Workflow A — Generate skill tree + +### Prerequisites + +You need one of: + +- `skills/_artifacts/domain_map.yaml` and `skills/_artifacts/skill_spec.md` + from skill-domain-discovery +- Raw library documentation and source code (run a compressed domain + discovery first) + +If starting from raw docs without a domain map, run a compressed +discovery. **Warning:** This produces significantly lower-fidelity +output than the full skill-domain-discovery skill. The maintainer +interview in domain discovery surfaces implicit knowledge, failure +modes, and prioritization that cannot be inferred from docs alone. +Always prefer running the full discovery when possible. Only use +compressed discovery when the maintainer has explicitly confirmed +they want to skip domain discovery. + +1. Build a concept inventory (every export, config key, constraint, warning) +2. Group into 4–7 capability domains using work-oriented names +3. Enumerate 10–20 task-focused skills from the intersection of domains + and developer tasks +4. Extract 3+ failure modes per skill (plausible, silent, grounded) +5. Proceed to Step 1 below + +### Scaffold flow output + +If the maintainer uses a custom skills root, replace `skills/` in the paths +below with their chosen directory. + +For the scaffold workflow, produce a single artifact before writing any +SKILL.md files: + +- `skills/_artifacts/skill_tree.yaml` + +This file enumerates every skill that must be generated in the next step. +Do not write SKILL.md files yet unless explicitly asked. + +Use this format: + +```yaml +# skills/_artifacts/skill_tree.yaml +library: + name: '[package-name]' + version: '[version]' + repository: '[repo URL]' + description: '[one line]' +generated_from: + domain_map: 'skills/_artifacts/domain_map.yaml' + skill_spec: 'skills/_artifacts/skill_spec.md' +generated_at: '[ISO date]' + +skills: + - name: '[task-focused skill name]' + slug: '[kebab-case]' + type: 'core | sub-skill | framework | lifecycle | composition | security' + domain: '[domain slug]' + path: 'skills/[path]/SKILL.md' + description: '[1–2 sentence agent-facing routing key]' + packages: # required for monorepo; omit for single-package libraries + - '[package where this skill ships]' + - '[additional package, if skill is relevant to multiple packages]' + requires: + - '[other skill slugs]' # omit if none + sources: + - '[Owner/repo]:docs/[path].md' + - '[Owner/repo]:src/[path].ts' + subsystems: + - '[adapter/backend name]' # omit if none + references: + - 'references/[file].md' # omit if none +``` + +### Step 1 — Plan the file tree + +From the domain map, each entry in the `skills` list becomes a SKILL.md +file. The `type` field on each skill (`core`, `framework`, `lifecycle`, +`composition`) determines where it goes. Determine the file tree. + +Present the planned file tree to the maintainer before writing any files. +Include the full `skill_tree.yaml` content and explain any structural +decisions (flat vs nested, which skills get reference files, how +cross-package skills are handled). + +**── STOP ── Wait for the maintainer to review and approve the file tree +before proceeding to Step 2. A bad tree means rewriting every generated +file.** + +Determine the file tree: + +**Core vs framework decision:** + +| Content | Goes in... | +| ---------------------------------------------- | ---------- | +| Mental models, concepts, lifecycle | Core | +| Configuration options and their effects | Core | +| Type system, generics, inference | Core | +| Common mistakes that apply to all frameworks | Core | +| Hooks (`useX`, `createX`) | Framework | +| Components (``, ``) | Framework | +| Provider setup and wiring | Framework | +| SSR/hydration patterns specific to a framework | Framework | +| Framework-specific gotchas | Framework | + +If a library has no framework adapters (e.g. Store, DB), produce only +core skills. + +**Framework-integration domain decomposition:** If the domain map from +skill-domain-discovery contains a single "Framework Integration" domain +and the library has separate framework adapter packages, decompose it +into per-framework skills co-located with each adapter package. Do not +produce a single monolithic framework-integration skill that covers +React, Vue, Solid, etc. in one file. + +**Adapter-heavy domains:** When a domain covers multiple backends or +adapters with distinct config interfaces (e.g. 5 sync adapters, 3 +database drivers), keep one SKILL.md for the shared patterns but +produce one reference file per adapter with its specific config, +setup, and gotchas. The SKILL.md covers what's common; each +`references/[adapter].md` covers what's unique. + +**Flat vs nested structure:** + +Choose the structure that matches how the domain map's skills are shaped. + +Use **nested** (`[lib]-core/[domain]/SKILL.md`) when: + +- Developer tasks cluster cleanly into 3–5 conceptual domains +- The library has a clear core + framework adapter split +- Skills build on each other in a layered way + +Use **flat** (`skills/[skill-name]/SKILL.md`) when: + +- Developer tasks are task-focused and don't nest into domains +- The domain discovery process recommended task-focused skills +- Skills map 1:1 to distinct developer intents with minimal overlap + +Both are valid. The domain map's `type` field and structure will signal +which fits. When in doubt, prefer flat — it's simpler and each skill +is independently discoverable. + +**Monorepo placement:** Skills ship inside each package so they are +available when developers install the package. Each package has its +own `skills/` directory. Cross-package skills live in whichever +package is the primary entry point for that task. For example: + +``` +packages/ +├── react-router/ +│ └── skills/ +│ ├── router-core/ +│ │ ├── SKILL.md +│ │ └── navigation/ +│ │ └── SKILL.md +│ └── react-router/ +│ └── SKILL.md +├── start/ +│ └── skills/ +│ ├── start-core/ +│ │ └── SKILL.md +│ └── start-server-functions/ +│ └── SKILL.md +``` + +The examples below show the `skills/` tree within a single package. + +**Nested structure:** + +``` +skills/ +├── [lib]-core/ # Core skill for the library +│ ├── SKILL.md # Core overview + sub-skill registry +│ ├── [domain-1]/ +│ │ └── SKILL.md # Core sub-skill +│ ├── [domain-2]/ +│ │ └── SKILL.md +│ └── references/ # Optional overflow content +│ └── options.md +├── react-[lib]/ # React framework skill +│ ├── SKILL.md # React overview + sub-skill registry +│ ├── [domain-1]/ +│ │ └── SKILL.md # React-specific sub-skill +│ └── references/ +├── solid-[lib]/ # Solid framework skill (if applicable) +│ └── SKILL.md +├── vue-[lib]/ # Vue framework skill (if applicable) +│ └── SKILL.md +``` + +**Flat structure:** + +``` +skills/ +├── [lib]-shapes/ # Task-focused skill +│ ├── SKILL.md +│ └── references/ +│ └── shape-options.md +├── [lib]-auth/ # Another task skill +│ └── SKILL.md +├── [lib]-proxy/ +│ └── SKILL.md +├── [lib]-quickstart/ # Lifecycle skill +│ └── SKILL.md +├── [lib]-go-live/ # Lifecycle skill +│ └── SKILL.md +├── [lib]-drizzle/ # Composition skill +│ └── SKILL.md +``` + +**Router skill:** A router skill (lightweight entry point with a decision +table) is optional. If the playbook CLI provides `list` and `show` +commands, agents can discover skills directly without a router. Only +create a router skill if the skill set is large enough (15+) that +browsing the list is insufficient, or if the nested structure needs +an entry point to guide agents to the right sub-skill. + +**Source repository layout for npm distribution:** + +Skills must ship with their respective packages so they're available in +`node_modules` after install. In a monorepo, co-locate skills with the +package they document: + +``` +packages/ +├── [lib]/ # Core package +│ ├── src/ +│ ├── skills/ # Core skills live here +│ │ ├── [lib]-core/ +│ │ │ ├── SKILL.md +│ │ │ └── [domain]/SKILL.md +│ │ └── compositions/ # Composition skills with co-used libs +│ └── package.json # Add "skills" to files array +├── react-[lib]/ # React adapter package +│ ├── src/ +│ ├── skills/ # React framework skills live here +│ │ └── react-[lib]/ +│ │ └── SKILL.md +│ └── package.json # Add "skills" to files array +``` + +Add `"skills"` to each package's `files` array in `package.json` so +skill files are included in the published npm tarball: + +```json +{ + "files": ["dist", "src", "skills"] +} +``` + +### Step 2 — Write the core skill + +The core skill is the foundational overview for the library. It covers +framework-agnostic concepts and contains the sub-skill registry. + +**Frontmatter:** + +```yaml +--- +name: [lib]-core +description: > + [1–3 sentences. What this library does and the framework-agnostic + concepts it provides. Pack with keywords: function names, config + options, concepts. This is a routing key, not a human summary.] +type: core +library: [lib] +library_version: "[version this targets]" +--- +``` + +**Body template:** + +```markdown +# [Library Name] — Core Concepts + +[One paragraph: what this library is, what problem it solves. Factual, +not promotional. Framework-agnostic.] + +## Sub-Skills + +| Need to... | Read | +| ---------- | ------------------------------ | +| [task 1] | [lib]-core/[domain-1]/SKILL.md | +| [task 2] | [lib]-core/[domain-2]/SKILL.md | + +## Quick Decision Tree + +- Setting up for the first time? → [lib]-core/[setup-domain] +- Working with [concept]? → [lib]-core/[concept-domain] +- Debugging [issue]? → [lib]-core/[domain] § Common Mistakes + +## Version + +Targets [library] v[X.Y.Z]. +``` + +### Step 3 — Write core sub-skills + +One SKILL.md per domain. Follow this structure exactly. + +**Frontmatter:** + +```yaml +--- +name: [lib]-core/[domain-slug] +description: > + [1–3 sentences. What this domain covers AND when to load it. Name + specific functions, options, or APIs. Dense routing key.] +type: sub-skill +library: [lib] +library_version: "[version]" +sources: + - "[repo]:docs/[path].md" + - "[repo]:src/[path].ts" +--- +``` + +**Body sections — in this order:** + +**1. Setup** + +Minimum working example for this domain. + +- Use the library's core API, not framework-specific hooks +- Real package imports with exact names +- No `// ...` or `[your code here]` — complete and copy-pasteable +- If a concept is better explained with a framework hook, reference the + framework skill: "For React usage, see `react-[lib]/SKILL.md`" + +**2. Core Patterns** + +2–4 patterns. For each: + +- One-line heading: what it accomplishes +- Complete code block using core API +- One sentence of explanation only if not self-explanatory +- No framework-specific code — use core abstractions + +**3. Common Mistakes** + +Each `failure_mode` entry from the domain map becomes a Common Mistake +entry in the SKILL file. Minimum 3 entries. Complex domains target 5–6. + +**Cross-skill failure modes:** The domain map may contain failure modes +with a `skills` list naming multiple skill slugs. Write these into +every SKILL file whose skill is listed. A developer loading the SSR +skill and a developer loading the state management skill both need to +see "stale state during hydration" — the same advice must appear in +both files. Do not deduplicate across skills at the cost of coverage. + +Format: + +````markdown +### [PRIORITY] [What goes wrong — 5–8 word phrase] + +Wrong: + +```[lang] +// code that looks correct but isn't +``` +```` + +Correct: + +```[lang] +// code that works +``` + +[One sentence: the specific mechanism by which the wrong version fails.] + +Source: [doc page or source file:line] + +```` + +Priority levels: +- **CRITICAL** — Breaks in production. Security risk or data loss. +- **HIGH** — Incorrect behavior under common conditions. +- **MEDIUM** — Incorrect under specific conditions or edge cases. + +Every mistake must be plausible (an agent would generate it), silent +(no immediate crash), and grounded (traceable to doc or source). + +**Failure mode status from domain map:** The domain map may include a +`status` field on failure modes. Handle as follows: +- `active` — Include as a normal Common Mistake entry +- `fixed-but-legacy-risk` — Include with a note: "Fixed in v[X] but + agents trained on older code may still generate this pattern" +- `removed` — Do not include. The bug is fixed and the pattern is no + longer relevant. + +**4. References** (only when needed) + +```markdown +## References + +- [Complete option reference](references/options.md) +```` + +Create reference files when any of these apply — not just length overflow: + +- **Length:** The skill would exceed 500 lines without them +- **Multiple subsystems:** The domain covers 3+ independent backends, + adapters, or providers with distinct config interfaces. Create one + reference file per subsystem (e.g. `references/electric-adapter.md`, + `references/query-adapter.md`) +- **Dense API surface:** A topic has >10 distinct API patterns, operators, + or option shapes that agents need for implementation. Move the full + reference to `references/` and keep only the most common 2–3 in the + SKILL.md +- **Deep validation/schema patterns:** If the library has schema + validation, type transforms (TInput/TOutput), or similar deep + configuration surfaces, give them a dedicated reference file even if + they technically fit in the parent skill + +### Step 4 — Write framework skills + +Framework skills build on their core skill. They cover only what is +specific to the framework — hooks, components, providers, and +framework-specific patterns and mistakes. + +**Frontmatter:** + +```yaml +--- +name: react-[lib] +description: > + [1–3 sentences. React-specific bindings for [library]. Name the hooks, + components, and providers. Mention React-specific patterns like SSR + hydration if applicable.] +type: framework +library: [lib] +framework: react +library_version: "[version]" +requires: + - [lib]-core +--- +``` + +**Body template:** + +```markdown +This skill builds on [lib]-core. Read [lib]-core first for foundational +concepts before applying React-specific patterns. + +# [Library Name] — React + +## Setup + +[React-specific setup: provider, hook wiring, app entry point] + +## Hooks and Components + +[React hooks and components with complete examples] + +## React-Specific Patterns + +[Patterns that only apply in React: concurrent features, Suspense +integration, SSR/hydration, etc.] + +## Common Mistakes + +[Only React-specific mistakes. Do not repeat core mistakes. Examples: +calling hooks outside provider, missing Suspense boundary, hydration +mismatch, etc.] +``` + +**Framework sub-skills** follow the same pattern as core sub-skills but +with the framework frontmatter: + +```yaml +--- +name: react-[lib]/[domain-slug] +description: > + [React-specific description for this domain.] +type: sub-skill +library: [lib] +framework: react +library_version: "[version]" +requires: + - [lib]-core + - [lib]-core/[domain-slug] +--- + +This skill builds on [lib]-core/[domain-slug]. Read the core skill first. +``` + +### Step 5 — Write cross-domain tension notes + +The domain map may contain a `tensions` section listing design conflicts +between domains. For each tension, add a brief note to the Common +Mistakes section of every SKILL file whose domain is involved. Format: + +```markdown +### HIGH Tension: [short phrase] + +This domain's patterns conflict with [other domain]. [One sentence +describing the pull.] Agents optimizing for [this domain's goal] +tend to [specific mistake] because they don't account for [other +domain's constraint]. + +See also: [lib]-core/[other-domain]/SKILL.md § Common Mistakes +``` + +The cross-reference ensures agents that load one skill are pointed +toward the related skill where the other side of the tension lives. + +### Step 6 — Write composition skills (if applicable) + +Use the `compositions` entries from `domain_map.yaml` (populated during +skill-domain-discovery Phase 2h) to identify which composition skills +to produce. + +Composition skills cover how two or more libraries work together. These +are framework-specific by default (the integration patterns depend on +framework hooks and providers). + +**Frontmatter:** + +```yaml +--- +name: compositions/[lib-a]-[lib-b] +description: > + [How lib-a and lib-b wire together. Name the specific integration + points: functions, hooks, patterns.] +type: composition +library_version: "[version of primary lib]" +requires: + - [lib-a]-core + - react-[lib-a] + - [lib-b]-core + - react-[lib-b] +--- + +This skill requires familiarity with both [lib-a] and [lib-b]. +Read their core and framework skills first. +``` + +**Body structure:** + +1. **Integration Setup** — How to wire the two libraries together +2. **Core Integration Patterns** — 2–4 patterns showing them working in concert +3. **Common Mistakes** — Mistakes that only occur at the integration boundary + +Do not duplicate content from either library's individual skills. Focus +exclusively on the seam between them. + +### Step 7 — Write checklist/audit skills (where applicable) + +Some skills don't fit the standard body structure (Setup → Core Patterns +→ Common Mistakes). Security, go-live, and some lifecycle skills are +audit-oriented — the agent runs through a checklist to verify correctness +rather than learning patterns. Use the alternative body structure below +for these skill types. + +**When to use the checklist body:** + +- `security` type skills — pre-deploy security validation +- `lifecycle` type skills focused on verification (go-live, migration) +- Any skill where the primary action is "check these things" not "learn + these patterns" + +**Frontmatter:** + +```yaml +--- +name: react-[lib]/security +description: > + Go-live security validation for [library]. Checks [specific concerns]. +type: security +library: [lib] +framework: react +library_version: '[version]' +requires: + - react-[lib] +--- +``` + +**Alternative body template (checklist/audit):** + +````markdown +# [Library Name] — [Security | Go-Live | Migration] Checklist + +Run through each section before [deploying | releasing | migrating]. + +## [Category 1] Checks + +### Check: [what to verify] + +Expected: + +```[lang] +// correct configuration or code +``` +```` + +Fail condition: [what indicates this check failed] +Fix: [one-line remediation] + +### Check: [what to verify] + +[same structure] + +## [Category 2] Checks + +[same structure] + +## Common Security Mistakes + +[Wrong/correct pairs specific to this library, same format as +Common Mistakes in standard skills] + +## Pre-Deploy Summary + +- [ ] [Verification 1] +- [ ] [Verification 2] +- [ ] [Verification 3] + +```` + +The key differences from the standard body: +- No "Setup" section — the agent already has the app running +- Checks replace "Core Patterns" — each check is a verification, not a + teaching pattern +- The summary checklist at the end gives agents a quick pass/fail list +- Common Mistakes section is still present for wrong/correct pairs + +### Step 8 — Validate the complete tree + +Run every check before outputting. Fix any failures before proceeding. +Present the validation results to the maintainer — list any checks that +required fixes and what was changed. + +**── STOP ── Wait for the maintainer to acknowledge the validation +results before proceeding to the feedback step.** + +| Check | Rule | +|-------|------| +| Every skill from domain_map has a SKILL.md | No orphaned skills | +| Core/framework split is clean | No framework hooks in core skills | +| Every framework skill has `requires` | Links to its core skill | +| Framework skill opens with dependency note | "builds on [core]" prose line | +| Every skill under 500 lines | Move excess to references/ | +| Every code block has real imports | Exact package name, correct adapter | +| No concept explanations | No "TypeScript is...", no "React hooks are..." | +| No marketing prose | First body line is heading or dependency note | +| Every code block is complete | Works without modification when pasted | +| Common Mistakes are silent | Not obvious compile errors | +| Common Mistakes are library-specific | Not generic TS/React mistakes | +| Common Mistakes are sourced | Every mistake traceable to doc or source | +| Core skills reference framework skills | "For React usage, see..." | +| Framework skills don't repeat core content | Only framework-specific | +| Composition skills don't repeat individual skills | Only the seam | +| `name` matches directory path | `router-core/search-params` → `router-core/search-params/SKILL.md` | +| `sources` filled in sub-skills | At least one repo:path per sub-skill | +| Cross-skill failures in all relevant files | Failure modes with multiple `skills` appear in each listed SKILL.md | +| Tensions noted in affected skills | Each tension has notes in all involved domain skills | +| Framework domains decomposed per-package | No single skill covering multiple framework adapters | +| Adapter-heavy domains have references | 3+ adapters/backends → one reference file per adapter | +| Dense API surfaces in references | >10 distinct patterns → reference file, not inline | +| Checklist skills use audit body | Security/go-live skills use checklist template, not Setup → Core Patterns → Common Mistakes | + +--- + +## Workflow B — Update existing skills + +### Trigger conditions + +Run when: +- The library has released a new version +- A maintainer reports skills produce outdated code +- A changelog or migration guide has been published since skill creation +- Feedback reports indicate skill content is inaccurate + +### Step 1 — Detect staleness + +Compare each skill's `library_version` against the current library version. + +1. Read changelog entries between the two versions +2. Read migration guide (if one exists) +3. For each skill, check if its `sources` files have changed + +Produce a staleness report: + +```yaml +# staleness_report.yaml +library: "[name]" +library_version_in_skills: "[old]" +library_version_current: "[new]" + +stale_skills: + - skill: "[skill name]" + reason: "[what changed]" + severity: "[BREAKING | DEPRECATION | BEHAVIORAL | ADDITIVE]" + changelog_entry: "[relevant entry]" + affected_sections: + - "[Setup | Core Patterns | Common Mistakes]" + +current_skills: + - skill: "[skill name]" + reason: "[no changes affect this domain]" +```` + +### Step 2 — Update stale skills + +**BREAKING changes:** + +1. Old pattern becomes a new Common Mistake entry (wrong/correct pair) +2. Update Setup if initialization changed +3. Update Core Patterns if idiomatic approach changed +4. Bump `library_version` in frontmatter +5. Check both core AND framework skills — breaking changes may affect both + +**DEPRECATION changes:** + +1. Add Common Mistake: deprecated API as wrong, replacement as correct +2. Update Core Patterns to use non-deprecated API +3. Bump `library_version` + +**BEHAVIORAL changes:** + +1. Default value changed → add Common Mistake entry +2. Type signature more restrictive → add Common Mistake entry +3. Update affected code blocks +4. Bump `library_version` + +**ADDITIVE changes:** + +1. Evaluate if new feature belongs in existing domain or needs a new skill +2. If existing: add to Core Patterns or references/ +3. If new skill needed: create it and update the parent skill's sub-skill + registry +4. Bump `library_version` + +### Step 3 — Produce a changelog entry + +```markdown +## [date] + +### Updated for [library] v[new version] + +**Breaking changes:** + +- [skill name]: [what changed and why] + +**Deprecation updates:** + +- [skill name]: [old API] → [new API] + +**New skills:** + +- [skill name]: [what it covers] +``` + +--- + +## Constraints — verify for every file + +| Check | Rule | +| ------------------------------------------- | ----------------------------------------------------------------------------------- | +| **File tree reviewed by maintainer** | Present skill_tree.yaml for approval before writing SKILL.md files | +| **Validation results presented** | Show check results to maintainer before finalizing | +| Under 500 lines per SKILL.md | Move excess to references/; also create references for content depth | +| Real imports in every code block | Exact package, correct adapter | +| No external concept explanations | No "TypeScript is...", no "React hooks are..." — library-specific concepts are fine | +| No marketing prose | First body line is heading, code, or dependency note | +| Complete code blocks | Every block works without modification | +| Common Mistakes are silent | Not obvious compile errors | +| Common Mistakes are library-specific | Not generic TS/React mistakes | +| Common Mistakes are sourced | Traceable to doc or source | +| Core skills are framework-agnostic | No hooks, no components, no providers | +| Framework skills have `requires` | Lists core dependency | +| Framework skills open with dependency note | First prose line references core | +| Composition skills require all dependencies | Lists all core + framework skills | +| `name` matches directory | `router-core/search-params` → file at that path | +| `library_version` in every frontmatter | Which version the skill targets | +| Cross-skill failures duplicated | Each listed skill gets the failure mode | +| Tensions cross-referenced | Tension notes in each involved skill point to the other | +| Skills ship with packages | `"skills"` in package.json `files` array | +| Checklist skills use audit template | Security/go-live skills use checklist body, not standard body | + +--- + +## Cross-model compatibility + +Output is consumed by all major AI coding agents. To ensure consistency: + +- Markdown with YAML frontmatter — universally parsed +- No XML tags in generated skill content +- Code blocks use triple backticks with language annotation +- Section boundaries use ## headers +- Descriptions are keyword-packed for routing +- Examples show concrete values, never placeholders +- Positive instructions ("Use X") over negative ("Don't use Y") +- Critical info at start or end of sections (not buried in middle) +- Each SKILL.md is self-contained except for declared `requires` + +--- + +## Output order + +When generating a complete skill tree: + +1. Core overview SKILL.md — entry point for the library +2. Core sub-skills in domain order +3. Framework overview SKILL.md for each framework +4. Framework sub-skills +5. Composition skills (if applicable) +6. Security skills (if applicable) +7. references/ files for any skill that needs them +8. CHANGELOG.md entry + +When updating: + +1. staleness_report.yaml +2. Updated SKILL.md files (core then framework) +3. CHANGELOG.md entry + +--- + +## Meta-skill feedback (alpha — temporary) + +During the alpha period, collect feedback from the maintainer on the +tree generation process. Ask if they'd like to share what worked well, +what was confusing, or suggestions for improvement. If they decline or +want to move on, that's fine — proceed to the next step. + +Update the single Markdown feedback +draft for all three meta skills used in scaffolding. If a draft exists from +Domain Discovery, keep it and fill only the **Tree Generator** section. If +no draft exists, create it using this exact template. + +``` +# Playbook Meta Skill Feedback + +## Domain Discovery +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Tree Generator +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Generate Skill +- What worked well: +- What was confusing or missing: +- Suggestions for improvement: +- Overall rating: good | mixed | bad + +## Context (optional) +- Library: +- Repo: +- Docs: +- Notes: +``` + +Do not submit feedback yet. Carry this draft forward to the generate-skill +step. +>>>>>>> 54555c4 (feat: enhance SKILL.md with clarifications on package ownership and skill generation process):packages/playbooks/meta/tree-generator/SKILL.md From 907f399c8cb51f0ab2f6a8d4767b2db1082f8fe1 Mon Sep 17 00:00:00 2001 From: LadyBluenotes Date: Thu, 5 Mar 2026 09:00:55 -0800 Subject: [PATCH 6/6] changset --- .changeset/whole-rocks-wait.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .changeset/whole-rocks-wait.md diff --git a/.changeset/whole-rocks-wait.md b/.changeset/whole-rocks-wait.md new file mode 100644 index 00000000..27fb6f0d --- /dev/null +++ b/.changeset/whole-rocks-wait.md @@ -0,0 +1,32 @@ +--- +'@tanstack/playbooks': patch +--- + +3 files changed in packages/playbooks/meta/ + +domain-discovery/SKILL.md (681 → ~792 lines) +- Added "Hard rules" section: 7 mandatory rules enforcing interactive interviews, prohibiting docs-as-substitute, question collapsing, and interview skipping +- Added 3 STOP gates between phases (1→2, 3→4, and after Phase 2d skill list confirmation) +- Strengthened Phase 2 & 4 headers with explicit interactivity requirements and "wait for response" instructions +- Added Phase 3 thoroughness: file checklist before reading, read-all enforcement, peer dependency analysis in Phase 1b +- Added 7 new constraint table rows for interview interactivity +- Updated cross-model compatibility notes with STOP gate and question protection rationale +- Added cross-package monorepo question in Phase 2a +- Added packages field to domain_map.yaml schema (package-relative ownership model) +- Softened feedback section to alpha-temporary + +- tree-generator/SKILL.md (859 → ~898 lines) +- Strengthened compressed discovery warning (requires maintainer confirmation to skip) +- Added packages field to skill_tree.yaml schema +- Added monorepo placement section with concrete directory tree example showing skills inside each package +- Added STOP gate after Step 1 (file tree review before writing) +- Added STOP gate after Step 8 (validation results review) +- Added 2 new constraint rows (file tree reviewed, validation presented) +- Softened feedback section to alpha-temporary + +- generate-skill/SKILL.md (419 → ~441 lines) +- Added packages field to frontmatter template +- Added monorepo path guidance: skills ship inside each package, not repo root +- Added STOP gate in Step 6: first skill reviewed before generating batch +- Added first-skill-reviewed constraint row +- Softened feedback section to alpha-temporary