#!/usr/bin/env python3 """ scaffold.py — Bootstrap a new LLM Wiki directory structure. Usage: python3 scaffold.py "" Example: python3 scaffold.py ~/wikis/ai-research "AI Research" Creates: / ├── CLAUDE.md (schema template) ├── log/ │ └── YYYYMMDD.md (first day's log with scaffold entry) ├── audit/ │ ├── .gitkeep │ └── resolved/ │ └── .gitkeep ├── raw/ │ ├── articles/ │ ├── papers/ │ ├── notes/ │ └── refs/ ├── wiki/ │ ├── index.md (category-structured catalog) │ ├── concepts/ │ ├── entities/ │ └── summaries/ └── outputs/ └── queries/ """ import os import sys from datetime import date, datetime def scaffold(root: str, title: str) -> None: today = date.today() today_iso = today.isoformat() today_compact = today.strftime("%Y%m%d") now_hm = datetime.now().strftime("%H:%M") dirs = [ "raw/articles", "raw/papers", "raw/notes", "raw/refs", "wiki/concepts", "wiki/entities", "wiki/summaries", "outputs/queries", "log", "audit", "audit/resolved", ] for d in dirs: os.makedirs(os.path.join(root, d), exist_ok=True) print(f"✓ Created directory tree under {root}/") # .gitkeep for empty audit dirs _write(root, "audit/.gitkeep", "") _write(root, "audit/resolved/.gitkeep", "") # CLAUDE.md claude_md = f"""# {title} Knowledge Base > Schema document — read at the start of every session together with `wiki/index.md`. > Update after every major compile, ingest batch, or structural change. ## Scope What this wiki covers: - What this wiki deliberately excludes: - ## Operations This wiki follows the llm-wiki skill's five operations: `compile`, `ingest`, `query`, `lint`, `audit`. Every operation appends an entry to `log/YYYYMMDD.md`. ## Naming conventions - **Concept pages** (`wiki/concepts/`): Title Case noun phrases. - **Folder-split concepts** (`wiki/concepts//`): used when a topic exceeds ~1200 words. Contains `index.md` + one file per aspect. - **Entity pages** (`wiki/entities/`): Proper names. - **Summary pages** (`wiki/summaries/`): kebab-case source slug. All pages require YAML frontmatter: `title`, `type`, `created`, `updated`, `sources`, `tags`. ### Diagrams and formulas - All diagrams are **mermaid**. No ASCII art. - All formulas are **KaTeX** (inline `$...$` or block `$$...$$`). ### Raw file policy - Small text sources → copy into `raw//`. - Large binaries → create a pointer file at `raw/refs/.md` with `kind: ref` and `external_path` fields. Do not copy the binary. ## Current articles *None yet — update this list after every compile.* ### Concepts *(none)* ### Entities *(none)* ### Summaries *(none)* ## Open research questions - - ## Research gaps Sources to ingest: - [ ] — why it's relevant ## Audit backlog *(none — run `python3 scripts/audit_review.py --open` to refresh)* ## Notes for the LLM - Language: - Tone: - Depth: - Handling contradictions: state both, cite each, add to Open Research Questions. """ _write(root, "CLAUDE.md", claude_md) print("✓ Created CLAUDE.md") # log/.md log_md = f"""# {today_iso} ## [{now_hm}] scaffold | Initialized {title} knowledge base - Created directory tree (raw/, wiki/, log/, audit/, outputs/) - Created CLAUDE.md schema template - Created wiki/index.md category skeleton """ _write(root, f"log/{today_compact}.md", log_md) print(f"✓ Created log/{today_compact}.md") # wiki/index.md index_md = f"""# Index — {title} > One-sentence scope of the wiki. ## 🔖 Navigation - [[#Concepts]] · [[#Entities]] · [[#Summaries]] · [[#Open Questions]] ## Concepts *(none yet)* ## Entities *(none yet)* ## Summaries (chronological) *(none yet)* ## Open Questions - """ _write(root, "wiki/index.md", index_md) print("✓ Created wiki/index.md") print(f""" ✅ Wiki scaffolded at: {root}/ Next steps: 1. Fill in CLAUDE.md — define scope and naming conventions 2. Add sources to raw/ (use Obsidian Web Clipper for web articles) 3. Run ingest: tell your LLM agent "ingest raw/.md" 4. Ask questions: "what does the wiki say about X?" 5. Run lint periodically: python3 scripts/lint_wiki.py {root} 6. Process feedback: python3 scripts/audit_review.py {root} --open """) def _write(root: str, path: str, content: str) -> None: full = os.path.join(root, path) os.makedirs(os.path.dirname(full) or ".", exist_ok=True) with open(full, "w", encoding="utf-8") as f: f.write(content) if __name__ == "__main__": if len(sys.argv) < 3: print(__doc__) sys.exit(1) scaffold(sys.argv[1], sys.argv[2])