NGHIÊN CỨU TỬ VI

Lịch sử Tử Vi Đẩu Số tại Trung Quốc và Việt Nam: những mốc có thể kiểm chứng

Sau 63 vòng khảo cứu thư tịch, bài viết tách rõ lịch sử tên sách, chứng bản và quá trình tiếp nhận Tử Vi tại Trung Quốc và Việt Nam, thay vì gán một “năm khai sinh” chưa được chứng minh.

Cập nhật: 27/10/2026 · Bản nghiên cứu chốt: 26/10/2026

Khi nói về lịch sử Tử Vi Đẩu Số, rất dễ bắt đầu bằng những nhân vật được truyền thống gán cho bộ môn này rồi suy ngược niên đại. Nhưng một tên tác giả truyền đời sau, một bài tựa có niên khoản, một mục thư viện, một bản khắc còn lưu và một sự kiện người Việt mua sách là những loại chứng cứ khác nhau.

Công trình này được tổng kết từ chuỗi R1 đến R63. Hồ sơ nền gồm workbook CN-R63 với 327 sheet, checkpoint CS11 và CS12, các handoff R51-R63 và tập ảnh R.293. Báo cáo cuối không coi mọi tuyên bố của từng vòng là đã được tự đối chiếu lại độc lập; khi viện dẫn học thuật, các mốc vẫn phải quay về đúng nguồn, tờ và mức kiểm chứng tương ứng.

Ba câu hỏi cần tách riêng

  1. Một văn bản gọi đích danh Tử Vi Đẩu Số xuất hiện sớm nhất trong tư liệu còn kiểm được tại Trung Quốc vào thời điểm nào?
  2. Đến khi nào có thể chứng minh người Việt biết đến, tìm mua, đọc hoặc bàn luận về Tử Vi bằng chứng cứ có mốc thời gian?
  3. Có thể chứng minh thời điểm một bản sách Tử Vi thực sự hiện diện và được sử dụng tại Việt Nam hay không?

Ba câu hỏi này không thể trả lời bằng cùng một niên đại. Năm một nhan đề xuất hiện trong thư mục, năm một bản sách được khắc, năm một sứ đoàn giao dịch sách và năm một bản sách thực sự đi vào đời sống học thuật Việt Nam là những sự kiện khác nhau.

Hai thang chứng cứ được dùng trong nghiên cứu

B0-B3 dùng để chỉ mức độ kiểm được nguồn:

  • B0: đầu mối hoặc ký hiệu chưa đọc trực tiếp.
  • B1: biểu ghi thư mục hoặc công trình nghiên cứu dẫn lại.
  • B2: đọc trực tiếp chính văn một thư mục lịch sử hoặc bản phiên văn nguồn.
  • B3: trực tiếp đối chiếu ảnh trang thuộc một chứng bản xác định.

B3 chỉ xác nhận những trang và mệnh đề thực sự đã kiểm, không tự động xác nhận toàn bộ niên đại hay lịch sử của tác phẩm.

D1-D5 dùng để chỉ ý nghĩa lịch sử trên tuyến Việt Nam:

  • D1: thuật số, thiên văn nói chung.
  • D2: tên Tử Vi xuất hiện trong một sự kiện định năm, như việc tìm mua sách.
  • D3: người Việt trực tiếp bàn luận môn này trong một văn bản có khung niên đại.
  • D4: hiện diện vật lý của một chứng bản có niên khoản và xuất xứ Việt Nam đủ tin cậy.
  • D5: sự lưu truyền hoặc thực hành được nhiều nguồn độc lập xác nhận.
Nguyên tắc quan trọng Không dùng 紫微垣 (Tử Vi viên) trong thiên văn như bằng chứng cho môn Tử Vi Đẩu Số. Không lấy thế kỷ của người được gán làm tác giả để định thế kỷ biên soạn. Không lấy năm số hóa hoặc năm một thư mục hiện đại được in làm năm chép sách cổ.

Trung Quốc: ứng viên thư mục năm 1570

Trong quyển III của Vạn Quyển Đường Thư Mục 《萬卷堂書目》, nhóm Ngũ hành gia 五行家, có dòng:

「紫微斗數八卷」, Tử Vi Đẩu Số, tám quyển.

Bài tự của thư mục do Chu Mục Khiết 朱睦㮮 đề Long Khánh Canh Ngọ 隆慶庚午, tức năm 1570. Đây là đầu mối sớm hơn mốc 1581 vốn thường được dùng trong nhiều tổng kết trước đó.

Tuy nhiên, bản hiện khảo thuộc các truyền bản muộn hơn. Công trình chưa chứng minh dòng “Tử Vi Đẩu Số, tám quyển” chắc chắn đã nằm trong chính lớp văn bản năm 1570. Vì thế cách nói an toàn là:

Tên Tử Vi Đẩu Số được ghi trong truyền bản của một thư mục mang bài tự năm 1570; niên đại riêng của mục sách vẫn còn mở.

Tiều Thị Bảo Văn Đường Thư Mục 《晁氏寶文堂書目》 cũng có nhan đề 紫微斗數 ở nhóm Âm dương 陰陽, nhưng truyền bản có lớp bổ sung qua đời Long Khánh và Vạn Lịch. Chưa thể dùng mục này để đẩy mốc chắc chắn về trước 1570.

1581: mốc bản khắc có niên đại trong hệ nguồn đã truy

Tân Khắc Toản Tập Tử Vi Đẩu Số Tiệp Lãm 《新刻纂集紫微斗數捷覽》 được thư mục cổ tịch ghi là bản khắc Minh Vạn Lịch thứ chín, tức 1581, tại Kim Lăng, bốn quyển. Bản lưu được chỉ về Bảo tàng An Huy.

Năm 2016, Tâm Nhất Đường 心一堂 phát hành một bản phục chế hai tập, trong đó tập trên được giới thiệu là ảnh màu bản khắc. Nhưng trong phạm vi nghiên cứu R1-R63, tờ niên khoản nguyên bản của bản lưu An Huy chưa được trực tiếp đối khám.

Do đó 1581 hiện là mốc bản khắc được xác nhận ở cấp biểu ghi thư mục, không được nâng thành B3 và không được gọi là “năm phát minh Tử Vi”.

Các hệ văn bản đời Minh và bản 1607

Một hệ Tử Vi Đẩu Số Toàn Thư 《紫微斗數全書》 bảy quyển hiện được lưu tại Nhật Bản, ký hiệu 子060-0001, và được định loại là bản in đời Minh. Biểu ghi đang dùng chưa cho phép chốt năm khắc cụ thể.

Năm 1607, Tục Đạo Tạng 《續道藏》 có Tử Vi Đẩu Số 《紫微斗數》 ba quyển, hiện có các tập số hóa 167-169. Hệ ba quyển này không được đồng nhất với bộ bảy quyển Toàn Thư.

Việc tồn tại nhiều hệ văn bản cùng mang hoặc gần cùng nhan đề cho thấy lịch sử Tử Vi không thể rút gọn thành một cuốn sách duy nhất truyền nguyên trạng qua nhiều thế kỷ.

Vì sao không dùng Trần Đoàn hay bài tựa 1550 để định niên đại?

Trần Đoàn 陳摶 là nhân vật thế kỷ X được nhiều truyền bản đời sau quy thuộc Tử Vi. Nhưng niên đại cuộc đời ông không phải chứng cứ rằng hệ Tử Vi Đẩu Số hiện còn đã hình thành ở thế kỷ X.

Tương tự, một bài tựa mang tên La Hồng Tiên 羅洪先 ghi năm 1550 xuất hiện trong các truyền bản muộn. Nghiên cứu đối khám dị bản năm 2021 được sử dụng trong công trình cho rằng lời tựa này được gắn thêm về sau. Vì vậy 1550 không được dùng làm năm khắc hoặc năm sáng tác đã được chứng minh.

Việt Nam năm 1761: người Việt tiếp cận sách Tử Vi tại Trung Quốc

Trong Bắc Sứ Thông Lục 《北使通錄》 A.179, gắn với sứ trình của Lê Quý Đôn, bản dịch đang dùng ghi tại tờ 48b hai khoản sách Tử vi đấu số, mỗi khoản giá 8 hào, nằm trong danh sách thu giữ và hoàn tiền.

Giá trị của chứng cứ này là rất cụ thể: người Việt trong sứ đoàn năm 1761 đã tìm mua hoặc giao dịch sách mang tên Tử Vi ở Trung Quốc. Trong hệ phân loại của công trình, đây là mốc D2.

Nhưng chính hoàn cảnh “thu giữ và hoàn tiền” khiến ta không được suy tiếp rằng những cuốn sách đó đã vượt biên giới và về đến Việt Nam.

Tuyến đối chứng đã được định vị đến A.179 tờ 48b, vi phim MF.1583, bản Paris SA.HM.2221 và ấn bản Hán văn hiện đại. Ảnh tờ gốc 48b chưa được khóa ở cấp B3 trong hồ sơ tổng kết.

1773: Tử Vi bước vào thảo luận học thuật của người Việt

Trong Vân Đài Loại Ngữ 《芸臺類語》 của Lê Quý Đôn, phần Lý khí, điều 38 theo bản dịch và hồ sơ học thuật đang sử dụng có nội dung bàn trực tiếp về Tử Vi, tác giả và sự quy thuộc của truyền thống này.

Tác phẩm có bài tựa năm 1773; một dị bản khác có tựa năm 1777. Công trình giữ 1773 như một mốc tham chiếu mạnh về tiếp nhận học thuật, D3, nhưng không nói rằng chính điều 38 chắc chắn được viết đúng năm 1773.

Ảnh chữ Hán A.141 tại đúng điều 38 cũng chưa được đối khám trong hồ sơ khóa, vì vậy cấp kiểm nguồn của chính đoạn này vẫn được giữ thận trọng.

Những nhánh sớm hơn 1761 chưa đạt mức chứng minh

Công trình đã khảo các nhánh liên quan Đại Việt Thông Sử, Nghệ Văn Chí, gia phả họ Phạm và nhiều ký hiệu Hán Nôm. Một số nguồn có lớp niên đại 1749, 1759 hoặc câu chuyện truyền học sớm hơn, nhưng chưa chứng minh được một đoạn Tử Vi có niên đại tương ứng.

Gia phả Đường An Đan Loan Phạm Gia Thế Phả A.909/VHv.1353 có phần Đẩu số, nhưng tập gia phả được biên tập năm 1820. Không được lấy tuổi đời của nhân vật được kể trong gia phả để đẩy niên đại phần Đẩu số lùi về trước.

18 ký hiệu Hán Nôm là danh mục kiểm kê, không phải 18 tác phẩm độc lập

Trong quá trình khảo sát, dự án quản lý một danh mục 18 ký hiệu ứng viên chuyên biệt, gồm các bản cùng tên, bản giải âm, bản rời và những tài liệu chỉ được mô tả gián tiếp. Con số này không có nghĩa đã xác định được 18 tác phẩm độc lập hoặc 18 chứng bản có niên đại sớm.

Những ký hiệu đáng chú ý gồm VHv.163, VHb.162, VHb.160, VHb.161, VHb.168, VHb.730, VHv.731, VHv.732, A.2553, Paris.SA.HM.2106, AB.316, AB.552, R.293, TNVNPF-110, VHv.734, ST.1129, AB.424 và VHb.166.

Một số ký hiệu còn xung đột tên gọi trong chỉ mục. Một số bản có nội dung Tử Vi nhưng chưa có năm sao chép. Vì vậy nhan đề, lối chữ, tên người được gán hoặc năm số hóa không được dùng thay cho chứng cứ niên đại.

R.293 và giá trị của việc nhìn vào ảnh chứng bản

Ở R60, công trình tiếp nhận 54 ảnh JPEG của 安紫微國語歌 (An Tử Vi Quốc Ngữ Ca), mã R.293. Số tệp được kiểm đầy đủ; các ảnh đầu, cuối và một số trang trọng điểm được đọc kỹ.

Một kết quả có giá trị là nhan đề gốc không có chữ 南 (Nam). Nhưng các trang đã kiểm không cho thấy niên khoản rõ, và ảnh cuối vẫn còn nội dung. Vì thế không được tuyên bố toàn bộ bản gốc không có hậu bạt hoặc chắc chắn không có năm ở một vị trí khác chưa được xem.

Niên biểu: những mốc được phép nói đến

Niên đại Không gian Chứng cứ Được phép kết luận
Thế kỷ X Trung Quốc Truyền thống quy cho Trần Đoàn Lịch sử quy thuộc tên tác giả, không phải niên đại môn học.
1550 Trung Quốc Bài tựa gán La Hồng Tiên Có niên khoản trong truyền bản muộn, không xác nhận bản tựa gốc năm 1550.
1570 Trung Quốc Vạn Quyển Đường Thư Mục có truyền bản ghi Tử Vi tám quyển Ứng viên mốc thư mục sớm; lớp văn bản của mục sách chưa khóa.
1581 Trung Quốc Tử Vi Đẩu Số Tiệp Lãm, bốn quyển Mốc bản khắc theo biểu ghi thư mục.
1607 Trung Quốc Tục Đạo Tạng, Tử Vi Đẩu Số ba quyển Một chứng bản cùng tên có niên đại nguồn, khác hệ Toàn Thư.
1761 Sứ đoàn Việt tại Trung Quốc Bắc Sứ Thông Lục Người Việt tiếp cận và giao dịch sách Tử Vi, D2.
1773 Việt Nam Vân Đài Loại Ngữ Mốc tiếp nhận học thuật, D3.
1820 Việt Nam Gia phả A.909 Có tập gia phả chứa mục Đẩu số; niên đại riêng của đoạn chưa xác định.
1934 Việt Nam / thư mục Nhật Matsumoto ghi A.2553 Sách đã được ghi nhận trong thư mục; không phải năm chép.

Những gì công trình chưa chứng minh

  1. Chưa xác định năm sáng tạo Tử Vi Đẩu Số ở Trung Quốc hoặc người sáng tạo đầu tiên.
  2. Chưa chứng minh Tử Vi có từ thời Tống chỉ vì được quy cho Trần Đoàn.
  3. Chưa chứng minh 1570 là niên đại chắc chắn của mục Tử Vi tám quyển trong lớp thư mục gốc.
  4. Chưa chứng minh mục tám quyển trong truyền thống 1570 đồng nhất với Tiệp Lãm bốn quyển năm 1581.
  5. Chưa chứng minh sách Tử Vi đã được mang về Việt Nam trong sự kiện năm 1761.
  6. Chưa chứng minh Tử Vi hiện diện tại Việt Nam từ thời Trần, thế kỷ XVI hoặc trước 1761.
  7. Chưa định năm sao chép 18 chứng bản chỉ dựa vào nhan đề, lối chữ, tên người được gán hoặc năm số hóa.

Kết luận: lịch sử văn bản có thể định vị, nhưng “năm khai sinh” vẫn chưa có

Kết quả của R1-R63 không phải một câu trả lời đơn giản kiểu “Tử Vi bắt đầu từ năm X”. Giá trị lớn nhất là tách được những tầng chứng cứ thường bị nhập làm một.

Ở Trung Quốc, có chứng cứ trực tiếp về tên sách trong truyền thống thư mục mang bài tựa năm 1570 và có biểu ghi đáng chú ý về bản khắc năm 1581. Năm 1607 bổ sung một hệ văn bản khác trong Tục Đạo Tạng.

Ở Việt Nam, năm 1761 cho thấy người Việt đã tìm mua sách Tử Vi ở Trung Quốc; khoảng 1773 cho thấy Tử Vi đã bước vào thảo luận học thuật của một học giả Việt Nam. Nhưng cả hai mốc đều không cho phép xác định ngày tháng Tử Vi bắt đầu được thực hành trên đất Việt.

Kết luận cuối cùng của công trình là một kết luận có giới hạn: lịch sử văn bản có những mốc có thể định vị, nhưng thời điểm khai sinh và thời điểm du nhập vẫn chưa được chứng minh.

Ba điểm ưu tiên nếu nghiên cứu tiếp

Nếu sau này có điều kiện mở lại công trình ở cấp chứng bản, ba điểm ưu tiên đã được chốt:

  1. Ảnh tờ ghi mục Tử Vi trong Vạn Quyển Đường Thư Mục để phân lớp mục sách với bài tựa 1570.
  2. Trang niên khoản của bản Tiệp Lãm 1581.
  3. Chữ Hán A.179 tờ 48b và A.141 điều 38 tại Việt Nam.

Nguồn đối chiếu chính

  • Lê Quý Đôn, Bắc Sứ Thông Lục 《北使通錄》, Viện Hán Nôm A.179, tờ 48b.
  • Lê Quý Đôn, Vân Đài Loại Ngữ 《芸臺類語》, A.141, phần Lý khí, điều 38.
  • Đường An Đan Loan Phạm Gia Thế Phả 《唐安丹鑾范家世譜》, A.909/VHv.1353.
  • An Tử Vi Quốc Ngữ Ca 《安紫微國語歌》, R.293 / NLVNPF-0508, 54 ảnh.
  • Chu Mục Khiết 朱睦㮮, Vạn Quyển Đường Thư Mục 《萬卷堂書目》, quyển III, mục 五行家.
  • Tiều Thị Bảo Văn Đường Thư Mục 《晁氏寶文堂書目》, mục 陰陽.
  • Tân Khắc Toản Tập Tử Vi Đẩu Số Tiệp Lãm 《新刻纂集紫微斗數捷覽》, biểu ghi bản khắc 1581.
  • Tục Đạo Tạng 《續道藏》, bản khắc 1607, các tập 167-169.
  • Nhật Bản Quốc lập Công văn Thư Quán, bản Minh Tử Vi Đẩu Số Toàn Thư 《紫微斗數全書》, 子060-0001.
  • Trần Chiêu Ngâm, nghiên cứu đối chiếu dị bản Tử Vi Đẩu Số, 2021.

Đường dẫn nguồn chi tiết: xem trực tiếp các hồ sơ thư viện và công trình đã được ghi trong báo cáo R1-R63, gồm Viện Hán Nôm, Nôm Foundation, Chinese Text Project, Thư viện Quốc gia Đài Loan, Quốc lập Công văn Thư quán Nhật Bản và các cơ sở dữ liệu cổ tịch liên quan.

Ghi chú phương pháp Bài viết này là bản biên tập phổ thông từ báo cáo tổng kết R1-R63. Nó phân biệt giữa chứng cứ thư mục, chứng bản, truyền thống quy thuộc và suy luận lịch sử. Những điểm chưa trực tiếp đối khám ảnh gốc được giữ nguyên trạng thái chưa xác lập, thay vì được trình bày như kết luận chắc chắn.

Đọc thêm nghiên cứu Ma Y, Ma Thị và các bài phú Tử Vi · Khám phá hệ Tử Vi

`; function preflight() { for (const file of [F.template, F.hub, F.sitemap, F.adsConfig]) { if (!fs.existsSync(file)) throw new Error("Missing: " + file); } if (fs.existsSync(F.articleDir)) throw new Error("Article route already exists"); if (fs.existsSync(F.test)) throw new Error("Test already exists"); if (fs.existsSync(BACKUP)) throw new Error("Backup already exists"); if (!/\benabled\s*:\s*false\b/.test(read(F.adsConfig))) throw new Error("Ads are not OFF"); if (!read(F.template).includes('
')) throw new Error("Template prose-card missing"); if (!read(F.hub).includes(OLD_ROUTE)) throw new Error("Knowledge hub anchor missing"); if (read(F.hub).includes(NEW_ROUTE)) throw new Error("Knowledge hub already contains new route"); if (read(F.sitemap).includes(NEW_URL)) throw new Error("Sitemap already contains new URL"); console.log("[KNOWLEDGE-MA-Y-MA-THI-1] PREFLIGHT PASS"); } function backup() { fs.mkdirSync(BACKUP, { recursive: true }); for (const file of [F.hub, F.sitemap]) { const dest = path.join(BACKUP, path.relative(ROOT, file)); fs.mkdirSync(path.dirname(dest), { recursive: true }); fs.copyFileSync(file, dest); } } function buildArticle() { let html = read(F.template); html = html.replaceAll(OLD_URL, NEW_URL).replaceAll(OLD_ROUTE, NEW_ROUTE).replaceAll(OLD_TITLE, NEW_TITLE).replaceAll(OLD_DESC, NEW_DESC); html = html.replace(/[\s\S]*?<\/title>/i, `<title>${NEW_TITLE}`); html = html.replace(//i, ``); html = html.replace(//i, ``); html = html.replace(/]*type=["']application\/ld\+json["'][^>]*>[\s\S]*?<\/script>/gi, ""); const schemas = ``; html = html.replace("", schemas + ""); const articleRe = /]*>[\s\S]*?<\/article>/i; if (!articleRe.test(html)) throw new Error("Template article block missing"); html = html.replace(articleRe, `
${ARTICLE_HTML}
`); fs.mkdirSync(F.articleDir, { recursive: true }); write(F.article, html); } function addHubCard() { let hub = read(F.hub); const escaped = OLD_ROUTE.replace(/[.*+?^${}()|[\]\\]/g, "\\

1. Điểm giống nhau dễ thấy: cùng cần dữ liệu sinh

Ở mức trải nghiệm người dùng, cả Tử Vi và Tứ Trụ đều thường cần ngày sinh, giờ sinh và một số thông tin bổ sung. Đây là lý do một “Hồ sơ Mệnh Lý” có thể giúp người dùng nhập một lần rồi dùng lại ở nhiều công cụ. Nhưng việc dùng chung dữ liệu đầu vào không có nghĩa hai hệ thống dùng chung cách lập và phân tích.

2. Tứ Trụ tổ chức dữ liệu theo bốn trụ

Tứ Trụ, hay Bát Tự, tổ chức dữ liệu quanh bốn trụ năm, tháng, ngày và giờ. Mỗi trụ gồm Thiên Can và Địa Chi. Từ cấu trúc đó, người học tiếp tục đi vào những quan hệ như Thập Thần và các lớp phân tích khác.

3. Tử Vi tổ chức lá số theo hệ cung và sao

Tử Vi Đẩu Số trình bày thông tin qua một cấu trúc cung và hệ thống sao. Giao diện vì vậy cũng khác: người dùng cần nhìn một lá số có bố cục cung, vị trí sao và các quan hệ giữa cung thay vì bốn cột Can Chi.

Khía cạnhTử ViTứ Trụ
Dữ liệu đầu vàoNgày giờ sinh và thông tin cần thiết để lập lá số.Ngày giờ sinh để lập bốn trụ Can Chi.
Cấu trúc hiển thịHệ cung và sao.Năm, tháng, ngày, giờ với Can Chi.
Ngôn ngữCung, sao và các cấu trúc của Tử Vi.Can Chi, Thập Thần và các quan hệ của Bát Tự.
Thiết kế webCần ưu tiên sơ đồ lá số.Cần ưu tiên bảng bốn trụ và các lớp phân tích.

4. Vì sao không nên gom thành một màn “xem vận mệnh”?

Nếu gom hai hệ vào cùng một kết quả, người dùng khó biết nhận định nào đến từ Tử Vi, nhận định nào đến từ Tứ Trụ. Khi hai hệ sử dụng thuật ngữ khác nhau hoặc cho cách diễn giải khác nhau, giao diện càng dễ gây cảm giác mâu thuẫn.

Cách tốt hơn là có một hồ sơ chung nhưng hai khu vực tra cứu độc lập. Người dùng có thể chuyển qua lại, so sánh, hoặc yêu cầu A Sinh AI giải thích từng hệ, nhưng nguồn dữ liệu và kết quả luôn được gắn nhãn rõ.

5. AI nên xử lý thế nào?

A Sinh AI chỉ nên dựa trên kết quả đã được lập từ đúng hệ thống tương ứng. Khi phân tích Tử Vi, AI dùng dữ liệu Tử Vi. Khi phân tích Tứ Trụ, AI dùng dữ liệu Tứ Trụ. Nếu người dùng yêu cầu đối chiếu hai hệ, hệ thống có thể đặt hai bộ dữ liệu cạnh nhau và nói rõ đây là phép đối chiếu, không phải một phương pháp duy nhất.

Kết luận ngắnDùng chung hồ sơ sinh để giảm thao tác, nhưng giữ riêng cách lập, thuật ngữ và màn kết quả của từng hệ. Đó là cách hệ sinh thái Mệnh Lý A Sinh tránh “trộn môn” chỉ vì các công cụ cùng nằm trên một website.
"); const re = new RegExp(`]*href=["']${escaped}["'][^>]*>[\\s\\S]*?<\\/a>`, "i"); const match = hub.match(re); if (!match) throw new Error("Could not locate existing Tử Vi/Tứ Trụ card"); let card = match[0].replaceAll(OLD_ROUTE, NEW_ROUTE); card = card.replace("Tử Vi và Tứ Trụ", "Ma Y, Ma Thị và phú Tử Vi"); card = card.replace("So sánh cách tổ chức lá số, ngôn ngữ và cách sử dụng dữ liệu ngày giờ sinh.", "Lần theo thư tịch Hán Nôm và sách Tử Vi thế kỷ XX để nhìn lại quá trình truyền thừa các bài phú."); if (card === match[0]) throw new Error("Hub card transform failed"); hub = hub.replace(match[0], match[0] + card); write(F.hub, hub); } function updateSitemap() { let xml = read(F.sitemap); const entry = `${NEW_URL}2026-10-100.8`; if (!xml.includes("")) throw new Error("Sitemap closing tag missing"); xml = xml.replace("", entry + "\n"); write(F.sitemap, xml); } function createTest() { const source = `import test from "node:test";\nimport assert from "node:assert/strict";\nimport fs from "node:fs";\nimport path from "node:path";\nconst ROOT=process.cwd();\nconst read=(r)=>fs.readFileSync(path.join(ROOT,r),"utf8");\ntest("Ma Y Ma Thi research article is published safely",()=>{\nconst a=read("public/kien-thuc/ma-y-ma-thi-phu-tu-vi-viet-nam/index.html");\nconst h=read("public/kien-thuc/index.html");\nconst s=read("public/sitemap.xml");\nconst ads=read("public/portal-assets/web-ads-config.js");\nassert.match(a,/Ma Y, Ma Thị và hành trình truyền thừa các bài phú Tử Vi tại Việt Nam/);\nassert.match(a,/https:\\/\\/menhlyasinh\\.com\\/kien-thuc\\/ma-y-ma-thi-phu-tu-vi-viet-nam\\//);\nassert.match(a,/\"@type\":\"Article\"/);\nassert.match(a,/\"@type\":\"BreadcrumbList\"/);\nassert.match(a,/Những gì chưa được phép kết luận/);\nassert.doesNotMatch(a,/name=\"robots\"[^>]*noindex/i);\nassert.match(h,/ma-y-ma-thi-phu-tu-vi-viet-nam/);\nassert.match(s,/ma-y-ma-thi-phu-tu-vi-viet-nam/);\nassert.match(ads,/\\benabled\\s*:\\s*false\\b/);\n});\n`; write(F.test, source); } function validate(templateHash, adsHash, protectedBefore, runtimeBefore) { if (!fs.existsSync(F.article)) throw new Error("Article file missing"); const article = read(F.article); if (!article.includes(NEW_H1)) throw new Error("H1 missing"); if (!article.includes('"@type":"Article"')) throw new Error("Article schema missing"); if (!article.includes('"@type":"BreadcrumbList"')) throw new Error("Breadcrumb schema missing"); if (!read(F.hub).includes(NEW_ROUTE)) throw new Error("Hub link missing"); if (!read(F.sitemap).includes(NEW_URL)) throw new Error("Sitemap URL missing"); if (sha(F.template) !== templateHash) throw new Error("Source template changed"); if (sha(F.adsConfig) !== adsHash) throw new Error("Ads config changed"); if (JSON.stringify(protectedSnapshot()) !== JSON.stringify(protectedBefore)) throw new Error("Protected core changed"); const runtimeAfter = { tuvi: fs.existsSync(F.tuviRuntime) ? sha(F.tuviRuntime) : "[MISSING]", tutru: fs.existsSync(F.tutruRuntime) ? sha(F.tutruRuntime) : "[MISSING]" }; if (JSON.stringify(runtimeAfter) !== JSON.stringify(runtimeBefore)) throw new Error("Runtime JS changed"); } function rollback() { for (const file of [F.hub, F.sitemap]) { const src = path.join(BACKUP, path.relative(ROOT, file)); if (fs.existsSync(src)) fs.copyFileSync(src, file); } if (fs.existsSync(F.articleDir)) fs.rmSync(F.articleDir, { recursive: true, force: true }); if (fs.existsSync(F.test)) fs.rmSync(F.test, { force: true }); fs.rmSync(BACKUP, { recursive: true, force: true }); console.log("[KNOWLEDGE-MA-Y-MA-THI-1] ROLLBACK PASS"); } let mutated = false; try { const templateHash = sha(F.template); const adsHash = sha(F.adsConfig); const protectedBefore = protectedSnapshot(); const runtimeBefore = { tuvi: fs.existsSync(F.tuviRuntime) ? sha(F.tuviRuntime) : "[MISSING]", tutru: fs.existsSync(F.tutruRuntime) ? sha(F.tutruRuntime) : "[MISSING]" }; preflight(); run("npm.cmd test", "BASELINE FULL REGRESSION"); backup(); mutated = true; buildArticle(); addHubCard(); updateSitemap(); createTest(); run("node --check tests/knowledgeMaYMaThiArticle.test.mjs", "NEW TEST SYNTAX CHECK"); validate(templateHash, adsHash, protectedBefore, runtimeBefore); run("npm.cmd test", "FULL REGRESSION"); validate(templateHash, adsHash, protectedBefore, runtimeBefore); console.log("\n=================================================="); console.log("KNOWLEDGE-MA-Y-MA-THI-1 PASS"); console.log("=================================================="); console.log("New research article route created: PASS"); console.log("Article + Breadcrumb JSON-LD: PASS"); console.log("Knowledge hub card added: PASS"); console.log("Sitemap entry added: PASS"); console.log("Source template unchanged: PASS"); console.log("Protected Tử Vi/Tứ Trụ canonical/core unchanged: PASS"); console.log("Tử Vi/Tứ Trụ runtime JS unchanged: PASS"); console.log("Ads config remains enabled:false: PASS"); console.log("FULL REGRESSION EXPECTED: 403/403"); console.log("backup=" + BACKUP); console.log("NOT DEPLOYED"); } catch (error) { console.error("\nKNOWLEDGE-MA-Y-MA-THI-1 FAILED"); console.error(error?.stack || error); if (mutated) { rollback(); run("npm.cmd test", "ROLLBACK FULL REGRESSION"); console.log("PATCH ROLLED BACK. NOTHING DEPLOYED."); } process.exitCode = 1; } ``` Sau khi lưu file, chạy: ```powershell id="dfgvxz" Set-Location "D:\MenhLyASinh-Web" node --check .\KNOWLEDGE_MA_Y_MA_THI_1_RUNNER.mjs node .\KNOWLEDGE_MA_Y_MA_THI_1_RUNNER.mjs ``` Mục tiêu là `403/403 PASS`. Nếu PASS, gửi em block cuối. Em sẽ chốt deploy và sau deploy tự smoke production route mới, Knowledge hub, sitemap, canonical/schema và xác nhận Ads vẫn OFF.