wake-alarm/TODO-file-length-250.md
Krzysztof kuhy Rudnicki 9379f14779 Add the removal marker to every TODO file
The rename commit staged the git mv but not the accompanying content
edit, so these TODO files landed without the "REMOVE ME AFTER FINISH"
line the md-naming gate requires. Repos whose hook was already live
refused that commit; repos without it accepted a file the gate would
now reject.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A47aX5DJwmA3QFn3pkEWi7
2026-08-24 15:56:24 +02:00

5.0 KiB

Refactor TODO — enforce the 250-line file cap

This file is a ready-to-use prompt. Paste it to Claude, or open this repo and say "do refactor_claude_todo". It is self-contained: everything needed to execute is below. Generated 2026-08-14 from a measured survey of every repo.

Goal

Every file in this repo must be at most 250 lines — source, tests, and prose (.md/.txt/.rst/.tex) alike — and must stay that way forever, enforced by a gate that fails the commit, not by a note anyone can ignore.

Why: a file that cannot be read in one piece forces re-reads and partial edits, which is the single largest avoidable cost in an LLM-assisted workflow. Aim by churn, not size alone — refactoring pays where code is read and changed often (Fowler, refactoring economic benefit).

Scope in this repo

  • 18 files currently exceed 250 lines (of 73 eligible files).
  • 6,553 lines sit in violation; longest file is 478 lines.

Exempt (do NOT split these):

  • generated files — *.g.dart, *.freezed.dart, *.gr.dart, **/l10n/generated/**, anything with a GENERATED header
  • markup — .html, .css, .scss
  • data files — .json, .yaml, .csv, wordlists and other data-ish .txt (mean line length under 25 chars)

Violations, highest ROI first

ROI = lines x commits in the last year. Work top-down; a long file nobody edits has near-zero payoff and should not be first.

lines commits/yr kind file
478 15 code wake_alarm/_alarm.py
438 12 code wake_alarm/tests/test_alarm_part2.py
435 12 code wake_alarm/tests/test_alarm.py
358 8 code wake_alarm/tests/test_alarm_part3.py
457 4 code wake_alarm/tests/test_alarm_sinks.py
283 6 code wake_alarm/tests/test_alarm_part4.py
329 4 code wake_alarm/_alarm_view.py
405 3 code wake_alarm/_audio.py
386 3 code wake_alarm/tests/test_sync.py
371 3 code wake_alarm/_sync.py
317 3 code wake_alarm/_escape_flow.py
314 3 code wake_alarm/tests/test_state.py
420 2 code wake_alarm/tests/test_alarm_audio.py
351 2 code wake_alarm/tests/test_smart_plug.py
341 2 code wake_alarm/_sinks.py

(3 further files over 250 lines not listed — re-run the survey for the full set.)

How to split

  • Python — extract cohesive helpers into sibling modules; keep the public API and imports stable.
  • Shell — split into lib/*.sh sourced by a thin entry script. Keep set -euo pipefail in each.
  • Dart / TypeScript — extract widgets/components into their own files.
  • Tests — split by test-group into sibling files (foo.test.ts -> foo.parsing.test.ts, foo.render.test.ts). Coverage must not drop.
  • Docs — split into topic files under docs/ with an index. For an oversized CLAUDE.md, move detail into referenced docs so the always-loaded part shrinks.

Do not game the cap: no one-lining, no deleting tests, no moving code into an exempt extension, no # noqa-style suppressions.

Make it permanent (required — this is the point)

A refactor without a gate silently regrows. Before this task is done:

  1. Wire the shared gate ~/utils/scripts/check_file_length.sh into this repo's .pre-commit-config.yaml as a local hook. If the repo has no pre-commit config, add a minimal one.
  2. The hook checks files in the commit (not the whole tree), so unrelated commits never break, and it fails — exit 1, not a warning.
  3. No baseline file and no allowlist. Those are suppressions.
  4. If this repo has CI (.github/workflows), add the same check there so it also fails on push.

Done condition

  • bash ~/utils/scripts/check_file_length.sh --all from this repo root exits 0.
  • The repo's own test suite and coverage bar are still green.
  • pre-commit run --files <changed files> passes.
  • A deliberately over-250-line test file, staged, makes git commit fail.
  • For a deployed daemon/app: the entry point still actually runs.

Verify

Run the suite, then the alarm entry point. The phone_app companion needs phone-deploy verification if touched.

Why this sat untouched (added 2026-08-24)

This repo ran a LOCAL scripts/check_file_length.py with MAX_LINES = 500, under a hook named "Max file length (500 lines)". It reported "gated" while permitting files every other repo rejects -- so the cap looked enforced and nothing ever failed. The hook now delegates to the shared 250-line gate in ~/utils, which reports 17 real violations.

Done condition is now an exit code, not a count:

bash scripts/check_file_length.sh --all   # must exit 0

REMOVE ME AFTER FINISH