mirror of
https://github.com/kuhyx/screen-locker.git
synced 2026-11-10 16:48:53 +01:00
Re-point paths for the ~ reorganisation (home-tidy)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AwtowrowDXx6ccmWVPkCaF
This commit is contained in:
parent
0fb2da9c86
commit
e98884b200
@ -277,7 +277,7 @@ repos:
|
||||
|
||||
# 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
|
||||
# Shared gate in ~/src/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
|
||||
|
||||
@ -71,7 +71,7 @@ an exempt extension, no `# noqa`-style suppressions.
|
||||
|
||||
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
|
||||
1. Wire the shared gate `~/src/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
|
||||
@ -82,7 +82,7 @@ A refactor without a gate silently regrows. Before this task is done:
|
||||
|
||||
## Done condition
|
||||
|
||||
- `bash ~/utils/scripts/check_file_length.sh --all` from this repo root exits 0.
|
||||
- `bash ~/src/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 <changed files>` passes.
|
||||
- A deliberately over-250-line test file, staged, makes `git commit` **fail**.
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
## Goal
|
||||
|
||||
`bash ~/utils/scripts/check_file_length.sh --all` from the repo root exits 0.
|
||||
`bash ~/src/utils/scripts/check_file_length.sh --all` from the repo root exits 0.
|
||||
|
||||
Everything else in `refactor_claude_todo.md` still applies (no gaming the cap,
|
||||
no deleting tests, no suppressions). This file only adds what the previous
|
||||
@ -16,7 +16,7 @@ session learned the hard way.
|
||||
## Start here (do this first, it costs one command)
|
||||
|
||||
```bash
|
||||
cd ~/screen-locker/stronglift_replacement/workout_app
|
||||
cd ~/src/screen-locker/stronglift_replacement/workout_app
|
||||
env -u GIT_DIR flutter test 2>&1 | tail -1 # MUST print: +402: All tests passed!
|
||||
```
|
||||
|
||||
@ -145,10 +145,10 @@ extension in a part still reaches `_privateField`.
|
||||
## Verify (all of it, every batch)
|
||||
|
||||
```bash
|
||||
cd ~/screen-locker/stronglift_replacement/workout_app
|
||||
cd ~/src/screen-locker/stronglift_replacement/workout_app
|
||||
env -u GIT_DIR dart analyze lib/ # must be "No issues found!"
|
||||
env -u GIT_DIR flutter test 2>&1 | tail -1 # must be +402
|
||||
cd ~/screen-locker && pre-commit run # includes the 100% Flutter coverage gate
|
||||
cd ~/src/screen-locker && pre-commit run # includes the 100% Flutter coverage gate
|
||||
```
|
||||
|
||||
`dart analyze` is a **no-op on test files** — `analysis_options.yaml` excludes
|
||||
@ -157,7 +157,7 @@ signal.
|
||||
|
||||
## Done condition
|
||||
|
||||
- `bash ~/utils/scripts/check_file_length.sh --all` exits 0.
|
||||
- `bash ~/src/utils/scripts/check_file_length.sh --all` exits 0.
|
||||
- 402 Dart tests pass; `flutter` coverage still 100%.
|
||||
- `pre-commit run --all-files` passes.
|
||||
- The app still runs on the phone: use the `phone-deploy` skill
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
# Task: replace blind coordinate tapping with element-targeted Android UI automation
|
||||
|
||||
> **STATUS 2026-08-10: BUILT.** The tool now exists at
|
||||
> `~/testsAndMisc/python_pkg/android_ui/` (see its README). It covers `dump` /
|
||||
> `~/src/testsAndMisc/python_pkg/android_ui/` (see its README). It covers `dump` /
|
||||
> `find` / `tap` / `type` / `wait` / `focus` with verified typing, ambiguity as
|
||||
> an error, keyboard detection, and partial-tree retries — all exercised
|
||||
> against the physical Pixel 6a. What remains from the spec below is the
|
||||
> optional MCP wrapper, `scroll_to()`, and rolling it out to `~/todo` and
|
||||
> `~/dufs-cloud/app`. Everything after this line is the original brief, kept
|
||||
> optional MCP wrapper, `scroll_to()`, and rolling it out to `~/src/todo` and
|
||||
> `~/src/dufs-cloud/app`. Everything after this line is the original brief, kept
|
||||
> because it records WHY each guarantee exists.
|
||||
|
||||
## what
|
||||
@ -51,7 +51,7 @@ nodes by class and gave exact centers, and the retry worked first time.
|
||||
|
||||
New shared tool, not a per-repo copy. Two options, pick one:
|
||||
|
||||
- `~/testsAndMisc/python_pkg/android_ui/` — a CLI (`android-ui find "Connect
|
||||
- `~/src/testsAndMisc/python_pkg/android_ui/` — a CLI (`android-ui find "Connect
|
||||
Firebase"`, `android-ui tap "Connect Firebase"`, `android-ui dump`), matching
|
||||
how `app_icons` is already shared across repos.
|
||||
- An MCP server exposing the same as tools, which is what makes it available to
|
||||
@ -59,9 +59,9 @@ New shared tool, not a per-repo copy. Two options, pick one:
|
||||
asked for "some tool ... (mcp?) which also translates to UI".
|
||||
|
||||
Consumers (every repo with an Android surface):
|
||||
- `~/screen-locker/stronglift_replacement/workout_app`
|
||||
- `~/todo`
|
||||
- `~/dufs-cloud/app`
|
||||
- `~/src/screen-locker/stronglift_replacement/workout_app`
|
||||
- `~/src/todo`
|
||||
- `~/src/dufs-cloud/app`
|
||||
- any future Flutter app (this should be part of the app scaffold)
|
||||
|
||||
## must
|
||||
@ -108,7 +108,7 @@ emulator and not a debug-only Flutter driver session.
|
||||
|
||||
- This session's working recovery: `uiautomator dump` + the bounds-parsing
|
||||
python in the screen-locker scratchpad (`ui.xml`, `ui2.xml`).
|
||||
- `~/screen-locker/CLAUDE.md` — "You are NOT done until you install the new
|
||||
- `~/src/screen-locker/CLAUDE.md` — "You are NOT done until you install the new
|
||||
version on the phone itself", which is why agent-driven UI is on the critical
|
||||
path for every task in this repo.
|
||||
- Note `uiautomator dump` returns an empty/partial tree while an animation is
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
## Shared gatelock library
|
||||
|
||||
`~/utils/gatelock` is **not** its own git repo — `git -C ~/utils/gatelock
|
||||
rev-parse --show-toplevel` resolves to `/home/kuhy/utils`, so it's a
|
||||
subdirectory of the `~/utils` monorepo. Per audit scope, gatelock itself was
|
||||
`~/src/utils/gatelock` is **not** its own git repo — `git -C ~/src/utils/gatelock
|
||||
rev-parse --show-toplevel` resolves to `/home/kuhy/src/utils`, so it's a
|
||||
subdirectory of the `~/src/utils` monorepo. Per audit scope, gatelock itself was
|
||||
not walked against all 28 rules and no separate
|
||||
`~/utils/gatelock/DESIGN_AUDIT_TODO.md` was written.
|
||||
`~/src/utils/gatelock/DESIGN_AUDIT_TODO.md` was written.
|
||||
|
||||
What's relevant here: gatelock defines exactly **one** real design token —
|
||||
`LockConfig.bg: str = "#1a1a1a"` (`~/utils/gatelock/gatelock/_window.py:71`),
|
||||
`LockConfig.bg: str = "#1a1a1a"` (`~/src/utils/gatelock/gatelock/_window.py:71`),
|
||||
applied via `self.root.configure(bg=self._config.bg, ...)` in
|
||||
`LockWindow.setup()` (`_window.py:143`). Both consumer repos re-hardcode
|
||||
this same literal instead of reading it back off their own `LockConfig`
|
||||
|
||||
@ -14,7 +14,7 @@ independently, in 9 files. Evidence:
|
||||
`_sick_dialog.py` (18), `_temperature_status_mixin.py` (5).
|
||||
`#1a1a1a` alone (the background) appears **31 times** — and it is *also*
|
||||
already defined once, correctly, as `LockConfig.bg = "#1a1a1a"` in
|
||||
`~/utils/gatelock/gatelock/_window.py:71`. None of the 31 in-repo literals
|
||||
`~/src/utils/gatelock/gatelock/_window.py:71`. None of the 31 in-repo literals
|
||||
import or reference it; `LockWindow.setup()` in gatelock applies
|
||||
`config.bg` to the root window (`_window.py:143`), and then every
|
||||
screen-locker dialog re-hardcodes the same string as if gatelock's value
|
||||
|
||||
@ -47,7 +47,7 @@ production in this user's other repos — read both before designing this
|
||||
one:
|
||||
|
||||
1. **diet-guard's Contents-API repo sync**
|
||||
(`~/diet-guard/diet_guard/_sync.py` + `_sync_github.py` +
|
||||
(`~/src/diet-guard/diet_guard/_sync.py` + `_sync_github.py` +
|
||||
`_sync_merge.py`, ~120/190/80 lines respectively). `GitHubSyncClient`
|
||||
(`_sync_github.py:38`) wraps the GitHub Contents API with
|
||||
`get_file_text(path)`, `put_file_text(path, text, message=...)`,
|
||||
@ -59,7 +59,7 @@ one:
|
||||
fine-grained PAT read from `~/.config/diet_guard/sync_token` (scoped to
|
||||
just that one repo's contents).
|
||||
2. **wake-alarm's Gist-based sync**
|
||||
(`~/wake-alarm/shutdown-wrapper.sh`, phone app writes to a **private
|
||||
(`~/src/wake-alarm/shutdown-wrapper.sh`, phone app writes to a **private
|
||||
Gist**, not a repo). Config at `~/.config/wake_alarm/gist_sync.json`
|
||||
with `token`/`gist_id`. Much simpler (single JSON blob, no per-device
|
||||
paths, no merge step) — matches wake-alarm's much simpler data shape (one
|
||||
@ -148,7 +148,7 @@ sync code first.
|
||||
- `screen_locker/_constants.py` (`WORKOUT_APP_JSON_REMOTES`,
|
||||
`WORKOUT_HTTP_PORT` — new `SYNC_*` constants go here too)
|
||||
- `stronglift_replacement/workout_app/lib/` (phone-side push, new work)
|
||||
- Reference-only, do not modify: `~/diet-guard/diet_guard/_sync_github.py`,
|
||||
`_sync.py`, `_sync_merge.py`; `~/wake-alarm/shutdown-wrapper.sh`
|
||||
- Reference-only, do not modify: `~/src/diet-guard/diet_guard/_sync_github.py`,
|
||||
`_sync.py`, `_sync_merge.py`; `~/src/wake-alarm/shutdown-wrapper.sh`
|
||||
- **Do not touch**: `screen_locker/_runnerup_verification.py`,
|
||||
`_runnerup_db.py` (hard boundary, see Context above)
|
||||
|
||||
@ -15,7 +15,7 @@ to have very different shareability:
|
||||
`put_file_text` / `list_directory` against a private repo) is genuinely
|
||||
shared already — it's independently duplicated almost line-for-line
|
||||
between todo's `GitHubClient` and diet-guard's `GitHubSyncClient`
|
||||
(`~/diet-guard/diet_guard/_sync_github.py`, 191 lines, `requests`-only).
|
||||
(`~/src/diet-guard/diet_guard/_sync_github.py`, 191 lines, `requests`-only).
|
||||
Extracting this into a shared Python lib (and a shared Dart lib for
|
||||
todo's/diet-guard's Dart-side client) is low-risk, small, and is the part
|
||||
Workstream C already committed to (Contents-API pattern, not Gist —
|
||||
@ -70,7 +70,7 @@ library too:
|
||||
## 3. Per-app migration cost (revised — the original doc's "todo = smallest
|
||||
lift" assumption does not hold)
|
||||
|
||||
Checked `~/todo/lib/data/note_repository.dart`: notes are **mutated in
|
||||
Checked `~/src/todo/lib/data/note_repository.dart`: notes are **mutated in
|
||||
place** — `upsert()` does `INSERT ... ON CONFLICT DO UPDATE SET text = ?,
|
||||
priority = ?, status = ?, updated_at = ?`, relying on `sqlite_crdt`'s
|
||||
per-column Hybrid-Logical-Clock last-writer-wins to reconcile concurrent
|
||||
@ -138,8 +138,8 @@ off the shelf.
|
||||
|
||||
## Critical files referenced (read-only during this pass)
|
||||
|
||||
- `~/todo/lib/sync/sync_service.dart`, `~/todo/lib/data/note_repository.dart`
|
||||
- `~/diet-guard/diet_guard/_sync.py`, `_sync_github.py`, `_sync_merge.py`
|
||||
- `~/diet-guard/app/lib/services/sync_merge.dart`
|
||||
- `~/wake-alarm/shutdown-wrapper.sh`
|
||||
- `~/src/todo/lib/sync/sync_service.dart`, `~/src/todo/lib/data/note_repository.dart`
|
||||
- `~/src/diet-guard/diet_guard/_sync.py`, `_sync_github.py`, `_sync_merge.py`
|
||||
- `~/src/diet-guard/app/lib/services/sync_merge.dart`
|
||||
- `~/src/wake-alarm/shutdown-wrapper.sh`
|
||||
- `docs/todo/workstream-c-github-sync-workout-data.md` (this repo)
|
||||
|
||||
@ -8,9 +8,9 @@ fell out of it (both resolved by explicit user call, 2026-07-04).
|
||||
|
||||
**The two shared libraries are now implemented and locally verified
|
||||
(2026-07-05):**
|
||||
- `~/crdt-sync` (Python) — 60 tests, 100% branch coverage, clean
|
||||
- `~/src/utils/crdt-sync` (Python) — 60 tests, 100% branch coverage, clean
|
||||
ruff/mypy/pylint/bandit/pre-commit. Local git repo, one commit.
|
||||
- `~/crdt_sync_dart` (pure Dart, no Flutter dep) — 59 tests, clean
|
||||
- `~/src/utils/crdt_sync_dart` (pure Dart, no Flutter dep) — 59 tests, clean
|
||||
`dart analyze`. Local git repo, one commit.
|
||||
|
||||
Both implement the unified LWW-map-with-sticky-remove scheme (`Hlc`,
|
||||
@ -62,7 +62,7 @@ from-scratch CRDT implementation.
|
||||
|
||||
**diet-guard and wake-alarm do NOT use CRDTs today.** Their existing
|
||||
"merge" mechanisms are much simpler:
|
||||
- diet-guard: `_sync_merge.merge_logs` (`~/diet-guard/diet_guard/_sync_merge.py`,
|
||||
- diet-guard: `_sync_merge.merge_logs` (`~/src/diet-guard/diet_guard/_sync_merge.py`,
|
||||
81 lines) is a tombstone-aware, entry-key-based merge — closer to
|
||||
last-write-wins per entry than a general CRDT. Transport is
|
||||
`_sync_github.GitHubSyncClient` against a private repo's Contents API
|
||||
@ -151,9 +151,9 @@ time this is scoped for real.
|
||||
|
||||
## Critical files (reference only — read, do not modify, during scoping)
|
||||
|
||||
- `~/todo/lib/sync/sync_service.dart`, `sync_settings.dart` (CRDT-via-package pattern)
|
||||
- `~/diet-guard/diet_guard/_sync.py`, `_sync_github.py`, `_sync_merge.py`
|
||||
- `~/diet-guard/app/lib/services/sync_service.dart`, `sync_merge.dart`
|
||||
- `~/wake-alarm/shutdown-wrapper.sh`
|
||||
- `~/src/todo/lib/sync/sync_service.dart`, `sync_settings.dart` (CRDT-via-package pattern)
|
||||
- `~/src/diet-guard/diet_guard/_sync.py`, `_sync_github.py`, `_sync_merge.py`
|
||||
- `~/src/diet-guard/app/lib/services/sync_service.dart`, `sync_merge.dart`
|
||||
- `~/src/wake-alarm/shutdown-wrapper.sh`
|
||||
- `docs/todo/workstream-c-github-sync-workout-data.md` (this repo — resolve
|
||||
its open questions jointly with this one, not independently)
|
||||
|
||||
@ -42,7 +42,7 @@ readonly REPO_DIR="$SCRIPT_DIR"
|
||||
readonly SYSTEMD_USER_DIR="$HOME/.config/systemd/user"
|
||||
readonly PROD_PYTHON="/usr/bin/python3"
|
||||
# The shared lock backend, developed in lockstep with this repo.
|
||||
readonly GATELOCK_DIR="$HOME/utils/gatelock"
|
||||
readonly GATELOCK_DIR="$HOME/src/utils/gatelock"
|
||||
|
||||
echo "=== Screen Locker Installer ==="
|
||||
|
||||
@ -58,7 +58,7 @@ fi
|
||||
# 2. Install the package ------------------------------------------------------
|
||||
# --break-system-packages is required on Arch (PEP 668). Editable so a later
|
||||
# `git pull` in THIS clone updates the running service with no reinstall. That
|
||||
# is also why the clone must live somewhere durable (~/screen-locker), never a
|
||||
# is also why the clone must live somewhere durable (~/src/screen-locker), never a
|
||||
# scratch directory: a non-editable snapshot would freeze at this commit and
|
||||
# silently stop tracking the repo.
|
||||
echo "[2/4] Installing screen_locker into user site-packages (editable)..."
|
||||
@ -69,7 +69,7 @@ echo "[2/4] Installing screen_locker into user site-packages (editable)..."
|
||||
# pyproject.toml pins `gatelock @ git+https://.../@gatelock-v0.2.1`, so the
|
||||
# install above resolves that pin and overwrites any local editable gatelock
|
||||
# with a frozen wheel built from the tag. That silently reverts every
|
||||
# unreleased change in ~/utils/gatelock and breaks the other lockers that
|
||||
# unreleased change in ~/src/utils/gatelock and breaks the other lockers that
|
||||
# depend on them -- observed: it removed `ScrollableSurface` and took
|
||||
# diet_guard down with it.
|
||||
#
|
||||
@ -122,7 +122,7 @@ if ! (cd /tmp && "$PROD_PYTHON" -c "import screen_locker" 2>/dev/null); then
|
||||
fi
|
||||
if ! (cd /tmp && "$PROD_PYTHON" -c "import gatelock" 2>/dev/null); then
|
||||
echo "ERROR: $PROD_PYTHON cannot import gatelock (the shared lock" >&2
|
||||
echo " backend). Install it editable from ~/utils/gatelock." >&2
|
||||
echo " backend). Install it editable from ~/src/utils/gatelock." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -d "$GATELOCK_DIR" ]]; then
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
> "do dopamine-ux-04-screen-locker". It is self-contained -- it needs no context from
|
||||
> any other session.
|
||||
>
|
||||
> Canonical copy: `~/utils/dopamine-ux/04-screen-locker.md` (source of truth; this is a
|
||||
> distributed copy). Running order and cross-prompt rules: `~/utils/dopamine-ux/00-INDEX.md`.
|
||||
> Canonical copy: `~/src/utils/dopamine-ux/04-screen-locker.md` (source of truth; this is a
|
||||
> distributed copy). Running order and cross-prompt rules: `~/src/utils/dopamine-ux/00-INDEX.md`.
|
||||
> Generated 2026-08-16 from a survey of this repo -- line numbers are accurate
|
||||
> as of that date; **anchor on the symbol names, not the line numbers.**
|
||||
|
||||
@ -19,10 +19,10 @@ Do **both**, in the same session that completes the work:
|
||||
Do not leave a finished prompt lying in the repo -- a stale prompt is
|
||||
indistinguishable from a pending one, and the next session will re-run it.
|
||||
|
||||
2. **Log completion in the canonical index**, in `~/utils` (a *different* repo,
|
||||
2. **Log completion in the canonical index**, in `~/src/utils` (a *different* repo,
|
||||
so it needs its own commit):
|
||||
```bash
|
||||
cd ~/utils
|
||||
cd ~/src/utils
|
||||
# append to the "Completion log" table in dopamine-ux/00-INDEX.md:
|
||||
# | 04-screen-locker.md | DONE <YYYY-MM-DD> | <impl commit sha> | <one-line note> |
|
||||
git add dopamine-ux/00-INDEX.md
|
||||
@ -69,7 +69,7 @@ the data already exists, is already true, and needs no new state.
|
||||
|
||||
## where
|
||||
|
||||
Repo: `~/screen-locker`.
|
||||
Repo: `~/src/screen-locker`.
|
||||
|
||||
Primary:
|
||||
- `screen_locker/_status_sections.py` — the section renderers used by the status
|
||||
@ -136,7 +136,7 @@ Primary:
|
||||
- optional: a daily streak alongside the weekly one. Note this **would** be new
|
||||
state (the existing streak is consecutive-*weeks*), so it triggers the conftest
|
||||
requirement above. diet-guard's consecutive-*day* streak
|
||||
(`~/diet-guard/diet_guard/_daystatus.py` ~:144) is the precedent to mirror.
|
||||
(`~/src/diet-guard/diet_guard/_daystatus.py` ~:144) is the precedent to mirror.
|
||||
|
||||
## done
|
||||
|
||||
@ -144,7 +144,7 @@ Primary:
|
||||
the current streak, bonus hours and early-bird state — with the real values
|
||||
from `extra_benefits_state.json`, not placeholders.
|
||||
2. A week-transition milestone reaches the UI instead of only `_logger.info`.
|
||||
3. `cd ~/screen-locker && python -m pytest` passes.
|
||||
3. `cd ~/src/screen-locker && python -m pytest` passes.
|
||||
4. `pre-commit run --files <changed files>` is clean — including the 250-line cap
|
||||
(`scripts/check_file_length.py`) and the silent-failure check.
|
||||
5. `git diff` touches no enforcement logic: no change to lock decisions, weekly
|
||||
@ -155,7 +155,7 @@ Primary:
|
||||
Desktop — this is a desktop Python app.
|
||||
|
||||
```
|
||||
cd ~/screen-locker
|
||||
cd ~/src/screen-locker
|
||||
python -m screen_locker --status # CLI: confirm the values it prints
|
||||
screen-locker-status # the Tk window: confirm they render
|
||||
```
|
||||
@ -176,7 +176,7 @@ Current real state for comparison: `screen_locker/extra_benefits_state.json` and
|
||||
(the enforcement invariant) and the reward strings ~:130-139.
|
||||
- `screen_locker/_unlock_view.py` — the existing celebration, for tone.
|
||||
- `screen_locker/status_view.py` — check its line count **before** editing.
|
||||
- `~/screen-locker/CLAUDE.md` — repo rules (no silent failures, ruff `select=ALL`).
|
||||
- `~/src/screen-locker/CLAUDE.md` — repo rules (no silent failures, ruff `select=ALL`).
|
||||
|
||||
## context you would otherwise rediscover
|
||||
|
||||
@ -196,7 +196,7 @@ Current real state for comparison: `screen_locker/extra_benefits_state.json` and
|
||||
tunable is a module-level constant. An opt-out toggle has no existing home;
|
||||
for a self-restriction tool, requiring a code edit to disable is arguably
|
||||
correct, so prefer a constant in `_constants.py` over new state.
|
||||
- `~/gatelock` is **not** a repo — it is `~/utils/gatelock/gatelock/`, consumed as
|
||||
- `~/gatelock` is **not** a repo — it is `~/src/utils/gatelock/gatelock/`, consumed as
|
||||
a pinned git dep, and it holds no workout state.
|
||||
- Manual workouts were **not** removed: `_manual_workout.py` implements a
|
||||
rate-limited, evidence-gated subsystem (budget 2 per 7 days, 10 per 30).
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
> "do dopamine-ux-05-workout-app". It is self-contained -- it needs no context from
|
||||
> any other session.
|
||||
>
|
||||
> Canonical copy: `~/utils/dopamine-ux/05-workout-app.md` (source of truth; this is a
|
||||
> distributed copy). Running order and cross-prompt rules: `~/utils/dopamine-ux/00-INDEX.md`.
|
||||
> Canonical copy: `~/src/utils/dopamine-ux/05-workout-app.md` (source of truth; this is a
|
||||
> distributed copy). Running order and cross-prompt rules: `~/src/utils/dopamine-ux/00-INDEX.md`.
|
||||
> Generated 2026-08-16 from a survey of this repo -- line numbers are accurate
|
||||
> as of that date; **anchor on the symbol names, not the line numbers.**
|
||||
|
||||
@ -19,10 +19,10 @@ Do **both**, in the same session that completes the work:
|
||||
Do not leave a finished prompt lying in the repo -- a stale prompt is
|
||||
indistinguishable from a pending one, and the next session will re-run it.
|
||||
|
||||
2. **Log completion in the canonical index**, in `~/utils` (a *different* repo,
|
||||
2. **Log completion in the canonical index**, in `~/src/utils` (a *different* repo,
|
||||
so it needs its own commit):
|
||||
```bash
|
||||
cd ~/utils
|
||||
cd ~/src/utils
|
||||
# append to the "Completion log" table in dopamine-ux/00-INDEX.md:
|
||||
# | 05-workout-app.md | DONE <YYYY-MM-DD> | <impl commit sha> | <one-line note> |
|
||||
git add dopamine-ux/00-INDEX.md
|
||||
@ -74,7 +74,7 @@ number with a motion token while you are in the file.
|
||||
|
||||
## where
|
||||
|
||||
Repo: `~/screen-locker`. App: `~/screen-locker/stronglift_replacement/workout_app`
|
||||
Repo: `~/src/screen-locker`. App: `~/src/screen-locker/stronglift_replacement/workout_app`
|
||||
(a Flutter app nested inside the screen-locker repo; that directory contains **no
|
||||
Python** — only the app and two design docs).
|
||||
|
||||
@ -175,7 +175,7 @@ Theme: `lib/ui/theme.dart` — local hand-copy, **no `design_system` dependency*
|
||||
2. Finishing a workout produces a haptic and a visible dialog arrival; step 2
|
||||
adds a sound.
|
||||
3. No inline animation duration remains in `exercise_tile_rows.dart`.
|
||||
4. `cd ~/screen-locker/stronglift_replacement/workout_app && flutter analyze` clean.
|
||||
4. `cd ~/src/screen-locker/stronglift_replacement/workout_app && flutter analyze` clean.
|
||||
5. `flutter test` passes **and coverage stays at 100%**.
|
||||
6. With OS "remove animations" on, the app works and durations are zero.
|
||||
7. Step 2: the settings toggle flips, persists across restart, and silences both
|
||||
@ -187,7 +187,7 @@ Theme: `lib/ui/theme.dart` — local hand-copy, **no `design_system` dependency*
|
||||
|
||||
```
|
||||
adb devices # confirm 23181JEGR08034
|
||||
cd ~/screen-locker/stronglift_replacement/workout_app
|
||||
cd ~/src/screen-locker/stronglift_replacement/workout_app
|
||||
flutter build apk --release
|
||||
adb install -r build/app/outputs/flutter-apk/app-release.apk
|
||||
```
|
||||
@ -209,7 +209,7 @@ state what you felt and heard; do not infer them from the code.
|
||||
`setLastWorkoutType` as the public-wrapper pattern.
|
||||
- `lib/screens/settings_screen_sections.dart` ~:1-11 — the coverage/line-cap
|
||||
comments, and `_SyncSection` as the section pattern.
|
||||
- `~/utils/unified-design-system/motion.md` — motion/haptic vocabulary from
|
||||
- `~/src/utils/unified-design-system/motion.md` — motion/haptic vocabulary from
|
||||
prompt 01. **Prompt 01 must have run first.**
|
||||
|
||||
## context you would otherwise rediscover
|
||||
|
||||
@ -49,7 +49,7 @@ def is_scheduled_skip_today(today: date | None = None) -> bool:
|
||||
"""Return True if *today* is in the shared free-day pool.
|
||||
|
||||
The source moved from this app's own ``scheduled_skips.json`` to the
|
||||
fleet-wide pool (``~/utils/freedays``), so one marked day now stands down
|
||||
fleet-wide pool (``~/src/utils/freedays``), so one marked day now stands down
|
||||
every gate app at once instead of only this one.
|
||||
|
||||
The date is **local**, not UTC. The file-backed check this replaces
|
||||
|
||||
@ -135,7 +135,7 @@ def get_flags() -> dict[str, bool]:
|
||||
|
||||
``is_scheduled_skip_today`` keeps its name but no longer reads this app's
|
||||
``scheduled_skips.json``: it is now the shared, fleet-wide free-day pool
|
||||
(``~/utils/freedays``), so a true here also means diet-guard, wake-alarm,
|
||||
(``~/src/utils/freedays``), so a true here also means diet-guard, wake-alarm,
|
||||
leetcode-guard and home-guard are standing down today.
|
||||
"""
|
||||
history = load_history()
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
# whole ratchet.
|
||||
#
|
||||
# Add to /etc/sudoers.d/workout-locker:
|
||||
# <username> ALL=(root) NOPASSWD: /home/kuhy/screen-locker/screen_locker/adjust_shutdown_schedule.sh
|
||||
# <username> ALL=(root) NOPASSWD: /home/kuhy/src/screen-locker/screen_locker/adjust_shutdown_schedule.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
This used to append to ``screen_locker/scheduled_skips.json``, which only
|
||||
screen-locker read. That file is no longer consulted by anything: the lock
|
||||
chain now asks the shared pool (``~/utils/freedays``), so a day taken here
|
||||
chain now asks the shared pool (``~/src/utils/freedays``), so a day taken here
|
||||
also stands down diet-guard, wake-alarm, leetcode-guard and home-guard.
|
||||
|
||||
Kept as a thin wrapper rather than deleted because ``arm.sh`` calls it, and
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# ============================================================================
|
||||
# Fail if any dependency in the commit is behind its ecosystem's newest stable.
|
||||
#
|
||||
# Thin delegate to the shared gate in ~/utils, which owns the registry
|
||||
# Thin delegate to the shared gate in ~/src/utils, which owns the registry
|
||||
# adapters, the pre-release rules and the allowlist semantics. Copying that
|
||||
# logic here is what lets one repo's idea of "current" drift from every other
|
||||
# repo's -- so this script only locates the shared checker and forwards its
|
||||
@ -18,12 +18,12 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_dependency_freshness.sh"
|
||||
readonly SHARED_GATE="${UTILS_ROOT:-$HOME/src/utils}/scripts/check_dependency_freshness.sh"
|
||||
|
||||
main() {
|
||||
if [[ ! -x "$SHARED_GATE" ]]; then
|
||||
echo "Error: shared dependency-freshness gate not found at $SHARED_GATE" >&2
|
||||
echo " Clone github.com/kuhyx/utils to ~/utils, or set" >&2
|
||||
echo " Clone github.com/kuhyx/utils to ~/src/utils, or set" >&2
|
||||
echo " UTILS_ROOT to where it lives." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# ============================================================================
|
||||
# Fail if any markdown file breaks the shared naming convention.
|
||||
#
|
||||
# Thin delegate to the shared gate in ~/utils, which owns the four namespaces
|
||||
# Thin delegate to the shared gate in ~/src/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
|
||||
@ -16,12 +16,12 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_md_naming.sh"
|
||||
readonly SHARED_GATE="${UTILS_ROOT:-$HOME/src/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 " Clone github.com/kuhyx/utils to ~/src/utils, or set" >&2
|
||||
echo " UTILS_ROOT to where it lives." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#
|
||||
# The apps depend on crdt_sync as a *git dependency pinned to a tag*, so what
|
||||
# CI builds is whatever that tag points at. A `dependency_overrides:` entry
|
||||
# pointing at ~/utils/crdt_sync_dart is invaluable while developing an unreleased
|
||||
# pointing at ~/src/utils/crdt_sync_dart is invaluable while developing an unreleased
|
||||
# library change -- and catastrophic if it survives the commit: local tests go
|
||||
# green against code CI has never seen, and the failure is silent in both
|
||||
# directions.
|
||||
|
||||
@ -18,7 +18,7 @@ whole ``tk`` module for every test so the suite can never reach a display, and
|
||||
widget heights can only be measured by really rendering them. Like
|
||||
``verify_lock_popup_safety.py``, this re-executes itself under Xvfb:
|
||||
|
||||
cd ~/screen-locker && python3 -m scripts.verify_screen_fits
|
||||
cd ~/src/screen-locker && python3 -m scripts.verify_screen_fits
|
||||
|
||||
Run as a *module*, not a path: ``-m`` puts the repo root on ``sys.path`` so
|
||||
``screen_locker`` resolves from the checkout. Running it as a path only works
|
||||
|
||||
@ -55,7 +55,7 @@ flutter:
|
||||
- assets/sounds/break_end.mp3
|
||||
|
||||
# Launcher icon generation. Source art is produced by the shared generator:
|
||||
# PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons generate --app <key>
|
||||
# PYTHONPATH=~/src/testsAndMisc python3 -m python_pkg.app_icons generate --app <key>
|
||||
# then run: dart run flutter_launcher_icons
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Tokens from ~/utils/unified-design-system (DOCS-tokens.md). Values are copied
|
||||
* Tokens from ~/src/utils/unified-design-system (DOCS-tokens.md). Values are copied
|
||||
* rather than imported because that system ships as documentation plus
|
||||
* per-stack generators, not an npm package -- keep these in step with it rather
|
||||
* than inventing new ones.
|
||||
|
||||
@ -61,7 +61,7 @@ export function makeHealth(over: Partial<HealthPayload> = {}): HealthPayload {
|
||||
armed: true,
|
||||
disarmed: false,
|
||||
disarm_marker: '/home/kuhy/.local/share/screen_locker/DISARMED',
|
||||
log_file: '/home/kuhy/screen-locker/screen_locker/log.json',
|
||||
log_file: '/home/kuhy/src/screen-locker/screen_locker/log.json',
|
||||
log_age_seconds: 3600,
|
||||
decision_log_file: '/home/kuhy/.local/share/screen_locker/decisions.jsonl',
|
||||
last_decision_age_seconds: 120,
|
||||
|
||||
@ -19,4 +19,4 @@ ExecStart=/usr/bin/python3 -m screen_locker.screen_lock --sync-only
|
||||
# disabled early-bird-workout-check.timer and nothing noticed for 13 days).
|
||||
# ExecStartPost without "-" means a disarmed locker marks this unit failed, so
|
||||
# it surfaces in `systemctl --user --failed` instead of scrolling past.
|
||||
ExecStartPost=/usr/bin/python3 %h/screen-locker/scripts/check_enforcement_armed.py --quiet
|
||||
ExecStartPost=/usr/bin/python3 %h/src/screen-locker/scripts/check_enforcement_armed.py --quiet
|
||||
|
||||
Loading…
Reference in New Issue
Block a user