Prettier the umbrella and phone_lease evidence

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Ajzz98xksbfak8CaunZWC
This commit is contained in:
Krzysztof Rudnicki 2026-09-25 15:08:37 +02:00
parent c0c51036fc
commit c3754681dc
3 changed files with 74 additions and 17 deletions

View File

@ -9,6 +9,8 @@
"No caller ever leases a placeholder serial.",
"phone_deploy.sh and android_ui keep working unchanged."
],
"out_of_scope": ["phone_deploy virtual-display default, android_ui --display, the raw-adb hook (other session)."],
"out_of_scope": [
"phone_deploy virtual-display default, android_ui --display, the raw-adb hook (other session)."
],
"verifier": "CLI scenario on a temp lease dir; two concurrent phone_vd displays on the real phone; pytest python_pkg/phone_lease 65 passed at 100% branch coverage."
}

View File

@ -1,13 +1,43 @@
{
"intent": "The new Umbrella? Flutter app (~/src/umbrella, com.kuhy.umbrella) gets a launcher icon from the shared family instead of the stock Flutter icon.",
"scope": ["python_pkg/app_icons: new `umbrella` glyph and registry entry", "AppIcon dataclass moved to _app_icon.py so apps.py stays under the 250-line cap (re-exported, API unchanged)", "No change to style.py or any other app's icon"],
"changes": ["_glyph_art_more.py: _UMBRELLA, a filled scalloped canopy over a stroked J-handle, geometry inside SAFE_BOX with a 40px hook opening (>= MIN_NEGATIVE_SPACE)", "glyphs.py: registers the umbrella glyph", "apps.py: registers the umbrella app; AppIcon now imported from _app_icon.py and listed in __all__", "_app_icon.py: the AppIcon record, Path under TYPE_CHECKING"],
"verification": [
{"command": "PYTHONPATH=. python3 -m python_pkg.app_icons generate --app umbrella --android", "result": "pass", "evidence": "umbrella: wrote 6 asset files to ~/src/umbrella/assets/icon; regenerated Android mipmaps; no safe-box warning"},
{"command": "PYTHONPATH=. python3 -m python_pkg.app_icons preview -o /tmp/sheet.png", "result": "pass", "evidence": "umbrella renders in the family row at full size, circle mask and 48dp; reads as an umbrella"},
{"command": "pytest python_pkg/app_icons", "result": "pass", "evidence": "44 passed; registry invariants (real glyph, shared accent, hex accent) cover the new entry"},
{"command": "pre-commit run --files <changed-files>", "result": "pass", "evidence": "all hooks passed"}
"scope": [
"python_pkg/app_icons: new `umbrella` glyph and registry entry",
"AppIcon dataclass moved to _app_icon.py so apps.py stays under the 250-line cap (re-exported, API unchanged)",
"No change to style.py or any other app's icon"
],
"risks": ["Importers of AppIcon from apps.py keep working via the re-export; generate.py and test_generate.py still import it from there."],
"rollback": ["git revert the commit; the umbrella app keeps its already-generated PNGs", "Re-run pytest python_pkg/app_icons"]
"changes": [
"_glyph_art_more.py: _UMBRELLA, a filled scalloped canopy over a stroked J-handle, geometry inside SAFE_BOX with a 40px hook opening (>= MIN_NEGATIVE_SPACE)",
"glyphs.py: registers the umbrella glyph",
"apps.py: registers the umbrella app; AppIcon now imported from _app_icon.py and listed in __all__",
"_app_icon.py: the AppIcon record, Path under TYPE_CHECKING"
],
"verification": [
{
"command": "PYTHONPATH=. python3 -m python_pkg.app_icons generate --app umbrella --android",
"result": "pass",
"evidence": "umbrella: wrote 6 asset files to ~/src/umbrella/assets/icon; regenerated Android mipmaps; no safe-box warning"
},
{
"command": "PYTHONPATH=. python3 -m python_pkg.app_icons preview -o /tmp/sheet.png",
"result": "pass",
"evidence": "umbrella renders in the family row at full size, circle mask and 48dp; reads as an umbrella"
},
{
"command": "pytest python_pkg/app_icons",
"result": "pass",
"evidence": "44 passed; registry invariants (real glyph, shared accent, hex accent) cover the new entry"
},
{
"command": "pre-commit run --files <changed-files>",
"result": "pass",
"evidence": "all hooks passed"
}
],
"risks": [
"Importers of AppIcon from apps.py keep working via the re-export; generate.py and test_generate.py still import it from there."
],
"rollback": [
"git revert the commit; the umbrella app keeps its already-generated PNGs",
"Re-run pytest python_pkg/app_icons"
]
}

View File

@ -1,6 +1,10 @@
{
"intent": "Several Claude sessions can use one phone at once without interrupting each other: leases are per app, a whole-phone lease is short and cleans up after itself, and every caller agrees on the serial.",
"scope": ["python_pkg/phone_lease only (lease, ops, owner, serial, _cleanup, CLI, tests)", "Callers unchanged: phone_deploy.sh's `acquire \"$SERIAL\" --note --wait` and android_ui's acquire(serial, note) keep the real-screen scope", "phone_deploy/android_ui/raw-adb hook changes belong to the image-attachments-todo-dufs session"],
"scope": [
"python_pkg/phone_lease only (lease, ops, owner, serial, _cleanup, CLI, tests)",
"Callers unchanged: phone_deploy.sh's `acquire \"$SERIAL\" --note --wait` and android_ui's acquire(serial, note) keep the real-screen scope",
"phone_deploy/android_ui/raw-adb hook changes belong to the image-attachments-todo-dufs session"
],
"changes": [
"Scopes: pkg:<package> (default pkg:__screen__) and whole-phone; per-package leases coexist, whole-phone conflicts with every foreign lease",
"whole-phone ttl capped at 300 s; --cleanup commands run exactly once on release or expiry, expiry enforced by a detached `reap` process that wakes at least every 5 s",
@ -10,11 +14,32 @@
"acquire(serial, note, *, scope, terms=Terms(ttl, wait, cleanup), owner, clock) to stay within max-args 6"
],
"verification": [
{"command": "two owners via PHONE_LEASE_OWNER against a temp PHONE_LEASE_DIR", "result": "pass", "evidence": "pkg:a + pkg:b coexist (0 0); B on pkg:a -> 3; B whole-phone while A holds a package -> 3; ttl 999 clamped to +300 s; release ran cleanup; unreleased whole-phone ttl 3 refreshed at +2 s was reaped only after the refreshed expiry"},
{"command": "~/.claude/scripts/phone_vd.sh start as testA (umbrella) and testB (settings) on the real phone", "result": "pass", "evidence": "displays 7 and 8 side by side; tap on 7 changed only 7; display 0 unchanged; third owner on umbrella exit 43; stop released both package leases"},
{"command": "pytest python_pkg/phone_lease --cov --cov-branch", "result": "pass", "evidence": "65 passed; every phone_lease module 100% line and branch"},
{"command": "pre-commit run --files <changed-files>", "result": "pass", "evidence": "all hooks passed"}
{
"command": "two owners via PHONE_LEASE_OWNER against a temp PHONE_LEASE_DIR",
"result": "pass",
"evidence": "pkg:a + pkg:b coexist (0 0); B on pkg:a -> 3; B whole-phone while A holds a package -> 3; ttl 999 clamped to +300 s; release ran cleanup; unreleased whole-phone ttl 3 refreshed at +2 s was reaped only after the refreshed expiry"
},
{
"command": "~/.claude/scripts/phone_vd.sh start as testA (umbrella) and testB (settings) on the real phone",
"result": "pass",
"evidence": "displays 7 and 8 side by side; tap on 7 changed only 7; display 0 unchanged; third owner on umbrella exit 43; stop released both package leases"
},
{
"command": "pytest python_pkg/phone_lease --cov --cov-branch",
"result": "pass",
"evidence": "65 passed; every phone_lease module 100% line and branch"
},
{
"command": "pre-commit run --files <changed-files>",
"result": "pass",
"evidence": "all hooks passed"
}
],
"risks": ["A reaper killed before expiry leaves cleanup to the next locked update of that phone's lease file, which runs it then."],
"rollback": ["git revert the commit; old lease files remain readable by the reverted code only if they hold a single object, so delete ~/.cache/phone-lease/*.json after reverting", "Re-run pytest python_pkg/phone_lease"]
"risks": [
"A reaper killed before expiry leaves cleanup to the next locked update of that phone's lease file, which runs it then."
],
"rollback": [
"git revert the commit; old lease files remain readable by the reverted code only if they hold a single object, so delete ~/.cache/phone-lease/*.json after reverting",
"Re-run pytest python_pkg/phone_lease"
]
}