diff --git a/app/verify/common.py b/app/verify/common.py index 82f3c14..8921245 100644 --- a/app/verify/common.py +++ b/app/verify/common.py @@ -10,6 +10,7 @@ import hashlib import json +import re import sys from collections.abc import Iterable from pathlib import Path @@ -30,6 +31,7 @@ ) VERIFY_DIR = DATA_DIR / "_verify" +_RAW_CHIPSET_YEAR = re.compile(r"^[^,]+,\s*((?:19|20)\d{2})\s*,") LEDGER_PATH = VERIFY_DIR / "ledger.jsonl" # git-tracked: promotion decisions only STATE_DIR = VERIFY_DIR / "state" # gitignored caches SCORES_PATH = STATE_DIR / "scores.jsonl" # full Tier 0 results (cheap to recompute) @@ -95,7 +97,10 @@ def foreign_key_sets( """Build FK lookups the way ``app.validate`` does, plus a SoC release-date map. Returns ``(brand_slugs, soc_slugs, soc_release_date)`` where ``soc_release_date`` - maps a SoC slug to its ISO release date (used for "chip can't postdate device"). + maps a SoC slug to its best available ISO release date (used for "chip can't + postdate device"). A structured year in ``raw_chipset`` takes precedence + when the normalized January 1 placeholder is later. The raw import often + records the chip's year while the normalized date is several years late. """ brand_slugs = {r.slug for r in records.get("brand", []) if r.slug} soc_slugs = {r.slug for r in records.get("soc", []) if r.slug} @@ -103,6 +108,11 @@ def foreign_key_sets( for r in records.get("soc", []): rd = r.data.get("release_date") if r.slug and isinstance(rd, str): + raw = r.data.get("raw_chipset") + if rd.endswith("-01-01") and isinstance(raw, str): + match = _RAW_CHIPSET_YEAR.search(raw) + if match and match.group(1) < rd[:4]: + rd = f"{match.group(1)}-01-01" soc_release[r.slug] = rd return brand_slugs, soc_slugs, soc_release diff --git a/tests/verify/test_common_soc_dates.py b/tests/verify/test_common_soc_dates.py new file mode 100644 index 0000000..039a411 --- /dev/null +++ b/tests/verify/test_common_soc_dates.py @@ -0,0 +1,44 @@ +"""Use a source chip year when a normalized SoC date is a later placeholder.""" + +from app.verify import offline +from app.verify.common import Record, foreign_key_sets + + +def _release_for(release_date: str, raw_chipset: str | None) -> str: + soc = Record("soc", "soc/chip-x.json", { + "slug": "chip-x", "release_date": release_date, "raw_chipset": raw_chipset, + }) + return foreign_key_sets({"soc": [soc]})[2]["chip-x"] + + +def test_earlier_structured_chip_year_corrects_late_placeholder(): + assert _release_for( + "2025-01-01", "Qualcomm Snapdragon 680 SM6225, 2021, 64 bit, octa-core" + ) == "2021-01-01" + + phone = Record("smartphone", "smartphone/phone-x.json", { + "slug": "phone-x", "soc": "chip-x", "release_date": "2022-08-01", + "source_urls": ["https://www.qualcomm.com/products/mobile/snapdragon"], + }) + before = offline.score_record(phone, 2026, {"chip-x": "2025-01-01"}) + after = offline.score_record(phone, 2026, {"chip-x": "2021-01-01"}) + assert "soc_not_after_device" in before.flags + assert "soc_not_after_device" not in after.flags + + +def test_precise_or_unstructured_dates_keep_the_normalized_date(): + assert _release_for("2024-05-07", "Chip X, 2021, 8 cores") == "2024-05-07" + assert _release_for("2025-01-01", "Chip X with 2021 revision") == "2025-01-01" + assert _release_for("2025-01-01", None) == "2025-01-01" + assert _release_for("2025-01-01", "Chip X, 2026, 8 cores") == "2025-01-01" + + +def test_raw_chip_year_still_flags_a_genuine_era_mismatch(): + release = _release_for( + "2024-01-01", "Qualcomm Snapdragon 8s Gen 3 SM8635, 2024, 8 cores" + ) + phone = Record("smartphone", "smartphone/phone-x.json", { + "slug": "phone-x", "soc": "chip-x", "release_date": "2015-01-09", + }) + score = offline.score_record(phone, 2026, {"chip-x": release}) + assert "soc_not_after_device" in score.flags