Files

11 KiB

APOPHIS Codebase Bloat Assessment

Date: 2026-04-29 Scope: src/ directory (214 files, ~51,315 lines) Goal: Identify consolidation opportunities without functional changes


Executive Summary

The codebase has grown organically through rapid feature delivery. While functional, it exhibits several bloat patterns:

  • 17% of source files are under 30 lines (36 files) - excessive fragmentation
  • Test utilities duplicated across 9+ files - same helpers redefined
  • 7 builder files with identical patterns - could be unified
  • ~2,500 lines of dead/unused code - zero imports
  • Massive types.ts monolith (636 lines) - imported by 64 files, high coupling
  • CLI commands average 450+ lines each - complex control flow

Estimated consolidation potential: ~8,000-12,000 lines (15-23% reduction)


1. Module Fragmentation (36 files under 30 lines)

Critical Issues

File Lines Issue Suggestion
src/plugin/cleanup-builder.ts 12 Single wrapper function Merge into cleanup-manager.ts
src/plugin/scenario-builder.ts 16 Thin wrapper Merge into plugin/index.ts or unified builder
src/plugin/swagger.ts 15 Single export Merge into spec-builder.ts
src/infrastructure/security.ts 25 Constants only Merge into http-executor.ts or types.ts
src/infrastructure/logger.ts 22 Logger setup Merge into plugin/index.ts
src/infrastructure/seeded-rng.ts 30 Small utility Move to test/ or merge into utilities
src/test/precondition-checker.ts 12 Always returns true Delete - dead abstraction
src/cli/core/exit-codes.ts 10 Constants only Merge into cli/core/types.ts
src/cli/renderers/index.ts 10 Barrel file, zero consumers Delete

Barrel Files (7 files)

All are under 10 lines and just re-export. Modern bundlers handle this; they're unnecessary:

  • src/extensions/serializers/index.ts
  • src/extensions/sse/index.ts
  • src/extensions/websocket/index.ts
  • src/cli/index.ts (10 lines, just exports main)
  • src/cli/renderers/index.ts (zero consumers)

Impact: Remove ~15 files, save ~300 lines


2. Type Duplication

The types.ts Monolith Problem

src/types.ts (636 lines, 43 exports) is imported by 64 files - a high-fan-in coupling point.

Issues:

  • RouteContract defined here AND referenced in src/cli/core/types.ts
  • EnvironmentPolicy, ProfileDefinition, PresetDefinition defined in BOTH src/types.ts AND src/cli/core/config-loader.ts
  • HttpMethod union duplicated conceptually across parser, evaluator, and types

Suggested split:

src/types/
  core.ts          # Plugin types (RouteContract, EvalContext, etc.)
  cli.ts           # CLI types (Config, ProfileDefinition, etc.)
  formula.ts       # Formula types (OperationHeader, Comparator, etc.)
  extension.ts     # Extension types

Impact: Smaller import surfaces, clearer ownership boundaries, and potentially narrower recompilation impact

Formula Type Sprawl

  • src/formula/types.ts (131 lines): OperationHeader, Comparator, FormulaNode
  • src/domain/formula.ts (45 lines): Mirrors some formula types
  • src/types.ts (lines 115-140): Also defines formula-related types

Impact: Merge into single src/formula/types.ts, remove from src/types.ts


3. Utility Sprawl in Tests (30+ helper files)

Identical Functions Defined Multiple Times

APOPHIS_INTERNALS array and captureTestStack():

  • src/test/runner-utils.ts (lines 15-25)
  • src/test/stateful-result-utils.ts (lines 12-22)
  • Exact same code in both files

deduplicateFailures:

  • src/test/runner-utils.ts (lines 45-66)
  • src/test/result-deduplicator.ts (lines 20-50)
  • Different signatures but same purpose

Route filtering:

  • src/test/petit-suite-utils.ts (67L)
  • src/test/route-filter.ts (73L)
  • Both filter routes by scope/patterns with overlapping logic

Formatter Proliferation

4 separate formatting utilities that could be unified:

  • src/test/error-renderer.ts (93L) - renders errors
  • src/test/counterexample-formatter.ts (108L) - formats counterexamples
  • src/test/tap-formatter.ts (110L) - TAP format
  • src/test/result-formatter.ts (74L) - result formatting

Suggestion: Single src/test/formatters.ts with format strategies

Impact: Merge 8 files into 3, save ~400 lines


4. Builder Pattern Proliferation (7 files)

All builders in src/plugin/ follow identical pattern:

export const buildX = (deps) => async (opts) => { ... }
Builder Lines Complexity
check-builder.ts 45 Medium
cleanup-builder.ts 12 Trivial
contract-builder.ts 89 High
scenario-builder.ts 16 Trivial
spec-builder.ts 25 Low
stateful-builder.ts 32 Low
swagger.ts 15 Trivial

Suggestion: Unified builder system

// src/plugin/builders.ts
export const builders = {
  check: (deps) => async (opts) => { ... },
  cleanup: (cm) => async () => cm.cleanup(),  // 1-liner
  contract: (deps) => async (opts) => { ... },
  // etc.
}

Impact: 7 files → 1 file, save ~150 lines of boilerplate


5. Test File Bloat (88 files, 26,938 lines)

Over-Testing

src/test/cli/config-validation.test.ts is 4,194 lines with 279 test cases.

  • Tests every permutation of invalid config
  • Could use parameterized tests or property-based testing
  • Potential reduction: 4,194 → ~800 lines (80%)

Duplicate Test Helpers

17 CLI test files define their own:

  • makeCtx() - defined in 9 files
  • createTestContext() - defined in 7 files
  • createTempDir() - defined in 9 files
  • cleanup() - defined in 9 files

Suggestion: src/test/cli/helpers.ts with shared test utilities

Overlapping Test Concerns

  • acceptance.test.ts (328L) and regression.test.ts (259L) both test "run all commands"
  • verify.test.ts and verify-ux.test.ts test similar verify behavior
  • doctor.test.ts and doctor-consistency.test.ts overlap

Impact: Merge/parameterize tests, save ~2,000 lines


6. Redundant Abstractions

Type-Only Files

File Lines Content Suggestion
src/infrastructure/cleanup.ts 18 Types only Merge into cleanup-manager.ts
src/infrastructure/cache.ts 23 Types only Merge into incremental/cache.ts
src/infrastructure/http-types.ts 32 3 interfaces Merge into types.ts or http-executor.ts
src/infrastructure/security.ts 25 Constants Merge into http-executor.ts

Dead Abstractions

  • src/test/precondition-checker.ts (12L): checkPreconditions() always returns true
  • src/test/plugin-contract-composer.ts (24L): composeEnsures() never imported
  • src/cli/renderers/index.ts (10L): Barrel file, zero consumers

Impact: Remove 5 files, save ~100 lines


7. Dead Code (Zero Imports)

File Lines Reason
src/protocol-packs/index.ts 184 New feature, not integrated yet
src/quality/mutation.ts 298 Mutation testing, not wired
src/test/result-formatter.ts 74 Replaced by other formatters
src/test/hypermedia-validator.ts 307 Only used by its own test
src/test/cascade-validator.ts 185 Only used by its own test
src/test/error-renderer.ts 93 Only used by counterexample.test.ts

Total dead code: ~1,141 lines

Note: protocol-packs/index.ts should be kept (new feature), but mutation.ts and test-only utilities should be evaluated.


8. Control Flow Complexity

Most Complex Functions (by control-flow statements)

File Lines Control-Flow Issue
src/cli/commands/qualify/index.ts 650 130 Giant command handler
src/cli/commands/verify/index.ts 505 122 Too many branches
src/cli/commands/replay/index.ts 513 116 Complex fallback logic
src/quality/chaos-v3.ts 504 82 Large switch statements and high branch count
src/domain/contract-validation.ts 301 53 Deep nesting
src/test/scenario-runner.ts 283 47 Cookie/form/capture logic

Specific Issues

src/test/failure-analyzer.ts (143L, 40 control-flow):

  • 15+ sequential if-else branches for different failure patterns
  • Could use a pattern table/dictionary:
const analyzers = {
  'timeout': analyzeTimeout,
  'crash': analyzeCrash,
  // etc.
}

src/cli/commands/qualify/index.ts (650L):

  • Handles scenario, stateful, AND chaos execution
  • Could split into sub-handlers:
// qualify/index.ts - orchestrator only
// qualify/scenario-handler.ts
// qualify/stateful-handler.ts
// qualify/chaos-handler.ts

src/quality/chaos-v3.ts (504L):

  • Large switch statements for event types
  • Could use strategy pattern or event registry

Consolidation Roadmap

Phase 1: Quick Wins (Low Risk, High Impact)

  1. Delete dead files: precondition-checker.ts, cli/renderers/index.ts
  2. Merge tiny builders: cleanup-builder.ts, scenario-builder.tsplugin/builders.ts
  3. Merge type-only files: cleanup.ts, cache.ts, http-types.ts into their implementations
  4. Remove barrel files: 7 index.ts files

Estimated savings: ~1,500 lines, 15 files removed

Phase 2: Test Consolidation (Medium Risk)

  1. Create src/test/cli/helpers.ts: Shared test utilities
  2. Parameterize config-validation tests: Reduce 4,194 lines
  3. Merge overlapping test files: acceptance + regression, verify + verify-ux
  4. Consolidate formatters: Single formatter module

Estimated savings: ~3,000 lines, 20 files removed

Phase 3: Structural Refactoring (Higher Risk)

  1. Split types.ts monolith: Into domain-specific type modules
  2. Unified builder system: Single builders.ts with all build functions
  3. Split CLI commands: Sub-handlers for qualify, verify
  4. Pattern-table refactor: failure-analyzer, chaos-v3

Estimated savings: ~4,000 lines, improved maintainability

Phase 4: Architecture Cleanup

  1. Evaluate protocol-packs integration: Wire into config system or remove
  2. Evaluate mutation.ts: Wire into test runner or remove
  3. Review extension system: 15 extension files, some may be redundant

Metrics Summary

Category Current Target Reduction
Source files 214 ~170 20%
Source lines 51,315 ~42,000 18%
Test files 88 ~65 26%
Test lines 26,938 ~20,000 26%
Files under 30L 36 5 86%
Dead code files 6 0 100%

Total potential reduction: ~16,000 lines (21% of codebase)


Recommendations Priority

  1. Immediate (this week): Delete dead files, merge tiny builders, remove barrel files
  2. Short-term (next 2 weeks): Test consolidation, shared helpers
  3. Medium-term (next month): types.ts split, builder unification
  4. Long-term (next quarter): CLI command refactoring, pattern tables

Report generated without code changes. All metrics based on static analysis.