Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/plugin-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,8 @@ jobs:
set -euo pipefail
SCRIPT="plugins/plugin-dev/skills/agent-development/scripts/validate-agent.sh"
errors=0
# Note: validate-agent.sh has a known bash arithmetic bug where
# ((warning_count++)) with set -e causes premature exit on the first
# warning. We capture output and only fail on actual ❌ errors.
# Capture output and detect ❌ markers rather than relying on exit code
# (defensive: tolerates any future regressions in the validator script).
while IFS= read -r f; do
echo "→ $f"
out=$(bash "$SCRIPT" "$f" 2>&1 || true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ fi
echo "✅ Starts with frontmatter"

# Check 3: Has closing ---
if ! tail -n +2 "$AGENT_FILE" | grep -q '^---$'; then
# Uses grep -c instead of grep -q to avoid SIGPIPE with set -o pipefail:
# grep -q exits early on first match while tail is still writing, causing
# tail to receive SIGPIPE (exit 141) which pipefail propagates as failure.
# grep -c reads all input before exiting, so no early-exit race condition.
if [ "$(tail -n +2 "$AGENT_FILE" | grep -c '^---$')" -eq 0 ]; then
echo "❌ Frontmatter not closed (missing second ---)"
exit 1
fi
Comment on lines +45 to 48

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current check ensures there is at least one closing ---, but it allows for multiple closing delimiters. This could lead to incorrect parsing of the frontmatter and system prompt later in the script if a file contains more than two --- lines. To make the validation more robust, I suggest checking for exactly one closing ---.

Suggested change
if [ "$(tail -n +2 "$AGENT_FILE" | grep -c '^---$')" -eq 0 ]; then
echo "❌ Frontmatter not closed (missing second ---)"
exit 1
fi
if [ "$(tail -n +2 "$AGENT_FILE" | grep -c '^---$')" -ne 1 ]; then
echo "❌ Frontmatter must be closed by exactly one '---' line"
exit 1
fi

Expand All @@ -60,30 +64,30 @@ NAME=$(echo "$FRONTMATTER" | grep '^name:' | sed 's/name: *//' | sed 's/^"\(.*\)

if [ -z "$NAME" ]; then
echo "❌ Missing required field: name"
((error_count++))
error_count=$((error_count+1))
else
echo "✅ name: $NAME"

# Validate name format
if ! [[ "$NAME" =~ ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$ ]]; then
echo "❌ name must start/end with alphanumeric and contain only letters, numbers, hyphens"
((error_count++))
error_count=$((error_count+1))
fi

# Validate name length
name_length=${#NAME}
if [ $name_length -lt 3 ]; then
if [ "$name_length" -lt 3 ]; then
echo "❌ name too short (minimum 3 characters)"
((error_count++))
elif [ $name_length -gt 50 ]; then
error_count=$((error_count+1))
elif [ "$name_length" -gt 50 ]; then
echo "❌ name too long (maximum 50 characters)"
((error_count++))
error_count=$((error_count+1))
fi

# Check for generic names
if [[ "$NAME" =~ ^(helper|assistant|agent|tool)$ ]]; then
echo "⚠️ name is too generic: $NAME"
((warning_count++))
warning_count=$((warning_count+1))
fi
fi

Expand All @@ -92,29 +96,29 @@ DESCRIPTION=$(echo "$FRONTMATTER" | grep '^description:' | sed 's/description: *

if [ -z "$DESCRIPTION" ]; then
echo "❌ Missing required field: description"
((error_count++))
error_count=$((error_count+1))
else
desc_length=${#DESCRIPTION}
echo "✅ description: ${desc_length} characters"

if [ $desc_length -lt 10 ]; then
if [ "$desc_length" -lt 10 ]; then
echo "⚠️ description too short (minimum 10 characters recommended)"
((warning_count++))
elif [ $desc_length -gt 5000 ]; then
warning_count=$((warning_count+1))
elif [ "$desc_length" -gt 5000 ]; then
echo "⚠️ description very long (over 5000 characters)"
((warning_count++))
warning_count=$((warning_count+1))
fi

# Check for example blocks
if ! echo "$DESCRIPTION" | grep -q '<example>'; then
echo "⚠️ description should include <example> blocks for triggering"
((warning_count++))
warning_count=$((warning_count+1))
fi

# Check for "Use this agent when" pattern
if ! echo "$DESCRIPTION" | grep -qi 'use this agent when'; then
echo "⚠️ description should start with 'Use this agent when...'"
((warning_count++))
warning_count=$((warning_count+1))
fi
fi

Expand All @@ -123,7 +127,7 @@ MODEL=$(echo "$FRONTMATTER" | grep '^model:' | sed 's/model: *//')

if [ -z "$MODEL" ]; then
echo "❌ Missing required field: model"
((error_count++))
error_count=$((error_count+1))
else
echo "✅ model: $MODEL"

Expand All @@ -133,7 +137,7 @@ else
;;
*)
echo "⚠️ Unknown model: $MODEL (valid: inherit, sonnet, opus, haiku)"
((warning_count++))
warning_count=$((warning_count+1))
;;
esac
fi
Expand All @@ -143,7 +147,7 @@ COLOR=$(echo "$FRONTMATTER" | grep '^color:' | sed 's/color: *//')

if [ -z "$COLOR" ]; then
echo "❌ Missing required field: color"
((error_count++))
error_count=$((error_count+1))
else
echo "✅ color: $COLOR"

Expand All @@ -153,13 +157,13 @@ else
;;
*)
echo "⚠️ Unknown color: $COLOR (valid: blue, cyan, green, yellow, magenta, red)"
((warning_count++))
warning_count=$((warning_count+1))
;;
esac
fi

# Check tools field (optional)
TOOLS=$(echo "$FRONTMATTER" | grep '^tools:' | sed 's/tools: *//')
TOOLS=$(echo "$FRONTMATTER" | grep '^tools:' | sed 's/tools: *//' || true)

if [ -n "$TOOLS" ]; then
echo "✅ tools: $TOOLS"
Expand All @@ -173,23 +177,23 @@ echo "Checking system prompt..."

if [ -z "$SYSTEM_PROMPT" ]; then
echo "❌ System prompt is empty"
((error_count++))
error_count=$((error_count+1))
else
prompt_length=${#SYSTEM_PROMPT}
echo "✅ System prompt: $prompt_length characters"

if [ $prompt_length -lt 20 ]; then
if [ "$prompt_length" -lt 20 ]; then
echo "❌ System prompt too short (minimum 20 characters)"
((error_count++))
elif [ $prompt_length -gt 10000 ]; then
error_count=$((error_count+1))
elif [ "$prompt_length" -gt 10000 ]; then
echo "⚠️ System prompt very long (over 10,000 characters)"
((warning_count++))
warning_count=$((warning_count+1))
fi

# Check for second person
if ! echo "$SYSTEM_PROMPT" | grep -q "You are\|You will\|Your"; then
echo "⚠️ System prompt should use second person (You are..., You will...)"
((warning_count++))
warning_count=$((warning_count+1))
fi

# Check for structure
Expand Down
12 changes: 4 additions & 8 deletions plugins/product-management/agents/pm-assistant.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
---
description: >
Product management assistant for PM decision support and workflow routing.
Use when the user asks for "PM help", "what should I work on", "help me prioritize",
"draft a spec", "analyze competitors", "write a stakeholder update", "review the
roadmap", "synthesize this feedback", or any product management task that spans
multiple PM disciplines. Reads existing project context before responding — never
makes assumptions about the product, roadmap, or stakeholders without first
checking available documentation.
name: pm-assistant
description: Use this agent when the user asks for "PM help", "what should I work on", "help me prioritize", "draft a spec", "analyze competitors", "write a stakeholder update", "review the roadmap", "synthesize this feedback", or any product management task spanning multiple PM disciplines. Reads existing project context before responding. <example>user: "Help me prioritize these features for the next sprint" assistant: "I'll use the pm-assistant agent to apply PM prioritization frameworks."</example> <example>user: "Write a stakeholder update for this week's progress" assistant: "I'll use the pm-assistant agent to draft a structured update."</example>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Quote agent descriptions containing colon-space examples

The new description values are plain YAML scalars but now include <example>user: "..." assistant: "..."</example> fragments, and : followed by a space is parsed as a mapping separator in YAML; this makes the frontmatter syntactically invalid and strict YAML loaders fail before reading metadata (Psych::SyntaxError reproduces on these files). This affects all four updated agents (plugins/product-management/agents/pm-assistant.md:3, plugins/productivity/agents/productivity-assistant.md:3, plugins/repo-structure/agents/automation-validator.md:3, plugins/strategy-toolkit/agents/strategic-analyst.md:3), so these agents can’t be reliably consumed by tooling that actually parses frontmatter as YAML.

Useful? React with 👍 / 👎.

capabilities:
- Routes between PM workflows: spec writing, roadmap, research synthesis, metrics, competitive analysis, stakeholder comms
- Reads existing docs (README, roadmap files, specs) before producing PM outputs
- Applies structured PM frameworks (RICE, MoSCoW, Jobs-to-be-Done, OKRs)
- Helps prioritize feature requests against strategic goals
- Surfaces metrics gaps and measurement blind spots
- Produces stakeholder-appropriate communications (exec summary vs eng detail)
model: sonnet
color: blue
---

# PM Assistant
Expand Down
12 changes: 4 additions & 8 deletions plugins/productivity/agents/productivity-assistant.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
---
description: >
Productivity assistant that routes between task management and memory management
based on conversational context. Use when the user asks about "my tasks", "what's
on my plate", "remind me to", "who is X", "what does Y mean", "help me stay on
track", "end of day review", "what did I work on today", or needs help maintaining
focus and clarity across a work session.
Reads TASKS.md and memory files before responding — never makes assumptions
about the user's current workload or terminology without checking.
name: productivity-assistant
description: Use this agent when the user asks about "my tasks", "what's on my plate", "remind me to", "who is X", "what does Y mean", "help me stay on track", "end of day review", or "what did I work on today". Routes between task management and memory management. Reads TASKS.md and memory files before responding. <example>user: "What tasks do I still have for today?" assistant: "I'll use the productivity-assistant agent to check your task list."</example> <example>user: "Who is the lead dev on the API project?" assistant: "I'll use the productivity-assistant agent to look up that context from memory."</example>
capabilities:
- Reads TASKS.md and surfaces active commitments and blockers
- Understands workplace acronyms, nicknames, and terminology from memory
- Extracts action items from meeting notes or conversation summaries
- Tracks what was worked on during a session and updates accordingly
- Flags overdue or stalled tasks proactively
- Bridges task-management and memory-management skills seamlessly
model: sonnet
color: green
---

# Productivity Assistant
Expand Down
10 changes: 4 additions & 6 deletions plugins/repo-structure/agents/automation-validator.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
---
description: >
Validates health of all automation files in a repository — GitHub Actions workflows,
pre-commit hooks, Claude Code hooks, Makefile/package.json scripts, and GitHub Actions
matrix coherence. Use when: "validate automation", "check my hooks", "automation health
check", /repo-validate --automation. Produces structured report with OK/WARN/FAIL per
category plus actionable fix list.
name: automation-validator
description: Use this agent when the user asks to "validate automation", "check my hooks", "automation health check", or runs /repo-validate --automation. Validates GitHub Actions workflows, pre-commit hooks, Claude Code hooks, Makefile/package.json scripts, and GitHub Actions matrix coherence. Produces structured report with OK/WARN/FAIL per category plus actionable fix list. <example>user: "Validate my GitHub Actions and hook setup" assistant: "I'll use the automation-validator agent for a comprehensive health check."</example> <example>user: "Check if my Claude Code hooks are correctly configured" assistant: "I'll use the automation-validator agent to audit the automation files."</example>
capabilities:
- Validate GitHub Actions workflow files (YAML syntax, events, runners, permissions)
- Validate .pre-commit-config.yaml (hook existence, stale versions, executable)
- Validate Claude Code hooks (scripts exist, executable, syntax OK)
- Validate task runners (Makefile, package.json scripts, pyproject.toml taskipy)
- Check GitHub Actions matrix coherence across workflow files
model: sonnet
color: yellow
---

# Automation Validator Agent
Expand Down
11 changes: 4 additions & 7 deletions plugins/strategy-toolkit/agents/strategic-analyst.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
---
description: >
Strategic analyst agent for deep project analysis and strategic recommendations.
Use when the user asks to "analyze this project strategically", "help me think about
expansion", "do a strategic deep-dive", "evaluate my product positioning",
"prepare me for a launch decision", or needs a systematic strategic perspective
that goes beyond quick brainstorming. This agent reads the full project context
before producing analysis — never makes claims without reading available files.
name: strategic-analyst
description: Use this agent when the user asks to "analyze this project strategically", "help me think about expansion", "do a strategic deep-dive", "evaluate my product positioning", or "prepare me for a launch decision". Reads full project context before producing analysis — never makes claims without reading available files. <example>user: "Do a strategic deep-dive on my CLI tool project" assistant: "I'll use the strategic-analyst agent for a comprehensive strategic analysis."</example> <example>user: "Help me think about whether to pivot this project" assistant: "I'll use the strategic-analyst agent to evaluate the strategic options."</example>
capabilities:
- Reads and synthesizes full project context (README, docs, CLAUDE.md, code structure)
- Applies 12 strategic frameworks from the toolkit reference
- Produces asset-first analysis (identifies the real asset, not just the code)
- Generates second-order thinking (what happens after success?)
- Delivers honest assessments including failure modes and uncomfortable truths
- Connects every insight to a concrete, actionable next step
model: sonnet
color: cyan
---

# Strategic Analyst
Expand Down