Skip to content

SDD-054 - Parent Model ​

Nguồn: SRC-1172, chủ dự án 01.10.2026: "Cần rà soát các evidence của các Parents trong Marlins, rồi đưa vào Evidence Registry. Rồi từ đó tính toán và update Parent Model. Trong admin.nemo12.com, cần có chỗ để tôi xem được chi tiết các model của từng parent." Migration: 0328_parent_evidence_registry_and_parent_model.sql, 0330_parent_ebook_reading_progress.sql. Mã: workers/api/src/modules/parentModel/, và trang Parents của admin. Cùng khuôn với lát cắt IELTS của learner (SRC-849, SDD-038).

1. Rà soát: phụ huynh đang để lại những gì ​

Đo trên D1 production ngày 01.10.2026. Dấu vết của phụ huynh nằm rải ở tám bảng, mỗi bảng một hình dạng, và không bảng nào biết về bảng kia:

NguồnDòngViệc nó ghi lại
milestones66đặt mốc cho con
invitations48mời con vào học, mời thêm người giám hộ
family_notes37ghi chú về gia đình
learner_context_events15báo hoàn cảnh của con
parent_course_progress6đọc xong chỗ học, làm quiz trong khoá CHO BỐ MẸ
portraits6dựng Student Portrait
community_event_registrations5đăng ký sự kiện
parent_beliefs0tự khai mức lo và dự đoán về con

Tổng khoảng 183 mẩu. Hai bảng rỗng (parent_beliefs, portrait_reactions) vẫn được nối vào vì đường ghi đã có trên Marlins, chỉ là chưa ai dùng; nối sẵn thì ngày đầu tiên có người dùng là mẩu ấy vào sổ ngay, không phải chờ một lượt sửa mã.

Kết luận của bước rà soát: không có câu truy vấn nào trả lời được "phụ huynh này đã để lại những gì", nên cũng không có cách nào tính ra một model về họ.

2. Vì sao một sổ RIÊNG, không dùng learner_evidence ​

Khoá ngoại của sổ cũ là learner_id REFERENCES learners(id). Một phụ huynh là một dòng users. Nhét user_id vào cột ấy thì hoặc vi phạm khoá ngoại, hoặc phải nới nó ra - mà nới là mất đúng thứ đang giữ cho sổ của learner không lẫn người lạ.

Sổ riêng còn giữ được một khác biệt thật: bằng chứng của learner nói về năng lực của chính họ, còn bằng chứng của phụ huynh phần lớn nói về việc họ làm cho một người khác. Vì thế parent_evidence có thêm about_learner_id, thứ không có nghĩa gì trong sổ của learner.

Giữ nguyên ba tính chất của Evidence Registry (SDD-002 §5): bất biến, có khoá chống ghi trùng, và mang mốc thời điểm việc xảy ra chứ không phải lúc ghi sổ.

3. Bốn chiều ​

Marlins đứng trên một câu: "Mục tiêu của việc làm bố mẹ không phải là khiến con phụ thuộc vào những bố mẹ tốt hơn. Mà là giúp con đủ sức sống mà không cần mình." Model vì thế đo họ đang ở đâu trên đường đó, không đo họ chăm chỉ tới mức nào.

ChiềuTrả lời câuNguồn nuôi nó
learningchính bố mẹ có đang học khôngparent_course_progress
understandinghọ hiểu con tới đâuportraits, parent_beliefs, learner_context_events
actinghiểu biết đã thành việc làm chưamilestones, invitations
presencehọ có quay lại đều đặn khôngfamily_notes, community_event_registrations

Bốn chiều này là một quyết định sản phẩm, không phải một sự thật toán học. Chúng được chọn vì mỗi chiều có ít nhất một nguồn CÓ THẬT trong bảng §1: một chiều không nguồn chỉ là ô trống làm màn admin trông đầy đặn hơn sự thật. Đổi bộ chiều thì phải tăng PARENT_MODEL_VERSION.

4. Phép tính ​

Điểm một chiều là trung bình có trọng số, trọng số = reliability × freshness.

  • Độ tin cậy ba bậc, cùng thang với sổ learner: .90 việc máy đo được (đọc xong chỗ học, làm quiz, ghi danh) · .70 việc quan sát được nhưng tự khai nội dung (viết ghi chú, đặt mốc, dựng chân dung) · .50 lời tự khai thuần.
  • Độ mới giảm theo nửa đời 120 ngày. Đủ dài để một phụ huynh bận ba tháng không tụt về 0, đủ ngắn để model không khoe mãi một lần hoạt động duy nhất từ năm ngoái.
  • Hai thứ nhân nhau chứ không cộng: một lời tự khai từ năm ngoái phải nhẹ ở cả hai chiều, mà phép cộng vẫn cho nó một nửa tiếng nói.

null không phải 0. Chiều chưa có mẩu nào trả về null, và chiều mà MỌI mẩu đã quá cũ cũng trả về null: khi không còn dám nói gì về hôm nay thì im lặng là câu trả lời đúng. Một số 0 ở đây sẽ bị đọc thành "phụ huynh này tệ", trong khi sự thật là "ta không biết".

Không có điểm tổng, và đó là chủ ý. Một con số duy nhất sẽ xếp hạng con người, giấu mất chiều đang yếu (thứ duy nhất đáng hành động), và mời người đọc so sánh hai gia đình không so sánh được.

Xu hướng cần ít nhất 4 mẩu. Với 2 hay 3 mẩu thì "xu hướng" chỉ là một mẩu lẻ đứng một mình, và một mũi tên đi xuống vì một lần duy nhất là một lời cáo buộc chứ không phải một quan sát.

confidence của cả lát cắt tính cả chiều rỗng: dày dữ liệu ở đúng một chiều không có nghĩa là ta hiểu người này.

5. Ảnh chụp, không phải một ô ghi đè ​

parent_models lưu từng ảnh chụp như ielts_learner_models (0229). Chỉ ghi dòng mới khi có gì đó đổi: thêm bằng chứng, đổi bản thuật toán, hoặc một trong bốn chiều đổi số. Mở trang mười lần trong một buổi không được đẻ ra mười ảnh giống hệt nhau - lịch sử toàn dòng trùng thì không đọc ra được đường đi nào, mà đọc đường đi đúng là lý do lưu lịch sử.

6. Đường chạy ​

ĐườngViệc
POST /v1/admin/parents/backfill-evidencerà tám nguồn, nạp mẩu còn thiếu; chạy lại không sinh bản trùng
POST /v1/admin/parents/recomputetính lại model cho mọi phụ huynh có bằng chứng
GET /v1/admin/parentsdanh sách kèm ảnh chụp mới nhất
GET /v1/admin/parents/{userId}lát cắt đang hiệu lực + lịch sử
GET /v1/admin/parents/{userId}/evidencesổ bằng chứng, mới nhất trước
POST /v1/admin/parents/{userId}/recomputetính lại một người

Tất cả đòi vai admin (QG-008): đây là dữ liệu về NGƯỜI, không phải dữ liệu của chính người đang đăng nhập. Mở một phụ huynh để lại một dòng ParentModelViewed trong nhật ký truy cập.

Nạp bù là một đường chạy riêng, không nằm trong migration: nó đọc tám bảng và phải chạy lại được bất cứ lúc nào, kể cả sau khi đã có dữ liệu mới.

7. Chưa mở cho chính phụ huynh, và vì sao ​

Bốn con số 0..1 về một người, hiện thẳng cho chính họ, sẽ đọc thành một bảng điểm làm-bố-mẹ - đúng thứ Marlins nói là không nên làm với trẻ con, nên cũng không nên làm với bố mẹ. Nếu sau này mở, nó phải mở dưới dạng gợi ý việc làm ("chỗ học tiếp theo cho bạn") chứ không dưới dạng điểm.

8. Lượt chạy đầu, và ba nguồn thêm sau nó (SRC-1228) ​

Lượt nạp bù và tính model đầu tiên chạy 04.10.2026: 182 mẩu, 32 phụ huynh, không nguồn nào lỗi. Kết quả đọc ra một điều mà thiết kế không đoán trước được:

ChiềuSố phụ huynh KHÔNG có mẩu nào
Có mặt27 / 32
Tự học26 / 32
Hiểu con24 / 32
Hành động2 / 32

Gần như mọi người chỉ có đúng một chiều, và đó là chiều Hành động - vì đặt mốc cho con và mời con vào học là việc ai cũng làm ngay khi lập tài khoản. Ba chiều còn lại trống không phải vì phụ huynh không làm gì, mà vì cổng này không ghi lại việc họ làm.

Chỉ đạo chủ dự án 04.10.2026: "Thêm đường ghi cho 'có mặt' và 'tự học' đi." Ba nguồn thêm vào:

NguồnChiềuTin cậyGhi chú
sessions (phiên đăng nhập)Có mặt.90chỉ phiên GỐC
email_opens (mở thư tuần)Có mặt.50chỉ lượt direct
parent_ebook_progress (đọc sách)Tự học.90mở .4, đọc xong 1.0

Chỉ phiên gốc (rotated_from IS NULL): token tự xoay trong lúc dùng nên một lần đăng nhập đẻ ra nhiều dòng. Đếm cả dòng xoay là đo tuổi phiên chứ không đo số lần quay lại - trên production 04.10.2026, 209 dòng chỉ ứng với 178 lần đăng nhập thật.

Chỉ lượt mở direct: ảnh theo dõi trong thư bị máy chủ thư tải hộ trước khi người ta mở, và Gmail tải qua proxy của họ. Một lượt proxy chứng minh máy chủ Google đã chạm vào thư, không chứng minh người nào đã đọc. Trên production 363/442 lượt là proxy: đếm cả chúng là dựng một chiều "có mặt" đo hạ tầng của Gmail. Ngay cả direct cũng yếu (khung xem trước cũng tải ảnh), nên nó mang độ tin cậy bậc thấp nhất và không bao giờ nặng bằng một lần đăng nhập.

Đọc sách tách MỞ khỏi ĐỌC XONG. Thư viện Marlins có 20 quyển và trang đọc chạy từ SRC-673, nhưng đọc xong một chương không để lại dấu vết nào. Nay parent_ebook_progress ghi hai mốc: opened_at (lần đầu mở) và finished_at (lần đầu cuộn hết chương, đo bằng IntersectionObserver ở khối cuối trang). Gộp cả hai thành "đã đọc" là biến một cú bấm nhầm thành bằng chứng ngang với một buổi ngồi đọc thật. Cả hai mốc chỉ đặt MỘT lần: mở lại hay đọc lại không đẩy mốc về hôm nay, vì mốc phải trả lời "họ bắt đầu học khi nào".

9. Còn nợ ​

  • Chưa có đường ghi trực tiếp: mẩu mới chỉ vào sổ khi chạy nạp bù. Đường ghi thẳng lúc việc xảy ra là bước sau, và event_id đã dựng tất định nên hai đường không đụng nhau.
  • Chưa nối portrait_reactions và family_journey (cả hai đang 0 dòng).
  • Chưa có lịch chạy lại định kỳ; hiện là hai nút trong admin.