app_icons: add the kuhylog app and its track-bars glyph
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run

Three rising bars with a plotted point above the tallest: a day-by-day log
that adds up to a trend, which is what the app tracks. Bars are strokes
rather than filled rects so the glyph keeps one stroke weight, and the
168px pitch leaves 96px gaps -- comfortably above MIN_NEGATIVE_SPACE, which
is where these glyphs usually fail.

kuhylog has a Linux desktop target as well as Android, so it is registered
with linux=True and gets the hicolor set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HQtqicQHSrvBa4XaNNh9Wy
This commit is contained in:
Krzysztof Rudnicki 2026-08-09 15:26:55 +02:00
parent 137fc99a2e
commit 82e936e62b
3 changed files with 82 additions and 0 deletions

View File

@ -0,0 +1,58 @@
{
"intent": "Give kuhylog (~/kuhylog/kuhylog) an on-style launcher icon from the shared family, replacing the stock Flutter logo it was still shipping. Registers it as app #11 with a new track-bars glyph.",
"scope": [
"python_pkg/app_icons/glyphs.py: adds the _TRACK_BARS fragment and its GLYPHS entry",
"python_pkg/app_icons/apps.py: adds the kuhylog AppIcon registry entry",
"Non-goal: no change to style.py, the renderer, or any existing app's icon - a style change would restyle the whole family",
"Non-goal: no iOS assets; kuhylog has no ios/ target at all (android/ and linux/ only)"
],
"changes": [
"Three rising bars with a hollow plotted point above the tallest: a day-by-day log that adds up to a trend, which is what the app records. Distinct from the existing ten glyphs at a glance.",
"Bars are strokes rather than filled rects so the glyph carries one stroke weight throughout, unlike the filled anvil/quill-nib silhouettes. At a 168px pitch the 72px strokes leave 96px gaps, well above MIN_NEGATIVE_SPACE, so they stay separate at 48dp instead of merging into a block.",
"The marker sits on its own row above the tallest bar cap rather than beside it, so the two never collide, and is hollow so it reads as a data point rather than a full stop.",
"Registered with linux=True: a Linux desktop target was added to kuhylog in the same session, and it ships desktop/icons plus a desktop entry.",
"Accent is the shared #B8862E, matching all ten existing apps - apps are distinguished by glyph shape, not colour."
],
"verification": [
{
"command": "pre-commit run --files python_pkg/app_icons/apps.py python_pkg/app_icons/glyphs.py",
"result": "pass",
"evidence": "All hooks Passed or Skipped, including ruff, ruff format, mypy, pylint, bandit, codespell, 'Block binary/image files' and 'check for leaked secrets'. 'pytest with coverage enforcement' reported 1309 passed and TOTAL 100% across python_pkg."
},
{
"command": "python3 -m pytest python_pkg/app_icons/tests/ -q --cov=python_pkg.app_icons --cov-branch",
"result": "pass",
"evidence": "44 passed; every app_icons module at 100% branch coverage (apps.py, glyphs.py, cli.py, generate.py, preview.py, render.py, style.py, __main__.py). The registry tests are invariant-based with no hardcoded app/glyph counts, so they cover the new entry without edits."
},
{
"command": "python3 -m python_pkg.app_icons generate --app kuhylog --android",
"result": "pass",
"evidence": "Wrote 6 asset files and regenerated the Android mipmaps with no safe-box warning. mipmap-hdpi/ic_launcher.png md5 changed from the stock 13e9c72ec37fac220397aa819fa1ef2d to c5fee3fe7667ae24d38af75ee313ee28, and mipmap-anydpi-v26/ic_launcher.xml now exists. First run failed until flutter_launcher_icons was added to the app's pubspec (skill step 5), which is expected."
},
{
"command": "python3 -m python_pkg.app_icons generate --app kuhylog --linux-out desktop/icons",
"result": "pass",
"evidence": "Wrote 8 hicolor PNGs (16..512). Placed under desktop/icons to match home_inventory/todo/diet-guard, not the linux/icons path the skill text suggests."
},
{
"command": "python3 -m python_pkg.app_icons preview -o sheet.png",
"result": "pass",
"evidence": "Inspected the three rows (full size, circle-masked, 48dp). track-bars is rightmost, legible at 48dp, and sits with the family in weight and colour."
},
{
"command": "unzip -p app-debug.apk res/mipmap-xxxhdpi-v4/ic_launcher.png (viewed)",
"result": "pass",
"evidence": "The icon inside the built APK is the new glyph on the charcoal field. Installed APK md5 matches the local build byte for byte, so the shipped artifact is correct."
}
],
"risks": [
"Glyph legibility is a visual judgement; checked on the preview sheet at 48dp and by viewing the icon extracted from the APK, not asserted by a test.",
"The launcher on the physical device (Pixel 6a, nexuslauncher) still drew the stock Flutter logo in the app drawer after `adb install -r`. The APK provably contains the new icon, so this is the launcher's stale icon cache, which the app-icon skill already warns about. Force-stopping nexuslauncher did not visibly refresh it within the session; not confirmed resolved on-device.",
"app-icon/SKILL.md still documents charcoal #1B1D21 and accent #4C7DF0, which the live generator and all eleven registered apps contradict (#211D1B / #B8862E). Following the skill text literally would produce an off-palette icon. Still not fixed - same finding as the anvil/octoforge artifact."
],
"rollback": [
"git revert the commit; it only adds a glyph and a registry entry, so nothing else depends on it.",
"After rollback, run python3 -m python_pkg.app_icons list and confirm ten apps and ten glyphs, then re-run the app_icons test suite.",
"kuhylog's already-generated icon assets live in its own repo and are unaffected by a revert here; regenerating them would then fail with 'unknown app kuhylog', which is the expected signal."
]
}

View File

@ -142,6 +142,17 @@ APPS: Final[dict[str, AppIcon]] = {
# the desktop too, so it gets the hicolor set and a desktop entry.
linux=True,
),
AppIcon(
key="kuhylog",
repo=_HOME / "kuhylog" / "kuhylog",
accent="#B8862E",
glyph="track-bars",
icon_name="kuhylog",
# Android is the real target (home-screen widget, quick-settings
# tile); the Linux build exists for trying the UI without a phone,
# so it still wants the hicolor set.
linux=True,
),
)
}

View File

@ -211,6 +211,18 @@ Q 592 512 592 592 L 716 592 L 716 708 L 304 708 L 304 592 L 428 592 \
Q 428 512 424 420 L 336 420 \
L 256 392 Q 248 376 256 360 L 336 316 Z"/>"""
# Three rising bars with a plotted point above the tallest -- a day-by-day log
# that adds up to a trend, which is what a life tracker is. The bars are
# strokes rather than filled rects so the glyph keeps one stroke weight
# throughout; at a 168px pitch the 72px strokes leave 96px gaps, well above
# MIN_NEGATIVE_SPACE. The marker sits on its own row clear of the bar caps,
# and is hollow so it reads as a data point rather than a full stop.
_TRACK_BARS = """\
<path d="M 320 700 L 320 556"/>
<path d="M 488 700 L 488 460"/>
<path d="M 656 700 L 656 364"/>
<circle cx="656" cy="252" r="40" fill="none"/>"""
GLYPHS: Final[dict[str, Glyph]] = {
glyph.name: glyph
@ -225,6 +237,7 @@ GLYPHS: Final[dict[str, Glyph]] = {
Glyph("receipt-split", "Torn receipt with a perforated split", _RECEIPT_SPLIT),
Glyph("quill-nib", "Dip-pen nib with vent hole and slit", _QUILL_NIB),
Glyph("anvil", "Blacksmith's anvil with horn and flared foot", _ANVIL),
Glyph("track-bars", "Rising log bars with a plotted trend point", _TRACK_BARS),
)
}