Skip to content

Audit #005 — Hệ tài liệu ​

Audit chuyên đề, không phải audit toàn hệ. Audit #004 đã chấm cả 255 chỉ báo và cho AS-01 (Tài liệu & Đóng vết) 18/25; bản này đào sâu đúng bộ đó bằng những phép đo mà chuẩn không có sẵn công cụ, để biến "18/25" thành danh sách việc làm được.

Không đặt thang điểm mới. Audit Standard đã cấm trục chấm thứ hai chồng lên PASS/KHÔNG PASS (§1.2). Mỗi phát hiện dưới đây vì vậy được nối thẳng về chỉ báo AS tương ứng, hoặc ghi rõ là ngoài phạm vi chỉ báo hiện có — chính chỗ đó là đề xuất mở rộng chuẩn.

1. Hệ tài liệu đang là gì ​

Số file .md trong docs/93
Tổng dòng19.849
Theo loạireference 40 · sdd 32 · index 11 · quality 6 · prd 3 · convention 1
Theo trạng tháiactive 78 · draft 15
Dài nhấtreference/data-dictionary.md (2.167 dòng, sinh tự động)

Cổng check-docs.mjs (QG-001) xanh: 93/93 file đủ frontmatter, id duy nhất, không link nội bộ gãy, trace satisfies ↔ REQ đóng.

2. Phát hiện ​

Xếp theo mức hại, không theo thứ tự đo.

D1 · Sổ tiếp nhận chạy nhanh gấp đôi việc canonical hoá (AS-01.1.3) ​

232/415 SRC (56%) chưa xuất hiện ở bất kỳ PRD, SDD, QG hay reference nào ngoài chính intake.md.

text
phân bố theo khoảng SRC:  0-49: 2 · 50-99: 25 · 100-149: 14 · 150-199: 35
                          200-249: 24 · 250-299: 45 · 300-349: 43 · 350-399: 34 · 400+: 10

Đây không phải nợ của riêng giai đoạn đầu: khoảng 250-399 (những chỉ đạo gần đây nhất) đóng góp 122/232. Nghĩa là tốc độ tiếp nhận đang vượt tốc độ đưa vào tài liệu chuẩn, và khoảng cách ngày càng rộng chứ không hẹp lại.

Hệ quả cụ thể, không phải lý thuyết: một quyết định chỉ nằm ở intake.md thì không ai tìm ra nó khi đọc tài liệu thiết kế. Ví dụ đang chạy: cột Parents của admin (SRC-404) và cổng phủ xác thực (SRC-412) đều có mã trên production mà không REQ nào mô tả.

D2 · Tài liệu yêu cầu gốc vẫn là draft sau 438 dòng REQ (ngoài phạm vi chỉ báo) ​

prd-001-nemo12-platform.md mang status: draft, trong khi nó chứa 438 dòng REQ, trong đó 258 đánh ✔ (đã làm). Một tài liệu mà hơn một nửa nội dung đã thi hành xong và đang chạy cho người dùng thật thì không còn là bản nháp.

Không chỉ báo AS nào bắt được điều này: AS-01.2.5 chỉ đòi status thuộc tập cho phép, không hỏi trạng thái ấy có còn đúng không. Đề xuất mở rộng chuẩn.

D3 · last_reviewed là trường trang trí (ngoài phạm vi chỉ báo) ​

25/93 doc có last_reviewed CŨ HƠN ngày sửa file thật. Vài ca nặng:

DocKhai last_reviewedSửa thật lần cuối
docs/index.md2026-08-152026-08-20
docs/intake.md2026-08-152026-08-20
traceability.md2026-08-142026-08-19
prd-001-nemo12-platform.md2026-08-152026-08-19
reference/engines.md2026-08-142026-08-19

AS-01.5.1 vẫn PASS vì ngưỡng của nó là 90 ngày, quá rộng để bắt được chuyện này. Nhưng ý nghĩa của trường đã mất: người đọc thấy last_reviewed: 2026-08-14 sẽ tưởng nội dung đã đứng yên từ hôm đó, trong khi nó vừa đổi hôm qua. Đề xuất: cổng CI chặn commit sửa nội dung doc mà không cập nhật last_reviewed — đo được, rẻ, và đóng luôn AS-01.5.2 (hiện là mã CM vì không ai spot-check nổi bằng tay).

D4 · Một doc mồ côi, và nó đúng là doc của chỉ báo 🔴 (AS-01.3.4) ​

docs/ops/backup-restore-drill.md không được file nào trong docs/ trỏ tới. Nó là tài liệu duy nhất phục vụ AS-04.5.5 🔴🚸 (diễn tập backup/restore), tức chỉ báo đang chặn Pilot Gate. Doc tồn tại nhưng không có đường đi tới thì khi cần dùng thật sẽ không ai tìm ra.

D5 · Hai SDD active mô tả bảng chưa từng được xây (ngoài phạm vi chỉ báo) ​

Đối chiếu mọi cụm "bảng `x`" trong doc status: active với 101 bảng thật trong migrations/:

DocBảng được mô tảTrạng thái thật
sdd-010-lab-platform.md:61inquirieskhông tồn tại
sdd-009-media.md:38media_linkskhông tồn tại

Hai câu ấy viết ở thì khẳng định chứ không phải thì dự định, nên người đọc SDD sẽ đi tìm bảng không có. (Ba ca khác mà phép đo bắt được là âm tính giả, đã soi tay: alignment_scores được nêu trong một câu nói rõ "không có bảng này và không nên có"; onboarding_learner_profiles là bảng của hệ chuyenchon cũ, không phải của Nemo12; d1_migrations là bảng do wrangler tự tạo.)

D6 · Ba đường dẫn mã nguồn trong docs đã chết (ngoài phạm vi chỉ báo) ​

DocĐường dẫn
sdd-001-platform.md:137packages/shared/configkhông tồn tại
open-questions/index.md:118packages/aikhông tồn tại
intake.md:105scripts/whale-data-p1..p3.jsonkhông tồn tại

check-docs.mjs kiểm link .md nội bộ nhưng không kiểm đường dẫn mã nguồn nhắc trong văn bản. Đây là loại drift âm thầm: doc vẫn "xanh" trong khi chỉ sai.

D7 · Con số của chính bộ chuẩn còn hai chỗ nói bản cũ (AS-01.4.x tinh thần) ​

docs/index.md:34 và docs/quality/quality-gates.md:41 vẫn ghi Audit Standard có 250 chỉ báo, trong khi chuẩn hiện hành là v0.2 với 255. Hai trang này là cửa vào của cả hệ tài liệu, nên sai ở đây lan xa nhất.

D8 · 15 doc draft, 12 trong số đó là SDD ​

prd-001, open-questions, chuyenchon-app-requirements, legacy-feature-inventory, và SDD-012 → SDD-021. Phần lớn SDD trong nhóm này mô tả hệ đã chạy thật (SDD-017 Retention, SDD-019 Mentor Albums, SDD-020 School Registry, SDD-021 Learning Entry Sequencing đều có mã trên production). Cùng loại vấn đề với D2: nhãn trạng thái không theo kịp thực tế.

3. Việc sinh ra từ audit này ​

#ViệcĐóngCỡ
T1Sửa hai con số 250 → 255 ở index.md và quality-gates.mdD7rất nhỏ
T2Nối ops/backup-restore-drill.md vào docs/index.mdD4, AS-01.3.4rất nhỏ
T3Sửa ba đường dẫn chết; đổi hai câu SDD sang thì dự định hoặc xây bảngD5, D6nhỏ
T4Cổng CI: sửa nội dung doc thì bắt buộc cập nhật last_reviewedD3, AS-01.5.2vừa
T5Cổng CI: đường dẫn mã nguồn nhắc trong docs phải tồn tạiD6nhỏ
T6Chuyển status của các SDD đang chạy thật từ draft sang active; quyết định riêng cho PRD-001D2, D8vừa
T7Canonical hoá 232 SRC còn treo, bắt đầu từ SRC có mã đang chạy productionD1, AS-01.1.3, AS-02.4.2LỚN

T7 là việc lớn và không làm một lần được. Đề xuất cách chia: mỗi phiên sửa mã cho một SRC thì canonical hoá luôn SRC đó, và mỗi tuần dọn một khối 20 SRC cũ theo thứ tự mới nhất trước (vì SRC mới còn nhớ được bối cảnh, SRC cũ thì phải khảo cổ).

4. Trace ​

NguồnChuẩnGhi vào
SRC-416 (chỉ đạo: "audit toàn bộ hệ thống tài liệu, hệ thống admin này, tạo ra các audit report, sau đó fix dần")audit-standard/index.md v0.2 — bản này bổ trợ AS-01, không thay thang điểmbáo cáo này + index + việc T1..T7

5. Đã sửa — 2026-08-20, ngay sau khi chấm ​

ViệcKết quả kiểm được
T1Hai chỗ nói Audit Standard có 250 chỉ báo (index.md, quality-gates.md) sửa thành 255. Kèm dọn cây thư mục ở index.md, vốn còn ghi SRC-001..111, Q-001..127, SDD-001..017 trong khi thực tế là SRC-001..416 · Q-001..137 · SDD-001..021, và thiếu hẳn thư mục ops/. Con số lấy bằng cách đếm từ chính các file, không gõ tay. → D7 đóng
T2ops/backup-restore-drill.md và ops/migration-reconciliation.md nay có một dòng riêng trong bản đồ theo domain của index.md. Đếm lại: 0 doc mồ côi. → D4 đóng
T3Bốn câu khẳng định sai sửa thành khẳng định trung thực, mỗi câu nói rõ thứ đó chưa dựng và hiện đang nằm ở đâu: packages/shared/config (SDD-001), packages/ai ×2 (open-questions), bảng media_links (SDD-009), bảng inquiries (SDD-010). → D5, D6 đóng
T5scripts/check-docs-drift.mjs, chạy trong npm run check:docs nên nằm trong CI. Bắt ba loại trôi mà QG-001 không thấy: đường dẫn mã nguồn đã chết · doc mô tả bảng D1 chưa tồn tại · doc mồ côi

Cổng chống trôi có thật sự bắt được không ​

Thêm một dòng drift giả vào reference/engines.md rồi chạy:

text
✗ SRC-416 — 2 chỗ tài liệu đã trôi khỏi mã đang chạy:
  docs/reference/engines.md:296  đường dẫn không tồn tại: workers/api/src/khong-he-ton-tai.ts
  docs/reference/engines.md:296  mô tả bảng chưa tồn tại: bang_ma_khong_co

Gỡ dòng đó ra thì xanh lại. Cổng có răng, không phải xanh giả.

Chính cổng này lỗi ngay lần đầu lên CI, và đó là bài học đáng giữ. Nó xanh ở máy nhưng đỏ trên CI, vì nó đo bằng existsSync trên thư mục làm việc: apps/data là app đã ngừng, git không còn tệp nào, nhưng ở máy vẫn sót một thư mục rỗng chứa .env cũ. Một cổng cư xử khác nhau ở hai nơi thì tệ hơn là không có cổng, vì nó dạy người ta bỏ qua kết quả CI. Đã sửa: cổng nay đo theo danh sách tệp git theo dõi, thứ giống hệt nhau ở mọi máy. Kèm thêm nhóm từ khoá thoát hiểm cho các câu nói về thứ đã ngừng dùng (hai câu về apps/data là tài liệu đúng, không phải drift).

Hai đường thoát hiểm cố ý, vì không có chúng thì cổng sẽ ép tài liệu nói dối:

  1. Câu văn tự nói ra rằng thứ đó chưa dựng, hoặc cố ý không dựng, thì không tính là trôi. Ví dụ SDD-020 viết "dựng bảng schools mới là tạo ra hai nguồn sự thật" — đó là một quyết định kiến trúc, không phải một lời sai.
  2. Sổ ghi chép theo thời gian được miễn trừ: intake.md và toàn bộ quality/audits/. Chúng ghi điều đã đúng tại một thời điểm, và luật của chính hệ audit là không sửa báo cáo cũ. Bắt một cuốn sổ cập nhật theo mã hiện tại là phá đúng công dụng của nó.

| T4 | scripts/check-docs-fresh.mjs thi hành đúng một luật đã viết sẵn ở conventions.md §4 ("Khi sửa nội dung đáng kể: tăng version, cập nhật last_reviewed") — luật có từ đầu, chỉ chưa ai thi hành. Phép đo: last_reviewed không được cũ hơn ngày commit gần nhất chạm vào chính file đó. Đo bằng git chứ không bằng mtime, vì mtime đổi cả khi chỉ git checkout. → D3 đóng, và AS-01.5.2 từ mã CM thành đo được bằng máy |

Nói thẳng về cách sửa 27 file lệch ngày: đây là một lần chỉnh đồng loạt cho khớp, KHÔNG phải một lần đọc lại nội dung 27 file. Gọi nó là "đã review" thì đúng chữ mà sai nghĩa. Giá trị nằm ở chỗ khác: từ nay cổng buộc mỗi lần sửa phải tự bump trong cùng commit, nên khoản nợ này không tích tụ lại được nữa. Báo cáo audit được miễn trừ khỏi cổng: last_reviewed của chúng là ngày chấm, và bắt chúng bump mỗi lần có ai gõ một dấu phẩy là làm hỏng đúng thứ khiến một báo cáo có giá trị.

| T6 | 9 doc chuyển draft → active, mỗi doc kèm bằng chứng đo được chứ không kèm cảm nhận |

DocBằng chứng chuyển sang active
SDD-013 Coralmodule coral + app Coral đã deploy
SDD-015 Student Portraitmodule portraits + 6 portrait thật
SDD-016 Orcamodule orca + 14 competition thật
SDD-017 Retentionmodule retention + 164 dòng learner_retention + cron 21:00 UTC
SDD-018 Community Eventsmodule events + bảng có dòng
SDD-019 Mentor Albums4 mentor_profiles + /v1/public/albums đang phục vụ
SDD-020 School Registry3 target_schools + trang trường công khai đang chạy
SDD-021 Learning Entry Sequencing667 cạnh unit_prereqs + hé cửa đang chạy trong learn
conventions.mdchính nó là luật mà bốn cổng CI đang thi hành, mà lại mang nhãn "bản nháp"

Hai doc CỐ Ý giữ draft, và đó là câu trả lời đúng: SDD-012 (Real Exam Bank) vì production có 0 dòng exams nào source_kind='real', và SDD-014 (Exam Acquisition) vì chưa có module crawler nào. Nhãn draft ở hai chỗ này đang nói đúng sự thật.

Bốn doc để chủ dự án quyết, vì đây là quyết định sản phẩm chứ không phải vệ sinh tài liệu: prd-001 (438 REQ, 258 đã ✔ — nhưng đổi trạng thái tài liệu yêu cầu gốc là việc của người sở hữu nó), open-questions/index.md, chuyenchon-app-requirements.md, legacy-feature-inventory.md. Riêng workflows/two-door-onboarding.md giữ draft đúng: grep toàn repo không thấy mã nào thi hành luồng hai cửa.

Hai lần cổng mới tự vấp, và vì sao đáng ghi lại ​

Cả hai cổng dựng trong đợt này đều xanh ở máy, đỏ trên CI ngay lần đầu. Cùng một nguyên nhân gốc: chúng đo một thứ không giống nhau ở hai nơi.

CổngĐo sai chỗ nàoSửa thành
Chống trôiexistsSync trên thư mục làm việc. apps/data là app đã ngừng, git không còn tệp nào, nhưng ở máy còn sót thư mục rỗng chứa .env cũĐo theo git ls-files — danh sách giống hệt ở mọi máy
last_reviewedgit log -1 trên bản clone nông. actions/checkout@v4 mặc định fetch-depth: 1, nên mọi tệp trả về cùng một commit và 55 doc đỏ oanNhận ra clone nông thì bỏ qua và nói rõ, thay vì đỏ oan; đồng thời đặt fetch-depth: 0 cho ci.yml và deploy-docs.yml để cổng thật sự chạy ở đó

Bài học chung, đáng đắt hơn cả hai cổng: một cổng cư xử khác nhau giữa máy và CI thì tệ hơn là không có cổng, vì nó dạy người ta bỏ qua kết quả CI. Và khi cổng không đủ dữ kiện để chấm thì nói thẳng là không chấm được vẫn tốt hơn là đỏ oan.

T7 — đợt đầu, và một con số tự nó nói ra vấn đề ​

Canonical hoá 6 REQ cho ba chỉ đạo mà mã đã chạy production nhưng tài liệu không mô tả:

REQ mớiBiến chỉ đạo nào thành luật
REQ-PLT-15Bảng learner của admin hiện phụ huynh, và supporter KHÔNG tính là phụ huynh (SRC-404)
REQ-PLT-16Màn hình admin phân biệt ba trạng thái đang tải · rỗng · hỏng; danh sách bị cắt phải nói ra (SRC-416)
REQ-PLT-17Hành động không hoàn tác được phải xác nhận; thao tác rủi ro thấp làm hàng loạt thì không hỏi (SRC-416)
REQ-PLT-18Mọi endpoint vận hành có đường vào từ giao diện (SRC-416)
REQ-SEC-07Phủ xác thực chứng minh được, đo bằng bảng route lúc chạy chứ không bằng grep (SRC-412)
REQ-DOC-07Tài liệu không được trôi khỏi mã đang chạy (SRC-416)

Cổng check-docs.mjs bắt ngay lỗi của chính đợt này: REQ-DOC-07 lúc đầu để trống ô SDD, và luật "REQ active phải trỏ tới một doc thiết kế" chặn lại. Đúng thứ một cổng nên làm.

Nhưng con số tổng thì đi ngược:

Lúc chấm auditSau đợt sửa này
Tổng SRC trong sổ415440
Chưa canonical hoá232263

Đóng được 3, sổ dài thêm 25. Khoảng cách rộng ra ngay trong chính phiên đang thu hẹp nó. Đây là bằng chứng sống cho D1, và nó nói rằng đuổi theo bằng tay là cách sai: chừng nào việc canonical hoá còn là một việc RIÊNG làm sau, nó sẽ luôn thua tốc độ ra chỉ đạo.

Đề xuất đổi cách, thay cho việc đuổi theo: buộc ràng buộc vào lúc GHI SỔ chứ không phải lúc dọn dẹp — một dòng SRC mới phải khai luôn nó sẽ nằm ở REQ/SDD nào, hoặc khai rõ "chưa canonical hoá" kèm hạn. Khi đó cổng đo được, và nợ không sinh thêm nữa; phần 263 dòng cũ mới đáng đem ra dọn dần.