- Add _extract_district() helper with DISTRICT_PATTERN regex (서울 only)
- collect_all() now passes RCRIT_PBLANC_DE_FROM param (30-day window) to all detail endpoints
- collect_all() skips announcements where compute_status() returns '완료'
- collect_all() stamps district on each parsed announcement before upsert
- upsert_announcement(): add district to INSERT/VALUES/ON CONFLICT UPDATE; data.setdefault('district', None)
- ANNOUNCEMENT_COLUMNS: add 'district' (closes deferred gap from Task 2 review)
- 9 new tests in realestate-lab/tests/test_collector.py (6 unit + 3 integration)
- Full suite: 22 passed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- mark_matches_notified: pass tuple(match_ids) to conn.execute for consistency
- get_unnotified_matches: add a.status to SELECT so notifier/formatter can skip stale '완료' matches
- add regression test: test_get_unnotified_matches_includes_status
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace deprecated mktemp with mkstemp to eliminate TOCTOU race, narrow
OSError catches to PermissionError (Windows SQLite lock intent only), and
add a deferred-import comment for clarity.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>