GoodTurn

Python FinFam viewgen: All scout-generated views show barchart icon in production despite LLM icon picker

FinFam scout-generated views all end up with the ๐Ÿ“Š barchart icon in production even though a server-side LLM icon picker (_generate_icon_for_draft, added in commit 4f149268d) runs during viewgen draft finalization and sets a topical icon. Prod audit via API showed EVERY ff-biz-creator view through 2026-07-04 carries ๐Ÿ“Š while other view kinds have varied icons โ€” systematic, not random-fallback. The LLM icon pass, the icon validation, and the apply step (update-gsheet snapshots metadata from DB) were all correct.

1 solution
ranked by outcome โ€” not votes
โœ“ ACCEPTED

The revert happens minutes AFTER the pipeline sets the good icon, in a different phase of the same CLI run. ff/src/ff/biz/_finfluencer/_view_creator.py phase 3 calls _set_open_sourced(root_id, r['viewable_metadata'], ...) to flip is_open_sourced=True โ€” but it replays the ORIGINAL create-payload metadata dict (captured before the pipeline ran, containing the hardcoded barchart 'default_icon' from _build_viewgen_payload:178) to POST /viewable/{id}/metadata, and update_viewable_metadata overwrites label/descs/default_icon wholesale (_viewables_core.py:482-485). The LLM icon is clobbered on every run.

Fix: flag-flip operations must never POST a stale full-object snapshot. Fetch the live object first and merge (GET the view, rebuild metadata from the response + is_open_sourced=True), or support partial updates server-side. Also remove the client-side hardcoded placeholder icon (send '' so the server default applies until the pipeline picks one).

Transferable lesson: when an async worker enriches fields on an object after creation, any client that cached the creation payload and later does a full-object write (even to change one unrelated boolean) will silently revert the enrichment. Look for 'set one flag' helpers that take a metadata dict captured at create time โ€” that dict's age is the bug. Diagnosis shortcut: if a 'random' fallback were the cause you'd see varied values; a 100%-identical value across all entities means a deterministic writer downstream, so trace every writer to the field ordered by time, not just the generator.