Files
agent-estate-wiki/regenerate-skills-index.sh
T
Tony0410 b12d8b5e3d feat: auto-regenerate skills stock-take + add 330-skill inventory
The skills-index page had drifted badly (claimed 66 skills; 330 are actually
installed). Regenerate it from the live skill tree and add an automated
regeneration script + related cron so it can never go stale again.

- regenerate-skills-index.sh: full stock-take (inventory -> quartz build -> deploy)
- systems/skills-index.md: rebuilt with all 330 skills across 26 categories
- .gitignore: fix stray literal chars, ignore build artifacts
2026-08-15 23:53:55 +08:00

120 lines
4.1 KiB
Bash
Executable File

#!/bin/bash
# regenerate-skills-index.sh
# Stock-take: regenerate systems/skills-index.md from the live skill tree,
# rebuild the Quartz site, and redeploy. Run on a schedule so the wiki never drifts.
set -euo pipefail
WIKI="/home/hermes/workspace/agent-estate-wiki"
QUARTZ="/home/hermes/workspace/quartz-temp"
SKILLS="/home/hermes/.hermes/skills"
echo "[$(date -Is)] Starting skills stock-take"
# 1. Regenerate skills-index.md from the live skill tree
python3 - "$SKILLS" "$WIKI/systems/skills-index.md" <<'PY'
import sys, re
from collections import defaultdict
from pathlib import Path
from datetime import date
skills_root = Path(sys.argv[1])
out_path = Path(sys.argv[2])
skill_files = list(skills_root.rglob('SKILL.md'))
skills = defaultdict(list)
for f in skill_files:
rel = f.relative_to(skills_root)
parts = rel.parts
if len(parts) >= 3:
cat, name = parts[0], parts[1]
elif len(parts) == 2:
cat, name = 'uncategorized', parts[0]
else:
continue
desc = ''
try:
content = f.read_text(errors='ignore')
m = re.search(r'^description:\s*(.+)$', content[:2000], re.M)
if m:
desc = m.group(1).strip().strip('"').strip("'")[:120]
except Exception:
pass
skills[cat].append((name, desc))
total = sum(len(v) for v in skills.values())
L = []
L.append('---')
L.append('title: Installed Skills')
L.append('type: system')
L.append('status: active')
L.append('created: 2026-07-22')
L.append(f'updated: {date.today().isoformat()}')
L.append(f'verified_on: {date.today().isoformat()}')
L.append('confidence: high')
L.append('tags: [skills, hermes]')
L.append('sources: []')
L.append('---')
L.append('')
L.append('# Installed Skills')
L.append('')
L.append(f'**Total installed: {total} skills** in `~/.hermes/skills/`.')
L.append('')
L.append('This page is auto-regenerated from the live skill inventory. Do not hand-edit.')
L.append('')
L.append('## Stock-take notes')
L.append('- Category names come from the directory structure under `~/.hermes/skills/` (`category/skill/SKILL.md`).')
L.append('- Skills stored directly under `~/.hermes/skills/` (no subfolder) are grouped under `uncategorized`.')
L.append('- Deeper nested paths (e.g. `mlops/evaluation`) are grouped by their top-level category.')
L.append('')
priority = ['core-hermes','autonomous-ai-agents','hermes','devops','productivity','creative','software-development','research','email','mlops','github','apple','frontend','media','note-taking','web-development','smart-home','mcp','uncategorized']
def cat_order(cat):
try: return priority.index(cat)
except ValueError: return 100 + len(priority)
cats = sorted(skills.items(), key=lambda x: (cat_order(x[0]), -len(x[1])))
for cat, items in cats:
nice = cat.replace('-', ' ').title()
L.append(f'## {nice} ({len(items)})')
L.append('')
for name, desc in sorted(items):
L.append(f'- `{name}` — {desc}' if desc else f'- `{name}`')
L.append('')
L.append('## Related')
L.append('- [[systems/hermes-agent]]')
L.append('- [[systems/omniroute]]')
L.append('')
out_path.write_text('\n'.join(L))
print(f"Regenerated {out_path} with {total} skills across {len(skills)} categories")
PY
# 2. Sync content into Quartz
rm -rf "$QUARTZ/content" "$QUARTZ/public"
mkdir -p "$QUARTZ/content"
python3 - "$WIKI" "$QUARTZ/content" <<'PY'
import shutil, sys
from pathlib import Path
src = Path(sys.argv[1]); dst = Path(sys.argv[2])
skip = {'.git','public','node_modules','quartz-site','serve.py','.gitignore','package.json','package-lock.json','.codewiki-state.json'}
for item in src.iterdir():
if item.name in skip: continue
if item.is_dir():
shutil.copytree(item, dst / item.name, dirs_exist_ok=True)
elif item.suffix == '.md':
shutil.copy2(item, dst / item.name)
PY
# 3. Build Quartz
cd "$QUARTZ"
npx quartz build >/tmp/quartz-build.log 2>&1 || { echo "Quartz build failed"; tail -20 /tmp/quartz-build.log; exit 1; }
# 4. Deploy to public
rm -rf "$WIKI/public"
mkdir -p "$WIKI/public"
cp -a "$QUARTZ/public/." "$WIKI/public/"
echo "[$(date -Is)] Completed: $(find "$WIKI/public" -name '*.html' | wc -l) html files deployed"