Coding Standards and Best Practices

All code must be reviewed before merging to the main branch.
Every function must have a clear, single responsibility.
Variable names must be descriptive and follow camelCase convention.
Constants must be named in UPPER_SNAKE_CASE.
Avoid magic numbers; use named constants instead.
Keep line length under 120 characters.
Use four spaces for indentation, never tabs.
Files must end with a newline character.
Remove trailing whitespace from all lines.
Do not commit commented-out code.
Delete dead code instead of leaving it in place.
Write self-documenting code; comments explain why, not what.
All TODO comments must reference a ticket number.
Do not use abbreviations that are not widely understood.
Use positive variable names; prefer isActive over isNotInactive.
Avoid double negatives in conditional expressions.
Keep nesting levels to a maximum of three.
Extract complex conditions into named boolean variables.
Use early returns to reduce nesting.
Avoid else after return.
Keep functions under 40 lines of code.
Keep files under 300 lines of code.
Split large files into smaller, focused modules.
Use named exports, not default exports.
Group imports: standard library, external, internal.
Sort import groups alphabetically.
Do not use wildcard imports.
Remove unused imports before committing.
Use absolute imports for cross-module dependencies.
Use relative imports only within the same module.
Avoid circular dependencies between modules.
Use barrel files only at module boundaries.
Do not re-export from multiple barrel files.
Prefer named interfaces over inline type definitions.
Use generic types to avoid duplication.
Avoid type assertions unless absolutely necessary.
Do not use ts-ignore comments without explanation.
Enable strict mode in tsconfig.
Use unknown instead of any for unsafe types.
Prefer type narrowing over type assertions.
Use discriminated unions for complex state.
Model optional fields explicitly with undefined.
Avoid null; prefer undefined.
Use optional chaining for nullable access.
Use nullish coalescing for defaults.
Do not mix null and undefined in the same API.
Use enums for finite sets of values.
Prefer const enums for performance-sensitive code.
Do not extend enums dynamically.
Use readonly arrays and objects where mutation is unintended.
Prefer immutable data structures in shared state.
Avoid mutations in pure functions.
Use spread operators for shallow copies.
Use structuredClone for deep copies.
Do not mutate function parameters.
Return new objects from transformation functions.
Use Array methods over imperative loops where readable.
Avoid side effects in map and filter callbacks.
