Commit Graph

952 Commits

Author SHA1 Message Date
093e2f6f68 Split the reverse_survivors test files; defer its two core sources
sim.test.ts 698 -> 175 and director.test.ts 315 -> 178, into four new
modules. 160 tests passing before and after.

sim.ts and types.ts are reverted. sim.ts's exported step() calls
survivorStep, which any seam moves out - 63 tests failed with a
ReferenceError while tsc reported only unused imports. types.ts has its
difficulty tables below the type declarations that use them.

Third project now where a TypeScript seam compiles clean and fails at
runtime. In TS, tsc does not tell you a split worked; the test run does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:26:59 +02:00
45b56b3e61 Split the Pi flasher and the boot-repair test harness
raspberry_pi_flash_sd.sh 661 -> 166 and test_boot_repair.sh 315 -> 104.
Heredoc positions were checked before choosing seams this time.

test_boot_repair.sh is the first linux_configuration script in this
effort that could be verified by running it: every case builds a
throwaway root in a temp dir and passes --root. 31 passed after the
split, and 31 passed from a detached worktree at HEAD - a real baseline
comparison rather than trusting the post-split number.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:21:44 +02:00
5387c5d19d Record the heredoc trap; update the handoff to 87 left
The deferred list is now a table of seven shell scripts plus the two
TypeScript ones, each with the specific variable or construct that
blocks it. All share one cause: state, or a heredoc, crossing the seam.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:18:26 +02:00
0aa78ea7aa Split three more scripts; make the verifier catch heredoc cuts
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
transcribe.sh 473 -> 39, setup_activitywatch.sh 457 -> 102 and
setup_wireguard_ssh.sh 464 -> 136.

enforce_vbox_hosts.sh is reverted: its seam landed inside a heredoc and
the resulting lib had an unterminated here-document. That is the worst
failure yet, because shellcheck reported it only as SC1094 on the caller
- which reads like a nicety, not a file that will not parse. The
verifier now runs bash -n over every lib before linting the entry and
names the offending file; proven by corrupting a copy and restoring it.

Also guarded a cd before `git clone ... .`, which would otherwise have
cloned an AUR repo into the caller's directory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:16:08 +02:00
63650fbc45 Split offline docs and arch optimiser; defer libre_translate
setup_offline_docs.sh 713 -> 121 across six libs, carved one language at
a time since the first cut left offline_cpp at 545. optimize_arch_
desktop.sh 623 -> 118.

Two recurring traps again: a script with no SCRIPT_DIR at all, and libs
that chained rather than being sourced from the entry. Both now checked
for routinely.

libre_translate.sh is reverted and stays at 488. Exporting GENERATED to
fix one SC2034 revealed eighteen more - when a fix uncovers more of the
same, the seam is imaginary, not the fix wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:09:54 +02:00
ebe56f0419 Update the handoff: 92 left, half the original count cleared
Records prose done, kcd2 down to four source files, and that a bad
TypeScript seam compiles clean and only fails at runtime via an import
cycle - so the suite is the check there too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:05:44 +02:00
776e04db89 Split the kcd2_dice_solver test files under the cap
Nine new modules from four over-cap test files. Every kcd2 test file is
now under 250 lines; only four source files remain.

App.test.tsx ended up with no describe blocks and vitest failed with
"No test suite found" - a split that empties a file has to delete it.
The shared `response`/`ordinary` fixtures went to src/test/fixtures.ts,
which vite.config.ts excludes from coverage; beside the source they
would have counted as production code and broken the 100% gate.

288 tests passing before and after, now across 24 files instead of 15,
coverage still 100% on all four metrics.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:03:33 +02:00
5a27acd9d0 Split kcd2 simulate and inventoryIo; revert two seams
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
simulate.ts 384 -> 226 and inventoryIo.ts 287 -> 178, with the moved
names re-exported so no importer or test changed.

search.ts and badgeValue.ts are reverted. findBestSet calls enumerateAll
and hillClimb which call back into expand; valueBadge and format are
mutually recursive with the recommendation half. Splitting either makes
the two files import each other.

The split also exposed a TypeScript hazard worth knowing: with the local
Selection type no longer imported, tsc silently resolved it to the DOM
global and complained about anchorNode and focusNode rather than saying
the name was missing.

288 tests passing before and after, coverage still 100%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:55:52 +02:00
c04001329e Split the kcd2_dice_solver data tables under the cap
dice.ts 415 -> 93 and badges.ts 369 -> 111, with the literal tables in
six new modules. Every previously exported name is still exported from
the same path, so no importer or test changed.

Two import cycles on the way, both of which tsc and eslint called clean
and which only showed up as a runtime TypeError when 11 test files
failed with "Cannot read properties of undefined (reading tin)".
HEADSTART_POINTS now has its own module so both halves of the badge
table can use it at init time.

288 tests passing before and after, coverage still 100% on all four
metrics with the new modules measured.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:50:54 +02:00
7a74804786 Split three more linux_configuration giants
raspberry_pi_nextcloud.sh 1276 -> 163, root_bl9000.sh 1116 -> 211,
lookup_docs.sh 942 -> 165. Sixteen new libs.

lookup_python was one 300-line function; its keyword-to-anchor mapping
became python_keyword_doc, emitting result and desc tab-separated so the
caller keeps its control flow.

bl9000_mtkclient had cd X; work; cd - with three return paths.
install_mtkclient became a subshell; extract_boot_with_mtkclient could
not, since it exports BOOT_IMG - so the venv check moved before the cd,
the cd is guarded, and the restores use a saved $PWD.

Four more unguarded cd calls fixed, and a third instance of the lib
chaining bug flattened. lookup_docs.sh had no SCRIPT_DIR at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:43:55 +02:00
5bacfa3883 Split setup_nextcloud_raspberry.sh 1383 -> 231
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Eight libs from the largest script in linux_configuration: five in the
first pass, then three of those carved again since they landed at 272,
292 and 277.

Fixed three more unguarded cd /var/www/nextcloud calls, each right
before an occ command - the installer would have run against whatever
directory the caller was in. Third script with this bug.

check_and_enable_services.sh is reverted and stays at 1337. Its
SERVICE_STATUS array is declared once and written by every check_*
function, so any lib holding them fails SC2034 alone. Fourth file
deferred for shared state, and the clearest: the script is an
accumulator, so there is no seam anywhere in it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:37:07 +02:00
cffd4587cf Apply prettier to two split prose files
prettier only runs on pre-push, so the split commit passed the per-file
gate and then failed the push. Both files stay under the cap.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:31:54 +02:00
346eb1f00b Bring every markdown file under the cap
Twelve prose violations to zero. Eight files split into per-topic
subdirectories with the original left as an index; both SKILL.md files
keep their frontmatter so discovery still works, with detail moved to
references/.

Deleted docs/cleanup-2026-05/ (7 files) and linux_configuration/docs/
VERIFICATION.md on the user's ruling: unreferenced records of finished
work whose rules are now enforced by the polling, shellcheck and shfmt
hooks. PACMAN_WRAPPER_SECURITY.md was split instead - unlike those, it
documents live guarantees.

Every split verified by a sorted diff against HEAD: zero content lines
lost, only the new headings and index links added.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:25:59 +02:00
8a8a91aec3 Update the handoff: 116 left, four shell files deferred for one reason
All four deferred linux_configuration scripts share a root cause -
state crossing the seam - so they are now one table with the specific
variable named for each, rather than a prose list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:19:18 +02:00
194b006453 Split fix_bluetooth.sh 720 -> 186; defer steam_compatibility.sh
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Four libs written in one pass rather than four sequential splits, which
is what stops the libs chaining - the entry gets one source block naming
all four and no lib sources a sibling.

steam_compatibility.sh is reverted and stays at 663. Its CACHE_MAP
associative array is declared and filled in what would be the ProtonDB
lib but read by main, so that lib fails SC2034 linted alone. Third file
deferred for the same reason: shared mutable state means the seam is not
there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:17:05 +02:00
0b0cea706d Record the content-hash check for config-generating scripts
The stubbed run proves the functions exist, not that what they write is
unchanged. Adds the before/after hash comparison used on setup_searxng,
and the rule that a heredoc travels with the comment explaining it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:13:13 +02:00
d9c315e3ef Split setup_searxng.sh 912 -> 184
Six libs: the script has four phases and write_stack alone was 342 lines
because it emits three config files from heredocs. That became three
functions, one per file, each keeping the comment that explains it -
including why settings.yml is mode 640 and not 600.

For a script whose job is writing config, "the functions still exist" is
not enough. Compared the sorted non-comment lines of the original
write_stack against its three successors: identical hash, so every line
of emitted compose, settings.yml and limiter.toml is byte-for-byte the
same and only the wrappers were added.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:11:40 +02:00
b84ad9d971 Update the handoff: 118 left, three shell files deferred with reasons
Also records that the pre-commit shellcheck hook lints each lib in
isolation - stricter than shellcheck -x on the entry, and the check that
decides whether a seam is real - and corrects the old advice to repeat
set -euo pipefail in every lib.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:08:17 +02:00
2527fb37e6 Split three large linux_configuration scripts, defer a fourth
organize_downloads.sh 513 -> 72, setup_kcd2_dice_solver.sh 497 -> 112,
fix_ubuntu_performance.sh 494 -> 150. First 490+ line scripts done; all
three needed two or three seams.

Repeated splitting chained the libs - each sourced the next, because the
tool inserts its source line relative to the file it just wrote.
Flattened so the entry sources all three and no lib sources a sibling.

diagnose_pacman_hook_stall.sh is reverted and stays at 493. Its
transaction runner assigns LAST_ELAPSED that the caller reads and reads
PACMAN_BIN that the caller defines, so linted alone it is SC2034 plus
SC2153. The pre-commit hook lints each lib in isolation and fails, while
shellcheck -x on the entry passes - suppressing that would be papering
over a seam that does not exist.

organize_downloads.sh is the ExecStart of media-organizer.service; the
unit still resolves and the script still parses.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:06:16 +02:00
4ac8c77abd Update the handoff: 121 left, linux_configuration 84 -> 63
Records the six shell batches, the two files deliberately left over the
cap with their reasons, and points at the verifier script rather than
describing the check in prose.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 19:01:22 +02:00
dbc4d099a3 Commit the shell-split verifier and the traps it found
meta/scripts/verify_shell_split.sh was a scratchpad file; it has caught
five bugs across 18 splits that bash -n and shellcheck both passed on,
so it belongs in the repo. Tested in both directions - it fails on a
deliberately broken source line and passes once restored.

docs/shell-split-recipes.md gains what the last two batches taught:
splitting a file twice can displace the first cut's source line, globals
read across a seam have three different fixes depending on how many, and
unguarded cd shows up constantly because a moved function finally gets
linted on its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:59:20 +02:00
7e967de79b Split seven more linux_configuration scripts
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
10-recon.sh, install_exercism.sh, fix_arch_performance.sh,
format_sd_card.sh, setup_dot_resolver.sh, fix_unity.sh and
20-dump-stock.sh, all now under the cap.

Splitting a file twice is the risky move: the second cut on
20-dump-stock.sh dropped the first cut's source line, leaving
verify_dump called but never defined, and the repair then landed the
line inside the lib instead of the entry script. Both fixed - the entry
sources both libs and no lib sources another. Grep the source lines
after any double split.

fix_unity.sh's desktop_dir is read across the seam; renamed to
DESKTOP_DIR to match the file's own convention for globals.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:56:05 +02:00
58fdc6c9de Split five more linux_configuration single_use scripts
install_unreal_mcp.sh 395 -> 155, diagnose_arch_performance.sh 377 ->
123 (two cuts), setup_local_llm.sh 370 -> 163, repo_to_study.sh 365 ->
160, setup_dwm.sh 359 -> 147.

The SCRIPT_DIR fix from the last batch held on all five. Fixed a second
unguarded cd, this time before the study-material generator ran - the
same latent bug class as build_website, surfaced because a moved
function gets linted in isolation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:51:28 +02:00
1a75ed5bf5 Split three more linux_configuration feature and fix scripts
setup_syncyomi.sh 408 -> 138 (two cuts), setup_personal_website.sh
396 -> 192, fix_thorium.sh 377 -> 208.

All three already declared SCRIPT_DIR and the splitter added a second
one, which aborts at runtime with "readonly variable" while bash -n and
shellcheck stay clean. The stubbed run caught it; the splitter now
reuses an existing declaration.

Fixed SC2164 in build_website rather than suppressing it: a bare
cd "$WEBSITE_SRC" inside a subshell, with pnpm install and pnpm run
build after it. A failed cd would have built in the caller's directory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:48:01 +02:00
9e62430b8d Split two more linux_configuration scripts; revert a third
control_from_mobile.sh 415 -> 180 and setup_periodic_system.sh 408 -> 228.

setup_periodic_system.sh has no main(): it defines functions then runs a
block of top-level calls, and the splitter moved that block into the lib,
changing when it ran. Redone by hand moving only definitions. It also
asks for sudo at source time, so the stubbed run is off-limits - verified
instead that the source line precedes the first call and all eleven
invoked functions are defined exactly once across the two files.

clean_audio.sh is reverted and stays over the cap. Two probe-result
globals are read from what would be two different libs, and renaming
them to satisfy SC2154 only moved the warning along. That is a refactor,
not a line-count split, and forcing it would have cost a suppression.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:44:18 +02:00
658988ef9b Split three near-miss linux_configuration scripts
turn_off_auto_idle_screen_shutdown.sh 289 -> 180, mtk_root/install.sh
262 -> 141, setup_gitea.sh 255 -> 198. A deliberately small batch to
check jscpd before scaling; it stayed well under 2%.

The stubbed run earned its place again: mtk_root/install.sh aborted with
"SCRIPT_DIR: readonly variable" because it already declared one, and
both bash -n and shellcheck were clean on that broken file.

Two shellcheck findings the split exposed are fixed at the source, not
suppressed: persist_with_systemd_logind now takes the flag as an
argument instead of reading the caller's global, and a dead python_bin
assignment is gone. Neither was introduced here - the pre-split file
already had three SC2034 warnings.

No script was executed; all three are installers or enforcement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:38:43 +02:00
dadd33f82d Split install_joplin.sh and establish the shell-split pattern
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
299 -> 103, with the --with-server half in lib/joplin_server.sh. First
of the 84 linux_configuration files, done slowly to settle the pattern.

Three things bash -n and shellcheck do not catch, all found here:

- SCRIPT_DIR from "$0" breaks when the entry script is itself sourced.
  Use "${BASH_SOURCE[0]}"; keep readlink -f for the one symlinked script.
- A lib needs a shebang AND +x: without the shebang shellcheck raises
  SC2148, with it the shebang-executable hook fails. Match common.sh.
- Only a stubbed run proves the source line resolves. Copy entry+lib to
  a mktemp -d, sed `main` into a declare -F probe, run that. No
  installer step executes.

Also enumerates which scripts escape the repo: three copied out by
install_pacman_hooks.sh, one symlink, everything else generated. All
recorded in docs/shell-split-recipes.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:33:59 +02:00
de930f3277 Apply prettier to the handoff and recipe docs
prettier only runs on pre-push, so the previous commit passed the
per-file gate and then failed the push. No line counts changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:27:18 +02:00
b5c357a011 Refresh the handoff: python_pkg done, 142 left, shell rules recorded
Updates the counts (183 -> 142, python_pkg 50 -> 0) and records what the
eight python_pkg packages taught: the seam-selection rule, that a
mispointed patch can hang rather than fail, and the copy-preamble-then-
let-ruff-prune order for test splits.

Adds docs/shell-split-recipes.md for the linux_configuration tranche,
where there is no pass count to verify against - names the two live
systemd units that point at repo paths and the jscpd trap on the first
multi-lib commit. Decision 10 records the user's call to fix lint rather
than relocate a per-file-ignore.

The handoff had grown to 280 lines splitting it out, which would have
been a new violation; it and both recipe docs are now under the cap.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:24:22 +02:00
4b2cd0c398 Clear the wsg_grabber test modules: python_pkg is now under the cap
The last six over-cap files split into eleven new modules, in two passes
since the first cut left five still over. python_pkg has no violations
left at all, down from 50 when this effort started.

Each split carries the whole preamble including the module's pytest
fixtures - started, toolkit and session are taken as parameters and
resolve lexically, so a hand-written import block would have missed
them. ruff then pruned 82 unused imports.

Pass count is 277 before and after, checked after both passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:19:26 +02:00
b60cb4972a Clear five python_pkg packages under the cap
android_ui, app_icons, token_audit, focus_policy and random_jpg are now
entirely under 250 lines. Only wsg_grabber's six test modules remain in
python_pkg.

android_ui/driver.py 411 -> 205 took two cuts and a class split: the
element and error types plus the XML parser to _elements.py, and the
text-entry methods to a TextEntryMixin, using the ABC-with-abstract-
methods shape because the tests call them as bound attributes.
app_icons/glyphs.py 291 -> 93 by moving the twelve path fragments out.

Three intermediate failures, all module-level globals that travelled
with their code (_logger, re, _SAME_FIELD_X_TOLERANCE_PX) - the same
class of miss as _make_verifier, which ruff cannot flag.

Counts unchanged: 81, 137, 14, 44, 57.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:14:36 +02:00
e3214c813c Clear the seven over-cap code_tutor test modules
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Partitioned at the section banners each file already used, into ten new
modules named for what they cover. python_pkg/code_tutor is now entirely
under the cap, from thirteen violations.

The splitter copies the whole original header into each new file and
lets ruff's F401 pass prune it - 59 imports removed correctly, versus a
hand-written import block failing on every earlier test split today.
That does not cover module-level helpers: _make_verifier sat between two
banners and was left behind by its callers, so it moved to conftest.py,
taking test_verifier.py's shadowing copy of _make_live_mock with it.

No patch string changed. Pass count is 217 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:06:38 +02:00
eb322dcf80 Split the Claude backend out of code_tutor/_llm
_llm.py 295 -> 217, clearing the last code_tutor source violation; only
its seven test modules remain over the cap.

The seam falls between the two backends because each pins a different
plain import: test_llm.py patches requests.post on _llm for
OllamaBackend and anthropic.Anthropic for ClaudeBackend. _llm keeps its
own anthropic import - complete_with_fallback still catches APIError -
so the four anthropic patch strings were split per test rather than
moved wholesale.

Pass count is 217 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 18:00:53 +02:00
1d1938ce23 Split code_tutor cli and verifier, deleting two lint suppressions
cli.py 345 -> 222 and _verifier.py 347 -> 228, via _cli_checks.py and
_verifier_support.py.

The cli seam cut straight through code covered by its per-file-ignores.
Rather than copy S607 and PERF203 onto a second entry, both are fixed:
systemctl is resolved with shutil.which, and the readiness poll no
longer carries a try/except in its body now that the probe is its own
function. Both ignores are deleted from meta/pyproject.toml and ruff
passes without them - the repo has two fewer suppressions than before.

The which() fix adds a systemctl-is-None branch, so the pass count goes
216 -> 217: one new test for it, no existing test touched. Coverage is
back at 100% by covering the branch, not excluding it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:57:38 +02:00
c113a3a192 Split the code_tutor import graph and scan tables out of _analyzer
_analyzer.py 388 -> 226. The file walk, dotted-name map, import
resolution and fingerprint go to _deps.py; the skip frozensets and the
function regex to _scan_tables.py, which covered the last nine lines
after the first cut landed at 259.

_is_binary is the only name any test patches on _analyzer and it stays
put, so no patch string needed editing. Only test_analyzer.py's import
block had to be split.

Pass count is 216 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:48:32 +02:00
6c999e3242 Record the hang failure mode in the split recipes
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
A mispointed mock.patch does not always fail loudly. In code_tutor it
spins, because the code under test reads from an input callable in a
retry loop. Documents running under timeout, asserting patch targets
resolve first, the absolute-patch-string cost, and the silent no-op sed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:43:34 +02:00
277cb9fd6f Split the code_tutor challenge flows out of _challenge
_challenge.py 467 -> 236. The two flows and run_coding_challenge go to
_challenge_flows.py; the three static prompt strings to
_challenge_prompts.py, which covered the last eleven lines after the
first cut landed at 261.

The 13 patch strings in test_challenge_part3.py were repointed per test,
by which function is under test - the _run_user_impl tests keep
_challenge. Getting that wrong does not fail here, it HANGS: an
unintercepted _collect_and_rate_tests ran the real interactive flow and
spun the suite for two minutes. Runs are now under an explicit timeout,
and the patch targets are asserted to resolve before pytest starts.

Pass count is 216 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:42:50 +02:00
40a4eaf5b5 Split the code_tutor pytest runner and verdict streaming out
_challenge_support.py 402 -> 237. _pytest_clean and _patch_and_test go
to _pytest_runner.py with the subprocess/os/sys imports they solely used;
_stream_verdict and _parse_verdict go to _verdict.py with rich's Live.

code_tutor patches by absolute string rather than a MOD constant, so the
seam cost 15 per-name rewrites instead of one sed. Two intermediate
failures caught by running it: the test modules import the moved names
directly, and five patch strings still named the old module.

Pass count is 216 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:33:58 +02:00
2c01a0267e Clear the last three brother_printer test modules over the cap
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
test_consumables_part2.py 273 -> 133 (renamed test_counter_scales.py),
test_consumables.py 272 -> 123, test_check_brother_printer.py 275 -> 112.
python_pkg/brother_printer is now entirely under the 250-line cap, from
fifteen violations at the start.

The consumables split lands exactly on the MOD/MOD_PD boundary an earlier
commit introduced, so the two-constant workaround dissolves instead of
being carried forward - each file has one module under test again.

Pass count is 402, unchanged across all eight commits of this pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:27:07 +02:00
74eee2b57f Split the brother_printer display and usb_query test modules
test_display.py 363 -> 204, with the supply maths and its display going
to test_supply_levels.py. test_usb_query.py 328 -> 126, with the retry
and sequencing tests going to test_usb_query_sequence.py.

That removed the last reader of the six _supply names through display,
so display.py's __all__ shrinks to the two public entry points and the
stale comment about tests reaching them there is gone. Checked by grep
across python_pkg and an import-time attribute probe, not by the suite.

The first run after the usb_query split reported 393: TestParsePagecount
sat between the two moved classes and travelled with them. Fixed.

Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:23:47 +02:00
607ba98c85 Split the brother_printer cups_service test modules under the cap
test_cups_service.py 390 -> 172 (usblp port status to _port),
part2 261 -> 115 (status mapping and discovery out), part3 260 -> 105
(the four healthy-port cases out). part3 was one 235-line class, so it
split by method rather than by class.

The four part-numbered files are renamed for what they cover; three of
them now name _cups_fallback, matching where the code moved earlier.

The first run after the part2 split reported 400, not 402: the moved
classes needed subprocess and get_status_info that my hand-written
import block had dropped. Fixed, and the count is 402 again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:19:55 +02:00
65bc65c7e3 Split the brother_printer cups_queue test modules under the cap
test_cups_queue.py 458 -> 167, partitioned at class boundaries into
_actions (the four shell-out primitives) and _backend (health check and
error-log scanning). test_cups_queue_part2.py 278 -> 131, with the four
_handle_* dispatchers moving to _handlers.

No MOD changed: unlike the source splits, every patched name already
lives in the module each file names, so this is a pure partition. The
two part-numbered survivors are renamed for what they cover.

Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:15:55 +02:00
ad3d70f197 Split brother_printer PJL wire transport out of usb_query
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
usb_query.py 267 -> 180. The non-blocking fd handling - _drain_buffer,
_write_with_deadline, _read_nonblocking, _wait_for_pjl_response and
pjl_query - moves to _pjl_io.py.

usb_query imports the three names test_usb_query.py patches back, which
is safe here only because all three still have real call sites in the
code that stayed; an import-only name would be stripped by ruff's F401
sweep and break the patch. os and time also stay: they are patched on
usb_query as well as on _pjl_io.

test_usb_query.py needs no edit. Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:11:15 +02:00
a438652aaa Split brother_printer dropped-page detection out of consumables
consumables.py 279 -> 217. check_page_delivery and _snapshot_counters
move to _page_delivery.py.

The state-file primitives stay put: test_consumables.py patches
_load_consumable_state, _save_consumable_state and CONSUMABLE_STATE_FILE
on consumables, and moving them would have let a test write to the real
~/.config/brother_printer/state.json. Verified by mtime after the run,
not just by a green suite.

test_consumables_part2.py patches the same three primitives from both
sides of the seam, so it gains a second MOD_PD applied per class rather
than a blanket swap. Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:07:21 +02:00
143dd9ff3d Split brother_printer CUPS fallback query out of cups_service
cups_service.py 406 -> 234. The IPP attribute queries, the CUPS
status-code mapping, find_cups_printer_name and query_usb_via_cups move
to _cups_fallback.py; cups_service keeps service control and raw USB
port status.

The seam is not the section header: test_cups_service_part2.py imports
_get_cups_economode and find_cups_printer_name together and patches
shutil once, so those two had to travel as a pair. test_cups_service.py,
the largest module, needs no edit.

usb_query.py reaches the fallback through a late import_module, so both
that string and the absolute patch target in test_usb_query.py moved
with it. Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:02:42 +02:00
cf44e54215 Split brother_printer queue display and fix prompt out of cups_queue
cups_queue.py 424 -> 245. display_cups_queue_status, _offer_queue_fix,
the _dwj_* choices and the _handle_* dispatchers move to _queue_fix.py.

The _cups_* action primitives stay put: test_cups_queue.py patches
subprocess and time on cups_queue, and those primitives are their only
consumers, so moving them would have left subprocess.run unpatched and
free to restart the real CUPS service mid-suite. test_cups_queue.py
therefore needs no edit; only part2/part3 repoint their MOD.

Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 16:53:51 +02:00
386ff25296 Split brother_printer page-count display into its own module
display.py 342 -> 248, under the 250-line cap. The page-count estimate,
the dropped-page warning and the consumables reference move verbatim to
_page_count.py, which imports the two collaborators the tests patch
(check_page_delivery, estimate_consumable_life) directly.

test_display_part3.py patched only those two names, so it becomes
test_page_count.py with its MOD pointing at the new module. Pass count is
402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 16:50:02 +02:00
82fe807deb Update handoff: 183 left, record the test-edit decision as decision 8
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Also notes brother_printer/display.py as explicitly partial so the next session
does not read it as cleared.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 16:43:49 +02:00
9e688c573a Record the mock.patch pinning rule and the agreed test-edit boundary
mock.patch pins a name to the module it is patched on. A function that moves
resolves collaborators through its new module's globals, so the patch stops
reaching it -- the failure is either AttributeError or, worse, a real call to
what should have been mocked. This governs brother_printer (15 files, ~90
patched names) and probably code_tutor. The grep to run first is in the doc.

Also records the user's decision: editing tests to follow moved code is
allowed, bounded by no assertion changed, nothing deleted or weakened, and an
identical pass count. The alternative was ~8 delegate stubs per file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 16:42:04 +02:00
2832b7841f Reduce brother_printer/display.py and dedup the consumable bars
Partial: display.py 427 -> 342. Still a violation, not yet cleared.

Moved out only what no test patches:
  _supply.py    the supply-level arithmetic (imported by tests, not patched)
  _severity.py  the three _SEVERITY_* tables (pure data)

Also collapsed the toner and drum bars in _display_page_count_estimate into
_supply.render_life_bar. They were the same logic with different colours and
notes, so this removes duplication rather than relocating it.

The remaining ~92 lines are blocked on mock.patch pinning. This package's test
modules patch ~90 names via patch(f"{MOD}.<name>"), and a patched name only
resolves in the module the test names -- moving a function that calls one
breaks the mock. An attempt to move the page-count block was reverted for
exactly that (display has no attribute 'estimate_consumable_life'). Clearing
it needs either test edits or ~8 delegate stubs, which is a decision to take
rather than assume.

402 tests pass, unchanged.

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