Awesome Reviewers

When code introduces multiple “modes” (output modes, session start vs resume, tool vs run-start context) or repeats non-trivial logic (git checks, shell detection, escaping/formatting), prefer explicit variant modeling and centralized utilities rather than duplicating logic or branching everywhere.

Guidelines

Example (strategy + discriminated union)

type SessionKind =
  | { kind: "start" }
  | { kind: "resume" };

type RunOutputter = {
  runStarted(): void;
  runResult(result: unknown): void;
  runAborted(err: unknown): void;
};

function createOutputter(outputMode: "json" | "console", verbose: boolean): RunOutputter {
  return outputMode === "json"
    ? new JsonRunOutputter({ verbose })
    : new ConsoleRunOutputter({ verbose });
}

async function runAgent(session: SessionKind) {
  const outputter = createOutputter("json", /* verbose */ false);

  if (session.kind === "resume") {
    // dispatch agent_resume
  } else {
    // dispatch agent_start
  }

  outputter.runStarted();
  // ... straight-line lifecycle calls
}

Applying this consistently yields code that is easier to read, easier to extend, and less prone to subtle drift between duplicated implementations.