diff --git a/docs/superpowers/evidence/app-icons-track-bars-kuhylog-2026-08-09.json b/docs/superpowers/evidence/app-icons-track-bars-kuhylog-2026-08-09.json
new file mode 100644
index 00000000..bf4d9b41
--- /dev/null
+++ b/docs/superpowers/evidence/app-icons-track-bars-kuhylog-2026-08-09.json
@@ -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."
+ ]
+}
diff --git a/python_pkg/app_icons/apps.py b/python_pkg/app_icons/apps.py
index 70568f1b..80c37b29 100644
--- a/python_pkg/app_icons/apps.py
+++ b/python_pkg/app_icons/apps.py
@@ -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,
+ ),
)
}
diff --git a/python_pkg/app_icons/glyphs.py b/python_pkg/app_icons/glyphs.py
index 7321816f..d84f6f30 100644
--- a/python_pkg/app_icons/glyphs.py
+++ b/python_pkg/app_icons/glyphs.py
@@ -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 = """\
+
+
+
+ """
+
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),
)
}