feat(data): add Rentometer API adapter for real rent comps - #376
Merged
Conversation
Fixes the exact bug that lost real work on this repo's own opencode validation run today (issue #369): opencode found and fixed a genuine 47-file Python 2 except-syntax bug plus the requested feature, 815 tests passing -- then git commit failed the local commitizen commit-msg hook (no type prefix), and since the hook blocks commit creation rather than just flagging it after, there was nothing for a backstop to fix. All of that work was lost when the runner tore down. This repo's opencode.yml never had a commit-msg-hook-install step in the first place (that pattern only existed on fawkes), so there is nothing to remove here -- this PR is the model resolver and the routing test, ported from paruff/fawkes (#1630 there) after the prei validation run's failure motivated both fixes. Replaces the hardcoded model: string with a Resolve model step that verifies the preferred model against the live models.dev catalog before use and falls back (with a visible warning) to another free tool-calling model on the same provider if it has been renamed or removed. Adds tests/unit/test_opencode_routing.py, testing the real if: trigger expression and the resolver's PREFERRED= literals extracted directly from the workflow file. Verified with ruff/mypy directly (this repo's pytest.ini needs plugins not installed in this session, so ran via a standalone module load instead of pytest) -- all assertions pass, noqa: S307 added since this repo's ruff config enables that rule unlike fawkes's.
Same mistake as uFawkesDevX: copying fawkes's full opencode.yml to apply the commit-hook-removal + model-resolver fixes accidentally re-added the Terraform/TFLint pre-install steps I'd deliberately removed for this repo earlier (zero .tf files here). Caught while verifying all five repos, not by this repo's own tests -- worth checking whether a similar workflow-validation test would be a useful addition here too.
Integrates Rentometer API for actual market rent estimates by address/ZIP. Replaces HUD FMR (40%+ off actual rents) as primary rent data source. - New adapter: core/integrations/market/rentometer.py with 7-day cache - Updated screening.py _get_monthly_rent() fallback chain: Rentometer → HUD FMR → None - Added _extract_zip() helper for ZIP code extraction - Added RENTO_METER_API_KEY to Django settings - 9 unit tests + 5 E2E tests Closes #359
Fix AttributeError on _PipelineView objects that lack address/city/state attributes. Use getattr with None defaults for safe access.
| address, | ||
| city, | ||
| state, | ||
| zip_code, |
| ) | ||
| return cast(Decimal, result["median_rent"]) | ||
| except RentometerError as exc: | ||
| logger.warning("Rentometer lookup failed for %s: %s", zip_code, exc) |
6 tasks
paruff
added a commit
that referenced
this pull request
Aug 21, 2026
…377) Tier 2 Governance's Trivy scan has been failing on every main push (predates #376) on two HIGH CVEs neither traceable to app code: - msgpack 1.1.2 (GHSA-6v7p-g79w-8964): not our dependency — it's pip's own vendored copy at pip/_vendor/msgpack. - setuptools 70.3.0 (CVE-2025-47273): not installed anywhere — it's a version string in pip's _vendor/vendor.txt that Trivy's scanner parses as an installed package. pip is never invoked at runtime (entrypoint.sh only runs manage.py/ gunicorn), so strip it from the final image after the existing setuptools/wheel patch step. Also drop the now-pointless ensurepip bundled wheel, and pin msgpack==1.2.1 directly (transitive via pytest-bdd->gherkin-official, flagged separately). Verified locally: rebuilt image, Trivy --severity HIGH,CRITICAL --ignore-unfixed exits 0, and Django still boots with pip removed. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
3 tasks
paruff
added a commit
that referenced
this pull request
Aug 21, 2026
…hain (#378) * fix(screening): address code-review findings on Rentometer fallback chain Multi-agent review of #376 (Rentometer adapter) surfaced 9 issues, fixed here: - Rentometer's address-based lookup could never fire for HUD/USDA sources: _PipelineView (the adapter used for those sources) never carried address/city/state, so the whole feature silently degraded to HUD FMR for 2 of 4 property source types. _adapt_source_to_pipeline now populates them from the source model. - The DB-write cache-on-read in _get_monthly_rent assumed pipeline_property always has a `.pk`, which _PipelineView (no persisted row) doesn't have — an AttributeError there was silently swallowed, discarding a successfully fetched rent. Added a _cache_rent() helper that only writes when a pk exists. - That same DB write also silently violated screening_preview()'s documented "without saving" contract. screen_property() and the eval helpers now take a cache_rent flag; screening_preview() passes cache_rent=False. - Both `except Exception: pass` blocks in _get_monthly_rent logged nothing, making a real bug (schema drift, broken import) look identical to "no data available" (AGENTS.md rule #10). Now logged, and RentometerClient._get() classifies timeouts/5xx/malformed JSON into RentometerError instead of leaking raw requests exceptions. - _extract_zip's ZIP regex matched the first 5-digit token in an address, which could be a house number. Anchored to the end of the string instead. - rentometer.py's hand-rolled, unbounded _rent_cache dict is replaced with django.core.cache (matching walkscore.py/schools.py in the same package), fixing both the multi-worker cache-miss problem and the memory-growth issue. - _parse_rent no longer round-trips through binary float before producing a Decimal. - Fixed a stale "future lookups" docstring on the bedrooms param (it's used today, for the cache key). Added tests for the fallback chain (Rentometer success, Rentometer- fails-then-HUD-succeeds, cache_rent=False, HUD/USDA _PipelineView non-crash), the ZIP/house-number regex regression, _parse_rent edge cases, and RentometerClient._get()'s error classification. Full existing suite plus new tests: 913 passed (4 pre-existing, unrelated ATTOM live-API failures — missing test credentials). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(screening): fix NameError and CodeQL PII findings from previous fix CI on this branch caught three issues in the previous commit's fixes: - _cache_rent() referenced PipelineProperty.objects.filter(...) but PipelineProperty is only imported under `if TYPE_CHECKING:` in this module — a NameError on every real invocation, silently swallowed by the (now-logged) except block. This bug predates this branch: the original inline code had the same gap, which is exactly why the previous commit's new fallback-chain tests (the first to actually exercise a successful rent lookup) caught it. Added a local `from core.models import PipelineProperty` inside _cache_rent, matching this file's existing lazy-import convention for model access. - CodeQL flagged the new cache-key hash (MD5 over address/city/state/ zip) and the new log statements (interpolating the raw zip_code) as PII handling issues. Switched the cache key to SHA-256, and swapped the logged zip_code for pipeline_property's pk (an opaque internal id, not location data). Verified: the two previously-failing E2E tests now pass, full rentometer/screening suite (61 tests) green, ruff/mypy clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Integrates Rentometer API for actual market rent estimates by address/ZIP. Replaces HUD FMR (40%+ off actual rents) as primary rent data source.
Changes
core/integrations/market/rentometer.pywith 7-day in-memory cachescreening.py_get_monthly_rent()fallback chain: Rentometer → HUD FMR → None_extract_zip()helper for ZIP code extraction from property/addressRENTO_METER_API_KEYto Django settingsAcceptance Criteria Met
Technical Notes
Closes #359