@indiccoder/mentis-cli 1.0.8 → 1.1.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.
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ /**
3
+ * ConversationCompacter - Compact conversation to save tokens
4
+ * Summarizes conversation history while preserving important context
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ConversationCompacter = void 0;
11
+ const inquirer_1 = __importDefault(require("inquirer"));
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ class ConversationCompacter {
14
+ /**
15
+ * Compact conversation history using AI
16
+ */
17
+ async compact(history, modelClient, options) {
18
+ const { keepSystemMessages = true, focusTopic } = options || {};
19
+ // Preserve system-style messages
20
+ const preserved = [];
21
+ const toCompact = [];
22
+ for (const msg of history) {
23
+ if (msg.role === 'system' || msg.role === 'tool') {
24
+ preserved.push(msg);
25
+ }
26
+ else {
27
+ toCompact.push(msg);
28
+ }
29
+ }
30
+ if (toCompact.length === 0) {
31
+ return history;
32
+ }
33
+ // Create compaction prompt
34
+ let compactPrompt = 'Please summarize the following conversation into a concise overview. ';
35
+ compactPrompt += 'Include:\n';
36
+ compactPrompt += '- The main topic/problem being discussed\n';
37
+ compactPrompt += '- Key decisions made\n';
38
+ compactPrompt += '- Important technical details\n';
39
+ compactPrompt += '- Current status/next steps\n\n';
40
+ if (focusTopic) {
41
+ compactPrompt += `Focus primarily on content related to: ${focusTopic}\n\n`;
42
+ }
43
+ compactPrompt += 'Return ONLY the summary, no other text.\n\n---\n\n';
44
+ for (const msg of toCompact.slice(-10)) { // Last 10 messages for context
45
+ compactPrompt += `${msg.role.toUpperCase()}: ${msg.content}\n\n`;
46
+ }
47
+ try {
48
+ // Call AI to summarize
49
+ const summaryResponse = await modelClient.chat([{ role: 'user', content: compactPrompt }], []);
50
+ const summary = summaryResponse.content;
51
+ // Create new compacted history
52
+ const newHistory = [...preserved];
53
+ // Add summary as a system message for context
54
+ newHistory.push({
55
+ role: 'system',
56
+ content: `[Previous Conversation Summary]\n${summary}`
57
+ });
58
+ return newHistory;
59
+ }
60
+ catch (error) {
61
+ console.error('Compaction failed:', error);
62
+ return history; // Return original if compaction fails
63
+ }
64
+ }
65
+ /**
66
+ * Prompt user to compact when threshold is reached
67
+ */
68
+ async promptIfCompactNeeded(percentage, history, modelClient) {
69
+ if (percentage < 80) {
70
+ return history;
71
+ }
72
+ console.log(chalk_1.default.yellow(`\n⚠️ Context is ${percentage}% full. Consider compacting to save tokens.`));
73
+ const { shouldCompact } = await inquirer_1.default.prompt([
74
+ {
75
+ type: 'confirm',
76
+ name: 'shouldCompact',
77
+ message: 'Compact conversation now?',
78
+ default: true
79
+ }
80
+ ]);
81
+ if (!shouldCompact) {
82
+ return history;
83
+ }
84
+ const { focusTopic } = await inquirer_1.default.prompt([
85
+ {
86
+ type: 'input',
87
+ name: 'focusTopic',
88
+ message: 'Focus on specific topic? (leave empty for general)',
89
+ default: ''
90
+ }
91
+ ]);
92
+ return await this.compact(history, modelClient, {
93
+ keepSystemMessages: true,
94
+ focusTopic: focusTopic || undefined
95
+ });
96
+ }
97
+ }
98
+ exports.ConversationCompacter = ConversationCompacter;
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /**
3
+ * ProjectInitializer - Initialize project with .mentis.md
4
+ * Interactive wizard for creating project guide files
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ var __importDefault = (this && this.__importDefault) || function (mod) {
40
+ return (mod && mod.__esModule) ? mod : { "default": mod };
41
+ };
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.ProjectInitializer = void 0;
44
+ const inquirer_1 = __importDefault(require("inquirer"));
45
+ const chalk_1 = __importDefault(require("chalk"));
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ class ProjectInitializer {
49
+ /**
50
+ * Run the interactive project initialization wizard
51
+ */
52
+ async run(cwd = process.cwd()) {
53
+ console.log('\n📁 Initialize Project with .mentis.md\n');
54
+ // Step 1: Project name
55
+ const { projectName } = await inquirer_1.default.prompt([
56
+ {
57
+ type: 'input',
58
+ name: 'projectName',
59
+ message: 'Project name:',
60
+ default: path.basename(cwd)
61
+ }
62
+ ]);
63
+ // Step 2: Project description
64
+ const { description } = await inquirer_1.default.prompt([
65
+ {
66
+ type: 'input',
67
+ name: 'description',
68
+ message: 'Brief description:',
69
+ default: 'A software project'
70
+ }
71
+ ]);
72
+ // Step 3: Tech stack
73
+ const { techStack } = await inquirer_1.default.prompt([
74
+ {
75
+ type: 'checkbox',
76
+ name: 'techStack',
77
+ message: 'Select technologies:',
78
+ choices: [
79
+ 'TypeScript',
80
+ 'JavaScript',
81
+ 'Python',
82
+ 'React',
83
+ 'Vue',
84
+ 'Node.js',
85
+ 'Express',
86
+ 'PostgreSQL',
87
+ 'MongoDB',
88
+ 'Redis',
89
+ 'Docker',
90
+ 'GraphQL',
91
+ 'REST API',
92
+ 'Other'
93
+ ]
94
+ }
95
+ ]);
96
+ // Step 4: Project type
97
+ const { projectType } = await inquirer_1.default.prompt([
98
+ {
99
+ type: 'list',
100
+ name: 'projectType',
101
+ message: 'Project type:',
102
+ choices: ['Web Application', 'API/Backend', 'CLI Tool', 'Library/Package', 'Mobile App', 'Desktop App', 'Other']
103
+ }
104
+ ]);
105
+ // Step 5: Conventions
106
+ const { useConventions } = await inquirer_1.default.prompt([
107
+ {
108
+ type: 'confirm',
109
+ name: 'useConventions',
110
+ message: 'Add coding conventions?',
111
+ default: true
112
+ }
113
+ ]);
114
+ let conventions = '';
115
+ if (useConventions) {
116
+ const { conventionStyle } = await inquirer_1.default.prompt([
117
+ {
118
+ type: 'list',
119
+ name: 'conventionStyle',
120
+ message: 'Style guide:',
121
+ choices: ['Standard', 'Airbnb', 'Google', 'Prettier', 'Custom']
122
+ }
123
+ ]);
124
+ conventions = this.getConventionText(conventionStyle);
125
+ }
126
+ // Create .mentis.md content
127
+ const content = this.generateMentisMd({
128
+ projectName,
129
+ description,
130
+ techStack,
131
+ projectType,
132
+ conventions
133
+ });
134
+ // Write to file
135
+ const mentisMdPath = path.join(cwd, '.mentis.md');
136
+ fs.writeFileSync(mentisMdPath, content, 'utf-8');
137
+ console.log(chalk_1.default.green(`\n✓ Created .mentis.md`));
138
+ console.log(chalk_1.default.dim(`\nTip: Edit .mentis.md to add project-specific instructions for Mentis.\n`));
139
+ return true;
140
+ }
141
+ /**
142
+ * Generate .mentis.md content
143
+ */
144
+ generateMentisMd(options) {
145
+ const { projectName, description, techStack, projectType, conventions } = options;
146
+ let content = `# ${projectName}\n\n`;
147
+ content += `${description}\n\n`;
148
+ content += `**Type**: ${projectType}\n\n`;
149
+ content += `## Tech Stack\n\n`;
150
+ content += techStack.map(t => `- ${t}`).join('\n');
151
+ content += `\n\n`;
152
+ if (conventions) {
153
+ content += `## Coding Conventions\n\n`;
154
+ content += `${conventions}\n\n`;
155
+ }
156
+ content += `## Project Structure\n\n`;
157
+ content += `<!-- Add project structure here -->\n\n`;
158
+ content += `## Guidelines for Mentis\n\n`;
159
+ content += `- When writing code, follow the conventions above\n`;
160
+ content += `- Prefer existing patterns in the codebase\n`;
161
+ content += `- Add comments for complex logic\n`;
162
+ content += `- Run tests before suggesting changes\n\n`;
163
+ content += `## Common Commands\n\n`;
164
+ content += `<!-- Add common development commands here -->\n`;
165
+ return content;
166
+ }
167
+ /**
168
+ * Get convention text based on style
169
+ */
170
+ getConventionText(style) {
171
+ const conventions = {
172
+ 'Standard': `- Use 2 spaces for indentation\n- Use camelCase for variables\n- Use PascalCase for classes\n- Prefer const over let\n- Use arrow functions`,
173
+ 'Airbnb': `- Follow Airbnb Style Guide\n- Use 2 spaces for indentation\n- Prefer named exports\n- Use template literals`,
174
+ 'Google': `- Follow Google JavaScript Style Guide\n- Use 2 spaces for indentation\n- JSDoc comments for functions`,
175
+ 'Prettier': `- Use Prettier for formatting\n- 2 spaces for indentation\n- Single quotes for strings\n- No trailing commas`,
176
+ 'Custom': `- Define your conventions below`
177
+ };
178
+ return conventions[style] || conventions['Standard'];
179
+ }
180
+ }
181
+ exports.ProjectInitializer = ProjectInitializer;
package/docs/SKILLS.md ADDED
@@ -0,0 +1,319 @@
1
+ # Agent Skills - User Guide
2
+
3
+ ## Overview
4
+
5
+ Agent Skills allow you to package your expertise into modular, reusable capabilities that Mentis can autonomously discover and use. Skills are organized folders containing instructions, scripts, and resources that extend Mentis's functionality.
6
+
7
+ ## How Skills Work
8
+
9
+ 1. **Discovery**: Mentis scans `~/.mentis/skills/` (personal) and `.mentis/skills/` (project) for skills
10
+ 2. **Metadata Injection**: At startup, skill names and descriptions are added to the system context
11
+ 3. **Model-Invoked**: When Mentis determines a skill is relevant to your request, it automatically loads the full skill content
12
+ 4. **Progressive Disclosure**: Supporting files are only loaded when explicitly referenced
13
+
14
+ ## Skill Structure
15
+
16
+ ```
17
+ skill-directory/
18
+ ├── SKILL.md # Required: YAML frontmatter + instructions
19
+ ├── reference.md # Optional: Additional documentation
20
+ ├── examples.md # Optional: Usage examples
21
+ ├── scripts/ # Optional: Executable utilities
22
+ │ └── helper.py
23
+ └── templates/ # Optional: File templates
24
+ └── template.txt
25
+ ```
26
+
27
+ ## SKILL.md Format
28
+
29
+ ```yaml
30
+ ---
31
+ name: your-skill-name
32
+ description: What this skill does and when to use it
33
+ allowed-tools: Read, Grep, Glob # Optional: Restrict tools
34
+ ---
35
+
36
+ # Your Skill Name
37
+
38
+ ## Instructions
39
+ Step-by-step guidance for Mentis.
40
+
41
+ ## Examples
42
+ Concrete usage examples.
43
+ ```
44
+
45
+ ### Required Fields
46
+
47
+ - **name**: Lowercase letters, numbers, hyphens only (max 64 characters)
48
+ - **description**: What the skill does + when to use it (max 1024 characters)
49
+
50
+ ### Optional Fields
51
+
52
+ - **allowed-tools**: List of tools the skill can use without permission
53
+
54
+ ## Creating Your First Skill
55
+
56
+ ### Option 1: Interactive Wizard
57
+
58
+ ```
59
+ /skills create
60
+ ```
61
+
62
+ Follow the prompts:
63
+ 1. Enter skill name (e.g., `my-custom-skill`)
64
+ 2. Choose type (personal or project)
65
+ 3. Write description (include "Use when..." for better discovery)
66
+ 4. Optionally restrict allowed tools
67
+
68
+ ### Option 2: Manual Creation
69
+
70
+ ```bash
71
+ # Create directory
72
+ mkdir -p ~/.mentis/skills/my-skill
73
+
74
+ # Create SKILL.md
75
+ cat > ~/.mentis/skills/my-skill/SKILL.md << 'EOF'
76
+ ---
77
+ name: my-skill
78
+ description: Does something useful. Use when the user mentions specific keywords.
79
+ ---
80
+
81
+ # My Skill
82
+
83
+ ## Instructions
84
+ 1. Do this first
85
+ 2. Then do that
86
+
87
+ ## Examples
88
+ Example usage...
89
+ EOF
90
+ ```
91
+
92
+ ## Skill Commands
93
+
94
+ | Command | Description |
95
+ |---------|-------------|
96
+ | `/skills` | List all available skills |
97
+ | `/skills list` | List all available skills |
98
+ | `/skills show <name>` | Display full skill content |
99
+ | `/skills create [name]` | Interactive skill creator |
100
+ | `/skills validate` | Validate all skills for errors |
101
+
102
+ ## Skill Types
103
+
104
+ ### Personal Skills
105
+
106
+ Stored in `~/.mentis/skills/` - available across all projects.
107
+
108
+ **Use for**:
109
+ - Individual workflows and preferences
110
+ - Experimental skills in development
111
+ - Personal productivity tools
112
+
113
+ ### Project Skills
114
+
115
+ Stored in `.mentis/skills/` - shared with your team via git.
116
+
117
+ **Use for**:
118
+ - Team workflows and conventions
119
+ - Project-specific expertise
120
+ - Shared utilities and scripts
121
+
122
+ ## Best Practices
123
+
124
+ ### 1. Write Clear Descriptions
125
+
126
+ ❌ **Too vague**:
127
+ ```yaml
128
+ description: Helps with data
129
+ ```
130
+
131
+ ✅ **Specific**:
132
+ ```yaml
133
+ description: Analyze Excel spreadsheets, generate pivot tables, create charts. Use when working with Excel files, spreadsheets, or .xlsx files.
134
+ ```
135
+
136
+ **Tip**: Include both what the skill does AND when to use it.
137
+
138
+ ### 2. Use Progressive Disclosure
139
+
140
+ Keep `SKILL.md` lean. Move detailed content to supporting files:
141
+
142
+ **SKILL.md**:
143
+ ```markdown
144
+ ## Quick Start
145
+ Basic instructions here.
146
+
147
+ For advanced patterns, see [reference.md](reference.md).
148
+ ```
149
+
150
+ **reference.md**:
151
+ ```markdown
152
+ # Advanced Reference
153
+ Detailed documentation...
154
+ ```
155
+
156
+ ### 3. Validate Your Skills
157
+
158
+ ```
159
+ /skills validate
160
+ ```
161
+
162
+ Check for:
163
+ - Missing required fields
164
+ - Invalid name format
165
+ - Description length
166
+ - Unknown tools in allowed-tools
167
+
168
+ ### 4. Test Skills
169
+
170
+ After creating a skill:
171
+ 1. Restart Mentis to load it
172
+ 2. Ask a question that should trigger the skill
173
+ 3. Verify Mentis loads and uses the skill
174
+
175
+ ## Example Skills
176
+
177
+ ### commit-helper
178
+
179
+ ```yaml
180
+ ---
181
+ name: commit-helper
182
+ description: Generates clear, conventional commit messages from git diffs. Use when writing commit messages or reviewing staged changes.
183
+ allowed-tools: ["GitStatus", "GitDiff", "GitCommit"]
184
+ ---
185
+ ```
186
+
187
+ ### code-reviewer
188
+
189
+ ```yaml
190
+ ---
191
+ name: code-reviewer
192
+ description: Reviews code for best practices, potential bugs, security issues. Use when reviewing code or checking PRs.
193
+ allowed-tools: ["Read", "Grep", "Glob"]
194
+ ---
195
+ ```
196
+
197
+ See `examples/skills/` for complete examples.
198
+
199
+ ## Troubleshooting
200
+
201
+ ### Skill Not Loading
202
+
203
+ **Check 1**: File location
204
+ ```bash
205
+ # Personal skills
206
+ ls ~/.mentis/skills/my-skill/SKILL.md
207
+
208
+ # Project skills
209
+ ls .mentis/skills/my-skill/SKILL.md
210
+ ```
211
+
212
+ **Check 2**: YAML syntax
213
+ ```bash
214
+ # Verify frontmatter format
215
+ cat ~/.mentis/skills/my-skill/SKILL.md | head -n 10
216
+ ```
217
+
218
+ Ensure:
219
+ - `---` on line 1
220
+ - `---` closes frontmatter
221
+ - Valid YAML (no tabs, correct indentation)
222
+
223
+ **Check 3**: Validation
224
+ ```bash
225
+ /skills validate
226
+ ```
227
+
228
+ ### Mentis Not Using Skill
229
+
230
+ **Problem**: Skill exists but Mentis doesn't invoke it.
231
+
232
+ **Solution**: Improve description to include trigger keywords.
233
+
234
+ ❌ **Vague**:
235
+ ```yaml
236
+ description: Code improvement
237
+ ```
238
+
239
+ ✅ **Clear with triggers**:
240
+ ```yaml
241
+ description: Refactor code for better performance and readability. Use when the user mentions optimization, refactoring, performance, or code cleanup.
242
+ ```
243
+
244
+ ### allowed-tools Not Working
245
+
246
+ **Check**: Tool names must match Mentis tool names exactly.
247
+
248
+ Valid tools: `Read`, `Write`, `Edit`, `Grep`, `Glob`, `ListDir`, `SearchFile`, `RunShell`, `WebSearch`, `GitStatus`, `GitDiff`, `GitCommit`, `GitPush`, `GitPull`
249
+
250
+ ## Sharing Skills
251
+
252
+ ### Via Git (Project Skills)
253
+
254
+ ```bash
255
+ # Add to repository
256
+ git add .mentis/skills/
257
+ git commit -m "Add team skill for X"
258
+ git push
259
+
260
+ # Team members get it automatically
261
+ git pull
262
+ # Skill is now available
263
+ ```
264
+
265
+ ### Via Manual Copy
266
+
267
+ ```bash
268
+ # Export
269
+ tar czf my-skill.tar.gz -C ~/.mentis/skills my-skill
270
+
271
+ # Import on another machine
272
+ tar xzf my-skill.tar.gz -C ~/.mentis/skills
273
+ ```
274
+
275
+ ## Advanced Topics
276
+
277
+ ### Code Execution in Skills
278
+
279
+ Skills can include executable scripts:
280
+
281
+ ```markdown
282
+ ## Running the Script
283
+
284
+ ```bash
285
+ python scripts/analyze.py data.csv
286
+ ```
287
+ ```
288
+
289
+ Mentis will execute the script and return results.
290
+
291
+ ### Tool Permissions
292
+
293
+ Use `allowed-tools` to:
294
+ - Restrict read-only skills from making changes
295
+ - Limit scope of specialized skills
296
+ - Add security for sensitive operations
297
+
298
+ ```yaml
299
+ ---
300
+ allowed-tools: ["Read", "Grep", "Glob"]
301
+ ---
302
+ ```
303
+
304
+ When this skill is active, only these tools can be used without explicit permission.
305
+
306
+ ### Dynamic Tool Loading
307
+
308
+ The model can invoke tools to load skills:
309
+
310
+ ```
311
+ load_skill({ name: "pdf-processing" })
312
+ ```
313
+
314
+ This loads the full SKILL.md content into context.
315
+
316
+ ## Resources
317
+
318
+ - [Claude Code Agent Skills](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills) - Official announcement
319
+ - [examples/skills/](../examples/skills/) - Example skills directory
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: code-reviewer
3
+ description: Reviews code for best practices, potential bugs, security issues, and improvements. Use when reviewing code, checking pull requests, or analyzing code quality.
4
+ allowed-tools: ["Read", "Grep", "Glob"]
5
+ ---
6
+
7
+ # Code Reviewer
8
+
9
+ This skill provides systematic code review to identify issues and suggest improvements.
10
+
11
+ ## Review Checklist
12
+
13
+ ### 1. Code Organization
14
+ - [ ] Single Responsibility Principle followed
15
+ - [ ] Clear and descriptive names
16
+ - [ ] Proper separation of concerns
17
+ - [ ] Appropriate abstraction levels
18
+
19
+ ### 2. Error Handling
20
+ - [ ] Proper error handling for all operations
21
+ - [ ] Meaningful error messages
22
+ - [ ] Graceful degradation
23
+ - [ ] No silent failures
24
+
25
+ ### 3. Performance
26
+ - [ ] No obvious performance issues
27
+ - [ ] Appropriate data structures used
28
+ - [ ] Caching where applicable
29
+ - [ ] Resource cleanup (no memory leaks)
30
+
31
+ ### 4. Security
32
+ - [ ] Input validation
33
+ - [ ] No hardcoded credentials
34
+ - [ ] SQL injection prevention
35
+ - [ ] XSS prevention (web apps)
36
+ - [ ] Proper authentication/authorization
37
+
38
+ ### 5. Testing
39
+ - [ ] Test coverage adequate
40
+ - [ ] Edge cases considered
41
+ - [ ] Error scenarios tested
42
+
43
+ ### 6. Documentation
44
+ - [ ] Complex logic explained
45
+ - [ ] Public API documented
46
+ - [ ] Usage examples provided
47
+
48
+ ## How to Review
49
+
50
+ 1. **Understand the purpose**: What is this code supposed to do?
51
+ 2. **Read the code**: Follow the execution flow
52
+ 3. **Check against checklist**: Go through each category
53
+ 4. **Provide feedback**:
54
+ - **Critical**: Must fix before merge
55
+ - **Important**: Should fix
56
+ - **Suggestion**: Nice to have
57
+ 5. **Explain why**: Don't just point out problems
58
+
59
+ ## Feedback Format
60
+
61
+ ```markdown
62
+ ## Critical Issues
63
+ - Issue description
64
+ - Location: file.ts:123
65
+ - Why: [reason]
66
+ - Suggestion: [fix]
67
+
68
+ ## Important Notes
69
+ - Note description
70
+ - Location: file.ts:456
71
+
72
+ ## Suggestions
73
+ - Suggestion description
74
+ - Could improve [aspect]
75
+ ```
76
+
77
+ ## Common Issues to Look For
78
+
79
+ | Issue | Example |
80
+ |-------|---------|
81
+ | Unhandled promises | No `.catch()` or `await` without try/catch |
82
+ | Missing null checks | Accessing properties without null check |
83
+ | Race conditions | Async operations without proper ordering |
84
+ | Resource leaks | File handles, connections not closed |
85
+ | Type coercion | Using `==` instead of `===` |
86
+ | Magic numbers | Unexplained numeric literals |
87
+ | Large functions | Functions > 50 lines |
88
+ | Deep nesting | More than 3 levels of nesting |