Skip to content

Nhịp thư: kế hoạch triển khai ​

PRD · SDD · Tests · lập 14.10.2026, cập nhật sau rà soát thiết kế cùng ngày

Một nhánh (feat/email-orchestrator), một PR (người soạn muốn giảm phút CI), làm trong git worktree riêng. Ship ở chế độ preview: sau deploy, người dùng thật không nhận thêm thư nào; hai hộp thư duyệt bắt đầu nhận kế hoạch + thư mẫu mỗi sáng.

Giai đoạn A: nền (xong) ​

#ViệcFileXong khi
A1Migration bảng + cột + chỉ mục + 11 cài đặt mặc định an toànmigrations/20261114a_email_orchestrator.sqlTên sắp sau migration mới nhất; không CREATE TABLE trong src/
A2Kiểu, người gửi (24 × 2 miền), người duyệt, siêu dữ liệu 17 loại (18 từ khi thêm journey_day), hằng số chấm điểm, đọc/ghi cài đặtorchestrator/types.ts, config.ts, time.tstsc sạch
A3Chấm điểm thuầnorchestrator/score.tsTest thuần chạy được không cần D1
A4Tách danh mục: catalog.ts ghép lõi + mới; templates.ts export layout/tieuDe/esc/fmt*, thêm preheader; mọi chỗ import EMAIL_CATALOG chuyển sang catalog.tscatalog.ts, templates.ts, domains/system/index.ts, domains/admin/emails.ts, test emailtemplates.ts < 1.000 dòng; npm run test:email xanh
A5Cổng gửi: người gửi + miền, Reply-To, X-Conan-Kind, [QC], xem trước, prefsBlock, theo dõi bấm, from_email/plan_date, chân "Đổi nhịp", thử lại một lần cho thư giao dịchsend.ts, orchestrator/links.tsKhông thêm any, không catch trả rỗng (mốc qc-scan api đang kín)

Giai đoạn B: song song (xong) ​

#ViệcFile
B1Generators nhóm Quan hệ (5 loại)orchestrator/generators/relationship.ts
B2Generators nhóm Bản tin có hạn (sự kiện, buổi học, What's New, khoá mới, tuần cộng đồng)orchestrator/generators/newsletter.ts
B3Generators kho thường xanh (unit, sách, playbook, JTBD)orchestrator/generators/evergreen.ts
B4Generators Giữ liên lạc + Ưu đãiorchestrator/generators/lifecycle.ts
B5Mẫu thư 13 loại mới + bảng kế hoạch (journey_day là loại mới thứ 14, thêm sau, xem mục cuối)orchestrator/catalog-*.ts
B6Audience + planner + preview + dispatch + tick + workflow + nối cron + daily.ts nhường kheorchestrator/{audience,planner,preview,dispatch,tick}.ts, src/workflows/email-orchestrator.ts, src/index.ts, wrangler.toml
B7Trang có chữ ký (bấm, tuỳ chọn, reconnect, giữ lại; huỷ đổi sang GET xác nhận + POST), chuyển trang huỷ cũ khỏi system/index.tssrc/domains/system/email-orch.ts, src/domains/system/index.ts
B8API admin (gồm stop-all, daily-email) + trang Nhịp thư + mục điều hướngsrc/domains/admin/email-orchestrator.ts, src/domains/admin/index.ts, admin.conan.school/legacy/admin-trial/src/pages/EmailOrchestratorPage.tsx, admin.conan.school/src/nav.ts
B9Test + bước CItests/email-orchestrator.test.mts, package.json (test:orchestrator), .github/workflows/ci-checks.yml
B10Sửa link sự kiện (/events/:slug → /online-events/:slug) trong event_remindertemplates.ts

Rà soát thiết kế 14.10.2026: những gì đã đổi ​

Trước khi viết phần lớn mã, PRD và SDD bản đầu qua một lượt rà soát đối kháng bốn góc nhìn (đúng sai, lược đồ dữ liệu, giao thư và pháp lý, chấm điểm sản phẩm), mỗi phát hiện kiểm lại trên mã và production. Những phát hiện đổi thiết kế:

Phát hiệnMứcThiết kế bây giờ
Kế hoạch ngày D lập trước khi thư ngày D-1 đi, nên lịch sử không thấy chúng: cùng một người nhận cùng thư hai ngày liềnchặnLịch sử ảo từ dòng kế hoạch các ngày trước; PK email_sent_refs; kiểm lại khoảng cách lúc gửi bằng sổ gửi thật
Ngày đầu 140/150 khe rơi vào người hệ cũ ngủ sáu thángchặnXếp hàng dưới trần theo tầng trước; trần riêng cho reconnect min(50, 25%); legacy_cold = skip
"Ngày khoẻ" đọc từ ngày chưa gửilớnTrần tính lại lúc gửi từ ngày live đã xong
Tăng tải tìm hạn mức bằng cách tiêu cạn nó, chặn mã đăng nhập tới 07:00 hôm saulớnlive đòi daily_quota; trần ≤ 60% hạn mức trừ đỉnh thư khác; trần mềm 80% (400/ngày khi chưa biết); E_DAILY_LIMIT tự về preview; ramp_pct = 0
"Khoẻ" không thấy báo spam, bật lại, Gmail hoãn thưlớnramp_pct = 0 mặc định; Postmaster Tools vào danh sách kiểm trước live
Gửi dồn 08:00 không nhịplớnRải 08-11 giờ, nghỉ 40 giây giữa lô 20 thư (~30/phút); thư giao dịch thử lại một lần khi chạm tốc độ
Lỗi giữa lập kế hoạch và xem trước làm mất cả ngày; một loại giành trước khi gửi xem trước thì không bao giờ được xem trướclớnLease nhận lại planned; khoá hai pha xem trước, tối đa 3 lần
Thử lại khi chạm tốc độ không bao giờ chạy (lượt hỏng bị đếm là "đã nhận thư hôm nay")lớn"Đã nhận" chỉ đếm thư sent
Giữ lại / tắt / deploy chỉ có hiệu lực ở instance saulớnĐọc lại cài đặt, giữ và mẫu ở mỗi lô 20 thư
Thư mẫu dựng từ dữ liệu người thật mang link "Không" có chữ ký của người đólớnMẫu chỉ chứa LINK_PLACEHOLDERS; cổng gửi thay bằng trang xem trước
Chỉ pro_offer được coi là quảng cáo; một lượt bấm được coi là đồng ýlớnBảng phân loại pháp lý chờ ký; đồng ý chỉ bằng POST "Có"; consent_version; chỉ Quan hệ được gửi thật
Gửi thư người hệ cũ từ cùng danh tính với mã đăng nhậplớnsender_domain chuyển được sang tin.conan.school
Thompson quyết cả ngưỡng và thứ tự dưới trầnlớnThompson chỉ xếp hạng; gửi hay im và thứ tự dưới trần dùng trung bình
Tiên nghiệm mặc định cao gấp 2-4 lần thực tếlớnCo về trung bình đo được (~0,13) với 30 thư ảo; bỏ thư người duyệt, thư thử, thư < 4 ngày
Mỏi quá yếu: một lượt mở mua 14 thư liền, ~33 thư trước khi dừnglớnMỏi 0,75^n; ngưỡng tầng .05/.08/.10/.12/.15; tụt tầng mỗi 3 thư; dừng sau 6 thư + 30 ngày
weekly_progress đếm lượt chuyển trang là "bài đã học"lớnĐếm DISTINCT concept_id
order_pending nhắc người đã chuyển khoảnlớnBỏ người có yêu cầu kích hoạt đang xử lý/đã duyệt; bỏ đơn lệch giá; câu chữ "đang chờ chuyển khoản"
event_upcoming thành thư hằng tuần về Bàn tròn của cộng đồng kháclớnRelevance 0,2 cho cộng đồng khác; cooldown 7 ngày; bỏ sự kiện của nhà đã có trong thư tuần
"Buổi học sắp tới" và "tuần qua có gì mới" không gửi được như mô tảlớnThêm session_upcoming từ workshops; What's New cho tài khoản gồm cả public
Số unit trong URL www là vị trí, không phải sort_order; trang thường xanh chỉ có ở wwwlớnBảng link theo loại; ROW_NUMBER như UNIT_LIST_SQL; stillValid so lại link
Người chưa đủ 16 tuổi nằm trong danh sách gửi hàng loạtnhỏChỉ nhóm Quan hệ
Mốc thời gian trộn hai dạng (seen_at)nhỏBọc strftime trước khi so
Dòng hết hạn chỉ được dọn lúc 22 giờ hôm naynhỏsweepPast mọi lượt, mọi chế độ
Lập kế hoạch lúc 21:07, 22:07 cho một ngày không gửi được gìnhỏChỉ lập 07-20 giờ VN
Fingerprint bỏ sót nhánh không tên, chữ thuần, người gửinhỏBăm ba lần dựng + chữ thuần + người gửi + SEND_DECOR_VERSION; mẫu đổi thì mở lại xem trước ngày mai
Thư mẫu mang tiền tố [BẢN SAO →, giấu 35 ký tự đầu thậtnhỏĐuôi · xem trước dd.mm, không tiền tố
Loại mới của Nhịp thư có thể quên vào ENGAGEMENT_KINDSnhỏ...NEW_ORCH_KINDS + test từng loại

Giai đoạn C: ghép và kiểm ​

  1. npm run typecheck (api, cổng tuyệt đối 0 lỗi), npm run test:email, npm run test:orchestrator.
  2. npx wrangler deploy --dry-run (bắt thiếu export workflow, binding sai, allowed_sender_addresses).
  3. Gác gốc: check:emdash, check:colors, check:emoji-icons, check:admin-icons, qc:scan --check.
  4. Build admin.
  5. Diễn tập trên dữ liệu thật (skill emails): chạy các truy vấn SELECT của audience và generators lên production bằng wrangler d1 execute --remote, đọc kết quả (không chỉ đếm).
  6. Rà soát mã theo các lớp lỗi đã xảy ra thật (skill code-reviewer), sửa, rồi mở PR.

Giai đoạn D: triển khai ​

  1. PR → CI xanh → merge (squash) → kiểm có lượt deploy-api cho đúng SHA merge.
  2. Kiểm migration đã áp: SELECT key, value FROM email_orch_settings ra 11 dòng, mode = preview.
  3. Lượt cron :07 kế tiếp (giờ VN 07-20) lập kế hoạch ngày mai và gửi xem trước tới [email protected] và [email protected]. Kiểm email_plan_runs (previewed), email_plan_kinds.preview_ok, và sổ gửi audit_of LIKE 'preview:%'.
  4. Admin → Nhịp thư → "Gửi bộ mẫu" để đọc cả 18 mẫu bằng dữ liệu giả ngay, không chờ kế hoạch.
  5. Người soạn đọc thư, chốt Q1-Q10 của PRD, ký bảng phân loại pháp lý.

Giai đoạn E: bật thật (người soạn quyết) ​

  1. Đi hết danh sách kiểm trước khi bật live.
  2. Admin → Nhịp thư → Chế độ: nhập hạn mức, giữ "Nhóm gửi thật" chỉ Quan hệ, chọn "Chạy thật". daily.ts tự nhường khe. Thư thật đầu tiên đi ở khung giờ gửi kế tiếp (08:00-11:00, bật sau 11:00 thì sáng hôm sau), cho các dòng đã xem trước đủ 24 giờ.
  3. Mỗi sáng đọc bảng kế hoạch và tab Kế hoạch: gửi hỏng, huỷ nhận, deferred, lý do bỏ qua; đọc Postmaster Tools.
  4. Mở thêm nhóm (Bản tin, Giữ liên lạc) chỉ khi có xác nhận của Cloudflare (Q1) và chữ ký phân loại pháp lý; tăng trần hay ramp_pct bằng tay sau ít nhất 3 ngày Postmaster sạch.
  5. Sau 7 ngày: đọc tỉ lệ bấm theo loại; chỉnh base_k nếu một loại liên tục thua mà vẫn có người bấm.

Rủi ro đã biết ​

Rủi roGiảm thiểu
Cloudflare coi thư gắn kết là sai mục đích, cưỡng chế ở cấp tài khoảnChờ xác nhận (Q1); chỉ Quan hệ được gửi thật; trần thấp; miền con tin.conan.school
Hạn mức ngày không rõ, dùng chung nemo12.comlive đòi hạn mức; trần mềm; phần chừa cho thư khác; chạm hạn mức thì dừng, deferred, tự về preview
D1 1.000 câu mỗi lần gọi, 100 tham số mỗi câuĐọc theo lô (~15 câu), ghi 5 dòng mỗi câu, gửi theo lô 20 trong từng bước workflow, tối đa 300 dòng mỗi instance
Người hệ cũ báo spamChỉ người từng mở thư cũ, tối đa 2 lần; trần reconnect riêng; xếp sau người đang tương tác
Mẫu đổi giữa xem trước và gửiFingerprint; loại đó tự giữ hôm nay, xem trước lại cho ngày mai
Ngày đầu chuyển sang live: kế hoạch lập lúc còn preview chứa mọi nhómDòng của nhóm chưa bật bị bỏ với class_not_live; theo dõi số dòng Quan hệ bị hạ over_cap ngày đó

Bổ sung 14.10.2026: chuỗi 30 thư làm quen (journey_day) ​

PR #351 (30 thư chào mừng, alias theo cộng đồng) đóng ngày 14.10.2026; nội dung vào Nhịp thư thành loại mới thứ 14, đúng khuyến nghị Q6 của PRD. Nhánh feat/orch-journey.

ViệcFile
Khai loại: NEW_ORCH_KINDS, nhóm tuỳ chọn lam_quen trong Category và MUTABLE_CATEGORIES; KIND_META.journey_day (Bản tin, nha, base 0,8, cooldown 1, tối đa 30)orchestrator/types.ts, config.ts
Generator: chỉ tài khoản có cộng đồng nhà, thư kế tiếp = số nhỏ nhất chưa nhận, stillValid đòi thư N-1 đã điorchestrator/generators/journey.ts, generators/index.ts
Chữ 30 thư + giọng 18 cộng đồng; khung thư, dữ liệu mẫu, dấu nội dung cả chuỗiorchestrator/journey-days.ts, catalog-journey.ts, catalog.ts
Nhãn "Chuỗi thư làm quen" ở trang tuỳ chọnsrc/domains/system/email-orch.ts (CATEGORY_OPTIONS)
Nhóm 13 của test: thứ tự, thư bị bỏ, quét 30 thư × 16 biến thể; tổng 570 phép kiểmtests/email-orchestrator.test.mts

Khác bản PR: mỗi thư là MỘT ứng viên tranh khe theo điểm (không chiếm 30 ngày liền), chịu tầng, mỏi, tuỳ chọn và cổng xem trước 24 giờ. Nội dung đã sửa khi chuyển (kiểm trên production 14.10.2026): bỏ chữ về lịch, bỏ lời chào Pro ở thư 22, thay tab Prompts và tab Thảo luận, không hứa trả lời từng thư, không dẫn người chưa xong hồ sơ vào trang bị khoá, không hứa lịch khi cộng đồng không có buổi nào, bỏ "cộng đồng thứ hai", đo ngày im từ hoạt động học thật. Chi tiết ở known-risks. Kế hoạch diễn tập cho ngày 16.10.2026 trên dữ liệu thật: 7 thư chuỗi (2 nếu base là 0,65).

Còn lại trước khi chuỗi gửi thật: người soạn ký dòng 15 của bảng phân loại pháp lý (PRD mục 13), và bật nhóm Bản tin sau khi Cloudflare xác nhận (Q1). Xem đủ 30 thư ở admin là việc giai đoạn sau.

Tài liệu nội bộ nền tảng Conan School.