Repository navigation
Conversation
* fix(proposals): backfill every master with a reviewed listing The criteria ratings backfill picked masters by the cached authentic_review_count or user_rating_weighted. A master whose review weight was written straight to rate.reviews keeps a stale count of 0 and was skipped, so V6 failed. The DOS.Me replay caught it. The backfill now also picks any master with a reviewed listing; the cached test stays for Item variants whose reviews sit on listings with no variant. The Docker replay zeroes the 256GB master's cached count before the first apply and checks the backfill still rates it; it fails on the old filter. Refs #1543 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1560) * feat(shared-data): cluster review pros and cons into product points Pure rules for #1546 (design #1531 section 5.1, D9), with no database access: normalise lines (diacritics kept, filler words dropped, negations joined to the next word), assign a criterion by keyword, cluster at 60% shared words, count each writer once by capped trust weight halved every 12 months, and show a point with two writers and a weight sum of 1.5 or one expert. Up to three per criterion and five per side in the summary; points silent for 18 months hide. Refs #1546 * fix(shared-data): product points review findings - Keywords match without diacritics only on a line typed without any, and words whose plain form is common ("đơ", "đo", "chờ", "êm", "cầm", "cam", "mắc") are dropped, so "Pin tụt nhanh do cập nhật" stays battery. - A keyword inside a longer match ("màn" in "màn hình") counts once. - A line that negates a word the other states never joins its cluster. - Lines outside 5..150 characters, with no words, no writer, no date or a non-finite weight are not counted. - D9 reads the exact support, not the two-decimal value. Refs #1546 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st (#1561) * fix(importer): reject used, like-new and refurbished listings at ingest (#1430) rate.products stores no condition, so a non-new listing linked to a published master (exact model_key, variant or a master hint) fed its lower price into the new device's min_price and the deal radar. - ingestProduct throws NonNewListingError (code NON_NEW_LISTING) before anything is written when the normalizer detects a non-new condition, with or without a master hint (option A of #1430, no DDL). - Trade-in offers for the buyer's old device ("nhận thu máy cũ", "thu cũ lên đời", "đổi máy cũ lấy máy mới") no longer read as used, so new listings are not dropped for them. - The error is exported from @repo/crawlers (dist smoke). * fix(importer): only a non-new title rejects a listing; 2nd Gen is new (#1430 review) - The ingest check reads the title alone. Description boilerplate such as "không bán hàng cũ" or "99% khách hàng hài lòng" would drop new listings, so a description hit still only sets needs_review. - "2nd" counts as used only in "2nd hand": "AirPods Pro 2nd Gen" and "iPhone SE 2nd generation" are new devices. - The trade-in strip also covers "thu máy cũ đổi máy mới" and "thu mua máy cũ". * fix(importer): check the sanitized title; a bare 98% is not a condition (#1430 Codex) - The normalizer sets title_condition from the sanitized title, and the ingest check reads it, so a control character inside "Máy cũ" no longer slips a used listing past the check. - A bare "98%" or "99%" (such as "Chống ồn 98%") no longer reads as like-new; a percentage counts only after máy, ngoại hình, hình thức, keng or pin, besides the existing mới, đẹp and zin. * fix(importer): "thu mua điện thoại cũ" is a trade-in offer too (#1430 Codex) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(importer): trade-in titles in any order stay new (#1430) detectProductCondition read new-device titles such as "Trợ giá lên đời máy cũ", "Lên đời máy cũ trợ giá" or "Hỗ trợ đổi máy cũ" as used, so ingest threw NON_NEW_LISTING on new listings. - The trade-in strip now takes a trade-in verb (thu, thu mua, đổi, lên đời, trợ giá, hỗ trợ) right before "(máy|điện thoại|đt) cũ", with a few filler words allowed, or "cũ" right before "lên đời" or "đổi/lấy/sang mới". - Fixtures: nine trade-in titles stay new, and five real used titles stay used. Refs #1430 * fix(importer): keep warranty swaps used; allow amounts and hyphens (#1430 review) - "Mới" followed by a number or a warranty term ("đổi mới 99%", "đổi mới trong 30 ngày") is not a trade-in, so those used listings stay used or like-new. - A bare "hỗ trợ" is no longer a trade-in verb; "hỗ trợ thu/đổi" still is. - "lại", "giá cao" and an amount ("2 triệu") may sit between the verb and the device, and a hyphen, colon or comma may separate the words. Refs #1430 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(proposals): dos-me review submission v2 rpc (p3) The DOS-Me migration P3 needs, as a proposal: rate.submit_community_review_v2 checks a Rate review under D5 in the database (criterion stars in half steps, the required criterion, at most two left out, a 20 to 300 character verdict, one to five pros and cons, up to three per criterion, no dodging con, no line twice or in both lists) and writes rating_exact, verdict, criteria_version and the review_points rows in one transaction. rate.rating_criteria holds the versioned lists. The replay test keeps the lists, the line rules and the dodge pattern equal to @repo/shared-data. v1 stays unchanged. Nothing is applied. Refs #1544 * fix(proposals): review v2 rpc review findings Two fresh-context reviews of the P3 proposal: - Lines are stored and measured in one form (NFC, no invisible characters, trimmed), on both sides, so a stored line always fits the review_points check. - Both sides strip the same invisible set: every format character, emoji variation selectors and the keycap mark. "Không có gì☺️ " was a dodge that passed in review-form.ts, and it differed from the SQL. - The SQL helpers read text under pg_c_utf8, so they do not depend on the database locale; verify V7 checks them on the target database. - Keyword rules cover criterion lines; criterion stars are stored at 0.1. - The replay test checks the RPC's star on random sets, every invisible code point, emoji and decomposed input; verify V2 and V3 cover every helper. Refs #1544 * fix(proposals): track the review v2 proposal files past .gitignore Refs #1544 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hind a flag (#1567) * feat(web): review form v2 with criteria, verdict and pros and cons behind a flag Refs #1544. The DB-free part of P3 (design #1531, D5): per-category criteria in half stars with the weighted star beside them, a 20-300 character verdict, 1-5 pros and cons, optional pros and cons per rated criterion, and a browser draft. The form and POST /api/v1/rate/reviews check a review with the same reviewV2Errors, per field. Behind NEXT_PUBLIC_RATE_REVIEW_FORM_V2=1, off by default: with the flag off the form and the API take the current path unchanged. The API reads the product's category on the server and computes the star itself; the v2 RPC does not exist yet (DOS-Me), so submitCommunityReviewV2 is a stub that never writes and the route answers 503 REVIEWS_UNAVAILABLE. * fix(web): review findings on form v2 errors, drafts and the v2 api path Refs #1544. Errors land on the line they name (blank rows are skipped in the count), the form is keyed per product so a draft never moves, stored stars outside half steps are dropped, and the pickers carry aria-required. The API refuses v1 bodies once v2 is on, keeps pros and cons on one line, checks a criterion's pros against its cons, rejects an empty criterion entry, and builds the submission in buildReviewV2Submission so a test sees the computed star. The stub takes the user's client for the real call. * fix(web): name the duplicate-line message key so gitleaks stops flagging it Refs #1544. gitleaks read `key: 'v2ErrDuplicate'` as a generic API key: the rules now use a DUPLICATE_LINE constant, and the two findings in 2f624a1 are listed in .gitleaksignore with the reason. * fix(web): keep the duplicate-line constant clear of the secret scan Refs #1544. The constant's own comment and typed declaration still read as a generic API key. The comment drops the literal and the declaration uses `as const`; the two findings in 4c05060 join .gitleaksignore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(db): mirror the p2 criteria ratings migrations from dos-me DOS/DOS.Me#1489 is applied to production (promote DOS/DOS.Me#1494, 09d264ca). Mirror its two migrations byte for byte into supabase/migrations and regenerate packages/shared-data/src/database.types.ts, so the web and the importer get types for rate.review_points, rate.product_points and the new reviews and master_products columns. Nothing is applied by this change. Refs #1543 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(importer): write product pros and cons from review lines The writer part of #1546: a job reads rate.review_points with each line's review, flag, listing and category, clusters the lines of every master with aggregateProductPoints and writes the points a page shows to rate.product_points (method 'code'). Dry run by default; --apply writes as rate_worker (SUPABASE_RATE_WORKER_KEY), inserting new rows before deleting a master's old 'code' rows. A user review counts once the analyzer included it; an expert review counts at least 1 unless the analyzer excluded it. Refs #1546 * fix(importer): product points count what the rating counts From a fresh-context review of the writer: - Lines count only on crawled listings and from crawled or community reviews, as the P2 rating does; seed, synthetic, fixture and backfill rows never show. - Only the writers' own lines (method 'writer') are read for now. - A flag with a NULL include counts, as COALESCE(include_in_rating, true) does. - The job signs in as the rate_worker Auth user (publishable key, email and password) and refuses any other role, since rate_worker has no API key. - The header documents one writer per review and the one-runner rule. Refs #1546 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(web): one rating everywhere from the stored rating_score Refs #1545 (P4 of design #1531, D3/D4/D9 approved by JOY). P2 is live, so every page and the API read master_products.rating_score: - resolveCompareEffectiveUserRating and the leaderboard's userScore5 read rating_score first, unrounded, so a page rounds once to 1 decimal (4.249 shows 4.2); the older ratings stay as the fallback. - The product page headline, catalog, home, hero search, deals, the catalog sort and the leaderboard order read the same number. - The leaderboard ranks by the rating as shown, the composite breaking ties; an unrated product with an expert score ranks last. Battle cards and rows show the rating at 1 decimal; a persona keeps its own score. - Criterion scores come from criteria_scores: 3 writers to show, 5 to rank or weigh a persona (D9); an expert score stands below that. - The API adds rating_score_5 to products, product, compare, leaderboard and versus; OpenAPI documents it. * fix(web): review findings on the one rating, versus and badges Refs #1545. The versus scoreboard and API no longer cut the rating to 2 decimals before the page rounds it, weigh personas only on criteria past the ranking threshold, and fall back to the rating, not the composite. The reviews section's buyer score is the stored rating the headline shows. The overall badge shows the rating at 1 decimal; the expert tab keeps the expert's own score and order. An expert-only product keeps its persona score. Deals price a point of the rating, and exports round like the page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.
Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
Promote dev to main.
Merge with a merge commit, never squash (Docs/Resources/RELEASE.md).
📌 TL;DR
This PR introduces the Review Submission v2 database migration (Phase P3), adding a new
submit_community_review_v2RPC with strict validation for criterion-based ratings, pros/cons, and verdicts. It also refines the criteria rating aggregation logic to cap individual review weights and fixes a bug in the product condition detector to prevent trade-in offers from misclassifying new items as used.🎯 Type of Change
🔍 Changes Walkthrough
.github/workflows/ci.ymltest-review-submission-v2-proposal.mjsscript in Docker..gitignore.gitleaksignorereview-form-v2.ts.Docs/Proposals/2026-10-31-dos-me-criteria-ratings.sqlrefresh_master_rating_extraslogic. It now usesLEAST(1.0, e.w)for the threshold check (shown_sum) to ensure one heavy review doesn't artificially pass the weight sum requirement, while keeping the storedweight_sumas the plain sum. Also improves the refresh trigger condition to check for actual reviews rather than just cached counts.Docs/Proposals/2026-10-31-dos-me-criteria-ratings.mdDocs/Proposals/2026-10-31-dos-me-criteria-ratings-verify.sqlDocs/Proposals/2026-11-01-dos-me-review-submission-v2.sqlrate.rating_criteriatable, helper functions for text normalization/validation (Vietnamese specific), and thesubmit_community_review_v2RPC. Handles criterion stars, verdicts, pros/cons, and writes torate.review_points.Docs/Proposals/2026-11-01-dos-me-review-submission-v2-rollback.sqlDocs/Proposals/2026-11-01-dos-me-review-submission-v2-verify.sqlDocs/Proposals/2026-11-01-dos-me-review-submission-v2.mdapps/importer/package.jsonproduct-pointsscript and includesproduct-points.test.tsin the test suite.apps/importer/src/shopee/__tests__/dist-exports.smoke.mjsNonNewListingErrorto the list of expected exports.apps/importer/src/shopee/__tests__/entity-matcher.test.tsdetectProductConditionto ensure trade-in offers ("thu cũ đổi mới", "trợ giá") do not misclassify new listings as used.apps/importer/src/shopee/__tests__/product-points.test.tsproduct-pointsjob, verifying weight calculation and point aggregation logic.📊 Architectural Flow
sequenceDiagram participant Client as Web/API participant DB as PostgreSQL (rate schema) participant RPC as submit_community_review_v2 Client->>RPC: POST /api/v1/rate/reviews (v2 payload) Note over RPC: SECURITY DEFINER<br/>search_path = '' RPC->>DB: Check auth (authenticated/service_role) RPC->>DB: Fetch master product & category RPC->>DB: Fetch latest rating_criteria version alt Invalid Criteria/Verdict/Points RPC-->>Client: Error (SQLSTATE 22023, DETAIL: field) end RPC->>DB: Validate criterion stars (1-5, half steps) RPC->>DB: Validate verdict (20-300 chars) RPC->>DB: Validate pros/cons (1-5 items, 5-150 chars) RPC->>DB: Check for duplicate lines (comparable form) RPC->>DB: Check for evasive cons (Vietnamese patterns) RPC->>DB: Check rate limits (5 reviews/24h) RPC->>DB: Check existing review for user/master RPC->>DB: INSERT INTO rate.reviews RPC->>DB: INSERT INTO rate.review_points (bulk) RPC->>DB: INSERT INTO rate.review_authors RPC->>DB: INSERT INTO rate.review_flags (excluded initially) RPC-->>Client: JSON Response (review_id, rating_exact, etc.)