v0.12.17 - ๐ City Pulse Review Pipeline: launch to hardened, weight-aware methodology (v0.12.0โv0.12.17)
Latest๐ New: the City Pulse review pipeline
An admin-triggered AI agent that audits City Pulse's own operation โ cost, translation caching, severity weights, status/trend usefulness, prompt quality โ and proposes concrete fixes as a draft PR.
- ๐งฎ Deterministic reducer (
review/reduce.py) turns days of raw debug logs +radar.dbinto a compact, cheap-to-read digest โ no LLM spend on re-parsing boilerplate - ๐ค Gemini reviewer (
review/reviewer.py) reasons over the digest only, producing a human-readable report plus machine-readable proposed edits - ๐ CI-mediated draft PR โ proposals never auto-apply; a GitHub Actions workflow turns accepted findings into a reviewable PR
- ๐ท๏ธ Every pulse run stamped with
pulse_config_versionso output-quality changes can be attributed to a specific methodology snapshot and compared version-over-version
๐ก๏ธ Hardened against real production data
Validated with a gold-standard methodology โ an independent human read of real digests vs. the actual Gemini report โ catching real bugs before trusting the pipeline's own output:
- ๐ณ Fixed missing
review/+prompts/in the web Docker image, and a missingGEMINI_API_KEYon the web container - ๐ง Fixed the reducer's service filter polluting
pulse_hourswith extraction/daily records - ๐ Fixed a cost-reconciliation month-boundary double-count
- ๐ Split
paid_churn/cache_churnso a zero-cost flapping alert can't be mistaken for a cost driver - ๐ Added a
status_distributionhistogram so the reviewer stops tallying status counts by eye - โ๏ธ Corrected reviewer guidance on false "never reaches clear" findings
- ๐ท๏ธ Renamed a naming-collision field (
prompt_samplesโprompt_sample_texts) that caused a hallucinated setting
๐ฏ Reviewer can now actually judge and propose severity weights
The reviewer had no repo access and no visibility into today's actual weight values or thresholds โ it could only guess. Fixed:
- โ๏ธ
weight_tablesโ the liveSEVERITY_WEIGHTS_DWD/SERVICE_WEIGHTS_RMV/etc. values, read straight offpulse_categories.py - ๐ Per-hour
baseline(mean/p25/p75) alongside each category's score โ the actual threshold a status was judged against - ๐
top_driversnow carry title/source/body, not just id+weight, so a proposed change can cite what an alert actually said
๐ง Pulse-system fixes
- โ๏ธ Cap prompt alerts by severity rank instead of sending every alert (140 alerts / 68KB โ bounded, ranked)
- ๐ Difflib-based similarity threshold before paying for a retranslation on a cosmetic body edit
- ๐ต๏ธ Explicit root-cause-naming instruction so the pulse LLM connects correlated disruptions to their shared cause
๐ฅ๏ธ Admin dashboard cleanup
- ๐จ Colored pill for the review service in the Gemini log
- ๐งน Trimmed redundant status dots (RAM/Load โ already on the health chart; StaticEvents โ can't fail; Cron โ duplicates "Last poll")
- ๐ท๏ธ Renamed "Extraction" health check to "Gemini"
- ๐ด "Last poll" text turns red once it exceeds the configured stale threshold
- ๐พ Added current disk usage display
- ๐๏ธ Added 30-day retention to
review_debug/โ previously the only debug directory with none
๐ Fixes
- ๐ถ Fixed
cost.monthly_budget_eurโcost.monthly_budgetkey mismatch (admin budget always silently fell back to a hardcoded โฌ10 default) - ๐๏ธ Moved
translation_min_change_ratioundertranslator:inconfig.yaml(it's a caching knob, not pulse methodology)