Upstream clone at ~/Mapperatorinator is a third-party sibling (MIT,
github.com/OliBomby/Mapperatorinator), driven by subprocess from
~/osu-automapper and never vendored or modified.
Verified both directions: is_vendored() returns True for a 2538-line upstream
file (which would otherwise fail the cap) and False for ~/osu-automapper's own
sources, which stay gated.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018iJHHN18dud8dXpjd7ff3R
An implementation plan under docs/superpowers/plans/ and an append-only log
under docs/superpowers/sessions/ are frozen records of one past session. They
are read whole or not at all, so splitting one rewrites a historical record
for no reading benefit -- the same reason generated files are exempt.
Scoped deliberately: specs/ and contracts/ stay capped, because those are
living documents that get re-read and edited.
is_session_artifact() is kept separate from is_vendored() so the gate reports
an accurate reason -- these are kuhy's own files, not third-party code.
Relaxes the gate only, so no already-wired repo can newly fail. Verified:
~/todo still exits 0 on --all; testsAndMisc drops 198 -> 197 violations
(plans/ exempt, specs/ still caught) in both absolute and relative modes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Three exemptions the first cut missed, all of them files no commit could
ever fix:
- Git-ignored files (todo's exported BACKLOG.md, logs, scratch dumps).
These are rewritten wholesale by whatever produces them, so splitting one
is meaningless, and pre-commit never sees them anyway. Applied to
explicitly-named paths as well as --all, so the two modes cannot disagree
about the same file.
- Vendored agent-skill bundles (.agents/skills, .claude/skills). A SKILL.md
is a fixed-name file with frontmatter; splitting one breaks the format.
Matched by directory name wherever it appears, since these get dropped
into any repo.
- .utils, where CI checks out this repo. Without it a repo's lint job fails
on utils' own long files, which that repo cannot fix.
Baseline accordingly drops from 657 to 597. Re-verified all eight fixtures:
over-cap fails, under-cap passes, generated/vendored/wordlist/git-ignored
exempt, prose still capped, and the gate still passes on its own source.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7yZz45ezmzCB89Cv5gAtZ
The measured distribution the 250-line cap was derived from, and the 657
files currently over it, so the baseline is reproducible rather than a
number in a commit message.
Stored as JSON, not a text list: a 651-line .txt would itself have failed
the gate, and the data belongs in a data file.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7yZz45ezmzCB89Cv5gAtZ
Files that cannot be read in one piece force re-reads and partial edits,
which is the largest avoidable cost in an LLM-assisted workflow. This adds
the enforcement side of a 250-line cap covering code AND prose.
- file_length/config.py: single source of truth for the cap and its
exemptions (generated, markup, vendored, data-ish txt), shared by both the
gate and the survey so the two cannot silently disagree.
- file_length/check.py: the check itself. Exits 1 and lists violations;
adjudication is an exit code, not a judgement call.
- scripts/check_file_length.sh: thin wrapper pre-commit calls with staged
files.
Verified against six fixtures: over-cap code fails, under-cap passes,
generated l10n (1417 lines) exempt, vendored pdfjs exempt, the 174800-line
wordlist exempt as data, and a 1101-line CLAUDE.md correctly fails since
prose is capped too.
Baseline at time of writing: 657 files over 250 lines across 29 repos.
Each repo carries a refactor_claude_todo.md prompt with its own list.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7yZz45ezmzCB89Cv5gAtZ