Major Changes: - Simplified OpenAgent execution philosophy (universal agent, delegate sparingly) - Reorganized context into 3-tier structure: standards/, workflows/, system/ - Improved approval gate wording for clarity - Enhanced .gitignore with comprehensive Node.js patterns - Added comprehensive plugin development guide Context Reorganization: - Consolidated scattered files into organized structure with Quick Reference sections - Emphasis on lazy loading for token efficiency (60-80% token savings) - New standards: code.md, docs.md, tests.md, patterns.md, analysis.md - New workflows: delegation.md, sessions.md, task-breakdown.md, review.md - New system: context-guide.md (master reference) Delegation Improvements: - Removed complex XML-style routing rules - Simplified to clear when/how structure with 7 delegation criteria - Added Perspective and Simulation as delegation triggers - Clearer delegation template and process Documentation Enhancements: - Added building-plugins.md (1,274 lines - comprehensive plugin guide) - Updated how-context-works.md with research-backed architecture - Enhanced slash-commands-and-subagents.md with path resolution findings Content Preservation: - context-discovery.md → system/context-guide.md + workflows/sessions.md - context-management.md → workflows/sessions.md - essential-patterns.md → standards/patterns.md - session-management.md → workflows/sessions.md
4.2 KiB
Code Standards
Quick Reference
Core Philosophy: Modular, Functional, Maintainable Golden Rule: If you can't easily test it, refactor it
Critical Patterns (use these):
- ✅ Pure functions (same input = same output, no side effects)
- ✅ Immutability (create new data, don't modify)
- ✅ Composition (build complex from simple)
- ✅ Small functions (< 50 lines)
- ✅ Explicit dependencies (dependency injection)
Anti-Patterns (avoid these):
- ❌ Mutation, side effects, deep nesting
- ❌ God modules, global state, large functions
Core Philosophy
Modular: Everything is a component - small, focused, reusable Functional: Pure functions, immutability, composition over inheritance Maintainable: Self-documenting, testable, predictable
Principles
Modular Design
- Single responsibility per module
- Clear interfaces (explicit inputs/outputs)
- Independent and composable
- < 100 lines per component (ideally < 50)
Functional Approach
- Pure functions: Same input = same output, no side effects
- Immutability: Create new data, don't modify existing
- Composition: Build complex from simple functions
- Declarative: Describe what, not how
Component Structure
component/
├── index.js # Public interface
├── core.js # Core logic (pure functions)
├── utils.js # Helpers
└── tests/ # Tests
Patterns
Pure Functions
// ✅ Pure
const add = (a, b) => a + b;
const formatUser = (user) => ({ ...user, fullName: `${user.firstName} ${user.lastName}` });
// ❌ Impure (side effects)
let total = 0;
const addToTotal = (value) => { total += value; return total; };
Immutability
// ✅ Immutable
const addItem = (items, item) => [...items, item];
const updateUser = (user, changes) => ({ ...user, ...changes });
// ❌ Mutable
const addItem = (items, item) => { items.push(item); return items; };
Composition
// ✅ Compose small functions
const processUser = pipe(validateUser, enrichUserData, saveUser);
const isValidEmail = (email) => validateEmail(normalizeEmail(email));
// ❌ Deep inheritance
class ExtendedUserManagerWithValidation extends UserManager { }
Declarative
// ✅ Declarative
const activeUsers = users.filter(u => u.isActive).map(u => u.name);
// ❌ Imperative
const names = [];
for (let i = 0; i < users.length; i++) {
if (users[i].isActive) names.push(users[i].name);
}
Naming
- Files: lowercase-with-dashes.js
- Functions: verbPhrases (getUser, validateEmail)
- Predicates: isValid, hasPermission, canAccess
- Variables: descriptive (userCount not uc), const by default
- Constants: UPPER_SNAKE_CASE
Error Handling
// ✅ Explicit error handling
function parseJSON(text) {
try {
return { success: true, data: JSON.parse(text) };
} catch (error) {
return { success: false, error: error.message };
}
}
// ✅ Validate at boundaries
function createUser(userData) {
const validation = validateUserData(userData);
if (!validation.isValid) {
return { success: false, errors: validation.errors };
}
return { success: true, user: saveUser(userData) };
}
Dependency Injection
// ✅ Dependencies explicit
function createUserService(database, logger) {
return {
createUser: (userData) => {
logger.info('Creating user');
return database.insert('users', userData);
}
};
}
// ❌ Hidden dependencies
import db from './database.js';
function createUser(userData) { return db.insert('users', userData); }
Anti-Patterns
❌ Mutation: Modifying data in place ❌ Side effects: console.log, API calls in pure functions ❌ Deep nesting: Use early returns instead ❌ God modules: Split into focused modules ❌ Global state: Pass dependencies explicitly ❌ Large functions: Keep < 50 lines
Best Practices
✅ Pure functions whenever possible ✅ Immutable data structures ✅ Small, focused functions (< 50 lines) ✅ Compose small functions into larger ones ✅ Explicit dependencies (dependency injection) ✅ Validate at boundaries ✅ Self-documenting code ✅ Test in isolation
Golden Rule: If you can't easily test it, refactor it.