--- name: distill-best-practices description: > Cross-project best practices distillation. Reads changed memory files from all tracked projects and proposes additions, updates, or removals to the skynet/best-practices repo (gitea.oreillyit.nz/skynet/best-practices). Approved changes are committed and pushed to that repo, then synced back to claude-foundations/best-practices/ for backward compatibility. Run from any project -- always targets skynet/best-practices as output. Interactive -- presents proposals for approval before making changes. allowed-tools: Read, Edit, Write, Glob, Grep, Bash(git clone *), Bash(git -C *), Bash(git rev-parse *), Bash(ls *), Bash(cat *), Bash(head *), Bash(date *), Bash(mktemp *), Bash(rm -rf *), Bash(cp *) --- # Distill Best Practices Skill You are extracting generalisable best practices from project-specific memory files across all tracked projects. ## Pre-gathered context ### Pre-gathered context (read at runtime) The following files should be read using the Read tool at the start of execution: - `~/dev/claude/projects/claude-foundations/best-practices/.distill-state.json` — Distill state (if not found, treat as `{}`) - `~/dev/claude/projects/claude-foundations/settings.yaml` — Settings (if not found, use defaults from instructions) - Use Glob to list `~/dev/claude/projects/*/` for the projects directory listing **Then clone the skynet/best-practices repo** (see Step 0 below) and read from it: - `/BESTPRACTICES.md` — Current best-practices index (from cloned repo) - Use Glob to list `/*.md` for available topic files (from cloned repo) ## Instructions ### Step 0: Clone skynet/best-practices Before reading any best-practices content, clone the dedicated repo to a temp directory: ``` tmpdir=$(mktemp -d) git clone https://gitea.oreillyit.nz/skynet/best-practices "$tmpdir/best-practices" ``` The working path for the cloned repo is `$tmpdir/best-practices`. Use this path throughout — referred to below as ``. Read `/BESTPRACTICES.md` and list `/*.md` to discover available topic files. ### Step 1: Discover changes per project The project root is `~/dev/claude` (hardcoded — change at the top of the `!`command`` blocks if your layout differs). Key paths: - **Settings**: `~/dev/claude/projects/claude-foundations/settings.yaml` - **Best practices repo (primary)**: `/` (cloned skynet/best-practices) - **Best practices local copy (backward compat)**: `~/dev/claude/projects/claude-foundations/best-practices/` - **Best practices index**: `/BESTPRACTICES.md` - **Distill state**: `~/dev/claude/projects/claude-foundations/best-practices/.distill-state.json` Read `settings.yaml` (pre-gathered above). For each project in `distill.projects`, get its path: `~/dev/claude//`. Also process any `distill.extra_projects` entries — these have a `path` field relative to `~/dev/claude`. For each project (from both lists): 1. Get current HEAD: `git -C rev-parse HEAD` 2. Look up `last_sha` from `.distill-state.json` for this project 3. If SHA matches → skip this project (no changes) 4. If `last_sha` exists → find changed files: `git -C diff --name-only ..HEAD -- memory/` 5. If `last_sha` is missing (first run) → list all memory files: `ls /memory/*.md` Filter to only `memory/*.md` files (exclude `memory/log/` — those are raw, unprocessed). If no projects have changes, say so and stop. ### Step 2: Read changed memory files For each changed memory file, read its full content using the Read tool. Also identify which existing best-practices topic files cover the same domain. Use this mapping as a guide: - `gotchas-k8s.md` → `kubernetes.md` - `gotchas-cilium.md` → `kubernetes.md` - `gotchas-helm.md` → `helm.md` - `gotchas-ansible.md` → `ansible.md` - `gotchas-sops.md` → `secrets-management.md` - `process-lessons.md` → `validation.md`, `debugging.md` - `decisions.md` → various (match by content) - Other gotchas → match by topic or propose a new file Read the matching best-practices files from `/` so you can compare. ### Step 3: Analyse and propose For each potential change, classify it: - **ADD**: A lesson that is project-agnostic and valuable across projects. When generalising: - Strip project-specific details (IPs, namespace names, service names, hostnames) - Replace specifics with generic descriptions (e.g., "10.111.0.5" → "the DNS server IP") - Keep the principle and the reasoning — lose the implementation detail - Only promote lessons that would apply to at least one other project type - **UPDATE**: An existing best-practice entry that has new supporting evidence, needs refinement, or should be expanded with a new example. - **REMOVE**: A best-practice that has been invalidated — version-specific bug fixed, tool changed, approach superseded. Cross-reference: if the source gotcha was removed from the project's memory, the best-practice may be stale. ### Step 4: Present proposals **Do NOT make any changes yet.** Present a numbered list of proposals: ``` Proposals: 1. ADD to kubernetes.md: "" Source: cluster-bootstrap/memory/gotchas-k8s.md 2. UPDATE validation.md: "" Source: cluster-bootstrap/memory/process-lessons.md 3. REMOVE helm.md: "" Reason: Source gotcha removed in cluster-bootstrap commit abc1234 ``` Wait for the user to approve, modify, or reject proposals. The user may say "all", give specific numbers, or ask for changes. ### Step 5: Apply approved changes For each approved proposal, apply changes to `/`: - **ADD**: Append the new entry to the target file in `/`, matching the existing style (heading level, bullet format, explanation depth) - **UPDATE**: Edit the existing entry in place in `/` - **REMOVE**: Delete the entry from the file in `/` If a new best-practices topic file is needed: - Create it in `/` following the format of existing files (top-level heading, subheadings per entry, 2-6 lines per entry) - Add it to `/BESTPRACTICES.md` with a one-line description **Sync to local copy for backward compatibility**: After applying all changes to `/`, copy the modified files to `~/dev/claude/projects/claude-foundations/best-practices/` using `cp`: - `cp /BESTPRACTICES.md ~/dev/claude/projects/claude-foundations/BESTPRACTICES.md` - For each modified topic file: `cp /.md ~/dev/claude/projects/claude-foundations/best-practices/.md` ### Step 6: Commit and push to skynet/best-practices Stage and commit the changes in the cloned repo, then push: ``` git -C add -A git -C commit -m "distill: apply best practice updates from project memory Applied: additions, updates, removals Sources: " git -C push ``` Report the outcome (commit SHA, push success/failure). ### Step 7: Update distill state Write `~/dev/claude/projects/claude-foundations/best-practices/.distill-state.json`: ```json { "version": 1, "last_run": "", "projects": { "": { "path": "", "last_sha": "", "last_run": "" } } } ``` Preserve entries for projects that weren't processed this run (no changes). ### Step 8: Clean up temp directory Remove the temp directory used for the clone: ``` rm -rf "$tmpdir" ``` ### Step 9: Summary Print: - Projects scanned and number of changed memory files per project - Number of proposals (add/update/remove) - Number approved and applied - Any new best-practices files created - Commit SHA pushed to skynet/best-practices ## Quality checks - Best practices must be **project-agnostic** — no hardcoded IPs, namespaces, or service names - Each entry should include the **principle and reasoning**, not just the rule - Entries must be **deduplicated** against existing best-practices content - The **BESTPRACTICES.md** must stay accurate after any file additions - Proposals are **always presented before applying** — never auto-apply - Changes go to **skynet/best-practices** (primary) and are synced to **claude-foundations/best-practices/** (backward compat)