Skip to content

refactor: split oversized production files to satisfy repository policy #711

Description

@ninthworld

Parent: #713.

Updated 2026-08-07 against main at 47e26cc. Every file the original body named has since
been split. The policy breach did not go away with them — the M19 tranche (#706) regrew the same
seams under new names, so the file list below is current and the old one is preserved at the
bottom as the before-half of the record this issue's acceptance criteria ask for.

Problem

Root AGENTS.md sets an approximately 800–1,000-line limit and docs/coding-standards.md calls
1000+ a hard smell to break up before adding more code. Twelve production source files exceed
1,000 lines
, counting code only — a file's own #[cfg(test)] mod tests { … } block is excluded,
and files whose tests live in a sibling tests.rs are counted in full.

File Code lines
crates/sage-engine/src/ability/effect.rs 1,936
crates/sage-server/src/rules_text/effects.rs 1,625
crates/sage-engine/src/state/zone.rs 1,236
crates/sage-engine/src/apply/cast/targeted.rs 1,232
crates/sage-engine/src/triggers.rs 1,225 (of 1,631 total)
crates/sage-engine/src/apply/cast/effects.rs 1,195
crates/sage-engine/src/choice/mod.rs 1,163
crates/sage-server/src/rules_text.rs 1,152
crates/sage-engine/src/state/types.rs 1,119
clients/web/src/interaction.ts 1,108
crates/sage-engine/src/resolve.rs 1,039
clients/web/src/protocol.ts 1,002

Six more sit in the 800–1,000 soft-ceiling band and are worth watching rather than splitting now:
clients/prototype/src/App.tsx (963), crates/sage-engine/src/actions/generation.rs (863),
crates/sage-engine/src/catalog/effects.rs (858), clients/web/src/ui/game/Board.tsx (857),
crates/sage-protocol/src/card.rs (831), crates/sage-engine/src/actions/definition.rs (801).

clients/prototype/src/styles.css (3,228) is out of scope: the prototype is a throwaway
sandbox and the repository's design and structure doctrine does not govern it.

These are again exactly the seams the next rules or protocol work will land in — ability/effect.rs
and rules_text/effects.rs are the two halves of the same vocabulary, and every card added widens
both.

Scope

Perform behavior-preserving splits along cohesive existing domains with root re-exports. Sequence
the work in small PRs rather than one repository-wide rewrite.

Suggested waves, in payoff order:

  1. The effect vocabularyability/effect.rs and its rules-text mirror
    sage-server/src/rules_text/effects.rs, split along the same domain seams so the two stay
    readable against each other.
  2. Engine statestate/zone.rs and state/types.rs.
  3. Cast applicationapply/cast/targeted.rs and apply/cast/effects.rs, which were
    themselves produced by the previous wave and have since regrown.
  4. Triggers, choices, and resolutiontriggers.rs, choice/mod.rs, resolve.rs.
  5. Clientinteraction.ts and protocol.ts.

Acceptance criteria

  • No production source file remains materially above the documented limit without a written exception.
  • Public APIs and serialized wire shapes remain unchanged.
  • Each split is single-purpose and reviewable.
  • Existing unit, integration, parity, agent-game, and browser tests remain green.
  • Module boundaries follow domain ownership rather than arbitrary line-count chunks.
  • No mechanic or product behavior is added in the refactor PRs.
  • Before/after line counts are recorded.

Non-goals

  • Broad renaming or formatting churn.
  • New abstractions without an existing domain seam.
  • Combining rules expansion with structural refactoring.

Original list (2026-08-04) — all of these are now split

Sixteen non-test production files exceeded 1,000 lines; the largest and most central were:

  • crates/sage-engine/src/apply/cast.rs — ~2,696
  • crates/sage-engine/src/apply/combat.rs — ~2,104
  • crates/sage-engine/src/ability.rs — ~1,849
  • crates/sage-server/src/lobby/commands.rs — ~1,521
  • crates/sage-engine/src/characteristics.rs — ~1,398
  • crates/sage-server/src/lobby.rs — ~1,332
  • crates/sage-server/src/view/requirements.rs — ~1,262
  • crates/sage-protocol/src/lobby.rs — ~1,215
  • crates/sage-server/src/rules_text.rs — ~1,190
  • seven additional production files between ~1,017 and ~1,168 lines

Not one of them is over the limit today: cast.rs became apply/cast/, combat.rs became
apply/combat/, ability.rs became ability/, characteristics.rs became characteristics/
with a module per CR 613 layer, and the server's lobby, view, and protocol files split the same
way. rules_text.rs is the one that came back — it is 1,152 lines again, with a
rules_text/effects.rs of 1,625 beside it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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