Skip to content

refactor: decompose learn.ts 673-line action handler into independent functions #207

Description

@dean0x

Problem

The learn.ts action handler (lines 1-673) contains 11 top-level if branches, each implementing a different command flag (--run-background, --enable, --disable, --configure, etc.). This monolithic structure makes the module difficult to understand, test, and maintain.

Current State

async function action(args: LearnArgs): Promise<void> {
  // 673 lines of code with 11 top-level if branches:
  if (args['run-background']) {
    // ~80 lines: background agent execution
  } else if (args.enable) {
    // ~40 lines: hook installation
  } else if (args.disable) {
    // ~30 lines: hook removal
  } else if (args.configure) {
    // ~60 lines: configuration UI
  } else if (args['run']) {
    // ~50 lines: foreground agent execution
  } else if (args.list) {
    // ~40 lines: listing artifacts
  } else if (args.review) {
    // ~100 lines: interactive review
  }
  // ... etc
}

The function is difficult to test because you must instantiate the entire CLI argument parser and can't invoke individual handler logic.

Solution

Extract each flag handler into its own async function:

async function handleRunBackground(config: LearningConfig): Promise<void> {
  // ~80 lines: background agent execution
}

async function handleEnable(): Promise<void> {
  // ~40 lines: hook installation
}

async function handleDisable(): Promise<void> {
  // ~30 lines: hook removal
}

async function handleConfigure(): Promise<void> {
  // ~60 lines: configuration UI
}

// ... etc

async function action(args: LearnArgs): Promise<void> {
  if (args['run-background']) {
    return handleRunBackground(config);
  } else if (args.enable) {
    return handleEnable();
  }
  // ... etc
}

This also enables easier testing: handleRunBackground can be unit-tested without CLI machinery.

Scope

  • Create 11 handler functions (one per flag)
  • Move all implementation logic from the if branches into handlers
  • Update action() to dispatch to handlers
  • Add JSDoc for each handler explaining inputs/outputs
  • Update or add tests for individual handlers
  • Verify no behavioral changes

Benefits

  • Readability: Each handler is 40-100 lines of focused logic
  • Testability: Handlers can be unit-tested independently
  • Maintainability: Adding a new flag is a simple two-step process
  • Debugging: Stack traces point directly to handler, not buried in if-else chains

Related

  • Pre-existing architectural issue found in PR #??? code review
  • Complements #??? (observation-store extraction)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions