From 976c08e4c35d4c9fe3596605af2d9baa858ca5ae Mon Sep 17 00:00:00 2001 From: jiangnan <1394485448@qq.com> Date: Fri, 6 Mar 2026 04:37:53 +0800 Subject: [PATCH] Add CI workflow to validate agent file format Adds a lint script and GitHub Actions workflow that checks agent markdown files for required YAML frontmatter fields (name, description, color) and recommends standard sections. Only changed files in PRs are validated to avoid blocking on pre-existing issues. --- .github/workflows/lint-agents.yml | 44 ++++++++++++ scripts/lint-agents.sh | 114 ++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 .github/workflows/lint-agents.yml create mode 100755 scripts/lint-agents.sh diff --git a/.github/workflows/lint-agents.yml b/.github/workflows/lint-agents.yml new file mode 100644 index 0000000..8baa37f --- /dev/null +++ b/.github/workflows/lint-agents.yml @@ -0,0 +1,44 @@ +name: Lint Agent Files + +on: + pull_request: + paths: + - 'design/**' + - 'engineering/**' + - 'marketing/**' + - 'product/**' + - 'project-management/**' + - 'testing/**' + - 'support/**' + - 'spatial-computing/**' + - 'specialized/**' + +jobs: + lint: + name: Validate agent frontmatter and structure + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get changed agent files + id: changed + run: | + FILES=$(git diff --name-only --diff-filter=ACMR origin/${{ github.base_ref }}...HEAD -- \ + 'design/*.md' 'engineering/*.md' 'marketing/*.md' 'product/*.md' \ + 'project-management/*.md' 'testing/*.md' 'support/*.md' \ + 'spatial-computing/*.md' 'specialized/*.md') + echo "files=$FILES" >> "$GITHUB_OUTPUT" + if [ -z "$FILES" ]; then + echo "No agent files changed." + else + echo "Changed files:" + echo "$FILES" + fi + + - name: Run agent linter + if: steps.changed.outputs.files != '' + run: | + chmod +x scripts/lint-agents.sh + ./scripts/lint-agents.sh ${{ steps.changed.outputs.files }} diff --git a/scripts/lint-agents.sh b/scripts/lint-agents.sh new file mode 100755 index 0000000..3ba121c --- /dev/null +++ b/scripts/lint-agents.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +# +# Validates agent markdown files: +# 1. YAML frontmatter must exist with name, description, color (ERROR) +# 2. Recommended sections checked but only warned (WARN) +# 3. File must have meaningful content +# +# Usage: ./scripts/lint-agents.sh [file ...] +# If no files given, scans all agent directories. + +set -euo pipefail + +AGENT_DIRS=( + design + engineering + marketing + product + project-management + testing + support + spatial-computing + specialized +) + +REQUIRED_FRONTMATTER=("name" "description" "color") +RECOMMENDED_SECTIONS=("Identity" "Core Mission" "Critical Rules") + +errors=0 +warnings=0 + +lint_file() { + local file="$1" + + # 1. Check frontmatter delimiters + local first_line + first_line=$(head -1 "$file") + if [[ "$first_line" != "---" ]]; then + echo "ERROR $file: missing frontmatter opening ---" + ((errors++)) + return + fi + + # Extract frontmatter (between first and second ---) + local frontmatter + frontmatter=$(awk 'NR==1{next} /^---$/{exit} {print}' "$file") + + if [[ -z "$frontmatter" ]]; then + echo "ERROR $file: empty or malformed frontmatter" + ((errors++)) + return + fi + + # 2. Check required frontmatter fields + for field in "${REQUIRED_FRONTMATTER[@]}"; do + if ! echo "$frontmatter" | grep -qE "^${field}:"; then + echo "ERROR $file: missing frontmatter field '${field}'" + ((errors++)) + fi + done + + # 3. Check recommended sections (warn only) + local body + body=$(awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}' "$file") + + for section in "${RECOMMENDED_SECTIONS[@]}"; do + if ! echo "$body" | grep -qi "$section"; then + echo "WARN $file: missing recommended section '${section}'" + ((warnings++)) + fi + done + + # 4. Check file has meaningful content + if [[ $(echo "$body" | wc -w) -lt 50 ]]; then + echo "WARN $file: body seems very short (< 50 words)" + ((warnings++)) + fi +} + +# Collect files to lint +files=() +if [[ $# -gt 0 ]]; then + files=("$@") +else + for dir in "${AGENT_DIRS[@]}"; do + if [[ -d "$dir" ]]; then + while IFS= read -r f; do + files+=("$f") + done < <(find "$dir" -maxdepth 1 -name "*.md" -type f | sort) + fi + done +fi + +if [[ ${#files[@]} -eq 0 ]]; then + echo "No agent files found." + exit 1 +fi + +echo "Linting ${#files[@]} agent files..." +echo "" + +for file in "${files[@]}"; do + lint_file "$file" +done + +echo "" +echo "Results: ${errors} error(s), ${warnings} warning(s) in ${#files[@]} files." + +if [[ $errors -gt 0 ]]; then + echo "FAILED: fix the errors above before merging." + exit 1 +else + echo "PASSED" + exit 0 +fi