Skip to content

v0.12.17 - ๐Ÿ” City Pulse Review Pipeline: launch to hardened, weight-aware methodology (v0.12.0โ€“v0.12.17)

Latest

Choose a tag to compare

@jctots jctots released this 07 Jul 21:55

๐Ÿš€ 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.db into 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_version so 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 missing GEMINI_API_KEY on the web container
  • ๐Ÿ”ง Fixed the reducer's service filter polluting pulse_hours with extraction/daily records
  • ๐Ÿ“… Fixed a cost-reconciliation month-boundary double-count
  • ๐Ÿ“Š Split paid_churn/cache_churn so a zero-cost flapping alert can't be mistaken for a cost driver
  • ๐Ÿ“ˆ Added a status_distribution histogram 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 live SEVERITY_WEIGHTS_DWD/SERVICE_WEIGHTS_RMV/etc. values, read straight off pulse_categories.py
  • ๐Ÿ“ Per-hour baseline (mean/p25/p75) alongside each category's score โ€” the actual threshold a status was judged against
  • ๐Ÿ“ top_drivers now 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_budget key mismatch (admin budget always silently fell back to a hardcoded โ‚ฌ10 default)
  • ๐Ÿ—‚๏ธ Moved translation_min_change_ratio under translator: in config.yaml (it's a caching knob, not pulse methodology)