@kurokeita/add-skill 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +56 -20
  2. package/dist/agents/backend-specialist.md +277 -0
  3. package/dist/agents/code-archaeologist.md +114 -0
  4. package/dist/agents/database-architect.md +238 -0
  5. package/dist/agents/debugger.md +231 -0
  6. package/dist/agents/devops-engineer.md +242 -0
  7. package/dist/agents/documentation-writer.md +104 -0
  8. package/dist/agents/explorer-agent.md +79 -0
  9. package/dist/agents/frontend-specialist.md +594 -0
  10. package/dist/agents/game-developer.md +162 -0
  11. package/dist/agents/mobile-developer.md +383 -0
  12. package/dist/agents/orchestrator.md +435 -0
  13. package/dist/agents/penetration-tester.md +188 -0
  14. package/dist/agents/performance-optimizer.md +191 -0
  15. package/dist/agents/product-manager.md +122 -0
  16. package/dist/agents/product-owner.md +106 -0
  17. package/dist/agents/project-planner.md +408 -0
  18. package/dist/agents/qa-automation-engineer.md +109 -0
  19. package/dist/agents/security-auditor.md +171 -0
  20. package/dist/agents/test-engineer.md +158 -0
  21. package/dist/bin/cli.js +29 -0
  22. package/dist/src/commands/add.js +115 -77
  23. package/dist/src/commands/import.js +73 -23
  24. package/dist/src/commands/list.js +84 -23
  25. package/dist/src/commands/remove.js +118 -0
  26. package/dist/src/utils/github.js +22 -11
  27. package/dist/src/utils/paths.js +45 -0
  28. package/dist/workflows/brainstorm.md +113 -0
  29. package/dist/workflows/create.md +60 -0
  30. package/dist/workflows/debug.md +107 -0
  31. package/dist/workflows/deploy.md +178 -0
  32. package/dist/workflows/enhance.md +64 -0
  33. package/dist/workflows/orchestrate.md +246 -0
  34. package/dist/workflows/plan.md +90 -0
  35. package/dist/workflows/preview.md +83 -0
  36. package/dist/workflows/status.md +87 -0
  37. package/dist/workflows/test.md +144 -0
  38. package/dist/workflows/ui-ux-pro-max.md +315 -0
  39. package/package.json +4 -4
  40. package/dist/bin/skills.js +0 -17
@@ -1,31 +1,92 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
1
  import fs from "fs-extra";
4
2
  import pc from "picocolors";
5
- const __filename = fileURLToPath(import.meta.url);
6
- const __dirname = path.dirname(__filename);
7
- // Assuming skills are in the root 'skills' directory relative to the project root
8
- // bin/skills.ts -> ../ -> src/commands -> ../../ -> root -> skills
9
- const PROJECT_ROOT = path.resolve(__dirname, "../..");
10
- const SKILLS_DIR = path.join(PROJECT_ROOT, "skills");
11
- export async function listSkills() {
3
+ import { getTargetPaths, TYPE_DIRS } from "../utils/paths.js";
4
+ export async function list(type, options) {
12
5
  try {
13
- if (!(await fs.pathExists(SKILLS_DIR))) {
14
- console.log(pc.yellow("No existing skills directory found at:"), SKILLS_DIR);
15
- return;
6
+ const typesToList = type
7
+ ? [type.toLowerCase()]
8
+ : ["skill", "agent", "workflow"];
9
+ for (const t of typesToList) {
10
+ // Handle plural/singular input for convenience
11
+ const normalizedType = t.endsWith("s") ? t.slice(0, -1) : t;
12
+ if (options?.local) {
13
+ // List installed items locally
14
+ console.log(pc.bold(pc.blue(`Installed ${normalizedType}s (Local):`)));
15
+ const targetPaths = getTargetPaths(normalizedType);
16
+ let foundAny = false;
17
+ for (const [platform, pathStr] of Object.entries(targetPaths)) {
18
+ const fullPath = pathStr;
19
+ if (await fs.pathExists(fullPath)) {
20
+ const entries = await fs.readdir(fullPath, {
21
+ withFileTypes: true,
22
+ });
23
+ const items = entries
24
+ .filter((entry) => entry.isDirectory() ||
25
+ // For local items, agents/workflows might be directories OR .md files depending on how they were installed/flattened.
26
+ // Usually flattened -> directory (if unpacked) or file (if generic).
27
+ // Existing add logic:
28
+ // Agents/Workflows can be flattened (unpacked to base) or not.
29
+ // If flattened, they are files in the base dir? No, unpacked to base means they are files/dirs IN the base dir.
30
+ // Wait, if I import "agent-a" (dir) and flatten, it copies contents of agent-a to agents/.
31
+ // So "agents/skill.md" might exist.
32
+ // The user requirement says "list all installed agents/skills/workflows".
33
+ // In local global_skills (antigravity), they are directories.
34
+ // In local global_agents, they might be directories or .md files.
35
+ // Let's list directories and .md files.
36
+ (entry.isFile() && entry.name.endsWith(".md")))
37
+ .map((entry) => entry.name)
38
+ .sort();
39
+ if (items.length > 0) {
40
+ foundAny = true;
41
+ console.log(pc.cyan(` ${platform}:`));
42
+ for (const item of items) {
43
+ console.log(` - ${item}`);
44
+ }
45
+ }
46
+ }
47
+ }
48
+ if (!foundAny) {
49
+ console.log(pc.dim(` No installed ${normalizedType}s found.`));
50
+ }
51
+ console.log(""); // Newline for separation
52
+ }
53
+ else {
54
+ // List available items in repo (existing logic)
55
+ if (!TYPE_DIRS[normalizedType]) {
56
+ if (type) {
57
+ console.error(pc.red(`Unknown type: ${type}. Supported types: skill, agent, workflow`));
58
+ }
59
+ continue;
60
+ }
61
+ const dirPath = TYPE_DIRS[normalizedType];
62
+ if (!(await fs.pathExists(dirPath))) {
63
+ if (type) {
64
+ console.log(pc.yellow(`No ${t} directory found at: ${dirPath}`));
65
+ }
66
+ continue;
67
+ }
68
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
69
+ const items = entries
70
+ .filter((entry) => entry.isDirectory() ||
71
+ (normalizedType !== "skill" &&
72
+ entry.isFile() &&
73
+ entry.name.endsWith(".md")))
74
+ .map((entry) => entry.name)
75
+ .sort();
76
+ if (items.length > 0) {
77
+ console.log(pc.bold(pc.blue(`Available ${normalizedType}s:`)));
78
+ for (const item of items) {
79
+ console.log(`- ${item}`);
80
+ }
81
+ console.log(pc.dim(`Total: ${items.length} ${normalizedType}s\n`));
82
+ }
83
+ else if (type) {
84
+ console.log(pc.dim(`No ${normalizedType}s found.`));
85
+ }
86
+ }
16
87
  }
17
- const entries = await fs.readdir(SKILLS_DIR, { withFileTypes: true });
18
- const skills = entries
19
- .filter((entry) => entry.isDirectory())
20
- .map((entry) => entry.name)
21
- .sort();
22
- console.log(pc.bold(pc.blue("Available Skills:")));
23
- for (const skill of skills) {
24
- console.log(`- ${skill}`);
25
- }
26
- console.log(pc.dim(`\nTotal: ${skills.length} skills`));
27
88
  }
28
89
  catch (error) {
29
- console.error(pc.red("Error listing skills:"), error);
90
+ console.error(pc.red("Error listing items:"), error);
30
91
  }
31
92
  }
@@ -0,0 +1,118 @@
1
+ import path from "node:path";
2
+ import { cancel, confirm, intro, isCancel, multiselect, outro, spinner, } from "@clack/prompts";
3
+ import fs from "fs-extra";
4
+ import pc from "picocolors";
5
+ import { getTargetPaths, PLATFORM_LABELS, } from "../utils/paths.js";
6
+ export async function remove(type) {
7
+ intro(pc.bgCyan(pc.black(` AI Manager : Remove ${type} `)));
8
+ // Normalize type
9
+ const normalizedType = type.toLowerCase().endsWith("s")
10
+ ? type.slice(0, -1)
11
+ : type;
12
+ const targetPaths = getTargetPaths(normalizedType);
13
+ // 1. Collect unique installed items across all platforms
14
+ const uniqueItems = new Set();
15
+ const s = spinner();
16
+ s.start("Scanning for installed items...");
17
+ for (const pathStr of Object.values(targetPaths)) {
18
+ if (await fs.pathExists(pathStr)) {
19
+ const entries = await fs.readdir(pathStr, {
20
+ withFileTypes: true,
21
+ });
22
+ for (const entry of entries) {
23
+ if (entry.isDirectory() ||
24
+ (normalizedType === "workflow" &&
25
+ entry.isFile() &&
26
+ entry.name.endsWith(".md")) ||
27
+ (normalizedType === "agent" &&
28
+ entry.isFile() &&
29
+ entry.name.endsWith(".md"))) {
30
+ uniqueItems.add(entry.name);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ s.stop(`Found ${uniqueItems.size} unique installed ${normalizedType}s.`);
36
+ if (uniqueItems.size === 0) {
37
+ cancel(`No installed ${normalizedType}s found.`);
38
+ process.exit(0);
39
+ }
40
+ // Sort explicitly
41
+ const sortedItems = Array.from(uniqueItems).sort();
42
+ // 2. Select Items
43
+ const itemSelections = await multiselect({
44
+ message: `Select ${normalizedType}s to remove:`,
45
+ options: sortedItems.map((item) => ({ value: item, label: item })),
46
+ required: true,
47
+ });
48
+ if (isCancel(itemSelections)) {
49
+ cancel("Operation cancelled.");
50
+ process.exit(0);
51
+ }
52
+ const selectedItems = itemSelections;
53
+ // 3. Select Platforms
54
+ // Only show platforms relevant to the type
55
+ const platformOptions = Object.entries(targetPaths).map(([platform]) => ({
56
+ label: PLATFORM_LABELS[platform],
57
+ value: platform,
58
+ }));
59
+ const platformSelections = await multiselect({
60
+ message: "Select platforms to remove from:",
61
+ options: platformOptions,
62
+ required: true,
63
+ });
64
+ if (isCancel(platformSelections)) {
65
+ cancel("Operation cancelled.");
66
+ process.exit(0);
67
+ }
68
+ const selectedPlatforms = platformSelections;
69
+ // 4. Confirmation
70
+ const confirmDelete = await confirm({
71
+ message: `Are you sure you want to remove ${selectedItems.length} item(s) from ${selectedPlatforms.length} platform(s)?`,
72
+ initialValue: false,
73
+ });
74
+ if (isCancel(confirmDelete) || !confirmDelete) {
75
+ cancel("Operation cancelled.");
76
+ process.exit(0);
77
+ }
78
+ // 5. Deletion Loop
79
+ const sDel = spinner();
80
+ sDel.start("Removing items...");
81
+ let removedCount = 0;
82
+ let notFoundCount = 0;
83
+ const errors = [];
84
+ for (const platform of selectedPlatforms) {
85
+ const targetBase = targetPaths[platform];
86
+ if (!targetBase)
87
+ continue;
88
+ for (const item of selectedItems) {
89
+ const targetPath = path.join(targetBase, item);
90
+ // Check if exists before trying to remove, to correctly count "removed" vs "not found"
91
+ if (await fs.pathExists(targetPath)) {
92
+ sDel.message(`Removing ${pc.bold(item)} from ${pc.cyan(platform)}...`);
93
+ try {
94
+ await fs.remove(targetPath);
95
+ removedCount++;
96
+ }
97
+ catch (err) {
98
+ const msg = err instanceof Error ? err.message : String(err);
99
+ errors.push(`${item} (${platform}): ${msg}`);
100
+ }
101
+ }
102
+ else {
103
+ notFoundCount++;
104
+ }
105
+ }
106
+ }
107
+ if (errors.length > 0) {
108
+ sDel.stop(pc.yellow(`Completed with errors. Removed: ${removedCount}, Not Found: ${notFoundCount}, Errors: ${errors.length}`));
109
+ console.error(pc.red("\nErrors encountered:"));
110
+ for (const e of errors) {
111
+ console.error(pc.red(`- ${e}`));
112
+ }
113
+ }
114
+ else {
115
+ sDel.stop(pc.green(`Successfully removed ${removedCount} items. (${notFoundCount} not found)`));
116
+ }
117
+ outro("Done!");
118
+ }
@@ -2,19 +2,18 @@ import os from "node:os";
2
2
  import path from "node:path";
3
3
  import fs from "fs-extra";
4
4
  export async function fetchSkillFromGitHub(url) {
5
- const regex = /github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/;
5
+ const regex = /github\.com\/([^/]+)\/([^/]+)\/(?:tree|blob)\/([^/]+)\/(.+)/;
6
6
  const match = url.match(regex);
7
7
  if (!match) {
8
- throw new Error("Invalid GitHub URL. Format: https://github.com/owner/repo/tree/branch/path/to/skill");
8
+ throw new Error("Invalid GitHub URL. Format: https://github.com/owner/repo/tree/branch/path/to/skill or blob/branch/path/to/file");
9
9
  }
10
10
  const [, owner, repo, ref, skillPath] = match;
11
11
  const skillName = path.basename(skillPath);
12
- // Initial API URL for the root of the skill
13
12
  const initialApiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${skillPath}?ref=${ref}`;
14
13
  const tempDir = path.join(os.tmpdir(), "ai-agents-install", skillName);
15
14
  await fs.ensureDir(tempDir);
16
15
  await fs.emptyDir(tempDir);
17
- // Recursive function to download directory contents
16
+ let isFile = false;
18
17
  async function downloadDirectory(apiUrl, localDir) {
19
18
  const response = await fetch(apiUrl, {
20
19
  headers: {
@@ -25,13 +24,26 @@ export async function fetchSkillFromGitHub(url) {
25
24
  if (!response.ok) {
26
25
  throw new Error(`Failed to fetch from GitHub (${response.status}): ${response.statusText}`);
27
26
  }
28
- const data = (await response.json());
27
+ const data = await response.json();
28
+ // Handle single file response
29
+ if (!Array.isArray(data) && data.type === "file") {
30
+ isFile = true;
31
+ const item = data;
32
+ if (item.download_url) {
33
+ const fileContentResponse = await fetch(item.download_url);
34
+ if (!fileContentResponse.ok) {
35
+ throw new Error(`Failed to download ${item.name}: ${fileContentResponse.statusText}`);
36
+ }
37
+ const content = await fileContentResponse.text();
38
+ await fs.writeFile(path.join(localDir, item.name), content);
39
+ }
40
+ return;
41
+ }
29
42
  if (!Array.isArray(data)) {
30
- // If it's not an array, it might be a single file if the URL pointed to a file,
31
- // but we expect a directory here per the Contents API usage for directories.
32
- throw new Error("Invalid response from GitHub API. Expected directory listing.");
43
+ throw new Error("Invalid response from GitHub API. Expected directory listing or file object.");
33
44
  }
34
- for (const item of data) {
45
+ const files = data;
46
+ for (const item of files) {
35
47
  if (item.type === "file" && item.download_url) {
36
48
  const fileContentResponse = await fetch(item.download_url);
37
49
  if (!fileContentResponse.ok) {
@@ -44,11 +56,10 @@ export async function fetchSkillFromGitHub(url) {
44
56
  else if (item.type === "dir") {
45
57
  const newLocalDir = path.join(localDir, item.name);
46
58
  await fs.ensureDir(newLocalDir);
47
- // Recursively download subdirectory using its API URL
48
59
  await downloadDirectory(item.url, newLocalDir);
49
60
  }
50
61
  }
51
62
  }
52
63
  await downloadDirectory(initialApiUrl, tempDir);
53
- return { tempDir, skillName };
64
+ return { tempDir, skillName, isFile };
54
65
  }
@@ -0,0 +1,45 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = path.dirname(__filename);
6
+ export const PROJECT_ROOT = path.resolve(__dirname, "../..");
7
+ export const PLATFORM_LABELS = {
8
+ antigravity: "Antigravity",
9
+ gemini: "Gemini CLI",
10
+ copilot: "GitHub Copilot",
11
+ windsurf: "Windsurf",
12
+ };
13
+ export const PLATFORM_PATHS_SKILLS = {
14
+ antigravity: path.join(os.homedir(), ".gemini/antigravity/global_skills"),
15
+ copilot: path.join(os.homedir(), ".copilot/skills"),
16
+ gemini: path.join(os.homedir(), ".gemini/skills"),
17
+ windsurf: path.join(os.homedir(), ".codeium/windsurf/skills"),
18
+ };
19
+ export const PLATFORM_PATHS_AGENTS = {
20
+ antigravity: path.join(os.homedir(), ".gemini/antigravity/global_agents"),
21
+ copilot: path.join(os.homedir(), ".copilot/agents"),
22
+ gemini: path.join(os.homedir(), ".gemini/agents"),
23
+ windsurf: path.join(os.homedir(), ".codeium/windsurf/agents"),
24
+ };
25
+ export const PLATFORM_PATHS_WORKFLOWS = {
26
+ antigravity: path.join(os.homedir(), ".gemini/antigravity/global_workflows"),
27
+ copilot: path.join(os.homedir(), ".copilot/prompts"),
28
+ gemini: path.join(os.homedir(), ".gemini/workflows"),
29
+ windsurf: path.join(os.homedir(), ".codeium/windsurf/global_workflows"),
30
+ };
31
+ export const TYPE_DIRS = {
32
+ skill: path.join(PROJECT_ROOT, "skills"),
33
+ agent: path.join(PROJECT_ROOT, "agents"),
34
+ workflow: path.join(PROJECT_ROOT, "workflows"),
35
+ };
36
+ export function getTargetPaths(type) {
37
+ switch (type) {
38
+ case "agent":
39
+ return PLATFORM_PATHS_AGENTS;
40
+ case "workflow":
41
+ return PLATFORM_PATHS_WORKFLOWS;
42
+ default:
43
+ return PLATFORM_PATHS_SKILLS;
44
+ }
45
+ }
@@ -0,0 +1,113 @@
1
+ ---
2
+ description: Structured brainstorming for projects and features. Explores multiple options before implementation.
3
+ ---
4
+
5
+ # /brainstorm - Structured Idea Exploration
6
+
7
+ $ARGUMENTS
8
+
9
+ ---
10
+
11
+ ## Purpose
12
+
13
+ This command activates BRAINSTORM mode for structured idea exploration. Use when you need to explore options before committing to an implementation.
14
+
15
+ ---
16
+
17
+ ## Behavior
18
+
19
+ When `/brainstorm` is triggered:
20
+
21
+ 1. **Understand the goal**
22
+ - What problem are we solving?
23
+ - Who is the user?
24
+ - What constraints exist?
25
+
26
+ 2. **Generate options**
27
+ - Provide at least 3 different approaches
28
+ - Each with pros and cons
29
+ - Consider unconventional solutions
30
+
31
+ 3. **Compare and recommend**
32
+ - Summarize tradeoffs
33
+ - Give a recommendation with reasoning
34
+
35
+ ---
36
+
37
+ ## Output Format
38
+
39
+ ```markdown
40
+ ## 🧠 Brainstorm: [Topic]
41
+
42
+ ### Context
43
+ [Brief problem statement]
44
+
45
+ ---
46
+
47
+ ### Option A: [Name]
48
+ [Description]
49
+
50
+ ✅ **Pros:**
51
+ - [benefit 1]
52
+ - [benefit 2]
53
+
54
+ ❌ **Cons:**
55
+ - [drawback 1]
56
+
57
+ 📊 **Effort:** Low | Medium | High
58
+
59
+ ---
60
+
61
+ ### Option B: [Name]
62
+ [Description]
63
+
64
+ ✅ **Pros:**
65
+ - [benefit 1]
66
+
67
+ ❌ **Cons:**
68
+ - [drawback 1]
69
+ - [drawback 2]
70
+
71
+ 📊 **Effort:** Low | Medium | High
72
+
73
+ ---
74
+
75
+ ### Option C: [Name]
76
+ [Description]
77
+
78
+ ✅ **Pros:**
79
+ - [benefit 1]
80
+
81
+ ❌ **Cons:**
82
+ - [drawback 1]
83
+
84
+ 📊 **Effort:** Low | Medium | High
85
+
86
+ ---
87
+
88
+ ## 💡 Recommendation
89
+
90
+ **Option [X]** because [reasoning].
91
+
92
+ What direction would you like to explore?
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Examples
98
+
99
+ ```
100
+ /brainstorm authentication system
101
+ /brainstorm state management for complex form
102
+ /brainstorm database schema for social app
103
+ /brainstorm caching strategy
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Key Principles
109
+
110
+ - **No code** - this is about ideas, not implementation
111
+ - **Visual when helpful** - use diagrams for architecture
112
+ - **Honest tradeoffs** - don't hide complexity
113
+ - **Defer to user** - present options, let them decide
@@ -0,0 +1,60 @@
1
+ ---
2
+ description: Create new application command. Triggers App Builder skill and starts interactive dialogue with user.
3
+ ---
4
+
5
+ # /create - Create Application
6
+
7
+ $ARGUMENTS
8
+
9
+ ---
10
+
11
+ ## Task
12
+
13
+ This command starts a new application creation process.
14
+
15
+ ### Steps
16
+
17
+ 1. **Request Analysis**
18
+ - Understand what the user wants
19
+ - If information is missing, use `conversation-manager` skill to ask
20
+
21
+ 2. **Project Planning**
22
+ - Use `project-planner` agent for task breakdown
23
+ - Determine tech stack
24
+ - Plan file structure
25
+ - Create plan file and proceed to building
26
+
27
+ 3. **Application Building (After Approval)**
28
+ - Orchestrate with `app-builder` skill
29
+ - Coordinate expert agents:
30
+ - `database-architect` → Schema
31
+ - `backend-specialist` → API
32
+ - `frontend-specialist` → UI
33
+
34
+ 4. **Preview**
35
+ - Start with `auto_preview.py` when complete
36
+ - Present URL to user
37
+
38
+ ---
39
+
40
+ ## Usage Examples
41
+
42
+ ```
43
+ /create blog site
44
+ /create e-commerce app with product listing and cart
45
+ /create todo app
46
+ /create Instagram clone
47
+ /create crm system with customer management
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Before Starting
53
+
54
+ If request is unclear, ask these questions:
55
+
56
+ - What type of application?
57
+ - What are the basic features?
58
+ - Who will use it?
59
+
60
+ Use defaults, add details later.
@@ -0,0 +1,107 @@
1
+ ---
2
+ description: Debugging command. Activates DEBUG mode for systematic problem investigation.
3
+ ---
4
+
5
+ # /debug - Systematic Problem Investigation
6
+
7
+ $ARGUMENTS
8
+
9
+ ---
10
+
11
+ ## Purpose
12
+
13
+ This command activates DEBUG mode for systematic investigation of issues, errors, or unexpected behavior.
14
+
15
+ ---
16
+
17
+ ## Behavior
18
+
19
+ When `/debug` is triggered:
20
+
21
+ 1. **Gather information**
22
+ - Error message
23
+ - Reproduction steps
24
+ - Expected vs actual behavior
25
+ - Recent changes
26
+
27
+ 2. **Form hypotheses**
28
+ - List possible causes
29
+ - Order by likelihood
30
+
31
+ 3. **Investigate systematically**
32
+ - Test each hypothesis
33
+ - Check logs, data flow
34
+ - Use elimination method
35
+
36
+ 4. **Fix and prevent**
37
+ - Apply fix
38
+ - Explain root cause
39
+ - Add prevention measures
40
+
41
+ ---
42
+
43
+ ## Output Format
44
+
45
+ ```markdown
46
+ ## 🔍 Debug: [Issue]
47
+
48
+ ### 1. Symptom
49
+ [What's happening]
50
+
51
+ ### 2. Information Gathered
52
+ - Error: `[error message]`
53
+ - File: `[filepath]`
54
+ - Line: [line number]
55
+
56
+ ### 3. Hypotheses
57
+ 1. ❓ [Most likely cause]
58
+ 2. ❓ [Second possibility]
59
+ 3. ❓ [Less likely cause]
60
+
61
+ ### 4. Investigation
62
+
63
+ **Testing hypothesis 1:**
64
+ [What I checked] → [Result]
65
+
66
+ **Testing hypothesis 2:**
67
+ [What I checked] → [Result]
68
+
69
+ ### 5. Root Cause
70
+ 🎯 **[Explanation of why this happened]**
71
+
72
+ ### 6. Fix
73
+ ```[language]
74
+ // Before
75
+ [broken code]
76
+
77
+ // After
78
+ [fixed code]
79
+ ```
80
+
81
+ ### 7. Prevention
82
+
83
+ 🛡️ [How to prevent this in the future]
84
+
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Examples
90
+
91
+ ```
92
+
93
+ /debug login not working
94
+ /debug API returns 500
95
+ /debug form doesn't submit
96
+ /debug data not saving
97
+
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Key Principles
103
+
104
+ - **Ask before assuming** - get full error context
105
+ - **Test hypotheses** - don't guess randomly
106
+ - **Explain why** - not just what to fix
107
+ - **Prevent recurrence** - add tests, validation