fix: use scalar Claude agent tools (#2583)

Normalize scalar Claude agent tool metadata across validators, adapters, dashboards, and generated surfaces with regression coverage.
This commit is contained in:
Affaan Mustafa 2026-07-26 03:20:15 -07:00 committed by GitHub
parent f3afd59045
commit 6a9f075cd9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
79 changed files with 515 additions and 87 deletions

View file

@ -55,6 +55,21 @@ This applies consistently across all component path fields.
--- ---
## Agent `tools` Frontmatter: USE A SCALAR
The array rule above applies to `plugin.json`, not agent Markdown frontmatter.
Claude Code agent files use a comma-separated scalar for their tool allowlist:
```yaml
tools: Read, Glob, Grep
```
Do not use a YAML sequence such as `tools: [Read, Glob, Grep]`. Omitting the
`tools` field grants the agent access to all tools, but ECC agents declare
explicit allowlists and the repository validator requires the field.
---
## The `agents` Field: DO NOT ADD ## The `agents` Field: DO NOT ADD
> WARNING: **CRITICAL:** Do NOT add an `"agents"` field to `plugin.json`. The Claude Code plugin validator rejects it entirely. > WARNING: **CRITICAL:** Do NOT add an `"agents"` field to `plugin.json`. The Claude Code plugin validator rejects it entirely.

View file

@ -199,7 +199,7 @@ agents/your-agent-name.md
--- ---
name: your-agent-name name: your-agent-name
description: What this agent does and when Claude should invoke it. Be specific! description: What this agent does and when Claude should invoke it. Be specific!
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1152,7 +1152,7 @@ Subagents handle delegated tasks with limited scope. Example:
--- ---
name: code-reviewer name: code-reviewer
description: Reviews code for quality, security, and maintainability description: Reviews code for quality, security, and maintainability
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: opus model: opus
--- ---

View file

@ -2,7 +2,7 @@
name: a11y-architect name: a11y-architect
description: Accessibility Architect specializing in WCAG 2.2 compliance for Web and Native platforms. Use PROACTIVELY when designing UI components, establishing design systems, or auditing code for inclusive user experiences. description: Accessibility Architect specializing in WCAG 2.2 compliance for Web and Native platforms. Use PROACTIVELY when designing UI components, establishing design systems, or auditing code for inclusive user experiences.
model: sonnet model: sonnet
tools: ["Read", "Write", "Edit", "Grep", "Glob"] tools: Read, Write, Edit, Grep, Glob
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -1,7 +1,7 @@
--- ---
name: agent-evaluator name: agent-evaluator
description: Evaluates agent output against 5-axis quality rubric (accuracy, completeness, clarity, actionability, conciseness). Use after any non-trivial task when the user wants a quality assessment, or when the agent-self-evaluation skill is active. Produces structured scorecard with evidence and improvement suggestions. description: Evaluates agent output against 5-axis quality rubric (accuracy, completeness, clarity, actionability, conciseness). Use after any non-trivial task when the user wants a quality assessment, or when the agent-self-evaluation skill is active. Produces structured scorecard with evidence and improvement suggestions.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: architect name: architect
description: Software architecture specialist for system design, scalability, and technical decision-making. Use PROACTIVELY when planning new features, refactoring large systems, or making architectural decisions. description: Software architecture specialist for system design, scalability, and technical decision-making. Use PROACTIVELY when planning new features, refactoring large systems, or making architectural decisions.
tools: ["Read", "Grep", "Glob"] tools: Read, Grep, Glob
model: opus model: opus
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: build-error-resolver name: build-error-resolver
description: Build and TypeScript error resolution specialist. Use PROACTIVELY when build fails or type errors occur. Fixes build/type errors only with minimal diffs, no architectural edits. Focuses on getting the build green quickly. description: Build and TypeScript error resolution specialist. Use PROACTIVELY when build fails or type errors occur. Fixes build/type errors only with minimal diffs, no architectural edits. Focuses on getting the build green quickly.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: chief-of-staff name: chief-of-staff
description: Personal communication chief of staff that triages email, Slack, LINE, and Messenger. Classifies messages into 4 tiers (skip/info_only/meeting_info/action_required), generates draft replies, and enforces post-send follow-through via hooks. Use when managing multi-channel communication workflows. description: Personal communication chief of staff that triages email, Slack, LINE, and Messenger. Classifies messages into 4 tiers (skip/info_only/meeting_info/action_required), generates draft replies, and enforces post-send follow-through via hooks. Use when managing multi-channel communication workflows.
tools: ["Read", "Grep", "Glob", "Bash", "Edit", "Write"] tools: Read, Grep, Glob, Bash, Edit, Write
model: sonnet model: sonnet
--- ---

View file

@ -2,7 +2,7 @@
name: code-architect name: code-architect
description: Designs feature architectures by analyzing existing codebase patterns and conventions, then providing implementation blueprints with concrete files, interfaces, data flow, and build order. description: Designs feature architectures by analyzing existing codebase patterns and conventions, then providing implementation blueprints with concrete files, interfaces, data flow, and build order.
model: sonnet model: sonnet
tools: [Read, Grep, Glob, Bash] tools: Read, Grep, Glob, Bash
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -2,7 +2,7 @@
name: code-explorer name: code-explorer
description: Deeply analyzes existing codebase features by tracing execution paths, mapping architecture layers, and documenting dependencies to inform new development. description: Deeply analyzes existing codebase features by tracing execution paths, mapping architecture layers, and documenting dependencies to inform new development.
model: sonnet model: sonnet
tools: [Read, Grep, Glob] tools: Read, Grep, Glob
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -1,7 +1,7 @@
--- ---
name: code-reviewer name: code-reviewer
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code. MUST BE USED for all code changes. description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code. MUST BE USED for all code changes.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -2,7 +2,7 @@
name: code-simplifier name: code-simplifier
description: Simplifies and refines code for clarity, consistency, and maintainability while preserving behavior. Focus on recently modified code unless instructed otherwise. description: Simplifies and refines code for clarity, consistency, and maintainability while preserving behavior. Focus on recently modified code unless instructed otherwise.
model: sonnet model: sonnet
tools: [Read, Write, Edit, Bash, Grep, Glob] tools: Read, Write, Edit, Bash, Grep, Glob
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -2,7 +2,7 @@
name: comment-analyzer name: comment-analyzer
description: Analyze code comments for accuracy, completeness, maintainability, and comment rot risk. description: Analyze code comments for accuracy, completeness, maintainability, and comment rot risk.
model: haiku model: haiku
tools: [Read, Grep, Glob] tools: Read, Grep, Glob
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -2,7 +2,7 @@
name: conversation-analyzer name: conversation-analyzer
description: Use this agent when analyzing conversation transcripts to find behaviors worth preventing with hooks. Triggered by /hookify without arguments. description: Use this agent when analyzing conversation transcripts to find behaviors worth preventing with hooks. Triggered by /hookify without arguments.
model: haiku model: haiku
tools: [Read, Grep] tools: Read, Grep
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -1,7 +1,7 @@
--- ---
name: cpp-build-resolver name: cpp-build-resolver
description: C++ build, CMake, and compilation error resolution specialist. Fixes build errors, linker issues, and template errors with minimal changes. Use when C++ builds fail. description: C++ build, CMake, and compilation error resolution specialist. Fixes build errors, linker issues, and template errors with minimal changes. Use when C++ builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: cpp-reviewer name: cpp-reviewer
description: Expert C++ code reviewer specializing in memory safety, modern C++ idioms, concurrency, and performance. Use for all C++ code changes. MUST BE USED for C++ projects. description: Expert C++ code reviewer specializing in memory safety, modern C++ idioms, concurrency, and performance. Use for all C++ code changes. MUST BE USED for C++ projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: csharp-reviewer name: csharp-reviewer
description: Expert C# code reviewer specializing in .NET conventions, async patterns, security, nullable reference types, and performance. Use for all C# code changes. MUST BE USED for C# projects. description: Expert C# code reviewer specializing in .NET conventions, async patterns, security, nullable reference types, and performance. Use for all C# code changes. MUST BE USED for C# projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: dart-build-resolver name: dart-build-resolver
description: Dart/Flutter build, analysis, and dependency error resolution specialist. Fixes `dart analyze` errors, Flutter compilation failures, pub dependency conflicts, and build_runner issues with minimal, surgical changes. Use when Dart/Flutter builds fail. description: Dart/Flutter build, analysis, and dependency error resolution specialist. Fixes `dart analyze` errors, Flutter compilation failures, pub dependency conflicts, and build_runner issues with minimal, surgical changes. Use when Dart/Flutter builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: database-reviewer name: database-reviewer
description: PostgreSQL database specialist for query optimization, schema design, security, and performance. Use PROACTIVELY when writing SQL, creating migrations, designing schemas, or troubleshooting database performance. Incorporates Supabase best practices. description: PostgreSQL database specialist for query optimization, schema design, security, and performance. Use PROACTIVELY when writing SQL, creating migrations, designing schemas, or troubleshooting database performance. Incorporates Supabase best practices.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: django-build-resolver name: django-build-resolver
description: Django/Python build, migration, and dependency error resolution specialist. Fixes pip/Poetry errors, migration conflicts, import errors, Django configuration issues, and collectstatic failures with minimal changes. Use when Django setup or startup fails. description: Django/Python build, migration, and dependency error resolution specialist. Fixes pip/Poetry errors, migration conflicts, import errors, Django configuration issues, and collectstatic failures with minimal changes. Use when Django setup or startup fails.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: django-reviewer name: django-reviewer
description: Expert Django code reviewer specializing in ORM correctness, DRF patterns, migration safety, security misconfigurations, and production-grade Django practices. Use for all Django code changes. MUST BE USED for Django projects. description: Expert Django code reviewer specializing in ORM correctness, DRF patterns, migration safety, security misconfigurations, and production-grade Django practices. Use for all Django code changes. MUST BE USED for Django projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: doc-updater name: doc-updater
description: Documentation and codemap specialist. Use PROACTIVELY for updating codemaps and documentation. Runs /update-codemaps and /update-docs, generates docs/CODEMAPS/*, updates READMEs and guides. description: Documentation and codemap specialist. Use PROACTIVELY for updating codemaps and documentation. Runs /update-codemaps and /update-docs, generates docs/CODEMAPS/*, updates READMEs and guides.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: haiku model: haiku
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: docs-lookup name: docs-lookup
description: When the user asks how to use a library, framework, or API or needs up-to-date code examples, use Context7 MCP to fetch current documentation and return answers with examples. Invoke for docs/API/setup questions. description: When the user asks how to use a library, framework, or API or needs up-to-date code examples, use Context7 MCP to fetch current documentation and return answers with examples. Invoke for docs/API/setup questions.
tools: ["Read", "Grep", "mcp__context7__resolve-library-id", "mcp__context7__query-docs"] tools: Read, Grep, mcp__context7__resolve-library-id, mcp__context7__query-docs
model: haiku model: haiku
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: e2e-runner name: e2e-runner
description: End-to-end testing specialist using Vercel Agent Browser (preferred) with Playwright fallback. Use PROACTIVELY for generating, maintaining, and running E2E tests. Manages test journeys, quarantines flaky tests, uploads artifacts (screenshots, videos, traces), and ensures critical user flows work. description: End-to-end testing specialist using Vercel Agent Browser (preferred) with Playwright fallback. Use PROACTIVELY for generating, maintaining, and running E2E tests. Manages test journeys, quarantines flaky tests, uploads artifacts (screenshots, videos, traces), and ensures critical user flows work.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: fastapi-reviewer name: fastapi-reviewer
description: Reviews FastAPI applications for async correctness, dependency injection, Pydantic schemas, security, OpenAPI quality, testing, and production readiness. description: Reviews FastAPI applications for async correctness, dependency injection, Pydantic schemas, security, OpenAPI quality, testing, and production readiness.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: flutter-reviewer name: flutter-reviewer
description: Flutter and Dart code reviewer. Reviews Flutter code for widget best practices, state management patterns, Dart idioms, performance pitfalls, accessibility, and clean architecture violations. Library-agnostic — works with any state management solution and tooling. description: Flutter and Dart code reviewer. Reviews Flutter code for widget best practices, state management patterns, Dart idioms, performance pitfalls, accessibility, and clean architecture violations. Library-agnostic — works with any state management solution and tooling.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: fsharp-reviewer name: fsharp-reviewer
description: Expert F# code reviewer specializing in functional idioms, type safety, pattern matching, computation expressions, and performance. Use for all F# code changes. MUST BE USED for F# projects. description: Expert F# code reviewer specializing in functional idioms, type safety, pattern matching, computation expressions, and performance. Use for all F# code changes. MUST BE USED for F# projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: gan-evaluator name: gan-evaluator
description: "GAN Harness — Evaluator agent. Tests the live running application via Playwright, scores against rubric, and provides actionable feedback to the Generator." description: "GAN Harness — Evaluator agent. Tests the live running application via Playwright, scores against rubric, and provides actionable feedback to the Generator."
tools: ["Read", "Write", "Bash", "Grep", "Glob"] tools: Read, Write, Bash, Grep, Glob
model: sonnet model: sonnet
color: red color: red
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: gan-generator name: gan-generator
description: "GAN Harness — Generator agent. Implements features according to the spec, reads evaluator feedback, and iterates until quality threshold is met." description: "GAN Harness — Generator agent. Implements features according to the spec, reads evaluator feedback, and iterates until quality threshold is met."
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
color: green color: green
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: gan-planner name: gan-planner
description: "GAN Harness — Planner agent. Expands a one-line prompt into a full product specification with features, sprints, evaluation criteria, and design direction." description: "GAN Harness — Planner agent. Expands a one-line prompt into a full product specification with features, sprints, evaluation criteria, and design direction."
tools: ["Read", "Write", "Grep", "Glob"] tools: Read, Write, Grep, Glob
model: sonnet model: sonnet
color: purple color: purple
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: go-build-resolver name: go-build-resolver
description: Go build, vet, and compilation error resolution specialist. Fixes build errors, go vet issues, and linter warnings with minimal changes. Use when Go builds fail. description: Go build, vet, and compilation error resolution specialist. Fixes build errors, go vet issues, and linter warnings with minimal changes. Use when Go builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: go-reviewer name: go-reviewer
description: Expert Go code reviewer specializing in idiomatic Go, concurrency patterns, error handling, and performance. Use for all Go code changes. MUST BE USED for Go projects. description: Expert Go code reviewer specializing in idiomatic Go, concurrency patterns, error handling, and performance. Use for all Go code changes. MUST BE USED for Go projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: harmonyos-app-resolver name: harmonyos-app-resolver
description: HarmonyOS application development expert specializing in ArkTS and ArkUI. Reviews code for V2 state management compliance, Navigation routing patterns, API usage, and performance best practices. Use for HarmonyOS/OpenHarmony projects. description: HarmonyOS application development expert specializing in ArkTS and ArkUI. Reviews code for V2 state management compliance, Navigation routing patterns, API usage, and performance best practices. Use for HarmonyOS/OpenHarmony projects.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: harness-optimizer name: harness-optimizer
description: Analyze and improve the local agent harness configuration for reliability, cost, and throughput. description: Analyze and improve the local agent harness configuration for reliability, cost, and throughput.
tools: ["Read", "Grep", "Glob", "Bash", "Edit"] tools: Read, Grep, Glob, Bash, Edit
model: sonnet model: sonnet
color: teal color: teal
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: healthcare-reviewer name: healthcare-reviewer
description: Reviews healthcare application code for clinical safety, CDSS accuracy, PHI compliance, and medical data integrity. Specialized for EMR/EHR, clinical decision support, and health information systems. description: Reviews healthcare application code for clinical safety, CDSS accuracy, PHI compliance, and medical data integrity. Specialized for EMR/EHR, clinical decision support, and health information systems.
tools: ["Read", "Grep", "Glob"] tools: Read, Grep, Glob
model: opus model: opus
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: homelab-architect name: homelab-architect
description: Designs home and small-lab network plans from hardware inventory, goals, and operator experience level, with safe staged changes and rollback guidance. description: Designs home and small-lab network plans from hardware inventory, goals, and operator experience level, with safe staged changes and rollback guidance.
tools: ["Read", "Grep"] tools: Read, Grep
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: java-build-resolver name: java-build-resolver
description: Java/Maven/Gradle build, compilation, and dependency error resolution specialist. Automatically detects Spring Boot or Quarkus and applies framework-specific fixes. Fixes build errors, Java compiler errors, and Maven/Gradle issues with minimal changes. Use when Java builds fail. description: Java/Maven/Gradle build, compilation, and dependency error resolution specialist. Automatically detects Spring Boot or Quarkus and applies framework-specific fixes. Fixes build errors, Java compiler errors, and Maven/Gradle issues with minimal changes. Use when Java builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: java-reviewer name: java-reviewer
description: Expert Java code reviewer for Spring Boot and Quarkus projects. Automatically detects the framework and applies the appropriate review rules. Covers layered architecture, JPA/Panache, MongoDB, security, and concurrency. MUST BE USED for all Java code changes. description: Expert Java code reviewer for Spring Boot and Quarkus projects. Automatically detects the framework and applies the appropriate review rules. Covers layered architecture, JPA/Panache, MongoDB, security, and concurrency. MUST BE USED for all Java code changes.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: kotlin-build-resolver name: kotlin-build-resolver
description: Kotlin/Gradle build, compilation, and dependency error resolution specialist. Fixes build errors, Kotlin compiler errors, and Gradle issues with minimal changes. Use when Kotlin builds fail. description: Kotlin/Gradle build, compilation, and dependency error resolution specialist. Fixes build errors, Kotlin compiler errors, and Gradle issues with minimal changes. Use when Kotlin builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: kotlin-reviewer name: kotlin-reviewer
description: Kotlin and Android/KMP code reviewer. Reviews Kotlin code for idiomatic patterns, coroutine safety, Compose best practices, clean architecture violations, and common Android pitfalls. description: Kotlin and Android/KMP code reviewer. Reviews Kotlin code for idiomatic patterns, coroutine safety, Compose best practices, clean architecture violations, and common Android pitfalls.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: loop-operator name: loop-operator
description: Operate autonomous agent loops, monitor progress, and intervene safely when loops stall. description: Operate autonomous agent loops, monitor progress, and intervene safely when loops stall.
tools: ["Read", "Grep", "Glob", "Bash", "Edit"] tools: Read, Grep, Glob, Bash, Edit
model: sonnet model: sonnet
color: orange color: orange
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: marketing-agent name: marketing-agent
description: Marketing strategist and copywriter for campaign planning, audience research, positioning, copy creation, and content review. Covers landing pages, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use when the user wants to plan or execute a product launch or marketing campaign. description: Marketing strategist and copywriter for campaign planning, audience research, positioning, copy creation, and content review. Covers landing pages, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use when the user wants to plan or execute a product launch or marketing campaign.
tools: ["Read", "Grep", "Glob", "WebSearch", "WebFetch"] tools: Read, Grep, Glob, WebSearch, WebFetch
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: mle-reviewer name: mle-reviewer
description: Production machine-learning engineering reviewer for data contracts, feature pipelines, training reproducibility, offline/online evaluation, model serving, monitoring, and rollback. Use when ML, MLOps, model training, inference, feature store, or evaluation code changes. description: Production machine-learning engineering reviewer for data contracts, feature pipelines, training reproducibility, offline/online evaluation, model serving, monitoring, and rollback. Use when ML, MLOps, model training, inference, feature store, or evaluation code changes.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: network-architect name: network-architect
description: Designs enterprise or multi-site network architecture from requirements, using existing network skills for focused routing, validation, automation, and troubleshooting detail. description: Designs enterprise or multi-site network architecture from requirements, using existing network skills for focused routing, validation, automation, and troubleshooting detail.
tools: ["Read", "Grep"] tools: Read, Grep
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: network-config-reviewer name: network-config-reviewer
description: Reviews router and switch configurations for security, correctness, stale references, risky change-window commands, and missing operational guardrails. description: Reviews router and switch configurations for security, correctness, stale references, risky change-window commands, and missing operational guardrails.
tools: ["Read", "Grep"] tools: Read, Grep
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: network-troubleshooter name: network-troubleshooter
description: Diagnoses network connectivity, routing, DNS, interface, and policy symptoms with a read-only OSI-layer workflow and evidence-backed root cause summary. description: Diagnoses network connectivity, routing, DNS, interface, and policy symptoms with a read-only OSI-layer workflow and evidence-backed root cause summary.
tools: ["Read", "Bash", "Grep"] tools: Read, Bash, Grep
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: opensource-forker name: opensource-forker
description: Fork any project for open-sourcing. Copies files, strips secrets and credentials (20+ patterns), replaces internal references with placeholders, generates .env.example, and cleans git history. First stage of the opensource-pipeline skill. description: Fork any project for open-sourcing. Copies files, strips secrets and credentials (20+ patterns), replaces internal references with placeholders, generates .env.example, and cleans git history. First stage of the opensource-pipeline skill.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: haiku model: haiku
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: opensource-packager name: opensource-packager
description: Generate complete open-source packaging for a sanitized project. Produces CLAUDE.md, setup.sh, README.md, LICENSE, CONTRIBUTING.md, and GitHub issue templates. Makes any repo immediately usable with Claude Code. Third stage of the opensource-pipeline skill. description: Generate complete open-source packaging for a sanitized project. Produces CLAUDE.md, setup.sh, README.md, LICENSE, CONTRIBUTING.md, and GitHub issue templates. Makes any repo immediately usable with Claude Code. Third stage of the opensource-pipeline skill.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: haiku model: haiku
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: opensource-sanitizer name: opensource-sanitizer
description: Verify an open-source fork is fully sanitized before release. Scans for leaked secrets, PII, internal references, and dangerous files using 20+ regex patterns. Generates a PASS/FAIL/PASS-WITH-WARNINGS report. Second stage of the opensource-pipeline skill. Use PROACTIVELY before any public release. description: Verify an open-source fork is fully sanitized before release. Scans for leaked secrets, PII, internal references, and dangerous files using 20+ regex patterns. Generates a PASS/FAIL/PASS-WITH-WARNINGS report. Second stage of the opensource-pipeline skill. Use PROACTIVELY before any public release.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: performance-optimizer name: performance-optimizer
description: Performance analysis and optimization specialist. Use PROACTIVELY for identifying bottlenecks, optimizing slow code, reducing bundle sizes, and improving runtime performance. Profiling, memory leaks, render optimization, and algorithmic improvements. description: Performance analysis and optimization specialist. Use PROACTIVELY for identifying bottlenecks, optimizing slow code, reducing bundle sizes, and improving runtime performance. Profiling, memory leaks, render optimization, and algorithmic improvements.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: php-reviewer name: php-reviewer
description: Expert PHP code reviewer specializing in PSR-12 compliance, PHP type system, Eloquent ORM patterns, security, and performance. Use for all PHP code changes. MUST BE USED for PHP projects. description: Expert PHP code reviewer specializing in PSR-12 compliance, PHP type system, Eloquent ORM patterns, security, and performance. Use for all PHP code changes. MUST BE USED for PHP projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: planner name: planner
description: Expert planning specialist for complex features and refactoring. Use PROACTIVELY when users request feature implementation, architectural changes, or complex refactoring. Automatically activated for planning tasks. description: Expert planning specialist for complex features and refactoring. Use PROACTIVELY when users request feature implementation, architectural changes, or complex refactoring. Automatically activated for planning tasks.
tools: ["Read", "Grep", "Glob"] tools: Read, Grep, Glob
model: opus model: opus
--- ---

View file

@ -2,7 +2,7 @@
name: pr-test-analyzer name: pr-test-analyzer
description: Review pull request test coverage quality and completeness, with emphasis on behavioral coverage and real bug prevention. description: Review pull request test coverage quality and completeness, with emphasis on behavioral coverage and real bug prevention.
model: sonnet model: sonnet
tools: [Read, Grep, Glob, Bash] tools: Read, Grep, Glob, Bash
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -1,7 +1,7 @@
--- ---
name: python-reviewer name: python-reviewer
description: Expert Python code reviewer specializing in PEP 8 compliance, Pythonic idioms, type hints, security, and performance. Use for all Python code changes. MUST BE USED for Python projects. description: Expert Python code reviewer specializing in PEP 8 compliance, Pythonic idioms, type hints, security, and performance. Use for all Python code changes. MUST BE USED for Python projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: pytorch-build-resolver name: pytorch-build-resolver
description: PyTorch runtime, CUDA, and training error resolution specialist. Fixes tensor shape mismatches, device errors, gradient issues, DataLoader problems, and mixed precision failures with minimal changes. Use when PyTorch training or inference crashes. description: PyTorch runtime, CUDA, and training error resolution specialist. Fixes tensor shape mismatches, device errors, gradient issues, DataLoader problems, and mixed precision failures with minimal changes. Use when PyTorch training or inference crashes.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: react-build-resolver name: react-build-resolver
description: Diagnose and fix React build failures across Vite, webpack, Next.js, CRA, Parcel, esbuild, and Bun. Handles JSX/TSX compile errors, hydration mismatches, server/client component boundary failures, missing types, and bundler-specific configuration issues with minimal, surgical changes. MUST BE USED when a React build fails. description: Diagnose and fix React build failures across Vite, webpack, Next.js, CRA, Parcel, esbuild, and Bun. Handles JSX/TSX compile errors, hydration mismatches, server/client component boundary failures, missing types, and bundler-specific configuration issues with minimal, surgical changes. MUST BE USED when a React build fails.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: react-reviewer name: react-reviewer
description: Expert React/JSX code reviewer specializing in hook correctness, render performance, server/client component boundaries, accessibility, and React-specific security. Use for any change touching .tsx/.jsx files or React component logic. MUST BE USED for React projects. description: Expert React/JSX code reviewer specializing in hook correctness, render performance, server/client component boundaries, accessibility, and React-specific security. Use for any change touching .tsx/.jsx files or React component logic. MUST BE USED for React projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: refactor-cleaner name: refactor-cleaner
description: Dead code cleanup and consolidation specialist. Use PROACTIVELY for removing unused code, duplicates, and refactoring. Runs analysis tools (knip, depcheck, ts-prune) to identify dead code and safely removes it. description: Dead code cleanup and consolidation specialist. Use PROACTIVELY for removing unused code, duplicates, and refactoring. Runs analysis tools (knip, depcheck, ts-prune) to identify dead code and safely removes it.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: rust-build-resolver name: rust-build-resolver
description: Rust build, compilation, and dependency error resolution specialist. Fixes cargo build errors, borrow checker issues, and Cargo.toml problems with minimal changes. Use when Rust builds fail. description: Rust build, compilation, and dependency error resolution specialist. Fixes cargo build errors, borrow checker issues, and Cargo.toml problems with minimal changes. Use when Rust builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: rust-reviewer name: rust-reviewer
description: Expert Rust code reviewer specializing in ownership, lifetimes, error handling, unsafe usage, and idiomatic patterns. Use for all Rust code changes. MUST BE USED for Rust projects. description: Expert Rust code reviewer specializing in ownership, lifetimes, error handling, unsafe usage, and idiomatic patterns. Use for all Rust code changes. MUST BE USED for Rust projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: security-reviewer name: security-reviewer
description: Security vulnerability detection and remediation specialist. Use PROACTIVELY after writing code that handles user input, authentication, API endpoints, or sensitive data. Flags secrets, SSRF, injection, unsafe crypto, and OWASP Top 10 vulnerabilities. description: Security vulnerability detection and remediation specialist. Use PROACTIVELY after writing code that handles user input, authentication, API endpoints, or sensitive data. Flags secrets, SSRF, injection, unsafe crypto, and OWASP Top 10 vulnerabilities.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: seo-specialist name: seo-specialist
description: SEO specialist for technical SEO audits, on-page optimization, structured data, Core Web Vitals, and content/keyword mapping. Use for site audits, meta tag reviews, schema markup, sitemap and robots issues, and SEO remediation plans. description: SEO specialist for technical SEO audits, on-page optimization, structured data, Core Web Vitals, and content/keyword mapping. Use for site audits, meta tag reviews, schema markup, sitemap and robots issues, and SEO remediation plans.
tools: ["Read", "Grep", "Glob", "WebSearch", "WebFetch"] tools: Read, Grep, Glob, WebSearch, WebFetch
model: sonnet model: sonnet
--- ---

View file

@ -2,7 +2,7 @@
name: silent-failure-hunter name: silent-failure-hunter
description: Review code for silent failures, swallowed errors, bad fallbacks, and missing error propagation. description: Review code for silent failures, swallowed errors, bad fallbacks, and missing error propagation.
model: sonnet model: sonnet
tools: [Read, Grep, Glob, Bash] tools: Read, Grep, Glob, Bash
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -2,7 +2,7 @@
name: spec-miner name: spec-miner
description: Extracts behavioral specs from existing codebases for OpenSpec. Produces flat Requirement and Invariant blocks with structured metadata (entities, enforced, id, test anchors). Outputs openspec/specs/<capability>/spec.md. Fully self-bootstrapping — no dependency on codebase-onboarding. Use when onboarding a brownfield project to spec-driven development. description: Extracts behavioral specs from existing codebases for OpenSpec. Produces flat Requirement and Invariant blocks with structured metadata (entities, enforced, id, test anchors). Outputs openspec/specs/<capability>/spec.md. Fully self-bootstrapping — no dependency on codebase-onboarding. Use when onboarding a brownfield project to spec-driven development.
model: opus model: opus
tools: ["Read", "Grep", "Glob", "Bash", "Write"] tools: Read, Grep, Glob, Bash, Write
--- ---
## Tool guardrails ## Tool guardrails

View file

@ -1,7 +1,7 @@
--- ---
name: swift-build-resolver name: swift-build-resolver
description: Swift/Xcode build, compilation, and dependency error resolution specialist. Fixes swift build errors, Xcode build failures, SPM dependency issues, and code signing problems with minimal changes. Use when Swift builds fail. description: Swift/Xcode build, compilation, and dependency error resolution specialist. Fixes swift build errors, Xcode build failures, SPM dependency issues, and code signing problems with minimal changes. Use when Swift builds fail.
tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] tools: Read, Write, Edit, Bash, Grep, Glob
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: swift-reviewer name: swift-reviewer
description: Expert Swift code reviewer specializing in protocol-oriented design, value semantics, ARC memory management, Swift Concurrency, and idiomatic patterns. Use for all Swift code changes. MUST BE USED for Swift projects. description: Expert Swift code reviewer specializing in protocol-oriented design, value semantics, ARC memory management, Swift Concurrency, and idiomatic patterns. Use for all Swift code changes. MUST BE USED for Swift projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: tdd-guide name: tdd-guide
description: Test-Driven Development specialist enforcing write-tests-first methodology. Use PROACTIVELY when writing new features, fixing bugs, or refactoring code. Ensures 80%+ test coverage. description: Test-Driven Development specialist enforcing write-tests-first methodology. Use PROACTIVELY when writing new features, fixing bugs, or refactoring code. Ensures 80%+ test coverage.
tools: ["Read", "Write", "Edit", "Bash", "Grep"] tools: Read, Write, Edit, Bash, Grep
model: sonnet model: sonnet
--- ---

View file

@ -2,7 +2,7 @@
name: type-design-analyzer name: type-design-analyzer
description: Analyze type design for encapsulation, invariant expression, usefulness, and enforcement. description: Analyze type design for encapsulation, invariant expression, usefulness, and enforcement.
model: sonnet model: sonnet
tools: [Read, Grep, Glob] tools: Read, Grep, Glob
--- ---
## Prompt Defense Baseline ## Prompt Defense Baseline

View file

@ -1,7 +1,7 @@
--- ---
name: typescript-reviewer name: typescript-reviewer
description: Expert TypeScript/JavaScript code reviewer specializing in type safety, async correctness, Node/web security, and idiomatic patterns. Use for all TypeScript and JavaScript code changes. MUST BE USED for TypeScript/JavaScript projects. description: Expert TypeScript/JavaScript code reviewer specializing in type safety, async correctness, Node/web security, and idiomatic patterns. Use for all TypeScript and JavaScript code changes. MUST BE USED for TypeScript/JavaScript projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -1,7 +1,7 @@
--- ---
name: vue-reviewer name: vue-reviewer
description: Expert Vue.js code reviewer specializing in Composition API correctness, reactivity pitfalls, component architecture, template security, and Vue-specific performance. Use for any change touching .vue, .ts/.js files with Vue imports, or Vue ecosystem code (Pinia, Vue Router, Nuxt). MUST BE USED for Vue projects. description: Expert Vue.js code reviewer specializing in Composition API correctness, reactivity pitfalls, component architecture, template security, and Vue-specific performance. Use for any change touching .vue, .ts/.js files with Vue imports, or Vue ecosystem code (Pinia, Vue Router, Nuxt). MUST BE USED for Vue projects.
tools: ["Read", "Grep", "Glob", "Bash"] tools: Read, Grep, Glob, Bash
model: sonnet model: sonnet
--- ---

View file

@ -19,24 +19,44 @@ function extractFrontmatter(content) {
const frontmatter = {}; const frontmatter = {};
const duplicates = []; const duplicates = [];
const sequenceFields = [];
let currentTopLevelKey = null;
const lines = match[1].split(/\r?\n/); const lines = match[1].split(/\r?\n/);
for (const line of lines) { for (const line of lines) {
if (/^\s*-\s+/.test(line)) {
if (currentTopLevelKey) {
sequenceFields.push(currentTopLevelKey);
}
continue;
}
// Only top-level keys are unique. Indented YAML belongs to nested values. // Only top-level keys are unique. Indented YAML belongs to nested values.
if (/^\s/.test(line)) continue; if (/^\s/.test(line)) continue;
if (!line.trim() || line.trim().startsWith('#')) continue;
currentTopLevelKey = null;
const colonIdx = line.indexOf(':'); const colonIdx = line.indexOf(':');
if (colonIdx > 0) { if (colonIdx > 0) {
const key = line.slice(0, colonIdx).trim(); const key = line.slice(0, colonIdx).trim();
const value = line.slice(colonIdx + 1).trim(); const value = line.slice(colonIdx + 1).trim();
currentTopLevelKey = key;
if (Object.prototype.hasOwnProperty.call(frontmatter, key)) { if (Object.prototype.hasOwnProperty.call(frontmatter, key)) {
duplicates.push(key); duplicates.push(key);
} }
frontmatter[key] = value; frontmatter[key] = value;
if (value && '[!&*{|>'.includes(value[0])) {
sequenceFields.push(key);
}
} }
} }
Object.defineProperty(frontmatter, '__duplicates__', { Object.defineProperty(frontmatter, '__duplicates__', {
value: duplicates, value: duplicates,
enumerable: false, enumerable: false,
}); });
Object.defineProperty(frontmatter, '__sequenceFields__', {
value: sequenceFields,
enumerable: false,
});
return frontmatter; return frontmatter;
} }
@ -79,6 +99,11 @@ function validateAgents() {
} }
} }
if (frontmatter.__sequenceFields__.includes('tools')) {
console.error(`ERROR: ${file} - Agent tools must be a comma-separated scalar, not a YAML sequence`);
hasErrors = true;
}
// Validate model is a known value // Validate model is a known value
if (frontmatter.model && !VALID_MODELS.includes(frontmatter.model)) { if (frontmatter.model && !VALID_MODELS.includes(frontmatter.model)) {
console.error(`ERROR: ${file} - Invalid model '${frontmatter.model}'. Must be one of: ${VALID_MODELS.join(', ')}`); console.error(`ERROR: ${file} - Invalid model '${frontmatter.model}'. Must be one of: ${VALID_MODELS.join(', ')}`);

View file

@ -12,6 +12,7 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const http = require('http'); const http = require('http');
const { normalizeAgentTools } = require('./lib/agent-tools');
function parsePort(v) { function parsePort(v) {
const n = parseInt(String(v), 10); const n = parseInt(String(v), 10);
@ -31,7 +32,11 @@ function readFrontmatter(p) {
const s = l.indexOf(':'); if (s <= 0) continue; const s = l.indexOf(':'); if (s <= 0) continue;
let k = l.slice(0, s).trim(), v = l.slice(s + 1).trim(); let k = l.slice(0, s).trim(), v = l.slice(s + 1).trim();
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1); if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
if (v.startsWith('[') && v.endsWith(']')) { try { v = JSON.parse(v); } catch { v = v.slice(1, -1).split(',').map(x => x.trim().replace(/["']/g, '')); } } if (k === 'tools') {
v = normalizeAgentTools(v);
} else if (v.startsWith('[') && v.endsWith(']')) {
try { v = JSON.parse(v); } catch { v = v.slice(1, -1).split(',').map(x => x.trim().replace(/["']/g, '')); }
}
fm[k] = v; fm[k] = v;
} }
fm._body = c.replace(/^---[\s\S]*?---\n*/, '').trim(); fm._body = c.replace(/^---[\s\S]*?---\n*/, '').trim();

View file

@ -3,6 +3,7 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { normalizeAgentTools } = require('./lib/agent-tools');
const TOOL_NAME_MAP = new Map([ const TOOL_NAME_MAP = new Map([
['Read', 'read_file'], ['Read', 'read_file'],
@ -53,25 +54,13 @@ function ensureDirectory(dirPath) {
} }
} }
function stripQuotes(value) {
return value.trim().replace(/^['"]|['"]$/g, '');
}
function parseToolList(line) { function parseToolList(line) {
const match = line.match(/^(\s*tools\s*:\s*)\[(.*)\]\s*$/); const match = line.match(/^\s*tools\s*:\s*(.*)$/);
if (!match) { if (!match) {
return null; return null;
} }
const rawItems = match[2].trim(); return normalizeAgentTools(match[1]);
if (!rawItems) {
return [];
}
return rawItems
.split(',')
.map(part => stripQuotes(part))
.filter(Boolean);
} }
function adaptToolName(toolName) { function adaptToolName(toolName) {

View file

@ -2,6 +2,7 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { normalizeAgentTools } = require('./agent-tools');
/** /**
* Parse YAML frontmatter from a markdown string. * Parse YAML frontmatter from a markdown string.
@ -35,6 +36,10 @@ function parseFrontmatter(content) {
value = value.slice(1, -1); value = value.slice(1, -1);
} }
if (key === 'tools') {
value = normalizeAgentTools(value);
}
frontmatter[key] = value; frontmatter[key] = value;
} }

View file

@ -0,0 +1,97 @@
'use strict';
function stripSurroundingQuotes(value) {
const trimmed = value.trim();
const quote = trimmed[0];
if ((quote === '"' || quote === "'") && trimmed.endsWith(quote)) {
return trimmed.slice(1, -1).trim();
}
return trimmed;
}
function splitTopLevelToolList(value) {
const items = [];
const delimiters = [];
let quote = null;
let escaped = false;
let itemStart = 0;
for (let index = 0; index < value.length; index += 1) {
const character = value[index];
if (quote) {
if (escaped) {
escaped = false;
} else if (character === '\\') {
escaped = true;
} else if (character === quote) {
quote = null;
}
continue;
}
if (character === '"' || character === "'") {
quote = character;
continue;
}
if (character === '(' || character === '[' || character === '{') {
delimiters.push(character);
continue;
}
const expectedOpener = {
')': '(',
']': '[',
'}': '{',
}[character];
if (expectedOpener && delimiters.at(-1) === expectedOpener) {
delimiters.pop();
continue;
}
if (character === ',' && delimiters.length === 0) {
items.push(value.slice(itemStart, index));
itemStart = index + 1;
}
}
items.push(value.slice(itemStart));
return items;
}
/**
* Normalize Claude agent frontmatter tools to the array shape used internally.
*
* Claude Code expects tools to be a comma-separated scalar. Flow sequences are
* still accepted here so ECC can read legacy or harness-adapted agent files.
*/
function normalizeAgentTools(value) {
if (Array.isArray(value)) {
return value
.filter(item => typeof item === 'string')
.map(stripSurroundingQuotes)
.filter(Boolean);
}
if (typeof value !== 'string') {
return [];
}
const trimmed = value.trim();
const listValue = trimmed.startsWith('[') && trimmed.endsWith(']')
? trimmed.slice(1, -1)
: stripSurroundingQuotes(trimmed);
if (!listValue.trim()) {
return [];
}
return splitTopLevelToolList(listValue)
.map(stripSurroundingQuotes)
.filter(Boolean);
}
module.exports = {
normalizeAgentTools,
};

View file

@ -0,0 +1,175 @@
/**
* Focused tests for validate-agents.js tools frontmatter rules.
*
* Run with: node tests/ci/validate-agents-tools.test.js
*/
const assert = require('assert');
const path = require('path');
const fs = require('fs');
const os = require('os');
const { execFileSync } = require('child_process');
const validatorsDir = path.join(__dirname, '..', '..', 'scripts', 'ci');
const repoRoot = path.join(__dirname, '..', '..');
const canonicalAgentsDir = path.join(repoRoot, 'agents');
function test(name, fn) {
try {
fn();
console.log(` \u2713 ${name}`);
return true;
} catch (err) {
console.log(` \u2717 ${name}`);
console.log(` Error: ${err.message}`);
return false;
}
}
function createTestDir() {
return fs.mkdtempSync(path.join(os.tmpdir(), 'validate-agents-tools-test-'));
}
function cleanupTestDir(testDir) {
fs.rmSync(testDir, { recursive: true, force: true });
}
function stripShebang(source) {
let s = source;
if (s.charCodeAt(0) === 0xFEFF) s = s.slice(1);
if (s.startsWith('#!')) {
const nl = s.indexOf('\n');
s = nl === -1 ? '' : s.slice(nl + 1);
}
return s;
}
function runSourceViaTempFile(source) {
const tmpFile = path.join(repoRoot, `.tmp-validator-${Date.now()}-${Math.random().toString(36).slice(2)}.js`);
try {
fs.writeFileSync(tmpFile, source, 'utf8');
const stdout = execFileSync('node', [tmpFile], {
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'],
timeout: 10000,
cwd: repoRoot,
});
return { code: 0, stdout, stderr: '' };
} catch (err) {
return {
code: err.status || 1,
stdout: err.stdout || '',
stderr: err.stderr || '',
};
} finally {
fs.rmSync(tmpFile, { force: true });
}
}
function runValidatorWithDir(validatorName, dirConstant, overridePath) {
const validatorPath = path.join(validatorsDir, `${validatorName}.js`);
let source = fs.readFileSync(validatorPath, 'utf8');
source = stripShebang(source);
const dirRegex = new RegExp(`const ${dirConstant} = .*?;`);
source = source.replace(dirRegex, `const ${dirConstant} = ${JSON.stringify(overridePath)};`);
return runSourceViaTempFile(source);
}
function readCanonicalAgent(file) {
const resolvedPath = path.resolve(canonicalAgentsDir, file);
const agentsRoot = path.resolve(canonicalAgentsDir);
assert.ok(
resolvedPath.startsWith(`${agentsRoot}${path.sep}`),
`${file} should resolve inside the canonical agents directory`
);
return fs.readFileSync(resolvedPath, 'utf8');
}
function runTests() {
console.log('\n=== Testing validate-agents tools frontmatter ===\n');
let passed = 0;
let failed = 0;
if (test('canonical agents declare tools as comma-separated scalars', () => {
const agentFiles = fs.readdirSync(canonicalAgentsDir).filter(file => file.endsWith('.md'));
for (const file of agentFiles) {
const content = readCanonicalAgent(file);
const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
assert.ok(frontmatter, `${file} should have frontmatter`);
const toolsLine = frontmatter[1].match(/^tools:\s*(.+)$/m);
assert.ok(toolsLine, `${file} should declare a non-empty tools scalar`);
assert.ok(
!toolsLine[1].trim().startsWith('['),
`${file} should use comma-separated scalar tools, not a YAML sequence`
);
}
})) passed++; else failed++;
if (test('accepts comma-separated scalar agent tools', () => {
const testDir = createTestDir();
try {
fs.writeFileSync(path.join(testDir, 'scalar-tools.md'), '---\nmodel: sonnet\ntools: Read, Glob, Grep\n---\n# Agent');
const result = runValidatorWithDir('validate-agents', 'AGENTS_DIR', testDir);
assert.strictEqual(result.code, 0, `Should accept scalar tools, got stderr: ${result.stderr}`);
} finally {
cleanupTestDir(testDir);
}
})) passed++; else failed++;
if (test('rejects YAML sequence-form agent tools', () => {
const testDir = createTestDir();
try {
fs.writeFileSync(path.join(testDir, 'sequence-tools.md'), '---\nmodel: sonnet\ntools: [Read, Glob, Grep]\n---\n# Agent');
const result = runValidatorWithDir('validate-agents', 'AGENTS_DIR', testDir);
assert.strictEqual(result.code, 1, 'Should reject sequence-form tools');
assert.ok(
result.stderr.includes('comma-separated scalar'),
`Should explain the supported tools format, got stderr: ${result.stderr}`
);
} finally {
cleanupTestDir(testDir);
}
})) passed++; else failed++;
if (test('rejects block sequence-form agent tools', () => {
const testDir = createTestDir();
try {
fs.writeFileSync(path.join(testDir, 'block-sequence-tools.md'), '---\nmodel: sonnet\ntools:\n - Read\n - Glob\n - Grep\n---\n# Agent');
const result = runValidatorWithDir('validate-agents', 'AGENTS_DIR', testDir);
assert.strictEqual(result.code, 1, 'Should reject block sequence-form tools');
assert.ok(
result.stderr.includes('comma-separated scalar'),
`Should explain the supported tools format, got stderr: ${result.stderr}`
);
} finally {
cleanupTestDir(testDir);
}
})) passed++; else failed++;
if (test('rejects explicitly tagged YAML sequence-form agent tools', () => {
const testDir = createTestDir();
try {
fs.writeFileSync(path.join(testDir, 'tagged-sequence-tools.md'), '---\nmodel: sonnet\ntools: !!seq [Read, Glob, Grep]\n---\n# Agent');
const result = runValidatorWithDir('validate-agents', 'AGENTS_DIR', testDir);
assert.strictEqual(result.code, 1, 'Should reject tagged sequence-form tools');
assert.ok(
result.stderr.includes('comma-separated scalar'),
`Should explain the supported tools format, got stderr: ${result.stderr}`
);
} finally {
cleanupTestDir(testDir);
}
})) passed++; else failed++;
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);
}
runTests();

View file

@ -45,6 +45,29 @@ function runTests() {
passed++; passed++;
else failed++; else failed++;
if (
test('parseFrontmatter normalizes comma-separated scalar tools to an array', () => {
const content = '---\nname: scalar-tools\ndescription: Scalar tools\ntools: Read, Glob, Grep\nmodel: sonnet\n---\n\nBody.';
const { frontmatter } = parseFrontmatter(content);
assert.deepStrictEqual(frontmatter.tools, ['Read', 'Glob', 'Grep']);
})
)
passed++;
else failed++;
if (
test('parseFrontmatter preserves commas inside scoped tool arguments', () => {
const content = '---\nname: scoped-tools\ndescription: Scoped tools\ntools: Agent(worker, researcher), Read, Bash\nmodel: sonnet\n---\n\nBody.';
const { frontmatter } = parseFrontmatter(content);
assert.deepStrictEqual(
frontmatter.tools,
['Agent(worker, researcher)', 'Read', 'Bash']
);
})
)
passed++;
else failed++;
if ( if (
test('parseFrontmatter handles content without frontmatter', () => { test('parseFrontmatter handles content without frontmatter', () => {
const content = 'Just a regular markdown file.'; const content = 'Just a regular markdown file.';
@ -155,7 +178,7 @@ function runTests() {
// Create a temp directory with test agent files // Create a temp directory with test agent files
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-compress-test-')); const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-compress-test-'));
const agentContent = '---\nname: test-agent\ndescription: A test agent\ntools: ["Read"]\nmodel: haiku\n---\n\nTest agent body paragraph.\n\n## Details\nMore info.'; const agentContent = '---\nname: test-agent\ndescription: A test agent\ntools: Read\nmodel: haiku\n---\n\nTest agent body paragraph.\n\n## Details\nMore info.';
fs.writeFileSync(path.join(tmpDir, 'test-agent.md'), agentContent); fs.writeFileSync(path.join(tmpDir, 'test-agent.md'), agentContent);
fs.writeFileSync(path.join(tmpDir, 'not-an-agent.txt'), 'ignored'); fs.writeFileSync(path.join(tmpDir, 'not-an-agent.txt'), 'ignored');
@ -332,6 +355,10 @@ function runTests() {
if (!fs.existsSync(realAgentsDir)) return; // skip if not present if (!fs.existsSync(realAgentsDir)) return; // skip if not present
const result = buildAgentCatalog(realAgentsDir, { mode: 'catalog' }); const result = buildAgentCatalog(realAgentsDir, { mode: 'catalog' });
assert.ok(result.agents.length > 0, 'Should find at least one agent'); assert.ok(result.agents.length > 0, 'Should find at least one agent');
assert.ok(
result.agents.every(agent => Array.isArray(agent.tools) && agent.tools.length > 0),
'Every catalog agent should retain its tools as a non-empty array'
);
assert.ok(result.stats.compressedBytes < result.stats.originalBytes, 'Catalog should be smaller than original'); assert.ok(result.stats.compressedBytes < result.stats.originalBytes, 'Catalog should be smaller than original');
// Verify significant compression ratio // Verify significant compression ratio
const ratio = result.stats.compressedBytes / result.stats.originalBytes; const ratio = result.stats.compressedBytes / result.stats.originalBytes;

View file

@ -36,6 +36,29 @@ function cleanup(dirPath) {
fs.rmSync(dirPath, { recursive: true, force: true }); fs.rmSync(dirPath, { recursive: true, force: true });
} }
function withTempDir(prefix, fn) {
const dirPath = createTempDir(prefix);
try {
return fn(dirPath);
} finally {
cleanup(dirPath);
}
}
test('withTempDir removes temp directories when the callback throws', () => {
let createdDir = '';
assert.throws(() => {
withTempDir('ecc-test-', dirPath => {
createdDir = dirPath;
assert.ok(fs.existsSync(createdDir));
throw new Error('fixture failure');
});
}, /fixture failure/);
assert.ok(createdDir);
assert.ok(!fs.existsSync(createdDir));
});
function writeFile(rootDir, relativePath, content) { function writeFile(rootDir, relativePath, content) {
const targetPath = path.join(rootDir, relativePath); const targetPath = path.join(rootDir, relativePath);
fs.mkdirSync(path.dirname(targetPath), { recursive: true }); fs.mkdirSync(path.dirname(targetPath), { recursive: true });
@ -125,6 +148,43 @@ test('readFrontmatter parses array tools field', () => {
cleanup(testRoot); cleanup(testRoot);
}); });
test('readFrontmatter preserves scoped tools in legacy flow sequences', () => {
const { readFrontmatter } = require(SCRIPT);
withTempDir('ecc-test-', tempDir => {
writeFile(tempDir, 'agent.md', [
'---',
'name: scoped-agent',
'tools: [Agent(worker, researcher), Read, Bash(git commit:*, git status:*)]',
'---',
'body',
].join('\n'));
const fm = readFrontmatter(path.join(tempDir, 'agent.md'));
assert.deepStrictEqual(fm.tools, [
'Agent(worker, researcher)',
'Read',
'Bash(git commit:*, git status:*)',
]);
});
});
test('readFrontmatter normalizes comma-separated scalar tools to an array', () => {
const { readFrontmatter } = require(SCRIPT);
testRoot = createTempDir('ecc-test-');
writeFile(testRoot, 'agent.md', [
'---',
'name: test-agent',
'tools: Bash, Read, Write',
'---',
'# Body',
].join('\n'));
const fm = readFrontmatter(path.join(testRoot, 'agent.md'));
assert.ok(Array.isArray(fm.tools));
assert.deepStrictEqual(fm.tools, ['Bash', 'Read', 'Write']);
cleanup(testRoot);
});
test('readFrontmatter handles quoted values', () => { test('readFrontmatter handles quoted values', () => {
const { readFrontmatter } = require(SCRIPT); const { readFrontmatter } = require(SCRIPT);
testRoot = createTempDir('ecc-test-'); testRoot = createTempDir('ecc-test-');
@ -202,7 +262,7 @@ test('loadAgents loads agent markdown files', () => {
'name: typescript-reviewer', 'name: typescript-reviewer',
'description: Reviews TypeScript code', 'description: Reviews TypeScript code',
'model: claude-sonnet-4-6', 'model: claude-sonnet-4-6',
'tools: [Bash, Read, Write, Grep]', 'tools: Bash, Read, Write, Grep',
'---', '---',
'# TypeScript Reviewer', '# TypeScript Reviewer',
'You are a TypeScript code reviewer.', 'You are a TypeScript code reviewer.',
@ -212,7 +272,7 @@ test('loadAgents loads agent markdown files', () => {
'name: python-reviewer', 'name: python-reviewer',
'description: Reviews Python code', 'description: Reviews Python code',
'model: claude-opus-4-8', 'model: claude-opus-4-8',
'tools: [Bash, Read]', 'tools: Bash, Read',
'---', '---',
'# Python Reviewer', '# Python Reviewer',
].join('\n')); ].join('\n'));

View file

@ -99,6 +99,36 @@ function runTests() {
} }
})) passed++; else failed++; })) passed++; else failed++;
if (test('adapts comma-separated scalar Claude Code tools', () => {
const tempDir = createTempDir();
const agentsDir = path.join(tempDir, '.gemini', 'agents');
try {
writeAgent(
agentsDir,
'docs-lookup.md',
[
'---',
'name: docs-lookup',
'description: Documentation lookup agent',
'tools: Read, Grep, mcp__context7__resolve-library-id, mcp__context7__query-docs',
'model: sonnet',
'---',
'',
'Body'
].join('\n')
);
const result = run([agentsDir]);
assert.strictEqual(result.code, 0, result.stderr);
const updated = fs.readFileSync(path.join(agentsDir, 'docs-lookup.md'), 'utf8');
assert.ok(updated.includes('tools: ["read_file", "grep_search", "mcp_context7_resolve_library_id", "mcp_context7_query_docs"]'));
} finally {
cleanupTempDir(tempDir);
}
})) passed++; else failed++;
if (test('defaults to the cwd .gemini/agents directory', () => { if (test('defaults to the cwd .gemini/agents directory', () => {
const tempDir = createTempDir(); const tempDir = createTempDir();
const agentsDir = path.join(tempDir, '.gemini', 'agents'); const agentsDir = path.join(tempDir, '.gemini', 'agents');