Skip to main content
Glama
QUALITY.md95.2 kB
# Quality Guidelines These are quality guidelines for this package. **THIS IS NOT AN ENTERPRISE REPOSITORY.** This is a small, open-source community project that must remain simple and approachable. Avoid multi-class architectures, dependency injection, abstract factories, and over-engineered solutions that would intimidate contributors or create maintenance burdens. ## AI AGENT CHECKLIST Before proposing any solution, ask: - Does this create a new class in test code? → REJECT - Does this create a new class in production? → ALLOWED - choose appropriate paradigm for the problem - Does this span multiple files? → REJECT - Does this add shared infrastructure or frameworks? → REJECT - Does this maintain backward compatibility? → REJECT - use breaking changes instead - Can this be solved with local variables/functions? → EVALUATE based on context ## CLASS USAGE MATRIX | Context | Classes Allowed | Examples | |---------|----------------|----------| | Type Definitions | ✅ Yes | `interface AuthConfig`, `type TokenResponse` | | Production Logic | ✅ Yes | Business logic classes when appropriate for the domain | | Test Code | ❌ No | Use local variables/arrays | | Shared Infrastructure | ❌ No | Use local constants/functions | ## CONTEXT SEPARATION NOTE **Test restrictions do NOT apply to production code.** The prohibition on classes in test code is to maintain simplicity and prevent test framework over-engineering. Production code should use the most appropriate paradigm for the problem. ## REJECTED PATTERNS (Auto-reject any proposal containing): ❌ `class TestEnvironmentValidator` (test context) ❌ `class TestDataManager` (test context) ❌ `class TestPrerequisites` (test context) ❌ Centralized validation systems ❌ Multi-phase implementation plans ❌ New test infrastructure or frameworks ❌ Over-engineered multi-class architectures ❌ Architectural diagrams or "architectural plans" ❌ Abstractions that would confuse open-source contributors ❌ **Backward compatibility layers or legacy code support** ❌ **Migration utilities that preserve old patterns** ❌ **Wrapper functions for deprecated APIs** ## ENFORCEMENT OF REJECTED PATTERNS **AUTO-REJECT**: Any proposal containing these patterns will be IMMEDIATELY REJECTED without consideration: - Any `class` keyword in test files (T10, T11) - Centralized validation systems (U2) - Multi-phase implementation plans (U2) - New test infrastructure or frameworks (T1, T2) - Over-engineered multi-class architectures (U1) - **Backward compatibility layers or legacy code support (U14)** - **Migration utilities that preserve old patterns (U14)** - **Wrapper functions for deprecated APIs (U14)** ## COMMON AI PITFALLS AI agents commonly misinterpret: - "Helper functions" ≠ "Helper classes" - "Testing standards" ≠ "Testing frameworks" - "Type definitions" ≠ "Class definitions" # DETAILED QUALITY RULES ## UNIVERSAL RULES (Apply to all code) ### U1. Production Paradigm Selection ## Intent Code should use the paradigm (functional vs class-based) that best serves the problem domain without over-engineering, maintaining the project's approachable nature for open-source contributors. ## Category Pattern This encompasses violations where paradigm choice: - Creates unnecessary complexity for the problem being solved - Follows patterns inappropriate for the domain's natural structure - Intimidates contributors with over-engineered abstractions ## Recognition Signals - Signal: Paradigm mismatch with domain characteristics Examples: Classes for pure transformations, functions for stateful business logic But also: Over-abstracted patterns, unnecessary design patterns - Signal: Complexity that doesn't serve the domain Examples: Multiple inheritance levels, abstract factories for simple operations But also: Functional compositions that obscure business logic ## Diverse Examples (Non-Exhaustive) ### Example 1: Appropriate Functional Approach ```typescript // ✅ COMPLIANT: Stateless transformation suits functional approach export function validateEmail(email: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } ``` ### Example 2: Appropriate Class Approach ```typescript // ✅ COMPLIANT: Stateful service benefits from encapsulation export class EmailService { constructor(private readonly transport: Transport) {} async send(message: Message): Promise<void> { /* maintains state and behavior */ } } ``` ### Example 3: Over-Engineering Violation ```typescript // ❌ VIOLATION: Unnecessary abstraction for simple operation abstract class ValidatorFactory { abstract createEmailValidator(): IEmailValidator; } // VIOLATION REASON: Simple validation doesn't need this complexity ``` ## Generalization Guidance Ask yourself: 1. Does this paradigm choice make the code easier to understand and maintain? 2. Would a new contributor immediately understand why this approach was chosen? 3. Does the complexity serve the actual problem domain? **Escalation**: For paradigm selection in complex business domains, consult the architect-reviewer agent. ## Anti-Patterns (What This Rule Does NOT Cover) - Using classes for legitimate business domain modeling - Functional approaches for appropriate transformations - Simple utility functions that don't need state --- ### U2. Critical Constraints ## Intent Development should remain focused on solving specific problems within existing boundaries rather than expanding infrastructure or creating dependencies that burden the community project. ## ABSOLUTE REQUIREMENTS (Non-Negotiable) - **NO CENTRALIZED FRAMEWORKS** or shared infrastructure - **NO CI/CD PIPELINE CHANGES** unless explicitly requested - **IMPLEMENT CHANGES IN EXISTING FILES ONLY** - **USE LOCAL CONSTANTS**, not global configs ## Category Pattern This encompasses violations where changes: - Introduce shared infrastructure that requires maintenance - Create dependencies between previously independent components - Expand the project's operational complexity beyond its community scope ## Recognition Signals - Signal: Infrastructure creation or modification Examples: New build pipelines, shared frameworks, deployment changes But also: Global configuration systems, cross-cutting concerns - Signal: Multi-file solution when local solution exists Examples: Spanning multiple packages, creating new modules for simple problems But also: Shared utilities that could be local functions ## Diverse Examples (Non-Exhaustive) ### Example 1: Constraint Violation - Infrastructure ```typescript // ❌ VIOLATION: Creates shared infrastructure burden class GlobalConfigManager { static configure() { /* manages global state */ } } // VIOLATION REASON: Introduces maintenance burden and coupling ``` ### Example 2: Compliant Local Solution ```typescript // ✅ COMPLIANT: Local solution within existing boundaries function processEmails(emails: Email[], config: ProcessConfig) { // Handles requirements locally without shared infrastructure } ``` ### Example 3: Constraint Violation - Multi-file Expansion ```typescript // ❌ VIOLATION: Creating new files for simple functionality // auth/new-validator.ts, shared/new-utils.ts, config/new-settings.ts // VIOLATION REASON: Could be solved within existing files ``` ## Generalization Guidance Ask yourself: 1. Can this be solved within existing files and boundaries? 2. Does this create new maintenance responsibilities for the community? 3. Would this make the project harder for new contributors to understand? ## Anti-Patterns (What This Rule Does NOT Cover) - Working within existing files to solve problems - Using existing shared utilities that already exist - Local constants and functions within current scope ## U2 CRITICAL CONSTRAINT ENFORCEMENT **ABSOLUTE PROHIBITION**: No recommendations for creating documentation, processes, CI/CD, or shared tooling. **ONLY ALLOWED**: Fix violations within existing files using existing tools. **Escalation**: For infrastructure vs. local solution questions, consult the architect-reviewer agent. ## Enforcement Note **ANY proposal violating the ABSOLUTE REQUIREMENTS will be IMMEDIATELY REJECTED.** --- ### U3. Functional Cohesion in File Organization ## Intent Files should group functionality that consumers would logically expect to find together, making the codebase predictable and maintainable without forcing developers to hunt through multiple files for related operations. ## Category Pattern This encompasses violations where file organization: - Groups unrelated functionality that serves different purposes - Uses generic names that don't indicate the file's specific domain - Forces consumers to import from multiple files for a single logical operation ## Recognition Signals - Signal: Generic utility collections Examples: utils.ts, helpers.ts, common.ts, misc.ts But also: Files named after implementation details rather than purpose - Signal: Functionally unrelated groupings Examples: Authentication + email formatting in same file, database utilities + UI helpers But also: Similar-looking functions that serve completely different use cases ## Diverse Examples (Non-Exhaustive) ### Example 1: Generic Utility Anti-Pattern ```typescript // ❌ VIOLATION: utils.ts - what does this file actually do? export function formatDate(date: Date): string { ... } export function validateEmail(email: string): boolean { ... } export function retryOperation<T>(fn: () => T): Promise<T> { ... } // VIOLATION REASON: Unrelated functions with no cohesive purpose ``` ### Example 2: Purpose-Based Organization ```typescript // ✅ COMPLIANT: email-validation.ts - clear domain export function validateEmailFormat(email: string): boolean { ... } export function normalizeEmailAddress(email: string): string { ... } export function extractEmailDomain(email: string): string { ... } ``` ### Example 3: Migration Approach ```typescript // ✅ COMPLIANT: Move functions to purpose-specific files // Don't duplicate or create backward compatibility - break old references ``` ## Generalization Guidance Ask yourself: 1. If I needed [specific functionality], would I logically look in this file? 2. Do these functions serve the same high-level purpose or domain? 3. Would a new contributor understand this file's scope from its name? **Escalation**: For file naming and grouping decisions, consult the architect-reviewer agent. ## Anti-Patterns (What This Rule Does NOT Cover) - Files with clear, specific purposes even if they have multiple functions - Domain-specific modules that naturally group related operations - Temporary files during active development before final organization --- ### U4. TypeScript API Design ## Intent Public APIs should make valid usage patterns self-evident through type design, reducing runtime errors and improving developer experience through clear interfaces. ## Category Pattern This encompasses violations where API design: - Forces consumers to guess at valid parameter combinations - Allows invalid states to be represented in the type system - Creates confusion about expected usage patterns ## Recognition Signals - Signal: Unclear valid parameter combinations Examples: Optional parameters that are actually required together, union types without clear constraints But also: APIs that accept "any" when specific types would guide usage - Signal: Interface inconsistency across related operations Examples: Similar operations with different parameter patterns, inconsistent naming conventions But also: Type definitions that don't reflect actual usage requirements ## Diverse Examples (Non-Exhaustive) ### Example 1: Self-Evident Interface ```typescript // ✅ COMPLIANT: Valid parameters are clear from types interface EmailConfig { readonly transport: 'smtp' | 'sendmail'; readonly auth: SmtpAuth | SendmailAuth; } ``` ### Example 2: Confusing Optional Parameters ```typescript // ❌ VIOLATION: When is clientId required? interface AuthOptions { provider?: 'google' | 'microsoft'; clientId?: string; scope?: string[]; } // VIOLATION REASON: Valid combinations aren't clear from types ``` ### Example 3: Shared Implementation Pattern ```typescript // ✅ COMPLIANT: Classes implement types-only package interface // @mcpeasy/oauth export interface IAuthProvider { authenticate(options: AuthOptions): Promise<AuthResult>; } // @mcpeasy/oauth-google export class GoogleAuthProvider implements IAuthProvider { authenticate(options: GoogleAuthOptions): Promise<AuthResult> { ... } } ``` ## Generalization Guidance Ask yourself: 1. Can a developer understand valid usage just from the types? 2. Do the types prevent common misuse patterns? 3. Would similar operations have consistent interfaces? ## Anti-Patterns (What This Rule Does NOT Cover) - Complex internal implementations with simple public interfaces - Domain-specific type constraints that serve business logic - Types that accurately reflect inherently complex business rules --- ### U5. Code Lifecycle Management ## Intent The codebase should contain only actively used, non-duplicated code to reduce maintenance burden and prevent confusion about which implementation to use or modify. ## Category Pattern This encompasses violations where code: - Exists but serves no active purpose in the current system - Duplicates functionality that already exists elsewhere - Creates maintenance burden through deprecated or unused artifacts ## Recognition Signals - Signal: Code artifacts with no active consumption Examples: Unused exports, functions with no callers, deprecated files But also: Dead import paths, commented code that should be deleted - Signal: Multiple implementations of the same logical operation Examples: Duplicate utility functions, multiple versions of similar logic But also: Wrapper functions that just re-export library functionality ## Diverse Examples (Non-Exhaustive) ### Example 1: Deprecated File Removal ```typescript // ❌ VIOLATION: File with DEPRECATED comment still exists // src/old-auth.ts // DEPRECATED: Use new auth system instead export function authenticate() { ... } // VIOLATION REASON: Should be deleted, not marked deprecated ``` ### Example 2: Direct Library Usage ```typescript // ❌ VIOLATION: Unnecessary re-export wrapper export { someFunction } from 'third-party-library'; // ✅ COMPLIANT: Import directly from library import { someFunction } from 'third-party-library'; ``` ### Example 3: Duplicate Code Elimination ```typescript // ❌ VIOLATION: Same logic in multiple places // file1.ts: function validateEmail() { ... } // file2.ts: function checkEmailFormat() { ... } // same implementation // VIOLATION REASON: Choose one location and use consistently ``` ## Generalization Guidance Ask yourself: 1. Is this code actively used in the current system? 2. Does this duplicate functionality that exists elsewhere? 3. Would removing this code simplify maintenance without losing functionality? ## Anti-Patterns (What This Rule Does NOT Cover) - Similar functions that serve genuinely different purposes - Code that appears unused but serves critical system functions - Temporary duplication during active refactoring work --- ### U6. Type Safety Over Runtime Guards ## Intent Code should rely on TypeScript's type system to prevent invalid states rather than using runtime checks that indicate missing type safety, improving both performance and developer confidence. ## Category Pattern This encompasses violations where runtime guards: - Protect against conditions that proper typing would prevent - Indicate missing or weak type contracts between components - Create defensive programming patterns that bypass compile-time safety ## Recognition Signals - Signal: Optional chaining where types should guarantee presence Examples: ctx?.google?.auth when ctx should have google.auth guaranteed But also: Excessive null checks for values that types should ensure exist - Signal: Runtime type checking for compile-time type issues Examples: typeof checks for known parameter types, instanceof for typed objects But also: Complex validation logic that types could handle ## Diverse Examples (Non-Exhaustive) ### Example 1: Unnecessary Optional Chaining ```typescript // ❌ VIOLATION: Types should guarantee this structure exists function processAuth(ctx: AuthContext) { if (ctx?.google?.auth) { // Types should make this check unnecessary return ctx.google.auth.token; } } // VIOLATION REASON: AuthContext type should guarantee google.auth exists ``` ### Example 2: Strict Type Contract ```typescript // ✅ COMPLIANT: Types guarantee structure, no guards needed interface AuthContext { readonly google: { readonly auth: GoogleAuth; }; } function processAuth(ctx: AuthContext) { return ctx.google.auth.token; // No guards needed } ``` ### Example 3: Appropriate Error Handling vs Guards ```typescript // ✅ COMPLIANT: Handle legitimate runtime conditions function processApiResponse(response: ApiResponse) { if (response.status === 'error') { // Business logic condition throw new Error(response.message); } return response.data; } ``` ## Generalization Guidance Ask yourself: 1. Should the type system prevent this condition from occurring? 2. Is this guard protecting against a type system failure or a business logic condition? 3. Would better type design eliminate the need for this runtime check? ## Anti-Patterns (What This Rule Does NOT Cover) - Guards for legitimate business logic conditions (API errors, user input validation) - Runtime checks for external data that can't be typed at compile time - Error handling for network conditions and external system failures --- ### U7. Static Import Dependencies ## Intent Module dependencies should be explicit and statically analyzable to enable better tooling, bundling optimization, and dependency understanding without runtime surprises. ## Category Pattern This encompasses violations where imports: - Hide dependencies until runtime execution - Make static analysis and bundling optimization impossible - Create unclear dependency graphs that are hard to reason about ## Recognition Signals - Signal: Runtime-dependent import resolution Examples: await import(), conditional imports based on runtime values But also: Dynamic import paths constructed from variables - Signal: Lazy loading where static imports would work Examples: Dynamic imports for modules that are always needed But also: Conditional imports for code that should be tree-shaken instead ## Diverse Examples (Non-Exhaustive) ### Example 1: Dynamic Import Anti-Pattern ```typescript // ❌ VIOLATION: Dynamic import for always-needed dependency async function processEmail(email: Email) { const { validateEmail } = await import('./email-validator.ts'); return validateEmail(email); } // VIOLATION REASON: email-validator is always needed, should be static ``` ### Example 2: Static Import Pattern ```typescript // ✅ COMPLIANT: Clear, static dependency import { validateEmail } from './email-validator.ts'; function processEmail(email: Email) { return validateEmail(email); } ``` ### Example 3: Legitimate Dynamic Import ```typescript // ✅ COMPLIANT: Truly conditional feature loading async function loadAdvancedFeatures() { if (config.enableAdvancedMode) { const { AdvancedProcessor } = await import('./advanced-features.ts'); return new AdvancedProcessor(); } } ``` ## Generalization Guidance Ask yourself: 1. Are these dependencies always needed when this module runs? 2. Would static analysis tools be able to understand this dependency? 3. Is the dynamic nature serving a real performance or architectural need? ## Anti-Patterns (What This Rule Does NOT Cover) - Dynamic imports for truly optional features or plugins - Conditional loading based on runtime environment capabilities - Lazy loading for large modules that may not be needed --- ### U8. Consistent File Naming ## Intent File names should follow consistent conventions that make them easy to find, sort, and organize within any operating system or tool environment. ## Category Pattern This encompasses violations where file naming: - Uses inconsistent casing conventions within the project - Creates file system compatibility issues across different operating systems - Makes files difficult to locate or organize systematically ## Recognition Signals - Signal: Mixed naming conventions within project Examples: some-file.ts mixed with someFile.ts or some_file.ts But also: Inconsistent patterns for similar file types - Signal: Platform-specific naming issues Examples: Case sensitivity problems, special characters But also: Names that conflict with reserved words or system conventions ## Diverse Examples (Non-Exhaustive) ### Example 1: Consistent Hyphenated Convention ```typescript // ✅ COMPLIANT: Consistent hyphenated naming email-validator.ts auth-provider.ts connection-manager.ts ``` ### Example 2: Mixed Convention Violation ```typescript // ❌ VIOLATION: Inconsistent naming patterns emailValidator.ts auth-provider.ts connection_manager.ts // VIOLATION REASON: Should pick one convention and apply consistently ``` ### Example 3: Migration Approach ```typescript // ✅ COMPLIANT: Rename files and update imports // OLD: authProvider.ts → NEW: auth-provider.ts // Update all import statements, don't copy content ``` ## Generalization Guidance Ask yourself: 1. Does this file name follow the project's established naming convention? 2. Would this name work consistently across different operating systems? 3. Can developers easily predict how to name similar files? ## Anti-Patterns (What This Rule Does NOT Cover) - Following external library or framework naming requirements - Temporary files during active development - Generated files that follow tool-specific conventions --- ### U9. Meaningful Comments ## Intent Comments should provide valuable context that isn't obvious from the code itself, helping maintainers understand decisions and complexity without cluttering the codebase with redundant information. ## Category Pattern This encompasses violations where comments: - State what the code obviously does rather than why or how decisions were made - Become outdated and misleading as code evolves - Add noise without providing valuable context for maintainers ## Recognition Signals - Signal: Self-evident descriptions Examples: // Set variable to true, // Call function with parameter But also: Comments that just restate the function name or obvious operations - Signal: Outdated or incorrect information Examples: Comments that describe old implementations, wrong parameter descriptions But also: TODO comments for completed work, outdated API references ## Diverse Examples (Non-Exhaustive) ### Example 1: Self-Evident Comment Violation ```typescript // ❌ VIOLATION: Comment adds no value // Set isAuthenticated to true const isAuthenticated = true; // ❌ VIOLATION: Just restates the obvious // Loop through emails array for (const email of emails) { ... } // VIOLATION REASON: Code is self-explanatory ``` ### Example 2: Valuable Context Comment ```typescript // ✅ COMPLIANT: Explains non-obvious business logic // Gmail API requires 100ms delay between requests to avoid rate limiting await delay(100); // ✅ COMPLIANT: Documents important constraint // Must validate before processing - invalid emails crash the service if (!isValidEmail(email)) throw new Error('Invalid email format'); ``` ### Example 3: Brief Current Comments ```typescript // ✅ COMPLIANT: Concise explanation of complex logic // Convert OAuth scope array to space-separated string per RFC 6749 const scopeString = scope.join(' '); ``` ## Generalization Guidance Ask yourself: 1. Does this comment explain something that isn't obvious from reading the code? 2. Would a new developer need this information to understand or modify the code safely? 3. Is this comment current and accurate with the existing implementation? ## Anti-Patterns (What This Rule Does NOT Cover) - API documentation comments for public interfaces - Comments explaining complex algorithms or business rules - Temporary debugging comments during active development --- ### U10. Concise Code Formatting ## Intent Code should be formatted consistently and compactly to maximize readability within reasonable line lengths while avoiding unnecessary syntax that doesn't add clarity. ## Category Pattern This encompasses violations where formatting: - Uses unnecessary verbosity that doesn't improve readability - Inconsistently applies formatting rules within the codebase - Creates excessive line breaks or whitespace that reduces information density ## Recognition Signals - Signal: Unnecessary braces for simple statements Examples: Single-line if statements wrapped in braces, simple expressions over-formatted But also: Inconsistent brace usage for similar code patterns - Signal: Excessive line length or unnecessary breaks Examples: Lines that could fit comfortably but are broken arbitrarily But also: Complex expressions that should be broken but aren't ## Generalization Guidance Ask yourself: 1. Does this formatting make the code easier to read and understand? 2. Is the formatting consistent with similar code patterns in the project? 3. Does the line length balance readability with information density? ## Anti-Patterns (What This Rule Does NOT Cover) - Multi-line formatting for genuinely complex expressions - Consistent formatting that follows established project patterns - Breaking lines for readability when expressions are actually complex --- ### U11. Node.js Type Stripping Configuration ## Intent The project should use Node.js built-in TypeScript support to minimize build complexity and external dependencies while maintaining type safety during development. ## Category Pattern This encompasses violations where TypeScript compilation: - Introduces unnecessary build processes or external compilation tools - Creates complex configuration that obscures the simple type-stripping approach - Adds dependencies that Node.js already provides natively ## Recognition Signals - Signal: Complex build processes for TypeScript Examples: webpack configs, babel setups, custom build scripts for TS compilation But also: Build tools that duplicate Node.js native capabilities - Signal: Configuration that doesn't match Node.js type stripping requirements Examples: emit: true, incorrect module resolution settings But also: Configurations that prevent proper ESM module handling ## Diverse Examples (Non-Exhaustive) ### Example 1: Correct Type Stripping Config ```json // ✅ COMPLIANT: Uses Node.js built-in type stripping { "compilerOptions": { "noEmit": true, "target": "esnext", "module": "nodenext", "rewriteRelativeImportExtensions": true, "erasableSyntaxOnly": true, "verbatimModuleSyntax": true } } ``` ### Example 2: Complex Build Process Violation ```json // ❌ VIOLATION: Unnecessary build complexity { "scripts": { "build": "webpack --config webpack.config.js", "compile": "tsc && babel dist --out-dir lib" } } // VIOLATION REASON: Node.js can run TypeScript directly ``` ### Example 3: Incorrect Emit Configuration ```json // ❌ VIOLATION: Conflicting with type-stripping approach { "compilerOptions": { "noEmit": false, "outDir": "dist", "target": "es2020" } } // VIOLATION REASON: Should use noEmit: true for type stripping ``` ## Generalization Guidance Ask yourself: 1. Does this configuration use Node.js native TypeScript capabilities? 2. Are we introducing build complexity that Node.js already handles? 3. Will this configuration work with Node.js type stripping requirements? ## Anti-Patterns (What This Rule Does NOT Cover) - Configurations required for specific deployment environments - Type checking configurations that don't affect runtime - Editor-specific TypeScript configurations --- ### U12. Module Boundary Preservation ## Intent Package boundaries should be respected through explicit imports to maintain clear architectural separation and prevent coupling that would make packages difficult to extract or reuse. ## Category Pattern This encompasses violations where imports: - Bypass package boundaries through relative path traversal - Create implicit coupling between packages that should be independent - Make package extraction or reorganization difficult ## Recognition Signals - Signal: Relative paths between packages Examples: ../other-package/src/file.ts, ../../shared/utils.ts from different packages But also: Direct file system access that bypasses package.json exports - Signal: Internal implementation access across packages Examples: Importing from src/ directories of other packages directly But also: Bypassing public APIs to access private implementation details ## Diverse Examples (Non-Exhaustive) ### Example 1: Relative Path Violation ```typescript // ❌ VIOLATION: Crosses package boundary with relative path // From @mcpeasy/oauth-google/src/client.ts import { helper } from '../../auth-core/src/internal/helper.ts'; // VIOLATION REASON: Should use explicit package import ``` ### Example 2: Explicit Package Import ```typescript // ✅ COMPLIANT: Respects package boundaries // From @mcpeasy/oauth-google/src/client.ts import { AuthHelper } from '@mcpeasy/oauth'; ``` ### Example 3: Internal Package Structure ```typescript // ✅ COMPLIANT: Relative imports within same package // From @mcpeasy/oauth-google/src/client.ts import { validateConfig } from './config-validator.ts'; import { TokenManager } from '../token/manager.ts'; ``` ## Generalization Guidance Ask yourself: 1. Does this import cross package boundaries through the file system? 2. Would this import break if the target package were extracted to a separate repository? 3. Am I accessing a public API or bypassing it to reach internal implementation? ## Anti-Patterns (What This Rule Does NOT Cover) - Relative imports within the same package structure - Importing from packages through their public package.json exports - Dependencies explicitly declared in package.json --- ### U13. TypeScript Type System Preservation ## Intent Code should leverage TypeScript's type system to prevent errors at compile time rather than circumventing type safety, maintaining confidence in code correctness and refactoring safety. ## Category Pattern This encompasses violations where code: - Bypasses TypeScript's type checking through escape hatches without justification - Uses patterns that eliminate compile-time error detection - Creates situations where types lie about runtime behavior ## Recognition Signals - Signal: Type system escape hatches without clear justification Examples: any types, type assertions (as SomeType), @ts-ignore directives But also: Non-null assertions (!) where types should guarantee non-null - Signal: Types that don't match runtime behavior Examples: Interface definitions that don't reflect actual data structure But also: Optional properties that are actually always present **Escalation**: For complex typing scenarios not covered in documentation, consult the `typescript-pro` agent. ## Diverse Examples (Non-Exhaustive) ### Example 1: Unjustified Type Escape ```typescript // ❌ VIOLATION: Using 'any' instead of proper typing function processApiResponse(response: any): UserData { return response.user; // No type safety } // VIOLATION REASON: Should type the response structure ``` ### Example 2: Proper Type Definition ```typescript // ✅ COMPLIANT: Leverages type system for safety interface ApiResponse { readonly user: UserData; readonly status: 'success' | 'error'; } function processApiResponse(response: ApiResponse): UserData { return response.user; // Type safe } ``` ### Example 3: Justified Type Assertion ```typescript // ✅ COMPLIANT: Type assertion with clear justification // We know this is HTMLInputElement because we just created it const input = document.createElement('input') as HTMLInputElement; ``` ## Generalization Guidance Ask yourself: 1. Does this preserve TypeScript's ability to catch errors at compile time? 2. Is there a type-safe way to express this pattern? 3. Would someone reading this code understand why type safety was bypassed? **Escalation**: For complex typing scenarios not covered in documentation, consult the `typescript-pro` agent. ## Anti-Patterns (What This Rule Does NOT Cover) - Type assertions for legitimate compiler limitations - Using any for genuinely dynamic content from external sources - Temporary type escapes during active migration work --- ### U14. Breaking Changes Over Compatibility ## ABSOLUTE REQUIREMENT (Non-Negotiable) **NO BACKWARD COMPATIBILITY** - This project does not have customers yet. All changes must be breaking changes that eliminate old patterns completely. ## Intent Code should evolve cleanly through breaking changes rather than maintaining backward compatibility layers that create complexity and technical debt. Since this is a pre-customer project, we prioritize clean architecture over compatibility. ## STRICT ENFORCEMENT **IMMEDIATELY REJECT any proposal that**: - Maintains old API signatures alongside new ones - Creates migration paths or transition periods - Adds feature flags for gradual rollouts - Preserves deprecated patterns "for compatibility" - Suggests "we can support both approaches" ## Category Pattern This encompasses violations where changes: - Add compatibility layers to support old APIs or data formats - Create migration paths that maintain multiple ways of doing the same thing - Preserve deprecated patterns that should be eliminated - Suggest gradual transitions instead of clean breaks ## Recognition Signals - Signal: Backward compatibility preservation Examples: Supporting both old and new API signatures, data migration utilities But also: Deprecated function wrappers, version detection logic - Signal: Gradual migration complexity Examples: Feature flags for new behavior, dual implementation paths But also: Migration utilities that preserve old state - Signal: "Support both" language Examples: "We can support both old and new formats", "Let's maintain compatibility while..." But also: Any suggestion of maintaining multiple code paths for the same functionality ## Diverse Examples (Non-Exhaustive) ### Example 1: Clean Breaking Change ```typescript // ✅ COMPLIANT: Clean API evolution // OLD: function authenticate(user, pass) // NEW: function authenticate(credentials: credentials) function authenticate(credentials: credentials): Promise<AuthResult> { // Single implementation, no backward compatibility } ``` ### Example 2: Compatibility Layer Violation ```typescript // ❌ VIOLATION: Maintains old API for compatibility function authenticate( userOrCredentials: string | credentials, password?: string ): Promise<AuthResult> { // Complex logic to support both old and new patterns } // VIOLATION REASON: Should break cleanly to new pattern ``` ### Example 3: Migration Utility Violation ```typescript // ❌ VIOLATION: Creates migration path that preserves old patterns function migrateOldConfig(oldConfig: LegacyConfig): NewConfig { // Don't do this - just regenerate from scratch } // VIOLATION REASON: Delete old data, regenerate with new format ``` ### Example 4: Data Format Evolution ```typescript // ✅ COMPLIANT: Generate new data to new format // Delete existing user.json files - don't migrate them // Regenerate tokens with new structure when needed const tokenData = { version: 2, // New format only accessToken: token.access, expiresAt: token.expires }; ``` ### Example 5: API Breaking Change ```typescript // ✅ COMPLIANT: Clean break to new API // OLD: authenticate(username, password) // NEW: authenticate(credentials) function authenticate(credentials: credentials): Promise<AuthResult> { // Single implementation - no backward compatibility // Update all callers to use new signature } ``` ## Generalization Guidance Ask yourself: 1. Does this change require maintaining multiple ways of doing the same thing? 2. Would it be simpler to break cleanly and regenerate/recreate affected data? 3. Is backward compatibility adding complexity that burdens the community project? ## Anti-Patterns (What This Rule Does NOT Cover) - Clean API evolution that doesn't maintain compatibility layers - Supporting external standards that require specific formats - Temporary duplication during active migration work --- ### U15. Environment Variable Extraction Boundaries ## Intent Environment variables should be extracted predictably at system boundaries to make configuration dependencies explicit, with conditional extraction allowed only when runtime configuration determines which variable set applies. ## Category Pattern This encompasses violations where environment variable extraction: - Occurs unpredictably throughout library code rather than at clear boundaries - Hides configuration requirements behind defaults or optional parameters - Bypasses the principle except when configuration legitimately determines variable sets ## Recognition Signals - Signal: Environment access scattered throughout codebase Examples: process.env in utility functions, middleware accessing ENV directly But also: Configuration spread across multiple modules, implicit environment coupling - Signal: Non-deterministic extraction patterns Examples: Optional parameters with env defaults, lazy environment access But also: Environment variables accessed on demand rather than at startup - Signal: Legitimate conditional extraction pattern Examples: Feature flags determining which configuration variables to load But also: Environment-based feature flags that load different configurations ## Diverse Examples (Non-Exhaustive) ### Example 1: Top-Level Extraction Pattern ```typescript // ✅ COMPLIANT: Extract all env vars at entry point const API_KEY = requiredEnv('API_KEY'); const DB_HOST = requiredEnv('DB_HOST'); // Pass as explicit parameters to functions ``` ### Example 2: Scattered Extraction Violation ```typescript // ❌ VIOLATION: Hidden environment dependency function queryDatabase() { const host = process.env.DB_HOST; // Unpredictable extraction } // VIOLATION REASON: Should receive config explicitly ``` ### Example 3: Legitimate Conditional Pattern ```typescript // ✅ COMPLIANT: Configuration determines variable set const STORAGE_MODE = requiredEnv('STORAGE_MODE'); const config = STORAGE_MODE === 'file' ? { path: requiredEnv('FILE_PATH') } : { uri: requiredEnv('DATABASE_URI') }; ``` ## Generalization Guidance Ask yourself: 1. Are environment variables extracted predictably at system boundaries? 2. Does conditional extraction serve a legitimate configuration-driven purpose? 3. Would configuration dependencies be obvious to someone reading the code? **Context**: Universal **Escalation**: For complex environment patterns and Docker/MCP configurations, consult the architect agent for environment.md guidance. ## Anti-Patterns (What This Rule Does NOT Cover) - Top-level extraction at entry points (always acceptable) - Conditional extraction based on configuration mode (feature flag pattern) - Explicit configuration objects passed through the system --- ### U16. Fix Root Issues Over Ignoring ## Fixed Requirement **Fix underlying issues instead of using "// biome-ignore" comments.** ## Intent Code quality issues should be resolved at their source rather than suppressed through tool directives, ensuring the codebase maintains consistent standards and doesn't accumulate technical debt. ## Category Pattern This encompasses violations where quality tools: - Are silenced through ignore directives rather than fixing underlying issues - Accumulate exceptions that indicate systematic problems - Create inconsistent code quality across the codebase ## Recognition Signals - Signal: Tool ignore directives instead of fixes Examples: // biome-ignore, // eslint-disable, @ts-ignore without clear justification But also: Accumulated exceptions that suggest tooling misconfiguration - Signal: Suppressing legitimate quality concerns Examples: Disabling rules that catch real issues, ignoring performance warnings But also: Using ignore directives as shortcuts during development ## Diverse Examples (Non-Exhaustive) ### Example 1: Fixing Instead of Ignoring ```typescript // ❌ VIOLATION: Suppressing instead of fixing // biome-ignore lint/complexity/noExtraBooleanCast: needed for truthy check if (!!isAuthenticated) { ... } // ✅ COMPLIANT: Fix the underlying issue if (isAuthenticated) { ... } ``` ### Example 2: Legitimate Tool Configuration ```typescript // ✅ COMPLIANT: Configuration-level adjustment when appropriate // biome.json - project-wide rule adjustment for valid architectural reasons { "rules": { "complexity": { "noExtraBooleanCast": "off" } } } ``` ### Example 3: Temporary Development Exceptions ```typescript // ✅ COMPLIANT: Justified temporary exception during development // TODO: Implement proper type definition for external API const response = await fetch(url) as any; // Will be typed when API contract is stable ``` ## Generalization Guidance Ask yourself: 1. Does this ignore directive address a real architectural need or avoid fixing a fixable issue? 2. Could this be resolved through proper implementation rather than suppression? 3. Would fixing this issue improve overall code quality? ## Anti-Patterns (What This Rule Does NOT Cover) - Justified exceptions for external library compatibility issues - Project-wide configuration changes for valid architectural reasons - Temporary exceptions during active development with clear resolution plans --- ### U17. Focused Public APIs ## Intent Packages should export only the functionality that external consumers actually need, keeping APIs small and focused to reduce maintenance burden and prevent unintended coupling. ## Category Pattern This encompasses violations where exports: - Include internal utilities or implementation details not meant for external use - Create convenience aliases that duplicate functionality - Export everything "just in case" rather than based on actual usage ## Recognition Signals - Signal: Exporting internal implementation details Examples: Helper functions meant for internal use, configuration objects, debug utilities But also: Intermediate types or interfaces that consumers shouldn't directly use - Signal: Convenience exports that duplicate functionality Examples: Re-exporting third-party libraries, alias functions that just wrap other exports But also: Multiple ways to access the same functionality ## Diverse Examples (Non-Exhaustive) ### Example 1: Focused Export ```typescript // ✅ COMPLIANT: Only export what consumers need export { authenticate } from './auth.ts'; export { type AuthConfig, type AuthResult } from './types.ts'; ``` ### Example 2: Over-Exporting Violation ```typescript // ❌ VIOLATION: Exporting internal utilities export { authenticate } from './auth.ts'; export { validateConfig } from './internal/config-validator.ts'; // Internal detail export { debugLogger } from './utils/debug.ts'; // Development utility export { retryWithBackoff } from './utils/retry.ts'; // Generic utility // VIOLATION REASON: Consumers don't need internal implementation details ``` ### Example 3: Convenience Re-export Violation ```typescript // ❌ VIOLATION: Unnecessary convenience wrapper export { fetch } from 'node-fetch'; // Just use the library directly export const httpClient = fetch; // Alias serves no purpose // VIOLATION REASON: Consumers should import from original library ``` ## Generalization Guidance Ask yourself: 1. Do external consumers actually need this functionality? 2. Is this exposing implementation details that might change? 3. Does this export add value or just create alternative ways to do the same thing? ## Anti-Patterns (What This Rule Does NOT Cover) - Exporting legitimate public API functions and types - Essential utilities that multiple consumers genuinely need - Type definitions required for API contracts --- ### U18. Simplified Package Exports ## Intent Package exports should remain simple with a single main export unless the package serves genuinely distinct domains, avoiding complexity that fragments related functionality. ## Package Export Requirements ✅ **ALLOWED**: Main export only: `"exports": { ".": { "import": "./src/index.ts" } }` ❌ **FORBIDDEN**: Single-purpose exports: "./auth", "./client", "./types" for functionality that belongs in main export **Exception criteria**: Additional exports allowed ONLY when: 1. Package serves 2+ completely separate use cases (e.g., client + server) 2. AND consuming packages would import fundamentally different functionality 3. AND tree-shaking benefit is significant (>50% code reduction) ## Category Pattern This encompasses violations where package exports: - Create artificial separation of functionality that belongs together - Fragment APIs that consumers would naturally use as a unit - Add complexity without meaningful architectural or performance benefits ## Recognition Signals - Signal: Multiple exports for single-purpose functionality Examples: Separate /auth, /client, /types exports for one authentication system But also: Splitting related operations across different export paths - Signal: Exports that don't meet distinct domain criteria Examples: Convenience paths that don't serve fundamentally different use cases But also: Exports that provide minimal tree-shaking benefit ## Diverse Examples (Non-Exhaustive) ### Example 1: Simple Main Export ```json // ✅ COMPLIANT: Single main export for focused package { "exports": { ".": { "import": "./src/index.ts" } } } ``` ### Example 2: Unnecessary Export Fragmentation ```json // ❌ VIOLATION: Artificial separation of related functionality { "exports": { ".": { "import": "./src/index.ts" }, "./auth": { "import": "./src/auth.ts" }, "./client": { "import": "./src/client.ts" }, "./types": { "import": "./src/types.ts" } } } // VIOLATION REASON: Auth, client, and types are part of one system ``` ### Example 3: Legitimate Multiple Domains ```json // ✅ COMPLIANT: Genuinely distinct domains with significant tree-shaking benefit { "exports": { ".": { "import": "./src/index.ts" }, "./server": { "import": "./src/server/index.ts" }, "./client": { "import": "./src/client/index.ts" } } } // Different deployment environments, >50% code reduction ``` ## Generalization Guidance Ask yourself: 1. Do these exports serve fundamentally different use cases or deployment environments? 2. Would consumers typically import from multiple exports for a single feature? 3. Does the separation provide meaningful tree-shaking benefit (>50% code reduction)? ## Anti-Patterns (What This Rule Does NOT Cover) - Single main exports that include all package functionality - Legitimate separation for server vs client deployment environments - Exports that provide significant performance benefits through code splitting --- ### U19. TypeScript Module Extensions ## Intent Internal imports should use .ts extensions to work correctly with Node.js type stripping and modern module resolution without requiring build steps. ## Category Pattern This encompasses violations where imports: - Use extension patterns that don't work with Node.js native TypeScript support - Create module resolution ambiguity that requires build tooling to resolve - Prevent proper ESM module handling in Node.js environment ## Recognition Signals - Signal: Missing or incorrect extensions for TypeScript files Examples: import './module' without .ts, import './file.js' for TypeScript sources But also: Inconsistent extension usage across the project - Signal: Extension patterns that break Node.js type stripping Examples: Extensions that require transformation, paths that don't resolve correctly But also: Import patterns that work only with specific build tools ## Diverse Examples (Non-Exhaustive) ### Example 1: Correct TypeScript Extensions ```typescript // ✅ COMPLIANT: .ts extensions for internal TypeScript imports import { validateEmail } from './email-validator.ts'; import { AuthProvider } from '../auth/provider.ts'; import { type UserData } from './types.ts'; ``` ### Example 2: Missing Extension Violation ```typescript // ❌ VIOLATION: Missing extension breaks Node.js module resolution import { validateEmail } from './email-validator'; // No extension import { AuthProvider } from '../auth/provider'; // No extension // VIOLATION REASON: Node.js type stripping requires explicit .ts extensions ``` ### Example 3: External Package Imports ```typescript // ✅ COMPLIANT: External packages don't need extensions import { someFunction } from '@mcpeasy/some-module'; import { fetch } from 'node-fetch'; ``` ## Generalization Guidance Ask yourself: 1. Will this import work with Node.js native TypeScript type stripping? 2. Does this import require build tooling to resolve correctly? 3. Is the extension consistent with the project's TypeScript setup? ## Anti-Patterns (What This Rule Does NOT Cover) - Imports from external npm packages (no extensions needed) - Standard library imports that follow Node.js conventions - Dynamic imports that follow different resolution rules --- ### U20. Local-First Solutions ## Intent Problems should be solved with local, contained solutions rather than shared infrastructure, keeping the community project approachable and avoiding maintenance burdens that span multiple files or systems. ## Category Pattern This encompasses violations where solutions: - Create shared infrastructure when local solutions would work - Add complexity that spans multiple files for problems solvable locally - Introduce dependencies or abstractions that burden the community project ## Recognition Signals - Signal: Multi-file solutions for single-file problems Examples: Creating utilities, helpers, or shared modules for simple operations But also: Abstractions that serve only one or two call sites - Signal: Infrastructure creation for simple problems Examples: Configuration systems, shared state management, centralized utilities But also: Frameworks or patterns that require understanding across multiple areas ## Diverse Examples (Non-Exhaustive) ### Example 1: Local Variable Solution ```typescript // ✅ COMPLIANT: Simple local solution function processEmails(emails: Email[]) { const results: ProcessResult[] = []; // Local tracking for (const email of emails) { const result = processOne(email); results.push(result); } return results; } ``` ### Example 2: Over-Engineered Infrastructure Violation ```typescript // ❌ VIOLATION: Creates shared infrastructure for simple problem // shared/result-tracker.ts export class ResultTracker { private results: Map<string, ProcessResult> = new Map(); track(id: string, result: ProcessResult) { ... } getResults(): ProcessResult[] { ... } } // VIOLATION REASON: Simple local array would suffice ``` ### Example 3: Appropriate Containment ```typescript // ✅ COMPLIANT: Solve within current context function authenticateUser(credentials: Credentials) { // Local validation logic here instead of shared validator system if (!credentials.username || !credentials.password) { throw new Error('Username and password required'); } return authenticate(credentials); } ``` ## Generalization Guidance Ask yourself: 1. Can this be solved within the current file with local variables or functions? 2. Would a shared solution create maintenance burden for future contributors? 3. Is the complexity of a shared solution justified by the problem size? ## Anti-Patterns (What This Rule Does NOT Cover) - Using existing shared utilities that already exist in the codebase - Local solutions that genuinely need to be shared across many files - Domain logic that naturally requires coordination across components --- ### U21. Standard Development Automation ## Intent Code quality should be maintained through automated tooling that runs consistently, catching issues early and maintaining consistent formatting and dependency health across the project. ## Category Pattern This encompasses violations where automation: - Isn't run regularly, allowing quality issues to accumulate - Fails silently without addressing underlying issues - Creates inconsistent code standards across different parts of the project ## Recognition Signals - Signal: Inconsistent formatting or style across files Examples: Mixed indentation, inconsistent import ordering, variable formatting patterns But also: Outdated dependencies, unused packages, inconsistent package.json formatting - Signal: Quality tool failures that aren't addressed Examples: Lint errors that are ignored, dependency warnings that accumulate But also: Format differences that suggest tools aren't being run ## Diverse Examples (Non-Exhaustive) ### Example 1: Standard Automation Commands ```bash # ✅ COMPLIANT: Run these commands regularly and fix all errors tsds validate ``` ### Example 2: Ignoring Tool Output Violation ```typescript // ❌ VIOLATION: Letting automation failures accumulate // Format command shows differences but they're not applied // Depcheck shows unused dependencies but they're not removed // VIOLATION REASON: Automation is only valuable if issues are fixed ``` ### Example 3: Consistent Quality Standards ```typescript // ✅ COMPLIANT: All files follow same formatting and dependency standards // No mixed styles, no unused imports, dependencies up to date ``` ## Generalization Guidance Ask yourself: 1. Are these automation tools being run regularly to maintain quality? 2. When tools report issues, are those issues being fixed rather than ignored? 3. Does the codebase show consistent application of quality standards? ## Anti-Patterns (What This Rule Does NOT Cover) - Running automation tools that are properly configured for the project - Addressing legitimate tool failures through proper fixes - Maintaining consistent quality standards across the codebase --- ### U22. MCP Stdio Communication Integrity ## Intent MCP (Model Context Protocol) servers must maintain clean stdio communication channels for JSON-RPC protocol compliance, preventing console output that corrupts protocol messages and breaks client-server communication. ## Category Pattern This encompasses violations where code: - Outputs to console streams that interfere with MCP JSON-RPC communication - Uses console fallbacks that corrupt stdio transport - Creates debug or warning output outside proper logging channels ## Recognition Signals - Signal: Console output in MCP server code Examples: console.log(), console.warn(), console.error() in production code But also: console casting as logger (console as unknown as Logger) - Signal: Fallback patterns that bypass logger Examples: logger?.warn() || console.warn(), conditional console usage But also: Debug output that doesn't respect MCP transport requirements ## Diverse Examples (Non-Exhaustive) ### Example 1: Proper Logger Usage ```typescript // ✅ COMPLIANT: Use logger without console fallbacks function processQuery(query: string, logger: Logger) { if (pageSize !== safePageSize && logger) { logger.warn('Page size bounded for API safety', { requested: pageSize, applied: safePageSize }); // No fallback to console - would corrupt MCP stdio communication } } ``` ### Example 2: Console Output Violation ```typescript // ❌ VIOLATION: Console output corrupts MCP JSON-RPC protocol function buildQuery(params: QueryParams) { if (params.invalid) { console.warn(`Invalid parameter: ${params.invalid}`); // Breaks MCP stdio } } // VIOLATION REASON: Console output interferes with JSON-RPC protocol ``` ### Example 3: Console Casting Violation ```typescript // ❌ VIOLATION: Console casting bypasses proper logging const log = (logger ?? (console as unknown as Logger)) as Logger; log.warn('Something happened'); // Corrupts stdio if logger is undefined // VIOLATION REASON: Should use conditional logging instead ``` ## Generalization Guidance Ask yourself: 1. Does this output go to console streams that could interfere with MCP communication? 2. Is there a fallback to console when logger is unavailable? 3. Would this code work correctly in an MCP stdio transport environment? ## Anti-Patterns (What This Rule Does NOT Cover) - Proper logger usage with conditional checks - Debug output in development tools that don't use MCP transport - Test output that explicitly doesn't use MCP stdio communication --- ### U23. Defensive Code Pattern Boundaries ## Intent Code should implement security measures and error handling for real threats while avoiding theoretical defensive patterns that add complexity without addressing actual risk vectors in the deployment context. ## Category Pattern This encompasses violations where defensive patterns: - Solve theoretical attack vectors that don't apply to the actual deployment context - Implement rate limiting or retry workarounds for provider API quotas - Create retry logic for failure modes that should fail fast ## Recognition Signals - Signal: Rate limiting or quota workarounds Examples: Per-process rate limiting, retry logic for 429 responses, artificial delays to "avoid" quotas Principle: Don't implement workarounds - analyze the situation and consult with humans before implementing solutions - Signal: Defensive patterns without clear threat model Examples: Authentication rate limiting for AI agents with valid credentials, complex error handling for scenarios that should fail fast Principle: Address real threats in the actual deployment context ## Diverse Examples (Non-Exhaustive) ### Example 1: Legitimate Rate Limit Detection ```typescript // ✅ COMPLIANT: Detect and classify rate limit errors appropriately function handleApiError(error: ApiError): never { if (error.status === 429) { throw new RateLimitError('API rate limit exceeded', error); } throw error; } ``` ### Example 2: Prohibited Rate Limit Workaround ```typescript // ❌ VIOLATION: Implementing rate limit workarounds class TokenRateLimiter { private requests = new Map<string, number>(); async checkLimit(clientId: string): Promise<boolean> { const count = this.requests.get(clientId) || 0; if (count > 60) return false; // Don't implement artificial limits this.requests.set(clientId, count + 1); return true; } } // VIOLATION REASON: Don't implement workarounds - analyze and consult humans ``` ### Example 3: Prohibited Retry Logic ```typescript // ❌ VIOLATION: Retrying rate limit errors async function requestWithRetry(request: () => Promise<Response>): Promise<Response> { try { return await request(); } catch (error) { if (error.status === 429) { await delay(1000); return requestWithRetry(request); // Don't retry rate limits } throw error; } } // VIOLATION REASON: Fail fast on 429 - don't implement workarounds ``` ### Example 4: Appropriate Network Retry ```typescript // ✅ COMPLIANT: Retry transient errors, fail fast on rate limits async function requestWithBackoff(request: () => Promise<Response>): Promise<Response> { try { return await request(); } catch (error) { if (error.status === 429) { throw error; // Fail fast - let caller handle appropriately } if (error.status >= 500) { await exponentialBackoff(); return requestWithBackoff(request); // Network errors can recover } throw error; } } ``` ## Generalization Guidance When encountering rate limiting or quota issues: 1. Do NOT implement workarounds (delays, retries, artificial limits) 2. Analyze the actual usage patterns and error frequency 3. Consult with humans before implementing any solution 4. Request quota increases from providers if needed When evaluating defensive patterns: - Identify the actual threat model and deployment context - Only implement defenses for real, applicable threats - Fail fast on errors that should not be retried - Consult with humans before adding complex error handling ## Anti-Patterns (What This Rule Does NOT Cover) - Rate limit detection and error classification (always appropriate) - Network retry for 5xx errors that can recover - Authentication and input validation for actual security threats --- ## TEST CODE RULES (Apply only to test/ files) ### T1. Real Service Integration Testing ## Intent Tests should surface real issues by integrating with actual services rather than hiding problems behind mocks, enabling quick identification and resolution of root causes. ## Category Pattern This encompasses violations where tests: - Hide real service issues behind simulation layers - Create false confidence through mocked behavior that doesn't match reality - Prevent discovery of integration problems that would occur in production ## Recognition Signals - Signal: Artificial service simulation Examples: Mock HTTP responses, stubbed API calls, dryRun modes that skip real operations But also: Test doubles that don't reflect actual service behavior - Signal: Error suppression that hides real issues Examples: try/catch blocks that silence legitimate API errors But also: Compatibility layers that work around real service problems ## Diverse Examples (Non-Exhaustive) ### Example 1: Real API Integration ```typescript // ✅ COMPLIANT: Test calls real Gmail API test('create and delete label', async () => { const gmail = await createGmailClient(); const label = await gmail.labels.create({ name: 'test-label-' + Date.now() }); expect(label.id).toBeTruthy(); await gmail.labels.delete({ id: label.id }); }); ``` ### Example 2: Mock API Violation ```typescript // ❌ VIOLATION: Mock hides real service behavior const mockGmail = { labels: { create: jest.fn().mockResolvedValue({ id: 'fake-id' }), delete: jest.fn().mockResolvedValue({}) } }; // VIOLATION REASON: Doesn't test real API integration ``` ### Example 3: Error Suppression Violation ```typescript // ❌ VIOLATION: Hiding legitimate API errors test('gmail operations', async () => { try { await gmail.labels.create({ name: 'test' }); } catch (error) { // Silently ignore errors instead of investigating console.log('Ignoring API error'); } }); // VIOLATION REASON: Should investigate and fix root cause ``` ## Generalization Guidance Ask yourself: 1. Does this test verify real service behavior or simulated behavior? 2. Would this test catch issues that would occur when using real services? 3. Are errors being properly investigated rather than worked around? ## Anti-Patterns (What This Rule Does NOT Cover) - Testing internal logic that doesn't require external services - Using real services with proper cleanup and isolation - Investigating and fixing errors rather than suppressing them --- ### T2. Local Test Data Management ## Intent Test data should be managed locally and cleaned up reliably without creating testing infrastructure that becomes a maintenance burden or obscures test logic. ## Category Pattern This encompasses violations where test data management: - Creates abstraction layers that hide what tests actually do - Introduces shared state or dependencies between tests - Makes tests harder to understand, debug, or run in isolation ## Recognition Signals - Signal: Test abstraction that hides operations Examples: TestDataManager classes, cleanup frameworks, shared test state But also: Helper functions that do too much, test utilities that maintain state - Signal: Cross-test dependencies or shared lifecycle Examples: Global cleanup hooks, shared test databases, test data that persists But also: Tests that depend on execution order, cleanup that affects other tests ## Diverse Examples (Non-Exhaustive) ### Example 1: Simple Local Management ```typescript // ✅ COMPLIANT: Local, visible, simple tracking test('email operations', async () => { const createdEmails: string[] = []; try { const email = await api.createEmail({ subject: 'test' }); createdEmails.push(email.id); // Test logic is visible and clear } finally { for (const id of createdEmails) await api.deleteEmail(id); } }); ``` ### Example 2: Over-Abstracted Management Violation ```typescript // ❌ VIOLATION: Creates testing framework complexity class TestEmailManager { private created: Set<string> = new Set(); async createTestEmail(): Promise<Email> { const email = await api.createEmail({ subject: 'test' }); this.created.add(email.id); return email; } async cleanup() { /* complex cleanup logic */ } } // VIOLATION REASON: Hides what tests actually do ``` ### Example 3: Acceptable Helper Function ```typescript // ✅ COMPLIANT: Focused utility in test/lib/, no hidden state // test/lib/email-helpers.ts export async function createTempEmail(api: EmailAPI, subject: string): Promise<Email> { return api.createEmail({ subject, labels: ['temp-test'] }); } ``` ## Generalization Guidance Ask yourself: 1. Can I understand what this test does just by reading the test function? 2. Would this test still work if copied to a different file? 3. Does the cleanup/management add clarity or hide important operations? ## Anti-Patterns (What This Rule Does NOT Cover) - Simple helper functions for common operations (create/delete, wait/poll) - Local arrays and variables for tracking test data - Self-contained tests that manage their own lifecycle --- ### T3. One-to-One Test File Mapping ## Intent Test organization should mirror source code structure to make it easy to find tests for any given functionality and ensure comprehensive coverage without navigation complexity. ## Category Pattern This encompasses violations where test organization: - Scatters tests for one source file across multiple test files - Groups unrelated tests based on arbitrary organizational schemes - Makes it difficult to find or run tests for specific functionality ## Recognition Signals - Signal: Multiple test files for one source file Examples: auth.test.ts, auth-validation.test.ts, auth-errors.test.ts for one auth.ts But also: Test files organized by test type rather than source code structure - Signal: Mixed functionality tests in single files Examples: Testing multiple unrelated source files in one test file But also: Organizational schemes that don't match source structure ## Diverse Examples (Non-Exhaustive) ### Example 1: One-to-One Mapping ```typescript // ✅ COMPLIANT: Clear mapping between source and tests // src/email-validator.ts → test/email-validator.test.ts // src/auth/provider.ts → test/auth/provider.test.ts ``` ### Example 2: Scattered Test Files Violation ```typescript // ❌ VIOLATION: Multiple test files for one source file // src/auth.ts maps to: // test/auth-basic.test.ts // test/auth-errors.test.ts // test/auth-integration.test.ts // VIOLATION REASON: Should use describe blocks in one file ``` ### Example 3: Proper Test Organization ```typescript // ✅ COMPLIANT: Use describe blocks for scenarios // test/auth.test.ts describe('Authentication', () => { describe('basic auth flow', () => { ... }); describe('error handling', () => { ... }); describe('integration scenarios', () => { ... }); }); ``` ## Generalization Guidance Ask yourself: 1. Is there a clear, predictable mapping between source files and test files? 2. Can I easily find all tests for a specific piece of functionality? 3. Would someone looking for tests know exactly which file to check? ## Anti-Patterns (What This Rule Does NOT Cover) - Using describe blocks to organize scenarios within a single test file - Having one test file per source file even if some source files have no tests - Clear mapping that follows source code structure --- ### T4. Consistent Test Dependencies and Patterns ## Intent Tests should use consistent patterns for setup and dependencies, making it easy for contributors to understand and maintain test code across the project. ## Category Pattern This encompasses violations where tests: - Use inconsistent setup patterns that make tests hard to understand - Don't follow established project conventions for test dependencies - Create confusion about how to structure new tests ## Recognition Signals - Signal: Mixed test setup patterns Examples: Some tests use createMiddleware(), others use different setup approaches But also: Inconsistent patterns for similar test scenarios - Signal: Weak typing in test code Examples: Using any types, untyped test data, missing type assertions But also: Test patterns that don't leverage TypeScript's type safety ## Diverse Examples (Non-Exhaustive) ### Example 1: Consistent Context Creation ```typescript // ✅ COMPLIANT: Uses established createMiddleware() pattern test('tool operations', async () => { const middleware = await createMiddleware(); const tool = createTool(); const wrappedTool = middleware.withToolAuth(tool); // Strongly typed middleware with all necessary setup }); ``` ### Example 2: Inconsistent Setup Violation ```typescript // ❌ VIOLATION: Different test uses ad-hoc setup test('tool operations', async () => { const config = { clientId: 'test', secret: 'test' }; // Manual setup const client = new Client(config); // VIOLATION REASON: Should use createMiddleware() like other tests }); ``` ### Example 3: Strong Test Typing ```typescript // ✅ COMPLIANT: Strongly typed test data and assertions interface TestEmailData { readonly subject: string; readonly body: string; } test('email processing', async () => { const testEmail: TestEmailData = { subject: 'Test Subject', body: 'Test Body' }; const result = await processEmail(testEmail); expect(result.processed).toBe(true); }); ``` ## Generalization Guidance Ask yourself: 1. Does this test follow the same patterns as similar tests in the project? 2. Would a new contributor understand how to structure a similar test? 3. Is the test using strong typing consistent with the project's TypeScript standards? ## Anti-Patterns (What This Rule Does NOT Cover) - Tests that follow established project patterns consistently - Strongly typed test code that leverages TypeScript - Setup patterns that are consistent across similar test scenarios --- ### T5. Meaningful Test Coverage After Stabilization ## Intent Test coverage should focus on providing value after the API surface has stabilized, rather than creating tests that become maintenance burdens during active development. ## Category Pattern This encompasses violations where testing: - Creates comprehensive test suites for APIs that are still changing frequently - Focuses on test coverage metrics rather than meaningful verification - Tests implementation details that are likely to change during development ## Recognition Signals - Signal: Extensive testing of unstable APIs Examples: Full test suites for experimental features, testing internal implementation details But also: Tests that break frequently due to ongoing API changes - Signal: Coverage-driven rather than value-driven testing Examples: Testing every function just to achieve coverage targets But also: Tests that don't verify meaningful behavior ## Diverse Examples (Non-Exhaustive) ### Example 1: Stable API Testing ```typescript // ✅ COMPLIANT: Test stable, public API after completing stabilization work test('email authentication flow', async () => { // Tests established, stable authentication API const auth = await authenticateEmailProvider(credentials); expect(auth.isValid).toBe(true); }); ``` ### Example 2: Premature Testing Violation ```typescript // ❌ VIOLATION: Testing unstable implementation during active development test('internal email parser helper', () => { // Testing private implementation that's still being developed const parser = new EmailParserInternal(); // VIOLATION REASON: Implementation is likely to change }); ``` ### Example 3: Value-Focused Testing ```typescript // ✅ COMPLIANT: Tests meaningful user-facing behavior test('complete email workflow', async () => { // Tests end-to-end behavior that provides real value const email = await sendEmail(recipient, message); const delivered = await verifyDelivery(email.id); expect(delivered).toBe(true); }); ``` ## Generalization Guidance Ask yourself: 1. Is the API surface stable enough that tests won't need frequent updates? 2. Does this test verify meaningful behavior rather than just achieving coverage? 3. Would this test provide value in catching real regressions? ## Anti-Patterns (What This Rule Does NOT Cover) - Testing stable, public APIs that provide real value - End-to-end tests that verify complete workflows - Tests that catch meaningful regressions in stable functionality --- ### T6. Failure Investigation Over Test Disabling ## Intent Test failures should lead to investigation and fixes rather than test modification, ensuring tests continue to surface real issues and maintain confidence in system reliability. ## Category Pattern This encompasses violations where test failures: - Are resolved by modifying tests rather than investigating root causes - Lead to test disabling rather than fixing underlying issues - Result in reduced test coverage instead of improved system reliability ## Recognition Signals - Signal: Test modification to avoid failures Examples: Changing assertions to match current behavior, adding guards to prevent failures But also: Weakening test conditions to avoid investigating real issues - Signal: Test disabling for convenience Examples: Skipping tests due to environment issues, disabling flaky tests But also: Removing tests that expose real system problems ## Diverse Examples (Non-Exhaustive) ### Example 1: Proper Failure Investigation ```typescript // ✅ COMPLIANT: Test failure leads to root cause investigation test('email delivery confirmation', async () => { const email = await sendEmail(recipient, message); // If this fails, investigate why delivery confirmation isn't working expect(email.deliveryStatus).toBe('confirmed'); }); ``` ### Example 2: Test Weakening Violation ```typescript // ❌ VIOLATION: Weakening test to avoid investigating failure test('email delivery confirmation', async () => { const email = await sendEmail(recipient, message); // Changed from 'confirmed' to avoid investigating delivery issues expect(email.deliveryStatus).toMatch(/confirmed|pending/); }); // VIOLATION REASON: Should investigate why confirmation isn't working ``` ### Example 3: Environment Fix Rather Than Test Skip ```typescript // ✅ COMPLIANT: Fix environment rather than skip test test('gmail integration', async () => { // Instead of { skip: !process.env.GMAIL_TOKEN } // Fix the environment setup and investigate configuration issues const gmail = await createGmailClient(); expect(gmail).toBeTruthy(); }); ``` ## Generalization Guidance Ask yourself: 1. Does this test failure indicate a real system issue that should be investigated? 2. Would fixing the root cause improve overall system reliability? 3. Is test modification hiding a problem that should be solved? ## Anti-Patterns (What This Rule Does NOT Cover) - Investigating and fixing real system issues exposed by test failures - Improving test design based on better understanding of requirements - Temporary test adjustments during active investigation of root causes --- ### T7. Explicit Environment Requirements ## Intent Tests should fail fast and clearly when environment configuration is incorrect, making it obvious what needs to be fixed rather than working around configuration issues. ## Category Pattern This encompasses violations where tests: - Hide configuration issues behind conditional skipping - Work around missing environment setup instead of surfacing problems - Create unclear failure modes that don't indicate what needs to be fixed ## Recognition Signals - Signal: Conditional test skipping based on environment Examples: { skip: !ENV_VAR }, tests that silently pass when misconfigured But also: Tests that work around missing configuration instead of failing clearly - Signal: Unclear failure modes for configuration issues Examples: Tests that fail with generic errors when environment is wrong But also: Tests that partially work with incorrect configuration ## Diverse Examples (Non-Exhaustive) ### Example 1: Clear Environment Requirement ```typescript // ✅ COMPLIANT: Fail fast with clear error for missing config test('gmail operations', async () => { const clientId = requiredEnv('GMAIL_CLIENT_ID'); // Throws clear error const context = await createGmailContext({ clientId }); // Test proceeds with proper configuration }); ``` ### Example 2: Silent Skip Violation ```typescript // ❌ VIOLATION: Hides configuration issues test('gmail operations', async () => { if (!process.env.GMAIL_CLIENT_ID) { test.skip(); // Silently skips instead of surfacing configuration problem return; } }); // VIOLATION REASON: Should fail clearly to surface configuration issues ``` ### Example 3: Proper Configuration Validation ```typescript // ✅ COMPLIANT: Test validates required configuration exists function requiredEnv(key: string): string { if (!process.env[key]) { throw new Error(`Environment variable ${key} is required for this test`); } return process.env[key]; } ``` ## Generalization Guidance Ask yourself: 1. Does this test clearly indicate what configuration is missing when it fails? 2. Would someone running this test understand how to fix configuration issues? 3. Is the test surfacing real configuration problems rather than hiding them? ## Anti-Patterns (What This Rule Does NOT Cover) - Tests that fail clearly with helpful error messages for configuration issues - Environment validation that makes requirements explicit - Clear documentation of what environment setup is needed for tests --- ### T8. Secure Test Data Storage ## Intent Test data should be stored in designated areas to prevent accidental commits of sensitive information and maintain clear separation between test artifacts and source code. ## Category Pattern This encompasses violations where test data: - Is created in source code directories where it might be accidentally committed - Contains or could contain sensitive information that shouldn't be in version control - Lacks clear separation between temporary test artifacts and permanent project files ## Recognition Signals - Signal: Test data files in source directories Examples: Creating files in src/, auth/, or other production code areas during tests But also: Test artifacts scattered throughout the project structure - Signal: Potential for sensitive data exposure Examples: Test files that could contain real credentials, PII, or tokens But also: Test data that persists across test runs in unsecured locations ## Diverse Examples (Non-Exhaustive) ### Example 1: Proper Test Data Location ```typescript // ✅ COMPLIANT: Test data in designated areas test('file processing', async () => { const testFile = path.join(STORE_DIR, 'test-data.json'); // Uses STORE_DIR await writeTestData(testFile, sampleData); // Test operations... await fs.unlink(testFile); // Cleanup }); ``` ### Example 2: Source Directory Violation ```typescript // ❌ VIOLATION: Creating test data in source code area test('config processing', async () => { const configFile = './src/test-config.json'; // Wrong location await fs.writeFile(configFile, JSON.stringify(testConfig)); // VIOLATION REASON: Could be accidentally committed with source code }); ``` ### Example 3: Temporary Directory Usage ```typescript // ✅ COMPLIANT: Using proper temporary areas test('data processing', async () => { const tempDir = path.join('.tmp', 'test-' + Date.now()); await fs.mkdir(tempDir, { recursive: true }); // Test operations in temporary area await fs.rm(tempDir, { recursive: true }); // Cleanup }); ``` ## Generalization Guidance Ask yourself: 1. Could this test data be accidentally committed to version control? 2. Is test data clearly separated from production source code? 3. Would this test data location create security or privacy concerns? ## Anti-Patterns (What This Rule Does NOT Cover) - Using designated test data directories (.tmp/, STORE_DIR) - Test data that is clearly temporary and properly cleaned up - Test configurations that don't contain sensitive information --- ### T9. Self-Contained Portable Tests ## Intent Tests should be self-contained and moveable, not dependent on shared infrastructure or cross-file dependencies that would break if the test were copied to a different location. ## Category Pattern This encompasses violations where tests: - Depend on shared test infrastructure that exists outside the test file - Have hidden dependencies on other test files or global setup - Would break if copied to a different project or directory structure ## Recognition Signals - Signal: Dependencies on shared test infrastructure Examples: Global test setup, shared state, test utilities that maintain state But also: Implicit dependencies on test execution order or global configuration - Signal: Cross-file test dependencies Examples: Tests that depend on other tests running first, shared test data But also: Tests that rely on global state set by other test files ## Diverse Examples (Non-Exhaustive) ### Example 1: Self-Contained Test ```typescript // ✅ COMPLIANT: All dependencies explicit and local test('email validation', async () => { // All setup within the test const emailValidator = new EmailValidator(); const testEmail = 'test@example.com'; const result = emailValidator.validate(testEmail); expect(result.isValid).toBe(true); // No external dependencies or cleanup needed }); ``` ### Example 2: Shared Infrastructure Violation ```typescript // ❌ VIOLATION: Depends on global test setup test('user authentication', async () => { // Relies on global testUser set up elsewhere const result = await authenticateUser(globalTestUser); // Hidden dependency expect(result.success).toBe(true); }); // VIOLATION REASON: Wouldn't work if copied to different project ``` ### Example 3: Portable Test with Local Setup ```typescript // ✅ COMPLIANT: Self-contained with explicit setup test('gmail operations', async () => { // All setup explicit and local const credentials = { clientId: requiredEnv('GMAIL_CLIENT_ID'), clientSecret: requiredEnv('GMAIL_CLIENT_SECRET') }; const gmail = await createGmailClient(credentials); // Test operations... // Cleanup is also local and explicit await gmail.cleanup(); }); ``` ## Generalization Guidance Ask yourself: 1. Would this test work if copied to a completely different project? 2. Are all dependencies explicit and contained within the test file? 3. Does this test rely on any global state or shared infrastructure? ## Anti-Patterns (What This Rule Does NOT Cover) - Tests that explicitly import and use required dependencies - Self-contained tests that include all necessary setup and cleanup - Tests that use only local variables and explicit dependencies --- ### T10. Function-Based Test Organization ## Absolute Requirement **NEVER create classes for test validation, data management, or tracking within test files.** ## Intent Test code should avoid class-based organization that can lead to over-engineering and instead use simple functions and variables that keep tests understandable and maintainable. ## Category Pattern This encompasses violations where test organization: - Uses class structures that add complexity without providing benefit - Creates object-oriented patterns that obscure test logic - Introduces abstraction layers that make tests harder to understand ## Recognition Signals - Signal: Class-based test organization Examples: Test classes, class-based test utilities, object-oriented test patterns But also: Class instances used for test state management or validation - Signal: Over-engineered test structure Examples: Inheritance hierarchies in tests, abstract test classes But also: Complex test organization that requires understanding OOP patterns ## VIOLATION REMEDIATION (T10/T11) **PRINCIPLE**: Test classes indicate over-engineering. Remove entirely, use existing production validation or simple inline logic instead. **Escalation**: For test helper categorization and edge cases, consult the test-automator agent. ## Diverse Examples (Non-Exhaustive) ### Example 1: Simple Function-Based Test ```typescript // ✅ COMPLIANT: Simple, clear test organization test('email processing', async () => { const testEmails = ['test1@example.com', 'test2@example.com']; const results = []; for (const email of testEmails) { const result = await processEmail(email); results.push(result); } expect(results.every(r => r.success)).toBe(true); }); ``` ### Example 2: Class-Based Test Violation ```typescript // ❌ VIOLATION: Unnecessary class structure in tests class EmailTestSuite { private testData: Email[] = []; async setupTestEmails() { ... } async validateResults() { ... } async cleanup() { ... } } // VIOLATION REASON: Simple variables and functions would be clearer ``` ### Example 3: Simple Helper Functions (When Needed) ```typescript // ✅ COMPLIANT: Simple helper functions in test/lib/ if needed // test/lib/email-helpers.ts export async function createTestEmail(subject: string): Promise<Email> { return { id: generateId(), subject, body: 'Test body' }; } // Used simply in tests without class structure test('email operations', async () => { const email = await createTestEmail('Test Subject'); // Simple, clear test logic }); ``` ## Generalization Guidance Ask yourself: 1. Does this test organization use simple, understandable patterns? 2. Would a new contributor immediately understand the test structure? 3. Is class structure adding value or just complexity? ## Anti-Patterns (What This Rule Does NOT Cover) - Simple functions and variables for test organization - Helper functions that don't maintain state or add complexity - Clear, functional test patterns that are easy to understand --- ### T11. Simple Test Implementation Patterns ## Absolute Requirement **NEVER use `class` keyword in test files unless explicitly required for interface/type definitions.** ## Intent Test implementation should use the simplest patterns possible, avoiding class-based patterns or complex abstractions that make tests harder to understand and maintain. ## Category Pattern This encompasses violations where test implementation: - Uses class keyword when simple functions and variables would work - Creates complex abstractions that obscure what tests actually do - Introduces patterns that require advanced language knowledge to understand ## Recognition Signals - Signal: Class keyword usage in test files Examples: `class TestValidator`, `class TestHelper`, any class instantiation in tests But also: Object-oriented patterns that could be replaced with functions - Signal: Complex test abstractions Examples: Test frameworks, validation classes, state management classes But also: Patterns that require understanding inheritance, polymorphism, or other OOP concepts ## VIOLATION REMEDIATION (T10/T11) **PRINCIPLE**: Test classes indicate over-engineering. Remove entirely, use existing production validation or simple inline logic instead. **Escalation**: For test helper categorization and edge cases, consult the test-automator agent. ## Diverse Examples (Non-Exhaustive) ### Example 1: Simple Variable Tracking ```typescript // ✅ COMPLIANT: Simple variables for test state test('email operations', async () => { const createdEmails: string[] = []; // Simple array tracking try { const email = await createEmail('test'); createdEmails.push(email.id); // Test logic... } finally { for (const id of createdEmails) await deleteEmail(id); } }); ``` ### Example 2: Class-Based Test Implementation Violation ```typescript // ❌ VIOLATION: Using class in test implementation class TestEmailValidator { validate(email: string): boolean { ... } cleanup(): void { ... } } test('email validation', () => { const validator = new TestEmailValidator(); // Class instantiation // VIOLATION REASON: Simple function would be clearer }); ``` ### Example 3: Simple Replacement Approach ```typescript // ✅ COMPLIANT: Replace test classes with existing solutions test('email validation', () => { // Instead of custom validator class, use existing validation const isValid = validateEmail('test@example.com'); // Use standard function expect(isValid).toBe(true); }); ``` ## Generalization Guidance Ask yourself: 1. Can this be implemented with simple functions and variables? 2. Would a contributor with basic JavaScript knowledge understand this pattern? 3. Is the class structure providing real benefit or just adding complexity? **Replacement Strategy**: When removing test classes, don't create functional equivalents. Instead: - Use `test/lib/*` utilities for allowed helper categories - Use simple inline code for local operations ## Anti-Patterns (What This Rule Does NOT Cover) - Simple functions and variables for test implementation - Using existing standard libraries and utilities - Clear, functional patterns that avoid class-based complexity --- ### T12. Test File Location and Structure ## Intent Test files should be located in predictable directories that mirror source structure and prevent confusion about which domain they test, making it easy to find and run tests for specific functionality. ## Category Pattern This encompasses violations where test placement: - Creates confusion about which code domain the test covers - Places tests in locations that don't mirror source structure - Mixes tests for different services or domains - Creates ambiguity about test ownership and scope ## Recognition Signals - Signal: Tests placed outside domain-specific test directories Examples: Test files in package root, tests in wrong package directory But also: Integration tests that span multiple domains without clear ownership - Signal: Test structure that doesn't mirror source organization Examples: Flat test organization when source has clear hierarchy But also: Test files grouped by test type rather than source code structure - Signal: Cross-domain test confusion Examples: Gmail tests in Outlook test directory, generic tests without domain context But also: Shared test utilities that could belong to multiple domains ## Diverse Examples (Non-Exhaustive) ### Example 1: Correct Test Placement ```typescript // ✅ COMPLIANT: Tests mirror source structure // Source: src/mcp/tools/message-search.ts // Test: test/unit/mcp/tools/message-search.test.ts // Clear domain ownership and mirrored structure ``` ### Example 2: Root-Level Test Violation ```typescript // ❌ VIOLATION: Test in wrong location // Root level: message-search.test.ts // VIOLATION REASON: Test should be in test/unit/ directory with proper organization ``` ### Example 3: Integration Test ```typescript // ✅ COMPLIANT: Integration test with clear scope // test/integration/api-validation.integration.test.ts // Tests cross-cutting functionality with clear purpose ``` ### Example 4: Shared Test Utilities Location ```typescript // ✅ COMPLIANT: Shared utilities in appropriate location // test/lib/create-middleware-context.ts - Common test setup utilities // test/lib/create-extra.ts - Test context helpers ``` ## Generalization Guidance Ask yourself: 1. Would someone immediately know which code domain this test covers from its location? 2. Does the test directory structure mirror the source code organization? 3. If this is an integration test, is its scope and ownership clear? **Context**: Test-Only **Escalation**: For complex test organization scenarios and cross-domain integration patterns, consult the test-automator agent. ## Anti-Patterns (What This Rule Does NOT Cover) - Tests that are clearly placed in domain-specific directories - Integration tests with explicit scope and ownership - Test utilities that are appropriately scoped to their domain --- ## EXPERT ESCALATION FRAMEWORK When implementation decisions require interpretation of quality principles, escalate to specialized agents rather than making arbitrary choices. ### ESCALATION TRIGGERS - File/package structure decisions that could go multiple ways - "Multiple domain" determinations for package exports - Entry point classification for non-standard startup files - Purpose-based naming when function scope is unclear - Test helper categorization for edge cases ### ESCALATION THRESHOLDS - **2+ viable interpretations** of a rule → Escalate - **Cross-cutting concerns** across multiple rules → Escalate - **Novel patterns** not covered in examples → Escalate - **"It depends" responses** to rule questions → Escalate ### AGENT ESCALATION MATRIX | Situation | Agent Type | Analysis Required | |-----------|------------|-------------------| | Entry point classification | `architect-reviewer` | Analyze file role against U15 principles | | Package export boundaries | `architect-reviewer` | Evaluate domain separation per U18 criteria | | File naming/grouping | `architect-reviewer` | Apply U3 cohesive grouping principles | | Test infrastructure scope | `test-automator` | Assess helper necessity against T2 rules | | Test file organization | `test-automator` | Apply T12 test placement principles to complex scenarios | | Type safety thresholds | `typescript-pro` | Evaluate U13 .d.ts creation triggers | | Environment configuration | `architect` | Evaluate patterns per `docs/environments.md` | ### ESCALATION PROMPT TEMPLATE "Analyze [specific situation] against QUALITY.md rule [UX/TX]. Apply the existing principles to determine the correct approach. If the situation reveals a gap in the rules, recommend specific guidance to add." ### POST-ESCALATION ACTIONS 1. **Document the decision** in code comments referencing the analysis 2. **Update QUALITY.md** if the analysis reveals missing guidance 3. **Create precedent** for similar future cases ## ENFORCEMENT Any proposal that creates new classes, frameworks, or centralized infrastructure for simple code quality fixes will be IMMEDIATELY REJECTED. This is an open-source community project - keep solutions simple enough that any contributor can understand and maintain them. Agents must implement the simplest possible solution within existing files. Violations of the CRITICAL CONSTRAINTS or use of REJECTED PATTERNS will result in automatic rejection of the entire proposal.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mcp-z/mcp-pdf'

If you have feedback or need assistance with the MCP directory API, please join our Discord server