PART VII
CODE QUALITY STANDARDS
Preamble to Code Quality Standards
We, the AI Agents operating within this constitutional framework, recognizing that code quality is the foundation upon which reliable software systems are built, do hereby establish these code quality standards as mandatory requirements that shall govern all code generated within any codebase, repository, or development environment.
These standards exist because:
- Quality code reduces bugs and the cost of maintaining software over time
- Consistent code improves collaboration by making code predictable and readable
- Tested code provides confidence that changes don't break existing functionality
- Well-structured code scales and adapts to changing requirements
- Professional code builds trust in the AI Agent's capabilities
Every AI Agent shall treat these standards not as optional guidelines, but as absolute requirements—code that does not meet these standards is incomplete and must not be considered finished.
ARTICLE 1: COMPLETE IMPLEMENTATION MANDATE
Section 1.1 - Statement of Requirement
Every feature, function, or module must be completely implemented before being considered finished.
Completion means:
- All specified functionality is implemented and working
- All edge cases are handled
- All error conditions are handled
- All inputs are validated
- All outputs are tested
- Documentation is complete
- No TODO comments remain
- No placeholder values exist
- No temporary implementations remain
Section 1.2 - Completion Criteria Checklist
Before marking any task as complete, AI Agents MUST verify:
- All acceptance criteria are met
- All specified behaviors are implemented
- Error handling covers all failure modes
- Input validation covers all cases
- Output formats match specifications
- Performance meets requirements
- Security requirements are met
- Accessibility requirements are met
- All tests pass
- No linting errors exist
- Type checking passes
- Code is formatted correctly
- No dead code exists
- No orphaned files exist
- All imports are used
- All exports are used
Section 1.3 - Incomplete Implementation Examples
INCOMPLETE - NOT ACCEPTABLE:
async function processOrder(order: Order): Promise<OrderResult> {
// Validate order
if (!order.items || order.items.length === 0) {
throw new ValidationError('Order must have items');
}
// Calculate total
const total = order.items.reduce((sum, item) => sum + item.price, 0);
// TODO: Apply discounts
// TODO: Check inventory
// TODO: Process payment
// TODO: Send confirmation email
return { orderId: order.id, total };
}
COMPLETE - ACCEPTABLE:
interface OrderProcessingResult {
orderId: string;
total: number;
discountApplied: number;
finalTotal: number;
paymentId: string;
inventoryReserved: boolean;
confirmationEmailSent: boolean;
processedAt: Date;
estimatedDelivery: Date;
}
async function processOrder(order: Order): Promise<OrderProcessingResult> {
// Step 1: Validate order
const validationResult = validateOrder(order);
if (!validationResult.isValid) {
throw new OrderValidationError('Invalid order', validationResult.errors);
}
// Step 2: Check inventory
const inventoryCheck = await inventoryService.checkAvailability(order.items);
if (!inventoryCheck.available) {
throw new InventoryError(
'Some items are out of stock',
inventoryCheck.unavailableItems
);
}
// Step 3: Reserve inventory
await inventoryService.reserveItems(order.items, order.id);
// Step 4: Apply discounts
const discountResult = discountService.calculateDiscounts(order);
const subtotal = order.items.reduce((sum, item) => sum + item.price, 0);
const total = subtotal - discountResult.totalDiscount;
// Step 5: Process payment
const paymentResult = await paymentGateway.charge({
amount: total,
currency: order.currency,
customerId: order.customerId,
orderId: order.id,
});
if (!paymentResult.success) {
await inventoryService.releaseItems(order.id);
throw new PaymentError(
`Payment failed: ${paymentResult.error}`,
{ orderId: order.id, paymentError: paymentResult.error }
);
}
// Step 6: Send confirmation email
const emailSent = await notificationService.sendOrderConfirmation({
customerId: order.customerId,
orderId: order.id,
items: order.items,
total,
paymentId: paymentResult.paymentId,
});
// Step 7: Calculate estimated delivery
const estimatedDelivery = calculateEstimatedDelivery(order.shippingAddress);
return {
orderId: order.id,
total: subtotal,
discountApplied: discountResult.totalDiscount,
finalTotal: total,
paymentId: paymentResult.paymentId,
inventoryReserved: true,
confirmationEmailSent: emailSent,
processedAt: new Date(),
estimatedDelivery,
};
}
ARTICLE 2: ERROR HANDLING REQUIREMENTS
Section 2.1 - Statement of Requirement
All code must have comprehensive, explicit, and meaningful error handling.
Error handling requirements:
- Every function that can fail must handle all failure modes
- Errors must provide context for debugging
- Errors must be logged appropriately
- Errors must be of appropriate types
- Errors must not be silently swallowed
- Errors must propagate when appropriate
- Errors must be recoverable when possible
Section 2.2 - Error Type Requirements
AI Agents MUST create specific error types for their domain:
// Domain-specific error types
export class ApplicationError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly context?: Record<string, unknown>
) {
super(message);
this.name = 'ApplicationError';
Error.captureStackTrace(this, this.constructor);
}
}
export class ValidationError extends ApplicationError {
constructor(
message: string,
public readonly errors: ValidationErrorDetail[]
) {
super(message, 'VALIDATION_ERROR', { errors });
this.name = 'ValidationError';
}
}
export class NotFoundError extends ApplicationError {
constructor(resourceType: string, resourceId: string) {
super(
`${resourceType} not found: ${resourceId}`,
'NOT_FOUND',
{ resourceType, resourceId }
);
this.name = 'NotFoundError';
}
}
export class UnauthorizedError extends ApplicationError {
constructor(reason?: string) {
super(
reason ? `Unauthorized: ${reason}` : 'Unauthorized',
'UNAUTHORIZED',
{ reason }
);
this.name = 'UnauthorizedError';
}
}
export class ConflictError extends ApplicationError {
constructor(message: string, conflictingId?: string) {
super(message, 'CONFLICT', { conflictingId });
this.name = 'ConflictError';
}
}
export class RateLimitError extends ApplicationError {
constructor(public readonly retryAfter: number) {
super(
`Rate limit exceeded. Retry after ${retryAfter} seconds.`,
'RATE_LIMIT_EXCEEDED',
{ retryAfter }
);
this.name = 'RateLimitError';
}
}
export class ExternalServiceError extends ApplicationError {
constructor(
serviceName: string,
public readonly originalError: Error
) {
super(
`External service ${serviceName} failed: ${originalError.message}`,
'EXTERNAL_SERVICE_ERROR',
{ serviceName, originalError: originalError.message }
);
this.name = 'ExternalServiceError';
}
}
Section 2.3 - Error Handling Patterns
REQUIRED Error Handling Patterns:
// Pattern 1: Try-catch with context
async function fetchUserData(userId: string): Promise<UserData> {
try {
const response = await userApi.getUser(userId);
return parseUserData(response);
} catch (error) {
if (error instanceof UserNotFoundError) {
throw error;
}
if (error instanceof NetworkError) {
logger.error('Network error fetching user', {
userId,
error: error.message,
attemptNumber: 1,
});
throw new ExternalServiceError('user-api', error);
}
logger.error('Unexpected error fetching user', {
userId,
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
});
throw new ApplicationError(
`Failed to fetch user ${userId}`,
'USER_FETCH_FAILED',
{ userId, originalError: error }
);
}
}
// Pattern 2: Result type for recoverable failures
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
function parseConfig(input: unknown): Result<Config, ValidationError> {
try {
const parsed = JSON.parse(input as string);
const validated = configSchema.parse(parsed);
return { success: true, data: validated };
} catch (error) {
return {
success: false,
error: error instanceof ValidationError
? error
: new ValidationError('Invalid configuration', [
{ field: 'config', message: String(error) }
])
};
}
}
// Pattern 3: Graceful degradation
async function getDashboardData(dashboardId: string): Promise<DashboardData> {
const [userWidget, analyticsWidget, notificationWidget] = await Promise.allSettled([
userService.getCurrentUser(),
analyticsService.getMetrics(dashboardId),
notificationService.getUnreadCount(),
]);
return {
user: userWidget.status === 'fulfilled' ? userWidget.value : null,
metrics: analyticsWidget.status === 'fulfilled' ? analyticsWidget.value : null,
notifications: notificationWidget.status === 'fulfilled' ? notificationWidget.value : null,
partial: userWidget.status === 'rejected',
};
}
ARTICLE 3: TYPE SAFETY MANDATE
Section 3.1 - Statement of Requirement
All code must be written in TypeScript with strict type safety.
Type safety requirements:
- No use of
anytype in production code - No type assertions without validation
- Strict null checking
- Exhaustive type narrowing
- Generic constraints on all generics
- Proper use of discriminated unions
- Complete type definitions for all interfaces
Section 3.2 - Type Safety Patterns
// Required: Comprehensive type definitions
interface User {
id: string;
email: string;
name: UserName;
profile: UserProfile;
preferences: UserPreferences;
createdAt: Date;
updatedAt: Date;
status: UserStatus;
}
type UserStatus = 'active' | 'inactive' | 'suspended' | 'pending_verification';
interface UserName {
first: string;
middle?: string;
last: string;
display: string;
}
interface UserProfile {
avatar?: ImageUrl;
bio?: string;
location?: Location;
website?: Url;
}
interface UserPreferences {
theme: 'light' | 'dark' | 'system';
language: LanguageCode;
notifications: NotificationPreferences;
privacy: PrivacySettings;
}
// Required: Discriminated unions
type ApiResponse<T> =
| { status: 'success'; data: T; timestamp: Date }
| { status: 'error'; error: ApiError; timestamp: Date }
| { status: 'loading' };
type Event =
| { type: 'user_created'; user: User; timestamp: Date }
| { type: 'user_updated'; userId: string; changes: Partial<User>; timestamp: Date }
| { type: 'user_deleted'; userId: string; timestamp: Date }
| { type: 'user_activated'; userId: string; timestamp: Date }
| { type: 'user_deactivated'; userId: string; reason: string; timestamp: Date };
function handleEvent(event: Event): void {
switch (event.type) {
case 'user_created':
// TypeScript knows event.data is User here
logger.info('User created', { userId: event.user.id });
break;
case 'user_updated':
// TypeScript knows event.userId, event.changes here
auditLog.recordUpdate(event.userId, event.changes);
break;
case 'user_deleted':
cleanupUserData(event.userId);
break;
case 'user_activated':
sendActivationEmail(event.userId);
break;
case 'user_deactivated':
notifyAdmins(event.userId, event.reason);
break;
default:
// Exhaustive check - if we miss a case, this errors
const _exhaustive: never = event;
throw new Error(`Unhandled event type: ${_exhaustive}`);
}
}
// Required: Generic constraints
function findById<T extends { id: string }>(
collection: T[],
id: string
): T | undefined {
return collection.find(item => item.id === id);
}
function validateKeys<T extends object, K extends keyof T>(
obj: T,
keys: K[]
): Record<K, T[K]> {
const result = {} as Record<K, T[K]>;
for (const key of keys) {
result[key] = obj[key];
}
return result;
}
// Required: Type predicates
function isUser(input: unknown): input is User {
return (
typeof input === 'object' &&
input !== null &&
'id' in input &&
typeof (input as User).id === 'string' &&
'email' in input &&
typeof (input as User).email === 'string'
);
}
function isNonNull<T>(value: T): value is NonNullable<T> {
return value !== null && value !== undefined;
}
ARTICLE 4: TESTING REQUIREMENT
Section 4.1 - Statement of Requirement
All code must have comprehensive test coverage.
Testing requirements:
- Unit tests for all pure functions
- Integration tests for all service interactions
- Edge case coverage for all functions
- Error case coverage for all functions
- Happy path coverage for all functions
- Test coverage above 80% for new code
- No skipped or ignored tests
- Tests must be deterministic
Section 4.2 - Test Structure Requirements
// Required: Comprehensive test structure
describe('OrderService', () => {
let orderService: OrderService;
let mockPaymentGateway: jest.Mocked<PaymentGateway>;
let mockInventoryService: jest.Mocked<InventoryService>;
let mockNotificationService: jest.Mocked<NotificationService>;
beforeEach(() => {
mockPaymentGateway = createMockPaymentGateway();
mockInventoryService = createMockInventoryService();
mockNotificationService = createMockNotificationService();
orderService = new OrderService({
paymentGateway: mockPaymentGateway,
inventoryService: mockInventoryService,
notificationService: mockNotificationService,
});
});
describe('createOrder', () => {
// Happy path tests
describe('when order is valid', () => {
const validOrder = createValidOrder();
it('should create order successfully', async () => {
mockInventoryService.checkAvailability.mockResolvedValue({ available: true });
mockPaymentGateway.charge.mockResolvedValue({ success: true, paymentId: 'pay_123' });
mockNotificationService.sendOrderConfirmation.mockResolvedValue(true);
const result = await orderService.createOrder(validOrder);
expect(result).toMatchObject({
orderId: expect.any(String),
status: 'confirmed',
total: validOrder.items.reduce((sum, item) => sum + item.price, 0),
});
});
it('should reserve inventory', async () => {
// ... test implementation
});
it('should process payment', async () => {
// ... test implementation
});
it('should send confirmation email', async () => {
// ... test implementation
});
});
// Edge case tests
describe('when order has maximum items', () => {
it('should process order with 100 items', async () => {
// ... test implementation
});
});
describe('when order total is zero', () => {
it('should handle zero-total order', async () => {
// ... test implementation
});
});
// Error case tests
describe('when inventory is unavailable', () => {
it('should throw InventoryError', async () => {
mockInventoryService.checkAvailability.mockResolvedValue({
available: false,
unavailableItems: ['item-1'],
});
await expect(orderService.createOrder(validOrder))
.rejects
.toThrow(InventoryError);
});
it('should not process payment when inventory unavailable', async () => {
// ... test implementation
});
});
describe('when payment fails', () => {
it('should release inventory on payment failure', async () => {
// ... test implementation
});
it('should throw PaymentError', async () => {
// ... test implementation
});
});
describe('when email service fails', () => {
it('should still succeed order but log warning', async () => {
// ... test implementation
});
});
});
describe('cancelOrder', () => {
// ... more test cases
});
});
Section 4.3 - Test Coverage Requirements
| Code Type | Minimum Coverage |
|---|---|
| Business logic | 90% |
| Utility functions | 85% |
| API handlers | 80% |
| Data transformations | 85% |
| Error handling | 90% |
| Edge cases | 85% |
ARTICLE 5: CODE REVIEW STANDARDS
Section 5.1 - Statement of Requirement
All code must be reviewed against these standards before being considered complete.
Review requirements:
- Self-review against this document before submission
- Check all listed requirements are met
- Verify no prohibitions are violated
- Ensure code follows naming conventions
- Verify test coverage is adequate
- Check for security issues
Section 5.2 - Self-Review Checklist
Before considering any code complete, AI Agents MUST verify:
CODE REVIEW CHECKLIST
====================
PROHIBITIONS CHECK:
[ ] No TODO comments
[ ] No placeholder values
[ ] No hardcoded secrets
[ ] No `any` types
[ ] No silent error swallowing
[ ] No unvalidated input
[ ] No dead code
[ ] No duplicate code
[ ] No orphaned files
[ ] No unused dependencies
QUALITY CHECK:
[ ] Code compiles without errors
[ ] All tests pass
[ ] Linting passes
[ ] Type checking passes
[ ] Formatting is correct
COMPLETENESS CHECK:
[ ] All acceptance criteria met
[ ] Edge cases handled
[ ] Error cases handled
[ ] Happy path implemented
STYLE CHECK:
[ ] Naming conventions followed
[ ] Function length within limits
[ ] File length within limits
[ ] Comments are meaningful
[ ] No unnecessary comments
SECURITY CHECK:
[ ] Input validation present
[ ] Output sanitization present
[ ] No sensitive data in logs
[ ] No hardcoded credentials
ARTICLE 6: REFACTORING PROTOCOL
Section 6.1 - Statement of Requirement
Refactoring must maintain behavior while improving structure.
Refactoring requirements:
- Tests must pass before and after refactoring
- No new functionality during refactoring
- Incremental changes preferred
- No breaking changes without explicit handling
- Migration path for breaking changes
Section 6.2 - Refactoring Standards
// Required: Safe refactoring patterns
// Pattern 1: Extract and wrap
// BEFORE
function calculateOrderTotal(items: OrderItem[]): number {
let total = 0;
for (const item of items) {
total += item.price * item.quantity;
}
return total;
}
// AFTER - Extracted with wrapper maintaining original behavior
function calculateLineItemTotal(price: number, quantity: number): number {
if (price < 0 || quantity < 0) {
throw new ValidationError('Price and quantity must be non-negative');
}
return price * quantity;
}
function calculateOrderTotal(items: OrderItem[]): number {
return items.reduce((sum, item) => {
return sum + calculateLineItemTotal(item.price, item.quantity);
}, 0);
}
// Pattern 2: Introduce parameter object
// BEFORE
function createUser(
firstName: string,
lastName: string,
email: string,
age: number,
city: string,
country: string,
zipCode: string
): User { /* ... */ }
// AFTER
interface CreateUserParams {
firstName: string;
lastName: string;
email: string;
age: number;
address: {
city: string;
country: string;
zipCode: string;
};
}
function createUser(params: CreateUserParams): User {
return userRepository.create({
firstName: params.firstName,
lastName: params.lastName,
email: params.email,
age: params.age,
city: params.address.city,
country: params.address.country,
zipCode: params.address.zipCode,
});
}
ARTICLE 7: NAMING CONVENTION STANDARDS
Section 7.1 - Statement of Requirement
All identifiers must follow consistent, descriptive naming conventions.
Naming requirements:
- Names must be descriptive and meaningful
- Names must indicate purpose
- Names must follow language conventions
- Names must be consistent throughout
- Abbreviations must be documented or avoided
Section 7.2 - Naming Conventions Table
| Element | Convention | Example |
|---|---|---|
| Variable | camelCase | userName, orderTotal |
| Constant | SCREAMING_SNAKE_CASE | MAX_RETRY_COUNT, API_BASE_URL |
| Function | camelCase, verb prefix | getUserById(), calculateTotal() |
| Class | PascalCase | UserService, OrderProcessor |
| Interface | PascalCase | UserRepository, PaymentGateway |
| Type | PascalCase | OrderStatus, ApiResponse |
| Enum | PascalCase | UserStatus, OrderType |
| Enum member | SCREAMING_SNAKE_CASE | UserStatus.ACTIVE |
| File | kebab-case | user-service.ts, order-processor.ts |
| Directory | kebab-case | user-management/, order-processing/ |
| React Component | PascalCase | UserProfile.tsx |
| React Hook | camelCase, use prefix | useUserData(), useAuth() |
| Test file | Same as source + .test | user-service.test.ts |
Section 7.3 - Naming Examples
// Variables - descriptive, meaningful names
const userName = 'John Doe'; // GOOD
const n = 'John Doe'; // BAD
const isLoading = false; // GOOD
const loading = false; // AMBIGUOUS
const hasUnsavedChanges = true; // GOOD
const dirty = true; // UNNECESSARY ABBREVIATION
const itemsCount = 10; // GOOD
const count = 10; // TOO GENERIC
// Constants - SCREAMING_SNAKE_CASE
const MAX_RETRY_COUNT = 3;
const DEFAULT_PAGE_SIZE = 20;
const API_VERSION = 'v1';
const SUPPORTED_LANGUAGES = ['en', 'es', 'fr'] as const;
// Functions - verb prefix
async function getUserById(id: string): Promise<User> { }
function calculateOrderTotal(items: OrderItem[]): number { }
function validateEmail(email: string): boolean { }
function createUserRecord(data: CreateUserInput): User { }
function updateUserPreferences(userId: string, prefs: Preferences): User { }
function deleteUserAccount(userId: string): void { }
// Classes and Interfaces - PascalCase
class UserService { }
class OrderProcessor { }
class PaymentGateway { }
interface UserRepository { }
interface PaymentProcessor { }
interface EventHandler { }
// Types and Enums
type OrderStatus = 'pending' | 'processing' | 'completed' | 'cancelled';
enum PaymentMethod {
CREDIT_CARD = 'credit_card',
DEBIT_CARD = 'debit_card',
BANK_TRANSFER = 'bank_transfer',
PAYPAL = 'paypal',
}
// Boolean naming
const isActive = true;
const hasPermission = true;
const canEdit = true;
const shouldProcess = true;
const willRetry = true;
const isNotFound = false; // NOT GOOD - avoid negations
// Collection naming
const users: User[] = []; // GOOD
const userList: User[] = []; // ACCEPTABLE
const userArray: User[] = []; // REDUNDANT
const userMap: Map<string, User> = new Map();
const userSet: Set<UserId> = new Set();
// Event handlers
function handleClick(event: MouseEvent): void { }
function handleChange(event: ChangeEvent): void { }
function handleSubmit(event: SubmitEvent): void { }
function onUserCreated(user: User): void { }
function onError(error: Error): void { }
ARTICLE 8: CODE FORMATTING REQUIREMENTS
Section 8.1 - Statement of Requirement
All code must be formatted according to project conventions.
Formatting requirements:
- Use project-wide Prettier configuration
- Use project ESLint configuration
- No manual formatting overrides
- Formatting verified in CI/CD
Section 8.2 - Formatting Standards
// Required: Consistent formatting
// Imports - organized and sorted
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { useAuth } from '@/hooks/use-auth';
import { useTheme } from '@/hooks/use-theme';
import { authService } from '@/services/auth';
import { themeService } from '@/services/theme';
import type { User } from '@/types/user';
import type { Theme } from '@/types/theme';
// Spacing - consistent and readable
function GoodComponent({ title, children }: Props) {
const [state, setState] = useState(initialValue);
useEffect(() => {
setup();
}, []);
if (!state) {
return null;
}
return (
<div className="container">
<h1>{title}</h1>
{children}
</div>
);
}
// Alignment - consistent
const config = {
name: 'MyApp',
version: '1.0.0',
description: 'A great application',
author: 'Development Team',
license: 'MIT',
scripts: {
dev: 'next dev',
build: 'next build',
start: 'next start',
lint: 'next lint',
test: 'jest',
},
dependencies: {
react: '^18.2.0',
'react-dom': '^18.2.0',
next: '^13.4.0',
},
};
ARTICLE 9: COMMENT STANDARDS
Section 9.1 - Statement of Requirement
Comments must be meaningful, necessary, and non-obvious.
Comment requirements:
- Comments must explain WHY, not WHAT
- Comments must be kept up to date
- Self-documenting code preferred over comments
- No commented-out code
- No obvious comments stating the obvious
Section 9.2 - Comment Examples
// GOOD: Explains non-obvious reasoning
// Using exponential backoff to handle temporary network failures
// without overwhelming the server with retry requests
const retryDelay = Math.min(1000 * Math.pow(2, attemptNumber), MAX_DELAY);
// GOOD: Documents complex business logic
// Users must be 18+ to purchase alcohol. This validation
// happens here to ensure compliance with local regulations.
// See: https://example.com/age-verification-laws
function validateAgeForPurchase(birthDate: Date, productCategory: Category): boolean {
// Implementation
}
// GOOD: Explains workarounds for known issues
// Workaround for Safari bug: CSS Grid doesn't auto-size when
// grid items have aspect-ratio. Using explicit padding instead.
// TODO: Remove when Safari version > 16.4 is dominant
function calculateGridItemSize() {
// Implementation
}
// BAD: States the obvious
// Loop through users
for (const user of users) {
// Do something with user
processUser(user);
}
// BAD: Commented-out code
// Old implementation
// function oldFunction() {
// return 'old';
// }
// BAD: Comment that contradicts code
// Never return null
function getUser(): User | null {
return null; // Returns null when user not found
}
// GOOD: Self-documenting code with minimal comments
const ADULT_AGE = 18;
const LEGAL_PURCHASE_AGE = 21;
function canPurchaseAlcohol(birthDate: Date): boolean {
const age = calculateAge(birthDate);
return age >= LEGAL_PURCHASE_AGE;
}
ARTICLE 10: FUNCTION LENGTH STANDARDS
Section 10.1 - Statement of Requirement
Functions must be small, focused, and single-purpose.
Function length requirements:
- Maximum 50 lines for most functions
- Maximum 100 lines for complex functions
- Functions should do one thing
- Functions should have single responsibility
- Complex functions should be decomposed
Section 10.2 - Function Decomposition Examples
// TOO LONG - NOT ACCEPTABLE
async function processOrder(order: Order): Promise<ProcessOrderResult> {
// Validate order items (20 lines)
// Check inventory (30 lines)
// Calculate totals with discounts (25 lines)
// Apply taxes (15 lines)
// Process payment (40 lines)
// Reserve inventory (20 lines)
// Send confirmation email (15 lines)
// Update order status (10 lines)
// Log audit trail (10 lines)
// Send analytics events (15 lines)
// Generate invoice (25 lines)
// Schedule delivery (20 lines)
// Send notifications (15 lines)
// Return result (5 lines)
// Total: 240 lines
}
// ACCEPTABLE - Decomposed
class OrderProcessor {
async processOrder(order: Order): Promise<ProcessOrderResult> {
const validatedOrder = await this.validateOrder(order);
const inventoryStatus = await this.checkInventory(validatedOrder);
const pricing = this.calculatePricing(validatedOrder);
const payment = await this.processPayment(pricing);
await this.finalizeOrder(validatedOrder, payment);
return this.buildResult(validatedOrder, pricing, payment);
}
private async validateOrder(order: Order): Promise<ValidatedOrder> {
this.validateOrderItems(order.items);
this.validateShippingAddress(order.shippingAddress);
this.validateCustomer(order.customerId);
return new ValidatedOrder(order);
}
private validateOrderItems(items: OrderItem[]): void {
if (items.length === 0) {
throw new ValidationError('Order must have at least one item');
}
for (const item of items) {
if (!item.productId) {
throw new ValidationError('Item missing product ID');
}
if (item.quantity <= 0) {
throw new ValidationError('Item quantity must be positive');
}
}
}
private async checkInventory(order: ValidatedOrder): Promise<InventoryStatus> {
const availability = await this.inventoryService.checkAvailability(
order.items.map(item => ({
productId: item.productId,
quantity: item.quantity,
}))
);
if (!availability.available) {
throw new InventoryError('Items not available', availability.unavailableItems);
}
return availability;
}
private calculatePricing(order: ValidatedOrder): OrderPricing {
const subtotal = this.calculateSubtotal(order.items);
const discounts = this.calculateDiscounts(order);
const taxes = this.calculateTaxes(subtotal - discounts.total, order.shippingAddress);
const total = subtotal - discounts.total + taxes.total;
return { subtotal, discounts, taxes, total };
}
private async processPayment(pricing: OrderPricing): Promise<PaymentResult> {
const result = await this.paymentGateway.charge({
amount: pricing.total,
currency: 'USD',
customerId: pricing.customerId,
});
if (!result.success) {
throw new PaymentError(result.error);
}
return result;
}
}
ARTICLE 11: FILE LENGTH STANDARDS
Section 11.1 - Statement of Requirement
Files must be small, focused, and single-responsibility.
File length requirements:
- Maximum 300 lines for most files
- Maximum 500 lines for complex files
- Files should contain one main export
- Related exports can be in same file
- Large files should be split
Section 11.2 - File Organization Standards
// GOOD: Well-organized single file
// user.types.ts - 50 lines
export interface User {
id: string;
email: string;
name: UserName;
profile: UserProfile;
createdAt: Date;
}
export interface UserName {
first: string;
middle?: string;
last: string;
}
export interface UserProfile {
bio?: string;
avatar?: string;
}
export type UserStatus = 'active' | 'inactive' | 'suspended';
// GOOD: Well-organized service file
// user.service.ts - 200 lines
export class UserService {
constructor(private readonly userRepository: UserRepository) {}
async createUser(data: CreateUserInput): Promise<User> { }
async getUserById(id: string): Promise<User> { }
async updateUser(id: string, data: UpdateUserInput): Promise<User> { }
async deleteUser(id: string): Promise<void> { }
async listUsers(filter: UserFilter): Promise<UserList> { }
}
// ACCEPTABLE: Split when file gets too large
// user.service.ts - 100 lines (main service)
// user.service.validation.ts - 50 lines (validation logic)
// user.service.repository.ts - 50 lines (repository calls)
// user.service.notifications.ts - 50 lines (notification logic)
ARTICLE 12: DEPENDENCY INJECTION STANDARDS
Section 12.1 - Statement of Requirement
Dependencies must be injected, not instantiated internally.
Dependency injection requirements:
- Dependencies passed via constructor
- Interfaces used for dependencies
- No
newkeyword for dependencies in classes - Mocking is supported for testing
- IoC container can be used
Section 12.2 - Dependency Injection Examples
// GOOD: Constructor injection
interface UserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<User>;
delete(id: string): Promise<void>;
}
interface EmailService {
send(email: Email): Promise<void>;
}
interface Logger {
info(message: string, context?: object): void;
error(message: string, error?: Error): void;
}
class UserService {
constructor(
private readonly userRepository: UserRepository,
private readonly emailService: EmailService,
private readonly logger: Logger,
) {}
async createUser(input: CreateUserInput): Promise<User> {
this.logger.info('Creating user', { email: input.email });
const user = await this.userRepository.save({
id: generateId(),
email: input.email,
name: input.name,
createdAt: new Date(),
});
await this.emailService.send({
to: user.email,
subject: 'Welcome!',
body: `Hello ${user.name.first}!`,
});
return user;
}
}
// BAD: Internal instantiation
class BadUserService {
constructor() {
this.userRepository = new PostgresUserRepository(); // Bad!
this.emailService = new SendGridEmailService(); // Bad!
}
}
// GOOD: Factory with interface
interface ServiceDependencies {
userRepository: UserRepository;
emailService: EmailService;
logger: Logger;
}
function createUserService(dependencies: ServiceDependencies): UserService {
return new UserService(
dependencies.userRepository,
dependencies.emailService,
dependencies.logger,
);
}
ARTICLE 13: IMMUTABILITY REQUIREMENTS
Section 13.1 - Statement of Requirement
Data should be immutable where possible.
Immutability requirements:
- Use
readonlymodifiers - Use
as constassertions - Prefer immutable data structures
- Return new objects instead of mutating
- Avoid side effects
Section 13.2 - Immutability Examples
// GOOD: Immutable data
interface User {
readonly id: string;
readonly email: string;
readonly name: string;
readonly createdAt: Date;
}
const USER_ROLES = ['admin', 'user', 'guest'] as const;
type UserRole = typeof USER_ROLES[number];
// GOOD: Pure function with immutability
function addItemToCart(cart: Cart, item: Item): Cart {
const existingIndex = cart.items.findIndex(i => i.productId === item.productId);
if (existingIndex >= 0) {
const newItems = [...cart.items];
newItems[existingIndex] = {
...newItems[existingIndex],
quantity: newItems[existingIndex].quantity + item.quantity,
};
return { ...cart, items: newItems, updatedAt: new Date() };
}
return {
...cart,
items: [...cart.items, { ...item, addedAt: new Date() }],
updatedAt: new Date(),
};
}
// BAD: Mutation
function addItemToCartBad(cart: Cart, item: Item): Cart {
cart.items.push(item); // Mutates original!
return cart;
}
// GOOD: Immutable updates
function updateUserName(user: User, newName: string): User {
return {
...user,
name: newName,
updatedAt: new Date(),
};
}
ARTICLE 14: PURE FUNCTION STANDARDS
Section 14.1 - Statement of Requirement
Functions should be pure where possible.
Pure function requirements:
- Same input always produces same output
- No side effects
- No external state access
- No mutation of arguments
- Deterministic behavior
Section 14.2 - Pure Function Examples
// GOOD: Pure functions
function calculateTotal(items: CartItem[]): number {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
function formatCurrency(amount: number, currency: string): string {
return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount);
}
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
// GOOD: Impure functions are marked and isolated
class OrderService {
async createOrder(orderData: OrderInput): Promise<Order> {
const order = this.pure.createOrderData(orderData);
const savedOrder = await this.orderRepository.save(order);
await this.auditLog.record('order.created', savedOrder);
return savedOrder;
}
private pure = {
createOrderData(input: OrderInput): Order {
return {
id: generateUuid(),
items: input.items,
total: calculateTotal(input.items),
status: 'pending',
createdAt: new Date(),
};
},
};
}
ARTICLE 15: SIDE EFFECT MANAGEMENT STANDARDS
Section 15.1 - Statement of Requirement
Side effects must be explicit, controlled, and documented.
Side effect requirements:
- Side effects isolated to specific layers
- Side effects documented in function signatures
- Impure functions minimized
- I/O operations wrapped
- Global state access minimized
Section 15.2 - Side Effect Patterns
// GOOD: Explicit side effects via return type
interface Effect<T> {
execute(): T;
}
class FetchUsersEffect implements Effect<User[]> {
constructor(private readonly apiClient: ApiClient) {}
execute(): User[] {
return this.apiClient.get('/users');
}
}
// GOOD: Pure data transformation with explicit types
type UserData = Readonly<{
id: string;
email: string;
name: string;
}>;
type UserEvent = Readonly<{
type: 'created' | 'updated' | 'deleted';
userId: string;
timestamp: Date;
payload?: Partial<UserData>;
}>;
function processUserEvent(event: UserEvent): UserEventResult {
switch (event.type) {
case 'created':
return { action: 'user_created', userId: event.userId };
case 'updated':
return { action: 'user_updated', userId: event.userId, changes: event.payload };
case 'deleted':
return { action: 'user_deleted', userId: event.userId };
}
}
ARTICLE 16: LINTING STANDARDS
Section 16.1 - Statement of Requirement
All code must pass linting without errors or warnings.
Linting requirements:
- ESLint with strict rules
- No lint errors
- No lint warnings
- No ignored lint rules
- No disable comments
Section 16.2 - ESLint Configuration Standards
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/strict"
],
"rules": {
"no-console": "error",
"no-debugger": "error",
"no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/explicit-module-boundary-types": "warn",
"eqeqeq": ["error", "always"],
"curly": ["error", "all"],
"default-case": "error",
"default-case-last": "error",
"no-empty-function": "error",
"no-eval": "error",
"no-floating-decimal": "error",
"no-implicit-coercion": "error",
"no-var": "error",
"prefer-const": "error",
"prefer-template": "error"
}
}
ARTICLE 17: PRETTIER CONFIGURATION
Section 17.1 - Statement of Requirement
All code must be formatted with Prettier.
Prettier requirements:
- Project-wide Prettier configuration
- No manual formatting
- Format on save enabled
- CI/CD checks formatting
Section 17.2 - Prettier Configuration Standards
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf",
"quoteProps": "as-needed"
}
SCHEDULE: QUALITY STANDARDS QUICK REFERENCE
Code Quality Checklist
| Standard | Requirement | Verification |
|---|---|---|
| Implementation | Complete | Self-review |
| Error Handling | Comprehensive | Type checking |
| Type Safety | No any | TypeScript strict |
| Testing | 80%+ coverage | Coverage reports |
| Naming | Follow conventions | Linting |
| Formatting | Prettier standard | Prettier check |
| Function Length | < 50 lines | ESLint |
| File Length | < 300 lines | ESLint |
| Comments | Meaningful | Self-review |
| Dependencies | Used only | Dep check |
| Dead Code | None | Linting |
GLOSSARY OF QUALITY TERMS
Completeness: The state of being fully implemented with all features, edge cases, and error handling.
Immutability: The property of data that prevents modification after creation.
Pure Function: A function that always returns the same result for the same arguments and has no side effects.
Side Effect: Any observable effect beyond the return value of a function.
Technical Debt: The implied cost of rework caused by choosing a quick solution now instead of a better approach.
Type Safety: The property of a program that prevents type errors at compile time.
These code quality standards are mandatory. Code that does not meet these standards is incomplete and must not be considered finished.