testsAndMisc/AGENTS.md
Krzysztof kuhy Rudnicki 3ac6a52fab
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Prettier-format AGENTS.md and token_audit prices.json
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-04 16:40:36 +02:00

8.8 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
bottles/ Small standalone project
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.

linux_configuration/ has no scripts/ or single_use/ level: those two were pure taxonomy carrying no information, and the directory-depth cap does not leave room for them. Categories sit directly under it — features/, fixes/, utils/, misc/, fresh-install/, installers/, diagnostics/, gaming/, boot_recovery/, periodic_background/, lib/, meta/, tests/. A script's own lib/ and tests/ subdirectories are exempt from the cap, so those stay where they are.

Extracted to their own repos: steam-backlog-enforcer, screen-locker, diet-guard, wake-alarm, dufs-cloud, build-your-x (lives at ~/build_your_x), reverse-survivors, kcd2-dice-solver (lives at ~/src/kcd2-dice-solver), focus-owner, mtk-root, system-maintenance (lives at ~/src/system-maintenance), android-guardian (lives at ~/android-guardian), phone-focus-mode (with python_pkg/focus_policy), wsg-grabber (private; lives at ~/src/wsg-grabber), hosts-blocker (lives at ~/src/hosts-blocker), digital-wellbeing (lives at ~/src/digital-wellbeing; carries the six suites that used to sit in linux_configuration/tests/). Monorepo callers resolve both via linux_configuration/lib/extracted_repos.sh, which reads the invoking user's home from SUDO_USER — never $HOME, which is /root under sudo and under systemd. Archived work: testsAndMisc-archive.

Adding a Flutter app

There is currently no Flutter app here — billsplit/ was archived, and with it the only committed binaries. Adding one means repeating both halves or the icons fail silently:

  1. Add the icon globs to .binary-allowlist.
  2. Add matching ! overrides at the end of .gitignore — an ignored file fails silently on git add rather than erroring.

Icons come from the shared generator in python_pkg/app_icons/. Dart style needs its own CI workflow; there is no local hook for it. Keep app dirs free of Python: the check-python-location hook requires every .py to sit under python_pkg/ (or linux_configuration/, meta/scripts/), so an app's coverage gate lives in python_pkg/.

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 — prettier and ci-mirror. ci-mirror runs a clean-venv install, pre-commit run over all files, and pytest for changed packages — but not on the push's critical path. The push spawns a detached, niced worker and returns in well under a second; the worker records a verdict for the tree it checked. A recorded failure refuses the next push until the tree is verified in the foreground with CI_MIRROR_SYNC=1 git push, so a broken tree reaches GitHub at most once. A tree that already passed costs nothing to re-push. prettier caches its verdict per file content + prettier version + config, so unchanged files never start Node.

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:

  1. Copy docs/superpowers/evidence/template.json → docs/superpowers/evidence/<task-slug>-<date>.json.
  2. Fill in intent, scope, changes, verification, risks, rollback.
  3. 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 annotations for 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 True with try/except StopIteration over for when 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 pipefail in every script.
  • Prefer /proc, /sys and bash builtins over $(...) in hot paths — see the efficient-polling-scripts skill. The no-polling-antipatterns hook only inspects functions named *_loop, *_daemon or poll*, so a fork storm elsewhere passes clean.
  • Use jq/yq for JSON/YAML, not grep/awk.

Key Files

  • meta/pyproject.toml — all Python tool configs
  • .pre-commit-config.yaml — hook definitions
  • linux_configuration/.githooks/ — the tracked git hooks
  • meta/requirements.txt — runtime + dev dependencies
  • docs/superpowers/evidence/template.json — evidence template
  • .github/workflows/ — pre-commit, python-tests, shell-tests, and one CI workflow per app

Commands

  • run: n/a: monorepo of independent scripts and apps, no single entry point (see Repository Layout)
  • test: python3 -m pytest -q -o addopts="--strict-markers --strict-config"
  • test-changed: scripts/test_changed.sh
  • lint: pre-commit run --hook-stage pre-commit
  • coverage: python3 -m pytest -q --cov=python_pkg --cov-branch --cov-report=xml -o addopts="--strict-markers --strict-config"
  • coverage-gaps: coverage-gaps coverage.xml