init: project structure, templates, build system

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
salvacybersec
2026-03-22 00:26:28 +03:00
commit 19ef1da170
6 changed files with 1013 additions and 0 deletions

156
build.py Executable file
View File

@@ -0,0 +1,156 @@
#!/usr/bin/env python3
"""Build script: Generate .yaml and .json from persona .md files."""
import json
import os
import re
import sys
from pathlib import Path
try:
import yaml
except ImportError:
print("PyYAML required: pip install pyyaml")
sys.exit(1)
def parse_persona_md(filepath: Path) -> dict:
"""Parse a persona markdown file into structured data."""
content = filepath.read_text(encoding="utf-8")
# Extract YAML frontmatter
fm_match = re.match(r"^---\n(.*?)\n---\n(.*)$", content, re.DOTALL)
if not fm_match:
print(f" WARN: No frontmatter in {filepath}")
return {}
frontmatter = yaml.safe_load(fm_match.group(1))
body = fm_match.group(2).strip()
# Extract sections from body
sections = {}
current_section = None
current_content = []
for line in body.split("\n"):
if line.startswith("## "):
if current_section:
sections[current_section] = "\n".join(current_content).strip()
current_section = line[3:].strip().lower().replace(" ", "_").replace("&", "and")
current_content = []
else:
current_content.append(line)
if current_section:
sections[current_section] = "\n".join(current_content).strip()
return {
"metadata": frontmatter,
"sections": sections,
"raw_body": body,
}
def build_persona(persona_dir: Path, output_dir: Path):
"""Build all variants for a persona directory."""
md_files = sorted(persona_dir.glob("*.md"))
if not md_files:
return
persona_name = persona_dir.name
out_path = output_dir / persona_name
out_path.mkdir(parents=True, exist_ok=True)
# Load _meta.yaml if exists
meta_file = persona_dir / "_meta.yaml"
meta = {}
if meta_file.exists():
meta = yaml.safe_load(meta_file.read_text(encoding="utf-8")) or {}
for md_file in md_files:
if md_file.name.startswith("_"):
continue
variant = md_file.stem
parsed = parse_persona_md(md_file)
if not parsed:
continue
# Merge meta into parsed data
output = {**meta, **parsed["metadata"], "variant": variant, "sections": parsed["sections"]}
# Write YAML
yaml_out = out_path / f"{variant}.yaml"
yaml_out.write_text(
yaml.dump(output, allow_unicode=True, default_flow_style=False, sort_keys=False),
encoding="utf-8",
)
# Write JSON
json_out = out_path / f"{variant}.json"
json_out.write_text(json.dumps(output, ensure_ascii=False, indent=2), encoding="utf-8")
# Write plain system prompt (just the body)
prompt_out = out_path / f"{variant}.prompt.md"
prompt_out.write_text(parsed["raw_body"], encoding="utf-8")
print(f" Built: {persona_name}/{variant} -> .yaml .json .prompt.md")
def build_catalog(personas_dir: Path, output_dir: Path):
"""Generate CATALOG.md from all personas."""
catalog_lines = ["# Persona Catalog\n", "_Auto-generated by build.py_\n"]
for persona_dir in sorted(personas_dir.iterdir()):
if not persona_dir.is_dir() or persona_dir.name.startswith((".", "_")):
continue
meta_file = persona_dir / "_meta.yaml"
if not meta_file.exists():
continue
meta = yaml.safe_load(meta_file.read_text(encoding="utf-8")) or {}
variants = [f.stem for f in sorted(persona_dir.glob("*.md")) if not f.name.startswith("_")]
catalog_lines.append(f"## {meta.get('codename', persona_dir.name)}{meta.get('role', 'Unknown')}")
catalog_lines.append(f"- **Domain:** {meta.get('domain', 'N/A')}")
catalog_lines.append(f"- **Hitap:** {meta.get('address_to', 'N/A')}")
catalog_lines.append(f"- **Variants:** {', '.join(variants)}")
catalog_lines.append("")
catalog_path = personas_dir / "CATALOG.md"
catalog_path.write_text("\n".join(catalog_lines), encoding="utf-8")
print(f" Catalog: {catalog_path}")
def main():
root = Path(__file__).parent
personas_dir = root / "personas"
if not personas_dir.exists():
print("No personas/ directory found.")
sys.exit(1)
output_dir = root / ".generated"
# Find all persona directories
persona_dirs = [
d for d in sorted(personas_dir.iterdir()) if d.is_dir() and not d.name.startswith((".", "_"))
]
if not persona_dirs:
print("No persona directories found.")
sys.exit(1)
output_dir.mkdir(parents=True, exist_ok=True)
print(f"Building {len(persona_dirs)} personas -> {output_dir}\n")
for pdir in persona_dirs:
build_persona(pdir, output_dir)
build_catalog(personas_dir, output_dir)
print(f"\nDone. {len(persona_dirs)} personas built.")
if __name__ == "__main__":
main()