From draft
Scans codebase to discover coding patterns and update guardrails.md with learned conventions and anti-patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/draft:learnThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scan the codebase to discover recurring coding patterns and update `draft/guardrails.md` with learned conventions and anti-patterns. This improves future quality command accuracy by reducing false positives and catching known-bad patterns.
Scan the codebase to discover recurring coding patterns and update draft/guardrails.md with learned conventions and anti-patterns. This improves future quality command accuracy by reducing false positives and catching known-bad patterns.
First resolve the bundled helpers:
# Locate Draft's bundled helpers (cwd is the user's project; ${CLAUDE_PLUGIN_ROOT}
# is not exported into skill Bash). See core/shared/tool-resolver.md.
DRAFT_TOOLS="$(cat ~/.cache/draft/plugin-root 2>/dev/null)/scripts/tools"
[ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/cache/*/draft/*/scripts/tools 2>/dev/null | sort -V | tail -1)"
[ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$(ls -d ~/.claude/plugins/marketplaces/*draft*/scripts/tools 2>/dev/null | tail -1)"
[ -d "$DRAFT_TOOLS" ] || DRAFT_TOOLS="$PWD/scripts/tools"
When draft/graph/schema.yaml exists, this skill must follow the graph-first lookup contract in core/shared/graph-query.md §Mandatory Lookup Contract. Use the graph to:
"$DRAFT_TOOLS/graph-callers.sh"/"$DRAFT_TOOLS/graph-impact.sh" and "$DRAFT_TOOLS/graph-arch.sh" --repo . (preferred over find)."$DRAFT_TOOLS/hotspot-rank.sh" --repo . — patterns in high-fanIn files are more impactful when learned.*-index.jsonl to identify class/function definitions rather than re-discovering them via regex.Filesystem find for source discovery (Step 2.1) is permitted as a complement to the graph for languages not covered by indexes (e.g. Ruby, Java without ctags). Record the rationale in the Graph Usage Report.
See shared red flags — applies to all code-touching skills.
Skill-specific:
tech-stack.md ## Accepted PatternsEvidence over assumptions. Quantity over anecdote.
promote — review high-confidence learned patterns and offer promotion to Hard Guardrails or Accepted Patternsmigrate — migrate ## Guardrails from workflow.md to guardrails.md (for existing projects)<path> — scan specific directory or file patternls draft/ 2>/dev/null
If draft/ does not exist: STOP — "No Draft context found. Run /draft:init first."
ls draft/guardrails.md 2>/dev/null
If it exists, read it and internalize:
Then verify core guardrails integrity (backfill if missing):
Check if draft/guardrails.md contains the C++/Systems Hard Guardrails from core/guardrails.md. Detection: look for the marker heading ### C++/Systems — Object Lifecycle & Memory Safety.
core/guardrails.md. Backfill by inserting the full C++/Systems Hard Guardrails sections from core/templates/guardrails.md (G1.x–G7.x, all pre-checked [x]) into the ## Hard Guardrails section, after any existing general guardrails. Preserve all existing entries. Announce: "Backfilled C++/Systems Hard Guardrails (G1.x–G7.x) from core/guardrails.md into draft/guardrails.md."If draft/guardrails.md does NOT exist:
draft/workflow.md for ## Guardrails sectiondraft/guardrails.md using template from core/templates/guardrails.mdworkflow.md ## Guardrails into the Hard Guardrails sectionworkflow.md where ## Guardrails was:
## Guardrails
> **Migrated** — Guardrails have moved to `draft/guardrails.md`. See that file for hard guardrails, learned conventions, and learned anti-patterns.
If migrate argument was given, stop here after migration. Otherwise, continue to pattern scanning.
Read and follow core/shared/draft-context-loading.md for full Draft context. Key files:
draft/.ai-context.md — Module boundaries, invariants, concurrency modeldraft/tech-stack.md — Frameworks, accepted patterns (do not learn patterns that duplicate these)draft/product.md — Product requirements# Find all source files (exclude vendored, generated, build artifacts)
find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \
-o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.java" \
-o -name "*.cpp" -o -name "*.cc" -o -name "*.h" -o -name "*.hpp" \
-o -name "*.rb" -o -name "*.php" -o -name "*.swift" -o -name "*.kt" \) \
-not -path "*/node_modules/*" -not -path "*/vendor/*" -not -path "*/.git/*" \
-not -path "*/dist/*" -not -path "*/build/*" -not -path "*/__pycache__/*" \
-not -path "*/draft/*" \
| head -500
If scope argument provided, filter to that path.
Scan the codebase across these dimensions, looking for recurring patterns (3+ occurrences):
Detect patterns that are being phased out by the team:
git blame to check the age of files containing it:
declining: true to the entry metadata:
- **Declining:** yes — found in 8 old files (avg age 18mo), 1 new file (avg age 2mo). Being replaced by [newer pattern].
try/catch with manual logging found in files last modified >1 year ago, newer files use structured error middleware — the old style is declining, not a convention to enforceReference: Google large-scale changes (Rosie) — systematic detection of patterns being migrated away from.
When in a monorepo (detected by draft/service-index.md existing OR multiple draft/ directories OR presence of packages/, services/, apps/ directories):
Result<T, E> for error handling, Service B uses exceptionsCross-service inconsistency: Error Handling
services/auth/ → uses custom Result type (5 files)
services/billing/ → uses thrown exceptions (8 files)
Suggestion: standardize on one approach
tech-stack.md or .ai-context.mdReference: Google monorepo practices — consistent patterns across services reduce cognitive overhead and enable large-scale tooling.
For each candidate pattern:
tech-stack.md ## Accepted Patterns — if already documented there, skip (no duplication)guardrails.md entries — if already learned, update evidence count and date.ai-context.md — if described as architecture, skip (it's documented)Mine git commit history for pattern signals that code scanning misses. Run only if the project is a git repository.
git log --oneline --no-merges -500
Scan the output for recurring message patterns (3+ occurrences of the same type):
| Commit pattern | Signal |
|---|---|
fix: don't X / fix: never X | Team keeps violating X → anti-pattern candidate |
refactor: replace X with Y | X is declining, Y is the replacement → mark X as declining: true |
chore: enforce X / chore: add X check | X is being formalized → convention candidate |
revert: followed by same topic 3+ times | That topic is consistently problematic → anti-pattern candidate |
Rules:
historically_recurring: true — do not add as active anti-pattern.Recency weighting — for each candidate pattern from Step 2.2, check when the files containing it were last modified:
git log --follow --oneline -1 -- {file_containing_pattern}
recently_active: true to the entrystale: true — lower enforcement priorityIf draft/graph/schema.yaml exists (engine live), derive objective severity for all anti-pattern candidates based on the fanIn of files where the pattern was found via "$DRAFT_TOOLS/hotspot-rank.sh" --repo ..
For each anti-pattern candidate from Step 2.2:
"$DRAFT_TOOLS/hotspot-rank.sh" --repo .graph_severity: critical (breakage propagates to many callers)graph_severity: highgraph_severity: mediumgraph_severity: lowgraph_severity: unresolvedCollect all evidence files with fanIn ≥ 5 for the high_fanin_files field.
When graph_severity differs from the subjectively assigned severity, use graph_severity as the enforcement priority in quality commands — it is objective and reproducible.
Follow the threshold from core/shared/pattern-learning.md:
| Evidence | Confidence | Action |
|---|---|---|
| Found 1-2x | — | Skip (insufficient data) |
| Found 3-5x, all consistent | medium | Learn as convention or anti-pattern |
| Found >5x, all consistent, cross-verified | high | Learn + flag as promotion candidate |
| Found >5x but inconsistent | — | Do NOT learn (investigate inconsistency) |
Consistency-claim ground-truth gate (Ground-Truth Discipline G1, G4): "Consistent" and "cross-verified" require you to have Read at least 3 of the instances in this session (5 if claiming high). A grep match count is not consistency proof — variant call sites can use the same identifier with different semantics. List the file:line of each Read instance in the learned-pattern record under §Evidence. A medium or high entry whose Evidence list shows only grep counts is a Red Flag and must be downgraded or discarded.
Before saving any new pattern, check for conflicts with existing entries:
If conflict found:
CONFLICT DETECTED:
Existing convention: "Use async/await for all async operations"
Evidence: 12 files, high confidence, learned 2025-01-15
New candidate: "Avoid async in database module — use callback style"
Evidence: 4 files in src/db/, medium confidence
These may both be valid (module-scoped exception) or one may be outdated.
Options:
[1] Keep both (new pattern is a scoped exception)
[2] Replace existing with new (pattern has evolved)
[3] Discard new (existing is correct)
Reference: Google Code Health — conflicting patterns create confusion and should be resolved explicitly.
After discovering patterns, optionally compare project conventions against community standards for the detected language:
| Language | Benchmarks |
|---|---|
| Go | Effective Go, Go Code Review Comments |
| Python | PEP 8, PEP 20, Google Python Style Guide |
| Java | Effective Java, Google Java Style Guide |
| TypeScript | typescript-eslint recommended rules |
| Rust | Rust API Guidelines, Clippy lints |
| C/C++ | Google C++ Style Guide, C++ Core Guidelines |
For each project convention that deviates from its language's community standard:
tech-stack.md ## Accepted Patterns with a rationalesnake_case for TypeScript functions (deviates from camelCase convention) — flag for documentation, not correctionReference: Google Abseil Tips of the Week, language-specific style guides — deviations from community standards increase onboarding friction and should be documented even when intentional.
Follow the write procedure in core/shared/pattern-learning.md:
draft/guardrails.mdlast_verifieddraft/metadata.json with current git state (use git-metadata.sh --project-metadata --generated-by "draft:learn" or update git.commit, git.commit_message, and synced_to_commit manually) — guardrails.md frontmatter carries only stable fields per WS-8Cap enforcement: Maintain a maximum of 50 learned entries per section. If at capacity, replace the oldest medium confidence entry that has not been re-verified in 90+ days (per core/shared/pattern-learning.md).
### [Pattern Name]
- **Category:** error-handling | naming | architecture | concurrency | state-management | data-flow | testing | configuration
- **Confidence:** high | medium
- **Evidence:** Found in N files — `path/file1.ext:line`, `path/file2.ext:line`, `path/file3.ext:line`
- **Discovered at:** YYYY-MM-DD (when Draft first observed this pattern)
- **Established at:** YYYY-MM-DD (when the pattern entered the codebase, via git blame)
- **Last verified:** YYYY-MM-DD
- **Last active:** YYYY-MM-DD (when source files containing this pattern were last modified)
- **Discovered by:** draft:learn on YYYY-MM-DD
- **Description:** [What the pattern is and why it's intentional]
### [Anti-Pattern Name]
- **Category:** security | reliability | performance | correctness | concurrency
- **Severity:** critical | high | medium
- **graph_severity:** critical | high | medium | low | unresolved (fanIn-derived from Step 2.7; "unresolved" if no graph data)
- **high_fanin_files:** `path/file.go` (fanIn:12), `path/other.go` (fanIn:7) (omit line if none meet fanIn ≥ 5)
- **Evidence:** Found in N files — `path/file1.ext:line`, `path/file2.ext:line`
- **Discovered at:** YYYY-MM-DD (when Draft first observed this pattern)
- **Established at:** YYYY-MM-DD (when the pattern entered the codebase, via git blame)
- **Last verified:** YYYY-MM-DD
- **Last active:** YYYY-MM-DD (when source files containing this pattern were last modified)
- **recently_active:** true | false (true if any evidence file modified within 90 days)
- **stale:** true | false (true if all evidence files unmodified for 12+ months)
- **Discovered by:** draft:learn on YYYY-MM-DD
- **Description:** [What the pattern is and why it's problematic]
- **Suggested fix:** [Brief description of the correct approach]
promote argument given)Review all learned patterns with confidence: high and present promotion candidates:
Pattern promotion candidates:
1. [Convention] "Centralized API client pattern" (high confidence, 12 files)
→ Promote to: tech-stack.md ## Accepted Patterns? [y/n]
2. [Convention] "Error boundary at route level" (high confidence, 8 files)
→ Promote to: Hard Guardrail (enforce always)? [y/n]
3. [Anti-Pattern] "Unguarded .env access" (high confidence, 6 files)
→ Promote to: Hard Guardrail (enforce always)? [y/n]
For each promoted pattern:
draft/tech-stack.md ## Accepted Patterns and remove from guardrails.md Learned Conventions[x] item)[x] item)Display results to the user:
/draft:learn complete
Scanned: N source files across M directories
Duration: ~Xs
Results:
New conventions learned: N [list names]
New anti-patterns learned: N [list names]
Existing patterns updated: N [list names]
Skipped (insufficient data): N
Skipped (already documented): N
Promotion candidates (high confidence):
N patterns ready for promotion — run /draft:learn promote to review
Updated: draft/guardrails.md
After /draft:learn populates guardrails.md, all quality commands automatically:
| Section | Quality Command Behavior |
|---|---|
| Hard Guardrails (checked) | Flag violations as issues |
| Learned Conventions | Skip these patterns during analysis (not bugs) |
| Learned Anti-Patterns | Always flag these patterns as bugs |
| Unchecked Hard Guardrails | Ignore (not enforced) |
This creates a continuous improvement loop:
/draft:learn promote → graduates stable patterns to permanent status| Don't | Instead |
|---|---|
| Learn from <3 occurrences | Require minimum 3 consistent instances |
| Auto-promote to Hard Guardrails | Always require human approval for promotion |
| Overwrite human-curated entries | Learned patterns complement, never replace |
| Learn framework defaults as conventions | Only learn project-specific patterns |
| Remove entries on re-scan | Update evidence/dates, never delete |
| Learn from test/mock code | Focus on production source code |
Before printing the completion summary, internally verify and report:
find/grep run for source discovery, state which languages or extensions were not covered by the graph indexes (e.g. Ruby without ctags).If draft/graph/schema.yaml does not exist, set Graph files queried: NONE and use justification graph data unavailable.
Emit the canonical footer from core/shared/graph-usage-report.md §Canonical footer. The lint hook scripts/tools/check-graph-usage-report.sh validates the section on save.
npx claudepluginhub drafthq/draft --plugin draftDetects codebase conventions via git-aware scans and generates pattern briefs/summaries for AI-guided planning. Use for 'analyze patterns' queries or before major tasks.
Analyzes codebase to create or update .conventions/ directory with gold standards, anti-patterns, and checks for naming, imports, and patterns. Use for setting up coding standards or bootstrapping new projects.
Learn, record, audit, and apply codebase patterns consistently using a repo-local pattern registry. Acts as a structured approach to preserving continuity, checking drift, and fixing inconsistencies across a repository.