diff --git a/CLAUDE.md b/CLAUDE.md index 704ae6b..694974b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,9 +15,9 @@ Scan the directories at runtime so the list is always current. Include a brief description if the project has a CLAUDE.md or README.md you can glean one from. 2. Based on the user's choice: - - **Existing project**: `cd` into the directory, read all `.md` files, and read `~/dev/claude/secrets/` (read-only reference — review every file to refresh context). Ask clarifying questions if anything is unclear or incomplete, and note context in MEMORY.md. + - **Existing project**: `cd` into the directory, read all `.md` files, and read `~/dev/claude/secrets/` (read-only reference — review every file to refresh context). Then read the [Best Practices Index](best-practices/INDEX.md) and load any topic files relevant to the selected project's technology stack. Ask clarifying questions if anything is unclear or incomplete, and note context in MEMORY.md. - **No project right now**: Do nothing further — just respond normally. - - **New project!**: Follow the "New Projects" section below. Also read `~/dev/claude/secrets/` as above. + - **New project!**: Follow the "New Projects" section below. Also read `~/dev/claude/secrets/` as above. Read the [Best Practices Index](best-practices/INDEX.md) and load topic files relevant to the new project's technology stack. ## Secrets (`~/dev/claude/secrets/`) @@ -110,6 +110,27 @@ Human-readable project documentation: - Milestone table with status - Scripts section listing every script with purpose and usage +## Knowledge Distillation Pipeline + +Three skills form a continuous learning pipeline across projects: + +1. **`/log`** — Run at end of session. Captures decisions, gotchas, open questions to `memory/log/YYYY-MM-DD..md` in the current project. Also prunes old reflected logs. +2. **`/reflect-logs`** — Run periodically. Processes unprocessed session logs into topic memory files (`memory/gotchas-*.md`, `memory/process-lessons.md`, etc.). Flags stale entries. Tracks state in `.reflection-state.json`. +3. **`/distill-best-practices`** — Run from any project. Reads changed memory files across all tracked projects and proposes updates to `claude-foundations/best-practices/`. Tracks state in `best-practices/.distill-state.json`. + +### State Files +- **`.reflection-state.json`** — Per-project, tracks which logs have been reflected on (md5 hashes of log file content) +- **`best-practices/.distill-state.json`** — In claude-foundations, tracks git SHAs per project at time of last distillation +- **`settings.yaml`** — In claude-foundations, configures log retention (default 7 days), max logs per reflection run, and tracked project list + +### Log Format +Session logs use structured markdown with parseable section headers: Summary, Decisions, Gotchas Discovered (tagged with `[topic]` for routing), Open Questions, Key Context, Process Notes. Empty sections are omitted. + +### Pruning +- Reflected logs older than `log.retention_days` (default: 7) are automatically deleted by `/log` +- Unreflected logs older than `log.warn_unreflected_days` (default: 14) trigger a warning instead of deletion +- `/reflect-logs` flags stale memory entries (version-specific bugs that have been fixed, manual processes that have been automated) + ## Milestones Break projects into numbered milestones (M1, M2, ...). Every milestone completion MUST include: diff --git a/best-practices/INDEX.md b/best-practices/INDEX.md new file mode 100644 index 0000000..0a16b2b --- /dev/null +++ b/best-practices/INDEX.md @@ -0,0 +1,17 @@ +# Best Practices Index + +Generalised best practices extracted from real project work. Each topic file is self-contained — read only the files relevant to the current project. + +## Topics + +- [Validation & Deployment](validation.md) — Validate locally, deploy once; full-chain testing; pre-flight checks +- [Secrets Management](secrets-management.md) — SOPS + age, credential handling, file naming, encryption gotchas +- [Git & Source Control](git-source-control.md) — Commit practices, GitOps workflows, remote conventions +- [Kubernetes Patterns](kubernetes.md) — Volume mounts, deployment strategies, naming, bootstrap ordering +- [Helm Charts](helm.md) — Schema validation, version verification, values structure +- [Ansible](ansible.md) — Inventory, templates, idempotency, credential safety +- [Scripting](scripting.md) — Shell conventions, verification scripts, idempotency, colour output +- [Documentation Standards](documentation.md) — CLAUDE.md, MEMORY.md, FUTURE.md, README.md structure and tiered memory +- [Milestones & Reflections](milestones.md) — Milestone workflow, verification, reflection process +- [Debugging Methodology](debugging.md) — Systematic diagnosis, full-chain testing, common pitfalls +- [Claude Code Skills](skills-development.md) — Skill authoring, context injection, tool restrictions diff --git a/best-practices/ansible.md b/best-practices/ansible.md new file mode 100644 index 0000000..abf4cc9 --- /dev/null +++ b/best-practices/ansible.md @@ -0,0 +1,36 @@ +# Ansible + +## Inventory and Execution + +- Always pass `-i inventory.yml` explicitly or run from the directory containing `ansible.cfg` +- Playbooks that can't find inventory skip silently with no error — a common source of "it ran but nothing happened" confusion +- Variables that need customisation go in `inventory.yml` files, not scattered across role defaults + +## Role Structure + +- Roles follow standard structure: `tasks/main.yml`, `templates/*.j2`, `handlers/main.yml` +- Jinja2 templates have `.j2` extension and include a "managed by Ansible" header comment + +## Template Safety + +- **Never use placeholder values with `-e` for vars that template config files.** Using `-e "var=dummy"` will overwrite live configs with garbage. Either read real values, use `--skip-tags` to skip templating tasks, or restructure roles so sensitive templates are in a separate tag. + +## Credential Safety + +- Pass secrets via `@file` not `-e` on the command line — `-e "key=value"` exposes secrets in `ps` output +- Use temp files with `trap rm` cleanup: `-e "@${tmpfile}"` + +## Module Gotchas + +- `docker_compose_v2` doesn't support `state: restarted` — use `recreate: always` instead +- `ansible.builtin.unarchive` with `remote_src` and `extra_opts: --strip-components` is unreliable — use `get_url` + `command: tar` separately +- `get_url` won't re-download when the URL changes but the destination filename stays the same — use a version marker file to detect changes + +## Service Restarts + +- Some services (dnsmasq, etc.) need container restarts for config changes to take effect +- Ansible handlers handle this, but always verify the change took effect (e.g., `dig @ +short`) + +## Docker Compose + +- `network_mode: host` ignores `ports:` mappings — remove `ports:` to avoid warnings diff --git a/best-practices/debugging.md b/best-practices/debugging.md new file mode 100644 index 0000000..62dfdc5 --- /dev/null +++ b/best-practices/debugging.md @@ -0,0 +1,41 @@ +# Debugging Methodology + +## Check Before You Act + +- Before writing firewall/network rules, check actual routing (`ip route get `) +- Before running config management with variables, ensure values are real, not placeholders +- Before assuming a container has a shell, `docker inspect` it +- Before creating API tokens, research all required scopes upfront — iterating one scope at a time costs a push-debug cycle each + +## Routing and Networking + +- Always run `ip route get ` on the forwarding host first +- macvlan, Docker bridge, and other virtual interfaces mean the "obvious" physical interface is often wrong +- Test from both in-cluster and external perspectives + +## Full-Chain Testing + +After wiring up any new service: +1. Test direct to backend (bypass all proxies) +2. Test through reverse proxy (bypass DNS) +3. Test end-to-end as a user would + +Use `curl --resolve` to test specific paths without depending on DNS propagation. + +## When Something Doesn't Sync/Apply + +- Check resource exclusions in the GitOps controller immediately +- Check if the resource type requires special permissions or labels +- Check if ServerSideApply conflicts are preventing field changes +- Don't try workarounds before understanding the root cause + +## OIDC Integration Checklist + +Before starting any OIDC integration, research: +1. What format is the `sub` claim (UUID? username?) +2. Which claims are in the ID token vs userinfo endpoint +3. How the consumer matches RBAC identities (groups? email? username?) + +## Grep Your Own Docs + +Known issues documented in CLAUDE.md or MEMORY.md but not applied to new scripts/configs waste debugging time. Search your own documentation before writing automation that touches areas with known gotchas. diff --git a/best-practices/documentation.md b/best-practices/documentation.md new file mode 100644 index 0000000..0af473f --- /dev/null +++ b/best-practices/documentation.md @@ -0,0 +1,50 @@ +# Documentation Standards + +Every project maintains four core markdown files. + +## CLAUDE.md + +The primary reference for Claude sessions. Should contain: +- Project overview and architecture +- Repository structure (keep updated as the project evolves) +- Key design decisions with rationale +- Conventions and coding standards +- Environment details (IPs, URLs, credential references — never actual values) +- Common operations / how-to recipes +- Put critical rules at the top — Claude reads sequentially and earlier content has more influence + +## MEMORY.md (Tiered Memory System) + +Long-running projects accumulate significant context. Use a **tiered memory** structure: + +**MEMORY.md** is a **thin index only** — one-line descriptions with links to topic files in `memory/`. No content lives in MEMORY.md itself. Keep it under ~50 lines. + +**memory/** contains the actual content, split by topic: +- `memory/project-status.md` — Current milestone, what's next, blockers +- `memory/gotchas-.md` — Gotchas grouped by technology +- `memory/process-lessons.md` — How-to-work-with-this-repo lessons +- `memory/m-reflection.md` — One file per milestone reflection +- `memory/decisions.md` — Architecture and design decisions + +**Principles:** +- Split by topic, not by time +- Index descriptions matter — they're used to decide what to read +- Prune aggressively — stale memory is worse than no memory +- Each file should be self-contained and greppable +- Deduplicate with CLAUDE.md — stable conventions go in CLAUDE.md, learnings and gotchas go in memory + +## FUTURE.md + +Backlog of improvement ideas, each with: +- **Problem:** What's painful or manual today +- **Idea:** What the improvement looks like +- **Open questions:** Unknowns to research before starting +- **Depends on:** Other items or milestones that should come first + +## README.md + +Human-readable project documentation: +- Architecture summary +- Quick start / setup instructions +- Milestone table with status +- Scripts section listing every script with purpose and usage diff --git a/best-practices/git-source-control.md b/best-practices/git-source-control.md new file mode 100644 index 0000000..853ef58 --- /dev/null +++ b/best-practices/git-source-control.md @@ -0,0 +1,34 @@ +# Git & Source Control + +## Commit Practices + +- Use meaningful commit messages; prefer small, focused commits over large batches +- Never commit secrets in plaintext — use SOPS + age or equivalent encryption +- Enable pre-commit hooks where appropriate (secret detection, linting, formatting) + +## Pre-Commit Hooks + +- Block `local_secrets/` and similar directories from being committed +- Auto-encrypt files matching `.sops.yaml` rules that aren't yet encrypted +- Enable with `git config core.hooksPath .githooks` +- Consider secret detection, linting, and formatting hooks + +## GitOps Workflow + +- All infrastructure changes should be tracked in Git +- No manual changes without corresponding GitOps manifests — anything applied manually (e.g., `kubectl apply`, `helm install`) should immediately get a corresponding tracked manifest +- For ArgoCD-managed clusters: edit in Git, push, sync — never edit live resources directly + +## Remote Conventions + +- SSH workflows preferred over HTTPS for Git remotes +- Use SSH config host aliases for multi-user setups (e.g., `gitea.example.com-`) +- Remote URL format: `git@:/.git` +- Optionally push-mirror to GitHub for public visibility + +## Version Management + +- Use the latest stable version of dependencies unless pinned for a reason +- Verify versions from live sources (`helm search repo`, upstream docs, package registries) — don't rely on memory +- Document the reason in a comment if a version is intentionally pinned below latest +- Check compatibility matrices before upgrading (e.g., Talos ↔ Kubernetes, framework ↔ runtime) diff --git a/best-practices/helm.md b/best-practices/helm.md new file mode 100644 index 0000000..66481ab --- /dev/null +++ b/best-practices/helm.md @@ -0,0 +1,25 @@ +# Helm Charts + +## Schema Validation + +- **Always validate values against the chart schema before committing.** Run `helm show values / --version ` to check the actual structure. +- Helm chart schemas change between versions — field names and nesting can differ from documentation or online examples. +- A quick `helm template` test locally catches schema errors before deployment. +- `additionalProperties: false` in chart schemas means any extra keys at the wrong nesting level cause a hard failure. + +## Version Verification + +- Run `helm search repo` or check upstream docs to confirm latest stable versions +- Don't rely on memory for chart versions — they go stale quickly +- Check compatibility matrices between chart version, app version, and other cluster components + +## Multi-Source Applications + +- ArgoCD multi-source Applications use `$ref` syntax to combine external Helm charts with Git-stored values files +- Keep values files in Git alongside the ArgoCD Application manifest + +## Timeout Handling + +- Under cluster pressure (many events, etcd busy), default Helm timeouts may not be enough +- Increase timeout for initial installs (e.g., 10m instead of 5m) +- `helm upgrade --install` is idempotent — retries are safe diff --git a/best-practices/kubernetes.md b/best-practices/kubernetes.md new file mode 100644 index 0000000..78061ca --- /dev/null +++ b/best-practices/kubernetes.md @@ -0,0 +1,36 @@ +# Kubernetes Patterns + +## Volume Mounts + +- **Avoid `subPath` volume mounts** for Secrets and ConfigMaps. The kubelet does not auto-update `subPath` mounts when the source changes — the pod must be restarted. Use directory mounts instead and adjust the application's config path. +- **Secret volume propagation is async.** After updating a Secret, the kubelet takes seconds to sync mounted volumes. A `rollout restart` issued immediately after may start pods with stale data. Add a short delay (5s) before restarting. + +## Deployment Strategies + +- **RWO PVC + RollingUpdate = Deadlock.** New pod can't attach the volume while the old pod holds it. Use `strategy: Recreate` for single-replica deployments with RWO PVCs. +- **SSA + strategy change conflict.** Switching from RollingUpdate to Recreate via ServerSideApply fails because SSA won't remove the old `rollingUpdate` field. Must patch the live resource first. + +## Naming + +- `metadata.name` must be DNS-1035 compliant — no dots allowed. Replace dots with dashes (e.g., `oreillyit-nz` not `oreillyit.nz`). Label values CAN contain dots. + +## Bootstrap Ordering + +Some components have chicken-and-egg dependencies: +1. CNI (e.g., Cilium) must be installed before anything else — nodes are NotReady without it +2. GitOps controller (e.g., ArgoCD) installed second +3. Root app applied last — the GitOps controller then "adopts" CLI-installed releases + +Manual bootstrap secrets (encryption keys, OIDC client secrets) must be documented as explicit steps. + +## Network Policies + +- DNS egress for `toFQDNs` rules must use `toEndpoints` targeting kube-dns pods with `rules.dns` — this triggers the DNS proxy. Using `toCIDRSet` for DNS bypasses the proxy and FQDN rules never populate. +- Cross-namespace policies need explicit namespace matching (e.g., `matchExpressions` on namespace label). +- Always test from the actual consumer namespace, not same-namespace test pods. + +## Miscellaneous + +- `enableServiceLinks: false` may be needed when K8s-injected service env vars conflict with app config (e.g., Authelia interprets `AUTHELIA_*` service vars as configuration). +- Proxmox VM names must match K8s node hostnames for cloud controller manager integration. +- Metrics-server on Talos needs `--kubelet-insecure-tls` (self-signed kubelet certs). diff --git a/best-practices/milestones.md b/best-practices/milestones.md new file mode 100644 index 0000000..6cde2a3 --- /dev/null +++ b/best-practices/milestones.md @@ -0,0 +1,42 @@ +# Milestones & Reflections + +## Milestone Structure + +Break projects into numbered milestones (M1, M2, ...). This provides clear checkpoints, measurable progress, and natural reflection points. + +## Milestone Completion Checklist + +Every milestone MUST include: + +### 1. Verification Script + +`scripts/verify-m.sh` — automated checks confirming all milestone outcomes. +- Idempotent, non-destructive, returns non-zero on failure +- Colour output (green/red) for pass/fail +- Environment-resilient (no sudo, test from accessible side) +- Check for default/insecure credentials + +### 2. Milestone Reflection + +Write `memory/m-reflection.md` by reviewing the **entire conversation** from milestone start. Cover: + +- **Process improvements:** What slowed us down? Wrong assumptions? Where did we go in circles? What would make this faster if redone from scratch? +- **Key knowledge for reproduction:** Critical facts, gotchas, non-obvious config details, version-specific quirks, debugging detours +- **Scripts and automation:** Existing tools that proved valuable, new scripts to build, patterns to extract into reusable automation +- **Future improvements:** Ideas that surfaced but don't belong in current scope — add to FUTURE.md + +### 3. Updated README.md + +Ensure the scripts section, milestone table, and setup steps are current. + +### 4. Updated CLAUDE.md + +Reflect new repo structure, conventions, and patterns discovered during the milestone. + +## Reflection Quality + +Good reflections capture: +- Commit stats (total commits, fix percentage) to measure validation discipline +- Longest detour and root cause +- Most avoidable waste and what would have prevented it +- Concrete checklist items for future similar work diff --git a/best-practices/scripting.md b/best-practices/scripting.md new file mode 100644 index 0000000..6f86f56 --- /dev/null +++ b/best-practices/scripting.md @@ -0,0 +1,29 @@ +# Scripting Conventions + +## Structure + +- All scripts live in `scripts/` and run from the repository root +- Scripts should be idempotent and safe to re-run +- Exit non-zero on failure so `&&` chains work naturally + +## Verification Scripts + +- Automated checks confirming milestone or feature outcomes +- Use colour output (green/red) for pass/fail indicators +- Should be non-destructive and environment-resilient +- Avoid needing sudo — test from the accessible side of a connection instead +- Check for default/insecure credentials and print remediation instructions on failure +- Use `curl --resolve` to bypass DNS/proxy layers when testing direct connectivity + +## Automation Triggers + +If you run the same 3+ commands in sequence more than once, it should become a script. Look for: +- Repeated command sequences in conversation history +- Steps requiring careful ordering +- Multi-step manual processes that are error-prone + +## Shell Gotchas + +- `((PASS++))` fails under `set -e` when PASS=0 — the expression evaluates to 0 (false), triggering errexit. Use `PASS=$((PASS + 1))` instead. +- Always quote variables in conditionals and file paths +- Use `trap` for cleanup of temp files and credentials diff --git a/best-practices/secrets-management.md b/best-practices/secrets-management.md new file mode 100644 index 0000000..7252965 --- /dev/null +++ b/best-practices/secrets-management.md @@ -0,0 +1,41 @@ +# Secrets Management + +## SOPS + age + +SOPS with age encryption is the standard across all projects. A single `.sops.yaml` at the repo root defines path-based encryption rules. + +### File Naming + +- `.sops.yaml` path-based rules match specific filename patterns (e.g., `**/*secret*.yaml`) +- Non-secret files must NOT contain `secret` in their name, or the pre-commit hook will encrypt them +- KSOPS generator files should be named `ksops-generator.yaml`, not `secret-generator.yaml` + +### encrypted_regex Gotcha + +When using `encrypted_regex` for selective field encryption (e.g., Ansible group_vars), variable names must contain a keyword that matches the regex (e.g., `password|private_key|api_key|secret|token`). Arbitrary key names are silently left unencrypted. + +### SOPS Vars Plugin + +Each Ansible project needs `vars_plugins_enabled = host_group_vars,community.sops.sops` in `ansible.cfg`. Files in `group_vars/` must be named after a group (e.g., `all.sops.yaml`), not arbitrary names. + +### Interactive Editor Pitfalls + +- `sops ` opens an interactive editor — fails in non-interactive sessions +- `sops -e /tmp/file` fails when the temp path doesn't match `.sops.yaml` rules +- Multiple `sops --set` calls can corrupt files — use the interactive editor for multi-field edits + +## Credential Handling + +- **Never pass secrets via command-line arguments** — visible in `ps` output +- Use `@file` references, environment variables sourced at runtime, or stdin +- For Ansible, use temp files with `trap rm` cleanup: `-e "@${tmpfile}"` +- Read secrets at execution time and use them ephemerally — never cache or persist values +- Reference the **existence** of a secret file in docs, never its contents + +## Bootstrap Secrets + +Some secrets are chicken-and-egg (e.g., the age decryption key for ArgoCD's KSOPS). These must be created manually as a bootstrap step and documented clearly. + +## Backup Considerations + +Backup plans must include encryption keys (age private keys, etc.) so that encrypted data in Git repos remains recoverable. diff --git a/best-practices/skills-development.md b/best-practices/skills-development.md new file mode 100644 index 0000000..f3255fd --- /dev/null +++ b/best-practices/skills-development.md @@ -0,0 +1,24 @@ +# Claude Code Skills + +## Skill Structure + +- Each skill lives in `skills//SKILL.md` +- Skills should be project-agnostic where possible — use dynamic context injection to adapt +- After adding a new skill, run the install script to register it +- Skills only useful for one project should live in that project's `.claude/skills/` instead + +## Authoring Guidelines + +- **Inline by default** — only use `context: fork` if the skill genuinely doesn't need conversation history +- **Pre-fetch context** with `!`command`` injection to reduce tool calls during execution +- **Restrict tools** with `allowed-tools` to the minimum needed — reduces permission prompts +- **Use $ARGUMENTS** for user input, `$0`, `$1` etc. for positional args +- Dynamic commands in `!`command`` run at skill load time, not during Claude's execution + +## `!`command`` Gotchas + +- **No `$()` command substitution** — the permission checker rejects commands containing `$()` +- **No complex shell pipelines relying on subshells** — keep commands simple and self-contained +- **`allowed-tools` patterns must match the command binary** — each binary used in `!`command`` blocks needs its own pattern +- **Prefer specific tool patterns over broad ones** — `Bash(git log *)` is safer than `Bash(git *)` +- **Fallback to tool instructions for dynamic paths** — if a command needs `$ARGUMENTS` to compute a path, use a plain-text instruction telling Claude to use the Read tool instead diff --git a/best-practices/validation.md b/best-practices/validation.md new file mode 100644 index 0000000..c133a9b --- /dev/null +++ b/best-practices/validation.md @@ -0,0 +1,35 @@ +# Validation & Deployment + +## Validate Locally, Deploy Once + +The single biggest time sink across projects is "deploy first, validate later." Real-world stats from a 9-milestone infrastructure project showed 50-60% of commits were fixes that could have been caught locally. + +**Always validate before pushing:** +- `helm template` for Helm chart values +- `kustomize build` (or `kubectl kustomize`) for Kustomize apps +- `kubectl apply --dry-run=server` for K8s naming/schema issues +- `docker run validate-configuration` for apps that support it (Authelia, Homepage, etc.) +- `docker inspect` for unfamiliar container images before writing init containers +- Lint/typecheck/test for application code + +**Batch fixes locally, push once.** Each push-sync-crash-fix cycle wastes minutes and clutters Git history. + +## Test the Full Chain Immediately + +After wiring up any new service or endpoint, test end-to-end from the user's perspective right away. Don't assume intermediate steps working means the whole chain works. + +- `curl --resolve domain:443: https://domain` to test bypassing DNS/proxy layers +- Test from the actual consumer (not same-namespace test pods for network policies) +- Test DNS resolution after deploying FQDN-based policies + +## Pre-Flight Checks + +Before starting a deploy or automation phase: +- Verify SSH keys are loaded (`ssh -T git@`) +- Confirm environment variables and credentials are available +- Check that the target environment is in the expected state +- Verify DNS records resolve as expected + +## Scripts That Change Config Must Self-Verify + +After updating and restarting a service, the script should test that the change actually took effect (e.g., curl an API endpoint, check a config value). A "success" message without verification hides failures. diff --git a/memory/log/2026-03-12.233744.md b/memory/log/2026-03-12.233744.md new file mode 100644 index 0000000..55da587 --- /dev/null +++ b/memory/log/2026-03-12.233744.md @@ -0,0 +1,25 @@ +# Session Log — 2026-03-12 + +## Summary +Created the claude-foundations repo on Gitea (skynet org), built a best-practices folder with 11 topic files extracted from cluster-bootstrap and custom-claude-skills, then designed and implemented a three-tier knowledge distillation pipeline (/log, /reflect-logs, /distill-best-practices). + +## Decisions +- Decision: Separate `/reflect-logs` from existing `/reflect` — Rationale: different purpose (continuous vs milestone), different cadence, avoids overcomplicating the existing skill +- Decision: Use MD5 hashes for reflection state, git SHAs for distill state — Rationale: log files may not be committed when reflected; distill explicitly works across committed repos +- Decision: Timestamp-based session IDs (HHMMSS) — Rationale: human-readable, naturally sorted, no external dependencies +- Decision: Pruning happens in `/log` not `/reflect-logs` — Rationale: runs most frequently, keeps log dir clean as side effect of the most common operation +- Decision: `/distill-best-practices` is interactive (proposals before changes) — Rationale: cross-project conventions need human judgment + +## Gotchas Discovered +- **[skills]** Symptom: install.sh failed with exit 1 on broken symlink — Fix: old reflect symlink pointed to pre-move path (`~/dev/claude/custom-claude-skills/` instead of `~/dev/claude/projects/custom-claude-skills/`). `readlink -f` on a broken symlink returns empty string, causing comparison failure under `set -e`. Fixed by removing stale symlink and re-running. +- **[skills]** Symptom: skills created mid-session not available as slash commands — Fix: skills are discovered at session start, not dynamically. New skills require a new session to become available. + +## Key Context +- Best practices files are in claude-foundations/best-practices/ with INDEX.md as the card catalog +- Settings for the pipeline live in claude-foundations/settings.yaml +- State files: `.reflection-state.json` (per-project), `best-practices/.distill-state.json` (in claude-foundations) +- SSH key for ai_enablement is password-protected — needs ssh-agent loaded before git push + +## Process Notes +- The plan mode workflow worked well for this — explored existing patterns, designed the architecture, got approval, then executed cleanly +- Creating all 11 best-practices files in parallel (single Write batch) was efficient diff --git a/settings.yaml b/settings.yaml new file mode 100644 index 0000000..9b37c93 --- /dev/null +++ b/settings.yaml @@ -0,0 +1,14 @@ +# Knowledge distillation pipeline settings + +log: + retention_days: 7 # Prune reflected logs older than this + warn_unreflected_days: 14 # Warn (don't delete) unreflected logs older than this + +reflect: + max_logs_per_run: 10 # Process at most N logs per invocation + +distill: + projects_dir: ~/dev/claude/projects + projects: # Projects to scan for memory changes + - cluster-bootstrap + - custom-claude-skills