git:20260401.f2ab67a to git:20260722.dc230a3

108 added, 31 removed. Audit A to A.

---
name: phx:learn-from-fix
- description: Capture lessons after fixing a bug or receiving a correction — ecto, liveview, oban, iron law mistakes. Use when the user corrects your approach or teaches a pattern.
+ description: Capture Elixir/Ecto/LiveView lessons and Hex API rules. Use after corrections or when asked to document learning, record a lesson, prevent a fixed mistake, or remember package guidance with --library.
effort: low
- argument-hint: <description of what was fixed>
+ argument-hint: "[--library <hex-package> --scope personal|project] <lesson>"
---
# Learn From Fix
After fixing a bug or receiving a correction, capture the lesson
to prevent future mistakes.
## Usage
```
/phx:learn-from-fix Fixed N+1 query in user listing - was missing preload
/phx:learn-from-fix String vs atom key mismatch in params handling
/phx:learn-from-fix LiveView assign_async needs render_async in tests
+ /phx:learn-from-fix --library ical --scope personal ICal.to_ics output needs CRLF line endings
+ /phx:learn-from-fix --library ical --scope project Use method: "PUBLISH" for calendar feeds
```
## Workflow
- ### Step 1: Identify the Pattern
+ ### Step 1: Verify the Lesson
- Look at recent conversation context. Ask yourself:
+ Persist only one of:
- - What was the root cause? (not the symptom)
- - Is this a common mistake others might make?
- - Can it be prevented with a simple rule?
+ - A completed fix verified by tests, reproduction, or user confirmation
+ - An explicit rule the user taught or asked to save
- ### Step 2: Check Existing Knowledge
+ Stop without writing if neither condition is met.
+ Do not save a hypothesis, unverified workaround, investigation narrative, or
+ unsolved error. Use `/phx:compound` for a detailed completed investigation.
+ Capture the root cause as a concise actionable rule, not the symptom.
+ ### Step 2: Select the Route
+
+ When both `--library <package>` and `--scope personal|project` are present,
+ use the [Library Route](#library-route). Require both flags; do not guess scope.
+ For the skill directory only, trim surrounding whitespace and lowercase the
+ package name. Preserve underscores when forming directory names
+ (`phoenix_live_view` becomes `hex-phoenix_live_view`).
+ Validate the normalized name against `^[a-z][a-z0-9_]+$`. If it does not match,
+ ask for a valid Hex package identifier instead of replacing characters or
+ inventing a name. Use the trimmed original identifier, not the normalized
+ directory name, to look up `mix.lock`.
+
+ Without `--library`, use the [General Correction Route](#general-correction-route).
+
+ ### Step 3: Check Existing Knowledge
+
Check if already documented:
- - Grep project CLAUDE.md for the pattern keyword
+ - Grep project CLAUDE.md and `~/.claude/CLAUDE.md` for the pattern keyword
- Check auto-memory files for similar lessons
+ - For library lessons, inspect both
+ `~/.claude/skills/hex-<package>/SKILL.md` and
+ `.claude/skills/hex-<package>/SKILL.md`
- Read `${CLAUDE_SKILL_DIR}/references/common-mistakes.md` (READ-ONLY plugin
reference — do NOT edit this file)
- If already documented, tell the user and stop.
+ Do not duplicate the same lesson across CLAUDE.md, memory, and a package skill.
+ If the same rule exists, merge wording or report it as already captured.
- ### Step 3: Decide Where to Save
+ ## Library Route
**CRITICAL: NEVER edit plugin files.** Files under
`~/.claude/plugins/` are cached and get overwritten on updates.
- Always write to project or memory locations.
+ Package skills are user-owned files, never plugin cache files.
- | Scope | Write to | Example |
- |-------|----------|---------|
- | This project only | Project CLAUDE.md | "Never use raw SQL in this app" |
- | All Elixir projects | Auto-memory MEMORY.md | "jsonb always uses string keys" |
- | Detailed fix with context | `.claude/solutions/` via `/phx:compound` | Complex debugging story |
+ ### Resolve Scope and Precedence
- ### Step 4: Write the Lesson
+ | `--scope` | Canonical destination |
+ |-----------|-----------------------|
+ | `personal` | `~/.claude/skills/hex-<package>/SKILL.md` |
+ | `project` | `.claude/skills/hex-<package>/SKILL.md` |
- **For project CLAUDE.md** — append a concise rule:
+ Personal skills override same-named project skills. If a personal
+ `hex-<package>` skill exists, never unknowingly create or update a shadowed
+ project skill: explain the conflict and ask whether to update personal scope or
+ keep distinct project-only knowledge. If project scope already exists before a
+ personal write, warn that the new skill will shadow it and offer to merge or
+ move it. Maintain one canonical skill per package unless the user explicitly
+ needs distinct scope-specific rules; never create one skill per lesson.
+ ### Read the Locked Version
+
+ Inspect `mix.lock` for the package. Record the exact locked version when found.
+ If it is absent, say the lesson is not tied to a locally locked version and do
+ not invent one. Qualify version-sensitive rules. When two verified rules
+ conflict across versions, preserve both with explicit version ranges instead of
+ replacing either.
+
+ ### Create or Safely Update the Skill
+
+ For a new package skill, create:
+
```markdown
- ### [Category] Iron Laws (continued)
+ ---
+ name: hex-<package>
+ description: <Package/module/API/task trigger terms for this knowledge>
+ user-invocable: false
+ ---
- N. **[SHORT RULE NAME]** — Do NOT [bad pattern]. Instead [good pattern]
+ # <Package> Knowledge
+
+ ## Verified Rules
+
+ - **<Rule>** (verified with <package> <version>): <actionable guidance>
```
- **For auto-memory** — append to
+ Make the description precise: include the Hex package, Elixir module names,
+ important APIs/file formats, and tasks that should trigger this knowledge.
+ Activation is model-selected from this description; package presence in
+ `mix.lock` does not guarantee activation.
+
+ Before updating an existing skill, read all of it. Preserve unrelated and
+ hand-authored sections. Merge semantically identical rules. If safe merging is
+ unclear, show the conflict and ask instead of overwriting content.
+
+ Do not add `paths:` to a personal package skill by default: it is a file-path
+ activation gate, not a dependency predicate. Add `paths:` only to project scope
+ when explicitly appropriate and meaningful package-specific paths exist.
+
+ ## General Correction Route
+
+ Choose the narrowest non-library destination:
+
+ | Scope | Write to | Example |
+ |-------|----------|---------|
+ | This project | Project CLAUDE.md | "Never use raw SQL in this app" |
+ | This project across sessions | Project-keyed auto-memory | "jsonb uses string keys" |
+ | All your projects | `~/.claude/CLAUDE.md` personal instructions | "Prefer explicit error tuples" |
+ | Detailed completed fix | `.claude/solutions/` via `/phx:compound` | Debugging narrative |
+
+ For project or personal instructions, preserve existing content and append
+ `**RULE NAME** — Do NOT [bad]. Instead [good]` under the relevant category. Use
+ personal instructions only for rules that should load in every project. For
+ auto-memory, append to the project-keyed
`~/.claude/projects/{project-hash}/memory/MEMORY.md`:
```markdown
### Lesson: [Title]
- **Pattern**: Do NOT [bad] — instead [good]
- **Why**: [root cause explanation]
```
- ### Step 5: Consider Broader Updates
-
- If the lesson is significant enough to be an Iron Law:
-
- - Suggest adding to project CLAUDE.md Iron Laws section
- - If it's universal (applies to all Elixir projects), suggest
- updating the plugin itself (the user can PR it)
+ If the lesson is universal to the plugin rather than one project or package,
+ suggest a plugin contribution; never write it into cached plugin files.
## Output
After capturing, confirm:
```text
Lesson captured in [location]
Pattern: Do NOT [bad pattern] — instead [good pattern]
Category: [Ecto/LiveView/OTP/Testing/etc]
+ Version: [locked package version, not found, or not applicable]
```
+ For package skills, also state that description-based activation is
+ model-selected, not guaranteed by `mix.lock`.
+
## Iron Laws
- 1. **NEVER edit plugin files** — files under `~/.claude/plugins/` are cached and overwritten on updates
+ 1. **NEVER write generated knowledge to plugin cache** — use only the user-owned destinations above
2. **DO NOT duplicate existing lessons** — always check CLAUDE.md and memory before writing
- 3. **Capture the root cause, not the symptom** — "missing preload" not "query was slow"
+ 3. **NEVER overwrite hand-authored content** — read both package skill scopes and merge safely
+ 4. **ONLY persist verified knowledge** — completed fixes or explicit user-taught rules, never hypotheses
+ 5. **DISCLOSE scope precedence** — a global package skill shadows its project counterpart
## References (READ-ONLY — do NOT edit)
- `${CLAUDE_SKILL_DIR}/references/common-mistakes.md` — Common Elixir mistakes
reference. Consult when checking for duplicates. Ships with
the plugin — NEVER modify.