From 8a93f68c10770c592468862dc9ec08386b291447 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 2 Jul 2026 13:20:24 -0400 Subject: feat(theme-studio): pin retired packages so themes keep covering them PINNED_PACKAGE_FACES is the curated record of packages retired from the config (ghostel, all-the-icons). A pinned package survives inventory regeneration, shows a 'not loaded' label + hover in the app dropdown, and keeps refreshing its face list from the live inventory while that still carries it. An attempted live regen made the fragility concrete: today's daemon session was missing 142 faces from lazily-loaded packages, so regen-from-live is inherently lossy and the pin is the only durable record. --- scripts/theme-studio/test_generate.py | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'scripts/theme-studio/test_generate.py') diff --git a/scripts/theme-studio/test_generate.py b/scripts/theme-studio/test_generate.py index d4744cde..e53bdd62 100644 --- a/scripts/theme-studio/test_generate.py +++ b/scripts/theme-studio/test_generate.py @@ -798,5 +798,55 @@ class NerdIconsGallery(unittest.TestCase): self.assertIn("nerd-icons-blue", faces) +class PinnedPackages(unittest.TestCase): + """The ecosystem coverage policy's mechanism: PINNED_PACKAGE_FACES is the + curated record of packages retired from this config. A pinned package is + always marked not loaded (pinning happens exactly at retirement), and it + survives inventory regeneration even when uninstalled. Its face list stays + fresh from the live inventory when present (a still-installed dependency + may grow faces); the pin is the fallback when the inventory drops it.""" + + def _apps_with_inventory(self, inventory): + import app_inventory + with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as f: + json.dump(inventory, f) + path = f.name + try: + return app_inventory.add_inventory_apps({}, path) + finally: + os.unlink(path) + + def test_pinned_package_absent_from_inventory_is_added_unloaded(self): + apps = self._apps_with_inventory({"someother": ["someother-face"]}) + self.assertIn("ghostel", apps) + self.assertTrue(apps["ghostel"]["unloaded"]) + self.assertIn("not loaded", apps["ghostel"]["label"]) + faces = {row[0] for row in apps["ghostel"]["faces"]} + self.assertIn("ghostel-default", faces) + + def test_pinned_package_in_inventory_keeps_live_faces_still_flagged (self): + apps = self._apps_with_inventory({"ghostel": ["ghostel-default", "ghostel-brand-new"]}) + self.assertTrue(apps["ghostel"]["unloaded"]) + self.assertIn("not loaded", apps["ghostel"]["label"]) + faces = {row[0] for row in apps["ghostel"]["faces"]} + self.assertIn("ghostel-brand-new", faces) + + def test_unpinned_inventory_package_is_not_flagged(self): + apps = self._apps_with_inventory({"someother": ["someother-face"]}) + self.assertFalse(apps["someother"].get("unloaded")) + self.assertNotIn("not loaded", apps["someother"]["label"]) + + def test_pinned_apps_carry_an_explanatory_hover(self): + apps = self._apps_with_inventory({}) + self.assertIn("pinned", apps["ghostel"].get("hover", "")) + + def test_all_the_icons_is_pinned(self): + apps = self._apps_with_inventory({}) + self.assertIn("all-the-icons", apps) + self.assertTrue(apps["all-the-icons"]["unloaded"]) + faces = {row[0] for row in apps["all-the-icons"]["faces"]} + self.assertIn("all-the-icons-blue", faces) + + if __name__ == "__main__": unittest.main() -- cgit v1.2.3