diff --git a/docs/superpowers/evidence/app-icons-bowl-star-2026-08-29.json b/docs/superpowers/evidence/app-icons-bowl-star-2026-08-29.json new file mode 100644 index 00000000..261c3aa2 --- /dev/null +++ b/docs/superpowers/evidence/app-icons-bowl-star-2026-08-29.json @@ -0,0 +1,45 @@ +{ + "intent": "Give the new ~/restaurant-rater app a launcher icon from the shared family, so it stops shipping the stock Flutter beach icon.", + "scope": [ + "python_pkg/app_icons/_glyph_art_more.py - the new SVG fragment", + "python_pkg/app_icons/glyphs.py - register the glyph in GLYPHS", + "python_pkg/app_icons/apps.py - register the app so --app restaurant_rater passes argument validation", + "Non-goal: no change to the shared accent #B8862E or the charcoal field; a glyph is distinguished by silhouette only", + "Non-goal: no change to any existing app's icon" + ], + "changes": [ + "Added _BOWL_STAR: a filled five-pointed star (R=140 r=56 about 512,380) above an open bowl with a rim at y=566 and walls dropping to y=752. Total ink y=240..788, inside the 560 safe box.", + "The star is filled rather than stroked, for the same reason as _QUILL_NIB and _ANVIL: at STROKE_WIDTH=72 its five interior notches close below MIN_NEGATIVE_SPACE and render as a pentagon at 48dp.", + "Registered Glyph('bowl-star', ...) in GLYPHS and AppIcon(key='restaurant_rater', glyph='bowl-star', linux=False) in APPS." + ], + "verification": [ + { + "command": "PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons list", + "result": "pass", + "evidence": "bowl-star appears under Glyphs; 'restaurant_rater #B8862E bowl-star /home/kuhy/restaurant-rater' appears under Apps." + }, + { + "command": "PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons generate --app restaurant_rater", + "result": "pass", + "evidence": "wrote 6 asset files to /home/kuhy/restaurant-rater/assets/icon (icon/foreground/monochrome, svg+png each). The generator's safe-box and negative-space checks did not fire." + }, + { + "command": "visual review of the rendered 640px icon.png", + "result": "pass", + "evidence": "First render read as a smiling face - shallow bowl walls stopping at y=736 became a mouth with the star for a nose. Deepened to y=752 between narrower walls (348/676) and re-rendered; it now reads as a bowl with a rim. Recorded in the fragment's comment so the next reader does not undo it." + }, + { + "command": "pre-commit run --files python_pkg/app_icons/glyphs.py python_pkg/app_icons/apps.py python_pkg/app_icons/_glyph_art_more.py", + "result": "pass", + "evidence": "mypy, pylint 10.00/10, bandit, pytest with coverage enforcement, 250-line cap and codespell all pass. An earlier run failed pylint C0301 on a 111-char comment line; the comment was rewrapped rather than suppressed." + } + ], + "risks": [ + "The glyph is new artwork, so only a visual check can confirm it reads correctly at 48dp. Mitigated by rendering and reviewing the actual PNG rather than trusting the SVG source.", + "_glyph_art_more.py grew to 127 lines; it and _glyph_art.py exist solely to stay under the 250-line cap, so a third file will be needed eventually." + ], + "rollback": [ + "git revert the commit. The three edits are additive - no existing glyph, app or shared token is touched - so a revert cannot change any other app's icon.", + "After rollback, re-run 'python3 -m python_pkg.app_icons list' and confirm the remaining 15 glyphs still resolve, then regenerate any app whose icon was rebuilt in the meantime." + ] +} diff --git a/python_pkg/app_icons/_glyph_art_more.py b/python_pkg/app_icons/_glyph_art_more.py index 45541052..e229978c 100644 --- a/python_pkg/app_icons/_glyph_art_more.py +++ b/python_pkg/app_icons/_glyph_art_more.py @@ -99,3 +99,34 @@ M 392 646 A 30 30 0 0 0 392 706 A 30 30 0 0 0 392 646 Z \ M 500 356 L 652 356 L 652 396 L 500 396 Z \ M 500 496 L 652 496 L 652 536 L 500 536 Z \ M 500 636 L 652 636 L 652 676 L 500 676 Z"/>""" + +# A filled five-pointed star sitting above an open bowl: a dish, and a verdict +# on it. Distinct from _SHIELD_CUTLERY (diet-guard) by silhouette rather than +# colour -- the accent is shared family-wide and must not carry meaning. +# +# The star is FILLED, not stroked, for the nib/anvil reason: at 72px weight an +# outlined star's five interior notches close up well above +# MIN_NEGATIVE_SPACE and render as a pentagon blob at 48dp. +# +# Geometry, all inside SAFE_BOX (x=232..792, y=232..792): +# star R=140 r=56 about (512,380): spans y=240..493, x=379..645 +# rim y=566, x=268..756 -- stroke top 530, so 37px clear of the star's +# lowest point at 493, just above MIN_NEGATIVE_SPACE=36 +# bowl walls at x=348 and x=676 dropping to y=752: stroke bottom 788, +# 4px inside the safe box +# +# The bowl is deep and narrow relative to its rim on purpose. A first pass +# used shallow walls at x=330..694 stopping at y=736, and the result read as +# a smiling mouth with the star for a nose -- two curves and a shape above +# them is a face unless the vessel is unmistakably deeper than it is wide at +# the base. Total ink runs y=240..788 = 548, under the 560 safe box. +# +# The star's lowest points are the two lower +# outer tips at y=493 -- NOT the inner vertex at y=436, which is what a first +# pass measured before checking; the rim was placed off that and overlapped +# the tips. Compute every extreme, do not eyeball one. +_BOWL_STAR = """\ + + + """ diff --git a/python_pkg/app_icons/apps.py b/python_pkg/app_icons/apps.py index e089de11..81fd84d6 100644 --- a/python_pkg/app_icons/apps.py +++ b/python_pkg/app_icons/apps.py @@ -118,6 +118,15 @@ APPS: Final[dict[str, AppIcon]] = { # Android-only app: no GTK desktop build to hand a hicolor PNG to. linux=False, ), + AppIcon( + key="restaurant_rater", + repo=_HOME / "restaurant-rater", + accent="#B8862E", + glyph="bowl-star", + icon_name="restaurant-rater", + # Android-only app: no GTK desktop build to hand a hicolor PNG to. + linux=False, + ), AppIcon( key="habit_stack", repo=_HOME / "habit_stack", diff --git a/python_pkg/app_icons/glyphs.py b/python_pkg/app_icons/glyphs.py index 79ee6ad8..2ea93b3d 100644 --- a/python_pkg/app_icons/glyphs.py +++ b/python_pkg/app_icons/glyphs.py @@ -30,6 +30,7 @@ from python_pkg.app_icons._glyph_art import ( _STORAGE_BOX, ) from python_pkg.app_icons._glyph_art_more import ( + _BOWL_STAR, _NOTE_ASCENDER, _PADLOCK_CLOSED, _PUNCH_CARD, @@ -85,6 +86,7 @@ GLYPHS: Final[dict[str, Glyph]] = { "Closed padlock with a punched-out keyhole", _PADLOCK_CLOSED, ), + Glyph("bowl-star", "Filled star above an open bowl", _BOWL_STAR), ) }