This file loads into context on every turn of every session, so every line is
paid for repeatedly. Two thirds of it either duplicated a gate that already
fails the commit, or stated something untrue.
Deleted because a hook enforces it: the ruff/mypy/pylint/coverage settings,
"double-quote expansions" (shellcheck runs with no severity filter), absolute
imports, Google docstrings, type hints, and the inline-Python rule -- which
got a real gate in 17b20e5 rather than being dropped.
Corrected four claims that were simply false, all verified against the config:
- pytest-coverage was listed as a pre-push hook; it is stages:[pre-commit].
Pre-push is prettier + ci-mirror.
- the root-symlink list named requirements.txt twice and omitted lint_python.sh
- "scripts/" described a directory that does not exist at repo root
- per-file-ignores were listed as S101/PLR2004/S310/S607/PLC0415; the actual
set is ARG/D/PLC0415/PLR2004/S101/SLF001
Added the five top-level dirs the layout table omitted (poker-stakes, bottles,
bucket_catch, focus_owner, kcd2_dice_solver) and documented three gates that
were enforced but undocumented: the 4-file contract threshold, append-only
session logs, and the 2% jscpd limit.
Also recorded two places the gate is weaker than it looks: the mypy hook
disables ~20 error codes despite strict=true, and no-polling-antipatterns only
inspects *_loop/*_daemon/poll* functions.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
7.2 KiB
testsAndMisc
Mixed-language monorepo: Python packages, Bash automation, and several apps.
Repository Layout
| Path | Description |
|---|---|
python_pkg/ |
Python packages — every .py in the repo belongs here or in an allowlisted dir |
meta/ |
Repo-wide tooling: pyproject.toml, requirements.txt, run.sh, lint_python.sh, .fvmrc, scripts/ |
linux_configuration/ |
Arch setup, i3 config, system maintenance, and the tracked git hooks |
phone_focus_mode/ |
GPS-based Android focus enforcer (Bash, ADB, Magisk) |
billsplit/ |
Receipt bill-splitting Flutter app (Dart) |
reverse_survivors/ |
React/Vite game — you play the horde (TypeScript) |
poker-stakes/ |
Poker stakes trainer (TypeScript, Vite) |
kcd2_dice_solver/ |
KCD2 dice solver |
focus_owner/ |
Android Device-Owner focus enforcer (Kotlin) |
bucket_catch/, bottles/ |
Small standalone projects |
docs/ |
Reference docs; docs/superpowers/ holds AI workflow artifacts |
third_party/ |
Vendored upstream skills/agents |
Root pyproject.toml, requirements.txt, run.sh, lint_python.sh and
.fvmrc are symlinks into meta/ — edit the files in meta/, not the
symlinks.
Extracted to their own repos: steam-backlog-enforcer,
screen-locker,
diet-guard,
wake-alarm,
dufs-cloud,
build-your-x (lives at ~/build_your_x).
Archived work: testsAndMisc-archive.
Adding a Flutter app
billsplit/ is currently the only one, and the only place binaries are
committed. To add another, repeat both halves or the icons fail silently:
- Add the icon globs to
.binary-allowlist. - Add matching
!overrides at the end of.gitignore— an ignored file fails silently ongit addrather than erroring.
Icons come from the shared generator in python_pkg/app_icons/. Dart style is
gated by CI only (.github/workflows/billsplit-ci.yml), not by a local hook.
Keep app dirs free of Python: the check-python-location hook requires every
.py to sit under python_pkg/ (or linux_configuration/, phone_focus_mode/,
meta/scripts/). billsplit/'s coverage gate therefore lives at
python_pkg/billsplit_coverage/.
Git Workflow
Work directly on main; commit and push straight there.
core.hooksPath points at the tracked linux_configuration/.githooks/, so
hooks travel with the repo. .git/hooks/ is unused — never run
pre-commit install.
- pre-commit: shfmt + shellcheck + jscpd (fails above 2% duplication),
then
pre-commit run --hook-stage pre-commit. - pre-push:
pre-commit run --hook-stage pre-push—prettierandci-mirror.ci-mirrorruns a clean-venv install,pre-commit runover all files, and pytest for changed packages.
Bootstrap a clone or new machine:
./meta/scripts/install_hooks.sh # wire hooks + install missing tools
./meta/scripts/install_hooks.sh --check # verify only; exit 1 if incomplete
Both hooks fail closed: every external binary is verified each run and
auto-installed via pacman where possible. A missing tool aborts the commit —
it never means "skip the check". Extend REQUIRED_TOOLS in
linux_configuration/.githooks/lib/common.sh when adding a language: system
hook. common.sh also warns when local shellcheck/prettier/shfmt/zsh drift
from the versions pinned in .github/workflows/pre-commit.yml.
Development Workflow
- Do NOT run tests unless instructed, or before committing.
- If tests fail on the same issue twice in a row, STOP and ask.
- Confirm a change works by running the program and inspecting output — not by running tests. Then ask the user to confirm the behaviour.
- Fix coverage gaps; do not ignore them.
AI evidence (enforced)
Every commit touching code needs an evidence artifact:
- Copy
docs/superpowers/evidence/template.json→docs/superpowers/evidence/<task-slug>-<date>.json. - Fill in intent, scope, changes, verification, risks, rollback.
- Stage it with the code.
validate_evidence.py rejects empty verification[] and the phrases
"should work", "probably fine", "seems right".
Staging ≥4 code files additionally requires a fresh
docs/superpowers/contracts/*.json in the same commit.
Deletions in docs/superpowers/sessions/* abort the commit (append-only).
Code Conventions
Anything already enforced by a hook is omitted here — run
pre-commit run --all-files and read .pre-commit-config.yaml for the
complete list. What follows is what a linter cannot check.
Python
from __future__ import annotationsfor forward references.- Prefix private functions/modules with
_(_smart_plug.py,_process_game_event). - Mock external calls in tests; never hit real APIs or the filesystem.
- For branch coverage: prefer an explicit
while Truewithtry/except StopIterationoverforwhen iterator exhaustion needs covering, and mock threads/subprocesses to keep tests fast.
Full linting/coverage configuration lives in meta/pyproject.toml
(ruff select = ["ALL"], mypy, pylint enable = "all", coverage
fail_under = 100 with branch coverage). Note the mypy hook disables a
number of error codes, so it is weaker than the strict = true in the config.
Shell
set -euo pipefailin every script.- Prefer
/proc,/sysand bash builtins over$(...)in hot paths — see theefficient-polling-scriptsskill. Theno-polling-antipatternshook only inspects functions named*_loop,*_daemonorpoll*, so a fork storm elsewhere passes clean. - Use
jq/yqfor JSON/YAML, notgrep/awk.
Key Files
meta/pyproject.toml— all Python tool configs.pre-commit-config.yaml— hook definitionslinux_configuration/.githooks/— the tracked git hooksmeta/requirements.txt— runtime + dev dependenciesdocs/superpowers/evidence/template.json— evidence template.github/workflows/—pre-commit,python-tests,shell-tests, and one CI workflow per app