Skip to content

Refactor hot TypeScript modules and enforce the LOC ratchet #105825

Description

@steipete

Summary

Split the three highest-churn TypeScript modules along their existing concern boundaries and enforce the repository's file-size ceiling as a downward-only ratchet.

Problem to solve

src/gateway/server-methods/chat.ts, src/agents/embedded-agent-runner/run/attempt.ts, and src/agents/openai-transport-stream.ts combine separable responsibilities in files that are thousands of lines long and change frequently. This raises review and merge-conflict cost, while the existing check:loc implementation is not wired into normal checks or CI, so the oversized-file backlog can continue growing.

Proposed solution

  • Move chat history budgeting, TTS markers, assistant display assembly, origin routing, and server-timing logic into focused modules while keeping the handler table in chat.ts.
  • Decompose runEmbeddedAttempt into setup, stream transport, stream lifecycle, and finalize phases without changing cleanup ownership or runtime behavior.
  • Split OpenAI Responses and Completions transports into separate modules with shared parameter and usage helpers, retaining a stable facade for existing imports and SDK declarations.
  • Add a checked-in current-size baseline for production .ts, .tsx, .mts, and .cts files over 500 lines. Reject growth, new oversized files, stale baselines, and baseline increases relative to the PR/push base.
  • Run the ratchet from check, check:changed, and the CI guards shard.

Alternatives considered

  • File-only moves that leave the embedded attempt mega-function intact do not improve its control-flow shape.
  • A hard 500-line gate would require an unrelated repository-wide rewrite before any incremental improvement can land.
  • Splitting cohesive, low-churn storage modules would add boundaries without reducing current maintenance risk.

Impact

Maintainers get smaller ownership surfaces for the hottest gateway and agent paths, lower conflict pressure, and CI protection against future TypeScript file growth. Runtime behavior and public APIs remain unchanged.

Evidence/examples

The targeted modules were approximately 6,400, 6,500, and 4,900 lines respectively before the split. Focused transport, gateway, and embedded-runner tests; TypeScript checks; formatting/lint; a full changed gate; and a production build are part of the implementation proof.

Additional information

This intentionally leaves session-accessor.sqlite.ts unchanged because it is cohesive and comparatively low churn.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.enhancementNew feature or requestissue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.maintainerMaintainer-authored PR

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions