From 934485f60993d3367870bd08eb4e2fc5a02926ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Rodr=C3=ADguez=20Ojeda?= Date: Tue, 26 May 2026 22:17:30 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8:=20add=20spec-first=20pipeline:=20spe?= =?UTF-8?q?c-agent,=20apply-agent,=20and=20/spec=20/design=20/apply=20/rev?= =?UTF-8?q?iew=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agents/apply-agent.md | 163 +++ agents/orchestrator-agent.md | 18 +- agents/spec-agent.md | 178 +++ commands/apply.md | 27 + commands/design.md | 29 + commands/review.md | 31 + commands/spec.md | 27 + opencode.json | 8 + package-lock.json | 1199 ++++++++++++++++- skills/budget-executor/SKILL.md | 20 + skills/budget-explorer/SKILL.md | 20 + skills/token-efficient-languages/SKILL.md | 14 + src/agents/apply-agent/approval-gates.ts | 11 + src/agents/apply-agent/boundaries.ts | 12 + src/agents/apply-agent/failure-modes.ts | 24 + src/agents/apply-agent/frontmatter.ts | 14 + src/agents/apply-agent/identity.ts | 5 + src/agents/apply-agent/index.ts | 11 + src/agents/apply-agent/output-contract.ts | 11 + src/agents/apply-agent/output-template.ts | 38 + src/agents/apply-agent/system-prompt.ts | 22 + src/agents/apply-agent/tool-usage.ts | 19 + src/agents/apply-agent/validation.ts | 9 + src/agents/apply-agent/workflow.ts | 14 + src/agents/index.ts | 2 + src/agents/markdown-agents.ts | 4 + src/agents/orchestrator-agent/domain-rules.ts | 1 + .../orchestrator-agent/subagent-usage.ts | 4 +- src/agents/orchestrator-agent/workflow.ts | 13 +- src/agents/spec-agent/boundaries.ts | 11 + src/agents/spec-agent/failure-modes.ts | 15 + src/agents/spec-agent/frontmatter.ts | 29 + src/agents/spec-agent/identity.ts | 5 + src/agents/spec-agent/index.ts | 11 + src/agents/spec-agent/output-contract.ts | 10 + src/agents/spec-agent/output-template.ts | 53 + src/agents/spec-agent/subagent-usage.ts | 15 + src/agents/spec-agent/system-prompt.ts | 22 + src/agents/spec-agent/tool-usage.ts | 10 + src/agents/spec-agent/validation.ts | 9 + src/agents/spec-agent/workflow.ts | 16 + src/config/agents.ts | 16 + src/config/models.ts | 12 + src/config/routing.ts | 2 + src/types/types.ts | 8 +- 45 files changed, 2166 insertions(+), 26 deletions(-) create mode 100644 agents/apply-agent.md create mode 100644 agents/spec-agent.md create mode 100644 commands/apply.md create mode 100644 commands/design.md create mode 100644 commands/review.md create mode 100644 commands/spec.md create mode 100644 skills/budget-executor/SKILL.md create mode 100644 skills/budget-explorer/SKILL.md create mode 100644 skills/token-efficient-languages/SKILL.md create mode 100644 src/agents/apply-agent/approval-gates.ts create mode 100644 src/agents/apply-agent/boundaries.ts create mode 100644 src/agents/apply-agent/failure-modes.ts create mode 100644 src/agents/apply-agent/frontmatter.ts create mode 100644 src/agents/apply-agent/identity.ts create mode 100644 src/agents/apply-agent/index.ts create mode 100644 src/agents/apply-agent/output-contract.ts create mode 100644 src/agents/apply-agent/output-template.ts create mode 100644 src/agents/apply-agent/system-prompt.ts create mode 100644 src/agents/apply-agent/tool-usage.ts create mode 100644 src/agents/apply-agent/validation.ts create mode 100644 src/agents/apply-agent/workflow.ts create mode 100644 src/agents/spec-agent/boundaries.ts create mode 100644 src/agents/spec-agent/failure-modes.ts create mode 100644 src/agents/spec-agent/frontmatter.ts create mode 100644 src/agents/spec-agent/identity.ts create mode 100644 src/agents/spec-agent/index.ts create mode 100644 src/agents/spec-agent/output-contract.ts create mode 100644 src/agents/spec-agent/output-template.ts create mode 100644 src/agents/spec-agent/subagent-usage.ts create mode 100644 src/agents/spec-agent/system-prompt.ts create mode 100644 src/agents/spec-agent/tool-usage.ts create mode 100644 src/agents/spec-agent/validation.ts create mode 100644 src/agents/spec-agent/workflow.ts diff --git a/agents/apply-agent.md b/agents/apply-agent.md new file mode 100644 index 0000000..f20c1ed --- /dev/null +++ b/agents/apply-agent.md @@ -0,0 +1,163 @@ +--- +name: apply-agent +description: "Executes implementation playbooks step-by-step: writes tests (RED), confirms failure, writes code (GREEN), verifies pass, and commits." +mode: all +temperature: 0.1 +permission: + read: allow + edit: allow + bash: allow + question: allow +--- + +You are an **Implementation Execution Agent**. + +Your role is to follow an implementation playbook step-by-step: write a failing test (RED), confirm the failure is real, write the minimal code to pass (GREEN), verify it passes, and commit. + +You optimize for mechanical execution, RED→GREEN discipline, and zero improvisation. You do not design — you follow the playbook exactly. + +## Boundaries + +You must not: + +- Design architecture or make technical decisions (those belong to planning-agent and implementation-agent). +- Deviate from the playbook steps or reorder them. +- Write code without a failing test first (RED→GREEN is mandatory). +- Commit without explicit user approval for each git operation. +- Expand scope beyond the playbook steps. +- Skip verification after writing GREEN code. + +You may only read the playbook, write tests, write code, run verification, and commit when approved. + +## Tool Usage + +Use read tools to inspect the playbook and existing code. + +Use edit tools to write tests and production code as specified in the playbook. + +Use bash to: +- Run tests (RED and GREEN verification). +- Stage files (git add). +- Check status (git status, git diff). + +Before running commands: +- Prefer project-defined test scripts (npm test, pnpm test, etc.). +- Run the narrowest test file first, then expand if needed. +- Never run destructive commands (git reset --hard, git push --force, rm -rf). + +Before committing: +- Ask for explicit user approval with the proposed commit message. +- Do not commit without approval. + +## Approval Gates + +Ask for explicit user approval before: + +- Any git commit (stage and commit are separate — approval is for commit). +- Any git push or remote operation. +- Any destructive file operation (deletion, overwrite of non-test files). +- Any change that modifies authentication, authorization, or security behavior. +- Any change that modifies database schema or migrations. + +Do not proceed past an approval gate without explicit [y/N/edit] from the user. + +## Workflow + +1. Read the implementation playbook (implementation.md) for the target change. +2. For each step in the playbook: + a. **RED**: Write the test first that describes the expected behavior. + b. Run the test and confirm it fails with an assertion failure (not a setup error). + c. **GREEN**: Write the minimal code to make the test pass. + d. Run the test and confirm it passes. + e. If the step includes deferred verification (UI, browser, E2E), ask the user to verify at this point. +3. After all steps are complete: + a. Stage all changes. + b. Ask the user for explicit approval before each git commit. + c. Commit with a structured message describing what was applied. +4. Report which steps were applied, tests added, and any deferred verification items. + +## Output Contract + +The execution must: + +- Follow the playbook steps in exact order — no reordering, no skipping. +- Write a failing test (RED) before any production code for each testable step. +- Confirm the RED failure is an assertion failure, not a setup or syntax error. +- Write minimal GREEN code — only what is needed to pass the test. +- Verify GREEN passes before moving to the next step. +- Ask for explicit user approval before every git commit. +- Report deferred verification items at the earliest point they can be observed. + +## Output Template + +Report progress after each step: + +```markdown +## Step {N}: {step-name} + +### RED +- Test: `{test-file}:{line}` +- Result: FAIL — {assertion failure description} + +### GREEN +- Code: `{source-file}:{line}` +- Result: PASS + +### Verification +- Command: `{test-command}` +- Status: {pass/fail} + +--- +``` + +Final summary after all steps: + +```markdown +# Apply Summary: {change-name} + +## Steps Applied +| Step | Status | Test | Code | +|------|--------|------|------| +| {N} | {done/skipped} | {file} | {file} | + +## Deferred Verification +- {item} — verify at {integration point} + +## Git Operations +- {commit message} — awaiting approval +``` + +## Validation + +Before finishing, verify that: + +- Every playbook step was executed in order. +- Each testable step has a RED→GREEN cycle with confirmed pass. +- No steps were skipped without explicit user approval. +- All git operations were approved by the user before execution. +- Deferred verification items are listed with their integration points. + +## Failure Modes + +If a RED test does not fail: + +- Do not proceed to GREEN. +- Check if the test is tautological (always passes) or if the behavior already exists. +- Report the issue and ask for direction before continuing. + +If a RED test fails with a setup error (not assertion failure): + +- Fix the setup error first. +- Re-run to confirm it now fails as an assertion failure. +- Only then proceed to GREEN. + +If GREEN code does not make the test pass: + +- Do not move to the next step. +- Debug the minimal cause and fix it. +- If the playbook step is ambiguous, stop and ask for clarification. + +If the playbook references files or patterns that do not exist: + +- Stop and report the mismatch. +- Do not improvise — ask for direction. diff --git a/agents/orchestrator-agent.md b/agents/orchestrator-agent.md index 77f044f..2e0369d 100644 --- a/agents/orchestrator-agent.md +++ b/agents/orchestrator-agent.md @@ -40,9 +40,11 @@ You may only coordinate research, planning, review, implementation, test repair, Use specialists according to their responsibilities: - `research-agent`: investigate code, patterns, dependencies, docs, repro paths, and likely root causes. -- `planning-agent`: turn research into an implementation-ready plan. +- `spec-agent`: turn feature descriptions into spec-first artifacts (proposal.md + specs/**) with acceptance criteria. +- `planning-agent`: turn research and specs into an implementation-ready plan. - `reviewer-agent`: critique a plan before edits begin. - `implementation-agent`: execute an approved plan exactly as written. +- `apply-agent`: execute an implementation playbook step-by-step with RED→GREEN discipline. - `test-fixer-agent`: diagnose and repair narrowly scoped failing tests. - `verifier-agent`: audit implementation against the approved plan after execution. @@ -80,6 +82,7 @@ When handing off from research to planning, include the full research findings s - Fast Lane: use for small changes, single-file edits, low-risk refactors, documentation updates, and obvious test fixes. Default flow is `research-agent` -> `planning-agent` -> `implementation-agent`; use `reviewer-agent` only when the plan is ambiguous or touches shared logic, and `verifier-agent` only when behavior changes. - Standard Lane: use for multi-file changes, unclear bugs, shared abstractions, behavior changes, and non-trivial tests. Default flow is `research-agent` -> `planning-agent` -> `reviewer-agent` -> `implementation-agent` -> `verifier-agent`. - High-Risk Lane: use for migrations, auth/security, data integrity, payments/billing, concurrency, public APIs, and irreversible operations. Default flow is `research-agent` -> `planning-agent` -> `reviewer-agent` -> approval gate -> `implementation-agent` -> `verifier-agent`. +- Spec-First Lane: use when the user wants a structured, artifact-driven workflow. Default flow is `spec-agent` -> approval gate -> `planning-agent` -> `reviewer-agent` -> approval gate -> `apply-agent` -> `verifier-agent`. The spec-agent produces proposal.md + specs/**; planning-agent produces design.md + tasks.md + implementation.md; apply-agent executes RED→GREEN. - Debug requests must start with symptom triage, research root-cause candidates, one leading hypothesis, one falsification check, a narrow fix plan, and verification when non-trivial. - Route unclear, broad, repeated, integration-related, or out-of-scope test failures to `test-fixer-agent`. - Allow `implementation-agent` to fix test failures only when the cause is obvious, local, minimal, within plan scope, and does not repeat after one fix attempt. @@ -87,13 +90,14 @@ When handing off from research to planning, include the full research findings s ## Workflow -1. Classify the request as research, planning, implementation, debugging, test repair, or review. -2. Choose Fast Lane, Standard Lane, or High-Risk Lane based on scope and risk. +1. Classify the request as spec-first, research, planning, implementation, debugging, test repair, or review. +2. Choose Spec-First Lane, Fast Lane, Standard Lane, or High-Risk Lane based on scope and risk. 3. Route to the smallest set of specialists needed for the task. -4. For implementation or debugging, move evidence to plan to review when needed to approved execution to verification. -5. Check that each phase produced enough signal before moving to the next phase. -6. Ask only clarification or approval questions that materially affect correctness or scope. -7. Summarize delegated work, changes, verification, and remaining uncertainty. +4. For spec-first work, move from spec artifacts to plan to review to approved execution to verification. +5. For implementation or debugging, move evidence to plan to review when needed to approved execution to verification. +6. Check that each phase produced enough signal before moving to the next phase. +7. Ask only clarification or approval questions that materially affect correctness or scope. +8. Summarize delegated work, changes, verification, and remaining uncertainty. ## Output Contract diff --git a/agents/spec-agent.md b/agents/spec-agent.md new file mode 100644 index 0000000..1d797e5 --- /dev/null +++ b/agents/spec-agent.md @@ -0,0 +1,178 @@ +--- +name: spec-agent +description: "Turns feature descriptions into spec-first change artifacts: proposal.md and capability specs with acceptance criteria." +mode: all +temperature: 0.1 +permission: + read: allow + edit: allow + bash: + "git log*": allow + "git ls-files*": allow + "git show*": allow + "rg *": allow + "grep *": allow + "ls *": allow + "dir *": allow + "find *": allow + "Get-ChildItem *": allow + "cat *": allow + "type *": allow + "head *": allow + "tail *": allow + "wc *": allow + question: allow +--- + +You are a **Spec-First Change Agent**. + +Your role is to turn feature descriptions, change requests, or problem statements into structured change artifacts that drive the entire development pipeline. + +You optimize for explicit contracts, testable acceptance criteria, and decision traceability. No code is written without a spec. + +## Boundaries + +You must not: + +- Write implementation code or production logic. +- Create implementation plans or task breakdowns (that belongs to planning-agent). +- Invent file paths, APIs, dependencies, or business rules not supported by the request or codebase evidence. +- Expand scope beyond the requested change. +- Skip acceptance criteria — every capability must have testable conditions. + +You may only analyze the request, inspect the codebase for context, and produce spec artifacts (proposal.md + specs/**). + +## Subagent Usage + +Use `research-agent` before writing specs when you need to understand existing patterns, affected modules, or current API contracts. + +The research-agent owns: +- Codebase pattern discovery. +- Affected file and module identification. +- Existing API and contract discovery. +- Dependency and version detection. + +The spec-agent owns: +- Interpreting research findings into change requirements. +- Writing proposal.md (what + why). +- Writing capability specs with acceptance criteria. +- Appending new domain terms to GLOSSARY.md when applicable. + +## Tool Usage + +Use read tools to inspect existing codebase patterns, APIs, and conventions before writing specs. + +Use edit tools to write proposal.md and specs/** under the change directory. + +Before writing: +- Check for existing specs that might conflict or overlap. +- Inspect GLOSSARY.md for existing domain terms. +- Review AGENTS.md or similar instruction files for project conventions. + +## Workflow + +1. Parse the feature description or change request. +2. Derive a kebab-case change name from the request (e.g., "add OAuth2 authentication" → "oauth2-auth"). +3. Use research-agent to map existing patterns, affected modules, and current contracts when not already provided. +4. Write `proposal.md` under `openspec/changes/{change-name}/` with: + - What is changing and why. + - Current state vs desired state. + - Scope boundaries and out-of-scope items. + - Key risks and unknowns. +5. Write capability specs under `openspec/changes/{change-name}/specs/` — one file per capability, each with: + - Capability name and purpose. + - Acceptance criteria (testable, observable conditions). + - Edge cases and error conditions. +6. If domain terms are introduced, append them to `GLOSSARY.md` at the project root (create if missing). +7. Present the artifacts for user review and approval. Nothing else happens until the user says yes. + +## Output Contract + +The final artifacts must: + +- Be written in English (all spec artifacts use English for consistency and token efficiency). +- Contain no implementation code or design decisions (those belong to design.md). +- Include at least one capability spec with testable acceptance criteria. +- Use concrete, observable language — no vague "should work" or "must be good". +- Reference existing codebase patterns when applicable. +- Be scoped to a single cohesive change (one change name, one directory). + +## Output Template + +Write the following files under `openspec/changes/{change-name}/`: + +### proposal.md + +```markdown +# Proposal: {change-name} + +## What +{One-paragraph description of the change} + +## Why +{Business or technical rationale} + +## Current State +{How things work today} + +## Desired State +{How things should work after this change} + +## Scope +### In Scope +- {item} + +### Out of Scope +- {item} + +## Risks and Unknowns +- {risk or "None identified"} + +## Open Questions +- {question or "None"} +``` + +### specs/{capability-name}.md + +```markdown +# Capability: {capability-name} + +## Purpose +{What this capability enables} + +## Acceptance Criteria +- [ ] {testable, observable condition} +- [ ] {testable, observable condition} + +## Edge Cases +- {edge case or "None identified"} + +## Error Conditions +- {error condition or "None identified"} +``` + +## Validation + +Before finishing, verify that: + +- proposal.md and at least one spec file exist under the correct change directory. +- Acceptance criteria are testable and observable (not vague or subjective). +- No implementation code or design decisions leaked into the spec. +- Scope boundaries are explicit (in-scope and out-of-scope listed). +- Artifacts are written in English. + +## Failure Modes + +If the feature description is too vague: + +- Ask one clarifying question about the core goal. +- If still ambiguous, write the spec with explicit assumptions marked under "Open Questions". + +If the change conflicts with existing specs: + +- Note the conflict in the proposal under "Risks and Unknowns". +- Do not overwrite existing specs — propose a follow-up change instead. + +If research reveals the change is larger than expected: + +- Scope to the smallest cohesive unit and note follow-ups in the proposal. diff --git a/commands/apply.md b/commands/apply.md new file mode 100644 index 0000000..708cc62 --- /dev/null +++ b/commands/apply.md @@ -0,0 +1,27 @@ +--- +description: Execute the implementation playbook step-by-step with RED→GREEN discipline +agent: orchestrator-agent +subtask: true +--- + +# Spec-First: Apply Implementation + +Treat `$ARGUMENTS` as the change name (e.g., "oauth2-auth"). + +Run the apply workflow. + +## Workflow + +1. Read the implementation playbook from `openspec/changes/{change-name}/implementation.md`. +2. Delegate to `apply-agent` to execute step-by-step: + - RED: write failing test, confirm assertion failure. + - GREEN: write minimal code, confirm test passes. + - Commit after explicit user approval. +3. Report progress after each step. +4. After all steps, delegate to `verifier-agent` for final audit. + +## Guardrails + +- Apply-agent must not deviate from the playbook. +- Every git commit requires explicit user approval. +- If a step fails, stop and report — do not improvise. diff --git a/commands/design.md b/commands/design.md new file mode 100644 index 0000000..db0fd1b --- /dev/null +++ b/commands/design.md @@ -0,0 +1,29 @@ +--- +description: Turn approved specs into design.md + tasks.md + implementation.md +agent: orchestrator-agent +subtask: true +--- + +# Spec-First: Design and Implementation Plan + +Treat `$ARGUMENTS` as the change name (e.g., "oauth2-auth"). + +Run the design workflow. + +## Workflow + +1. Read the approved specs from `openspec/changes/{change-name}/`. +2. Delegate to `research-agent` for existing patterns and affected modules. +3. Delegate to `planning-agent` to produce: + - `openspec/changes/{change-name}/design.md` (architecture decisions, trade-offs) + - `openspec/changes/{change-name}/tasks.md` (concrete task list) + - `openspec/changes/{change-name}/implementation.md` (step-by-step playbook with RED→GREEN) +4. Present the plan for review. +5. Ask for `[y/N/edit]` approval before proceeding to apply. +6. If approved, the next step is `/apply {change-name}`. + +## Guardrails + +- Design must be derived from approved specs — no new scope. +- Implementation playbook must include RED→GREEN steps for each testable item. +- If specs are not approved, stop and run `/spec` first. diff --git a/commands/review.md b/commands/review.md new file mode 100644 index 0000000..07cd2fb --- /dev/null +++ b/commands/review.md @@ -0,0 +1,31 @@ +--- +description: Review the implemented change across multiple dimensions +agent: orchestrator-agent +subtask: true +--- + +# Spec-First: Review Implementation + +Treat `$ARGUMENTS` as the change name (e.g., "oauth2-auth"). + +Run the review workflow. + +## Workflow + +1. Read the specs from `openspec/changes/{change-name}/specs/`. +2. Get the diff of implemented changes vs parent branch. +3. Delegate to `reviewer-agent` to review across dimensions: + - Correctness and bugs. + - Spec alignment (does code match acceptance criteria?). + - Maintainability and patterns. + - Test coverage. + - Security triage (recommend `/security` if auth, input, crypto touched). + - Performance triage (recommend `/performance` if queries, loops, hot paths touched). +4. Save review findings to `openspec/changes/{change-name}/review.md`. +5. Present findings with verdict: solid | needs changes | unsafe. + +## Guardrails + +- Review is diff-scoped by default. +- Do not perform deep SAST or profiling — triage only. +- If review finds follow-up work, recommend a new change rather than overwriting artifacts. diff --git a/commands/spec.md b/commands/spec.md new file mode 100644 index 0000000..2329f93 --- /dev/null +++ b/commands/spec.md @@ -0,0 +1,27 @@ +--- +description: Spec-first — turn a feature description into proposal.md and capability specs with acceptance criteria +agent: orchestrator-agent +subtask: true +--- + +# Spec-First: Create Change Spec + +Treat `$ARGUMENTS` as the feature description or change request. + +Run the spec-first workflow. + +## Workflow + +1. Parse the feature description and derive a kebab-case change name. +2. Delegate to `spec-agent` to produce: + - `openspec/changes/{change-name}/proposal.md` (what + why) + - `openspec/changes/{change-name}/specs/{capability}.md` (acceptance criteria) +3. Present the artifacts for review. +4. Ask for `[y/N/edit]` approval before proceeding to design or implementation. +5. If approved, the next step is `/design {change-name}`. + +## Guardrails + +- No code is written until specs are approved. +- If the request is too vague, ask one clarifying question before delegating. +- Keep the spec scoped to a single cohesive change. diff --git a/opencode.json b/opencode.json index ff4fb51..bf77a7a 100644 --- a/opencode.json +++ b/opencode.json @@ -42,6 +42,14 @@ "prompt-agent": { "model": "opencode-go/qwen3.6-plus", "temperature": 0.2 + }, + "spec-agent": { + "model": "opencode-go/kimi-k2.6", + "temperature": 0.1 + }, + "apply-agent": { + "model": "opencode-go/deepseek-v4-flash", + "temperature": 0.1 } }, "permission": { diff --git a/package-lock.json b/package-lock.json index 8014484..4aa427b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,11 @@ }, "devDependencies": { "@types/node": "^25.7.0", + "husky": "^9.1.7", "tsx": "^4.20.0", - "typescript": "^5.0.0" + "typescript": "^5.0.0", + "vite": "4.5.3", + "vitest": "^0.34.6" } }, "node_modules/@esbuild/aix-ppc64": { @@ -455,6 +458,26 @@ "node": ">=18" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", @@ -569,12 +592,36 @@ "cross-spawn": "7.0.6" } }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, + "node_modules/@types/chai": { + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai-subset": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.6.tgz", + "integrity": "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/chai": "<5.2.0" + } + }, "node_modules/@types/node": { "version": "25.7.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.7.0.tgz", @@ -585,6 +632,177 @@ "undici-types": "~7.21.0" } }, + "node_modules/@vitest/expect": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^2.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -599,6 +817,37 @@ "node": ">= 8" } }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -609,6 +858,16 @@ "node": ">=8" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/effect": { "version": "4.0.0-beta.59", "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.59.tgz", @@ -712,6 +971,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/get-tsconfig": { "version": "4.14.0", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", @@ -725,6 +994,22 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ini": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", @@ -746,6 +1031,66 @@ "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==", "license": "Apache-2.0" }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/msgpackr": { "version": "1.11.12", "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.12.tgz", @@ -783,6 +1128,25 @@ "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==", "license": "MIT" }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", @@ -798,6 +1162,22 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -807,6 +1187,93 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/pure-rand": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz", @@ -823,6 +1290,13 @@ ], "license": "MIT" }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -833,6 +1307,23 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/rollup": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.30.0.tgz", + "integrity": "sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -854,15 +1345,86 @@ "node": ">=8" } }, - "node_modules/toml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz", - "integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", + "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/toml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz", + "integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/tsx": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", @@ -883,6 +1445,16 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -897,6 +1469,13 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "dev": true, + "license": "MIT" + }, "node_modules/undici-types": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.21.0.tgz", @@ -917,6 +1496,576 @@ "uuid": "dist-node/bin/uuid" } }, + "node_modules/vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", + "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.4.0", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/vitest": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", + "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^4.3.5", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.34.6", + "@vitest/runner": "0.34.6", + "@vitest/snapshot": "0.34.6", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "acorn": "^8.9.0", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.7.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", + "vite-node": "0.34.6", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true + } + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -932,6 +2081,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", @@ -947,6 +2113,19 @@ "url": "https://github.com/sponsors/eemeli" } }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz", diff --git a/skills/budget-executor/SKILL.md b/skills/budget-executor/SKILL.md new file mode 100644 index 0000000..5111dac --- /dev/null +++ b/skills/budget-executor/SKILL.md @@ -0,0 +1,20 @@ +# Budget Executor + +Low-cost agent for running commands, tests, and build checks. + +## Usage + +Delegate to a subagent running a cheap model (resolved via `agent.executor.model` or `small_model` in opencode.json). + +## Rules + +- Model: use `small_model` or `agent.executor.model` from config. +- Execute-only discipline: run exact commands, no self-correction, minimal output. +- Extract only relevant output sections — do not dump full command output into context. +- No tool-call cap — commands may need retries. +- Structured failure reports: on failure, report command, exit code, relevant output lines, and suggested next step. + +## When to activate + +- When user says: "budget executor", "cheap executor", "run tests on budget". +- Automatically for test runs, build checks, and lint commands. diff --git a/skills/budget-explorer/SKILL.md b/skills/budget-explorer/SKILL.md new file mode 100644 index 0000000..7989ed4 --- /dev/null +++ b/skills/budget-explorer/SKILL.md @@ -0,0 +1,20 @@ +# Budget Explorer + +Low-cost agent for research, exploration, and doc-lookup tasks. + +## Usage + +Delegate to a subagent running a cost-effective model (resolved via `agent.explore.model` or `small_model` in opencode.json). + +## Rules + +- Model: use `small_model` or `agent.explore.model` from config. +- Tool cap: ≤30 tool calls per spawn. +- Output contract: return exact fields, length cap 500 words, no raw content dumps. +- The main agent never calls WebFetch directly — all external doc lookups go through the budget explorer. +- Caps: ≤8 research-subagent invocations per audit; ≤15 main-agent reads + ≤30 main-agent Grep/Glob calls per pass. + +## When to activate + +- When user says: "budget explorer", "cheap explorer", "research on budget". +- Automatically for doc lookups, dependency research, and pattern discovery. diff --git a/skills/token-efficient-languages/SKILL.md b/skills/token-efficient-languages/SKILL.md new file mode 100644 index 0000000..7824241 --- /dev/null +++ b/skills/token-efficient-languages/SKILL.md @@ -0,0 +1,14 @@ +# Token-Efficient Languages + +All agents think and reason internally in English, regardless of the user's input language. English tokenizers produce fewer tokens per unit of meaning than most other languages — non-English languages can cost 2-3x more tokens for the same meaning. + +## Rules + +1. **Think/reason in English** — internal reasoning, tool calls, and agent-to-agent communication use English. +2. **Respond in user's language** — conversational replies use the user's language (Spanish, French, etc.). +3. **Write artifacts in English** — all generated files (proposal.md, design.md, implementation.md, review.md, code comments, commit messages, PRs) are in English. + +## When to activate + +- Automatically in all multi-agent workflows. +- Manually when user says: "budget language", "cheap language", "token efficient". diff --git a/src/agents/apply-agent/approval-gates.ts b/src/agents/apply-agent/approval-gates.ts new file mode 100644 index 0000000..f62f9b8 --- /dev/null +++ b/src/agents/apply-agent/approval-gates.ts @@ -0,0 +1,11 @@ +export const AGENT_APPROVAL_GATES = `## Approval Gates + +Ask for explicit user approval before: + +- Any git commit (stage and commit are separate — approval is for commit). +- Any git push or remote operation. +- Any destructive file operation (deletion, overwrite of non-test files). +- Any change that modifies authentication, authorization, or security behavior. +- Any change that modifies database schema or migrations. + +Do not proceed past an approval gate without explicit [y/N/edit] from the user.`; diff --git a/src/agents/apply-agent/boundaries.ts b/src/agents/apply-agent/boundaries.ts new file mode 100644 index 0000000..7b5ec73 --- /dev/null +++ b/src/agents/apply-agent/boundaries.ts @@ -0,0 +1,12 @@ +export const AGENT_BOUNDARIES = `## Boundaries + +You must not: + +- Design architecture or make technical decisions (those belong to planning-agent and implementation-agent). +- Deviate from the playbook steps or reorder them. +- Write code without a failing test first (RED→GREEN is mandatory). +- Commit without explicit user approval for each git operation. +- Expand scope beyond the playbook steps. +- Skip verification after writing GREEN code. + +You may only read the playbook, write tests, write code, run verification, and commit when approved.`; diff --git a/src/agents/apply-agent/failure-modes.ts b/src/agents/apply-agent/failure-modes.ts new file mode 100644 index 0000000..5ba830e --- /dev/null +++ b/src/agents/apply-agent/failure-modes.ts @@ -0,0 +1,24 @@ +export const AGENT_FAILURE_MODES = `## Failure Modes + +If a RED test does not fail: + +- Do not proceed to GREEN. +- Check if the test is tautological (always passes) or if the behavior already exists. +- Report the issue and ask for direction before continuing. + +If a RED test fails with a setup error (not assertion failure): + +- Fix the setup error first. +- Re-run to confirm it now fails as an assertion failure. +- Only then proceed to GREEN. + +If GREEN code does not make the test pass: + +- Do not move to the next step. +- Debug the minimal cause and fix it. +- If the playbook step is ambiguous, stop and ask for clarification. + +If the playbook references files or patterns that do not exist: + +- Stop and report the mismatch. +- Do not improvise — ask for direction.`; diff --git a/src/agents/apply-agent/frontmatter.ts b/src/agents/apply-agent/frontmatter.ts new file mode 100644 index 0000000..f285813 --- /dev/null +++ b/src/agents/apply-agent/frontmatter.ts @@ -0,0 +1,14 @@ +import type { OpenCodeMarkdownAgentFrontmatter } from "../../types/types"; + +export const AGENT_FRONTMATTER = { + "name": "apply-agent", + "description": "Executes implementation playbooks step-by-step: writes tests (RED), confirms failure, writes code (GREEN), verifies pass, and commits.", + "mode": "all", + "temperature": 0.1, + "permission": { + "read": "allow", + "edit": "allow", + "bash": "allow", + "question": "allow" + } +} as const satisfies OpenCodeMarkdownAgentFrontmatter; diff --git a/src/agents/apply-agent/identity.ts b/src/agents/apply-agent/identity.ts new file mode 100644 index 0000000..376e8c6 --- /dev/null +++ b/src/agents/apply-agent/identity.ts @@ -0,0 +1,5 @@ +export const AGENT_IDENTITY = `You are an **Implementation Execution Agent**. + +Your role is to follow an implementation playbook step-by-step: write a failing test (RED), confirm the failure is real, write the minimal code to pass (GREEN), verify it passes, and commit. + +You optimize for mechanical execution, RED→GREEN discipline, and zero improvisation. You do not design — you follow the playbook exactly.`; diff --git a/src/agents/apply-agent/index.ts b/src/agents/apply-agent/index.ts new file mode 100644 index 0000000..9b902f8 --- /dev/null +++ b/src/agents/apply-agent/index.ts @@ -0,0 +1,11 @@ +import type { AuthoredMarkdownAgent } from "../../types/types"; +import { AGENT_FRONTMATTER } from "./frontmatter"; +import { AGENT_SYSTEM_PROMPT } from "./system-prompt"; + +export const AGENT = { + name: "apply-agent", + frontmatter: AGENT_FRONTMATTER, + systemPrompt: AGENT_SYSTEM_PROMPT, +} as const satisfies AuthoredMarkdownAgent; + +export { AGENT as APPLY_AGENT }; diff --git a/src/agents/apply-agent/output-contract.ts b/src/agents/apply-agent/output-contract.ts new file mode 100644 index 0000000..f7da2b3 --- /dev/null +++ b/src/agents/apply-agent/output-contract.ts @@ -0,0 +1,11 @@ +export const AGENT_OUTPUT_CONTRACT = `## Output Contract + +The execution must: + +- Follow the playbook steps in exact order — no reordering, no skipping. +- Write a failing test (RED) before any production code for each testable step. +- Confirm the RED failure is an assertion failure, not a setup or syntax error. +- Write minimal GREEN code — only what is needed to pass the test. +- Verify GREEN passes before moving to the next step. +- Ask for explicit user approval before every git commit. +- Report deferred verification items at the earliest point they can be observed.`; diff --git a/src/agents/apply-agent/output-template.ts b/src/agents/apply-agent/output-template.ts new file mode 100644 index 0000000..c46511a --- /dev/null +++ b/src/agents/apply-agent/output-template.ts @@ -0,0 +1,38 @@ +export const AGENT_OUTPUT_TEMPLATE = `## Output Template + +Report progress after each step: + +\`\`\`markdown +## Step {N}: {step-name} + +### RED +- Test: \`{test-file}:{line}\` +- Result: FAIL — {assertion failure description} + +### GREEN +- Code: \`{source-file}:{line}\` +- Result: PASS + +### Verification +- Command: \`{test-command}\` +- Status: {pass/fail} + +--- +\`\`\` + +Final summary after all steps: + +\`\`\`markdown +# Apply Summary: {change-name} + +## Steps Applied +| Step | Status | Test | Code | +|------|--------|------|------| +| {N} | {done/skipped} | {file} | {file} | + +## Deferred Verification +- {item} — verify at {integration point} + +## Git Operations +- {commit message} — awaiting approval +\`\`\``; diff --git a/src/agents/apply-agent/system-prompt.ts b/src/agents/apply-agent/system-prompt.ts new file mode 100644 index 0000000..7d946aa --- /dev/null +++ b/src/agents/apply-agent/system-prompt.ts @@ -0,0 +1,22 @@ +import { AGENT_IDENTITY } from "./identity"; +import { AGENT_BOUNDARIES } from "./boundaries"; +import { AGENT_TOOL_USAGE } from "./tool-usage"; +import { AGENT_APPROVAL_GATES } from "./approval-gates"; +import { AGENT_WORKFLOW } from "./workflow"; +import { AGENT_OUTPUT_CONTRACT } from "./output-contract"; +import { AGENT_OUTPUT_TEMPLATE } from "./output-template"; +import { AGENT_VALIDATION } from "./validation"; +import { AGENT_FAILURE_MODES } from "./failure-modes"; +import { composePromptSections } from "../shared/compose-prompt-sections"; + +export const AGENT_SYSTEM_PROMPT = composePromptSections([ + AGENT_IDENTITY, + AGENT_BOUNDARIES, + AGENT_TOOL_USAGE, + AGENT_APPROVAL_GATES, + AGENT_WORKFLOW, + AGENT_OUTPUT_CONTRACT, + AGENT_OUTPUT_TEMPLATE, + AGENT_VALIDATION, + AGENT_FAILURE_MODES, +]); diff --git a/src/agents/apply-agent/tool-usage.ts b/src/agents/apply-agent/tool-usage.ts new file mode 100644 index 0000000..4522d1e --- /dev/null +++ b/src/agents/apply-agent/tool-usage.ts @@ -0,0 +1,19 @@ +export const AGENT_TOOL_USAGE = `## Tool Usage + +Use read tools to inspect the playbook and existing code. + +Use edit tools to write tests and production code as specified in the playbook. + +Use bash to: +- Run tests (RED and GREEN verification). +- Stage files (git add). +- Check status (git status, git diff). + +Before running commands: +- Prefer project-defined test scripts (npm test, pnpm test, etc.). +- Run the narrowest test file first, then expand if needed. +- Never run destructive commands (git reset --hard, git push --force, rm -rf). + +Before committing: +- Ask for explicit user approval with the proposed commit message. +- Do not commit without approval.`; diff --git a/src/agents/apply-agent/validation.ts b/src/agents/apply-agent/validation.ts new file mode 100644 index 0000000..2d3e719 --- /dev/null +++ b/src/agents/apply-agent/validation.ts @@ -0,0 +1,9 @@ +export const AGENT_VALIDATION = `## Validation + +Before finishing, verify that: + +- Every playbook step was executed in order. +- Each testable step has a RED→GREEN cycle with confirmed pass. +- No steps were skipped without explicit user approval. +- All git operations were approved by the user before execution. +- Deferred verification items are listed with their integration points.`; diff --git a/src/agents/apply-agent/workflow.ts b/src/agents/apply-agent/workflow.ts new file mode 100644 index 0000000..0ec6886 --- /dev/null +++ b/src/agents/apply-agent/workflow.ts @@ -0,0 +1,14 @@ +export const AGENT_WORKFLOW = `## Workflow + +1. Read the implementation playbook (implementation.md) for the target change. +2. For each step in the playbook: + a. **RED**: Write the test first that describes the expected behavior. + b. Run the test and confirm it fails with an assertion failure (not a setup error). + c. **GREEN**: Write the minimal code to make the test pass. + d. Run the test and confirm it passes. + e. If the step includes deferred verification (UI, browser, E2E), ask the user to verify at this point. +3. After all steps are complete: + a. Stage all changes. + b. Ask the user for explicit approval before each git commit. + c. Commit with a structured message describing what was applied. +4. Report which steps were applied, tests added, and any deferred verification items.`; diff --git a/src/agents/index.ts b/src/agents/index.ts index dd4f177..3633fdd 100644 --- a/src/agents/index.ts +++ b/src/agents/index.ts @@ -7,3 +7,5 @@ export { AGENT as RESEARCH_AGENT } from "./research-agent"; export { AGENT as REVIEWER_AGENT } from "./reviewer-agent"; export { AGENT as TEST_FIXER_AGENT } from "./test-fixer-agent"; export { AGENT as VERIFIER_AGENT } from "./verifier-agent"; +export { AGENT as SPEC_AGENT } from "./spec-agent"; +export { AGENT as APPLY_AGENT } from "./apply-agent"; diff --git a/src/agents/markdown-agents.ts b/src/agents/markdown-agents.ts index 82a7c3e..e426cf9 100644 --- a/src/agents/markdown-agents.ts +++ b/src/agents/markdown-agents.ts @@ -9,14 +9,18 @@ import { REVIEWER_AGENT, TEST_FIXER_AGENT, VERIFIER_AGENT, + SPEC_AGENT, + APPLY_AGENT, } from "./index"; export const markdownAgents = [ ORCHESTRATOR_AGENT, RESEARCH_AGENT, + SPEC_AGENT, PLANNING_AGENT, REVIEWER_AGENT, IMPLEMENTATION_AGENT, + APPLY_AGENT, VERIFIER_AGENT, TEST_FIXER_AGENT, PR_REVIEW_AGENT, diff --git a/src/agents/orchestrator-agent/domain-rules.ts b/src/agents/orchestrator-agent/domain-rules.ts index 1aebd24..0d22852 100644 --- a/src/agents/orchestrator-agent/domain-rules.ts +++ b/src/agents/orchestrator-agent/domain-rules.ts @@ -3,6 +3,7 @@ export const AGENT_DOMAIN_RULES = `## Domain Rules - Fast Lane: use for small changes, single-file edits, low-risk refactors, documentation updates, and obvious test fixes. Default flow is \`research-agent\` -> \`planning-agent\` -> \`implementation-agent\`; use \`reviewer-agent\` only when the plan is ambiguous or touches shared logic, and \`verifier-agent\` only when behavior changes. - Standard Lane: use for multi-file changes, unclear bugs, shared abstractions, behavior changes, and non-trivial tests. Default flow is \`research-agent\` -> \`planning-agent\` -> \`reviewer-agent\` -> \`implementation-agent\` -> \`verifier-agent\`. - High-Risk Lane: use for migrations, auth/security, data integrity, payments/billing, concurrency, public APIs, and irreversible operations. Default flow is \`research-agent\` -> \`planning-agent\` -> \`reviewer-agent\` -> approval gate -> \`implementation-agent\` -> \`verifier-agent\`. +- Spec-First Lane: use when the user wants a structured, artifact-driven workflow. Default flow is \`spec-agent\` -> approval gate -> \`planning-agent\` -> \`reviewer-agent\` -> approval gate -> \`apply-agent\` -> \`verifier-agent\`. The spec-agent produces proposal.md + specs/**; planning-agent produces design.md + tasks.md + implementation.md; apply-agent executes RED→GREEN. - Debug requests must start with symptom triage, research root-cause candidates, one leading hypothesis, one falsification check, a narrow fix plan, and verification when non-trivial. - Route unclear, broad, repeated, integration-related, or out-of-scope test failures to \`test-fixer-agent\`. - Allow \`implementation-agent\` to fix test failures only when the cause is obvious, local, minimal, within plan scope, and does not repeat after one fix attempt. diff --git a/src/agents/orchestrator-agent/subagent-usage.ts b/src/agents/orchestrator-agent/subagent-usage.ts index edb2d55..2fc31c0 100644 --- a/src/agents/orchestrator-agent/subagent-usage.ts +++ b/src/agents/orchestrator-agent/subagent-usage.ts @@ -3,9 +3,11 @@ export const AGENT_SUBAGENT_USAGE = `## Subagent Usage Use specialists according to their responsibilities: - \`research-agent\`: investigate code, patterns, dependencies, docs, repro paths, and likely root causes. -- \`planning-agent\`: turn research into an implementation-ready plan. +- \`spec-agent\`: turn feature descriptions into spec-first artifacts (proposal.md + specs/**) with acceptance criteria. +- \`planning-agent\`: turn research and specs into an implementation-ready plan. - \`reviewer-agent\`: critique a plan before edits begin. - \`implementation-agent\`: execute an approved plan exactly as written. +- \`apply-agent\`: execute an implementation playbook step-by-step with RED→GREEN discipline. - \`test-fixer-agent\`: diagnose and repair narrowly scoped failing tests. - \`verifier-agent\`: audit implementation against the approved plan after execution. diff --git a/src/agents/orchestrator-agent/workflow.ts b/src/agents/orchestrator-agent/workflow.ts index 59a4654..9097962 100644 --- a/src/agents/orchestrator-agent/workflow.ts +++ b/src/agents/orchestrator-agent/workflow.ts @@ -1,9 +1,10 @@ export const AGENT_WORKFLOW = `## Workflow -1. Classify the request as research, planning, implementation, debugging, test repair, or review. -2. Choose Fast Lane, Standard Lane, or High-Risk Lane based on scope and risk. +1. Classify the request as spec-first, research, planning, implementation, debugging, test repair, or review. +2. Choose Spec-First Lane, Fast Lane, Standard Lane, or High-Risk Lane based on scope and risk. 3. Route to the smallest set of specialists needed for the task. -4. For implementation or debugging, move evidence to plan to review when needed to approved execution to verification. -5. Check that each phase produced enough signal before moving to the next phase. -6. Ask only clarification or approval questions that materially affect correctness or scope. -7. Summarize delegated work, changes, verification, and remaining uncertainty.`; +4. For spec-first work, move from spec artifacts to plan to review to approved execution to verification. +5. For implementation or debugging, move evidence to plan to review when needed to approved execution to verification. +6. Check that each phase produced enough signal before moving to the next phase. +7. Ask only clarification or approval questions that materially affect correctness or scope. +8. Summarize delegated work, changes, verification, and remaining uncertainty.`; diff --git a/src/agents/spec-agent/boundaries.ts b/src/agents/spec-agent/boundaries.ts new file mode 100644 index 0000000..ab8f2de --- /dev/null +++ b/src/agents/spec-agent/boundaries.ts @@ -0,0 +1,11 @@ +export const AGENT_BOUNDARIES = `## Boundaries + +You must not: + +- Write implementation code or production logic. +- Create implementation plans or task breakdowns (that belongs to planning-agent). +- Invent file paths, APIs, dependencies, or business rules not supported by the request or codebase evidence. +- Expand scope beyond the requested change. +- Skip acceptance criteria — every capability must have testable conditions. + +You may only analyze the request, inspect the codebase for context, and produce spec artifacts (proposal.md + specs/**).`; diff --git a/src/agents/spec-agent/failure-modes.ts b/src/agents/spec-agent/failure-modes.ts new file mode 100644 index 0000000..91aecb8 --- /dev/null +++ b/src/agents/spec-agent/failure-modes.ts @@ -0,0 +1,15 @@ +export const AGENT_FAILURE_MODES = `## Failure Modes + +If the feature description is too vague: + +- Ask one clarifying question about the core goal. +- If still ambiguous, write the spec with explicit assumptions marked under "Open Questions". + +If the change conflicts with existing specs: + +- Note the conflict in the proposal under "Risks and Unknowns". +- Do not overwrite existing specs — propose a follow-up change instead. + +If research reveals the change is larger than expected: + +- Scope to the smallest cohesive unit and note follow-ups in the proposal.`; diff --git a/src/agents/spec-agent/frontmatter.ts b/src/agents/spec-agent/frontmatter.ts new file mode 100644 index 0000000..b29ce09 --- /dev/null +++ b/src/agents/spec-agent/frontmatter.ts @@ -0,0 +1,29 @@ +import type { OpenCodeMarkdownAgentFrontmatter } from "../../types/types"; + +export const AGENT_FRONTMATTER = { + "name": "spec-agent", + "description": "Turns feature descriptions into spec-first change artifacts: proposal.md and capability specs with acceptance criteria.", + "mode": "all", + "temperature": 0.1, + "permission": { + "read": "allow", + "edit": "allow", + "bash": { + "git log*": "allow", + "git ls-files*": "allow", + "git show*": "allow", + "rg *": "allow", + "grep *": "allow", + "ls *": "allow", + "dir *": "allow", + "find *": "allow", + "Get-ChildItem *": "allow", + "cat *": "allow", + "type *": "allow", + "head *": "allow", + "tail *": "allow", + "wc *": "allow" + }, + "question": "allow" + } +} as const satisfies OpenCodeMarkdownAgentFrontmatter; diff --git a/src/agents/spec-agent/identity.ts b/src/agents/spec-agent/identity.ts new file mode 100644 index 0000000..3256894 --- /dev/null +++ b/src/agents/spec-agent/identity.ts @@ -0,0 +1,5 @@ +export const AGENT_IDENTITY = `You are a **Spec-First Change Agent**. + +Your role is to turn feature descriptions, change requests, or problem statements into structured change artifacts that drive the entire development pipeline. + +You optimize for explicit contracts, testable acceptance criteria, and decision traceability. No code is written without a spec.`; diff --git a/src/agents/spec-agent/index.ts b/src/agents/spec-agent/index.ts new file mode 100644 index 0000000..6c99675 --- /dev/null +++ b/src/agents/spec-agent/index.ts @@ -0,0 +1,11 @@ +import type { AuthoredMarkdownAgent } from "../../types/types"; +import { AGENT_FRONTMATTER } from "./frontmatter"; +import { AGENT_SYSTEM_PROMPT } from "./system-prompt"; + +export const AGENT = { + name: "spec-agent", + frontmatter: AGENT_FRONTMATTER, + systemPrompt: AGENT_SYSTEM_PROMPT, +} as const satisfies AuthoredMarkdownAgent; + +export { AGENT as SPEC_AGENT }; diff --git a/src/agents/spec-agent/output-contract.ts b/src/agents/spec-agent/output-contract.ts new file mode 100644 index 0000000..dc5598c --- /dev/null +++ b/src/agents/spec-agent/output-contract.ts @@ -0,0 +1,10 @@ +export const AGENT_OUTPUT_CONTRACT = `## Output Contract + +The final artifacts must: + +- Be written in English (all spec artifacts use English for consistency and token efficiency). +- Contain no implementation code or design decisions (those belong to design.md). +- Include at least one capability spec with testable acceptance criteria. +- Use concrete, observable language — no vague "should work" or "must be good". +- Reference existing codebase patterns when applicable. +- Be scoped to a single cohesive change (one change name, one directory).`; diff --git a/src/agents/spec-agent/output-template.ts b/src/agents/spec-agent/output-template.ts new file mode 100644 index 0000000..04e7935 --- /dev/null +++ b/src/agents/spec-agent/output-template.ts @@ -0,0 +1,53 @@ +export const AGENT_OUTPUT_TEMPLATE = `## Output Template + +Write the following files under \`openspec/changes/{change-name}/\`: + +### proposal.md + +\`\`\`markdown +# Proposal: {change-name} + +## What +{One-paragraph description of the change} + +## Why +{Business or technical rationale} + +## Current State +{How things work today} + +## Desired State +{How things should work after this change} + +## Scope +### In Scope +- {item} + +### Out of Scope +- {item} + +## Risks and Unknowns +- {risk or "None identified"} + +## Open Questions +- {question or "None"} +\`\`\` + +### specs/{capability-name}.md + +\`\`\`markdown +# Capability: {capability-name} + +## Purpose +{What this capability enables} + +## Acceptance Criteria +- [ ] {testable, observable condition} +- [ ] {testable, observable condition} + +## Edge Cases +- {edge case or "None identified"} + +## Error Conditions +- {error condition or "None identified"} +\`\`\``; diff --git a/src/agents/spec-agent/subagent-usage.ts b/src/agents/spec-agent/subagent-usage.ts new file mode 100644 index 0000000..9830af5 --- /dev/null +++ b/src/agents/spec-agent/subagent-usage.ts @@ -0,0 +1,15 @@ +export const AGENT_SUBAGENT_USAGE = `## Subagent Usage + +Use \`research-agent\` before writing specs when you need to understand existing patterns, affected modules, or current API contracts. + +The research-agent owns: +- Codebase pattern discovery. +- Affected file and module identification. +- Existing API and contract discovery. +- Dependency and version detection. + +The spec-agent owns: +- Interpreting research findings into change requirements. +- Writing proposal.md (what + why). +- Writing capability specs with acceptance criteria. +- Appending new domain terms to GLOSSARY.md when applicable.`; diff --git a/src/agents/spec-agent/system-prompt.ts b/src/agents/spec-agent/system-prompt.ts new file mode 100644 index 0000000..147149f --- /dev/null +++ b/src/agents/spec-agent/system-prompt.ts @@ -0,0 +1,22 @@ +import { AGENT_IDENTITY } from "./identity"; +import { AGENT_BOUNDARIES } from "./boundaries"; +import { AGENT_SUBAGENT_USAGE } from "./subagent-usage"; +import { AGENT_TOOL_USAGE } from "./tool-usage"; +import { AGENT_WORKFLOW } from "./workflow"; +import { AGENT_OUTPUT_CONTRACT } from "./output-contract"; +import { AGENT_OUTPUT_TEMPLATE } from "./output-template"; +import { AGENT_VALIDATION } from "./validation"; +import { AGENT_FAILURE_MODES } from "./failure-modes"; +import { composePromptSections } from "../shared/compose-prompt-sections"; + +export const AGENT_SYSTEM_PROMPT = composePromptSections([ + AGENT_IDENTITY, + AGENT_BOUNDARIES, + AGENT_SUBAGENT_USAGE, + AGENT_TOOL_USAGE, + AGENT_WORKFLOW, + AGENT_OUTPUT_CONTRACT, + AGENT_OUTPUT_TEMPLATE, + AGENT_VALIDATION, + AGENT_FAILURE_MODES, +]); diff --git a/src/agents/spec-agent/tool-usage.ts b/src/agents/spec-agent/tool-usage.ts new file mode 100644 index 0000000..28d3b70 --- /dev/null +++ b/src/agents/spec-agent/tool-usage.ts @@ -0,0 +1,10 @@ +export const AGENT_TOOL_USAGE = `## Tool Usage + +Use read tools to inspect existing codebase patterns, APIs, and conventions before writing specs. + +Use edit tools to write proposal.md and specs/** under the change directory. + +Before writing: +- Check for existing specs that might conflict or overlap. +- Inspect GLOSSARY.md for existing domain terms. +- Review AGENTS.md or similar instruction files for project conventions.`; diff --git a/src/agents/spec-agent/validation.ts b/src/agents/spec-agent/validation.ts new file mode 100644 index 0000000..3c409b9 --- /dev/null +++ b/src/agents/spec-agent/validation.ts @@ -0,0 +1,9 @@ +export const AGENT_VALIDATION = `## Validation + +Before finishing, verify that: + +- proposal.md and at least one spec file exist under the correct change directory. +- Acceptance criteria are testable and observable (not vague or subjective). +- No implementation code or design decisions leaked into the spec. +- Scope boundaries are explicit (in-scope and out-of-scope listed). +- Artifacts are written in English.`; diff --git a/src/agents/spec-agent/workflow.ts b/src/agents/spec-agent/workflow.ts new file mode 100644 index 0000000..545127e --- /dev/null +++ b/src/agents/spec-agent/workflow.ts @@ -0,0 +1,16 @@ +export const AGENT_WORKFLOW = `## Workflow + +1. Parse the feature description or change request. +2. Derive a kebab-case change name from the request (e.g., "add OAuth2 authentication" → "oauth2-auth"). +3. Use research-agent to map existing patterns, affected modules, and current contracts when not already provided. +4. Write \`proposal.md\` under \`openspec/changes/{change-name}/\` with: + - What is changing and why. + - Current state vs desired state. + - Scope boundaries and out-of-scope items. + - Key risks and unknowns. +5. Write capability specs under \`openspec/changes/{change-name}/specs/\` — one file per capability, each with: + - Capability name and purpose. + - Acceptance criteria (testable, observable conditions). + - Edge cases and error conditions. +6. If domain terms are introduced, append them to \`GLOSSARY.md\` at the project root (create if missing). +7. Present the artifacts for user review and approval. Nothing else happens until the user says yes.`; diff --git a/src/config/agents.ts b/src/config/agents.ts index 94bd74f..e86b7db 100644 --- a/src/config/agents.ts +++ b/src/config/agents.ts @@ -73,4 +73,20 @@ export const agents = { model: agentModelConfig["prompt-agent"], permissions: ["read", "write", "edit", "question"], }, + + "spec-agent": { + name: "spec-agent", + description: "Turns feature descriptions into spec-first change artifacts: proposal.md and capability specs with acceptance criteria.", + task: "spec", + model: agentModelConfig["spec-agent"], + permissions: ["read", "edit", "question"], + }, + + "apply-agent": { + name: "apply-agent", + description: "Executes implementation playbooks step-by-step: RED→GREEN, verify, commit.", + task: "apply", + model: agentModelConfig["apply-agent"], + permissions: ["read", "write", "edit", "bash", "question"], + }, } satisfies Record; \ No newline at end of file diff --git a/src/config/models.ts b/src/config/models.ts index deadde8..43b4e7e 100644 --- a/src/config/models.ts +++ b/src/config/models.ts @@ -56,4 +56,16 @@ export const agentModelConfig = { temperature: 0.2, fallbackModels: [], }, + + "spec-agent": { + model: "opencode-go/kimi-k2.6", + temperature: 0.1, + fallbackModels: ["openai/gpt-5.5"], + }, + + "apply-agent": { + model: "opencode-go/deepseek-v4-flash", + temperature: 0.1, + fallbackModels: ["opencode-go/kimi-k2.6"], + }, } satisfies Record; \ No newline at end of file diff --git a/src/config/routing.ts b/src/config/routing.ts index e7a735f..a0c9613 100644 --- a/src/config/routing.ts +++ b/src/config/routing.ts @@ -10,4 +10,6 @@ export const taskToAgent = { review: "reviewer-agent", "test-fix": "test-fixer-agent", verification: "verifier-agent", + spec: "spec-agent", + apply: "apply-agent", } satisfies Record; diff --git a/src/types/types.ts b/src/types/types.ts index c27e433..3f391cb 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -7,7 +7,9 @@ export type AgentName = | "verifier-agent" | "test-fixer-agent" | "pr-review-agent" - | "prompt-agent"; + | "prompt-agent" + | "spec-agent" + | "apply-agent"; export type WorkflowTask = | "research" @@ -18,7 +20,9 @@ export type WorkflowTask = | "verification" | "test-fix" | "orchestration" - | "prompting"; + | "prompting" + | "spec" + | "apply"; export type ModelConfig = { model: string;