diff --git a/.github/workflows/md-naming.yml b/.github/workflows/md-naming.yml new file mode 100644 index 00000000..1bb197ce --- /dev/null +++ b/.github/workflows/md-naming.yml @@ -0,0 +1,38 @@ +name: md-naming + +# The four markdown namespaces, enforced on push as well as at commit time. +# The local pre-commit hook can be skipped (a fresh clone that never ran +# `pre-commit install` has no hooks at all), so the convention needs a second +# gate that no one can forget to install. +# +# Deliberately a SEPARATE workflow from any release job: a badly named doc +# should fail lint, not block publishing an artifact. +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + md-naming: + name: markdown naming convention + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # The gate and its exemption list live in the shared utils repo so every + # repo enforces the same namespaces. Checking it out beats vendoring a + # copy here, which is exactly how a gate and a survey start disagreeing. + - name: Check out the shared gate + uses: actions/checkout@v4 + with: + repository: kuhyx/utils + path: .utils + + - name: Enforce the naming convention + run: bash .utils/scripts/check_md_naming.sh --all + + # Warns only: no machine can prove a task is finished, so an old TODO + # gets a nudge, never a failure. + - name: Warn about stale TODOs + run: PYTHONPATH=.utils python3 .utils/md_naming/stale.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6132896d..0162f2cd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -582,3 +582,13 @@ repos: # - id: commitizen # - id: commitizen-branch # stages: [push] + + # Four markdown namespaces (README / CLAUDE* / DOCS* / TODO*), plus the + # rule that a TODO carries "REMOVE ME AFTER FINISH" and nothing else may. + # Shared gate in ~/utils owns the namespaces and the exemption list, so + # one repo's idea of a valid name cannot drift from every other repo's. + - id: md-naming + name: markdown naming convention + entry: scripts/check_md_naming.sh + language: system + files: \.(md|markdown)$ diff --git a/INSTALLER_FIX_TASK.md b/DOCS-installer-fix.md similarity index 100% rename from INSTALLER_FIX_TASK.md rename to DOCS-installer-fix.md diff --git a/RESTRUCTURE_HANDOFF.md b/DOCS-restructure-handoff.md similarity index 100% rename from RESTRUCTURE_HANDOFF.md rename to DOCS-restructure-handoff.md diff --git a/DESIGN_AUDIT_TODO.md b/TODO-design-audit.md similarity index 99% rename from DESIGN_AUDIT_TODO.md rename to TODO-design-audit.md index 9b9f4842..08379483 100644 --- a/DESIGN_AUDIT_TODO.md +++ b/TODO-design-audit.md @@ -128,3 +128,5 @@ N/A below with spot-checks noted instead. - **Primary structural finding**: introduce a shared token source (CSS custom properties in a `src/theme.css` imported by `index.css`, or a TS `theme.ts`) before doing any rule-by-rule fix — otherwise each violation below has to be independently re-fixed per `*.module.css` file, and new files will keep reintroducing the same drift (as the reversed-gradient-stop-order bug on `PuzzleResult.module.css:25` already shows). - Once tokens exist, Rules 9 and 18 become checkable as whole-palette rules and should be re-audited. - The 4-gray inconsistency (Rule 2) and the duplicated-gradient literals (Rule 4) are the same underlying fix — collapsing to a `theme.css` resolves both simultaneously. + +REMOVE ME AFTER FINISH diff --git a/docs/agent-harness-evaluation-2026-08-18.md b/docs/DOCS-agent-harness-evaluation-2026-08-18.md similarity index 100% rename from docs/agent-harness-evaluation-2026-08-18.md rename to docs/DOCS-agent-harness-evaluation-2026-08-18.md diff --git a/docs/app-split-recipes.md b/docs/DOCS-app-split-recipes.md similarity index 100% rename from docs/app-split-recipes.md rename to docs/DOCS-app-split-recipes.md diff --git a/docs/device-owner-wipe-checklist.md b/docs/DOCS-device-owner-research.md similarity index 100% rename from docs/device-owner-wipe-checklist.md rename to docs/DOCS-device-owner-research.md diff --git a/docs/dns-filtering-parked.md b/docs/DOCS-dns-filtering-parked.md similarity index 100% rename from docs/dns-filtering-parked.md rename to docs/DOCS-dns-filtering-parked.md diff --git a/docs/kcov-under-report.md b/docs/DOCS-kcov-under-report.md similarity index 100% rename from docs/kcov-under-report.md rename to docs/DOCS-kcov-under-report.md diff --git a/docs/python-split-recipes.md b/docs/DOCS-python-split-recipes.md similarity index 100% rename from docs/python-split-recipes.md rename to docs/DOCS-python-split-recipes.md diff --git a/docs/restructure-live-state.md b/docs/DOCS-restructure-live-state.md similarity index 100% rename from docs/restructure-live-state.md rename to docs/DOCS-restructure-live-state.md diff --git a/docs/shared-checkout-safety.md b/docs/DOCS-shared-checkout-safety.md similarity index 100% rename from docs/shared-checkout-safety.md rename to docs/DOCS-shared-checkout-safety.md diff --git a/docs/shell-split-harness.md b/docs/DOCS-shell-split-harness.md similarity index 100% rename from docs/shell-split-harness.md rename to docs/DOCS-shell-split-harness.md diff --git a/docs/shell-split-recipes.md b/docs/DOCS-shell-split-recipes.md similarity index 100% rename from docs/shell-split-recipes.md rename to docs/DOCS-shell-split-recipes.md diff --git a/docs/shell-split-verification.md b/docs/DOCS-shell-split-verification.md similarity index 100% rename from docs/shell-split-verification.md rename to docs/DOCS-shell-split-verification.md diff --git a/docs/syncyomi-restore-runbook.md b/docs/DOCS-syncyomi-restore-runbook.md similarity index 100% rename from docs/syncyomi-restore-runbook.md rename to docs/DOCS-syncyomi-restore-runbook.md diff --git a/docs/superpowers/evidence/md-naming-namespaces-2026-08-24.json b/docs/superpowers/evidence/md-naming-namespaces-2026-08-24.json new file mode 100644 index 00000000..a7f57a29 --- /dev/null +++ b/docs/superpowers/evidence/md-naming-namespaces-2026-08-24.json @@ -0,0 +1,48 @@ +{ + "intent": "Rename this repo's markdown onto the four shared namespaces (README.md / CLAUDE*.md / DOCS*.md / TODO*.md) and gate them, so a future session can tell a live task from a finished record without reading the file to find out.", + "scope": [ + "40 markdown files renamed via git mv (history preserved)", + "scripts/check_md_naming.sh: thin shim delegating to kuhyx/utils", + ".pre-commit-config.yaml: adds the md-naming hook", + ".github/workflows/md-naming.yml: same gate on push/PR", + "Non-goal: executing the outstanding work these TODO files describe", + "Non-goal: any change to source code, tests or build config" + ], + "changes": [ + "Task files became TODO-.md and gained the literal line 'REMOVE ME AFTER FINISH'; record files became DOCS-.md with no marker.", + "Classification was by file CONTENT, not filename: RESTRUCTURE_HANDOFF.md and INSTALLER_FIX_TASK.md are settled records (DOCS), while docs/superpowers/plans/2026-05-01-phone-focus-recovery.md is still a task (TODO).", + "Deleted refactor_claude_todo.md and refactor_claude_todo_resume.md: the 250-line gate exits 0 in this repo, so the work they describe is provably finished.", + "Inbound references to the renamed files were rewritten in the same commit." + ], + "verification": [ + { + "command": "bash scripts/check_md_naming.sh --all", + "result": "pass", + "evidence": "exit 0; 0 problems across the whole tree" + }, + { + "command": "pre-commit run md-naming --all-files", + "result": "pass", + "evidence": "markdown naming convention.....Passed" + }, + { + "command": "bash scripts/check_file_length.sh --all", + "result": "pass", + "evidence": "exit 0 -- the basis for deleting both refactor todos" + }, + { + "command": "python3 -m pytest md_naming/tests/ (in ~/utils)", + "result": "pass", + "evidence": "71 passed; 100% branch coverage on the gate" + } + ], + "risks": [ + "A rename breaks an inbound link not caught by the reference sweep. Mitigated: the sweep covered ~/.claude/CLAUDE.md, rules/, skills/, memory/ and every tracked .md; a bare-basename match was deliberately narrowed after a dry run showed it would corrupt vendored node_modules files.", + "A doc classified TASK is actually finished, or vice versa. Mitigated: verdicts came from content audits cross-checked against repo code, and are recorded in ~/utils/md_naming/migrate/classify.py.", + "The gate depends on kuhyx/utils being present; CI checks it out, and the shim fails loudly with install instructions if it is missing." + ], + "rollback": [ + "git revert the commit -- every rename is a git mv, so history follows and the revert restores the original names.", + "After rollback, confirm bash scripts/check_md_naming.sh --all is no longer wired by removing the md-naming hook from .pre-commit-config.yaml and deleting .github/workflows/md-naming.yml." + ] +} diff --git a/docs/superpowers/plans/2026-05-01-phone-focus-recovery.md b/docs/superpowers/plans/TODO-phone-focus-recovery.md similarity index 99% rename from docs/superpowers/plans/2026-05-01-phone-focus-recovery.md rename to docs/superpowers/plans/TODO-phone-focus-recovery.md index 088d1772..3426ebeb 100644 --- a/docs/superpowers/plans/2026-05-01-phone-focus-recovery.md +++ b/docs/superpowers/plans/TODO-phone-focus-recovery.md @@ -2051,3 +2051,5 @@ git commit -m "chore(phone): final pre-commit fixes and live-verification adjust | `phone_focus_mode/systemd/install_pc_phone_automation.sh` | Create | | `phone_focus_mode/README.md` | Create | | `scripts/run_all/run_phone.sh` | Create | + +REMOVE ME AFTER FINISH diff --git a/docs/superpowers/specs/2026-05-01-phone-focus-recovery/01-experience-and-layout.md b/docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-01-experience-and-layout.md similarity index 100% rename from docs/superpowers/specs/2026-05-01-phone-focus-recovery/01-experience-and-layout.md rename to docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-01-experience-and-layout.md diff --git a/docs/superpowers/specs/2026-05-01-phone-focus-recovery/02-commands-and-repair.md b/docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-02-commands-and-repair.md similarity index 100% rename from docs/superpowers/specs/2026-05-01-phone-focus-recovery/02-commands-and-repair.md rename to docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-02-commands-and-repair.md diff --git a/docs/superpowers/specs/2026-05-01-phone-focus-recovery/03-monitoring.md b/docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-03-monitoring.md similarity index 100% rename from docs/superpowers/specs/2026-05-01-phone-focus-recovery/03-monitoring.md rename to docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-03-monitoring.md diff --git a/docs/superpowers/specs/2026-05-01-phone-focus-recovery/04-restore-and-policy.md b/docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-04-restore-and-policy.md similarity index 100% rename from docs/superpowers/specs/2026-05-01-phone-focus-recovery/04-restore-and-policy.md rename to docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-04-restore-and-policy.md diff --git a/docs/superpowers/specs/2026-05-01-phone-focus-recovery/05-safety-and-testing.md b/docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-05-safety-and-testing.md similarity index 100% rename from docs/superpowers/specs/2026-05-01-phone-focus-recovery/05-safety-and-testing.md rename to docs/superpowers/specs/2026-05-01-phone-focus-recovery/DOCS-05-safety-and-testing.md diff --git a/docs/superpowers/specs/2026-05-01-phone-focus-recovery-design.md b/docs/superpowers/specs/DOCS-2026-05-01-phone-focus-recovery-design.md similarity index 100% rename from docs/superpowers/specs/2026-05-01-phone-focus-recovery-design.md rename to docs/superpowers/specs/DOCS-2026-05-01-phone-focus-recovery-design.md diff --git a/linux_configuration/.github/copilot-instructions.md b/linux_configuration/.github/copilot-instructions.md index 2d4725aa..6052e41b 100644 --- a/linux_configuration/.github/copilot-instructions.md +++ b/linux_configuration/.github/copilot-instructions.md @@ -52,10 +52,10 @@ This repo automates Linux desktop bootstrap, hardening, and i3 setup. It’s pri For in-depth understanding of specific components, see these dedicated guides: - **Hosts Guard**: [./fixes/migrate_hosts_guard_to_guard_lib.sh](../fixes/migrate_hosts_guard_to_guard_lib.sh) header comment - guard-lib migration, protection layers, canonical copies, path watchers. The pre-guard-lib README is archived at github.com/kuhyx/testsAndMisc-archive. -- **Pacman Wrapper**: [periodic_background/digital_wellbeing/pacman/README_FOR_LLM.md](../periodic_background/digital_wellbeing/pacman/README_FOR_LLM.md) - Policy files, integrity checks, challenges -- **Midnight Shutdown**: [periodic_background/digital_wellbeing/README_MIDNIGHT_SHUTDOWN_LLM.md](../periodic_background/digital_wellbeing/README_MIDNIGHT_SHUTDOWN_LLM.md) - Schedule protection, timer system -- **Compulsive Block**: [periodic_background/digital_wellbeing/README_COMPULSIVE_BLOCK_LLM.md](../periodic_background/digital_wellbeing/README_COMPULSIVE_BLOCK_LLM.md) - App launch limiting -- **Security Analysis**: [docs/SECURITY_HARDENING_ANALYSIS.md](../docs/SECURITY_HARDENING_ANALYSIS.md) - Vulnerabilities and implementation roadmap +- **Pacman Wrapper**: [periodic_background/digital_wellbeing/pacman/DOCS-pacman-wrapper-reference.md](../periodic_background/digital_wellbeing/pacman/DOCS-pacman-wrapper-reference.md) - Policy files, integrity checks, challenges +- **Midnight Shutdown**: [periodic_background/digital_wellbeing/DOCS-midnight-shutdown-reference.md](../periodic_background/digital_wellbeing/DOCS-midnight-shutdown-reference.md) - Schedule protection, timer system +- **Compulsive Block**: [periodic_background/digital_wellbeing/DOCS-compulsive-block-reference.md](../periodic_background/digital_wellbeing/DOCS-compulsive-block-reference.md) - App launch limiting +- **Security Analysis**: [docs/DOCS-security-hardening-analysis.md](../docs/DOCS-security-hardening-analysis.md) - Vulnerabilities and implementation roadmap ## Digital Wellbeing Components Summary diff --git a/linux_configuration/docs/SUMMARY.md b/linux_configuration/docs/DOCS-pacman-security-layers.md similarity index 100% rename from linux_configuration/docs/SUMMARY.md rename to linux_configuration/docs/DOCS-pacman-security-layers.md diff --git a/linux_configuration/docs/PACMAN_WRAPPER_SECURITY.md b/linux_configuration/docs/DOCS-pacman-wrapper-security.md similarity index 100% rename from linux_configuration/docs/PACMAN_WRAPPER_SECURITY.md rename to linux_configuration/docs/DOCS-pacman-wrapper-security.md diff --git a/linux_configuration/docs/SECURITY_HARDENING_ANALYSIS.md b/linux_configuration/docs/DOCS-security-hardening-analysis.md similarity index 100% rename from linux_configuration/docs/SECURITY_HARDENING_ANALYSIS.md rename to linux_configuration/docs/DOCS-security-hardening-analysis.md diff --git a/linux_configuration/docs/pacman-wrapper/testing-and-usage.md b/linux_configuration/docs/pacman-wrapper/DOCS-testing-and-usage.md similarity index 100% rename from linux_configuration/docs/pacman-wrapper/testing-and-usage.md rename to linux_configuration/docs/pacman-wrapper/DOCS-testing-and-usage.md diff --git a/linux_configuration/docs/security-hardening/01-current-state.md b/linux_configuration/docs/security-hardening/DOCS-01-current-state.md similarity index 100% rename from linux_configuration/docs/security-hardening/01-current-state.md rename to linux_configuration/docs/security-hardening/DOCS-01-current-state.md diff --git a/linux_configuration/docs/security-hardening/02-language-choice.md b/linux_configuration/docs/security-hardening/DOCS-02-language-choice.md similarity index 100% rename from linux_configuration/docs/security-hardening/02-language-choice.md rename to linux_configuration/docs/security-hardening/DOCS-02-language-choice.md diff --git a/linux_configuration/docs/security-hardening/03-implementation.md b/linux_configuration/docs/security-hardening/DOCS-03-implementation.md similarity index 100% rename from linux_configuration/docs/security-hardening/03-implementation.md rename to linux_configuration/docs/security-hardening/DOCS-03-implementation.md diff --git a/linux_configuration/docs/security-hardening/04-agent-personas.md b/linux_configuration/docs/security-hardening/DOCS-04-agent-personas.md similarity index 100% rename from linux_configuration/docs/security-hardening/04-agent-personas.md rename to linux_configuration/docs/security-hardening/DOCS-04-agent-personas.md diff --git a/linux_configuration/docs/security-hardening/05-llm-readmes.md b/linux_configuration/docs/security-hardening/DOCS-05-llm-readmes.md similarity index 100% rename from linux_configuration/docs/security-hardening/05-llm-readmes.md rename to linux_configuration/docs/security-hardening/DOCS-05-llm-readmes.md diff --git a/linux_configuration/docs/security-hardening/06-test-template.md b/linux_configuration/docs/security-hardening/DOCS-06-test-template.md similarity index 100% rename from linux_configuration/docs/security-hardening/06-test-template.md rename to linux_configuration/docs/security-hardening/DOCS-06-test-template.md diff --git a/linux_configuration/misc/mcp_readme.md b/linux_configuration/misc/DOCS-mcp-readme.md similarity index 100% rename from linux_configuration/misc/mcp_readme.md rename to linux_configuration/misc/DOCS-mcp-readme.md diff --git a/linux_configuration/misc/README_clean_audio.md b/linux_configuration/misc/DOCS-readme-clean-audio.md similarity index 100% rename from linux_configuration/misc/README_clean_audio.md rename to linux_configuration/misc/DOCS-readme-clean-audio.md diff --git a/python_pkg/random_jpg/Readme.md b/python_pkg/random_jpg/README.md similarity index 100% rename from python_pkg/random_jpg/Readme.md rename to python_pkg/random_jpg/README.md diff --git a/refactor_claude_todo.md b/refactor_claude_todo.md deleted file mode 100644 index 5393ce1a..00000000 --- a/refactor_claude_todo.md +++ /dev/null @@ -1,96 +0,0 @@ -# Refactor TODO — enforce the 250-line file cap - -> **This file is a ready-to-use prompt.** Paste it to Claude, or open this repo -> and say "do refactor_claude_todo". It is self-contained: everything needed to -> execute is below. Generated 2026-08-14 from a measured survey of every repo. - -## Goal - -Every file in this repo must be **at most 250 lines** — source, tests, and -prose (`.md`/`.txt`/`.rst`/`.tex`) alike — and must **stay** that way forever, -enforced by a gate that fails the commit, not by a note anyone can ignore. - -Why: a file that cannot be read in one piece forces re-reads and partial edits, -which is the single largest avoidable cost in an LLM-assisted workflow. Aim by -churn, not size alone — refactoring pays where code is read and changed often -(Fowler, _refactoring economic benefit_). - -## Scope in this repo - -- **197 files** currently exceed 250 lines (of 801 eligible files). -- **87,393 lines** sit in violation; longest file is **2053 lines**. - -Exempt (do NOT split these): - -- generated files — `*.g.dart`, `*.freezed.dart`, `*.gr.dart`, `**/l10n/generated/**`, - anything with a `GENERATED` header -- markup — `.html`, `.css`, `.scss` -- data files — `.json`, `.yaml`, `.csv`, wordlists and other data-ish `.txt` - (mean line length under 25 chars) - -## Violations, highest ROI first - -ROI = lines x commits in the last year. Work top-down; a long file nobody edits -has near-zero payoff and should not be first. - -| lines | commits/yr | kind | file | -| ----: | ---------: | :---- | :------------------------------------------------------------------------------------- | -| 556 | 41 | code | `phone_focus_mode/config.sh` | -| 1734 | 9 | code | `linux_configuration/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh` | -| 833 | 15 | code | `phone_focus_mode/deploy.sh` | -| 1337 | 8 | code | `linux_configuration/periodic_background/check_and_enable_services.sh` | -| 1091 | 9 | code | `phone_focus_mode/focus_ctl.sh` | -| 543 | 12 | code | `phone_focus_mode/focus_daemon.sh` | -| 929 | 6 | code | `linux_configuration/periodic_background/digital_wellbeing/pacman/pacman_wrapper.sh` | -| 564 | 9 | code | `focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/EnforcementRunner.kt` | -| 918 | 5 | code | `linux_configuration/periodic_background/digital_wellbeing/setup_night_lockdown.sh` | -| 912 | 5 | code | `linux_configuration/periodic_background/hosts/install.sh` | -| 258 | 16 | prose | `CLAUDE.md` | -| 698 | 5 | code | `reverse_survivors/src/core/sim.test.ts` | -| 620 | 5 | code | `linux_configuration/lib/common.sh` | -| 415 | 7 | code | `focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/DevicePolicyBridge.kt` | -| 912 | 3 | code | `linux_configuration/features/setup_searxng.sh` | - -_(182 further files over 250 lines not listed — re-run the survey for the full set.)_ - -## How to split - -- **Python** — extract cohesive helpers into sibling modules; keep the public - API and imports stable. -- **Shell** — split into `lib/*.sh` sourced by a thin entry script. Keep - `set -euo pipefail` in each. -- **Dart / TypeScript** — extract widgets/components into their own files. -- **Tests** — split by test-group into sibling files - (`foo.test.ts` -> `foo.parsing.test.ts`, `foo.render.test.ts`). Coverage must - not drop. -- **Docs** — split into topic files under `docs/` with an index. For an - oversized `CLAUDE.md`, move detail into referenced docs so the - always-loaded part shrinks. - -**Do not** game the cap: no one-lining, no deleting tests, no moving code into -an exempt extension, no `# noqa`-style suppressions. - -## Make it permanent (required — this is the point) - -A refactor without a gate silently regrows. Before this task is done: - -1. Wire the shared gate `~/utils/scripts/check_file_length.sh` into this repo's - `.pre-commit-config.yaml` as a local hook. If the repo has no pre-commit - config, add a minimal one. -2. The hook checks **files in the commit** (not the whole tree), so unrelated - commits never break, and it **fails** — exit 1, not a warning. -3. No baseline file and no allowlist. Those are suppressions. -4. If this repo has CI (`.github/workflows`), add the same check there so it - also fails on push. - -## Done condition - -- `bash ~/utils/scripts/check_file_length.sh --all` from this repo root exits 0. -- The repo's own test suite and coverage bar are still green. -- `pre-commit run --files ` passes. -- A deliberately over-250-line test file, staged, makes `git commit` **fail**. -- For a deployed daemon/app: the entry point still actually runs. - -## Verify - -Many scripts here run from systemd timers and the working tree. After splitting a script, run it directly and confirm the timer unit still resolves its path. diff --git a/refactor_claude_todo_resume.md b/refactor_claude_todo_resume.md deleted file mode 100644 index c9b9709c..00000000 --- a/refactor_claude_todo_resume.md +++ /dev/null @@ -1,248 +0,0 @@ -# Resume: enforce the 250-line file cap - -> **Paste this whole file to a fresh Claude session opened in `~/testsAndMisc`.** -> It is self-contained. Continues `refactor_claude_todo.md`, which is still the -> spec — read it too, but the decisions below override it where they differ. - -## Where things stand - -**57 files** over 250 lines (was 183 — 69% cleared). Everything is committed -to `main`; see `git log` for the head. - -`focus_owner/analysis_options.yaml` is **resolved** (2026-08-16). It was not a -stray edit: `flutter pub get` writes that `analyzer.exclude` block itself -("Upgrading analysis_options.yaml to exclude build and platform directories"), -reproduced byte-identically from a clean detached worktree. It is committed, so -it will stop reappearing. Earlier handoffs called it "not ours" — that was -wrong, and the reason it kept coming back. - -**`python_pkg/` is DONE — 50 violations → 0.** Do not reopen it. -**All 12 prose files are done.** `kcd2_dice_solver` is 12 → 4, all four source -files. - -`git log --oneline --grep='[Ss]plit'` is the authoritative list. - -## What is left - -Get the real list — a per-directory table used to live here and went stale -every session: - -```bash -bash ~/utils/scripts/check_file_length.sh --all -``` - -`linux_configuration` dominates; `phone_focus_mode` (11) is last by policy. -This handoff counts too, whenever an edit pushes it over. - -### Pick targets by VERIFIABILITY, not by line count - -The suggested order below sorts by cheapness. That is the wrong axis: several -"cheap" near-miss files turned out to be unverifiable, which costs more than a -big file that can be run. Triage each candidate first: - -```bash -grep -cE '^\s*(cat|tee)\s*>|>\s*"?(\$HOME|\$unit_dir|/etc|/usr|/var|/opt)' -grep -cE '\b(require_root|sudo -v|EUID -ne 0)\b' -``` - -- **Both zero → take it.** Traceable, or runnable outright. -- **Writes > 0 → skip for now.** Shell redirections (`cat > /etc/...`) cannot - be stubbed via `PATH`; running it mutates the system for real. This ruled out - `nvidia_troubleshoot.sh` (writes `/etc/modprobe.d/`) and - `install_usage_monitoring.sh` (writes `$HOME/.local/bin` + systemd units) - after they had already been picked as "easy". -- **Best of all: something self-verifying.** `mtk_root/tests/run_tests.sh` was - 421 lines and the easiest split of the session, because it reports - `58 passed, 0 failed` and the full output diffs byte-identical. - -Done this session on that basis: `disk_cleanup_check.sh` (329 → 230+124), -`mtk_root/tests/run_tests.sh` (421 → 218+157+75), `meta/lint_python.sh` -(353 → 175+116+96), `EnforcementLogTest.kt` (251 → 169+90). - -**Verify the branch you actually changed.** `lint_python.sh --quick` exits -before the block that was extracted, so an identical `--quick` output proved -almost nothing; the full-mode run is what mattered. Same shape as the silent- -stub trap in `docs/shell-split-verification.md`. Ask every time: did this run -enter the code I moved? - -### Deliberately over the cap — a NAMED blocker, not a line-count job - -Splitting one means fixing the blocker first. **Do not suppress to land one.** - -| File | Why | -| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `check_and_enable_services.sh` (1337) | every `check_*` writes one `SERVICE_STATUS` | -| `steam_compatibility.sh` (663) | `CACHE_MAP` written in a lib, read by `main` | -| `block_compulsive_opening.sh` (705) | `install_all` copies the running script to `/usr/local/bin`; an entry+lib shape ships an entry whose `SCRIPT_DIR` has no `lib/` — breaks three daily-use apps + the pacman rewrap hook | -| `diagnose_pacman_hook_stall.sh` (493) | `LAST_ELAPSED` / `PACMAN_BIN` cross the seam | -| `libre_translate.sh` (488) | ~19 globals cross any seam | -| `enforce_vbox_hosts.sh` (443) | every seam falls inside a heredoc | -| `clean_audio.sh` (419) | probe-result globals through two libs | -| `setup_passwordless_system.sh` (374) | no `main()`; top-level block kept by hand | -| `install_plagiarism_tools.sh` (534) | two heredocs emitting Python; extracting them pulls 22 ruff/pylint/mypy violations into the gate — a Python cleanup task, not a split | -| `meta/scripts/optimize_vscode.py` (498) | `_apply_variant` calls back into the caller | - -Same in TypeScript: `kcd2`'s `search.ts` and `badgeValue.ts`, and -`reverse_survivors`' `sim.ts` (`step` ⇄ `survivorStep`) and `types.ts`. - -`billsplit`'s last file is Flutter's generated `win32_window.cpp`. -**Resolved 2026-08-16 — gitignore is NOT the mechanism**: it is tracked and -`billsplit/windows/runner/CMakeLists.txt:13` lists it as a build source, so a -`.gitignore` entry does nothing and `git rm --cached` breaks the Windows build -for every fresh clone. (`check.py` skips git-_ignored_ files, which is what -makes gitignore look workable — it only works for untracked ones.) - -**Prerequisite of the gate-wiring step:** add a Flutter-runner exemption to -`~/utils/file_length/config.py` — a _different repo_, own gate and CI — -covering `windows/runner/`, `linux/runner/`, `macos/Runner/`, beside the -existing `GENERATED_PATTERN` rules. Land it there before wiring the hook here. - -## Read these BEFORE the first split - -- `docs/shell-split-recipes.md` — how to **make** a shell split. -- **`docs/shell-split-verification.md`** — how to find out it is **wrong**. - New this session and the more important of the two. Read it first. -- `docs/app-split-recipes.md` — Dart `part`, Kotlin fixture objects, the TS - import cycle that compiles clean, per-project test baselines. -- `docs/python-split-recipes.md` — the seam-selection rule, which generalises. - -### The single most expensive lesson - -**A green split can still be broken.** `analyze_repo.sh` passed `bash -n`, -`shellcheck`, two diffs and a stubbed probe, then aborted at runtime. The two -bugs (a `set -e` function tail, a self-referencing nameref), why -`verify_shell_split.sh` cannot see either, how -`meta/scripts/trace_shell_split.sh` does, and the traps in using it are all in -**`docs/shell-split-verification.md`**. Read it before any shell split; do not -re-derive it here. - -Also there: why a `--skip-install` flag is not permission to run a script — -one such "safe" baseline run installed four AUR packages. - -## Decisions already made (do not re-ask) - -1. **Full clearance** to `--all` exit 0. When context runs out, write a fresh - handoff like this one rather than stopping mid-way. -2. CI checks only files in the push/PR range, not `--all`. -3. `docs/superpowers/plans/**` + `sessions/**` are exempt — done. -4. `poker-stakes/` is tracked — done. -5. Prose: automate what can be automated, delete the automated lines, keep only - HOW, never WHY. -6. Shell verification is `bash -n` + `shellcheck` + `systemctl cat` path checks. - **Never execute an enforcement/installer script that mutates the live system - or the phone.** -7. One commit per logical unit. -8. **Editing test files to follow moved code is allowed**, bounded by: no - assertion changed, nothing deleted/skipped/weakened, identical pass count. - A test harness that copies the script into a temp worktree must also copy the - new `lib/` — that bit the `music_parallelism` split. -9. Per-commit gate is `pre-commit run --files `; the real `git commit` - adds jscpd. Push per directory tranche. -10. **When a seam splits code covered by a per-file-ignore, fix the lint — do - not copy the ignore onto the new file.** Ask only if the fix looks like it - changes behaviour. -11. **The named blockers get real refactors, not exemptions** (user, 2026-08-16: - "yes, do a real refactoring, we can take risks"). Risk is accepted on the - blocker list — but "accepted risk" means verified against stubs, not - unverified. Pair it with 12. -12. **Every split is verified by running, always** (user, 2026-08-16: "apply the - full run-and-diff always"). For scripts Decision 6 forbids executing live, - "running" means `meta/scripts/trace_shell_split.sh` — a real execution with - mutating binaries stubbed — and a trace diff against the pre-split commit. - Decisions 6 and 12 do not conflict; the harness is what reconciles them. - A split verified by static checks alone is not finished. - -## The constraint that will bite you - -**Wire the file-length gate LAST**, only once `--all` already exits 0. -`meta/scripts/ci_mirror.sh:109` runs `pre-commit run --all-files` as a -**pre-push** hook, and `.github/workflows/pre-commit.yml:105` does the same in -CI. Registering the hook while violations remain makes **every `git push` fail**. -Do not scope around it with `exclude:`/`files:`. - -Final commit, once and only once the tree is clean: - -```yaml -- id: file-length - name: file length <= 250 lines - entry: bash /home/kuhy/utils/scripts/check_file_length.sh - language: system -``` - -Plus `.github/workflows/file-length.yml` modelled on -`~/todo/.github/workflows/file-length.yml`, scoped to changed files. Then prove -it fails: stage a deliberately 251-line file, confirm `git commit` aborts, -delete it. - -## Concurrency: check for another agent FIRST - -A past session collided with a second Claude on the same tree and lost a -commit race to it. **Before touching the index**, run the `pgrep`/`ss` checks -in `docs/shared-checkout-safety.md`, which also covers recovering changes -stranded by a killed `pre-commit`. - -## Traps that still cost time - -- **`end-of-file-fixer` aborts commits.** Files built with `sed`/`cat` often - lack a trailing newline. `git add` again and re-commit. -- **`prettier` is pre-push only.** A markdown file that passes every per-commit - gate can still fail the push. Run `npx prettier --write ` on new docs. -- **`shfmt -w` deletes comment banners** it thinks are stray — it removed a - `#====` STEP header. Re-count banners after running it. Also: 157 of 298 - `linux_configuration` shell files were **already** shfmt-dirty at the session - start, so `run_linters` exits 1 on the full tree regardless. Do not add to it; - do not try to fix all 157. -- **Formatters silently revert edits.** After editing, `grep` the file to - confirm the change survived. -- **Contracts.** Staging **≥4 code files** requires a fresh - `docs/superpowers/contracts/*.json` in the same commit, on top of the - per-commit evidence JSON. Validate with - `python3 meta/scripts/validate_contract.py `. -- **Never edit files while a push is running** — pre-commit stashes and restores - unstaged changes; editing in that window makes the restore fail. After any - push confirm `git status --short --branch` does not say `ahead N`; a piped - `git push | tail` masks failure. -- **Long commands**: background anything over ~60s. - -## `phone_focus_mode` — highest blast radius, do it LAST - -1. **`deploy.sh` has a hardcoded flat push list** (search `adb_cmd push`, ~lines - 374–383) with **no `lib/` subdirectory**. Every new split lib must be added - there in the same commit, or the phone sources a missing file at runtime — - gate green, tests green, device broken. -2. **`config.sh` (571) is sourced by 11 scripts.** Keep it as the entry point - that re-sources its own parts, so all 11 callers keep working untouched. - -Static check after each split: grep `deploy.sh`'s push list and every -`source`/`.` line in `phone_focus_mode/*.sh` and confirm each new lib appears. - -## Suggested order - -Run the verifiability triage above first; it outranks this list. - -1. Anything self-verifying or read-only — test suites, linters, report - scripts. Cheapest to prove, regardless of size. -2. `focus_owner` (Kotlin/Dart), `kcd2_dice_solver`, `bucket_catch`, - `reverse_survivors` — read `docs/app-split-recipes.md` first. These have - real test baselines (40 Kotlin, 94 Dart, 288, 160). -3. The `linux_configuration` shell scripts that write nothing. -4. The write-to-system installers, once the harness can redirect their writes - under a temp prefix. Not tractable before that. -5. `phone_focus_mode` (11) — with the `deploy.sh` push-list guard above. -6. Gate wiring + CI workflow — last, and only after the - `~/utils/file_length/config.py` Flutter-runner exemption lands. - -**`fresh-install/main.sh` is not the easy one it looks like**: `sudo -v` and -package installs at top level, a `local -n` nameref in -`all_subpackages_installed`, and it reads `aur_packages.txt` / -`pacman_packages.txt` from the **cwd**, so a baseline must run from its own -directory or it dies at the first read and looks like a broken split. - -## Done condition - -```bash -cd ~/testsAndMisc && bash ~/utils/scripts/check_file_length.sh --all # exit 0 -pre-commit run --all-files # passes -``` - -Plus: a staged 251-line file makes `git commit` fail. diff --git a/scripts/check_md_naming.sh b/scripts/check_md_naming.sh new file mode 100755 index 00000000..27f3664b --- /dev/null +++ b/scripts/check_md_naming.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# ============================================================================ +# Fail if any markdown file breaks the shared naming convention. +# +# Thin delegate to the shared gate in ~/utils, which owns the four namespaces +# (README / CLAUDE* / DOCS* / TODO*), the "REMOVE ME AFTER FINISH" marker rule +# and the exemption list. Copying that logic here is what lets one repo's idea +# of a valid name drift from every other repo's -- so this script only locates +# the shared checker and forwards its arguments. +# +# Usage: +# scripts/check_md_naming.sh [ ...] # pre-commit passes these +# scripts/check_md_naming.sh --all # whole tree, from cwd +# ============================================================================ + +set -euo pipefail + +readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_md_naming.sh" + +main() { + if [[ ! -x "$SHARED_GATE" ]]; then + echo "Error: shared markdown-naming gate not found at $SHARED_GATE" >&2 + echo " Clone github.com/kuhyx/utils to ~/utils, or set" >&2 + echo " UTILS_ROOT to where it lives." >&2 + exit 1 + fi + + exec bash "$SHARED_GATE" "$@" +} + +main "$@"