Tài liệu này tổng hợp đầy đủ User-Level Hard Rules (C:\Users\JOY\AGENTS.md, C:\Users\JOY\.claude\CLAUDE.md) và Workspace Rules dành cho mọi AI Coding Agents (Antigravity, Claude Code, OpenAI Codex, Cursor, Windsurf, ZCode, v.v.) khi làm việc trên Rate Platform (rate.vn).
📌 Session Product Owner (PO): nếu session là PO (tiêu đề có "Product Owner", hoặc JOY giao làm PO của Rate Core hay Rate Services), việc ĐẦU TIÊN là đọc và làm theo toàn bộ skill
.claude/skills/product-owner/SKILL.md, trước mọi thao tác khác. Chi tiết ở Mục 6.
-
CẤM TUYỆT ĐỐI chạy Migration / DDL trực tiếp lên Shared Prod Supabase (
gulptwduchsjcsbndmua) từ BẤT KỲ repo nào:- Project Supabase
dos(prod ref:gulptwduchsjcsbndmua) được dùng chung bởiDOS-Me,DOS-AI,DOSafe,Bexly,An-Nhan, vàRate. - CHỈ CÓ
DOS-Me/supabase/migrations/(D:\Projects\DOS-Me) là sổ cái migration (migration ledger) và đường deploy CI duy nhất (quapreview -> beta -> prod) cho mọi schema (public,dosai,dosafe,bexly,nhan,rate). - TUYỆT ĐỐI KHÔNG chạy DDL (
CREATE,ALTER,DROP,GRANT,REVOKE) lêngulptwduchsjcsbndmuaqua Supabase MCP (apply_migration,execute_sql), Dashboard SQL Editor, hoặcsupabase db pushtừ repoRate. Chỉ được phép chạySELECT(read-only) qua MCP. - Khi cần thay đổi schema
rate: Viết file migration idempotent (CREATE ... IF NOT EXISTS,ADD COLUMN IF NOT EXISTS,DROP POLICY IF EXISTStrướcCREATE POLICY,DO $$ ... $$), xin phép JOY để tạo PR bênDOS-Me/supabase/migrations/, test/deploy trên beta trước rồi mới qua prod. (Bản copy trongDOS/Rate/supabase/migrations/chỉ mang tính tham chiếu mã nguồn mở Open-Core, không dùng để push thẳng lêngulptwduchsjcsbndmua).
- Project Supabase
-
JOY KHÔNG CODE, KHÔNG CHẠY LỆNH, VÀ KHÔNG MERGE PR:
- Không bao giờ đưa lệnh terminal, bash/PowerShell snippet hay code bảo JOY tự chạy hoặc tự dán. Agent phải tự chạy tất cả.
- Không bao giờ bảo JOY tự review code diff hay bấm nút Merge PR ("chờ mày merge"). Agent phải chạy code review (
superpowers:code-reviewer/ subagent fresh-context review), sửa hết lỗi, đợi CI xanh và tự động merge PR (gh pr merge). - Chỉ hỏi ý kiến JOY cho: quyết định sản phẩm/kiến trúc, thao tác rủi ro cao (xóa dữ liệu, thay đổi prod, tiêu tiền, sửa khác repo
cross-repo writes), hoặc bước bắt buộc cần người thật (2FA, CAPTCHA, OAuth device code). - PR promote
dev->main(deploy production) cũng do agent tự merge. JOY không phải coder, không biết merge và không bấm nút Merge cho bất kỳ PR nào, kể cả PR promote. Promote theo đợt, không hỏi JOY mỗi lần: agent cứ làm task liên tục, không kết thúc task bằng câu hỏi "deploy lên production nhé?". Agent tự mở và merge PR promote khi gặp một trong các mốc: hết backlog;devdồn từ 10 PR chưa promote trở lên; thay đổi cũ nhất chưa promote đã quá 24 giờ; hoặc agent kết thúc một phiên làm việc dài. Chỉ promote khi CI củadevhead xanh và không có PR nào đang sửa dở một lỗi đã lên production. Merge bằng merge commit (gh pr merge <N> --merge, không squash/rebase), rồi tự kiểm tra bản live theoDocs/Resources/RELEASE.md. Không bao giờ viết "chờ JOY merge", "JOY duyệt merge" hay "JOY merge bằng merge commit". Vẫn phải hỏi JOY trước những việc ngoài một lần promote thông thường (migration DOS-Me, sửa dữ liệu production, đổi credential).
-
Ngôn ngữ & Định dạng Giao tiếp:
- Trả lời trực tiếp JOY (Private / Direct Chat): Luôn dùng Tiếng Việt có dấu đầy đủ 100% trên bề mặt giao tiếp trực tiếp với JOY (chat, câu hỏi
ask_question, nhãn lựa chọn). Giữ nguyên thuật ngữ kỹ thuật thông dụng bằng tiếng Anh (API,commit,branch,PR,CI,build,deploy,repo,merge,push,workflow,token,key,env,prod,staging). - Toàn bộ bề mặt Public trên GitHub & trong Repo (Issues, PRs, Comments, Code, Commits, Docs) = 100% Tiếng Anh:
- Vì
DOS/Ratelà kho mã nguồn mở công khai (Open-Core) hướng tới cộng đồng quốc tế (vi,en,cs), BẮT BUỘC viết 100% bằng Tiếng Anh cho: GitHub Issues (Title, Body, Comments), GitHub Pull Requests (Title, Body, Review comments), Commit messages, Code & Code comments, Tests, và các tài liệu chuẩn (README.md,ROADMAP.md,CHANGELOG.md,CONTRIBUTING.md,SECURITY.md,DESIGN.md). Không bao giờ tạo Issue, PR hoặc comment bằng tiếng Việt trên GitHub.
- Vì
- Tài liệu đưa cho JOY đọc/review (Proposal, Plan, Report, Audit) = HTML + Dark Theme + Tiếng Việt có dấu:
- Mọi tài liệu cần JOY đọc để ra quyết định BẮT BUỘC phải xuất thành file HTML tự chứa (self-contained) lưu ngay trong repo (ví dụ
Docs/Proposals/<YYYY-MM-DD>-<slug>.html), có Dark Theme gốc (<meta name="color-scheme" content="dark">, nền tối~#0f1113, chữ sáng, điểm nhấn đỏ#FF2E29), viết bằng Tiếng Việt có dấu đầy đủ. Không đưa file.mdthô hoặc trang nền sáng cho JOY đọc.
- Mọi tài liệu cần JOY đọc để ra quyết định BẮT BUỘC phải xuất thành file HTML tự chứa (self-contained) lưu ngay trong repo (ví dụ
- Cấm dùng dấu gạch ngang dài (No em-dashes): Không bao giờ dùng
—(U+2014),–(U+2013), hoặc—. Luôn dùng dấu gạch nối đơn-.
- Trả lời trực tiếp JOY (Private / Direct Chat): Luôn dùng Tiếng Việt có dấu đầy đủ 100% trên bề mặt giao tiếp trực tiếp với JOY (chat, câu hỏi
-
Trung thực tuyệt đối (Never Lie / Evidence-Based):
- Chỉ khẳng định khi có bằng chứng trực tiếp (log, output lệnh, dòng code, kết quả truy vấn). Nếu suy đoán phải ghi rõ là giả thuyết kèm lý do và cách kiểm chứng.
-
Cách ly Worktree & Bảo vệ Cross-Repo:
- Không tự ý sửa repo khác ngoài workspace hiện tại khi chưa được JOY đồng ý.
- Khi làm việc đa nhánh/đa repo, tạo worktree riêng theo runtime (
<repo>\.claude\worktrees\<task>,<repo>\.codex\worktrees\<task>,<repo>\.gemini\worktrees\<task>). Không bao giờ chạygit checkout/git reset --hardtrên nhánh chính đang dùng chung. - Mọi deliverable (báo cáo HTML, proposal, script) phải lưu trong repo và commit, không vứt ở thư mục tạm (
C:\Temp, scratchpad).
-
CẤM deploy thẳng lên Production (
rate.vn). Production chỉ build từ nhánhmainqua Vercel Git integration:- Luồng chuẩn (giống
DOS.AIvàDOS.Me): PR tính năng ->dev(squash); PR promotedev->mainmở từ chính nhánhdevvà merge bằng merge commit (gh pr merge --merge), không bao giờ squash hay rebase. Hotfix: nhánhhotfix/*->maincó labelemergency-hotfix, rồi back-merge ngaymain->devbằng merge commit. Chi tiết:Docs/Resources/RELEASE.md. - TUYỆT ĐỐI KHÔNG chạy
vercel deploy --prod,vercel --prod,--prebuilt --prod,--skip-domainrồipromote, hay promote một bản Preview củadevlên production, kể cả khi JOY đã cho phép "deploy". Lời cho phép deploy nghĩa là merge PR promotedev->main, không phải deploy từ máy local. - Chốt kỹ thuật:
scripts/vercel-production-guard.mjs(chạy trongbuildCommandcủavercel.json) làm build production thất bại nếu không phải GitHub build từDOS/Rate@main; workflowValidate PR Basechặn PR vàomainkhông từdev; workflowBranch Divergencebáo lỗi khimaincó commit màdevkhông có. Không được sửa hay vô hiệu hóa các chốt này để deploy cho nhanh. - Ngoại lệ duy nhất: rollback về một bản production cũ đã build từ Git (
vercel rollback), vì không build lại. Sau đó sửa tiếp qua PR hotfix. - Script vận hành có sẵn trong repo (
scripts/ops/, dùng thay cho lệnh gõ tay):node scripts/ops/merge-when-green.mjs <pr>: chờ commit head xanh rồi merge, ghim theo SHA head. Xanh nghĩa là mọi check run và mọi commit status (Vercel) đều đạt, và các check mà ruleset bắt buộc đã báo kết quả. PR vàomainluôn dùng merge commit, PR khác mặc định squash.--ignore "<check>"chỉ dùng khi một check không bắt buộc đang hỏng có lý do đã ghi trong PR.node scripts/ops/promote.mjs: mở hoặc dùng lại PR promotedev->main, liệt kê các PR được phát hành, merge bằng merge commit khi CI xanh.node scripts/ops/verify-live.mjs --wait 900: kiểm tra rate.vn chạy đúng commit củamain(/api/healthtrảcommit), database đọc được và các route chính trả 200. Script đọc lạimainmỗi vòng chờ. Chỉ khi bản live chậm hơnmain, nó mới in lệnhvercel promote <deployment của main> --scope metados; nếu bản live đi trước hoặc lệch nhánh so vớimain, nó dặn không làm gì. Không bao giờ redeploy hay promote một deployment build từ commit khác (promotekhông build lại, và bật lại tự gán domain sau một lầnvercel rollback).node scripts/ops/board.mjs <issue> --status in-progress|in-review|done --agent <Nick>: cập nhật Project #9 và nhãn (xem mục 1). Script từ chối issue đang mang nhãnagent:*của agent khác;--take-overchỉ dùng khi agent đó đã bàn giao hoặc JOY chỉ định.
- Luồng chuẩn (giống
-
Chủ động thực thi liên tục & đề xuất việc tiếp theo (Always-On Proactive Backlog - Skill
proactive-backlog):- Luôn kích hoạt mặc định ở MỌI lượt hội thoại (không chỉ trong
/goal): Mọi Agent (Antigravity, Claude Code, Codex) phải luôn tuân theo quy trình khép kín của skillproactive-backlog(~/.gemini/config/skills/proactive-backlog/SKILL.md,~/.claude/skills/proactive-backlog/SKILL.md,~/.codex/skills/proactive-backlog/SKILL.md). - Ngay khi hoàn thành một task (hoặc khi được gọi dậy), tự động quét GitHub Issues (
gh issue list) và codebase theo chuyên môn (agent:web,agent:core,agent:crawl,agent:guard,agent:brand), tự tạo Issue Tiếng Anh nếu cần, claim quanode scripts/ops/board.mjs <issue> --status in-progress --agent <Nick>, cài đặt + viết unit test, chạy fresh-context review, tự merge PR quanode scripts/ops/merge-when-green.mjs <pr>, đóng Issue (--status done), và chuyển ngay sang task tiếp theo mà KHÔNG dừng lại hỏiBắt đầu chứ?hayLàm tiếp nhé?. - Chỉ dừng lại báo cáo tổng kết khi toàn bộ backlog khả dụng đã sạch hoàn toàn, gặp thao tác rủi ro cao bắt buộc hỏi JOY (Mục 0.1, 0.2), hoặc khi JOY chủ động yêu cầu dừng.
- Luôn kích hoạt mặc định ở MỌI lượt hội thoại (không chỉ trong
Bảng điều phối trung tâm: https://github.com/orgs/DOS/projects/9
Lộ trình chuẩn: Docs/Resources/ROADMAP.md
Trước khi viết bất kỳ dòng code nào, Agent phải kiểm tra danh sách Issue trên cả 2 repo:
# Xem danh sách Issue đang mở
gh issue list -R DOS/Rate --state open
gh issue list -R DOS/Rate-Services --state open-
Quy tắc Định danh Agent (Agent Nickname) & Tránh trùng lặp:
- Vì mọi Agent đều chạy dưới tài khoản GitHub của JOY (
@me), MỖI AGENT PHẢI TỰ ĐẶT MỘT NICKNAME NGẮN GỌN theo chuyên môn hoặc phiên làm việc (ví dụ:Crawl,Web,Core,DB,QA) và gắn cả Nhãnagent:<nickname>lẫn CộtAgenttrên GitHub Project #9. - TUYỆT ĐỐI KHÔNG tự ý làm các Issue đang có nhãn
status:in-progress,status:in-reviewhoặc đã có nhãnagent:<khác>đang chạy (trừ khi JOY chỉ định rõ). - Issue có nhãn
incidentlà ưu tiên số 1, trên mọi việc khác: chúng do.github/workflows/incident-report.ymltự mở khi CI đỏ trêndev/main(DOS/Rate-Services có workflow tương tự cho crawler theo lịch), hoặc do Upptime mở trongDOS/statuskhi rate.vn sập. Nhận issue, tìm thay đổi gây lỗi, sửa tiếp (fix forward). Issue tự đóng khi mọi job đã lỗi chạy xanh lại (job bị bỏ qua,skipped, không tính là đã hồi phục). - Sau đó ưu tiên chọn các Issue đang có nhãn
status:ready. - Nếu yêu cầu của người dùng chưa có Issue tương ứng, TẠO NGAY ISSUE MỚI BẰNG TIẾNG ANH và gắn vào GitHub Project #9:
$agentNick = "Crawl" # Đặt nickname riêng của Agent (vd: Crawl, Web, Core...) $agentLabel = "agent:$($agentNick.ToLower())" gh label create $agentLabel -R DOS/Rate --color "D93F0B" --description "Claimed by Agent: $agentNick" --force gh issue create -R DOS/Rate --title "<English task title>" --body "<Detailed English description>" --label "status:in-progress,$agentLabel" --assignee "@me" gh project item-add 9 --owner DOS --url <ISSUE_URL>
- Vì mọi Agent đều chạy dưới tài khoản GitHub của JOY (
-
Chuyển trạng thái sang
In Progress& Ghi danh Agent ngay khi bắt đầu (BẮT BUỘC đồng bộ cả Issue lẫn Board Project #9, comment bằng Tiếng Anh):Cách nhanh, một lệnh làm cả nhãn lẫn board (tự thêm issue vào Project #9 nếu chưa có, chỉ giữ một nhãn
status:*):node scripts/ops/board.mjs <ISSUE_NUMBER> --status in-progress --agent $agentNick. Các trạng thái khác:ready,in-review,done,backlog. Các lệnhghdưới đây là cách làm tương đương bằng tay.$agentNick = "Crawl" # Nickname của Agent hiện tại $agentLabel = "agent:$($agentNick.ToLower())" gh label create $agentLabel -R DOS/Rate --color "D93F0B" --description "Claimed by Agent: $agentNick" --force # 1. Cập nhật nhãn Issue (status:in-progress + agent:<nick>) & comment ghi danh bằng Tiếng Anh gh issue edit <ISSUE_NUMBER> -R DOS/Rate --remove-label "status:ready" --add-label "status:in-progress,$agentLabel" --add-assignee "@me" gh issue comment <ISSUE_NUMBER> -R DOS/Rate --body "🤖 **[Agent: $agentNick]** Claimed this issue (Status: Ready -> In Progress)." # 2. BẮT BUỘC cập nhật cột Status VÀ trường Agent trên bảng GitHub Project #9 # Project ID: PVT_kwDOA388Vc4Bm5Ml | Field Status: PVTSSF_lADOA388Vc4Bm5MlzhlgSt8 | Field Agent: PVTF_lADOA388Vc4Bm5MlzhlqBH8 # Status Option IDs: Backlog=f75ad846 | Ready=e18bf179 | In progress=47fc9ee4 | In review=aba860b9 | Done=98236657 # Tra item từ phía issue: `gh project item-list` mặc định chỉ trả 30 trong hơn 300 item của Project #9 nên không thấy issue mới (`$itemId` rỗng, cập nhật board thất bại âm thầm). $itemId = gh api graphql -F n=<ISSUE_NUMBER> -f query='query($n: Int!) { repository(owner: "DOS", name: "Rate") { issue(number: $n) { projectItems(first: 10) { nodes { id project { number } } } } } }' --jq '.data.repository.issue.projectItems.nodes[] | select(.project.number == 9) | .id' gh project item-edit --project-id PVT_kwDOA388Vc4Bm5Ml --id $itemId --field-id PVTSSF_lADOA388Vc4Bm5MlzhlgSt8 --single-select-option-id 47fc9ee4 gh project item-edit --project-id PVT_kwDOA388Vc4Bm5Ml --id $itemId --field-id PVTF_lADOA388Vc4Bm5MlzhlqBH8 --text $agentNick
-
Check bắt buộc
task-claim: rulesetdev-task-claimchặn merge PR vàodevcho tới khi mỗi issue mà PR sẽ đóng (từ khóaCloses/Fixes/Resolves #Nhoặc liên kết thủ công) có nhãnagent:<nick>vàstatus:in-progresshoặcstatus:in-review. PR của Dependabot được miễn; PR không đóng issue nào thì pass. Khi issue được thêm hoặc gỡ nhãnagent:*/status:*, check của các PR liên quan tự chạy lại; nếu không thấy chạy lại thì push/sửa mô tả PR hoặc chạygh run rerun <run-id> -R DOS/Rate. Nguồn:.github/workflows/task-claim.yml,.github/workflows/task-claim-revalidate.yml,scripts/task-claim-check.mjs.
Sau khi code xong, chạy pass toàn bộ bài test/build và qua bước review:
- Trường hợp đang mở PR chờ CI / Reviewer tự động (
In Review):gh issue edit <ISSUE_NUMBER> -R DOS/Rate --remove-label "status:in-progress" --add-label "status:in-review" gh issue comment <ISSUE_NUMBER> -R DOS/Rate --body "🔍 **[Agent: $agentNick]** Implementation complete and tests passing. Moving status to In Review (Commit/PR: <SHA/URL>)." $itemId = gh api graphql -F n=<ISSUE_NUMBER> -f query='query($n: Int!) { repository(owner: "DOS", name: "Rate") { issue(number: $n) { projectItems(first: 10) { nodes { id project { number } } } } } }' --jq '.data.repository.issue.projectItems.nodes[] | select(.project.number == 9) | .id' gh project item-edit --project-id PVT_kwDOA388Vc4Bm5Ml --id $itemId --field-id PVTSSF_lADOA388Vc4Bm5MlzhlgSt8 --single-select-option-id aba860b9
- Trường hợp đã hoàn tất & merge xong (
Done):gh issue edit <ISSUE_NUMBER> -R DOS/Rate --remove-label "status:in-progress,status:in-review" --add-label "status:done" gh issue close <ISSUE_NUMBER> -R DOS/Rate --comment "✅ **[Agent: $agentNick]** Completed in commit <SHA> (Status -> Done)." $itemId = gh api graphql -F n=<ISSUE_NUMBER> -f query='query($n: Int!) { repository(owner: "DOS", name: "Rate") { issue(number: $n) { projectItems(first: 10) { nodes { id project { number } } } } } }' --jq '.data.repository.issue.projectItems.nodes[] | select(.project.number == 9) | .id' gh project item-edit --project-id PVT_kwDOA388Vc4Bm5Ml --id $itemId --field-id PVTSSF_lADOA388Vc4Bm5MlzhlgSt8 --single-select-option-id 98236657
Hệ thống Rate được tách thành 2 repositories riêng biệt (và dùng chung DB với DOS/DOS.Me):
| Repository | Độ riêng tư | Đường dẫn Local | Những gì ĐƯỢC PHÉP đặt tại đây |
|---|---|---|---|
DOS/Rate |
🌍 Public (Open-Core) | D:\Projects\Rate |
• apps/web: Giao diện Next.js 16.3.8 (rate.vn), i18n (vi, en, cs), Server Data Layer (src/server/rate/) & REST API v1 (src/app/api/v1/rate/)• apps/extension: Giao diện Browser Extension MV3 minh bạch• packages/shared-data: Zod Schema 10 nhóm thông số (specs.schema.ts)• apps/importer: Bộ não chuẩn hóa & chấm điểm công khai (types.ts, product-normalizer.ts, entity-matcher.ts, ai-spec-enricher.ts, ai-review-analyzer.ts, shopee-to-supabase.ts)• supabase/migrations: Bản sao tham chiếu schema rate cho Open-Core (KHÔNG chạy db push hay MCP apply_migration từ đây) |
DOS/Rate-Services |
🔒 Private (Enterprise) | D:\Projects\Rate-Services |
• Anti-Detect Scrapers: shopee-scraper.ts, shopee-search-scraper.ts, sniff-search-api.ts• Bypass & Proxy: shopee-captcha-solver.ts (giải Captcha), proxy-manager.ts (mproxy.vn)• Queue Workers: queue-worker.ts, crawl-smartphones-with-proxy.ts• GitHub Actions Cron: .github/workflows/scheduled-crawler.yml |
DOS/DOS.Me |
🔒 Sole DB Authority | D:\Projects\DOS-Me |
• supabase/migrations/: Nơi DUY NHẤT được phép chứa migration chính thức và chạy CI deploy (preview -> beta -> prod) lên Supabase gulptwduchsjcsbndmua. |
⚠️ CẤM TUYỆT ĐỐI: Không bao giờ commit code giải Captcha, xoay Proxy, sniff API nội bộ của sàn, hoặc khoá bí mật (SUPABASE_SECRET_KEY,AI_API_KEY,MPROXY_*) vàoDOS/Rate.
🔗 Engine dùng chung:
DOS/Rate-Serviceslấy@repo/crawlers(apps/importer) và@repo/shared-data(packages/shared-data) từ repo này qua git submodulevendor/rate(pnpm workspace). Module mới cần dùng bên đó thì thêm subpath vàoexportscủaapps/importer/package.jsonvà vàotest:dist.
- Bỏ hoàn toàn Strapi CMS & Splink Python: Không sử dụng hay khởi tạo lại các thành phần Strapi cũ.
- Chuẩn Ngôn Ngữ & Công Cụ (Ecosystem Standard 2026):
- TypeScript
^7.0.2(strict: true,ignoreBuildErrors: false), Node.js >= 22 (v26 LTS), pnpm10.x, Turborepo^2.10.12.
- TypeScript
- Kiến Trúc 4 Tầng Backend (4-Layer Composable Backend Architecture):
- Layer 1 - Web BFF & REST API v1 (
apps/web):- Server Data Layer (
apps/web/src/server/rate/): Tầng truy vấn Server-only bọcReact.cache()chống trùng lặp request giữagenerateMetadata()và React Server Components (page.tsx). - JSON REST API v1 (
apps/web/src/app/api/v1/rate/*&/api/reviews/[id]/vote): Cung cấp REST API chuẩn (GET /api/v1/rate/products,GET /api/v1/rate/products/[slug],POST /api/reviews/[id]/vote) phục vụ cả Web Client islands lẫn Browser Extension Manifest V3.
- Server Data Layer (
- Layer 2 - Open-Core Intelligence & Normalization Service (
apps/importer+packages/shared-data):packages/shared-data/src/schemas/specs.schema.ts: Chuẩn 10 Field Groups bằng Zod (^3.25.76), kết hợp cấu trúc sạch của PhoneArena (tách riêngmain_camera,second_camera,third_camera,fourth_camera,front_camera) và độ sâu kỹ thuật của GSMArena.apps/importer/src/shopee/*:ProductNormalizer,EntityMatcher(Dedupe 3 tầng:model_key->pg_trgm-> LLM),AiSpecEnricher,AiReviewAnalyzer,ShopeeToSupabasePipeline.- AI Provider-Agnostic: Hỗ trợ chuẩn OpenAI-compatible (
dos-aigatewayapi.dos.ai/ vLLM Qwen,openai,gemini,deepseek,groq,openrouter,ollama) quaAI_PROVIDER,AI_API_KEY,AI_BASE_URL,AI_MODEL.
- Layer 3 - Private Anti-Detect Scraper & Queue Worker Service (
DOS/Rate-Services):- Playwright Stealth, xoay IP
mproxy.vn, giải Slider Captcha, vàqueue-worker.tsxử lý hàng đợi bất đồng bộ qua cơ chế khóa nguyên tử PostgreSQLFOR UPDATE SKIP LOCKED.
- Playwright Stealth, xoay IP
- Layer 4 - Database, Atomic Queue & In-DB Trigger Engine (
Supabase Cloud PostgreSQL 17-rateschema):rate.master_products: Sản phẩm gốc chuẩn hóa (model_keyduy nhất,specificationsJSONB 10 nhóm,key_specs).rate.products: Gian hàng/Listing từ các sàn liên kết quacluster_id.rate.price_history: Lịch sử giá chống trùng theoobservation_id.rate.reviews,rate.review_flags,rate.review_votes: Đánh giá người dùng, phân tích seeding bằng AI, bình chọn/báo cáo theo từng người dùng, và triggerSECURITY DEFINERtự động tính điểm.
- Layer 1 - Web BFF & REST API v1 (
# Tại D:\Projects\Rate (Monorepo dùng pnpm + TypeScript 7.0.2)
pnpm --filter @repo/shared-data build
pnpm --filter @repo/crawlers build
pnpm --filter @repo/crawlers exec tsx src/shopee/test-ai-enricher.ts
pnpm --filter @repo/crawlers exec tsx src/shopee/test-review-analyzer.ts
pnpm --filter @repo/web typecheck
pnpm --filter @repo/web build
pnpm --filter @repo/crawlers test:dist
# Tại D:\Projects\Rate-Services (pnpm workspace + submodule vendor/rate)
git submodule update --init
pnpm install
pnpm build
pnpm test:enricherMỗi finding khi review (subagent fresh-context, bot, hoặc người) phải được gắn một mức độ:
| Mức | Định nghĩa |
|---|---|
| P0 | Gây sập dịch vụ, mất dữ liệu, xâm phạm bảo mật, hoặc dịch chuyển tiền sai trong luồng sử dụng bình thường. |
| P1 | Lỗi đúng/sai trên luồng bình thường, hoặc lỗi về bảo mật / phân quyền / tiền / credential / dữ liệu chưa tới mức P0. |
| P2 | Lỗi ở edge case, hoặc lỗi có cách né (workaround), nằm ngoài các vùng bảo mật / phân quyền / tiền / credential / dữ liệu. |
| P3 | Câu chữ, style, đặt tên. |
Quy tắc hội tụ (nhẹ):
- Vòng 1: Sửa các finding hợp lý ở mọi mức.
- Từ vòng 2 trở đi: Trong PR hiện tại chỉ sửa P0/P1, mọi finding về bảo mật hoặc dữ liệu, lỗi trong hành vi mà chính PR này thêm vào, và required check đang đỏ. Các P2/P3 còn lại gom vào một issue follow-up duy nhất; trả lời từng thread kèm link issue đó rồi resolve thread.
- Một lượt review của bot bị rate-limit, bị bỏ qua (skipped) hoặc không có nội dung không phải là review. Không chờ và không tính là đã review.
- Cổng review thật sự là review bằng subagent fresh-context (Mục 0.2). Các required check
Typecheck & Build Monorepo,E2E (Playwright)vàSecret scan (gitleaks)phải xanh trước khi merge (rulesetdev-main-lighttrêndevvàmain: chặn xóa nhánh và force-push, không yêu cầu approval). Riêngmaincó thêm rulesetmain-release: bắt buộc qua PR, chỉ cho merge commit, và phải xanh thêmPR into main comes from devvàmain must not lead dev(Mục 0.6).
⚠️ BẮT BUỘC: PO nạp skillproduct-ownerTRƯỚC mọi thao tác khác. Một session là PO khi tiêu đề có "Product Owner" hoặc khi JOY giao session làm PO của Rate Core hay Rate Services. Việc đầu tiên của PO là đọc và làm theo toàn bộ.claude/skills/product-owner/SKILL.md, trước khi đọc board, mở session con hay trả lời JOY:
- Claude Code: gọi skill
product-owner(công cụSkill).- Công cụ không có bộ nạp skill (Codex, Antigravity, Cursor, ...): đọc thẳng file đó.
- Đọc lại skill sau mỗi lần context bị reset, bị tóm tắt (compact) hoặc session được resume. Brief hay trí nhớ của chính session không thay cho skill.
- Session con (do PO mở) đọc Mục 6 này và các phần dành cho session con trong skill: "Starting a sub-session", "Review gate", "Coordinating", "Stop lines".
Bài học 2026-10-27: session PO của Rate Core chạy nhiều giờ mà không nạp skill, chỉ biết quy tắc qua brief của chính nó, và hỏi JOY quá nhiều.
JOY có thể giao một session Claude Desktop làm Product Owner (PO) cho một line: Rate Core (issue của DOS/Rate) hoặc Rate Services (issue của DOS/Rate-Services). PO điều phối backlog, mở session con cho từng issue, trả lời câu hỏi của chúng và chỉ mang quyết định thật sự lên JOY. Toàn bộ quy trình nằm trong skill .claude/skills/product-owner/SKILL.md; skill dùng lại giao thức nhãn ở Mục 1 (agent:<nick>, status:*, board.mjs, check task-claim), không thêm giao thức claim thứ hai.
Khi một session do PO mở (session con), các quy tắc sau thay đổi so với Mục 0 và Mục 1:
- Báo cáo cho PO, không hỏi JOY: session con chỉ làm issue trong brief (vòng lặp backlog của Mục 0.7 do PO chạy). Câu hỏi, quyết định, xin quyền hay xin truy cập gửi cho PO bằng
SendMessage; phần wrap-up chỉ là tóm tắt, không có câu hỏi hay nút bấm cho JOY. - Cổng chấp nhận của PO trước khi merge: khi required checks xanh và review đã xong (Mục 5), session con gửi PO tóm tắt ngắn (người dùng thấy gì thay đổi, bằng chứng cho từng tiêu chí chấp nhận, kết quả review, rủi ro còn lại) và chỉ chạy
merge-when-green.mjssau khi PO trả lời "merge". - Bước Production do PO chạy: session con không bao giờ tự chạy bước Production, migration DOS-Me, sửa dữ liệu production, secret hay credential. Session con viết runbook (lệnh, cách kiểm tra, cách rollback), PO trình JOY danh sách bước cụ thể, JOY duyệt trong chat của PO, rồi PO chạy đúng các bước đó.
- Khi bộ kiểm tra quyền của session con từ chối một thao tác (kể cả
merge-when-green.mjs): session con không thử lại, không tìm cách lách, và báo PO. PO không làm thay chỉ vì session con nói vậy, không sửa permission để vượt qua; PO hỏi JOY trong chat của PO và chỉ chạy khi JOY đồng ý. - Merge của session con: đường chuẩn là PO duyệt "merge" rồi session con tự chạy
merge-when-green.mjs. Nếu bộ kiểm tra quyền chặn, quy tắc ở gạch đầu dòng trên thay cho câu "agent tự merge" của Mục 0.2: PO hỏi JOY một câu ngắn trong chat của PO (không bao giờ bảo JOY tự bấm Merge) rồi PO tự chạy script. merge-when-green.mjscủa chính PO cũng có thể bị từ chối (bài học 2026-10-27, lý do "Merge Without Review") cho tới khi JOY duyệt đúng PR đó trong chat của PO. Một câu chung như "chủ động lên" không phải là lời duyệt merge. Khi đó, thay cho câu "agent tự merge" của Mục 0.2, PO không thử lại mà gom mọi PR đã qua cổng chấp nhận nhưng chưa merge được (session con hoặc chính PO bị từ chối) vào MỘT câu hỏi ngắn gửi JOY ("PR #a, #b, #c: merge?") thay vì hỏi từng PR, rồi tự chạy script cho đúng các PR JOY duyệt. Không bao giờ bảo JOY tự bấm Merge.- Nhả issue (release) là một lần bàn giao: session con nhả issue thì comment lý do và chỗ dừng rồi chạy
board.mjs <n> --status ready --agent <Nick>; session sau được dùng--take-overvà dẫn link comment đó. Claim không có bàn giao nhưng trông như bị bỏ rơi (ví dụ sau khi đổi máy) chỉ được lấy lại khi JOY đồng ý (Mục 0.6). - Done của thay đổi runtime: issue tự đóng khi PR merge vào
dev; với thay đổi runtime, PO chuyển sangdonesau khi promote vàverify-live.mjsđạt. Thay đổi docs, CI, tooling thìdonengay khi merge. - PR promote
dev->mainvẫn theo đợt như Mục 0.2, do PO chạy. - Rate Services khác Rate Core:
DOS/Rate-Serviceskhông có nhánhdev, không có checktask-claimvà không cóscripts/ops/; PR vàomain, vàboard.mjs/merge-when-green.mjschạy từ checkoutDOS/Ratevới--repo DOS/Rate-Services. Chi tiết trong skill.