Files
custom-claude-skills/skills/distill-best-practices/SKILL.md

197 lines
8.2 KiB
Markdown

---
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:
- `<tmpdir>/BESTPRACTICES.md` — Current best-practices index (from cloned repo)
- Use Glob to list `<tmpdir>/*.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 `<bp-repo>`.
Read `<bp-repo>/BESTPRACTICES.md` and list `<bp-repo>/*.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)**: `<bp-repo>/` (cloned skynet/best-practices)
- **Best practices local copy (backward compat)**: `~/dev/claude/projects/claude-foundations/best-practices/`
- **Best practices index**: `<bp-repo>/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/<projects_dir>/<project_name>`.
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 <path> 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 <path> diff --name-only <last_sha>..HEAD -- memory/`
5. If `last_sha` is missing (first run) → list all memory files: `ls <path>/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 `<bp-repo>/` 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: "<brief description of the new entry>"
Source: cluster-bootstrap/memory/gotchas-k8s.md
2. UPDATE validation.md: "<what changes and why>"
Source: cluster-bootstrap/memory/process-lessons.md
3. REMOVE helm.md: "<entry to remove and why it's stale>"
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 `<bp-repo>/`:
- **ADD**: Append the new entry to the target file in `<bp-repo>/`, matching the existing style (heading level, bullet format, explanation depth)
- **UPDATE**: Edit the existing entry in place in `<bp-repo>/`
- **REMOVE**: Delete the entry from the file in `<bp-repo>/`
If a new best-practices topic file is needed:
- Create it in `<bp-repo>/` following the format of existing files (top-level heading, subheadings per entry, 2-6 lines per entry)
- Add it to `<bp-repo>/BESTPRACTICES.md` with a one-line description
**Sync to local copy for backward compatibility**: After applying all changes to `<bp-repo>/`, copy the modified files to `~/dev/claude/projects/claude-foundations/best-practices/` using `cp`:
- `cp <bp-repo>/BESTPRACTICES.md ~/dev/claude/projects/claude-foundations/BESTPRACTICES.md`
- For each modified topic file: `cp <bp-repo>/<file>.md ~/dev/claude/projects/claude-foundations/best-practices/<file>.md`
### Step 6: Commit and push to skynet/best-practices
Stage and commit the changes in the cloned repo, then push:
```
git -C <bp-repo> add -A
git -C <bp-repo> commit -m "distill: apply best practice updates from project memory
Applied: <count> additions, <count> updates, <count> removals
Sources: <comma-separated list of source projects>"
git -C <bp-repo> 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": "<ISO-8601 timestamp>",
"projects": {
"<project_name>": {
"path": "<absolute_path>",
"last_sha": "<current HEAD sha>",
"last_run": "<ISO-8601 timestamp>"
}
}
}
```
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)