{ "title": "Split kcd2_dice_solver src/core/scoring.ts under the 250-line cap", "objective": "Bring kcd2_dice_solver/src/core/scoring.ts (361 lines) under the repo-wide 250-line file cap by extracting the move generator -- the enumeration of every legal single step from a position (straights, badge formations, n-of-a-kind, singles, and both joker rules) together with the n-of-a-kind value helpers -- into a sibling module, leaving Scorer with its caches and recursions, and proving Farkle scoring is unchanged with the project's own 288-test suite at 100% coverage.", "acceptance_criteria": [ "scoring.ts and the new sibling module are each at most 250 lines, and check_file_length.sh --all no longer lists src/core/scoring.ts.", "npx vitest run still reports 24 files and 288 tests, all passing -- no test was added, deleted, or had an assertion weakened.", "npx vitest run --coverage still reports 100% statements, 100% branches, 100% functions and 100% lines, with the same 863/375/181/810 totals, since no statement is added or removed.", "npm run lint (tsc --noEmit && eslint src) still exits 0 with no output.", "Every importer of a moved symbol imports it from the module that now defines it, with no re-export barrel added to scoring.ts for the moved symbols. scoring.ts's pre-existing re-export of CATEGORIES/FACES/WILD_ALONE/WILD_COMBO/CountVector from counts.ts predates this change and stays as it is.", "Zero suppressions added: no eslint-disable, no @ts-ignore, no @ts-expect-error, and vite.config.ts is byte-identical (thresholds and exclude untouched)." ], "out_of_scope": [ "Any change to the scoring rules themselves -- the doubling rule, the two joker rules, the Emperor/Tyche triple-only multipliers, the straight and badge-formation values, and the 'only a natural 1 or 5 scores alone' rule all keep their current semantics exactly.", "Changing Scorer's caching strategy or its public method set (score, scoreKey, scoreFaces, scoreUsingAll).", "Removing or altering scoring.ts's existing re-exports from counts.ts, which other modules rely on.", "Modifying vite.config.ts, including adding any new file to the coverage exclude list.", "Splitting badgeValue.ts or App.tsx -- each is its own separate commit.", "Wiring the file-length pre-commit hook -- it must land last." ], "verifier": "npx vitest run (expect 24 files / 288 tests passed); npx vitest run --coverage (expect 100% on all four metrics, totals 863/375/181/810); npm run lint (expect exit 0, no output); bash ~/utils/scripts/check_file_length.sh --all (expect src/core/scoring.ts absent from the listing); git diff --stat vite.config.ts (expect empty); grep -rn 'eslint-disable\\|ts-ignore\\|ts-expect-error' src/ (expect no new hits); pre-commit run --files on every touched file." }