name: Validate SKILL.md files

on:
  push:
    paths:
      - 'skills/**'
      - 'tools/**'
      - '.github/workflows/validate-skills.yml'
  pull_request:
    paths:
      - 'skills/**'
      - 'tools/**'
      - '.github/workflows/validate-skills.yml'
  workflow_dispatch:

jobs:
  validate:
    runs-on: ubuntu-latest
    name: Validate SKILL.md frontmatter
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: pip install pyyaml

      # All frontmatter is parsed by tools/skill_frontmatter.py (PyYAML). Any
      # reintroduced regex parser silently truncates multi-line descriptions --
      # that bug shipped 604/817 broken descriptions before it was caught.
      - name: Guard against hand-rolled YAML parsers
        run: |
          if grep -rnE '(re\.(search|match|compile)\([^)]*description|^\s*description:.*\(\.\*\))' \
               tools/ --include='*.py' ; then
            echo "::error::Regex-based frontmatter parsing detected. Use tools/skill_frontmatter.py."
            exit 1
          fi
          echo "OK: no regex frontmatter parsers"

      # Single source of truth: tools/validate-skill.py validates required
      # frontmatter fields, kebab-case name, description length, subdomain, and
      # tag count. (Previously this step duplicated a weaker inline parser.)
      - name: Validate SKILL.md frontmatter
        run: python3 tools/validate-skill.py --all

      # agentskills.io conformance: name==directory, 1..1024 description,
      # reserved-word ban, angle-bracket injection check.
      - name: Validate agentskills.io conformance
        run: python3 tools/validate-agentskills.py --strict

      # index.json is generated; a PR that changes a description must regenerate it.
      - name: Check index.json is current
        run: python3 tools/generate-index.py --check

      # Description quality gate. Pre-existing failures are grandfathered in
      # tools/lint-baseline.json so this blocks NEW debt only; the baseline is
      # allowed to shrink and never to grow.
      - name: Lint descriptions
        run: python3 tools/lint-descriptions.py --all --stats

      # Ratchet: the number of unreviewed near-duplicate description pairs may
      # never increase. Lower this cap as disambiguation lands.
      - name: Detect skill collisions
        run: python3 tools/detect-collisions.py --max-unreviewed 55

      - name: Check for duplicate skill names
        run: |
          python3 << 'EOF'
          import os
          import re
          from collections import Counter

          names = []
          for root, dirs, files in os.walk('skills'):
              for file in files:
                  if file == 'SKILL.md':
                      path = os.path.join(root, file)
                      with open(path, 'r', encoding='utf-8') as f:
                          content = f.read()
                      fm_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
                      if fm_match:
                          name_match = re.search(r'^name:\s*(.+)$', fm_match.group(1), re.MULTILINE)
                          if name_match:
                              names.append(name_match.group(1).strip().strip('"'))

          duplicates = [name for name, count in Counter(names).items() if count > 1]
          if duplicates:
              print(f"❌ Duplicate skill names found: {duplicates}")
              exit(1)
          print(f"✅ No duplicate names in {len(names)} skills")
          EOF

      - name: Report skill counts
        if: always()
        run: |
          echo "## Skill Database Stats" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          python3 << 'EOF'
          import os
          import re
          from collections import Counter

          subdomain_counts = Counter()
          total = 0
          for root, dirs, files in os.walk('skills'):
              for file in files:
                  if file == 'SKILL.md':
                      total += 1
                      path = os.path.join(root, file)
                      with open(path, 'r', encoding='utf-8') as f:
                          content = f.read()
                      fm_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
                      if fm_match:
                          sd_match = re.search(r'^subdomain:\s*(.+)$', fm_match.group(1), re.MULTILINE)
                          if sd_match:
                              subdomain_counts[sd_match.group(1).strip()] += 1

          print(f"**Total Skills: {total}**")
          print("")
          print("| Subdomain | Count |")
          print("|-----------|-------|")
          for sd, count in sorted(subdomain_counts.items(), key=lambda x: -x[1]):
              print(f"| {sd} | {count} |")
          EOF
