V10.403 widen retryable PChome revalidation
All checks were successful
CD Pipeline / deploy (push) Successful in 1m5s

This commit is contained in:
OoO
2026-05-24 12:54:00 +08:00
committed by AiderHeal Bot
parent 56f787351a
commit b2dbf98c3b
4 changed files with 29 additions and 7 deletions

View File

@@ -325,7 +325,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
# ==========================================
# 系統版本與路徑
# ==========================================
SYSTEM_VERSION = "V10.402"
SYSTEM_VERSION = "V10.403"
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
public_url = PUBLIC_URL # 用於模板顯示

View File

@@ -13,6 +13,7 @@
## 📅 詳細更新日誌 (考古存檔)
### 2026-05-24PChome 近門檻身份回收第二輪
- **V10.403 近門檻候選重驗擴池**: production 最新 72h attempt audit 顯示 7853 筆近門檻/被擋候選中,有 105 筆可被現行 matcher 回收,其中 46 筆已達 `price_alert_exact`、59 筆只進 `identity_review``CompetitorPriceFeeder._fetch_retryable_candidate_skus()` 擴大每日 revalidation 候選池,納入 `true_low_confidence``unit_comparable``refresh_unit_comparable` 與高分 `identity_veto`;但仍要求 PChome product_id、`best_match_score >= 0.70`,且正式寫入前必須由現行 matcher 重判、通過 hard-veto 與既有配對保護。
- **V10.402 catalog variant identity-review 回收**: marketplace matcher 新增 Johnsons 嬰兒潤膚乳 catalog 對同香型、IM MEME 涼感定妝噴霧、SO NATURAL FIXX 定妝噴霧三條 review-only focused identity讓同品線 catalog / variant 候選可脫離 `true_low_confidence` 但只進 `identity_review`,不直接價格告警;同版明確保留 MUJI 品牌缺漏護手霜等 brandless catalog 案例在低信心,避免品牌缺漏與多款任選同時存在時被過度救回。
- **V10.401 focused identity 邊界整理**: 將 Laundrin TOKYO 車用夾式消臭芳香劑判定抽成 `_has_laundrin_tokyo_car_freshener_alignment()`,並在 variant descriptor guard 中豁免同一條強身份線,避免 TOKYO / 車用 / 芳香劑語序差異造成誤擋。Yuskin 經典乳霜 30g 6 入組改用 `_has_exact_count_alignment()` 判斷包數,保留 6入 vs 6盒這類同數量但不同容器字詞的人工覆核路徑。
- **V10.400 氣墊粉餅補充蕊包數正規化**: marketplace matcher 針對氣墊粉餅新增保守的 `cushion_refill_pack_alignment`,只在一側明確為 `一盒兩蕊 / 2蕊`、另一側為單規格 `15g x2` 這類乘數包裝時,解除 `multi_component_conflict` 並進 `identity_review`。CLIO 羽緻無限緞光氣墊粉餅「一盒兩蕊」可被同款覆核;`2盒4蕊``15g x2` 仍維持 hard veto。同版補香氛蠟燭、TOKYO 車用消臭芳香劑、融蠟燈與有機護膚油 search identity anchors。離線 audit 759 筆 accepted 從 753 提升到 754剩餘 5 筆 fresh veto 皆為應擋的套組/品類差異。

View File

@@ -1006,12 +1006,12 @@ class CompetitorPriceFeeder:
def _fetch_retryable_candidate_skus(self, limit: int = 80, min_score: float = 0.70) -> list:
"""
取得近門檻且非 hard veto 的候選,供 matcher 升級後重新評分。
取得近門檻候選,供 matcher 升級後重新評分。
這條路徑不重新搜尋,只用前次留下的 PChome product_id 批次查詢最新商品資料,
適合把舊 scorer 卡在 0.70~0.759 的真同款重新推進正式比價。
僅重跑明顯仍在 exact identity 軌道內、具回收價值的候選;
真正低信心與 hard veto 不再反覆空轉
僅重跑明顯有回收價值的候選;最後仍由現行 matcher 重新判斷,
不因舊 attempt_status 自動寫入正式比價
"""
if self.engine is None:
raise RuntimeError("需要注入 SQLAlchemy engine")
@@ -1064,11 +1064,22 @@ class CompetitorPriceFeeder:
AND COALESCE(cp.tags, '[]'::jsonb) ? 'identity_v2'
WHERE lm.rn = 1
AND cp.sku IS NULL
AND la.attempt_status IN ('low_score', 'refresh_low_score', 'recoverable_low_score')
AND la.attempt_status IN (
'low_score',
'refresh_low_score',
'recoverable_low_score',
'true_low_confidence',
'unit_comparable',
'refresh_unit_comparable',
'identity_veto'
)
AND la.best_competitor_product_id IS NOT NULL
AND la.best_competitor_product_id <> ''
AND COALESCE(la.best_match_score, 0) >= :min_score
AND COALESCE(la.hard_veto, false) = false
AND (
COALESCE(la.hard_veto, false) = false
OR la.attempt_status = 'identity_veto'
)
ORDER BY la.best_match_score DESC NULLS LAST, lm.momo_price DESC NULLS LAST, lm.sku
LIMIT :limit
""")

View File

@@ -73,7 +73,17 @@ def test_competitor_feeder_persists_all_match_attempt_outcomes():
retryable_source = source.split("def _fetch_retryable_candidate_skus", 1)[1].split(
"def _fetch_expired_identity_skus", 1
)[0]
assert "la.attempt_status IN ('low_score', 'refresh_low_score', 'recoverable_low_score')" in retryable_source
for status in (
"'low_score'",
"'refresh_low_score'",
"'recoverable_low_score'",
"'true_low_confidence'",
"'unit_comparable'",
"'refresh_unit_comparable'",
"'identity_veto'",
):
assert status in retryable_source
assert "OR la.attempt_status = 'identity_veto'" in retryable_source
latest_attempt_source = retryable_source.split("latest_attempt AS", 1)[1].split(
"SELECT\n lm.product_id", 1
)[0]