---
url: https://docs.nemo12.com/architecture/sdd-026-family-journey.md
description: >-
  Bản nháp Family Journey (SDD-026): theo dõi từng người trong nhà đang ở bước
  nào trong bảy bước và bước gần nhất là gì.
---

# SDD-026 — Family Journey

[Dory](sdd-024-dory.md) trả lời *"ta biết gì về gia đình này?"*. Nó **không** trả lời được một câu mà mentor hỏi mỗi ngày: *"nhà này đang ở đâu, và việc gần nhất tôi nên làm là gì?"*

Đọc ba mươi bảy note để tự rút ra câu trả lời đó là việc không ai làm mỗi sáng. Journey là lớp mỏng đặt lên trên Dory để trả lời đúng hai câu ấy, **cho từng người một** chứ không cho cả nhà.

## 1. Vì sao theo TỪNG NGƯỜI, không theo cả nhà

Bốn ghi chép thật cho thấy các thành viên trong cùng một nhà ở những chỗ rất khác nhau:

* **Nhà Trí Minh**: bố Dũng đã hào hứng và đang đòi hiểu phương pháp, trong khi chính Minh mới đang thử và chưa ai biết em nghĩ gì.
* **Nhà Anh Tú**: mẹ đã tin tới mức đổi định hướng học của con theo một lời tư vấn, còn Tú thì *"chưa chắc là muốn, hay đang đi theo lời người lớn"* — đúng câu ghi chép tự đặt ra.

Gán một bước cho cả nhà sẽ **xoá mất chính khoảng cách đó**, mà khoảng cách đó lại là thứ đáng làm gì nhất. Vì vậy đơn vị của journey là **một người**: mỗi liên hệ trong `family_contacts` và mỗi learner.

## 2. Bảy bước

Đây **không phải phễu bán hàng**. [PRD-003](../product/prd-003-dory-anchor.md) §8 đã từ chối CRM bán hàng và điểm số gia đình; journey này là **hành trình hiểu nhau**, và nó đo quan hệ chứ không đo doanh thu.

| # | Bước | Với phụ huynh | Với học sinh |
| --- | --- | --- | --- |
| 1 | `unknown` | Chưa biết Nemo12 là gì | Chưa từng chạm vào |
| 2 | `met` | Đã gặp: buổi offline, được giới thiệu, thăm nhà | Đã gặp mentor một lần |
| 3 | `exploring` | Đang hỏi: phương pháp thế nào, con tôi hợp không | Đang thử xem có thích không |
| 4 | `tried` | Đã cho con thử một buổi, đã vào hệ thống xem | Đã làm bài đầu tiên |
| 5 | `engaged` | Theo sát đều, trao đổi thường xuyên | Học đều, tự quay lại |
| 6 | `trusting` | **Hành động theo lời tư vấn**, kể cả khi chưa hiểu hết phương pháp | **Tự đặt mục tiêu** thay vì làm theo yêu cầu |
| 7 | `advocating` | Giới thiệu gia đình khác | Kéo bạn vào, tự dẫn dắt việc học của mình |

Bảy bước, mỗi bước là một trạng thái **quan sát được**, không phải một cảm giác.

**Bước 6 là bước quan trọng nhất và cũng dễ hiểu sai nhất.** *"Tin"* ở đây không có nghĩa là quý mến; nó có nghĩa là **hành động thay đổi vì lời tư vấn**. Mẹ Tú đổi định hướng từ Chuyên Toán sang Chuyên Tin ngay sau một buổi nói chuyện — đó là bước 6, có bằng chứng. Bố Dũng rất hào hứng và khoe với bạn bè nhưng vẫn đang đòi được giải thích phương pháp — đó vẫn là bước 3, dù cảm xúc thì nồng nhiệt hơn.

## 3. Máy nhìn được hành vi, không nhìn được niềm tin

Đây là ranh giới quan trọng nhất của thiết kế này.

| Bước | Suy ra được bằng luật? | Vì sao |
| --- | :-: | --- |
| 1 `unknown` | ✅ | không có note nào, không có tài khoản |
| 2 `met` | ✅ | có note gắn `event` |
| 3 `exploring` | ✅ | có note về người này ngoài `event` |
| 4 `tried` | ✅ | đã đăng nhập, hoặc learner có hoạt động học |
| 5 `engaged` | ✅ | có hoạt động trong 30 ngày gần nhất |
| 6 `trusting` | ❌ | **chỉ người khẳng định được** |
| 7 `advocating` | ❌ | **chỉ người khẳng định được** |

Năm bước đầu là **dấu vết để lại trong hệ thống**. Hai bước cuối là **phán đoán về một con người**, và không có tín hiệu nào trong D1 chứng minh được chúng: một phụ huynh đăng nhập mỗi ngày vẫn có thể chưa tin ai, còn một phụ huynh không bao giờ đăng nhập vẫn có thể đổi cả định hướng học của con vì một câu tư vấn.

Nên hệ **đề xuất tối đa tới bước 5**, và bước 6-7 chỉ lên khi có người bấm. Đúng nguyên tắc đã chốt xuyên suốt: máy đề xuất, người quyết ([Q31](../product/family-notes-review/answers.md)).

### Giới hạn hiện tại: với phụ huynh, dấu vết chỉ có ở mức GIA ĐÌNH

Note gắn được với một learner cụ thể (`family_notes.learner_id`) nhưng **không gắn được với một liên hệ cụ thể**. Hệ quả thật, không phải chi tiết kỹ thuật: **bố và mẹ trong cùng một nhà luôn được hệ suy ra cùng một bước**, cho tới khi có người bấm xác nhận khác đi.

Nói cách khác, ví dụ ở §1 — *bố Dũng đã hào hứng còn Minh thì chưa* — hệ **chỉ phân biệt được** khi có người xác nhận bước cho bố. Phần máy tự làm được mới dừng ở mức "nhà này đang ở đâu".

Đây là đánh đổi có ý thức, không phải chỗ bị bỏ sót. Sửa được bằng một cột `contact_id` trên `family_notes`, nhưng cột đó đi ngược nguyên tắc "ít fields" đã chốt, và chỉ đáng thêm khi thấy nhu cầu thật. Trong lúc đó, **giao diện phải nói rõ** bước của phụ huynh là suy ra ở mức gia đình.

## 4. Bước gần nhất, và điều kiện để tới đó

Giá trị thật không nằm ở cái nhãn mà ở câu **"để lên bước sau thì cần gì"**. Mỗi bước có đúng một điều kiện, viết bằng thứ quan sát được:

| Từ → tới | Cần gì | Với học sinh thì là |
| --- | --- | --- |
| 1 → 2 | Một lần gặp thật, dù chỉ mười phút | Gặp mentor một lần |
| 2 → 3 | Họ **hỏi lại** một câu về cách học | Em hỏi lại một câu ngoài bài |
| 3 → 4 | Con làm thử một buổi | Làm xong bài đầu tiên |
| 4 → 5 | Quay lại lần thứ hai mà không cần ai nhắc | Tự quay lại học |
| 5 → 6 | Họ **làm một việc khác đi** vì lời tư vấn | Em tự đặt một mục tiêu của riêng mình |
| 6 → 7 | Họ kể cho một gia đình khác | Em rủ một người bạn |

Bước gần nhất **luôn là bước liền sau**, không nhảy cóc. Một hệ gợi ý "nhà này nên lên thẳng bước 7" là một hệ đang nói điều vô nghĩa.

## 5. Lùi bước là chuyện bình thường

Một gia đình đang ở bước 5 có thể rơi về 4 khi im lặng hai tháng. **Journey không phải cái thang một chiều**, và việc lùi:

* **không phải lỗi của mentor** — cùng nguyên tắc đã chốt cho escalation ở [Anchor](sdd-025-anchor.md) §1;
* **được ghi lại như mọi thay đổi khác**, để nhìn ra xu hướng chứ không để trách ai;
* **không bao giờ hiện cho gia đình**. Journey là công cụ nội bộ. Một phụ huynh nhìn thấy mình đang bị xếp ở "bước 3" là một phụ huynh sẽ không bao giờ tin nơi này nữa.

## 6. Dữ liệu — một bảng nhỏ, lịch sử miễn phí

```text
family_journey   family_id · member_kind(contact|learner) · member_id
                 · stage · confirmed_by → users · confirmed_at · updated_at
                 PRIMARY KEY (member_kind, member_id)
```

Sáu cột. **Chỉ lưu bước ĐÃ ĐƯỢC NGƯỜI XÁC NHẬN**; bước hệ suy ra thì tính tại chỗ mỗi lần đọc, không lưu — một bảng chứa kết quả suy luận sẽ đầy hàng lặp lại mỗi lần cron chạy, đúng lỗi đã tránh ở [SDD-024](sdd-024-dory.md) §5.

**Lịch sử không cần bảng riêng.** Mỗi lần một người xác nhận bước mới, hệ ghi thêm **một note gắn `event`** vào chính `family_notes`: *"Journey: Mẹ Loan moved to trusting"*. Thế là dòng thời gian của journey nằm chung dòng thời gian của mọi thứ khác — đúng chỗ người ta sẽ tìm nó.

## 7. API

| Method | Path | Quyền |
| --- | --- | --- |
| GET | `/v1/mentor/families/{id}/journey` | 🔐 role `mentor` |
| PUT | `/v1/mentor/journey/{kind}/{memberId}` | 🔐 role `mentor` |

`GET` trả cho **mỗi thành viên**: bước hệ suy ra kèm lý do, bước người đã xác nhận (nếu có), bước đang hiệu lực, bước kế tiếp và điều kiện để tới đó.

**Bước hệ suy ra luôn kèm câu giải thích.** Một con số bước không nói được vì sao thì người nhận chỉ có hai lựa chọn: tin mù, hoặc tắt đi — cùng lý do `reason` là `NOT NULL` ở tín hiệu Dory.

## 7b. Chữ của engine dịch được (SRC-628)

Ba nhóm chữ do engine sinh — nhãn bảy bước, mười hai câu **điều kiện lên bước** (§4), và bảy câu **lý do máy suy ra** (§3) — trước đây là tiếng Anh ghép sẵn trong `journey.ts`.

Chúng là **chỗ tiếng Anh cuối cùng** còn sót khi cổng bật tiếng Việt, và [SDD-023 §20](sdd-023-family-workspace/disclosure-and-albums.md#20-câu-của-scorecard-dịch-được-src-626) đã phải mở riêng một lối thoát `raw` cho chúng. Nay engine trả `Phrase` (khoá + tham số) như scorecard, và **lối thoát `raw` đóng lại**.

Kiểu `Phrase` tách sang `phrase.ts` dùng chung: hai module cùng một khái niệm mà mỗi bên khai một kiểu thì client phải viết hai hàm dựng câu, và bản thứ hai sẽ lệch bản thứ nhất.

**Điều kiện lên bước mang cả `stage` lẫn `kind` trong khoá** (`next.exploring.parent`). Điều kiện của bố mẹ và của bé khác nhau ở **mọi** bước — gộp một khoá rồi chèn "bố mẹ"/"em" vào sẽ ra những câu đúng ngữ pháp mà sai nội dung.

### Một bộ từ vựng, không phải hai

Trước đợt này bảy bước có **hai cách gọi**: `STAGE_LABEL` ở đây (*"Asking questions"*) và một bộ riêng trong catalog của scorecard (*"exploring"*). Cùng một bước, hai cái tên, tuỳ chỗ nhìn — người dùng không có cách nào biết đó là một thứ. Nay chỉ còn bộ của **§2 tài liệu này**; catalog của scorecard trỏ về đúng nó.

## 8. Cái cố ý KHÔNG làm

| Việc | Vì sao |
| --- | --- |
| Điểm số journey cho cả gia đình | Một số tổng che mất thứ nó tổng hợp; xem [Q-137](../open-questions/index.md) và [PRD-003](../product/prd-003-dory-anchor.md) §8 |
| Xếp hạng mentor theo số nhà lên bước | Escalation và journey đều để cứu việc, không để bắt lỗi người |
| Hiện journey cho phụ huynh | §5 |
| Tự động đẩy bước khi đủ điều kiện | Hệ **đề xuất**, người bấm. Một bước tự nhảy là một phán đoán không ai chịu trách nhiệm |
| Dùng AI đoán bước 6-7 | §3: không có tín hiệu nào trong dữ liệu chứng minh được niềm tin. AI đoán ở đây chỉ là đoán có văn phong |

## Trace

REQ-DOR-07→§2-3 · REQ-DOR-08→§4 · REQ-DOR-09→§6-7 · nền [SDD-024](sdd-024-dory.md) · nguồn [SRC-589](../intake.md).
