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),
)
}