From 085d08b5c99cca538e8496b694ab9a8b508771b5 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sat, 22 Aug 2026 14:59:27 +0200 Subject: [PATCH] Split the two shell scripts and the gate's own config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit aur-publish/publish.sh 439 -> 148 + lib/aur_registration 107 + lib/aur_verify 122 + lib/aur_publish_one 107 guard-lib/lib/file_guard.sh 350 -> 140 + file_guard_unlock 214 file_length/config.py 252 -> 45 + _tables 202 + exemptions 77 The libs are sourced, never executed: they read the readonly config the entry script declares, and a `readonly` re-run inside a twice-sourced lib aborts under `set -e`. Verified by function parity rather than by eye — publish.sh resolves the same 17 functions as before the split, guardctl the same 15 — plus `shellcheck -x` clean on every file and a real `--help` / bad-option run. file_length is the gate's own code, so a broken import there turns the gate into a no-op. Split three ways to avoid an import cycle without a `# noqa`: _tables holds the data, exemptions the rules that read it, config re-exports both so `from file_length.config import is_generated` still resolves. The first attempt was wrong — EXCLUDED_DIRS was left behind and every invocation raised — caught because the gate was re-run in both modes rather than assumed. Now verified: exit 0 on a clean file, exit 1 on an over-cap one, --explain intact, and the same 61 exemption decisions as HEAD. Also deletes baseline-2026-08-14.json and SURVEY-2026-08-14.txt: the task forbids a baseline file, and nothing in the tree read either. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CFSGeWxHPY5rHUGrPqhcmG --- aur-publish/lib/aur_publish_one.sh | 107 + aur-publish/lib/aur_registration.sh | 107 + aur-publish/lib/aur_verify.sh | 122 + aur-publish/publish.sh | 307 +-- file_length/SURVEY-2026-08-14.txt | 208 -- file_length/_tables.py | 201 ++ file_length/baseline-2026-08-14.json | 3589 -------------------------- file_length/config.py | 279 +- file_length/exemptions.py | 82 + guard-lib/guardctl | 2 + guard-lib/lib/file_guard.sh | 210 -- guard-lib/lib/file_guard_unlock.sh | 214 ++ 12 files changed, 879 insertions(+), 4549 deletions(-) create mode 100644 aur-publish/lib/aur_publish_one.sh create mode 100644 aur-publish/lib/aur_registration.sh create mode 100644 aur-publish/lib/aur_verify.sh delete mode 100644 file_length/SURVEY-2026-08-14.txt create mode 100644 file_length/_tables.py delete mode 100644 file_length/baseline-2026-08-14.json create mode 100644 file_length/exemptions.py create mode 100644 guard-lib/lib/file_guard_unlock.sh diff --git a/aur-publish/lib/aur_publish_one.sh b/aur-publish/lib/aur_publish_one.sh new file mode 100644 index 0000000..ee19327 --- /dev/null +++ b/aur-publish/lib/aur_publish_one.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# ============================================================================ +# Building, verifying and pushing one package to the AUR. +# +# Sourced by publish.sh, never executed: these functions read the readonly +# config (AUR_HOST, AUR_ROOT, DRY_RUN, PUBLISHED, FAILED) that the entry script declares, and +# a `readonly` re-run inside a twice-sourced lib would abort under `set -e`. +# ============================================================================ + +set -euo pipefail + +publish_one() { + local pkg="$1" repo="$2" wrapper="$3" binary="$4" expected="$5" + local dir="$AUR_ROOT/$pkg" + local version + + log "$pkg" + + [[ -d "$repo" ]] || { warn "$pkg: no repo at $repo"; return 1; } + [[ -f "$dir/PKGBUILD" ]] || { warn "$pkg: no PKGBUILD at $dir"; return 1; } + + version="$(newest_tag "$repo")" + [[ -n "$version" ]] || { warn "$pkg: no vX.Y.Z tag on the remote"; return 1; } + info "newest release tag: v$version" + + cd "$dir" + sed -i -E "s/^pkgver=.*/pkgver=$version/" PKGBUILD + # The tarball for a tag contains the PKGBUILD, so the checksum can only be + # computed after the tag exists — never committed ahead of time. + updpkgsums >/dev/null 2>&1 || { warn "$pkg: updpkgsums failed (tag missing?)"; return 1; } + + info "building" + if ! env PATH=/usr/bin:/bin:/usr/local/bin makepkg -Cf --noconfirm >/dev/null 2>&1; then + warn "$pkg: makepkg failed" + return 1 + fi + + local built + built="$(find . -maxdepth 1 -name "$pkg-$version-*.pkg.tar.zst" | head -1)" + [[ -n "$built" ]] || { warn "$pkg: no package produced"; return 1; } + + # namcap's "ELF files outside of a valid path ('opt/')" is a false positive + # for /opt-installed apps, so only genuinely new errors are worth failing on. + local findings + findings="$(namcap "$built" 2>&1 | grep -E ' E: ' | grep -v "outside of a valid path" || true)" + if [[ -n "$findings" ]]; then + warn "$pkg: namcap errors:" + printf ' %s\n' "$findings" + return 1 + fi + + info "installing and launching" + sudo pacman -U --noconfirm "$built" >/dev/null 2>&1 \ + || { warn "$pkg: pacman -U failed"; return 1; } + verify_installed "$binary" "$expected" "$wrapper" || { warn "$pkg: launch check failed"; return 1; } + + # Generated before the rule check, which verifies it matches the PKGBUILD. + makepkg --printsrcinfo > .SRCINFO + check_aur_rules "$pkg" || return 1 + + # The AUR repo is a separate remote living alongside the build dir; adding + # it here (rather than cloning into a fresh path) keeps the verified + # PKGBUILD and the thing being pushed byte-identical. + if [[ ! -d .git ]]; then + git init -q -b master . + git remote add origin "ssh://aur@$AUR_HOST/$pkg.git" + fi + git remote get-url origin >/dev/null 2>&1 \ + || git remote add origin "ssh://aur@$AUR_HOST/$pkg.git" + + # Fetch first: an existing AUR package must be built on, not overwritten. + if git fetch -q origin master 2>/dev/null; then + git reset -q --soft FETCH_HEAD 2>/dev/null || true + fi + + cat > .gitignore <<'EOF' +# Build products; the AUR tracks only the recipe. +*.pkg.tar.zst +*.tar.gz +src/ +pkg/ +EOF + + git add PKGBUILD .SRCINFO .gitignore + if git diff --cached --quiet; then + info "already up to date on the AUR; nothing to push" + PUBLISHED+=("$pkg v$version (unchanged)") + return 0 + fi + + git -c user.name='Krzysztof Rudnicki' \ + -c user.email='krzysztofrudnicki0@gmail.com' \ + commit -q -m "$pkg $version-1" + + if ((DRY_RUN)); then + info "DRY RUN — not pushing" + PUBLISHED+=("$pkg v$version (dry run)") + return 0 + fi + + info "pushing to the AUR" + git push -q origin master 2>&1 | tail -3 || { warn "$pkg: push failed"; return 1; } + PUBLISHED+=("$pkg v$version") + return 0 +} + diff --git a/aur-publish/lib/aur_registration.sh b/aur-publish/lib/aur_registration.sh new file mode 100644 index 0000000..c7b2ce9 --- /dev/null +++ b/aur-publish/lib/aur_registration.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# ============================================================================ +# Waiting for AUR registration and SSH access to come up. +# +# Sourced by publish.sh, never executed: these functions read the readonly +# config (AUR_HOST, SSH_KEY, GATE, POLL_SECONDS) that the entry script declares, and +# a `readonly` re-run inside a twice-sourced lib would abort under `set -e`. +# ============================================================================ + +set -euo pipefail + +register_status() { + python3 "$GATE" /register 2>/dev/null | head -1 +} + +open_browser() { + local url="$1" + local browser + for browser in xdg-open thorium-browser chromium google-chrome-stable firefox librewolf; do + if command -v "$browser" >/dev/null 2>&1; then + "$browser" "$url" >/dev/null 2>&1 & + info "Opened $url in $browser" + return 0 + fi + done + warn "No browser found; open this yourself: $url" +} + +ensure_key() { + if [[ ! -f "$SSH_KEY" ]]; then + log "Generating an AUR SSH key (none at $SSH_KEY)" + ssh-keygen -t ed25519 -f "$SSH_KEY" -N '' -C 'kuhy@aur' + fi + if ! grep -q "Host $AUR_HOST" "$HOME/.ssh/config" 2>/dev/null; then + log "Adding $AUR_HOST to ~/.ssh/config" + mkdir -p "$HOME/.ssh" + cat >> "$HOME/.ssh/config" <&1 | + grep -qiE 'interactive shell is disabled|Welcome to AUR' +} + +wait_for_registration() { + local status + status="$(register_status)" + if [[ "$status" == "200" ]]; then + log "AUR registration is OPEN" + else + log "AUR registration is closed (HTTP $status). Polling every ${POLL_SECONDS}s." + info "Ctrl-C to stop; re-run any time, nothing is lost." + while :; do + sleep "$POLL_SECONDS" + status="$(register_status)" + if [[ "$status" == "200" ]]; then + log "Registration is BACK (HTTP 200)" + break + fi + printf ' %s still HTTP %s\n' "$(date +%H:%M)" "$status" + done + fi + + open_browser "https://$AUR_HOST/register" + cat </dev/null | + awk '{print $2}' | + sed 's|refs/tags/||' | + grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | + sed 's/^v//' | + sort -V | + tail -1 +} + +verify_installed() { + local binary="$1" expected="$2" wrapper="$3" output + + # An instance left over from a previous run would make the wrapper print + # "already running" and hand off, which passes trivially and turns the + # strongest gate in this script into the weakest. Clear it first so the + # check always exercises a real cold start. + # + # Resolved through /proc//exe rather than any form of name or + # command-line matching. Every argv-based approach selects the wrong + # processes here: + # * `pkill -x` compares against the kernel's 15-character comm field, and + # two of these wrappers are longer (habit_stack_desktop is 19), so a + # name match would silently never fire. + # * `pkill -f`, and equally `ps -eo args` piped through a pattern, match + # any process whose command line merely *mentions* the path — this + # script, the shell running it, and the matching tool itself all + # qualify, so the run kills its own shell instead of the app. A + # $$/$PPID guard does not cover it, because the offending shell is + # often a more distant ancestor. + # /proc//exe is a kernel-maintained symlink to the binary actually + # being executed, so it cannot collide with an incidental mention. + # The wrapper name is unique per app, so the /opt// segment is left as + # a glob instead of threading the package name through another parameter. + # + # The link is read without `-f`: it is already fully resolved, and by the + # time this runs `pacman -U` has replaced the binary, so a leftover process + # points at an unlinked inode that the kernel reports with a " (deleted)" + # suffix. That suffix has to be stripped or the match silently misses the + # one process this exists to kill. + local pid exe killed=() + for pid in /proc/[0-9]*; do + pid="${pid#/proc/}" + exe="$(readlink "/proc/$pid/exe" 2>/dev/null)" || continue + exe="${exe% (deleted)}" + [[ "$exe" == /opt/*/bin/"$wrapper" ]] || continue + kill -TERM "$pid" 2>/dev/null && killed+=("$pid") + done + if ((${#killed[@]})); then + info "stopped a running instance so the launch check is meaningful" + # `kill` only reports that the signal was sent. Waiting for the process + # to actually go keeps a slow exit from failing the cold start below on + # a port that is still bound. + local waited=0 + while ((waited < 100)) && kill -0 "${killed[@]}" 2>/dev/null; do + sleep 0.1 + ((waited++)) + done + fi + + output="$(timeout 15 "/usr/bin/$binary" 2>&1 | head -3 || true)" + if grep -qF "$expected" <<<"$output"; then + return 0 + fi + warn "unexpected startup output: $output" + return 1 +} + +# The AUR does not review uploads, but "packages that violate the rules may be +# deleted without warning" (AUR submission guidelines). These are the rules that +# are mechanically checkable, enforced here so a violation blocks the push +# rather than surfacing later as a deletion request. +check_aur_rules() { + local pkg="$1" problems=() + + grep -q '^# Maintainer:' PKGBUILD \ + || problems+=("missing '# Maintainer:' comment on line 1") + + grep -qE "^arch=\(.*x86_64" PKGBUILD \ + || problems+=("x86_64 not in arch=() — packages without it are not allowed") + + # `replaces` makes pacman rip out the named package on the next -Sy, which + # is only correct for a genuine rename. `conflicts` is the right tool. + grep -q '^replaces=' PKGBUILD \ + && problems+=("uses replaces=; AUR rules reserve it for renames — use conflicts=") + + # A package already in an official repo must never be duplicated. + if pacman -Si "$pkg" >/dev/null 2>&1; then + problems+=("$pkg exists in an official repo — must not be submitted") + fi + + grep -qE '^(pkgdesc|url|license)=' PKGBUILD \ + || problems+=("missing pkgdesc/url/license") + + # A stale .SRCINFO is the single most common upload rejection. + if ! diff -q <(makepkg --printsrcinfo) .SRCINFO >/dev/null 2>&1; then + problems+=(".SRCINFO does not match PKGBUILD") + fi + + if ((${#problems[@]})); then + warn "$pkg: AUR rule violations:" + printf ' - %s\n' "${problems[@]}" + return 1 + fi + info "AUR rule checks passed" + return 0 +} + diff --git a/aur-publish/publish.sh b/aur-publish/publish.sh index f733809..fa84730 100755 --- a/aur-publish/publish.sh +++ b/aur-publish/publish.sh @@ -86,305 +86,14 @@ require_tools() { # Phase 1: wait for registration, then for the key to work # --------------------------------------------------------------------------- -register_status() { - python3 "$GATE" /register 2>/dev/null | head -1 -} - -open_browser() { - local url="$1" - local browser - for browser in xdg-open thorium-browser chromium google-chrome-stable firefox librewolf; do - if command -v "$browser" >/dev/null 2>&1; then - "$browser" "$url" >/dev/null 2>&1 & - info "Opened $url in $browser" - return 0 - fi - done - warn "No browser found; open this yourself: $url" -} - -ensure_key() { - if [[ ! -f "$SSH_KEY" ]]; then - log "Generating an AUR SSH key (none at $SSH_KEY)" - ssh-keygen -t ed25519 -f "$SSH_KEY" -N '' -C 'kuhy@aur' - fi - if ! grep -q "Host $AUR_HOST" "$HOME/.ssh/config" 2>/dev/null; then - log "Adding $AUR_HOST to ~/.ssh/config" - mkdir -p "$HOME/.ssh" - cat >> "$HOME/.ssh/config" <&1 | - grep -qiE 'interactive shell is disabled|Welcome to AUR' -} - -wait_for_registration() { - local status - status="$(register_status)" - if [[ "$status" == "200" ]]; then - log "AUR registration is OPEN" - else - log "AUR registration is closed (HTTP $status). Polling every ${POLL_SECONDS}s." - info "Ctrl-C to stop; re-run any time, nothing is lost." - while :; do - sleep "$POLL_SECONDS" - status="$(register_status)" - if [[ "$status" == "200" ]]; then - log "Registration is BACK (HTTP 200)" - break - fi - printf ' %s still HTTP %s\n' "$(date +%H:%M)" "$status" - done - fi - - open_browser "https://$AUR_HOST/register" - cat </dev/null | - awk '{print $2}' | - sed 's|refs/tags/||' | - grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | - sed 's/^v//' | - sort -V | - tail -1 -} - -verify_installed() { - local binary="$1" expected="$2" wrapper="$3" output - - # An instance left over from a previous run would make the wrapper print - # "already running" and hand off, which passes trivially and turns the - # strongest gate in this script into the weakest. Clear it first so the - # check always exercises a real cold start. - # - # Resolved through /proc//exe rather than any form of name or - # command-line matching. Every argv-based approach selects the wrong - # processes here: - # * `pkill -x` compares against the kernel's 15-character comm field, and - # two of these wrappers are longer (habit_stack_desktop is 19), so a - # name match would silently never fire. - # * `pkill -f`, and equally `ps -eo args` piped through a pattern, match - # any process whose command line merely *mentions* the path — this - # script, the shell running it, and the matching tool itself all - # qualify, so the run kills its own shell instead of the app. A - # $$/$PPID guard does not cover it, because the offending shell is - # often a more distant ancestor. - # /proc//exe is a kernel-maintained symlink to the binary actually - # being executed, so it cannot collide with an incidental mention. - # The wrapper name is unique per app, so the /opt// segment is left as - # a glob instead of threading the package name through another parameter. - # - # The link is read without `-f`: it is already fully resolved, and by the - # time this runs `pacman -U` has replaced the binary, so a leftover process - # points at an unlinked inode that the kernel reports with a " (deleted)" - # suffix. That suffix has to be stripped or the match silently misses the - # one process this exists to kill. - local pid exe killed=() - for pid in /proc/[0-9]*; do - pid="${pid#/proc/}" - exe="$(readlink "/proc/$pid/exe" 2>/dev/null)" || continue - exe="${exe% (deleted)}" - [[ "$exe" == /opt/*/bin/"$wrapper" ]] || continue - kill -TERM "$pid" 2>/dev/null && killed+=("$pid") - done - if ((${#killed[@]})); then - info "stopped a running instance so the launch check is meaningful" - # `kill` only reports that the signal was sent. Waiting for the process - # to actually go keeps a slow exit from failing the cold start below on - # a port that is still bound. - local waited=0 - while ((waited < 100)) && kill -0 "${killed[@]}" 2>/dev/null; do - sleep 0.1 - ((waited++)) - done - fi - - output="$(timeout 15 "/usr/bin/$binary" 2>&1 | head -3 || true)" - if grep -qF "$expected" <<<"$output"; then - return 0 - fi - warn "unexpected startup output: $output" - return 1 -} - -# The AUR does not review uploads, but "packages that violate the rules may be -# deleted without warning" (AUR submission guidelines). These are the rules that -# are mechanically checkable, enforced here so a violation blocks the push -# rather than surfacing later as a deletion request. -check_aur_rules() { - local pkg="$1" problems=() - - grep -q '^# Maintainer:' PKGBUILD \ - || problems+=("missing '# Maintainer:' comment on line 1") - - grep -qE "^arch=\(.*x86_64" PKGBUILD \ - || problems+=("x86_64 not in arch=() — packages without it are not allowed") - - # `replaces` makes pacman rip out the named package on the next -Sy, which - # is only correct for a genuine rename. `conflicts` is the right tool. - grep -q '^replaces=' PKGBUILD \ - && problems+=("uses replaces=; AUR rules reserve it for renames — use conflicts=") - - # A package already in an official repo must never be duplicated. - if pacman -Si "$pkg" >/dev/null 2>&1; then - problems+=("$pkg exists in an official repo — must not be submitted") - fi - - grep -qE '^(pkgdesc|url|license)=' PKGBUILD \ - || problems+=("missing pkgdesc/url/license") - - # A stale .SRCINFO is the single most common upload rejection. - if ! diff -q <(makepkg --printsrcinfo) .SRCINFO >/dev/null 2>&1; then - problems+=(".SRCINFO does not match PKGBUILD") - fi - - if ((${#problems[@]})); then - warn "$pkg: AUR rule violations:" - printf ' - %s\n' "${problems[@]}" - return 1 - fi - info "AUR rule checks passed" - return 0 -} - -publish_one() { - local pkg="$1" repo="$2" wrapper="$3" binary="$4" expected="$5" - local dir="$AUR_ROOT/$pkg" - local version - - log "$pkg" - - [[ -d "$repo" ]] || { warn "$pkg: no repo at $repo"; return 1; } - [[ -f "$dir/PKGBUILD" ]] || { warn "$pkg: no PKGBUILD at $dir"; return 1; } - - version="$(newest_tag "$repo")" - [[ -n "$version" ]] || { warn "$pkg: no vX.Y.Z tag on the remote"; return 1; } - info "newest release tag: v$version" - - cd "$dir" - sed -i -E "s/^pkgver=.*/pkgver=$version/" PKGBUILD - # The tarball for a tag contains the PKGBUILD, so the checksum can only be - # computed after the tag exists — never committed ahead of time. - updpkgsums >/dev/null 2>&1 || { warn "$pkg: updpkgsums failed (tag missing?)"; return 1; } - - info "building" - if ! env PATH=/usr/bin:/bin:/usr/local/bin makepkg -Cf --noconfirm >/dev/null 2>&1; then - warn "$pkg: makepkg failed" - return 1 - fi - - local built - built="$(find . -maxdepth 1 -name "$pkg-$version-*.pkg.tar.zst" | head -1)" - [[ -n "$built" ]] || { warn "$pkg: no package produced"; return 1; } - - # namcap's "ELF files outside of a valid path ('opt/')" is a false positive - # for /opt-installed apps, so only genuinely new errors are worth failing on. - local findings - findings="$(namcap "$built" 2>&1 | grep -E ' E: ' | grep -v "outside of a valid path" || true)" - if [[ -n "$findings" ]]; then - warn "$pkg: namcap errors:" - printf ' %s\n' "$findings" - return 1 - fi - - info "installing and launching" - sudo pacman -U --noconfirm "$built" >/dev/null 2>&1 \ - || { warn "$pkg: pacman -U failed"; return 1; } - verify_installed "$binary" "$expected" "$wrapper" || { warn "$pkg: launch check failed"; return 1; } - - # Generated before the rule check, which verifies it matches the PKGBUILD. - makepkg --printsrcinfo > .SRCINFO - check_aur_rules "$pkg" || return 1 - - # The AUR repo is a separate remote living alongside the build dir; adding - # it here (rather than cloning into a fresh path) keeps the verified - # PKGBUILD and the thing being pushed byte-identical. - if [[ ! -d .git ]]; then - git init -q -b master . - git remote add origin "ssh://aur@$AUR_HOST/$pkg.git" - fi - git remote get-url origin >/dev/null 2>&1 \ - || git remote add origin "ssh://aur@$AUR_HOST/$pkg.git" - - # Fetch first: an existing AUR package must be built on, not overwritten. - if git fetch -q origin master 2>/dev/null; then - git reset -q --soft FETCH_HEAD 2>/dev/null || true - fi - - cat > .gitignore <<'EOF' -# Build products; the AUR tracks only the recipe. -*.pkg.tar.zst -*.tar.gz -src/ -pkg/ -EOF - - git add PKGBUILD .SRCINFO .gitignore - if git diff --cached --quiet; then - info "already up to date on the AUR; nothing to push" - PUBLISHED+=("$pkg v$version (unchanged)") - return 0 - fi - - git -c user.name='Krzysztof Rudnicki' \ - -c user.email='krzysztofrudnicki0@gmail.com' \ - commit -q -m "$pkg $version-1" - - if ((DRY_RUN)); then - info "DRY RUN — not pushing" - PUBLISHED+=("$pkg v$version (dry run)") - return 0 - fi - - info "pushing to the AUR" - git push -q origin master 2>&1 | tail -3 || { warn "$pkg: push failed"; return 1; } - PUBLISHED+=("$pkg v$version") - return 0 -} +# The rest lives in lib/, sourced (not executed) so every function sees the +# readonly config above and the mutable FAILED/PUBLISHED arrays main() reads. +# shellcheck source=lib/aur_registration.sh +source "$SCRIPT_DIR/lib/aur_registration.sh" +# shellcheck source=lib/aur_verify.sh +source "$SCRIPT_DIR/lib/aur_verify.sh" +# shellcheck source=lib/aur_publish_one.sh +source "$SCRIPT_DIR/lib/aur_publish_one.sh" main() { require_tools diff --git a/file_length/SURVEY-2026-08-14.txt b/file_length/SURVEY-2026-08-14.txt deleted file mode 100644 index 4979158..0000000 --- a/file_length/SURVEY-2026-08-14.txt +++ /dev/null @@ -1,208 +0,0 @@ -============================================================================== -TOTALS: 4045 readable files (code 2700, prose 580, data 765) -code lines total: 471,749 -============================================================================== - -### LONGEST FILES OVERALL (any readable kind), top 30 - -lines kind lang path ------- ----- ---------- --------------------------------------------------------------------------------------------------------- -174800 prose Text testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/words.txt -2053 prose Markdown testsAndMisc/docs/superpowers/plans/2026-05-01-phone-focus-recovery.md -1838 prose Markdown todo/BACKLOG.md -1734 code Shell testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh -1570 data JSON testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/leechblock_defaults.json -1475 data JSON macro-cam/assets/testdata/meals.json -1437 code TypeScript konbini-67/src/core/shift.test.ts -1417 code Dart epopeja_karta/lib/l10n/generated/app_localizations.dart -1383 code Shell testsAndMisc/linux_configuration/scripts/single_use/features/setup_nextcloud_raspberry.sh -1337 code Shell testsAndMisc/linux_configuration/scripts/periodic_background/check_and_enable_services.sh -1325 code Dart home_inventory/test/data/item_repository_test.dart -1276 code Shell testsAndMisc/linux_configuration/scripts/single_use/features/raspberry_pi_nextcloud.sh -1274 data JSON macro-cam/assets/testdata/model_areas.json -1120 code Dart home_inventory/lib/data/item_repository.dart -1116 code Shell testsAndMisc/linux_configuration/scripts/single_use/utils/root_bl9000.sh -1101 prose Markdown diet-guard/CLAUDE.md -1097 code TypeScript konbini-67/src/core/shift.ts -1091 data JSON macro-cam/assets/testdata/claude_meal_estimates.json -1091 code Shell testsAndMisc/phone_focus_mode/focus_ctl.sh -1089 code Dart dufs-cloud/app/test/browser_screen_test.dart -1076 code Python steam-backlog-enforcer/steam_backlog_enforcer/main.py -1072 code Python steam-backlog-enforcer/steam_backlog_enforcer/tests/test_stats.py -1052 code Dart diet-guard/app/lib/screens/history_screen.dart -1047 code TypeScript dufs-cloud/web/src/components/gallery.test.tsx -1042 code Python steam-backlog-enforcer/steam_backlog_enforcer/tests/test_total_block.py -1017 code Dart diet-guard/app/test/screens/history_screen_test.dart -1017 code Shell testsAndMisc/linux_configuration/scripts/single_use/utils/generate_study_materials.sh -942 code Shell testsAndMisc/linux_configuration/scripts/single_use/utils/lookup_docs.sh -929 code Shell testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/pacman_wrapper.sh -925 prose Markdown todo/CLAUDE.md - -### LONGEST CODE FILES, top 30 - -lines lang commits/yr path ------ ---------- ---------- --------------------------------------------------------------------------------------------------------- -1734 Shell 9 testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh -1437 TypeScript 12 konbini-67/src/core/shift.test.ts -1417 Dart 2 epopeja_karta/lib/l10n/generated/app_localizations.dart -1383 Shell 1 testsAndMisc/linux_configuration/scripts/single_use/features/setup_nextcloud_raspberry.sh -1337 Shell 8 testsAndMisc/linux_configuration/scripts/periodic_background/check_and_enable_services.sh -1325 Dart 6 home_inventory/test/data/item_repository_test.dart -1276 Shell 1 testsAndMisc/linux_configuration/scripts/single_use/features/raspberry_pi_nextcloud.sh -1120 Dart 7 home_inventory/lib/data/item_repository.dart -1116 Shell 1 testsAndMisc/linux_configuration/scripts/single_use/utils/root_bl9000.sh -1097 TypeScript 13 konbini-67/src/core/shift.ts -1091 Shell 9 testsAndMisc/phone_focus_mode/focus_ctl.sh -1089 Dart 12 dufs-cloud/app/test/browser_screen_test.dart -1076 Python 26 steam-backlog-enforcer/steam_backlog_enforcer/main.py -1072 Python 4 steam-backlog-enforcer/steam_backlog_enforcer/tests/test_stats.py -1052 Dart 6 diet-guard/app/lib/screens/history_screen.dart -1047 TypeScript 9 dufs-cloud/web/src/components/gallery.test.tsx -1042 Python 2 steam-backlog-enforcer/steam_backlog_enforcer/tests/test_total_block.py -1017 Dart 6 diet-guard/app/test/screens/history_screen_test.dart -1017 Shell 2 testsAndMisc/linux_configuration/scripts/single_use/utils/generate_study_materials.sh -942 Shell 2 testsAndMisc/linux_configuration/scripts/single_use/utils/lookup_docs.sh -929 Shell 6 testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/pacman_wrapper.sh -918 Shell 5 testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/setup_night_lockdown.sh -912 Shell 5 testsAndMisc/linux_configuration/scripts/periodic_background/hosts/install.sh -912 Shell 3 testsAndMisc/linux_configuration/scripts/single_use/features/setup_searxng.sh -909 Dart 15 dufs-cloud/app/lib/screens/browser_screen.dart -897 Dart 8 screen-locker/stronglift_replacement/workout_app/lib/screens/history_screen.dart -896 Dart 2 epopeja_karta/test/widget_test.dart -870 Shell 2 testsAndMisc/linux_configuration/scripts/single_use/utils/update_android_hosts.sh -869 Shell 3 testsAndMisc/linux_configuration/scripts/single_use/utils/analyze_repo.sh -850 Python 3 europe-county-map/scripts/extract_ck3_counties.py - -### LONGEST PROSE (md/txt/rst/tex), top 30 - -lines lang path ------- -------- ----------------------------------------------------------------------------------------------- -174800 Text testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/words.txt -2053 Markdown testsAndMisc/docs/superpowers/plans/2026-05-01-phone-focus-recovery.md -1838 Markdown todo/BACKLOG.md -1101 Markdown diet-guard/CLAUDE.md -925 Markdown todo/CLAUDE.md -761 Markdown testsAndMisc/linux_configuration/docs/SECURITY_HARDENING_ANALYSIS.md -709 Markdown testsAndMisc/docs/superpowers/specs/2026-05-01-phone-focus-recovery-design.md -648 Markdown .claude/plans/i-dont-want-to-resilient-teapot.md -621 Markdown konbini-67/SPEC-physicality.md -592 Markdown .claude/plans/i-added-google-anonymous-elegant-stallman.md -578 Markdown .claude/plans/i-am-trying-to-starry-emerson.md -564 Markdown .claude/plans/inventory-app-improvements-1-cheeky-mountain.md -548 LaTeX CV/magisterskie/cv.tex -528 Markdown diet-guard/app/.agents/skills/dart-migrate-to-checks-package/SKILL.md -528 Markdown todo/.agents/skills/dart-migrate-to-checks-package/SKILL.md -521 Markdown .claude/plans/build-prompt-melodic-mango.md -478 Markdown .claude/plans/abundant-cooking-hippo.md -461 Markdown .claude/plans/where-the-guard-lives-fluffy-shell.md -459 Markdown .claude/plans/changes-to-diet-guard-splendid-spindle.md -440 Markdown .claude/plans/japanese-convenience-store-clerk-witty-cocoa.md -421 Markdown .claude/plans/all-repos-that-build-cozy-pike.md -419 Markdown diet-guard/app/.agents/skills/dart-setup-ffi-assets/SKILL.md -419 Markdown todo/.agents/skills/dart-setup-ffi-assets/SKILL.md -406 Markdown .claude/plans/grind-leetcode-guard-velvet-engelbart.md -402 Markdown .claude/skills/wiki-to-mcp-kb/references/pitfalls.md -402 Markdown .claude/plans/inventory-management-for-spicy-cray.md -390 Markdown .claude/plans/read-and-fix-incident-2026-08-05-no-way-wiggly-karp.md -386 Markdown .claude/plans/take-https-github-com-punkpeye-awesome-m-gentle-swing.md -384 Markdown testsAndMisc/.claude/skills/test-driven-development/SKILL.md -384 Markdown testsAndMisc/.github/skills/test-driven-development/SKILL.md - -### TOP REFACTOR ROI (lines x commits-last-year), top 30 - -roi lines commits/yr lang path ------ ----- ---------- ---------- --------------------------------------------------------------------------------------------------------- -27976 1076 26 Python steam-backlog-enforcer/steam_backlog_enforcer/main.py -22796 556 41 Shell testsAndMisc/phone_focus_mode/config.sh -18720 390 48 Python screen-locker/screen_locker/screen_lock.py -17244 1437 12 TypeScript konbini-67/src/core/shift.test.ts -15606 1734 9 Shell testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh -14261 1097 13 TypeScript konbini-67/src/core/shift.ts -14041 739 19 Dart todo/lib/ui/capture_screen.dart -13635 909 15 Dart dufs-cloud/app/lib/screens/browser_screen.dart -13068 1089 12 Dart dufs-cloud/app/test/browser_screen_test.dart -12495 833 15 Shell testsAndMisc/phone_focus_mode/deploy.sh -11220 660 17 Dart todo/test/capture_screen_test.dart -10696 1337 8 Shell testsAndMisc/linux_configuration/scripts/periodic_background/check_and_enable_services.sh -9954 553 18 Python steam-backlog-enforcer/steam_backlog_enforcer/game_install.py -9819 1091 9 Shell testsAndMisc/phone_focus_mode/focus_ctl.sh -9423 1047 9 TypeScript dufs-cloud/web/src/components/gallery.test.tsx -9252 771 12 Dart screen-locker/stronglift_replacement/workout_app/lib/screens/settings_screen.dart -7950 1325 6 Dart home_inventory/test/data/item_repository_test.dart -7840 1120 7 Dart home_inventory/lib/data/item_repository.dart -7215 555 13 Python steam-backlog-enforcer/steam_backlog_enforcer/library_hider.py -7176 897 8 Dart screen-locker/stronglift_replacement/workout_app/lib/screens/history_screen.dart -7170 478 15 Python wake-alarm/wake_alarm/_alarm.py -7020 702 10 Dart todo/lib/ui/note_editor.dart -6994 538 13 TypeScript konbini-67/src/app.test.tsx -6773 521 13 Python steam-backlog-enforcer/steam_backlog_enforcer/scanning.py -6768 752 9 Dart screen-locker/stronglift_replacement/workout_app/lib/services/storage_service.dart -6699 319 21 Python screen-locker/screen_locker/tests/conftest.py -6612 551 12 CSS europe-county-map/src/App.css -6600 440 15 Dart diet-guard/app/lib/screens/log_meal_screen.dart -6516 543 12 Shell testsAndMisc/phone_focus_mode/focus_daemon.sh -6312 1052 6 Dart diet-guard/app/lib/screens/history_screen.dart - -### DISTRIBUTION BY LANGUAGE (code only) - -lang n median mean p75 p90 p95 p99 max ----------- --- ------ ----- --- --- --- ---- ---- -Python 895 179 206.6 294 399 466 652 1076 -Dart 758 105 160.5 203 351 480 897 1417 -TypeScript 459 85 125.4 162 266 361 698 1437 -Shell 363 120 201.1 243 457 663 1276 1734 -Kotlin 68 26 71.0 69 223 277 564 564 -HTML 60 402 333.8 548 716 738 843 843 -C 22 21 70.5 88 229 249 478 478 -CSS 19 169 261.1 535 768 774 774 774 -Swift 17 12 12 15 16 16 16 16 -C++ 16 70 97.8 151 288 288 288 288 -JavaScript 15 47 65.7 97 134 179 179 179 -Java 8 40 69.2 101 247 247 247 247 - -### DISTRIBUTION BY PROJECT (code only, >=10 files) - -project n median MEAN p90 max total ----------------------- --- ------ ----- --- ---- ------- -steam-backlog-enforcer 114 269 301.3 588 1076 34,352 -epopeja_karta 37 192 289.4 759 1417 10,708 -kuhytrack 12 215 240 392 652 2,880 -screen-locker 211 169 209.8 390 897 44,261 -steam-game-installer 18 144 198.2 473 765 3,567 -utils 127 167 193.3 412 525 24,552 -mcp-servers 27 136 189.1 467 487 5,106 -testsAndMisc 745 127 187.7 421 1734 139,813 -europe-county-map 75 138 181.8 374 850 13,637 -manga_translate 40 144 181.2 417 720 7,250 -leetcode-guard 117 181 180.4 296 400 21,111 -wake-alarm 68 150 178.2 405 764 12,118 -diet-guard 217 128 175.6 379 1052 38,101 -yay-mcp 16 109 168.3 478 554 2,693 -todo 99 109 165.9 405 739 16,421 -i3wm-mcp 12 130 165.8 275 615 1,989 -home_inventory 113 96 152.6 328 1325 17,249 -konbini-67 73 96 149.6 209 1437 10,919 -dufs-cloud 126 99 146.8 257 1089 18,497 -hotline3d 38 82 136.4 353 736 5,184 -macro-cam 55 103 133.5 279 574 7,341 -wiki-kb 31 95 121.3 215 463 3,760 -atomichabits 15 88 109.8 188 251 1,647 -octoforge 76 80 104.3 209 510 7,929 -kuhylog 92 89 94.9 166 301 8,727 -.claude 17 64 74.5 177 311 1,267 -iron-and-anvil 40 55 71.7 159 220 2,869 -habit_stack 54 42 71.7 169 288 3,870 -personal-website 25 48 65.3 165 303 1,633 - -### COUNT OVER CANDIDATE THRESHOLDS (code only) - -threshold files over % of code of those, edited last yr ---------- ---------- --------- ------------------------ -300 474 17.6% 452 -400 243 9.0% 229 -500 118 4.4% 114 -600 82 3.0% 80 -800 33 1.2% 33 -1000 19 0.7% 19 -1500 1 0.0% 1 -2000 0 0.0% 0 diff --git a/file_length/_tables.py b/file_length/_tables.py new file mode 100644 index 0000000..5c1b1b7 --- /dev/null +++ b/file_length/_tables.py @@ -0,0 +1,201 @@ +"""Exemption tables for the 250-line file-length cap. + +The data half: which extensions are capped, and which paths are generated, +vendored, third-party or session artifacts. :mod:`file_length.exemptions` +holds the rules that read these, and :mod:`file_length.config` re-exports +both as the public surface. + +Duplicating these lists in shell is what lets a gate and a survey silently +disagree, so they live here once. +""" + +from __future__ import annotations + +import re + +#: Hard cap. Files above this fail the gate. Code and prose alike. +MAX_LINES = 250 + +#: Extensions the cap applies to: real programming languages plus prose. +#: Markup (.html/.css/.scss) is deliberately absent -- templates split into +#: partials, not functions, so a line cap does not express anything useful. +CAPPED_EXTENSIONS = { + # code + ".py", + ".dart", + ".ts", + ".tsx", + ".js", + ".jsx", + ".sh", + ".bash", + ".zsh", + ".c", + ".h", + ".cpp", + ".cc", + ".hpp", + ".go", + ".rs", + ".java", + ".kt", + ".kts", + ".swift", + ".rb", + ".lua", + ".sql", + ".vue", + ".cs", + ".php", + # prose + ".md", + ".markdown", + ".txt", + ".rst", + ".tex", + ".org", +} + +#: Generated files: regenerated by a tool, so splitting them is meaningless +#: (the tool would just rewrite the original next run). +GENERATED_PATTERN = re.compile( + r"\.g\.dart$" + r"|\.freezed\.dart$" + r"|\.gr\.dart$" + r"|\.config\.dart$" + r"|\.mocks\.dart$" + r"|\.min\.(js|css)$" + r"|\.pb\.(go|py)$" + r"|_pb2(_grpc)?\.py$" + r"|\.generated\.ts$" + r"|\.d\.ts$" + r"|/l10n/generated/" + r"|/generated/" +) + +#: A marker in the first few lines also marks a file generated. Covers tools +#: that do not use a distinguishing extension. +GENERATED_MARKERS = ( + "GENERATED CODE - DO NOT MODIFY", + "@generated", + "DO NOT EDIT", + "Autogenerated", + "AUTOGENERATED", + "generated by", +) + +#: Directory names never descended into: dependencies, build output, caches. +EXCLUDED_DIRS = frozenset( + { + ".git", + "node_modules", + ".dart_tool", + "build", + ".venv", + "venv", + "env", + "site-packages", + "target", + "ephemeral", + "__pycache__", + ".mypy_cache", + ".pytest_cache", + ".ruff_cache", + "dist", + ".next", + "vendor", + "third_party", + "Pods", + ".gradle", + ".idea", + ".cxx", + "coverage", + "htmlcov", + ".tox", + "Library", + "Temp", + "obj", + ".terraform", + ".fvm", + ".angular", + ".cache", + ".svelte-kit", + "migrations", + ".ci-mirror-venv", + ".hippo", + ".build-deps", + # Where CI checks out the shared gate itself (kuhyx/utils). Without + # this, a repo's lint job fails on utils' own long files -- a gate + # that fails for reasons the repo being gated cannot fix. + ".utils", + } +) + +#: Third-party content living *inside* a repo you own, keyed by repo dir name. +#: Verified by git remote / vendor manifest, not guessed. +VENDORED_SUBPATHS = { + "mcp-servers": ("servers",), + "dufs-cloud": ("app/assets/pdfjs", "web/assets/pdfjs"), + ".claude": ( + "projects", + "shell-snapshots", + "cache", + "backups", + "todos", + "statsig", + "history", + "chrome", + "downloads", + "plugins", + "ide", + ), + # Agent skill bundles vendored from Anthropic (todo: commit f91311f). + # A SKILL.md is a fixed-name file with frontmatter; detail belongs in a + # sibling references/ dir, so splitting one into SKILL.part2.md would + # break the format rather than improve readability. + "todo": (".agents/skills",), +} + +#: Directory names that mark a vendored agent-skill tree wherever they appear. +#: Keyed by name rather than repo because these bundles get dropped into any +#: repo that wants them, not just the one they were first seen in. +VENDORED_ANYWHERE = ("/.agents/skills/", "/.claude/skills/") + +#: Frozen records of past agent sessions: an implementation plan or an +#: append-only session log describes what was done at one moment. Splitting one +#: rewrites a historical record for no reading benefit -- nobody navigates them, +#: they are read whole or not at all. Same category as generated files. +#: +#: Deliberately NOT the whole of docs/superpowers/: `specs/` and `contracts/` +#: stay capped, because those are living documents that get re-read and edited. +SESSION_ARTIFACTS_ANYWHERE = ( + "/docs/superpowers/plans/", + "/docs/superpowers/sessions/", +) + +#: Whole repos under ~ that are third-party clones, not kuhy's work. +#: Verified 2026-08-14 by `git remote get-url origin` + commit authors. +THIRD_PARTY_REPOS = frozenset( + { + "StringTheory", # github.com/AnthonySf/TheStringTheory + "reaper-mcp", # github.com/TwelveTake-Studios/reaper-mcp + "freesound-mcp", # github.com/timjrobinson/FreesoundMCPServer + "llama_cpp_dart_local", # generated FFI bindings + "aseprite-mcp", + "Mapperatorinator", # github.com/OliBomby/Mapperatorinator + "aur", + "build-your-own-x", + "build_your_x", + "byox-ladder", + "warriorjs", + "untools", + "awesome-mcp-explorer", + "runnerup", + "depotdownloader", + "actions-runner", + } +) + +#: A `.txt` whose mean line is shorter than this is data (a wordlist, a +#: coordinate dump), not prose, so the cap does not apply. +DATA_TXT_MAX_MEAN_LINE = 25 diff --git a/file_length/baseline-2026-08-14.json b/file_length/baseline-2026-08-14.json deleted file mode 100644 index ee6347a..0000000 --- a/file_length/baseline-2026-08-14.json +++ /dev/null @@ -1,3589 +0,0 @@ -{ - "generated": "2026-08-14", - "cap": 250, - "total": 597, - "files": [ - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/main.py", - "lines": 1076, - "churn": 26, - "roi": 27976 - }, - { - "path": "testsAndMisc/phone_focus_mode/config.sh", - "lines": 556, - "churn": 41, - "roi": 22796 - }, - { - "path": "screen-locker/screen_locker/screen_lock.py", - "lines": 390, - "churn": 48, - "roi": 18720 - }, - { - "path": "konbini-67/src/core/shift.test.ts", - "lines": 1437, - "churn": 12, - "roi": 17244 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh", - "lines": 1734, - "churn": 9, - "roi": 15606 - }, - { - "path": "konbini-67/src/core/shift.ts", - "lines": 1097, - "churn": 13, - "roi": 14261 - }, - { - "path": "todo/lib/ui/capture_screen.dart", - "lines": 739, - "churn": 19, - "roi": 14041 - }, - { - "path": "dufs-cloud/app/lib/screens/browser_screen.dart", - "lines": 909, - "churn": 15, - "roi": 13635 - }, - { - "path": "diet-guard/CLAUDE.md", - "lines": 1101, - "churn": 12, - "roi": 13212 - }, - { - "path": "dufs-cloud/app/test/browser_screen_test.dart", - "lines": 1089, - "churn": 12, - "roi": 13068 - }, - { - "path": "testsAndMisc/phone_focus_mode/deploy.sh", - "lines": 833, - "churn": 15, - "roi": 12495 - }, - { - "path": "todo/test/capture_screen_test.dart", - "lines": 660, - "churn": 17, - "roi": 11220 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/check_and_enable_services.sh", - "lines": 1337, - "churn": 8, - "roi": 10696 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/game_install.py", - "lines": 553, - "churn": 18, - "roi": 9954 - }, - { - "path": "testsAndMisc/phone_focus_mode/focus_ctl.sh", - "lines": 1091, - "churn": 9, - "roi": 9819 - }, - { - "path": "dufs-cloud/web/src/components/gallery.test.tsx", - "lines": 1047, - "churn": 9, - "roi": 9423 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/screens/settings_screen.dart", - "lines": 771, - "churn": 12, - "roi": 9252 - }, - { - "path": "home_inventory/test/data/item_repository_test.dart", - "lines": 1325, - "churn": 6, - "roi": 7950 - }, - { - "path": "home_inventory/lib/data/item_repository.dart", - "lines": 1120, - "churn": 7, - "roi": 7840 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/library_hider.py", - "lines": 555, - "churn": 13, - "roi": 7215 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/screens/history_screen.dart", - "lines": 897, - "churn": 8, - "roi": 7176 - }, - { - "path": "wake-alarm/wake_alarm/_alarm.py", - "lines": 478, - "churn": 15, - "roi": 7170 - }, - { - "path": "todo/lib/ui/note_editor.dart", - "lines": 702, - "churn": 10, - "roi": 7020 - }, - { - "path": "konbini-67/src/app.test.tsx", - "lines": 538, - "churn": 13, - "roi": 6994 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/scanning.py", - "lines": 521, - "churn": 13, - "roi": 6773 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/services/storage_service.dart", - "lines": 752, - "churn": 9, - "roi": 6768 - }, - { - "path": "screen-locker/screen_locker/tests/conftest.py", - "lines": 319, - "churn": 21, - "roi": 6699 - }, - { - "path": "diet-guard/app/lib/screens/log_meal_screen.dart", - "lines": 440, - "churn": 15, - "roi": 6600 - }, - { - "path": "testsAndMisc/phone_focus_mode/focus_daemon.sh", - "lines": 543, - "churn": 12, - "roi": 6516 - }, - { - "path": "diet-guard/app/lib/screens/history_screen.dart", - "lines": 1052, - "churn": 6, - "roi": 6312 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/hltb.py", - "lines": 384, - "churn": 16, - "roi": 6144 - }, - { - "path": "diet-guard/app/test/screens/history_screen_test.dart", - "lines": 1017, - "churn": 6, - "roi": 6102 - }, - { - "path": "todo/test/note_repository_test.dart", - "lines": 677, - "churn": 9, - "roi": 6093 - }, - { - "path": "europe-county-map/src/App.tsx", - "lines": 337, - "churn": 18, - "roi": 6066 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/screens/settings_screen_test.dart", - "lines": 480, - "churn": 12, - "roi": 5760 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/screens/workout_screen.dart", - "lines": 633, - "churn": 9, - "roi": 5697 - }, - { - "path": "dufs-cloud/web/src/components/gallery.tsx", - "lines": 622, - "churn": 9, - "roi": 5598 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/pacman_wrapper.sh", - "lines": 929, - "churn": 6, - "roi": 5574 - }, - { - "path": "todo/CLAUDE.md", - "lines": 925, - "churn": 6, - "roi": 5550 - }, - { - "path": "screen-locker/screen_locker/tests/test_init_and_log.py", - "lines": 343, - "churn": 16, - "roi": 5488 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_hltb.py", - "lines": 447, - "churn": 12, - "roi": 5364 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_alarm_part2.py", - "lines": 438, - "churn": 12, - "roi": 5256 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_alarm.py", - "lines": 435, - "churn": 12, - "roi": 5220 - }, - { - "path": "screen-locker/screen_locker/_ui_flows.py", - "lines": 370, - "churn": 14, - "roi": 5180 - }, - { - "path": "todo/test/settings_screen_test.dart", - "lines": 391, - "churn": 13, - "roi": 5083 - }, - { - "path": "testsAndMisc/focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/EnforcementRunner.kt", - "lines": 564, - "churn": 9, - "roi": 5076 - }, - { - "path": "diet-guard/diet_guard/_sync.py", - "lines": 498, - "churn": 10, - "roi": 4980 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_enforce_loop.py", - "lines": 410, - "churn": 12, - "roi": 4920 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_scanning.py", - "lines": 444, - "churn": 11, - "roi": 4884 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_main_part2.py", - "lines": 476, - "churn": 10, - "roi": 4760 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/setup_night_lockdown.sh", - "lines": 918, - "churn": 5, - "roi": 4590 - }, - { - "path": "diet-guard/app/lib/screens/settings_screen.dart", - "lines": 286, - "churn": 16, - "roi": 4576 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/hosts/install.sh", - "lines": 912, - "churn": 5, - "roi": 4560 - }, - { - "path": "screen-locker/screen_locker/_phone_verification.py", - "lines": 377, - "churn": 12, - "roi": 4524 - }, - { - "path": "diet-guard/diet_guard/tests/test_sync.py", - "lines": 482, - "churn": 9, - "roi": 4338 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_stats.py", - "lines": 1072, - "churn": 4, - "roi": 4288 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_hltb_detail.py", - "lines": 592, - "churn": 7, - "roi": 4144 - }, - { - "path": "testsAndMisc/CLAUDE.md", - "lines": 258, - "churn": 16, - "roi": 4128 - }, - { - "path": "europe-county-map/src/sim/view.test.ts", - "lines": 374, - "churn": 11, - "roi": 4114 - }, - { - "path": "konbini-67/src/core/types.ts", - "lines": 393, - "churn": 10, - "roi": 3930 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_enforce_loop.py", - "lines": 393, - "churn": 10, - "roi": 3930 - }, - { - "path": "konbini-67/src/app.tsx", - "lines": 269, - "churn": 14, - "roi": 3766 - }, - { - "path": "europe-county-map/src/MapView.tsx", - "lines": 466, - "churn": 8, - "roi": 3728 - }, - { - "path": "konbini-67/SPEC-physicality.md", - "lines": 621, - "churn": 6, - "roi": 3726 - }, - { - "path": "europe-county-map/src/sim/war.test.ts", - "lines": 737, - "churn": 5, - "roi": 3685 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/services/workout_sync_service_test.dart", - "lines": 590, - "churn": 6, - "roi": 3540 - }, - { - "path": "testsAndMisc/reverse_survivors/src/core/sim.test.ts", - "lines": 698, - "churn": 5, - "roi": 3490 - }, - { - "path": "diet-guard/app/test/services/sync_merge_test.dart", - "lines": 694, - "churn": 5, - "roi": 3470 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_main.py", - "lines": 491, - "churn": 7, - "roi": 3437 - }, - { - "path": "todo/lib/data/note_repository.dart", - "lines": 429, - "churn": 8, - "roi": 3432 - }, - { - "path": "europe-county-map/src/sim/war.ts", - "lines": 424, - "churn": 8, - "roi": 3392 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_cmd_done.py", - "lines": 333, - "churn": 10, - "roi": 3330 - }, - { - "path": "screen-locker/screen_locker/tests/test_adb_and_phone.py", - "lines": 256, - "churn": 13, - "roi": 3328 - }, - { - "path": "diet-guard/diet_guard/_gatelock_ui.py", - "lines": 472, - "churn": 7, - "roi": 3304 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_hltb_part2.py", - "lines": 409, - "churn": 8, - "roi": 3272 - }, - { - "path": "diet-guard/diet_guard/_cli.py", - "lines": 466, - "churn": 7, - "roi": 3262 - }, - { - "path": "screen-locker/screen_locker/_manual_workout_dialog.py", - "lines": 357, - "churn": 9, - "roi": 3213 - }, - { - "path": "diet-guard/diet_guard/tests/conftest.py", - "lines": 282, - "churn": 11, - "roi": 3102 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/lib/common.sh", - "lines": 620, - "churn": 5, - "roi": 3100 - }, - { - "path": "utils/gatelock/gatelock/_window.py", - "lines": 515, - "churn": 6, - "roi": 3090 - }, - { - "path": "todo/lib/ui/notes_list_screen.dart", - "lines": 439, - "churn": 7, - "roi": 3073 - }, - { - "path": "screen-locker/screen_locker/_shutdown.py", - "lines": 384, - "churn": 8, - "roi": 3072 - }, - { - "path": "diet-guard/app/test/screens/settings_screen_test.dart", - "lines": 274, - "churn": 11, - "roi": 3014 - }, - { - "path": "todo/test/note_editor_test.dart", - "lines": 502, - "churn": 6, - "roi": 3012 - }, - { - "path": "testsAndMisc/focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/DevicePolicyBridge.kt", - "lines": 415, - "churn": 7, - "roi": 2905 - }, - { - "path": "diet-guard/app/test/screens/log_meal_screen_test.dart", - "lines": 362, - "churn": 8, - "roi": 2896 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_alarm_part3.py", - "lines": 358, - "churn": 8, - "roi": 2864 - }, - { - "path": "diet-guard/diet_guard/_state.py", - "lines": 357, - "churn": 8, - "roi": 2856 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/services/storage_service_test.dart", - "lines": 714, - "churn": 4, - "roi": 2856 - }, - { - "path": "diet-guard/app/lib/services/sync_merge.dart", - "lines": 475, - "churn": 6, - "roi": 2850 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_library_hider.py", - "lines": 468, - "churn": 6, - "roi": 2808 - }, - { - "path": "europe-county-map/src/sim/tick.ts", - "lines": 309, - "churn": 9, - "roi": 2781 - }, - { - "path": "screen-locker/screen_locker/status_view.py", - "lines": 396, - "churn": 7, - "roi": 2772 - }, - { - "path": "europe-county-map/src/sim/tick.test.ts", - "lines": 346, - "churn": 8, - "roi": 2768 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_game_install.py", - "lines": 346, - "churn": 8, - "roi": 2768 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/conftest.py", - "lines": 275, - "churn": 10, - "roi": 2750 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/services/workout_sync_service.dart", - "lines": 342, - "churn": 8, - "roi": 2736 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_library_hider_part2.py", - "lines": 342, - "churn": 8, - "roi": 2736 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_searxng.sh", - "lines": 912, - "churn": 3, - "roi": 2736 - }, - { - "path": "testsAndMisc/focus_owner/lib/main.dart", - "lines": 544, - "churn": 5, - "roi": 2720 - }, - { - "path": "europe-county-map/src/EventLog.tsx", - "lines": 384, - "churn": 7, - "roi": 2688 - }, - { - "path": "testsAndMisc/phone_focus_mode/README.md", - "lines": 336, - "churn": 8, - "roi": 2688 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/analyze_repo.sh", - "lines": 869, - "churn": 3, - "roi": 2607 - }, - { - "path": "europe-county-map/scripts/extract_ck3_counties.py", - "lines": 850, - "churn": 3, - "roi": 2550 - }, - { - "path": "testsAndMisc/phone_focus_mode/hosts_enforcer.sh", - "lines": 421, - "churn": 6, - "roi": 2526 - }, - { - "path": "screen-locker/screen_locker/_sick_dialog.py", - "lines": 278, - "churn": 9, - "roi": 2502 - }, - { - "path": "todo/test/sync_service_test.dart", - "lines": 356, - "churn": 7, - "roi": 2492 - }, - { - "path": "screen-locker/screen_locker/tests/test_verify_workout.py", - "lines": 351, - "churn": 7, - "roi": 2457 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/cups_service.py", - "lines": 406, - "churn": 6, - "roi": 2436 - }, - { - "path": "testsAndMisc/linux_configuration/tests/test_i3blocks_efficiency.sh", - "lines": 345, - "churn": 7, - "roi": 2415 - }, - { - "path": "diet-guard/diet_guard/tests/test_state.py", - "lines": 400, - "churn": 6, - "roi": 2400 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_main_part3.py", - "lines": 397, - "churn": 6, - "roi": 2382 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_main_part4.py", - "lines": 790, - "churn": 3, - "roi": 2370 - }, - { - "path": "diet-guard/app/test/services/sync_service_test.dart", - "lines": 394, - "churn": 6, - "roi": 2364 - }, - { - "path": "europe-county-map/src/EventLog.test.tsx", - "lines": 337, - "churn": 7, - "roi": 2359 - }, - { - "path": "home_inventory/lib/screens/items_screen.dart", - "lines": 336, - "churn": 7, - "roi": 2352 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_hltb_search.py", - "lines": 588, - "churn": 4, - "roi": 2352 - }, - { - "path": "diet-guard/diet_guard/_sync_merge.py", - "lines": 470, - "churn": 5, - "roi": 2350 - }, - { - "path": "screen-locker/screen_locker/tests/test_weekly_logic.py", - "lines": 390, - "churn": 6, - "roi": 2340 - }, - { - "path": "screen-locker/screen_locker/_workout_sync.py", - "lines": 332, - "churn": 7, - "roi": 2324 - }, - { - "path": "diet-guard/diet_guard/tests/test_gatelock.py", - "lines": 331, - "churn": 7, - "roi": 2317 - }, - { - "path": "diet-guard/app/test/services/log_storage_service_test.dart", - "lines": 385, - "churn": 6, - "roi": 2310 - }, - { - "path": "steam-game-installer/tests/test_recognize.py", - "lines": 765, - "churn": 3, - "roi": 2295 - }, - { - "path": "screen-locker/screen_locker/tests/test_screen_lock_coverage_part2.py", - "lines": 380, - "churn": 6, - "roi": 2280 - }, - { - "path": "testsAndMisc/phone_focus_mode/dns_enforcer.sh", - "lines": 325, - "churn": 7, - "roi": 2275 - }, - { - "path": "home_inventory/test/screens/items_screen_test.dart", - "lines": 378, - "churn": 6, - "roi": 2268 - }, - { - "path": "europe-county-map/src/App.test.tsx", - "lines": 320, - "churn": 7, - "roi": 2240 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_hltb_detail.py", - "lines": 373, - "churn": 6, - "roi": 2238 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_mcp.py", - "lines": 435, - "churn": 5, - "roi": 2175 - }, - { - "path": "screen-locker/screen_locker/_runnerup_verification.py", - "lines": 310, - "churn": 7, - "roi": 2170 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/display.py", - "lines": 427, - "churn": 5, - "roi": 2135 - }, - { - "path": "testsAndMisc/linux_configuration/tests/test_security_hardening.sh", - "lines": 423, - "churn": 5, - "roi": 2115 - }, - { - "path": "diet-guard/diet_guard/_gatelock.py", - "lines": 263, - "churn": 8, - "roi": 2104 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_stats.py", - "lines": 523, - "churn": 4, - "roi": 2092 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_hltb_search.py", - "lines": 348, - "churn": 6, - "roi": 2088 - }, - { - "path": "dufs-cloud/scripts/build_media_index.sh", - "lines": 298, - "churn": 7, - "roi": 2086 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_total_block.py", - "lines": 1042, - "churn": 2, - "roi": 2084 - }, - { - "path": "diet-guard/diet_guard/_gatelock_mealflow.py", - "lines": 259, - "churn": 8, - "roi": 2072 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_scanning_part3.py", - "lines": 412, - "churn": 5, - "roi": 2060 - }, - { - "path": "testsAndMisc/docs/superpowers/plans/2026-05-01-phone-focus-recovery.md", - "lines": 2053, - "churn": 1, - "roi": 2053 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/screens/home_screen.dart", - "lines": 341, - "churn": 6, - "roi": 2046 - }, - { - "path": "testsAndMisc/python_pkg/app_icons/glyphs.py", - "lines": 291, - "churn": 7, - "roi": 2037 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/generate_study_materials.sh", - "lines": 1017, - "churn": 2, - "roi": 2034 - }, - { - "path": "todo/test/wrapper_server_test.dart", - "lines": 402, - "churn": 5, - "roi": 2010 - }, - { - "path": "screen-locker/screen_locker/_ui_widgets.py", - "lines": 287, - "churn": 7, - "roi": 2009 - }, - { - "path": "testsAndMisc/linux_configuration/tests/test_pacman_wrapper_security.sh", - "lines": 287, - "churn": 7, - "roi": 2009 - }, - { - "path": "screen-locker/screen_locker/tests/test_early_bird.py", - "lines": 331, - "churn": 6, - "roi": 1986 - }, - { - "path": "kuhytrack/server/kt_server.py", - "lines": 652, - "churn": 3, - "roi": 1956 - }, - { - "path": "screen-locker/screen_locker/tests/test_status_view_part2.py", - "lines": 389, - "churn": 5, - "roi": 1945 - }, - { - "path": "testsAndMisc/focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/FocusPolicy.kt", - "lines": 277, - "churn": 7, - "roi": 1939 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/screens/history_screen_test.dart", - "lines": 386, - "churn": 5, - "roi": 1930 - }, - { - "path": "diet-guard/app/test/services/app_settings_service_test.dart", - "lines": 321, - "churn": 6, - "roi": 1926 - }, - { - "path": "europe-county-map/src/SidePanel.tsx", - "lines": 317, - "churn": 6, - "roi": 1902 - }, - { - "path": "diet-guard/diet_guard/tests/test_gatelock_mealflow.py", - "lines": 379, - "churn": 5, - "roi": 1895 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/lookup_docs.sh", - "lines": 942, - "churn": 2, - "roi": 1884 - }, - { - "path": "screen-locker/screen_locker/tests/test_screen_lock_coverage_part1.py", - "lines": 372, - "churn": 5, - "roi": 1860 - }, - { - "path": "screen-locker/screen_locker/tests/test_weekly_logic_part2.py", - "lines": 309, - "churn": 6, - "roi": 1854 - }, - { - "path": "wiki-kb/tests/test_scraper.py", - "lines": 463, - "churn": 4, - "roi": 1852 - }, - { - "path": "diet-guard/diet_guard/_mcp.py", - "lines": 369, - "churn": 5, - "roi": 1845 - }, - { - "path": "europe-county-map/src/sim/view.ts", - "lines": 263, - "churn": 7, - "roi": 1841 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_alarm_sinks.py", - "lines": 457, - "churn": 4, - "roi": 1828 - }, - { - "path": "diet-guard/diet_guard/_foodbank.py", - "lines": 365, - "churn": 5, - "roi": 1825 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_display.py", - "lines": 363, - "churn": 5, - "roi": 1815 - }, - { - "path": "europe-county-map/scripts/test_extract_ck3_counties.py", - "lines": 603, - "churn": 3, - "roi": 1809 - }, - { - "path": "testsAndMisc/reverse_survivors/src/core/sim.ts", - "lines": 361, - "churn": 5, - "roi": 1805 - }, - { - "path": "dufs-cloud/web/src/components/grid.test.tsx", - "lines": 256, - "churn": 7, - "roi": 1792 - }, - { - "path": "epopeja_karta/test/widget_test.dart", - "lines": 896, - "churn": 2, - "roi": 1792 - }, - { - "path": "todo/bin/todo_desktop.dart", - "lines": 253, - "churn": 7, - "roi": 1771 - }, - { - "path": "screen-locker/screen_locker/tests/test_status_view.py", - "lines": 294, - "churn": 6, - "roi": 1764 - }, - { - "path": "screen-locker/screen_locker/_manual_workout.py", - "lines": 352, - "churn": 5, - "roi": 1760 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_protondb.py", - "lines": 291, - "churn": 6, - "roi": 1746 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_web_dataset.py", - "lines": 436, - "churn": 4, - "roi": 1744 - }, - { - "path": "home_inventory/tool/sync_smoke.dart", - "lines": 290, - "churn": 6, - "roi": 1740 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/update_android_hosts.sh", - "lines": 870, - "churn": 2, - "roi": 1740 - }, - { - "path": "screen-locker/screen_locker/tests/test_status.py", - "lines": 289, - "churn": 6, - "roi": 1734 - }, - { - "path": "macro-cam/tool/fit_from_meals.py", - "lines": 574, - "churn": 3, - "roi": 1722 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_dns_blocker.sh", - "lines": 569, - "churn": 3, - "roi": 1707 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/system-maintenance/bin/usage_report.py", - "lines": 425, - "churn": 4, - "roi": 1700 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_alarm_part4.py", - "lines": 283, - "churn": 6, - "roi": 1698 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/data/dice.ts", - "lines": 415, - "churn": 4, - "roi": 1660 - }, - { - "path": "diet-guard/diet_guard/tests/test_sync_merge.py", - "lines": 414, - "churn": 4, - "roi": 1656 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_whitelist.py", - "lines": 412, - "churn": 4, - "roi": 1648 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_usb_query.py", - "lines": 328, - "churn": 5, - "roi": 1640 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_total_block.py", - "lines": 813, - "churn": 2, - "roi": 1626 - }, - { - "path": "diet-guard/diet_guard/_budget.py", - "lines": 323, - "churn": 5, - "roi": 1615 - }, - { - "path": "screen-locker/screen_locker/tests/test_manual_workout.py", - "lines": 399, - "churn": 4, - "roi": 1596 - }, - { - "path": "screen-locker/screen_locker/tests/test_status_data.py", - "lines": 399, - "churn": 4, - "roi": 1596 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/store_blocker.py", - "lines": 399, - "churn": 4, - "roi": 1596 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/components/components.test.tsx", - "lines": 532, - "churn": 3, - "roi": 1596 - }, - { - "path": "screen-locker/screen_locker/tests/test_runnerup_verification_part3.py", - "lines": 398, - "churn": 4, - "roi": 1592 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_actions.py", - "lines": 397, - "churn": 4, - "roi": 1588 - }, - { - "path": "screen-locker/screen_locker/_sick_tracker.py", - "lines": 317, - "churn": 5, - "roi": 1585 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/models/manual_workout.dart", - "lines": 392, - "churn": 4, - "roi": 1568 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/services/backup_service.dart", - "lines": 261, - "churn": 6, - "roi": 1566 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_cups_service.py", - "lines": 390, - "churn": 4, - "roi": 1560 - }, - { - "path": "diet-guard/diet_guard/tests/test_foodbank.py", - "lines": 311, - "churn": 5, - "roi": 1555 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_pool_resolve.py", - "lines": 386, - "churn": 4, - "roi": 1544 - }, - { - "path": "testsAndMisc/python_pkg/focus_policy/tests/test_export.py", - "lines": 255, - "churn": 6, - "roi": 1530 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_polls_tracking.py", - "lines": 382, - "churn": 4, - "roi": 1528 - }, - { - "path": "testsAndMisc/linux_configuration/docs/SECURITY_HARDENING_ANALYSIS.md", - "lines": 761, - "churn": 2, - "roi": 1522 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_mcp.py", - "lines": 380, - "churn": 4, - "roi": 1520 - }, - { - "path": "leetcode-guard/leetcode_guard/_cli.py", - "lines": 376, - "churn": 4, - "roi": 1504 - }, - { - "path": "screen-locker/screen_locker/tests/test_manual_workout_features.py", - "lines": 375, - "churn": 4, - "roi": 1500 - }, - { - "path": "europe-county-map/src/sim/ai.test.ts", - "lines": 295, - "churn": 5, - "roi": 1475 - }, - { - "path": "testsAndMisc/reverse_survivors/src/core/types.ts", - "lines": 295, - "churn": 5, - "roi": 1475 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/screens/workout_screen_test.dart", - "lines": 362, - "churn": 4, - "roi": 1448 - }, - { - "path": "manga_translate/mangatl/tests/test_adapters.py", - "lines": 720, - "churn": 2, - "roi": 1440 - }, - { - "path": "utils/gatelock/gatelock/tests/test_recovery.py", - "lines": 477, - "churn": 3, - "roi": 1431 - }, - { - "path": "diet-guard/diet_guard/_gatelock_calendar.py", - "lines": 286, - "churn": 5, - "roi": 1430 - }, - { - "path": "steam-game-installer/steam_installer/recognize.py", - "lines": 473, - "churn": 3, - "roi": 1419 - }, - { - "path": "diet-guard/app/lib/services/firebase_backend.dart", - "lines": 282, - "churn": 5, - "roi": 1410 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_store_blocker.py", - "lines": 470, - "churn": 3, - "roi": 1410 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/block_compulsive_opening.sh", - "lines": 705, - "churn": 2, - "roi": 1410 - }, - { - "path": "testsAndMisc/focus_owner/test/widget_test.dart", - "lines": 351, - "churn": 4, - "roi": 1404 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_wireguard_ssh.sh", - "lines": 464, - "churn": 3, - "roi": 1392 - }, - { - "path": "todo/test/notes_list_screen_test.dart", - "lines": 347, - "churn": 4, - "roi": 1388 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_nextcloud_raspberry.sh", - "lines": 1383, - "churn": 1, - "roi": 1383 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_enforce_loop_part2.py", - "lines": 274, - "churn": 5, - "roi": 1370 - }, - { - "path": "todo/lib/desktop/wrapper_server.dart", - "lines": 336, - "churn": 4, - "roi": 1344 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_steam_api.py", - "lines": 333, - "churn": 4, - "roi": 1332 - }, - { - "path": "screen-locker/screen_locker/tests/test_runnerup_verification_part2.py", - "lines": 332, - "churn": 4, - "roi": 1328 - }, - { - "path": "wiki-kb/wikikb/scraper.py", - "lines": 331, - "churn": 4, - "roi": 1324 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_config.py", - "lines": 264, - "churn": 5, - "roi": 1320 - }, - { - "path": "wake-alarm/wake_alarm/_alarm_view.py", - "lines": 329, - "churn": 4, - "roi": 1316 - }, - { - "path": "home_inventory/test/models/item_filter_test.dart", - "lines": 328, - "churn": 4, - "roi": 1312 - }, - { - "path": "dufs-cloud/web/src/lib/filter-sort.test.ts", - "lines": 260, - "churn": 5, - "roi": 1300 - }, - { - "path": "utils/crdt_sync_dart/lib/src/sync.dart", - "lines": 259, - "churn": 5, - "roi": 1295 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/widgets/exercise_tile.dart", - "lines": 319, - "churn": 4, - "roi": 1276 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/raspberry_pi_nextcloud.sh", - "lines": 1276, - "churn": 1, - "roi": 1276 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_game_install_part2.py", - "lines": 255, - "churn": 5, - "roi": 1275 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/system-maintenance/bin/_usage_report_parsing.py", - "lines": 425, - "churn": 3, - "roi": 1275 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/cups_queue.py", - "lines": 424, - "churn": 3, - "roi": 1272 - }, - { - "path": "diet-guard/app/lib/services/foodbank_service.dart", - "lines": 314, - "churn": 4, - "roi": 1256 - }, - { - "path": "testsAndMisc/focus_owner/android/app/src/test/kotlin/com/kuhy/focus_owner/EnforcementDecisionTest.kt", - "lines": 418, - "churn": 3, - "roi": 1254 - }, - { - "path": "kuhytrack/importers/kt-import.py", - "lines": 310, - "churn": 4, - "roi": 1240 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_web_dataset.py", - "lines": 620, - "churn": 2, - "roi": 1240 - }, - { - "path": "epopeja_karta/lib/state/app_state.dart", - "lines": 617, - "churn": 2, - "roi": 1234 - }, - { - "path": "diet-guard/app/test/screens/food_bank_screen_test.dart", - "lines": 614, - "churn": 2, - "roi": 1228 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/setup_periodic_system.sh", - "lines": 408, - "churn": 3, - "roi": 1224 - }, - { - "path": "utils/crdt-sync/crdt_sync/_firebase_auth.py", - "lines": 406, - "churn": 3, - "roi": 1218 - }, - { - "path": "wake-alarm/wake_alarm/_audio.py", - "lines": 405, - "churn": 3, - "roi": 1215 - }, - { - "path": "screen-locker/screen_locker/tests/test_sick_features.py", - "lines": 301, - "churn": 4, - "roi": 1204 - }, - { - "path": "screen-locker/screen_locker/_compliance_state.py", - "lines": 399, - "churn": 3, - "roi": 1197 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_whitelist.py", - "lines": 298, - "churn": 4, - "roi": 1192 - }, - { - "path": "diet-guard/app/test/services/foodbank_service_test.dart", - "lines": 395, - "churn": 3, - "roi": 1185 - }, - { - "path": "utils/crdt-sync/crdt_sync/tests/test_firebase_auth.py", - "lines": 393, - "churn": 3, - "roi": 1179 - }, - { - "path": "epopeja_karta/test/app_state_test.dart", - "lines": 588, - "churn": 2, - "roi": 1176 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_cli.py", - "lines": 293, - "churn": 4, - "roi": 1172 - }, - { - "path": "screen-locker/screen_locker/tests/test_runnerup_verification_part1.py", - "lines": 387, - "churn": 3, - "roi": 1161 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_sync.py", - "lines": 386, - "churn": 3, - "roi": 1158 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/turn_off_auto_idle_screen_shutdown.sh", - "lines": 289, - "churn": 4, - "roi": 1156 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/hosts/guard/setup_hosts_guard.sh", - "lines": 576, - "churn": 2, - "roi": 1152 - }, - { - "path": "testsAndMisc/phone_focus_mode/lib/tests/test_adb_common.sh", - "lines": 287, - "churn": 4, - "roi": 1148 - }, - { - "path": "screen-locker/screen_locker/tests/test_shutdown_part2.py", - "lines": 285, - "churn": 4, - "roi": 1140 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_actions.py", - "lines": 282, - "churn": 4, - "roi": 1128 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/steam_api.py", - "lines": 281, - "churn": 4, - "roi": 1124 - }, - { - "path": "epopeja_karta/lib/models/character.dart", - "lines": 560, - "churn": 2, - "roi": 1120 - }, - { - "path": "screen-locker/screen_locker/tests/test_runnerup_verification_part5.py", - "lines": 373, - "churn": 3, - "roi": 1119 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/root_bl9000.sh", - "lines": 1116, - "churn": 1, - "roi": 1116 - }, - { - "path": "wake-alarm/wake_alarm/_sync.py", - "lines": 371, - "churn": 3, - "roi": 1113 - }, - { - "path": "screen-locker/screen_locker/tests/test_workout_sync.py", - "lines": 278, - "churn": 4, - "roi": 1112 - }, - { - "path": "testsAndMisc/phone_focus_mode/curfew_enforcer.sh", - "lines": 367, - "churn": 3, - "roi": 1101 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_check_brother_printer.py", - "lines": 275, - "churn": 4, - "roi": 1100 - }, - { - "path": "utils/crdt-sync/crdt_sync/_sync.py", - "lines": 363, - "churn": 3, - "roi": 1089 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/install_plagiarism_tools.sh", - "lines": 541, - "churn": 2, - "roi": 1082 - }, - { - "path": "macro-cam/test/geometry/synthetic_scale_test.dart", - "lines": 358, - "churn": 3, - "roi": 1074 - }, - { - "path": "leetcode-guard/leetcode_guard/_pool_resolve.py", - "lines": 268, - "churn": 4, - "roi": 1072 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/usb_query.py", - "lines": 267, - "churn": 4, - "roi": 1068 - }, - { - "path": "testsAndMisc/meta/lint_python.sh", - "lines": 353, - "churn": 3, - "roi": 1059 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/models/manual_workout_test.dart", - "lines": 350, - "churn": 3, - "roi": 1050 - }, - { - "path": "utils/crdt_sync_dart/test/firebase_auth_rest_test.dart", - "lines": 525, - "churn": 2, - "roi": 1050 - }, - { - "path": "diet-guard/app/test/desktop/wrapper_server_test.dart", - "lines": 349, - "churn": 3, - "roi": 1047 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_cups_service_part2.py", - "lines": 261, - "churn": 4, - "roi": 1044 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_cups_service_part3.py", - "lines": 260, - "churn": 4, - "roi": 1040 - }, - { - "path": "testsAndMisc/phone_focus_mode/lib/adb_common.sh", - "lines": 346, - "churn": 3, - "roi": 1038 - }, - { - "path": "diet-guard/diet_guard/tests/_gate_layout_probe.py", - "lines": 345, - "churn": 3, - "roi": 1035 - }, - { - "path": "home_inventory/lib/screens/filter_sheet.dart", - "lines": 343, - "churn": 3, - "roi": 1029 - }, - { - "path": "dufs-cloud/app/test/dufs_client_test.dart", - "lines": 257, - "churn": 4, - "roi": 1028 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/App.test.tsx", - "lines": 512, - "churn": 2, - "roi": 1024 - }, - { - "path": "diet-guard/app/lib/desktop/wrapper_server.dart", - "lines": 254, - "churn": 4, - "roi": 1016 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_scanning_confidence.py", - "lines": 253, - "churn": 4, - "roi": 1012 - }, - { - "path": "europe-county-map/src/sim/events.ts", - "lines": 333, - "churn": 3, - "roi": 999 - }, - { - "path": "testsAndMisc/meta/scripts/optimize_vscode.py", - "lines": 498, - "churn": 2, - "roi": 996 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_kcd2_dice_solver.sh", - "lines": 497, - "churn": 2, - "roi": 994 - }, - { - "path": "epopeja_karta/lib/ui/character_screen.dart", - "lines": 493, - "churn": 2, - "roi": 986 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_scanning_part4.py", - "lines": 326, - "churn": 3, - "roi": 978 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_hltb_search_part2.py", - "lines": 325, - "churn": 3, - "roi": 975 - }, - { - "path": "utils/gatelock/gatelock/_scrollable.py", - "lines": 483, - "churn": 2, - "roi": 966 - }, - { - "path": "utils/gatelock/gatelock/_recovery.py", - "lines": 321, - "churn": 3, - "roi": 963 - }, - { - "path": "testsAndMisc/linux_configuration/tests/test_usage_report_since.py", - "lines": 480, - "churn": 2, - "roi": 960 - }, - { - "path": "wake-alarm/wake_alarm/_escape_flow.py", - "lines": 317, - "churn": 3, - "roi": 951 - }, - { - "path": "screen-locker/screen_locker/tests/test_shutdown_part3.py", - "lines": 316, - "churn": 3, - "roi": 948 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/install_pacman_wrapper.sh", - "lines": 316, - "churn": 3, - "roi": 948 - }, - { - "path": "testsAndMisc/reverse_survivors/src/core/director.test.ts", - "lines": 315, - "churn": 3, - "roi": 945 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_state.py", - "lines": 314, - "churn": 3, - "roi": 942 - }, - { - "path": "screen-locker/screen_locker/tests/test_extra_benefits.py", - "lines": 311, - "churn": 3, - "roi": 933 - }, - { - "path": "steam-game-installer/steam_installer/cli.py", - "lines": 311, - "churn": 3, - "roi": 933 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_dot_resolver.sh", - "lines": 309, - "churn": 3, - "roi": 927 - }, - { - "path": "home_inventory/lib/screens/item_form_screen.dart", - "lines": 308, - "churn": 3, - "roi": 924 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/App.tsx", - "lines": 306, - "churn": 3, - "roi": 918 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_cups_queue.py", - "lines": 458, - "churn": 2, - "roi": 916 - }, - { - "path": "utils/sync_settings_ui/test/sync_settings_screen_test.dart", - "lines": 457, - "churn": 2, - "roi": 914 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_analyzer.py", - "lines": 452, - "churn": 2, - "roi": 904 - }, - { - "path": "utils/crdt_sync_dart/test/mirror_store_test.dart", - "lines": 452, - "churn": 2, - "roi": 904 - }, - { - "path": "utils/crdt_sync_dart/test/sync_revisions_test.dart", - "lines": 451, - "churn": 2, - "roi": 902 - }, - { - "path": "testsAndMisc/phone_focus_mode/lib/monitor.sh", - "lines": 449, - "churn": 2, - "roi": 898 - }, - { - "path": "dufs-cloud/app/lib/util/filter_sort.dart", - "lines": 298, - "churn": 3, - "roi": 894 - }, - { - "path": "screen-locker/screen_locker/tests/test_manual_push.py", - "lines": 294, - "churn": 3, - "roi": 882 - }, - { - "path": "utils/aur-publish/publish.sh", - "lines": 439, - "churn": 2, - "roi": 878 - }, - { - "path": "utils/crdt_sync_dart/test/github_client_test.dart", - "lines": 291, - "churn": 3, - "roi": 873 - }, - { - "path": "home_inventory/test/screens/filter_sheet_test.dart", - "lines": 284, - "churn": 3, - "roi": 852 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_alarm_audio.py", - "lines": 420, - "churn": 2, - "roi": 840 - }, - { - "path": "epopeja_karta/test/describe_change_test.dart", - "lines": 418, - "churn": 2, - "roi": 836 - }, - { - "path": "utils/gatelock/gatelock/tests/test_outputs.py", - "lines": 418, - "churn": 2, - "roi": 836 - }, - { - "path": "CV/generic/build_cv.py", - "lines": 417, - "churn": 2, - "roi": 834 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_polls_tracking_part2.py", - "lines": 417, - "churn": 2, - "roi": 834 - }, - { - "path": "manga_translate/mangatl/src/mangatl/adapters/vision.py", - "lines": 417, - "churn": 2, - "roi": 834 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/music_parallelism.sh", - "lines": 412, - "churn": 2, - "roi": 824 - }, - { - "path": "utils/crdt-sync/crdt_sync/tests/test_mirror.py", - "lines": 412, - "churn": 2, - "roi": 824 - }, - { - "path": "manga_translate/mangatl/tests/test_scripts.py", - "lines": 412, - "churn": 2, - "roi": 824 - }, - { - "path": "leetcode-guard/leetcode_guard/_escape_flow.py", - "lines": 274, - "churn": 3, - "roi": 822 - }, - { - "path": "testsAndMisc/focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/EnforcementDecision.kt", - "lines": 274, - "churn": 3, - "roi": 822 - }, - { - "path": "testsAndMisc/focus_owner/lib/policy.dart", - "lines": 272, - "churn": 3, - "roi": 816 - }, - { - "path": "utils/crdt_sync_dart/test/sync_test.dart", - "lines": 269, - "churn": 3, - "roi": 807 - }, - { - "path": "screen-locker/screen_locker/tests/test_phone_verification_part2.py", - "lines": 268, - "churn": 3, - "roi": 804 - }, - { - "path": "home_inventory/test/screens/item_detail_screen_test.dart", - "lines": 264, - "churn": 3, - "roi": 792 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_personal_website.sh", - "lines": 396, - "churn": 2, - "roi": 792 - }, - { - "path": "leetcode-guard/leetcode_guard/_lock.py", - "lines": 393, - "churn": 2, - "roi": 786 - }, - { - "path": "leetcode-guard/leetcode_guard/_view.py", - "lines": 262, - "churn": 3, - "roi": 786 - }, - { - "path": "testsAndMisc/billsplit/lib/ui/receipt_screen.dart", - "lines": 393, - "churn": 2, - "roi": 786 - }, - { - "path": "kuhytrack/linux/kt-watcher-linux.py", - "lines": 392, - "churn": 2, - "roi": 784 - }, - { - "path": "utils/crdt-sync/crdt_sync/tests/test_github.py", - "lines": 261, - "churn": 3, - "roi": 783 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_status_view_part3.py", - "lines": 391, - "churn": 2, - "roi": 782 - }, - { - "path": "screen-locker/screen_locker/tests/test_manual_sync.py", - "lines": 260, - "churn": 3, - "roi": 780 - }, - { - "path": "screen-locker/screen_locker/tests/test_weekly_check.py", - "lines": 259, - "churn": 3, - "roi": 777 - }, - { - "path": "screen-locker/screen_locker/tests/test_sick_tracker.py", - "lines": 386, - "churn": 2, - "roi": 772 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/core/simulate.ts", - "lines": 384, - "churn": 2, - "roi": 768 - }, - { - "path": "testsAndMisc/.github/skills/test-driven-development/SKILL.md", - "lines": 384, - "churn": 2, - "roi": 768 - }, - { - "path": "octoforge/octoforge/app/test/screens/sign_in_screen_test.dart", - "lines": 256, - "churn": 3, - "roi": 768 - }, - { - "path": "home_inventory/test/screens/locations_screen_test.dart", - "lines": 380, - "churn": 2, - "roi": 760 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/diagnose_arch_performance.sh", - "lines": 377, - "churn": 2, - "roi": 754 - }, - { - "path": "home_inventory/test/screens/item_form_screen_test.dart", - "lines": 376, - "churn": 2, - "roi": 752 - }, - { - "path": "epopeja_karta/test/l10n_test.dart", - "lines": 373, - "churn": 2, - "roi": 746 - }, - { - "path": "screen-locker/screen_locker/_status_data.py", - "lines": 370, - "churn": 2, - "roi": 740 - }, - { - "path": "diet-guard/diet_guard/tests/_tk_fakes.py", - "lines": 368, - "churn": 2, - "roi": 736 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_sync.py", - "lines": 365, - "churn": 2, - "roi": 730 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/core/scoring.ts", - "lines": 361, - "churn": 2, - "roi": 722 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/fix_bluetooth.sh", - "lines": 720, - "churn": 1, - "roi": 720 - }, - { - "path": "utils/crdt_sync_dart/test/firebase_config_test.dart", - "lines": 360, - "churn": 2, - "roi": 720 - }, - { - "path": "testsAndMisc/.github/skills/code-review-and-quality/SKILL.md", - "lines": 358, - "churn": 2, - "roi": 716 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/setup_offline_docs.sh", - "lines": 713, - "churn": 1, - "roi": 713 - }, - { - "path": "diet-guard/app/lib/screens/food_bank_screen.dart", - "lines": 712, - "churn": 1, - "roi": 712 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/tools/_transcribe_diarize.py", - "lines": 356, - "churn": 2, - "roi": 712 - }, - { - "path": "testsAndMisc/docs/superpowers/specs/2026-05-01-phone-focus-recovery-design.md", - "lines": 709, - "churn": 1, - "roi": 709 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_smart_plug.py", - "lines": 351, - "churn": 2, - "roi": 702 - }, - { - "path": "home_inventory/test/ui/widgets_test.dart", - "lines": 349, - "churn": 2, - "roi": 698 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_lock_part3.py", - "lines": 342, - "churn": 2, - "roi": 684 - }, - { - "path": "wake-alarm/wake_alarm/_sinks.py", - "lines": 341, - "churn": 2, - "roi": 682 - }, - { - "path": "screen-locker/screen_locker/tests/test_phone_verification_part3.py", - "lines": 340, - "churn": 2, - "roi": 680 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/README_FOR_LLM.md", - "lines": 338, - "churn": 2, - "roi": 676 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_main_part5.py", - "lines": 334, - "churn": 2, - "roi": 668 - }, - { - "path": "dufs-cloud/scripts/setup_dufs_cloud.sh", - "lines": 333, - "churn": 2, - "roi": 666 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_scenarios.py", - "lines": 333, - "churn": 2, - "roi": 666 - }, - { - "path": "utils/crdt_sync_dart/lib/src/firebase_auth_rest.dart", - "lines": 333, - "churn": 2, - "roi": 666 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/steam_compatibility.sh", - "lines": 663, - "churn": 1, - "roi": 663 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/raspberry_pi_flash_sd.sh", - "lines": 661, - "churn": 1, - "roi": 661 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/install_exercism.sh", - "lines": 330, - "churn": 2, - "roi": 660 - }, - { - "path": "testsAndMisc/meta/scripts/disk_cleanup_check.sh", - "lines": 329, - "churn": 2, - "roi": 658 - }, - { - "path": "utils/gatelock/gatelock/tests/test_scrollable.py", - "lines": 329, - "churn": 2, - "roi": 658 - }, - { - "path": "kuhytrack/tests/test_kt.py", - "lines": 328, - "churn": 2, - "roi": 656 - }, - { - "path": "macro-cam/tool/build_meal_dataset.py", - "lines": 327, - "churn": 2, - "roi": 654 - }, - { - "path": "home_inventory/lib/screens/locations_screen.dart", - "lines": 326, - "churn": 2, - "roi": 652 - }, - { - "path": "diet-guard/diet_guard/_estimator.py", - "lines": 325, - "churn": 2, - "roi": 650 - }, - { - "path": "screen-locker/screen_locker/tests/test_runnerup_verification_part4.py", - "lines": 320, - "churn": 2, - "roi": 640 - }, - { - "path": "utils/crdt-sync/crdt_sync/tests/test_firebase.py", - "lines": 319, - "churn": 2, - "roi": 638 - }, - { - "path": "screen-locker/scripts/verify_lock_popup_safety.py", - "lines": 318, - "churn": 2, - "roi": 636 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/screens/manual_workout_screen.dart", - "lines": 313, - "churn": 2, - "roi": 626 - }, - { - "path": "home_inventory/test/data/item_repository_locations_test.dart", - "lines": 624, - "churn": 1, - "roi": 624 - }, - { - "path": "macro-cam/test/vlm/vlm_response_test.dart", - "lines": 312, - "churn": 2, - "roi": 624 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/optimize_arch_desktop.sh", - "lines": 623, - "churn": 1, - "roi": 623 - }, - { - "path": ".claude/scripts/phone_deploy.sh", - "lines": 311, - "churn": 2, - "roi": 622 - }, - { - "path": "diet-guard/diet_guard/_gatelock_groups.py", - "lines": 309, - "churn": 2, - "roi": 618 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fresh-install/main.sh", - "lines": 309, - "churn": 2, - "roi": 618 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_playtime.py", - "lines": 617, - "churn": 1, - "roi": 617 - }, - { - "path": "i3wm-mcp/src/i3wm_mcp/server.py", - "lines": 615, - "churn": 1, - "roi": 615 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_lock_part2.py", - "lines": 306, - "churn": 2, - "roi": 612 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/fix_unity.sh", - "lines": 302, - "churn": 2, - "roi": 604 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/tools/transcribe_fw.py", - "lines": 302, - "churn": 2, - "roi": 604 - }, - { - "path": "kuhylog/kuhylog/lib/src/model/tracker.dart", - "lines": 301, - "churn": 2, - "roi": 602 - }, - { - "path": "diet-guard/app/test/services/average_service_test.dart", - "lines": 299, - "churn": 2, - "roi": 598 - }, - { - "path": "diet-guard/diet_guard/tests/test_gatelock_keyboard.py", - "lines": 299, - "churn": 2, - "roi": 598 - }, - { - "path": "dufs-cloud/app/test/pdf_screen_test.dart", - "lines": 298, - "churn": 2, - "roi": 596 - }, - { - "path": "diet-guard/diet_guard/_gatelock_calendar_ui.py", - "lines": 294, - "churn": 2, - "roi": 588 - }, - { - "path": "epopeja_karta/lib/ui/dialogs.dart", - "lines": 581, - "churn": 1, - "roi": 581 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/tools/transcribe_helpers.py", - "lines": 289, - "churn": 2, - "roi": 578 - }, - { - "path": "kuhylog/kuhylog/lib/src/state/app_state.dart", - "lines": 285, - "churn": 2, - "roi": 570 - }, - { - "path": "epopeja_karta/test/models_test.dart", - "lines": 282, - "churn": 2, - "roi": 564 - }, - { - "path": "manga_translate/mangatl/scripts/install-arch.sh", - "lines": 281, - "churn": 2, - "roi": 562 - }, - { - "path": "leetcode-guard/leetcode_guard/_ledger.py", - "lines": 280, - "churn": 2, - "roi": 560 - }, - { - "path": "macro-cam/lib/vlm/vlm_response.dart", - "lines": 279, - "churn": 2, - "roi": 558 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_cups_queue_part2.py", - "lines": 278, - "churn": 2, - "roi": 556 - }, - { - "path": "yay-mcp/yay_mcp/_actions.py", - "lines": 554, - "churn": 1, - "roi": 554 - }, - { - "path": "epopeja_karta/README.md", - "lines": 276, - "churn": 2, - "roi": 552 - }, - { - "path": "europe-county-map/src/sim/character.ts", - "lines": 275, - "churn": 2, - "roi": 550 - }, - { - "path": "leetcode-guard/leetcode_guard/_sync.py", - "lines": 275, - "churn": 2, - "roi": 550 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_lock.py", - "lines": 273, - "churn": 2, - "roi": 546 - }, - { - "path": "screen-locker/screen_locker/tests/test_phone_verification_part4.py", - "lines": 272, - "churn": 2, - "roi": 544 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/core/simulate.test.ts", - "lines": 272, - "churn": 2, - "roi": 544 - }, - { - "path": "leetcode-guard/leetcode_guard/_status_sections.py", - "lines": 271, - "churn": 2, - "roi": 542 - }, - { - "path": "diet-guard/app/test/services/day_status_service_test.dart", - "lines": 270, - "churn": 2, - "roi": 540 - }, - { - "path": "diet-guard/app/test/screens/edit_entry_screen_test.dart", - "lines": 269, - "churn": 2, - "roi": 538 - }, - { - "path": "testsAndMisc/python_pkg/focus_policy/tests/test_model.py", - "lines": 269, - "churn": 2, - "roi": 538 - }, - { - "path": "utils/gatelock/gatelock/tests/test_window.py", - "lines": 269, - "churn": 2, - "roi": 538 - }, - { - "path": "testsAndMisc/billsplit/test/ui_flows_test.dart", - "lines": 536, - "churn": 1, - "roi": 536 - }, - { - "path": "europe-county-map/src/eventQuery.ts", - "lines": 266, - "churn": 2, - "roi": 532 - }, - { - "path": "screen-locker/scripts/verify_screen_fits.py", - "lines": 266, - "churn": 2, - "roi": 532 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_cli_part2.py", - "lines": 263, - "churn": 2, - "roi": 526 - }, - { - "path": "manga_translate/mangatl/tests/test_app.py", - "lines": 523, - "churn": 1, - "roi": 523 - }, - { - "path": "testsAndMisc/linux_configuration/docs/VERIFICATION.md", - "lines": 261, - "churn": 2, - "roi": 522 - }, - { - "path": "testsAndMisc/linux_configuration/docs/PACMAN_WRAPPER_SECURITY.md", - "lines": 258, - "churn": 2, - "roi": 516 - }, - { - "path": "utils/unified-design-system/README.md", - "lines": 257, - "churn": 2, - "roi": 514 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/organize_downloads.sh", - "lines": 513, - "churn": 1, - "roi": 513 - }, - { - "path": "diet-guard/app/test/screens/github_mirror_screen_test.dart", - "lines": 512, - "churn": 1, - "roi": 512 - }, - { - "path": "diet-guard/app/test/widgets/day_status_calendar_test.dart", - "lines": 256, - "churn": 2, - "roi": 512 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_gitea.sh", - "lines": 255, - "churn": 2, - "roi": 510 - }, - { - "path": "octoforge/octoforge/packages/gh_core/lib/src/models/models.dart", - "lines": 510, - "churn": 1, - "roi": 510 - }, - { - "path": "testsAndMisc/focus_owner/test/policy_test.dart", - "lines": 253, - "churn": 2, - "roi": 506 - }, - { - "path": "europe-county-map/src/eventQuery.test.ts", - "lines": 252, - "churn": 2, - "roi": 504 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/lib/mtk_common.sh", - "lines": 503, - "churn": 1, - "roi": 503 - }, - { - "path": "atomichabits/atomichabits/extract.py", - "lines": 251, - "churn": 2, - "roi": 502 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/fix_ubuntu_performance.sh", - "lines": 494, - "churn": 1, - "roi": 494 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/diagnose_pacman_hook_stall.sh", - "lines": 493, - "churn": 1, - "roi": 493 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/libre_translate.sh", - "lines": 488, - "churn": 1, - "roi": 488 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/install_leechblock.sh", - "lines": 485, - "churn": 1, - "roi": 485 - }, - { - "path": "diet-guard/app/lib/screens/github_mirror_screen.dart", - "lines": 481, - "churn": 1, - "roi": 481 - }, - { - "path": "testsAndMisc/linux_configuration/C/atop_agg/atop_agg.c", - "lines": 478, - "churn": 1, - "roi": 478 - }, - { - "path": "yay-mcp/scripts/tdqs_score.py", - "lines": 478, - "churn": 1, - "roi": 478 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_player.py", - "lines": 473, - "churn": 1, - "roi": 473 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/transcribe.sh", - "lines": 473, - "churn": 1, - "roi": 473 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/screens/github_mirror_screen_test.dart", - "lines": 470, - "churn": 1, - "roi": 470 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_cli.py", - "lines": 470, - "churn": 1, - "roi": 470 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/_challenge.py", - "lines": 469, - "churn": 1, - "roi": 469 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/_playtime_block.py", - "lines": 462, - "churn": 1, - "roi": 462 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_activitywatch.sh", - "lines": 457, - "churn": 1, - "roi": 457 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_ui.py", - "lines": 453, - "churn": 1, - "roi": 453 - }, - { - "path": "manga_translate/mangatl/tests/test_quality.py", - "lines": 449, - "churn": 1, - "roi": 449 - }, - { - "path": "macro-cam/tool/run_meal_inference.py", - "lines": 448, - "churn": 1, - "roi": 448 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/migrate_hosts_guard_to_guard_lib.sh", - "lines": 444, - "churn": 1, - "roi": 444 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh", - "lines": 443, - "churn": 1, - "roi": 443 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/setup_thorium_startup.sh", - "lines": 443, - "churn": 1, - "roi": 443 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/screens/github_mirror_screen.dart", - "lines": 441, - "churn": 1, - "roi": 441 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_playtime_block_part2.py", - "lines": 438, - "churn": 1, - "roi": 438 - }, - { - "path": "utils/crdt-sync/crdt_sync/tests/test_sync_revisions.py", - "lines": 434, - "churn": 1, - "roi": 434 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/lib/services/progression_sync_service.dart", - "lines": 433, - "churn": 1, - "roi": 433 - }, - { - "path": "utils/gatelock/gatelock/tests/test_arbiter.py", - "lines": 432, - "churn": 1, - "roi": 432 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_app.py", - "lines": 429, - "churn": 1, - "roi": 429 - }, - { - "path": "octoforge/octoforge/packages/gh_core/lib/src/capabilities/feature_registry.dart", - "lines": 429, - "churn": 1, - "roi": 429 - }, - { - "path": "screen-locker/stronglift_replacement/workout_app/test/services/progression_sync_service_test.dart", - "lines": 426, - "churn": 1, - "roi": 426 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/mtk_root/tests/run_tests.sh", - "lines": 421, - "churn": 1, - "roi": 421 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/downloader.py", - "lines": 420, - "churn": 1, - "roi": 420 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/misc/testsAndMisc-bash/clean_audio.sh", - "lines": 419, - "churn": 1, - "roi": 419 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/core/search.ts", - "lines": 417, - "churn": 1, - "roi": 417 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/control_from_mobile.sh", - "lines": 415, - "churn": 1, - "roi": 415 - }, - { - "path": "testsAndMisc/python_pkg/android_ui/driver.py", - "lines": 411, - "churn": 1, - "roi": 411 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_syncyomi.sh", - "lines": 408, - "churn": 1, - "roi": 408 - }, - { - "path": "epopeja_karta/lib/pdf/character_pdf.dart", - "lines": 407, - "churn": 1, - "roi": 407 - }, - { - "path": "todo/test/port_guard_test.dart", - "lines": 405, - "churn": 1, - "roi": 405 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/_challenge_support.py", - "lines": 402, - "churn": 1, - "roi": 402 - }, - { - "path": "utils/gatelock/gatelock/_outputs.py", - "lines": 401, - "churn": 1, - "roi": 401 - }, - { - "path": "leetcode-guard/leetcode_guard/_study.py", - "lines": 400, - "churn": 1, - "roi": 400 - }, - { - "path": "screen-locker/screen_locker/tests/test_workout_sync_part2.py", - "lines": 400, - "churn": 1, - "roi": 400 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/ui.py", - "lines": 398, - "churn": 1, - "roi": 398 - }, - { - "path": "utils/gatelock/gatelock/_arbiter.py", - "lines": 397, - "churn": 1, - "roi": 397 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/install_unreal_mcp.sh", - "lines": 395, - "churn": 1, - "roi": 395 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/_analyzer.py", - "lines": 388, - "churn": 1, - "roi": 388 - }, - { - "path": "yay-mcp/tests/test_actions.py", - "lines": 387, - "churn": 1, - "roi": 387 - }, - { - "path": "home_inventory/test/screens/github_mirror_screen_test.dart", - "lines": 386, - "churn": 1, - "roi": 386 - }, - { - "path": "testsAndMisc/bucket_catch/packages/frontend/src/hooks/usePuzzleGameLoop.ts", - "lines": 386, - "churn": 1, - "roi": 386 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/store.py", - "lines": 382, - "churn": 1, - "roi": 382 - }, - { - "path": "utils/sync_settings_ui/lib/src/sync_settings_screen.dart", - "lines": 382, - "churn": 1, - "roi": 382 - }, - { - "path": "utils/gatelock/gatelock/_surfaces.py", - "lines": 380, - "churn": 1, - "roi": 380 - }, - { - "path": "testsAndMisc/python_pkg/android_ui/tests/test_driver.py", - "lines": 377, - "churn": 1, - "roi": 377 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/fix_thorium.sh", - "lines": 377, - "churn": 1, - "roi": 377 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/setup_passwordless_system.sh", - "lines": 374, - "churn": 1, - "roi": 374 - }, - { - "path": "utils/crdt_sync_dart/test/firebase_client_test.dart", - "lines": 374, - "churn": 1, - "roi": 374 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/player.py", - "lines": 373, - "churn": 1, - "roi": 373 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_challenge_part3.py", - "lines": 373, - "churn": 1, - "roi": 373 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_net.py", - "lines": 370, - "churn": 1, - "roi": 370 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_local_llm.sh", - "lines": 370, - "churn": 1, - "roi": 370 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/data/badges.ts", - "lines": 369, - "churn": 1, - "roi": 369 - }, - { - "path": "todo/lib/ui/github_mirror_screen.dart", - "lines": 368, - "churn": 1, - "roi": 368 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_escape_flow.py", - "lines": 367, - "churn": 1, - "roi": 367 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/repo_to_study.sh", - "lines": 365, - "churn": 1, - "roi": 365 - }, - { - "path": "todo/test/github_mirror_screen_test.dart", - "lines": 365, - "churn": 1, - "roi": 365 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_verifier.py", - "lines": 361, - "churn": 1, - "roi": 361 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/features/setup_dwm.sh", - "lines": 359, - "churn": 1, - "roi": 359 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_study_part2.py", - "lines": 352, - "churn": 1, - "roi": 352 - }, - { - "path": "diet-guard/diet_guard/tests/test_averages.py", - "lines": 351, - "churn": 1, - "roi": 351 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_playtime_tick.py", - "lines": 350, - "churn": 1, - "roi": 350 - }, - { - "path": "utils/guard-lib/lib/file_guard.sh", - "lines": 350, - "churn": 1, - "roi": 350 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/mtk_root/10-recon.sh", - "lines": 349, - "churn": 1, - "roi": 349 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/_verifier.py", - "lines": 347, - "churn": 1, - "roi": 347 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_challenge.py", - "lines": 346, - "churn": 1, - "roi": 346 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/cli.py", - "lines": 345, - "churn": 1, - "roi": 345 - }, - { - "path": "utils/gatelock/gatelock/tests/test_escape.py", - "lines": 343, - "churn": 1, - "roi": 343 - }, - { - "path": "screen-locker/DESIGN_AUDIT_TODO.md", - "lines": 341, - "churn": 1, - "roi": 341 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_downloader.py", - "lines": 341, - "churn": 1, - "roi": 341 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/nvidia_troubleshoot.sh", - "lines": 336, - "churn": 1, - "roi": 336 - }, - { - "path": "home_inventory/lib/screens/github_mirror_screen.dart", - "lines": 335, - "churn": 1, - "roi": 335 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/net.py", - "lines": 335, - "churn": 1, - "roi": 335 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/core/badgeValue.ts", - "lines": 333, - "churn": 1, - "roi": 333 - }, - { - "path": "testsAndMisc/phone_focus_mode/phone_backup.sh", - "lines": 333, - "churn": 1, - "roi": 333 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_downloader_part2.py", - "lines": 333, - "churn": 1, - "roi": 333 - }, - { - "path": "testsAndMisc/bucket_catch/packages/frontend/src/hooks/usePuzzleGameLoop.test.ts", - "lines": 332, - "churn": 1, - "roi": 332 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/review.py", - "lines": 330, - "churn": 1, - "roi": 330 - }, - { - "path": "utils/crdt-sync/crdt_sync/_firebase.py", - "lines": 330, - "churn": 1, - "roi": 330 - }, - { - "path": "steam-game-installer/tests/test_cli.py", - "lines": 328, - "churn": 1, - "roi": 328 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_lock_study.py", - "lines": 327, - "churn": 1, - "roi": 327 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/fixes/fix_arch_performance.sh", - "lines": 326, - "churn": 1, - "roi": 326 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/utils/format_sd_card.sh", - "lines": 323, - "churn": 1, - "roi": 323 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_llm.py", - "lines": 320, - "churn": 1, - "roi": 320 - }, - { - "path": "utils/crdt-sync/tool/google_id_token.py", - "lines": 316, - "churn": 1, - "roi": 316 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/boot_recovery/tests/test_boot_repair.sh", - "lines": 315, - "churn": 1, - "roi": 315 - }, - { - "path": "octoforge/octoforge/packages/gh_core/test/rest_client_test.dart", - "lines": 313, - "churn": 1, - "roi": 313 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/system-maintenance/bin/_usage_report_render.py", - "lines": 310, - "churn": 1, - "roi": 310 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/tests/test_challenge_part2.py", - "lines": 308, - "churn": 1, - "roi": 308 - }, - { - "path": "diet-guard/diet_guard/tests/test_gatelock_fanout.py", - "lines": 302, - "churn": 1, - "roi": 302 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/lib/inventoryIo.test.ts", - "lines": 302, - "churn": 1, - "roi": 302 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/digital_wellbeing/README_MIDNIGHT_SHUTDOWN_LLM.md", - "lines": 300, - "churn": 1, - "roi": 300 - }, - { - "path": "todo/test/analytics_service_test.dart", - "lines": 300, - "churn": 1, - "roi": 300 - }, - { - "path": "utils/gatelock/gatelock/_escape.py", - "lines": 300, - "churn": 1, - "roi": 300 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/single_use/install_joplin.sh", - "lines": 299, - "churn": 1, - "roi": 299 - }, - { - "path": "diet-guard/diet_guard/_averages.py", - "lines": 298, - "churn": 1, - "roi": 298 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/tests/test_review.py", - "lines": 297, - "churn": 1, - "roi": 297 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_status_view.py", - "lines": 296, - "churn": 1, - "roi": 296 - }, - { - "path": "octoforge/octoforge/packages/gh_core/test/models_test.dart", - "lines": 296, - "churn": 1, - "roi": 296 - }, - { - "path": "testsAndMisc/python_pkg/code_tutor/_llm.py", - "lines": 295, - "churn": 1, - "roi": 295 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/mtk_root/20-dump-stock.sh", - "lines": 295, - "churn": 1, - "roi": 295 - }, - { - "path": "manga_translate/mangatl/src/mangatl/adapters/aot.py", - "lines": 294, - "churn": 1, - "roi": 294 - }, - { - "path": "testsAndMisc/billsplit/lib/domain/eparagon_parser.dart", - "lines": 293, - "churn": 1, - "roi": 293 - }, - { - "path": "manga_translate/mangatl/src/mangatl/web/app.py", - "lines": 293, - "churn": 1, - "roi": 293 - }, - { - "path": "manga_translate/mangatl/tests/test_domain.py", - "lines": 291, - "churn": 1, - "roi": 291 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/periodic_background/system-maintenance/bin/install_usage_monitoring.sh", - "lines": 290, - "churn": 1, - "roi": 290 - }, - { - "path": "diet-guard/diet_guard/tests/test_budget_history.py", - "lines": 288, - "churn": 1, - "roi": 288 - }, - { - "path": "habit_stack/windows/runner/win32_window.cpp", - "lines": 288, - "churn": 1, - "roi": 288 - }, - { - "path": "testsAndMisc/billsplit/windows/runner/win32_window.cpp", - "lines": 288, - "churn": 1, - "roi": 288 - }, - { - "path": "testsAndMisc/docs/cleanup-2026-05/SHELL_SCRIPT_QUALITY_GUIDELINES.md", - "lines": 288, - "churn": 1, - "roi": 288 - }, - { - "path": "testsAndMisc/kcd2_dice_solver/src/lib/inventoryIo.ts", - "lines": 287, - "churn": 1, - "roi": 287 - }, - { - "path": "utils/crdt-sync/crdt_sync/tests/test_config.py", - "lines": 285, - "churn": 1, - "roi": 285 - }, - { - "path": "steam-backlog-enforcer/steam_backlog_enforcer/tests/test_playtime_part2.py", - "lines": 283, - "churn": 1, - "roi": 283 - }, - { - "path": "testsAndMisc/docs/cleanup-2026-05/COMPLETE_IMPLEMENTATION_SUMMARY.md", - "lines": 283, - "churn": 1, - "roi": 283 - }, - { - "path": "utils/crdt_sync_dart/lib/src/firebase_client.dart", - "lines": 283, - "churn": 1, - "roi": 283 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/cli.py", - "lines": 282, - "churn": 1, - "roi": 282 - }, - { - "path": "utils/gatelock/gatelock/tests/test_surfaces.py", - "lines": 282, - "churn": 1, - "roi": 282 - }, - { - "path": "epopeja_karta/tool/check_l10n.dart", - "lines": 279, - "churn": 1, - "roi": 279 - }, - { - "path": "opengameart-mcp/opengameart_mcp/client.py", - "lines": 279, - "churn": 1, - "roi": 279 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/consumables.py", - "lines": 279, - "churn": 1, - "roi": 279 - }, - { - "path": "testsAndMisc/billsplit/lib/domain/models.dart", - "lines": 278, - "churn": 1, - "roi": 278 - }, - { - "path": "todo/docs/desktop-performance-findings.md", - "lines": 278, - "churn": 1, - "roi": 278 - }, - { - "path": "testsAndMisc/docs/cleanup-2026-05/QUICK_REFERENCE_SHELL_QUALITY.md", - "lines": 276, - "churn": 1, - "roi": 276 - }, - { - "path": "i3wm-mcp/tests/test_server.py", - "lines": 275, - "churn": 1, - "roi": 275 - }, - { - "path": "screen-locker/screen_locker/tests/test_compliance_state.py", - "lines": 275, - "churn": 1, - "roi": 275 - }, - { - "path": "testsAndMisc/billsplit/lib/ui/people_screen.dart", - "lines": 273, - "churn": 1, - "roi": 273 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_consumables.py", - "lines": 272, - "churn": 1, - "roi": 272 - }, - { - "path": "testsAndMisc/focus_owner/lib/enforcement_status_card.dart", - "lines": 268, - "churn": 1, - "roi": 268 - }, - { - "path": "testsAndMisc/python_pkg/brother_printer/tests/test_consumables_part2.py", - "lines": 268, - "churn": 1, - "roi": 268 - }, - { - "path": "leetcode-guard/leetcode_guard/tests/test_gate.py", - "lines": 267, - "churn": 1, - "roi": 267 - }, - { - "path": "testsAndMisc/phone_focus_mode/tether_enforcer.sh", - "lines": 267, - "churn": 1, - "roi": 267 - }, - { - "path": "octoforge/octoforge/packages/gh_core/lib/src/repositories/repositories.dart", - "lines": 267, - "churn": 1, - "roi": 267 - }, - { - "path": "testsAndMisc/linux_configuration/zsh/calc-live.zsh", - "lines": 266, - "churn": 1, - "roi": 266 - }, - { - "path": "epopeja_karta/test/legacy_load_test.dart", - "lines": 265, - "churn": 1, - "roi": 265 - }, - { - "path": ".claude/rules/shell.instructions.md", - "lines": 263, - "churn": 1, - "roi": 263 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/mtk_root/install.sh", - "lines": 262, - "churn": 1, - "roi": 262 - }, - { - "path": "manga_translate/mangatl/src/mangatl/domain/models.py", - "lines": 259, - "churn": 1, - "roi": 259 - }, - { - "path": "leetcode-guard/leetcode_guard/_status_extra.py", - "lines": 254, - "churn": 1, - "roi": 254 - }, - { - "path": "i3wm-mcp/tests/conftest.py", - "lines": 253, - "churn": 1, - "roi": 253 - }, - { - "path": "testsAndMisc/meta/scripts/mutate_session_autopsy_hooks.py", - "lines": 253, - "churn": 1, - "roi": 253 - }, - { - "path": "wake-alarm/wake_alarm/tests/test_trigger.py", - "lines": 252, - "churn": 1, - "roi": 252 - }, - { - "path": "testsAndMisc/focus_owner/android/app/src/test/kotlin/com/kuhy/focus_owner/EnforcementLogTest.kt", - "lines": 251, - "churn": 1, - "roi": 251 - }, - { - "path": "testsAndMisc/python_pkg/random_jpg/tests/test_generate_jpeg.py", - "lines": 251, - "churn": 1, - "roi": 251 - }, - { - "path": "testsAndMisc/python_pkg/wsg_grabber/catalog.py", - "lines": 251, - "churn": 1, - "roi": 251 - }, - { - "path": "wake-alarm/DESIGN_AUDIT_TODO.md", - "lines": 251, - "churn": 1, - "roi": 251 - }, - { - "path": "CV/magisterskie/cv.tex", - "lines": 548, - "churn": 0, - "roi": 0 - }, - { - "path": "CV/ai_clearing_parp/pl/gen_oswiadczenie.py", - "lines": 278, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/parse.py", - "lines": 487, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/report.py", - "lines": 476, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/cli.py", - "lines": 390, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/records.py", - "lines": 390, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/detectors.py", - "lines": 467, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/traces.py", - "lines": 392, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/tests/test_parse.py", - "lines": 356, - "churn": 0, - "roi": 0 - }, - { - "path": "mcp-servers/session-autopsy/session_autopsy/tests/test_traces.py", - "lines": 266, - "churn": 0, - "roi": 0 - }, - { - "path": "testsAndMisc/poker-stakes/src/ui/useGame.test.tsx", - "lines": 494, - "churn": 0, - "roi": 0 - }, - { - "path": "testsAndMisc/poker-stakes/src/ui/useGame.ts", - "lines": 268, - "churn": 0, - "roi": 0 - }, - { - "path": "testsAndMisc/poker-stakes/src/engine/handFlow.ts", - "lines": 252, - "churn": 0, - "roi": 0 - }, - { - "path": "testsAndMisc/poker-stakes/src/engine/handEval.test.ts", - "lines": 269, - "churn": 0, - "roi": 0 - }, - { - "path": "testsAndMisc/linux_configuration/scripts/meta/shell_check.sh", - "lines": 428, - "churn": 0, - "roi": 0 - } - ] -} \ No newline at end of file diff --git a/file_length/config.py b/file_length/config.py index 7550b58..700ace3 100644 --- a/file_length/config.py +++ b/file_length/config.py @@ -1,252 +1,45 @@ """Shared configuration for the 250-line file-length cap. Single source of truth for the cap and its exemptions, imported by both the -pre-commit gate (`check.py`) and the survey. Duplicating these lists in shell -is what lets a gate and a survey silently disagree. +pre-commit gate (`check.py`) and the survey. This module is the public +surface: :mod:`file_length._tables` holds the data, and +:mod:`file_length.exemptions` the rules that read it. """ from __future__ import annotations -from pathlib import Path -import re - -#: Hard cap. Files above this fail the gate. Code and prose alike. -MAX_LINES = 250 - -#: Extensions the cap applies to: real programming languages plus prose. -#: Markup (.html/.css/.scss) is deliberately absent -- templates split into -#: partials, not functions, so a line cap does not express anything useful. -CAPPED_EXTENSIONS = { - # code - ".py", - ".dart", - ".ts", - ".tsx", - ".js", - ".jsx", - ".sh", - ".bash", - ".zsh", - ".c", - ".h", - ".cpp", - ".cc", - ".hpp", - ".go", - ".rs", - ".java", - ".kt", - ".kts", - ".swift", - ".rb", - ".lua", - ".sql", - ".vue", - ".cs", - ".php", - # prose - ".md", - ".markdown", - ".txt", - ".rst", - ".tex", - ".org", -} - -#: Generated files: regenerated by a tool, so splitting them is meaningless -#: (the tool would just rewrite the original next run). -GENERATED_PATTERN = re.compile( - r"\.g\.dart$" - r"|\.freezed\.dart$" - r"|\.gr\.dart$" - r"|\.config\.dart$" - r"|\.mocks\.dart$" - r"|\.min\.(js|css)$" - r"|\.pb\.(go|py)$" - r"|_pb2(_grpc)?\.py$" - r"|\.generated\.ts$" - r"|\.d\.ts$" - r"|/l10n/generated/" - r"|/generated/" +from file_length._tables import ( + CAPPED_EXTENSIONS, + DATA_TXT_MAX_MEAN_LINE, + EXCLUDED_DIRS, + GENERATED_MARKERS, + GENERATED_PATTERN, + MAX_LINES, + SESSION_ARTIFACTS_ANYWHERE, + THIRD_PARTY_REPOS, + VENDORED_ANYWHERE, + VENDORED_SUBPATHS, +) +from file_length.exemptions import ( + is_data_text, + is_generated, + is_session_artifact, + is_vendored, ) -#: A marker in the first few lines also marks a file generated. Covers tools -#: that do not use a distinguishing extension. -GENERATED_MARKERS = ( - "GENERATED CODE - DO NOT MODIFY", - "@generated", - "DO NOT EDIT", - "Autogenerated", - "AUTOGENERATED", - "generated by", -) - -#: Directory names never descended into: dependencies, build output, caches. -EXCLUDED_DIRS = frozenset( - { - ".git", - "node_modules", - ".dart_tool", - "build", - ".venv", - "venv", - "env", - "site-packages", - "target", - "ephemeral", - "__pycache__", - ".mypy_cache", - ".pytest_cache", - ".ruff_cache", - "dist", - ".next", - "vendor", - "third_party", - "Pods", - ".gradle", - ".idea", - ".cxx", - "coverage", - "htmlcov", - ".tox", - "Library", - "Temp", - "obj", - ".terraform", - ".fvm", - ".angular", - ".cache", - ".svelte-kit", - "migrations", - ".ci-mirror-venv", - ".hippo", - ".build-deps", - # Where CI checks out the shared gate itself (kuhyx/utils). Without - # this, a repo's lint job fails on utils' own long files -- a gate - # that fails for reasons the repo being gated cannot fix. - ".utils", - } -) - -#: Third-party content living *inside* a repo you own, keyed by repo dir name. -#: Verified by git remote / vendor manifest, not guessed. -VENDORED_SUBPATHS = { - "mcp-servers": ("servers",), - "dufs-cloud": ("app/assets/pdfjs", "web/assets/pdfjs"), - ".claude": ( - "projects", - "shell-snapshots", - "cache", - "backups", - "todos", - "statsig", - "history", - "chrome", - "downloads", - "plugins", - "ide", - ), - # Agent skill bundles vendored from Anthropic (todo: commit f91311f). - # A SKILL.md is a fixed-name file with frontmatter; detail belongs in a - # sibling references/ dir, so splitting one into SKILL.part2.md would - # break the format rather than improve readability. - "todo": (".agents/skills",), -} - -#: Directory names that mark a vendored agent-skill tree wherever they appear. -#: Keyed by name rather than repo because these bundles get dropped into any -#: repo that wants them, not just the one they were first seen in. -VENDORED_ANYWHERE = ("/.agents/skills/", "/.claude/skills/") - -#: Frozen records of past agent sessions: an implementation plan or an -#: append-only session log describes what was done at one moment. Splitting one -#: rewrites a historical record for no reading benefit -- nobody navigates them, -#: they are read whole or not at all. Same category as generated files. -#: -#: Deliberately NOT the whole of docs/superpowers/: `specs/` and `contracts/` -#: stay capped, because those are living documents that get re-read and edited. -SESSION_ARTIFACTS_ANYWHERE = ( - "/docs/superpowers/plans/", - "/docs/superpowers/sessions/", -) - -#: Whole repos under ~ that are third-party clones, not kuhy's work. -#: Verified 2026-08-14 by `git remote get-url origin` + commit authors. -THIRD_PARTY_REPOS = frozenset( - { - "StringTheory", # github.com/AnthonySf/TheStringTheory - "reaper-mcp", # github.com/TwelveTake-Studios/reaper-mcp - "freesound-mcp", # github.com/timjrobinson/FreesoundMCPServer - "llama_cpp_dart_local", # generated FFI bindings - "aseprite-mcp", - "Mapperatorinator", # github.com/OliBomby/Mapperatorinator - "aur", - "build-your-own-x", - "build_your_x", - "byox-ladder", - "warriorjs", - "untools", - "awesome-mcp-explorer", - "runnerup", - "depotdownloader", - "actions-runner", - } -) - -#: A `.txt` whose mean line is shorter than this is data (a wordlist, a -#: coordinate dump), not prose, so the cap does not apply. -DATA_TXT_MAX_MEAN_LINE = 25 - - -def is_generated(path: Path) -> bool: - """True if the file is tool-generated and must not be split by hand.""" - if GENERATED_PATTERN.search(path.as_posix()): - return True - try: - with path.open("r", encoding="utf-8", errors="replace") as handle: - head = "".join(next(handle, "") for _ in range(5)) - except OSError: - return False - return any(marker in head for marker in GENERATED_MARKERS) - - -def is_data_text(path: Path, lines: int, size: int) -> bool: - """True for wordlist-style .txt: many lines, very short ones.""" - if path.suffix.lower() != ".txt" or lines <= 0: - return False - return (size / lines) < DATA_TXT_MAX_MEAN_LINE - - -def is_vendored(path: Path) -> bool: - """True if the path sits under a known vendored subtree or excluded dir. - - Callers must pass an absolute path (see `check.absolutize`). Every rule - below needs the repo-name context that a repo-relative path has already - thrown away: '/.claude/skills/' cannot match 'skills/x.md', so a relative - path would quietly skip the exemption instead of applying it. - """ - parts = path.parts - if any(part in EXCLUDED_DIRS for part in parts): - return True - posix = path.as_posix() - if any(marker in posix for marker in VENDORED_ANYWHERE): - return True - for repo, subs in VENDORED_SUBPATHS.items(): - for sub in subs: - if f"/{repo}/{sub}/" in posix: - return True - return any(f"/{repo}/" in posix for repo in THIRD_PARTY_REPOS) - - -def is_session_artifact(path: Path) -> bool: - """True for a frozen agent-session record (a plan or a session log). - - Kept separate from `is_vendored` so the gate reports why a file is exempt: - these are kuhy's own files, not third-party code. - - Callers must pass an absolute path (see `check.absolutize`), for the same - reason `is_vendored` does -- a repo-relative path has already dropped the - leading directory these markers match on. - """ - posix = path.as_posix() - return any(marker in posix for marker in SESSION_ARTIFACTS_ANYWHERE) +__all__ = [ + "CAPPED_EXTENSIONS", + "DATA_TXT_MAX_MEAN_LINE", + "EXCLUDED_DIRS", + "GENERATED_MARKERS", + "GENERATED_PATTERN", + "MAX_LINES", + "SESSION_ARTIFACTS_ANYWHERE", + "THIRD_PARTY_REPOS", + "VENDORED_ANYWHERE", + "VENDORED_SUBPATHS", + "is_data_text", + "is_generated", + "is_session_artifact", + "is_vendored", +] diff --git a/file_length/exemptions.py b/file_length/exemptions.py new file mode 100644 index 0000000..be7ffa4 --- /dev/null +++ b/file_length/exemptions.py @@ -0,0 +1,82 @@ +"""Predicates deciding whether a file is exempt from the 250-line cap. + +Split from :mod:`file_length.config`, which holds the tables these read. +Keeping the rules separate from the data they consult means a new exemption +is a table entry, not a new branch, and the gate and the survey keep sharing +one definition of "exempt". + +Re-exported from :mod:`file_length.config`, so existing +``from file_length.config import is_generated`` imports keep working. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from file_length._tables import ( + DATA_TXT_MAX_MEAN_LINE, + EXCLUDED_DIRS, + GENERATED_MARKERS, + GENERATED_PATTERN, + SESSION_ARTIFACTS_ANYWHERE, + THIRD_PARTY_REPOS, + VENDORED_ANYWHERE, + VENDORED_SUBPATHS, +) + +if TYPE_CHECKING: + from pathlib import Path + + +def is_generated(path: Path) -> bool: + """True if the file is tool-generated and must not be split by hand.""" + if GENERATED_PATTERN.search(path.as_posix()): + return True + try: + with path.open("r", encoding="utf-8", errors="replace") as handle: + head = "".join(next(handle, "") for _ in range(5)) + except OSError: + return False + return any(marker in head for marker in GENERATED_MARKERS) + + +def is_data_text(path: Path, lines: int, size: int) -> bool: + """True for wordlist-style .txt: many lines, very short ones.""" + if path.suffix.lower() != ".txt" or lines <= 0: + return False + return (size / lines) < DATA_TXT_MAX_MEAN_LINE + + +def is_vendored(path: Path) -> bool: + """True if the path sits under a known vendored subtree or excluded dir. + + Callers must pass an absolute path (see `check.absolutize`). Every rule + below needs the repo-name context that a repo-relative path has already + thrown away: '/.claude/skills/' cannot match 'skills/x.md', so a relative + path would quietly skip the exemption instead of applying it. + """ + parts = path.parts + if any(part in EXCLUDED_DIRS for part in parts): + return True + posix = path.as_posix() + if any(marker in posix for marker in VENDORED_ANYWHERE): + return True + for repo, subs in VENDORED_SUBPATHS.items(): + for sub in subs: + if f"/{repo}/{sub}/" in posix: + return True + return any(f"/{repo}/" in posix for repo in THIRD_PARTY_REPOS) + + +def is_session_artifact(path: Path) -> bool: + """True for a frozen agent-session record (a plan or a session log). + + Kept separate from `is_vendored` so the gate reports why a file is exempt: + these are kuhy's own files, not third-party code. + + Callers must pass an absolute path (see `check.absolutize`), for the same + reason `is_vendored` does -- a repo-relative path has already dropped the + leading directory these markers match on. + """ + posix = path.as_posix() + return any(marker in posix for marker in SESSION_ARTIFACTS_ANYWHERE) diff --git a/guard-lib/guardctl b/guard-lib/guardctl index d19c5a4..55e58c9 100755 --- a/guard-lib/guardctl +++ b/guard-lib/guardctl @@ -18,6 +18,8 @@ fi source "$LIB_DIR/common.sh" # shellcheck source=lib/file_guard.sh source "$LIB_DIR/file_guard.sh" +# shellcheck source=lib/file_guard_unlock.sh +source "$LIB_DIR/file_guard_unlock.sh" # shellcheck source=lib/package_block.sh source "$LIB_DIR/package_block.sh" diff --git a/guard-lib/lib/file_guard.sh b/guard-lib/lib/file_guard.sh index fcb91fb..098c0ff 100644 --- a/guard-lib/lib/file_guard.sh +++ b/guard-lib/lib/file_guard.sh @@ -138,213 +138,3 @@ fg_enforce() { [[ "$BIND_MOUNT" == "yes" ]] && _reapply_bind_mount "$name" log_hook "file-guard $name: enforce ok" } - -fg_unlock() { - local name="$1" - require_root - load_target_conf "$name" - # shellcheck disable=SC2153 # PLUGIN set by load_target_conf, not a typo - load_plugin "$PLUGIN" - echo "About to unlock file-guard '$name' ($TARGET) for editing." - read -rp "Reason for unlocking: " reason - [[ -n "$reason" ]] || die "a reason is required" - log_hook "file-guard $name: UNLOCK requested by ${SUDO_USER:-$(whoami)}: $reason" - echo "Unlocking in 45s (Ctrl-C to abort)..." - sleep 45 - # Stop the watcher before unlocking: chattr alone (no content write) - # fires PathModified, and the resulting enforce pass unconditionally - # re-locks the target even with no drift - which would silently - # re-lock this file out from under the editor. Confirmed live during - # the shutdown-schedule migration (see guard-lib project notes). - systemctl stop "guard-file@${name}.path" 2>/dev/null || true - # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo - [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" - unlock_file "$TARGET" - log_hook "file-guard $name: unlocked for editing" - - local before after - before="$(sha256sum "$TARGET" 2>/dev/null | awk '{print $1}')" - # Deliberately unquoted: $EDITOR commonly carries arguments (e.g. - # "code --wait", "emacsclient -t") that must be word-split. - ${EDITOR:-vi} "$TARGET" - after="$(sha256sum "$TARGET" 2>/dev/null | awk '{print $1}')" - - if [[ "$before" != "$after" ]]; then - if declare -f validate >/dev/null 2>&1 && ! validate "$TARGET"; then - echo "New content fails this instance's validate() check - reverting your edit; canonical unchanged." >&2 - log_hook "file-guard $name: edit REJECTED (failed validate), reverting to canonical" - [[ -e "$CANONICAL" ]] && cp --preserve=mode,ownership,timestamps "$CANONICAL" "$TARGET" - else - # Update canonical to match: without this, re-locking below - # fires the watcher, which would see the new content as - # "drift" against the stale canonical and silently revert - # this legitimate edit. - log_hook "file-guard $name: content changed, updating canonical" - unlock_file "$CANONICAL" - cp --preserve=mode,ownership,timestamps "$TARGET" "$CANONICAL" - lock_file "$CANONICAL" - fi - else - log_hook "file-guard $name: no content change" - fi - - lock_file "$TARGET" - # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo - [[ "$BIND_MOUNT" == "yes" ]] && _reapply_bind_mount "$name" - systemctl start "guard-file@${name}.path" 2>/dev/null || true - log_hook "file-guard $name: re-locked after edit" - echo "Re-locked '$name'." -} - -fg_uninstall() { - local name="$1" - shift - local keep_canonical=0 - while [[ $# -gt 0 ]]; do - case "$1" in - --keep-canonical) keep_canonical=1; shift ;; - *) die "file-guard uninstall: unknown argument '$1'" ;; - esac - done - require_root - load_target_conf "$name" - systemctl disable --now "guard-file@$name.path" 2>/dev/null || true - systemctl disable --now "guard-bind-mount@$name.service" 2>/dev/null || true - rm -rf "${GUARD_LIB_SYSTEMD_DIR:?}/guard-file@$name.path.d" - systemctl daemon-reload - # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo - [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" - unlock_file "$TARGET" - if [[ "$keep_canonical" -eq 0 ]]; then - unlock_file "$CANONICAL" - rm -f "$CANONICAL" - fi - rm -f "$(target_conf_path "$name")" - log_hook "file-guard $name: uninstalled (keep_canonical=$keep_canonical)" - echo "uninstalled file-guard '$name'" -} - -fg_status() { - local name="$1" - load_target_conf "$name" - echo "name: $name" - echo "target: $TARGET" - echo "canonical: $CANONICAL" - # shellcheck disable=SC2153 # BIND_MOUNT/PLUGIN/ALSO_WATCH set by load_target_conf, not typos - echo "bind_mount: $BIND_MOUNT" - echo "plugin: ${PLUGIN:-}" - echo "also_watch: ${ALSO_WATCH:-}" - if [[ -e "$TARGET" ]]; then - local attrs - attrs="$(lsattr "$TARGET" 2>/dev/null | awk '{print $1}')" - echo "target attrs: ${attrs:-unknown}" - else - echo "target: MISSING" - fi - local unit_state - unit_state="$(systemctl is-active "guard-file@$name.path" 2>/dev/null || true)" - echo "path unit: ${unit_state:-unknown}" -} - -fg_canonical_path() { - # Machine-readable single-value output: the canonical path for an - # instance, so consumers with bespoke unlock flows (that can't go - # through `unlock`/`enforce` directly) don't have to hardcode or - # duplicate guard-lib's canonical-path convention. - local name="$1" - load_target_conf "$name" - echo "$CANONICAL" -} - -fg_pacman_unlock() { - # Quiet, non-interactive unlock used only by the generic pacman - # PreTransaction hook - no typed reason, no editor. The pacman - # transaction itself is the sanctioned reason. - # - # Stops the path unit, not just chattr -i's the target: chattr alone - # fires PathModified, and if the watcher's enforce pass wins the race - # against pacman's own write, it silently re-locks the file before - # pacman gets to it, breaking the very transaction this hook exists - # to allow. Matches the pre-existing hosts-guard pacman hooks, which - # stop hosts-guard.path/nsswitch-guard.path/resolved-guard.path for - # the same reason. - local name="$1" - load_target_conf "$name" - systemctl stop "guard-file@${name}.path" 2>/dev/null || true - # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo - [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" - unlock_file "$TARGET" - log_hook "file-guard $name: pacman-unlock (pre-transaction)" -} - -fg_pacman_relock() { - # Counterpart to fg_pacman_unlock, used only by the generic pacman - # PostTransaction hook: re-enforce (drift-restore + chattr +i, and - - # if this instance is bind-mounted - re-establish the read-only - # bind mount, since fg_enforce does that itself now) then restart - # the path unit that pacman-unlock stopped. - local name="$1" - fg_enforce "$name" - systemctl start "guard-file@${name}.path" 2>/dev/null || true - log_hook "file-guard $name: pacman-relock (post-transaction)" -} - -fg_sync_canonical() { - # Counterpart to fg_pacman_unlock for callers that legitimately EDITED - # the target (not pacman's own hook flow, which wants drift reverted). - # Adopts the target's current content as the new canonical, instead of - # fg_enforce's drift-check-and-revert - which would otherwise silently - # undo the very edit the caller just made. Assumes the watcher was - # already stopped by a prior fg_pacman_unlock; does not stop it itself. - local name="$1" - load_target_conf "$name" - snapshot_canonical "$name" - # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo - [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" - unlock_file "$TARGET" - lock_file "$TARGET" - [[ "$BIND_MOUNT" == "yes" ]] && _reapply_bind_mount "$name" - systemctl start "guard-file@${name}.path" 2>/dev/null || true - log_hook "file-guard $name: synced canonical to current content" -} - -# Self-bind-mounts TARGET over itself, then remounts that layer -# read-only. This is a mount-level lock independent of chattr: even a -# successful `chattr -i` bypass still can't write through a read-only -# mount. Deliberately does NOT bind CANONICAL over TARGET - that would -# merge them onto the same inode, so chattr/writes to either would hit -# both and "restore from canonical" would become meaningless. -_reapply_bind_mount() { - local name="$1" - if mountpoint -q "$TARGET" 2>/dev/null; then - return 0 - fi - mount --bind "$TARGET" "$TARGET" - mount -o remount,ro,bind "$TARGET" - log_hook "file-guard $name: bind-mounted $TARGET read-only" -} - -fg_bind_mount() { - local name="$1" - require_root - load_target_conf "$name" - _reapply_bind_mount "$name" -} - -file_guard_main() { - local sub="$1" - shift || true - case "$sub" in - install) fg_install "$@" ;; - enforce) fg_enforce "$@" ;; - unlock) fg_unlock "$@" ;; - pacman-unlock) fg_pacman_unlock "$@" ;; - uninstall) fg_uninstall "$@" ;; - status) fg_status "$@" ;; - canonical-path) fg_canonical_path "$@" ;; - bind-mount) fg_bind_mount "$@" ;; - pacman-relock) fg_pacman_relock "$@" ;; - sync) fg_sync_canonical "$@" ;; - *) die "file-guard: unknown subcommand '$sub' (expected install|enforce|unlock|pacman-unlock|pacman-relock|sync|uninstall|status|canonical-path|bind-mount)" ;; - esac -} diff --git a/guard-lib/lib/file_guard_unlock.sh b/guard-lib/lib/file_guard_unlock.sh new file mode 100644 index 0000000..3461c31 --- /dev/null +++ b/guard-lib/lib/file_guard_unlock.sh @@ -0,0 +1,214 @@ +#!/bin/bash +# guardctl file-guard unlocking, pacman coordination and dispatch. +# Split from file_guard.sh for the shared 250-line cap; sourced by +# guardctl right after it, never executed directly. + +fg_unlock() { + local name="$1" + require_root + load_target_conf "$name" + # shellcheck disable=SC2153 # PLUGIN set by load_target_conf, not a typo + load_plugin "$PLUGIN" + echo "About to unlock file-guard '$name' ($TARGET) for editing." + read -rp "Reason for unlocking: " reason + [[ -n "$reason" ]] || die "a reason is required" + log_hook "file-guard $name: UNLOCK requested by ${SUDO_USER:-$(whoami)}: $reason" + echo "Unlocking in 45s (Ctrl-C to abort)..." + sleep 45 + # Stop the watcher before unlocking: chattr alone (no content write) + # fires PathModified, and the resulting enforce pass unconditionally + # re-locks the target even with no drift - which would silently + # re-lock this file out from under the editor. Confirmed live during + # the shutdown-schedule migration (see guard-lib project notes). + systemctl stop "guard-file@${name}.path" 2>/dev/null || true + # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo + [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" + unlock_file "$TARGET" + log_hook "file-guard $name: unlocked for editing" + + local before after + before="$(sha256sum "$TARGET" 2>/dev/null | awk '{print $1}')" + # Deliberately unquoted: $EDITOR commonly carries arguments (e.g. + # "code --wait", "emacsclient -t") that must be word-split. + ${EDITOR:-vi} "$TARGET" + after="$(sha256sum "$TARGET" 2>/dev/null | awk '{print $1}')" + + if [[ "$before" != "$after" ]]; then + if declare -f validate >/dev/null 2>&1 && ! validate "$TARGET"; then + echo "New content fails this instance's validate() check - reverting your edit; canonical unchanged." >&2 + log_hook "file-guard $name: edit REJECTED (failed validate), reverting to canonical" + [[ -e "$CANONICAL" ]] && cp --preserve=mode,ownership,timestamps "$CANONICAL" "$TARGET" + else + # Update canonical to match: without this, re-locking below + # fires the watcher, which would see the new content as + # "drift" against the stale canonical and silently revert + # this legitimate edit. + log_hook "file-guard $name: content changed, updating canonical" + unlock_file "$CANONICAL" + cp --preserve=mode,ownership,timestamps "$TARGET" "$CANONICAL" + lock_file "$CANONICAL" + fi + else + log_hook "file-guard $name: no content change" + fi + + lock_file "$TARGET" + # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo + [[ "$BIND_MOUNT" == "yes" ]] && _reapply_bind_mount "$name" + systemctl start "guard-file@${name}.path" 2>/dev/null || true + log_hook "file-guard $name: re-locked after edit" + echo "Re-locked '$name'." +} + +fg_uninstall() { + local name="$1" + shift + local keep_canonical=0 + while [[ $# -gt 0 ]]; do + case "$1" in + --keep-canonical) keep_canonical=1; shift ;; + *) die "file-guard uninstall: unknown argument '$1'" ;; + esac + done + require_root + load_target_conf "$name" + systemctl disable --now "guard-file@$name.path" 2>/dev/null || true + systemctl disable --now "guard-bind-mount@$name.service" 2>/dev/null || true + rm -rf "${GUARD_LIB_SYSTEMD_DIR:?}/guard-file@$name.path.d" + systemctl daemon-reload + # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo + [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" + unlock_file "$TARGET" + if [[ "$keep_canonical" -eq 0 ]]; then + unlock_file "$CANONICAL" + rm -f "$CANONICAL" + fi + rm -f "$(target_conf_path "$name")" + log_hook "file-guard $name: uninstalled (keep_canonical=$keep_canonical)" + echo "uninstalled file-guard '$name'" +} + +fg_status() { + local name="$1" + load_target_conf "$name" + echo "name: $name" + echo "target: $TARGET" + echo "canonical: $CANONICAL" + # shellcheck disable=SC2153 # BIND_MOUNT/PLUGIN/ALSO_WATCH set by load_target_conf, not typos + echo "bind_mount: $BIND_MOUNT" + echo "plugin: ${PLUGIN:-}" + echo "also_watch: ${ALSO_WATCH:-}" + if [[ -e "$TARGET" ]]; then + local attrs + attrs="$(lsattr "$TARGET" 2>/dev/null | awk '{print $1}')" + echo "target attrs: ${attrs:-unknown}" + else + echo "target: MISSING" + fi + local unit_state + unit_state="$(systemctl is-active "guard-file@$name.path" 2>/dev/null || true)" + echo "path unit: ${unit_state:-unknown}" +} + +fg_canonical_path() { + # Machine-readable single-value output: the canonical path for an + # instance, so consumers with bespoke unlock flows (that can't go + # through `unlock`/`enforce` directly) don't have to hardcode or + # duplicate guard-lib's canonical-path convention. + local name="$1" + load_target_conf "$name" + echo "$CANONICAL" +} + +fg_pacman_unlock() { + # Quiet, non-interactive unlock used only by the generic pacman + # PreTransaction hook - no typed reason, no editor. The pacman + # transaction itself is the sanctioned reason. + # + # Stops the path unit, not just chattr -i's the target: chattr alone + # fires PathModified, and if the watcher's enforce pass wins the race + # against pacman's own write, it silently re-locks the file before + # pacman gets to it, breaking the very transaction this hook exists + # to allow. Matches the pre-existing hosts-guard pacman hooks, which + # stop hosts-guard.path/nsswitch-guard.path/resolved-guard.path for + # the same reason. + local name="$1" + load_target_conf "$name" + systemctl stop "guard-file@${name}.path" 2>/dev/null || true + # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo + [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" + unlock_file "$TARGET" + log_hook "file-guard $name: pacman-unlock (pre-transaction)" +} + +fg_pacman_relock() { + # Counterpart to fg_pacman_unlock, used only by the generic pacman + # PostTransaction hook: re-enforce (drift-restore + chattr +i, and - + # if this instance is bind-mounted - re-establish the read-only + # bind mount, since fg_enforce does that itself now) then restart + # the path unit that pacman-unlock stopped. + local name="$1" + fg_enforce "$name" + systemctl start "guard-file@${name}.path" 2>/dev/null || true + log_hook "file-guard $name: pacman-relock (post-transaction)" +} + +fg_sync_canonical() { + # Counterpart to fg_pacman_unlock for callers that legitimately EDITED + # the target (not pacman's own hook flow, which wants drift reverted). + # Adopts the target's current content as the new canonical, instead of + # fg_enforce's drift-check-and-revert - which would otherwise silently + # undo the very edit the caller just made. Assumes the watcher was + # already stopped by a prior fg_pacman_unlock; does not stop it itself. + local name="$1" + load_target_conf "$name" + snapshot_canonical "$name" + # shellcheck disable=SC2153 # BIND_MOUNT set by load_target_conf, not a typo + [[ "$BIND_MOUNT" == "yes" ]] && collapse_bind_mount "$TARGET" + unlock_file "$TARGET" + lock_file "$TARGET" + [[ "$BIND_MOUNT" == "yes" ]] && _reapply_bind_mount "$name" + systemctl start "guard-file@${name}.path" 2>/dev/null || true + log_hook "file-guard $name: synced canonical to current content" +} + +# Self-bind-mounts TARGET over itself, then remounts that layer +# read-only. This is a mount-level lock independent of chattr: even a +# successful `chattr -i` bypass still can't write through a read-only +# mount. Deliberately does NOT bind CANONICAL over TARGET - that would +# merge them onto the same inode, so chattr/writes to either would hit +# both and "restore from canonical" would become meaningless. +_reapply_bind_mount() { + local name="$1" + if mountpoint -q "$TARGET" 2>/dev/null; then + return 0 + fi + mount --bind "$TARGET" "$TARGET" + mount -o remount,ro,bind "$TARGET" + log_hook "file-guard $name: bind-mounted $TARGET read-only" +} + +fg_bind_mount() { + local name="$1" + require_root + load_target_conf "$name" + _reapply_bind_mount "$name" +} + +file_guard_main() { + local sub="$1" + shift || true + case "$sub" in + install) fg_install "$@" ;; + enforce) fg_enforce "$@" ;; + unlock) fg_unlock "$@" ;; + pacman-unlock) fg_pacman_unlock "$@" ;; + uninstall) fg_uninstall "$@" ;; + status) fg_status "$@" ;; + canonical-path) fg_canonical_path "$@" ;; + bind-mount) fg_bind_mount "$@" ;; + pacman-relock) fg_pacman_relock "$@" ;; + sync) fg_sync_canonical "$@" ;; + *) die "file-guard: unknown subcommand '$sub' (expected install|enforce|unlock|pacman-unlock|pacman-relock|sync|uninstall|status|canonical-path|bind-mount)" ;; + esac +}