fix: refactor update_readme to match current README (counts only, no Full Skill Registry)

- Remove Full Skill Registry and table logic; keep only count substitutions
- Add Browse N+ Skills and TOC link updates
- Always write README after substitutions so chain completes without error
This commit is contained in:
sck_0
2026-01-29 13:13:34 +01:00
parent 559dd6f40f
commit f9b6a3b8db
5 changed files with 28 additions and 105 deletions

View File

@@ -3,140 +3,63 @@ import json
import os
import re
def update_readme():
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
readme_path = os.path.join(base_dir, "README.md")
index_path = os.path.join(base_dir, "skills_index.json")
print(f"📖 Reading skills index from: {index_path}")
with open(index_path, 'r', encoding='utf-8') as f:
with open(index_path, "r", encoding="utf-8") as f:
skills = json.load(f)
total_skills = len(skills)
print(f"🔢 Total skills found: {total_skills}")
print(f"📝 Updating README at: {readme_path}")
with open(readme_path, 'r', encoding='utf-8') as f:
with open(readme_path, "r", encoding="utf-8") as f:
content = f.read()
# 1. Update Title Count
content = re.sub(
r'(# 🌌 Antigravity Awesome Skills: )\d+(\+ Agentic Skills)',
f'\\g<1>{total_skills}\\g<2>',
content
r"(# 🌌 Antigravity Awesome Skills: )\d+(\+ Agentic Skills)",
rf"\g<1>{total_skills}\g<2>",
content,
)
# 2. Update Blockquote Count
content = re.sub(
r'(Collection of )\d+(\+ Universal)',
f'\\g<1>{total_skills}\\g<2>',
content
r"(Collection of )\d+(\+ Universal)",
rf"\g<1>{total_skills}\g<2>",
content,
)
# 3. Update Intro Text Count
content = re.sub(
r'(library of \*\*)\d+( high-performance skills\*\*)',
f'\\g<1>{total_skills}\\g<2>',
content
r"(library of \*\*)\d+( high-performance skills\*\*)",
rf"\g<1>{total_skills}\g<2>",
content,
)
# 4. Update Registry Header Count
# 4. Update Browse section header
content = re.sub(
r'(## Full Skill Registry \()\d+/\d+(\))',
f'\\g<1>{total_skills}/{total_skills}\\g<2>',
content
r"## Browse \d+\+ Skills",
f"## Browse {total_skills}+ Skills",
content,
)
# 5. Ensure Curated Collections section exists (idempotent)
#
# Historical note: we previously used "## 📦 Curated Collections" in some runs.
# If the README already contains "## Curated Collections", inserting the emoji header creates duplicates.
canonical_collections_header = "## Curated Collections"
canonical_collections_body = "[Check out our Starter Packs in docs/BUNDLES.md](docs/BUNDLES.md) to find the perfect toolkit for your role."
# Normalize any emoji variant to the canonical header
content = content.replace("## 📦 Curated Collections", canonical_collections_header)
# If the section is missing entirely, insert it right before the Full Skill Registry section
if canonical_collections_header not in content:
registry_header_match = re.search(r'^## Full Skill Registry', content, flags=re.MULTILINE)
if registry_header_match:
insert_block = f"{canonical_collections_header}\n\n{canonical_collections_body}\n\n"
content = content[:registry_header_match.start()] + insert_block + content[registry_header_match.start():]
# De-dupe repeated Curated Collections blocks (e.g. after a previous buggy insert)
escaped_body = re.escape(canonical_collections_body)
dedupe_pattern = re.compile(
rf'(?:{re.escape(canonical_collections_header)}\s*\n\s*\n{escaped_body}\s*\n\s*){{2,}}',
flags=re.MULTILINE
# 5. Update TOC link for Browse (anchor matches header-derived slug)
content = re.sub(
r"\[📚 Browse \d+\+ Skills\]\(#browse-\d+-skills\)",
f"[📚 Browse {total_skills}+ Skills](#browse-{total_skills}-skills)",
content,
)
content = dedupe_pattern.sub(f"{canonical_collections_header}\n\n{canonical_collections_body}\n\n", content)
# 6. Generate New Registry Table
print("🔄 Generating new registry table...")
# Store the Note block to preserve it
note_pattern = r'(> \[!NOTE\].*?)\n\n\| Skill Name'
note_match = re.search(note_pattern, content, re.DOTALL)
note_block = ""
if note_match:
note_block = note_match.group(1)
else:
note_block = "> [!NOTE] > **Document Skills**: We provide both **community** and **official Anthropic** versions. Locally, the official versions are used by default."
with open(readme_path, "w", encoding="utf-8") as f:
f.write(content)
table_header = "| Skill Name | Risk | Description | Path |\n| :--- | :--- | :--- | :--- |"
table_rows = []
print("✅ README.md updated successfully.")
for skill in skills:
name = skill.get('name', 'Unknown')
desc = skill.get('description', '').replace('\n', ' ').strip()
path = skill.get('path', '')
risk = skill.get('risk', 'unknown')
# Risk Icons
risk_icon = ""
if risk == "official": risk_icon = "🟣" # Mapping official to purple
if risk == "none": risk_icon = "🟢"
if risk == "safe": risk_icon = "🔵"
if risk == "critical": risk_icon = "🟠"
if risk == "offensive": risk_icon = "🔴"
# Escape pipes
desc = desc.replace('|', r'\|')
row = f"| **{name}** | {risk_icon} | {desc} | `{path}` |"
table_rows.append(row)
new_table_section = f"{note_block}\n\n{table_header}\n" + "\n".join(table_rows)
# Replace the old table section
header_pattern = r'## Full Skill Registry \(\d+/\d+\)'
header_match = re.search(header_pattern, content)
if not header_match:
print("❌ Could not find 'Full Skill Registry' header.")
return
start_pos = header_match.end()
# Find the next section (## ...) or end of file
next_section_match = re.search(r'\n## ', content[start_pos:])
if next_section_match:
end_pos = start_pos + next_section_match.start()
rest_of_file = content[end_pos:]
else:
rest_of_file = ""
before_header = content[:header_match.start()]
new_header = f"## Full Skill Registry ({total_skills}/{total_skills})"
new_content = f"{before_header}{new_header}\n\n{new_table_section}\n{rest_of_file}"
with open(readme_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print("✅ README.md updated successfully with Collections link and Risk columns.")
if __name__ == "__main__":
update_readme()