testsAndMisc/NEXT_SESSION_PROMPT.md
Krzysztof kuhy Rudnicki 0cf487b3f3
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
Retarget the brief at the remaining over-cap files
Rewrites NEXT_SESSION_PROMPT.md against what is actually left: 37 files
(29 shell, 4 python, 2 kotlin, 1 dart) rather than the 40 it described,
with the system-maintenance python now finished.

Also drops it from 260 lines to 155, so the brief is no longer itself
over the cap it tracks. Over-cap 37 -> 36.

Carries forward the five traps that cost real time this session -
especially that a monkeypatch aimed at the wrong module made main() call
the real _run_since, read the machine's atop logs and hang the suite
rather than fail - and records the two shell blockers with the specific
thing that breaks and the order to do it in.

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

8.8 KiB
Raw Blame History

Next session: keep splitting, tests first

Paste this whole file into a fresh Claude session opened in ~/testsAndMisc. It is self-contained. Do not go looking for the previous session's context.

Where things stand

Over-cap: 41 → 37 (29 shell, 4 python, 2 kotlin, 1 dart, 1 markdown — the markdown is this file). 12 commits, 6713ef3..ff1a1b6, all pushed.

The C++ category is empty and the system-maintenance/bin/ python is done: every module there is under the cap at 100% line+branch coverage.

The method, which worked six times

  1. Measure coverage of the block you intend to move, first. The failure this catches is real: _usage_report_parsing.py was 39% covered and the uncovered 61% was almost exactly the half a split would extract. Splitting that first would have proved nothing.
  2. Tests land in their own commit, before the split. Not negotiable — a split verified by tests written alongside it is verified against the post-split shape.
  3. Move code verbatim, then prove it. Write a throwaway script that parses HEAD and the new modules with ast, normalises each top-level def through ast.dump(ast.parse(ast.unparse(node))), and asserts identity. It caught a literal × typed where the original had a × escape. Formatting-blind, logic-sensitive; ~40 lines, worth rewriting each time.
  4. Rewrite import sites to name the owning module. No re-export barrels. Check the whole graph: one split shipped with usage_report.py still importing _fmt_h through the render module, and the commit message claimed otherwise.
  5. Run the actual program. Every unit test here stubs subprocesses, so only a real run proves the import graph resolves. Run every entry point the split touched, not just one.
  6. Re-run every gate, commit one split at a time, with evidence.

Traps that cost time this session, in order of cost

  • monkeypatch.setattr must target the module whose namespace resolves the name — the caller's, not the one the function moved to. Getting this wrong on _run_since made main() call the real function, which read the machine's actual atop logs and hung the suite rather than failing. If a pytest run stalls after a split, this is why.
  • Splitting a test file can put it over the cap. Two commits added over-cap files while fixing something else (DropZone.test.tsx 250 → 256 on a lint fix; two new test files at 373 and 272). Check check_file_length.sh --all before committing, not after.
  • Don't move too much at once. The usage_report.py split needed two functions relocated after their first placement made an import cycle, plus four modules' worth of patch targets re-pointed. Smaller slices are cheaper.
  • TYPE_CHECKING imports bite when code moves. Path, _fmt_h and dataclass each ended up importable only for type checking while used at runtime. All three failed at first call; 100% coverage surfaced them at once.
  • A backgrounded git push | tail hides failure. One push reported exit 0 while printing error: failed to push some refs. Verify with git status -sb showing no [ahead N].

What to do next

1. meta/scripts/optimize_vscode.py (498, untested)

The largest remaining python file and completely uncovered. Same recipe: coverage commit, then split. Take a smaller first slice than the last one.

2. The three transcribe_* files (356 / 302 / 289, untested)

linux_configuration/scripts/single_use/misc/testsAndMisc-bash/tools/. _transcribe_diarize.py, transcribe_fw.py, transcribe_helpers.py. Check whether they import heavy ML deps at module scope — if so, testing them needs the import stubbed, and python-mpv-style "loads a native lib at import" is a known CI-breaker in this repo.

3. Shell, where the remaining 29 are

docs/shell-split-verification.md has the harness. Two named blockers:

Scripts copied to a system location and run from there. install_leechblock.sh (485) is copied to /usr/local/share/digital_wellbeing/ and pacman_wrapper.sh:831 prefers that deployed copy on every pacman invocation. Split the repo copy into an entry that sources lib/, and the deployed copy — which has no lib/ beside it — dies on its first source. Every pacman -S on this machine then fails. The trace harness cannot see this: it runs the repo copy, where lib/ exists. Same for block_compulsive_opening.sh (705), whose install_all copies the running script into /usr/local/bin. Teach the installer to deploy lib/ first, in its own commit, then re-baseline its manifest, then split.

Source-text tests. test_pacman_wrapper_security.sh asserts things like grep -q 'source .*pacman_lock_lib.sh' pacman_wrapper.sh. It is in CI (.github/workflows/shell-tests.yml, the arch-tests list). Rewriting those assertions is authorised, but the replacement must prove the same property of the split whole — grep across entry and libs, or better, source the library and assert the behaviour. State in the evidence how the new assertion is at least as strong.

nvidia_troubleshoot.sh (336) has a different blocker: its trace dies at step 3 because backup_file writes into an unbound /etc, so 239 of 336 lines never execute under the harness.

Rules that will bite you

  • No suppressions, ever. No # noqa, # type: ignore, eslint-disable, # shellcheck disable, no lowered coverage threshold. Several were tempted this session; all were resolved by changing the code. If a split seems to need one, the seam is wrong.
  • Every commit touching code needs evidence in docs/superpowers/evidence/<slug>-<date>.json (copy template.json). Staging ≥4 code files also needs a fresh docs/superpowers/contracts/*.json. Validate both with meta/scripts/validate_{evidence,contract}.py.
  • pre-commit run --files <changed> before committing. prettier and ci-mirror run on pre-push, not pre-commit — a commit can pass and the push still fail. Run npx prettier --write on any .md you touch, including this one.
  • Work directly on main. git stash and branch creation are blocked by hooks.
  • Do not wire the file-length pre-commit hook. It lands last, once bash ~/utils/scripts/check_file_length.sh --all exits 0. 37 files are still over.
  • Cap pytest memory: systemd-run --user --scope -p MemoryMax=2G -p MemorySwapMax=0.
  • New sourced shell libs: shebang and the executable bit, sourced via "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib.sh", with # shellcheck source=<name>.sh relative to the script's own directory.

Known pre-existing state — not yours, do not fix silently

  • bucket_catch/packages/frontend has 4 eslint errors (was 45). Each is documented with measured reasoning in docs/superpowers/evidence/bucket-catch-eslint-2026-08-17.json. The one worth knowing: usePuzzleGameLoop.ts:129's Map.get(...)! cannot be fixed with ?? Infinity — that was tried and measured at 219 branches / 99.54%, because the default side is unreachable. Trading a lint error for a coverage failure is not a fix. npm run coverage is green: 145 tests, 100%.
  • bash linux_configuration/tests/test_security_hardening.sh exits 1 with one failure, ❌ FAIL: Compulsive block wrappers installed. It belongs to block_compulsive_opening.sh.
  • _compute_window in _usage_report_run.py is dead: documented as "kept for backwards import compatibility", zero callers anywhere (verified by grep over .py and .sh). It is tested, so deleting it is safe and cheap.
  • Repo-wide jscpd reports ~2.5% from the working tree but 1.47% at HEAD in a clean worktree — the excess is vendored .venv site-packages. Don't chase it.

Testing notes specific to this repo

  • linux_configuration/tests is in CI, but never by name: pyproject.toml sets testpaths, so the bare pytest in python-tests.yml collects it, and meta/scripts/pytest_changed_packages.py hard-codes the directory into the pre-commit hook. Behaviour is gated; coverage is not (--cov=python_pkg only). A broken split of these files does break the build.
  • name-tests-test requires every .py under tests/ to be named test_*.py, including in subdirectories. A shared helper module there is not possible without a hook exclusion; put helpers in conftest.py or in the one file that needs them.
  • For a test-file split the discriminating check is the test count, not a green run: a file outside the runner's glob is silently never collected.
  • phone_focus_mode's shell tests are not in CI. shell-tests.yml uses an explicit file list covering linux_configuration/tests/ only.
  • focus_owner gradle needs JAVA_HOME=/usr/lib/jvm/java-21-openjdk and --rerun-tasks; a plain gradlew test reports UP-TO-DATE and proves nothing.