Files
Anthropic-Cybersecurity-Skills/.github/workflows/update-index.yml
T
Mahipal 796d96c413 fix: replace three hand-rolled YAML parsers with a shared PyYAML loader
index.json shipped 604 of 817 descriptions truncated to their first line.
The cause was the inline regex parser in update-index.yml: it reconstructed
multi-line descriptions only for the YAML block-scalar styles ('>' and '|')
and silently dropped continuation lines for every other style.

A census of the corpus explains the blast radius:

  block scalar   (description: >-)    43
  single-quoted multiline            278
  plain unquoted multiline           496
  single-line                          0

So 774 of 817 skills (94.7%) used a style the parser mishandled. Commit
d56fc0a7 had fixed only the 43 block-scalar files, and CONTRIBUTING.md
recommends that one working style, which is why it stayed hidden.

- add tools/skill_frontmatter.py, the single PyYAML-backed loader
- add tools/generate-index.py so generation is testable outside CI, with
  a --check mode for use as a gate
- delete the hand-rolled parsers from validate-skill.py (98 lines) and
  validate-agentskills.py, routing both through the shared loader
- implement the reserved-word check that agentskills-skill.schema.json
  names validate-agentskills.py as the enforcement point for

Verified by a differential harness against yaml.safe_load ground truth:
index-vs-source mismatches 606 -> 0.
2026-08-23 17:15:12 +02:00

80 lines
3.4 KiB
YAML

name: Update marketplace index
on:
push:
branches: [main]
paths:
- 'skills/**'
- '.github/workflows/update-index.yml'
workflow_dispatch:
jobs:
update-index:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: pip install pyyaml
# Generation lives in tools/generate-index.py so it is testable outside CI
# and shares one PyYAML-backed frontmatter parser with the validators.
# The previous inline regex parser silently truncated 604/817 descriptions
# to their first line for every YAML scalar style except '>'/'|'.
- name: Regenerate index.json
run: python3 tools/generate-index.py
- name: Sync skill count into README and marketplace
run: |
python3 << 'EOF'
import os, re, json
# Authoritative count: directories under skills/ that contain a SKILL.md
# and are not .bak backups (matches index.json generation above).
count = 0
for name in os.listdir("skills"):
if name.endswith(".bak"):
continue
if os.path.isfile(os.path.join("skills", name, "SKILL.md")):
count += 1
print(f"Authoritative skill count: {count}")
# README.md — replace the skills badge and every "<NNN> ... skills" phrase.
with open("README.md", encoding="utf-8") as f:
readme = f.read()
readme = re.sub(r"(badge/skills-)\d+", rf"\g<1>{count}", readme)
# "817 production-grade", "817 structured", "817 skills", "all 817 skills",
# "Scans 817 skill", "contains **817 skills**", BibTeX "{817 structured"
readme = re.sub(r"\b\d+(?=\s+production-grade cybersecurity skills)", str(count), readme)
readme = re.sub(r"\b\d+(?=\s+structured cybersecurity skills)", str(count), readme)
readme = re.sub(r"(all\s+)\d+(?=\s+skills)", rf"\g<1>{count}", readme)
readme = re.sub(r"(Scans\s+)\d+(?=\s+skill\b)", rf"\g<1>{count}", readme)
readme = re.sub(r"(contains\s+\*\*)\d+(?=\s+skills\*\*)", rf"\g<1>{count}", readme)
readme = re.sub(r"(\{)\d+(?=\s+structured cybersecurity skills)", rf"\g<1>{count}", readme)
with open("README.md", "w", encoding="utf-8") as f:
f.write(readme)
# marketplace.json + plugin.json — patch "<NNN> cybersecurity skills" in descriptions.
for path in (".claude-plugin/marketplace.json", ".claude-plugin/plugin.json"):
with open(path, encoding="utf-8") as f:
data = f.read()
data = re.sub(r"\b\d+(?=\s+cybersecurity skills)", str(count), data)
json.loads(data) # fail loudly if the regex broke JSON
with open(path, "w", encoding="utf-8") as f:
f.write(data)
print("Synced skill count into README.md, marketplace.json, plugin.json")
EOF
- name: Commit updated index and skill count
run: |
git config user.name "mukul975"
git config user.email "mukuljangra5@gmail.com"
git add index.json README.md .claude-plugin/marketplace.json .claude-plugin/plugin.json
git diff --staged --quiet || git commit -m "chore: auto-update index.json and skill count"
git push