feat(forecast): wire admin→micro district resolver into §9.x filters — Step 2 #1054

Merged
bot-backend merged 1 commit from feat/wire-district-resolver into main 2026-06-05 02:04:10 +00:00
Collaborator

What — Step 2 of forecast wiring (resolver into §9.x filters)

Wires the Step-1 ekb_district_alias bridge into the §9.x district filters so an ADMIN district name resolves to its MICRO-districts → real data (was: admin name → 0 rows → silent empty forecast).

  • New site_finder/district_resolver.py::resolve_objective_districts(db, district) -> list[str] | None: admin→clean micros (ekb_district_alias, note IS NULL); None/"не определён"→None (EKB-wide); admin-without-aliases→None (never empty list); raw-micro→[micro] passthrough. 8-admin name set cached per-process; DB errors degrade safely (logged).
  • Wired into market_metrics (§9.2 stock+sales), supply_layers L1 (§9.3 open), sales_series Sources A(crm)+B(objective_lots) — crm shares the same 35-micro vocab (prod-verified full overlap). Scalar filter → psycopg3-safe = ANY(CAST(:districts AS text[])); EKB-wide branch preserved.
  • supply_layers L2/L3 deliberately NOT wired (they filter domrf_kn_objects.district_name = already admin vocab; regression-pinned).

Prod ground-truth (before → after)

admin before obj_count after L1 units after
Кировский 0 32 45,284
Ленинский 0 64 72,855
Орджоникидзевский 0 31 23,568

Quality

  • code-review: APPROVE — mutation-verified. Reviewer regressed the wiring (admin pass-through) and the empty-list-vs-None invariant; the guard tests FAILED on both → genuinely non-vacuous. The autouse identity-patch exercises the real wiring, not masks it.
  • 192 module tests pass; ruff clean; psycopg :x::type check clean.

Deferrals (Step 3)

confidence-penalty on EKB fallback (never triggers — all 8 admins resolve on prod); market_metrics elasticity (_elasticity_coef, separate analytics_queries path). Refs #969 #949.

## What — Step 2 of forecast wiring (resolver into §9.x filters) Wires the Step-1 `ekb_district_alias` bridge into the §9.x district filters so an ADMIN district name resolves to its MICRO-districts → real data (was: admin name → 0 rows → silent empty forecast). - New `site_finder/district_resolver.py::resolve_objective_districts(db, district) -> list[str] | None`: admin→clean micros (`ekb_district_alias`, `note IS NULL`); None/"не определён"→None (EKB-wide); admin-without-aliases→**None (never empty list)**; raw-micro→`[micro]` passthrough. 8-admin name set cached per-process; DB errors degrade safely (logged). - Wired into `market_metrics` (§9.2 stock+sales), `supply_layers` L1 (§9.3 open), `sales_series` Sources A(crm)+B(objective_lots) — crm shares the same 35-micro vocab (prod-verified full overlap). Scalar filter → psycopg3-safe `= ANY(CAST(:districts AS text[]))`; EKB-wide branch preserved. - `supply_layers` L2/L3 deliberately NOT wired (they filter `domrf_kn_objects.district_name` = already admin vocab; regression-pinned). ## Prod ground-truth (before → after) | admin | before | obj_count after | L1 units after | |---|---|---|---| | Кировский | 0 | 32 | 45,284 | | Ленинский | 0 | 64 | 72,855 | | Орджоникидзевский | 0 | 31 | 23,568 | ## Quality - **code-review: APPROVE — mutation-verified.** Reviewer regressed the wiring (admin pass-through) and the empty-list-vs-None invariant; the guard tests FAILED on both → genuinely non-vacuous. The autouse identity-patch exercises the real wiring, not masks it. - 192 module tests pass; ruff clean; psycopg `:x::type` check clean. ## Deferrals (Step 3) confidence-penalty on EKB fallback (never triggers — all 8 admins resolve on prod); `market_metrics` elasticity (`_elasticity_coef`, separate analytics_queries path). Refs #969 #949.
bot-backend added 1 commit 2026-06-05 02:04:08 +00:00
feat(forecast): resolve admin district -> micro set in §9.x market/supply/sales filters
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m29s
Deploy / build-worker (push) Successful in 2m32s
Deploy / deploy (push) Successful in 1m7s
681a922d99
/analyze passes the official ЕКБ admin district (ekb_districts polygon, e.g.
'Кировский'), but objective_lots/corpus_room_month store informal micro-districts
('Втузгородок','ЖБИ') -> admin name matched 0 rows -> silent empty forecast.

Add resolve_objective_districts() (site_finder/district_resolver.py) mapping an
admin name to its clean micros via ekb_district_alias (note IS NULL), with
None -> EKB-wide fallback and raw-micro pass-through. Wire into the objective_lots
district filters of market_metrics (§9.2 stock+sales), supply_layers L1 (§9.3),
and sales_series Sources A+B (crm shares the micro vocab, prod-verified),
switching the scalar filter to psycopg3-safe = ANY(CAST(:districts AS text[])).
supply_layers L2/L3 keep the admin name (domrf_kn_objects.district_name is admin vocab).

Prod: Кировский/Ленинский/Орджоникидзевский obj_count 0 -> 32/64/31.
Tests mutation-verified non-vacuous. 192 module tests pass; ruff clean. Refs #969 #949.
bot-backend merged commit 681a922d99 into main 2026-06-05 02:04:10 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1054
No description provided.