diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e128868..b735087 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,3 +38,130 @@ jobs: echo "$unformatted" exit 1 fi + + validate-counts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Validate README and ROADMAP counts + run: | + set -uo pipefail + ERRORS="" + CHECKS=0 + + # Verify directories exist + for dir in commands skills workflows hooks; do + if [ ! -d "$dir" ]; then + echo "FATAL: $dir/ directory missing" + exit 1 + fi + done + + # Count actual files + CMD_COUNT=$(set -- commands/*.md; echo $#) + SKILL_COUNT=$(find skills -maxdepth 2 -name 'SKILL.md' | wc -l | tr -d ' ') + WORKFLOW_COUNT=$(set -- workflows/*.yml; echo $#) + HOOK_COUNT=$(python3 -c " + import sys, json + data = json.load(open('hooks/hooks.json')) + scripts = set() + for event in data.get('hooks', {}).values(): + for entry in event: + for h in entry.get('hooks', []): + cmd = h.get('command', '') + scripts.add(cmd.split('/')[-1]) + print(len(scripts)) + ") || { echo "FATAL: failed to parse hooks/hooks.json"; exit 1; } + + # Validate counts are non-zero + for var_name in CMD_COUNT SKILL_COUNT WORKFLOW_COUNT HOOK_COUNT; do + val=$(eval echo \$$var_name) + if [ -z "$val" ] || [ "$val" = "0" ]; then + echo "FATAL: $var_name is empty or zero ($val)" + exit 1 + fi + done + + echo "Actual counts: commands=$CMD_COUNT skills=$SKILL_COUNT workflows=$WORKFLOW_COUNT hooks=$HOOK_COUNT" + + # Check README and ROADMAP + for file in README.md ROADMAP.md; do + if [ ! -f "$file" ]; then continue; fi + + # Commands + if grep -qE "\*\*[0-9]+ slash commands\*\*" "$file"; then + DOC_CMD=$(grep -m1 -oE '\*\*[0-9]+ slash commands\*\*' "$file" | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$DOC_CMD" != "$CMD_COUNT" ]; then + ERRORS="$ERRORS\n$file: says $DOC_CMD commands, actual is $CMD_COUNT" + fi + fi + + # Skills + if grep -qE "\*\*[0-9]+ context-activated skills\*\*" "$file"; then + DOC_SKILL=$(grep -m1 -oE '\*\*[0-9]+ context-activated skills\*\*' "$file" | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$DOC_SKILL" != "$SKILL_COUNT" ]; then + ERRORS="$ERRORS\n$file: says $DOC_SKILL skills, actual is $SKILL_COUNT" + fi + fi + + # Workflows + if grep -qE "\*\*[0-9]+ YAML workflows\*\*" "$file"; then + DOC_WF=$(grep -m1 -oE '\*\*[0-9]+ YAML workflows\*\*' "$file" | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$DOC_WF" != "$WORKFLOW_COUNT" ]; then + ERRORS="$ERRORS\n$file: says $DOC_WF workflows, actual is $WORKFLOW_COUNT" + fi + fi + + # Hooks + if grep -qE "\*\*[0-9]+ hooks\*\*" "$file"; then + DOC_HOOK=$(grep -m1 -oE '\*\*[0-9]+ hooks\*\*' "$file" | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$DOC_HOOK" != "$HOOK_COUNT" ]; then + ERRORS="$ERRORS\n$file: says $DOC_HOOK hooks, actual is $HOOK_COUNT" + fi + fi + done + + # Check README repo structure comments + if grep -qE '# [0-9]+ slash commands' README.md; then + TREE_CMD=$(grep -m1 -oE '# [0-9]+ slash commands' README.md | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$TREE_CMD" != "$CMD_COUNT" ]; then + ERRORS="$ERRORS\nREADME.md tree: says $TREE_CMD commands, actual is $CMD_COUNT" + fi + fi + if grep -qE '# [0-9]+ context-activated skills' README.md; then + TREE_SKILL=$(grep -m1 -oE '# [0-9]+ context-activated skills' README.md | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$TREE_SKILL" != "$SKILL_COUNT" ]; then + ERRORS="$ERRORS\nREADME.md tree: says $TREE_SKILL skills, actual is $SKILL_COUNT" + fi + fi + if grep -qE '# [0-9]+ YAML workflow' README.md; then + TREE_WF=$(grep -m1 -oE '# [0-9]+ YAML workflow' README.md | grep -oE '[0-9]+' | head -1) + CHECKS=$((CHECKS + 1)) + if [ "$TREE_WF" != "$WORKFLOW_COUNT" ]; then + ERRORS="$ERRORS\nREADME.md tree: says $TREE_WF workflows, actual is $WORKFLOW_COUNT" + fi + fi + + # Ensure at least some counts were validated + if [ "$CHECKS" -lt 1 ]; then + echo "FATAL: no count patterns found in README.md or ROADMAP.md — expected at least one" + exit 1 + fi + + if [ -n "$ERRORS" ]; then + echo "" + echo "COUNT MISMATCHES FOUND:" + printf '%b\n' "$ERRORS" + echo "" + echo "Fix the counts in README.md and/or ROADMAP.md to match actual file counts." + exit 1 + else + echo "All counts match ($CHECKS checks passed)." + fi