skills/aif-fix/SKILL.md
Fix a specific bug or problem in the codebase. Supports two modes - immediate fix or plan-first. Without arguments executes existing FIX_PLAN.md. Always suggests test coverage and adds logging. Use when user says "fix bug", "debug this", "something is broken", or pastes an error message.
npx skillsauth add lee-to/ai-factory aif-fixInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fix a specific bug or problem in the codebase. Supports two modes: immediate fix or plan-first approach.
Determine Handoff mode, task ID, and skip-review flag. If the caller passed HANDOFF_MODE, HANDOFF_TASK_ID, and HANDOFF_SKIP_REVIEW as explicit text in the prompt, use those values. Otherwise, use the Bash tool:
Bash: printenv HANDOFF_MODE || true
Bash: printenv HANDOFF_TASK_ID || true
Bash: printenv HANDOFF_SKIP_REVIEW || true
Then check HANDOFF_MODE:
HANDOFF_MODE is 1 (autonomous Handoff agent)The Handoff coordinator already manages status transitions and DB writes directly. Do NOT call MCP tools. Instead:
AskUserQuestion. If $ARGUMENTS contains --plan-first, use "Plan first" mode. Otherwise default to "Fix now" mode. Always include tests and logging.HANDOFF_TASK_ID is non-empty, you MUST insert <!-- handoff:task:<HANDOFF_TASK_ID> --> as the very first line of the fix plan file, before the title. Omitting this annotation when HANDOFF_TASK_ID is set is a bug — verify before completing. This applies to both Step 1.1 (creating new plan) and any plan rewrite.HANDOFF_MODE is NOT 1 (manual Claude Code session)Handoff sync is handled inline — see Step 0.1 (after reading the fix plan file) for the task ID extraction and MCP sync trigger. The sync points are:
"planning" → "plan_ready" (after save)"implementing" (Step 2 entry) → "done" if HANDOFF_SKIP_REVIEW=1, else "review" (Step 5)"implementing" (Step 0.1) → "done" if HANDOFF_SKIP_REVIEW=1, else "review" (Step 5)CRITICAL: Always pass paused: true with every handoff_sync_status call except done.
When creating a new FIX_PLAN.md: if there is no existing annotation and no Handoff context, do not add the annotation.
FIRST: Read .ai-factory/config.yaml if it exists to resolve:
paths.description, paths.architecture, paths.rules_file, paths.rules, paths.fix_plan, and paths.patcheslanguage.ui for prompts and summaries, language.artifacts for FIX_PLAN.md and patch artifacts, and language.technical_terms for human-readable technical terminology in artifactsrules.base plus any named rules.<area> entriesIf config.yaml doesn't exist, use defaults:
.ai-factory/DESCRIPTION.md.ai-factory/ARCHITECTURE.md.ai-factory/RULES.md.ai-factory/rules/.ai-factory/FIX_PLAN.md.ai-factory/patches/ui_language: enartifact_language: entechnical_terms_policy: keepResolved language values:
ui_language = language.ui || "en"artifact_language = language.artifacts || language.ui || "en"technical_terms_policy = language.technical_terms || "keep"If technical_terms_policy is not one of keep, translate, or mixed, treat it as keep. Legacy values such as english also behave like keep.
All AskUserQuestion prompts, progress updates, fix summaries, test prompts, and next-step guidance MUST be written in ui_language.
Generated FIX_PLAN.md and self-improvement patch files under paths.patches MUST be written in artifact_language.
Templates and examples define structure, not fixed English output. If artifact_language is not en, translate human-readable headings, labels, analysis text, fix steps, risks, prevention notes, and patch prose before saving. Preserve Handoff annotations, markdown structure, checkbox syntax, paths, commands, config keys, code identifiers, package names, API names, raw error messages, code snippets, log prefixes such as [FIX], and patch tags unchanged. Apply technical_terms_policy to other human-readable terminology.
BEFORE anything else after config resolution, check the resolved fix plan path (default: .ai-factory/FIX_PLAN.md).
If the file EXISTS:
<!-- handoff:task:<uuid> -->:
HANDOFF_MODE is NOT 1 (manual session): extract the task ID. Call handoff_sync_status with { taskId: <extracted-id>, newStatus: "implementing", sourceTimestamp: "<current UTC time in ISO 8601 format>", direction: "aif_to_handoff", paused: true }. (Status is "implementing" because we are executing an existing plan, not creating one.)HANDOFF_MODE is 1: the Handoff coordinator handles sync — do nothing.rm <resolved fix plan path>
If the file DOES NOT exist AND $ARGUMENTS is empty:
/aif-fix <description>) or create a fix plan first."If the file DOES NOT exist AND $ARGUMENTS is provided:
THEN: Read .ai-factory/DESCRIPTION.md (use path from config) if it exists to understand:
Also read .ai-factory/ARCHITECTURE.md (use path from config), the resolved RULES.md path, and the configured rules hierarchy when present to avoid fixes that violate project structure or local conventions.
Read .ai-factory/skill-context/aif-fix/SKILL.md — MANDATORY if the file exists.
This file contains project-specific rules accumulated by /aif-evolve from patches,
codebase conventions, and tech-stack analysis. These rules are tailored to the current project.
How to apply skill-context rules:
Enforcement: After generating any output artifact, verify it against all skill-context rules. If any rule is violated — fix the output before presenting it to the user.
Patch fallback (limited, only when skill-context is missing):
.ai-factory/skill-context/aif-fix/SKILL.md does not exist and the resolved patches dir exists:
Glob to find *.md files in <resolved patches dir>From $ARGUMENTS, identify:
If unclear, ask:
To fix this effectively, I need more context:
1. What is the expected behavior?
2. What actually happens?
3. Can you share the error message/stack trace?
4. When did this start happening?
After understanding the problem, ask the user to choose a mode using AskUserQuestion:
Question: "How would you like to proceed with the fix?"
Options:
Based on choice:
Handoff sync (manual mode only): If a Handoff task ID is known (from HANDOFF_TASK_ID or an existing annotation) AND HANDOFF_MODE is NOT 1, call handoff_sync_status with { taskId: <id>, newStatus: "planning", sourceTimestamp: "<current UTC time in ISO 8601 format>", direction: "aif_to_handoff", paused: true }.
Investigate the codebase enough to understand the problem and create a plan.
Use the same parallel exploration approach as Step 2 — launch Explore agents to investigate the problem area, related code, and past patterns simultaneously.
After agents return, synthesize findings to:
Then create the resolved fix plan file (default: .ai-factory/FIX_PLAN.md).
Write the fix plan in artifact_language. The template below is the required structure only; translate human-readable headings, labels, and prose before saving when artifact_language is not en, while preserving stable technical tokens from Step 0.
Before writing: If HANDOFF_MODE is 1 and HANDOFF_TASK_ID is non-empty, the very first line of the file MUST be <!-- handoff:task:<HANDOFF_TASK_ID> --> followed by a blank line, then the plan content below. If in manual mode and a task ID was extracted from an existing annotation, preserve it.
Structure:
# Fix Plan: [Brief title]
**Problem:** [What's broken — from user's description]
**Created:** YYYY-MM-DD HH:mm
## Analysis
What was found during investigation:
- Root cause (or suspected root cause)
- Affected files and functions
- Impact scope
## Fix Steps
Step-by-step plan for implementing the fix:
1. [ ] Step one — what to change and why
2. [ ] Step two — ...
3. [ ] Step three — ...
## Files to Modify
- `path/to/file.ts` — what changes are needed
- `path/to/another.ts` — what changes are needed
## Risks & Considerations
- Potential side effects
- Things to verify after the fix
- Edge cases to watch for
## Test Coverage
- What tests should be added
- What edge cases to cover
After creating the plan, output:
## Fix Plan Created ✅
Plan saved to the resolved fix plan path.
Review the plan and when you're ready to execute, run:
/aif-fix
Handoff sync (manual mode only): If a Handoff task ID is known AND HANDOFF_MODE is NOT 1, call handoff_push_plan with { taskId: <id>, planContent: <full fix plan text> }, then handoff_sync_status with { taskId: <id>, newStatus: "plan_ready", sourceTimestamp: "<current UTC time in ISO 8601 format>", direction: "aif_to_handoff", paused: true }.
STOP here. Do NOT apply the fix.
Handoff sync (manual mode, "Fix now" path only): If a Handoff task ID is known AND HANDOFF_MODE is NOT 1, call handoff_sync_status with { taskId: <id>, newStatus: "implementing", sourceTimestamp: "<current UTC time in ISO 8601 format>", direction: "aif_to_handoff", paused: true }.
Use Task tool with subagent_type: Explore to investigate the problem in parallel. This keeps the main context clean and allows simultaneous investigation of multiple angles.
Launch 2-3 Explore agents simultaneously:
Agent 1 — Locate the problem area:
Task(subagent_type: Explore, model: sonnet, prompt:
"Find code related to [error location / affected functionality].
Read the relevant functions, trace the data flow.
Thoroughness: medium.")
Agent 2 — Related code & side effects:
Task(subagent_type: Explore, model: sonnet, prompt:
"Find all callers/consumers of [affected function/module].
Identify what else might break or be affected.
Thoroughness: medium.")
Agent 3 — Similar past patterns (if patches exist):
Task(subagent_type: Explore, model: sonnet, prompt:
"Search for similar error patterns or related fixes in the codebase.
Check git log for recent changes to [affected files].
Thoroughness: quick.")
After agents return, synthesize findings to identify:
Fallback: If Task tool is unavailable, investigate directly:
Apply the fix with logging:
// ✅ REQUIRED: Add logging around the fix
console.log("[FIX] Processing user input", { userId, input });
try {
// The actual fix
const result = fixedLogic(input);
console.log("[FIX] Success", { userId, result });
return result;
} catch (error) {
console.error("[FIX] Error in fixedLogic", {
userId,
input,
error: error.message,
stack: error.stack,
});
throw error;
}
Logging is MANDATORY because:
Handoff sync (manual mode ONLY — skip entirely when HANDOFF_MODE is 1): If a Handoff task ID is known AND HANDOFF_MODE is NOT 1:
handoff_push_plan with { taskId: <id>, planContent: <fix summary or updated plan> }.HANDOFF_SKIP_REVIEW is 1: call handoff_sync_status with { taskId: <id>, newStatus: "done", sourceTimestamp: "<current UTC time in ISO 8601 format>", direction: "aif_to_handoff", paused: false }.handoff_sync_status with { taskId: <id>, newStatus: "review", sourceTimestamp: "<current UTC time in ISO 8601 format>", direction: "aif_to_handoff", paused: true }.ALWAYS suggest covering this case with a test:
The Step 5 and After Fixing output templates define structure only. Render all human-readable text in these user-facing responses in ui_language. Preserve code snippets, commands, file paths, line references, log prefixes such as [FIX], and AskUserQuestion option structure unchanged.
## Fix Applied ✅
The issue was: [brief explanation]
Fixed by: [what was changed]
### Logging Added
The fix includes logging with prefix `[FIX]`.
Please test and share any logs if issues persist.
### Recommended: Add a Test
This bug should be covered by a test to prevent regression:
\`\`\`typescript
describe('functionName', () => {
it('should handle [the edge case that caused the bug]', () => {
// Arrange
const input = /* the problematic input */;
// Act
const result = functionName(input);
// Assert
expect(result).toBe(/* expected */);
});
});
\`\`\`
AskUserQuestion: Would you like me to create this test?
Options:
1. Yes, create the test
2. No, skip for now
Handling the user's response:
If "Yes, create the test":
If "No, skip for now":
All fixes MUST include logging:
[FIX] or [FIX:<issue-id>] for easy filtering// Pattern for fixes
const LOG_FIX = process.env.LOG_LEVEL === "debug" || process.env.DEBUG_FIX;
function fixedFunction(input) {
if (LOG_FIX) console.log("[FIX] Input:", input);
// ... fix logic ...
if (LOG_FIX) console.log("[FIX] Output:", result);
return result;
}
User: /aif-fix TypeError: Cannot read property 'name' of undefined in UserProfile
Actions:
.name is accessedUser: /aif-fix /api/orders returns empty array for authenticated users
Actions:
User: /aif-fix email validation accepts invalid emails
Actions:
/aif-fix owns paths.fix_plan and paths.patches; treat .ai-factory/DESCRIPTION.md, roadmap, rules, and architecture context artifacts as read-only unless the user explicitly requests otherwise[FIX] logging requirements for fixes; context-gate outputs in this command should use WARN/ERROR and must not change global logging policy in other skillsUse this output template in Step 5 (before the AskUserQuestion about tests):
## Fix Applied ✅
**Issue:** [what was broken]
**Cause:** [why it was broken]
**Fix:** [what was changed]
**Files modified:**
- path/to/file.ts (line X)
**Logging added:** Yes, prefix `[FIX]`
ALWAYS create a patch after every fix. This builds a knowledge base for future fixes.
Create the patch:
Create directory if it doesn't exist:
mkdir -p <resolved patches dir>
Create a patch file with the current timestamp as filename.
Format: YYYY-MM-DD-HH.mm.md (e.g., 2026-02-07-14.30.md)
Use this template:
Write the patch artifact in artifact_language. The template below is the required structure only; translate human-readable headings, labels, root-cause text, solution text, and prevention text before saving when artifact_language is not en, while preserving stable technical tokens from Step 0.
# [Brief title describing the fix]
**Date:** YYYY-MM-DD HH:mm
**Files:** list of modified files
**Severity:** low | medium | high | critical
## Problem
What was broken. How it manifested (error message, wrong behavior).
Be specific — include the actual error or symptom.
## Root Cause
WHY the problem occurred. This is the most valuable part.
Not "what was wrong" but "why it was wrong":
- Logic error? Why was the logic incorrect?
- Missing check? Why was it missing?
- Wrong assumption? What was assumed?
- Race condition? What sequence caused it?
## Solution
How the fix was implemented. Key code changes and reasoning.
Include the approach, not just "changed line X".
## Prevention
How to prevent this class of problems in the future:
- What pattern/practice should be followed?
- What should be checked during code review?
- What test would catch this?
## Tags
Space-separated tags for categorization, e.g.:
`#null-check` `#async` `#validation` `#typescript` `#api` `#database`
Example patch:
# Null reference in UserProfile when user has no avatar
**Date:** 2026-02-07 14:30
**Files:** src/components/UserProfile.tsx
**Severity:** medium
## Problem
TypeError: Cannot read property 'url' of undefined when rendering
UserProfile for users without an uploaded avatar.
## Root Cause
The `user.avatar` field is optional in the database schema but the
component accessed `user.avatar.url` without a null check. This was
introduced in commit abc123 when avatar display was added — the
developer tested only with users that had avatars.
## Solution
Added optional chaining: `user.avatar?.url` with a fallback to a
default avatar URL. Also added a null check in the Avatar sub-component.
## Prevention
- Always check if database fields marked as `nullable` / `optional`
are handled with null checks in the UI layer
- Add test cases for "empty state" — user with minimal data
- Consider a lint rule for accessing nested optional properties
## Tags
`#null-check` `#react` `#optional-field` `#typescript`
This is NOT optional. Every fix generates a patch. The patch is your learning.
Suggest the user to free up context space if needed: /clear (full reset) or /compact (compress history).
DO NOT:
data-ai
Archive completed plans and roadmap milestones. Moves finished plans to the archive directory and optionally trims closed milestones from ROADMAP.md. Use when user says "archive plans", "clean up plans", "archive completed", or "trim roadmap".
tools
Set up agent context for a project. Analyzes tech stack, installs relevant skills from skills.sh, generates custom skills, and configures MCP servers. Use when starting new project, setting up AI context, or asking "set up project", "configure AI", "what skills do I need".
development
Verify completed implementation against the plan. Checks that all tasks were fully implemented, nothing was forgotten, code compiles, tests pass, and quality standards are met. Use after "/aif-implement" completes, or when user says "verify", "check work", "did we miss anything".
data-ai
Plan implementation for a feature or task. Two modes — fast (single quick plan) or full (richer plan with optional git branch/worktree flow). Use when user says "plan", "new feature", "start feature", "create tasks".