---
name: study
trigger: "học tiếp | ôn bài | ôn tập | topic nào tới hạn | tiến độ học | bắt đầu học | học theo lộ trình | học có hệ thống"
requires: "learning-mode"
mutates: true
default_read_limit: "learning-progress.md + curriculum MOC + 1 topic note đang học"
desc: "Điều phối học theo curriculum: chọn topic → learning-mode dạy → chấm mastery có bằng chứng → ghi 4 việc lõi + 2 có điều kiện (thẻ/quest); state machine 1 nguồn, turn=state (v7)"
llm_managed: true
slash: study
slash_expand: "học tiếp {lĩnh vực}"
---

# Skill: STUDY — điều phối học theo curriculum

`study` là **cụm state điều phối + ghi** của một máy; KHÔNG tự dạy. Chỉ có MỘT Bob: ở state nào thì làm việc của state đó. learning-mode (L0–L6) là **cụm dạy** của cùng máy, không phải tiến trình riêng — không có chuyện "study ghi hộ" hay "study giám sát".

**Dùng khi:** "học tiếp / học theo lộ trình", "ôn bài / topic nào tới hạn", "tiến độ học tới đâu".
**KHÔNG dùng khi:** hỏi nhanh 1 khái niệm (→ `query`); học 1 chủ đề rời không gắn curriculum (→ `learning-mode` trực tiếp).

---

## Data model (NGUỒN DUY NHẤT — khớp dashboard `.base`)

Frontmatter mỗi topic note:
```yaml
learn_curriculum: <domain>   # membership để dashboard lọc (vd ai-pilot, ba) — curriculum set, study GIỮ
learn_order:                 # thứ tự topic trong domain — curriculum stamp · dashboard sort · study GIỮ (không tự tính)
learn_understood: []         # list token đã đạt — study QUẢN
learn_reviewed:              # ngày ôn gần nhất (YYYY-MM-DD) — study QUẢN
learn_next:                  # ngày ôn kế (spaced repetition) — study QUẢN
```

> **Phân quyền field:** study **chỉ tính/ghi 3 field mastery** (`learn_understood`/`reviewed`/`next`); `learn_curriculum` + `learn_order` do `curriculum` set, study **giữ nguyên không sửa** (S3 ① phải bảo toàn — xem §GHI). **NGOẠI LỆ DUY NHẤT — activate parked topic** (xem GATE A): khi user chọn 1 note **parked** (chưa có `learn_curriculum`), study set `learn_curriculum` + `learn_order = max+1` (append CUỐI DAG), **KHÔNG bao giờ reorder/đổi cái đã có**. Thứ tự học study lấy từ **curriculum MOC (DAG)**, không từ `learn_order`; `learn_order` chỉ phục vụ dashboard sort.

- **Rubric 17 token + 5 core ⭐** định nghĩa **canonical ở `learning-mode` §Rubric — KHÔNG chép lại ở đây.** study chỉ *map* token đã có bằng chứng → `learn_understood`.
- **🟢 nắm cơ bản** = đủ **5 core** (`essence`+`mechanism`+`application`+`discrimination`+`teach-back`) → mở khoá topic kế (soft gate). **✅ master** = đủ 17.
- **Đa lĩnh vực:** mỗi domain = 1 `learn_curriculum` + 1 curriculum MOC riêng; thứ tự/prereq ở MOC. `learn_next` độc lập từng note → học xen kẽ không xung đột.
- **Ranh giới lưu vs derive** (đọc kỹ — 2 loại khác nhau, đừng gộp):
  - **Derive, KHÔNG lưu riêng:** icon trạng thái (🟢/📖/⚪) + cờ "cần ôn" (⏰) → `dashboard-hoc-tap.base` tự tính từ frontmatter mỗi lần mở. Không chép tay đi đâu.
  - **Lưu nhiều nơi CÓ CHỦ ĐÍCH:** con số `M/17` xuất hiện ở `frontmatter` (chân lý) + `learning-progress.md` (bảng phẳng, regen tự động) + `so-hoc` (đọc offline không cần mở dashboard). Đây là đánh đổi cố ý — cái giá là **phải rà khớp ở S3** (xem §GHI cuối).

---

## Máy trạng thái — NGUỒN QUY TRÌNH DUY NHẤT (ngân sách đọc nằm ngay cột)

**Kiểu state:** **(D) DỪNG-CHỜ** kết bằng 1 câu hỏi rồi hết lượt · **(A) ACTION** chạy directive rồi đi tiếp cùng lượt, không hỏi.

```
S0 CHỌN_LĨNH_VỰC ▶ S1 MENU_TOPIC ──GATE A──▶ [learning-mode L0…L6] ──GATE B──▶ S2 CHẤM_MASTERY ──GATE C──▶ S3 GHI ▶ S4 CHỐT_PHIÊN
```

| State | Kiểu | Đọc TỐI ĐA | Hành động | GATE / nhánh |
|---|---|---|---|---|
| **S0 CHỌN_LĨNH_VỰC** | A | các `curriculum-<domain>` MOC | Hiện danh sách lĩnh vực, đẩy vào S1. | Lĩnh vực **MỚI** → `$$LOAD_SKILL: curriculum$$` scaffold trước, rồi quay lại. |
| **S1 MENU_TOPIC** | D | `learning-progress.md` (1 file = đủ menu) + MOC domain; nghi cũ → ≤**1–2** frontmatter ứng viên | Menu = note **có `learn_curriculum`** (active). Phân 3 nhóm (đang dở / tới hạn / học mới) — topic có token sai ở quest (§TÍN-HIỆU-NGƯỢC) gắn thêm ⚠ + tên token, **ĐỀ XUẤT theo thứ tự DAG** — domain to → đề xuất topic kế + đếm số, **KHÔNG liệt kê hết**. Note **parked** (trong `_index`, chưa `learn_curriculum`) KHÔNG ở menu — user muốn học nó → **activate** (GATE A). | KHÔNG đọc body để dựng menu · KHÔNG `$$SEARCH$$` khi MOC đã có wikilink · KHÔNG đọc `.base` để lấy trạng thái. |
| → **GATE A** | | | có topic + đã `$$READ$$` **đúng 1** topic note (hoặc xác định note CHƯA tồn tại) | **3 nhánh:** ① **note active đủ liệu** → vào L0. ② **PARKED** (note CÓ, thiếu `learn_curriculum`) → activate inline: `$$REPLACE$$` set `learn_curriculum: <domain>` + `learn_order = max+1`; `$$APPEND$$` 1 dòng DAG vào `curriculum-<domain>.md` (so-hoc section ở S3 ③). ③ **CHƯA CÓ NOTE** (chỉ `[[wikilink]]` trong DAG/MOC, vd domain mới ngoài pilot) → **KHÔNG read-fail**; đề xuất **research trước** (`custom-research-pipeline` materialize note đúng folder dimension) HOẶC tạo **stub tạm** (`$$WRITE$$` frontmatter `learn_curriculum`+`learn_order` + heading vào folder dimension của topic) — **không tự quyết, HỎI user**. → rồi vào L0. **Nếu note là stub/mỏng → BÁO "sẽ dạy bằng kiến thức chung tạm" + HỎI: học chung tạm hay research trước? — không tự quyết.** |
| **[L0…L6]** | | đúng 1 topic note | `$$LOAD_SKILL: learning-mode$$`, chạy đúng luật của nó (luật dạy/vẽ định nghĩa ở L0–L6). | study KHÔNG in lại luật dạy, KHÔNG trả lời nhanh thay dạy. |
| → **GATE B** | | | phiên kết: đủ 5 core / **user dừng** / chủ động chốt phiên sau khi xong một mảng L2–L5 | → S2 |
| **S2 CHẤM_MASTERY** | D | `engram-quest/state/*.json` của topic (nếu có — xem §TÍN-HIỆU-NGƯỢC) | **TRƯỚC khi đề xuất: đọc tín hiệu ngược** (token nào sai ở quest/thẻ) → nếu token đang tick mà thực chiến sai → ĐỀ XUẤT HẠ. Rồi ĐỀ XUẤT token đã đạt (không tự quyết) — **map từ checklist 17 token đã hiển thị ở L1 + bằng chứng phát sinh L2–L6; KHÔNG tự phát minh tiêu chí, KHÔNG suy từ "user có vẻ hiểu"**. Với **5 core**: BẮT BUỘC trích **bằng chứng** = câu user tự nêu bản chất/cơ chế/áp dụng/phân biệt/dạy lại. | Không bằng chứng → không tick. **GATE C:** user duyệt token — **kể cả khi dừng gấp vẫn xin duyệt nhanh 1 câu rồi mới ghi** (không tự ghi khi chưa duyệt). |
| **S3 GHI** | A | `_agent/skills/learning/templates.md` (khung) | **4 việc LÕI, LIỀN LƯỢT, KHÔNG chèn câu nói giữa:** ① frontmatter → ② regen progress **(ĐÚNG 1 LẦN)** → ③ so-hoc → ④ buổi rich (**nhúng lại sơ đồ, KHÔNG append so-do lần 2**). **Rồi 2 việc CÓ ĐIỀU KIỆN (chỉ khi ≥🟢):** ⑤ đúc thẻ EngramQuest (xin duyệt) · ⑥ cập nhật quest domain. Xem §GHI. | **4 việc lõi** xong → (⑤⑥ nếu đủ 🟢, duyệt xong) → S4. |
| **S4 CHỐT_PHIÊN** | D | — | Trỏ dashboard; hỏi học tiếp / ôn / dừng. | Học tiếp → S1 · dừng (đã GHI) → hết. |

> ⛔ **Nhánh user DỪNG** (tín hiệu "ghi tiến trình học"/"dừng và ghi tiến trình học"/"tạm dừng"/"tạm ngừng"/"bận"/"để sau"/"thôi") ở **BẤT KỲ state L nào** = nhảy thẳng **GATE B → S2 (đề xuất token + XIN DUYỆT NHANH 1 câu) → S3 ghi đủ **4 việc LÕI** → RỒI mới chào** (dừng giữa chừng = chưa ≥🟢 → ⑤⑥ tự động không áp dụng). Không có "study lát ghi" (không state nào khác ghi). TUYỆT ĐỐI không chào tạm biệt khi chưa qua S3.

---

## §GHI — state S3 (4 việc LÕI + 2 CÓ ĐIỀU KIỆN; 3 nơi M/17 phải KHỚP)

> **Lỗi hay mắc nhất:** ghi so-hoc (sổ) xong tưởng xong, BỎ frontmatter+progress → dashboard/menu vẫn "chưa học". **4 việc lõi (①–④) là một khối action liền lượt**, không dừng giữa; ⑤⑥ chỉ chạy thêm khi bài đạt ≥🟢.

| # | Việc | Cách |
|---|---|---|
| ① | **Frontmatter topic** (`$$REPLACE$$`) — **NGUỒN dashboard derive, ghi ĐẦU TIÊN** | `learn_understood` = cũ ∪ mới · `learn_reviewed` = hôm nay · `learn_next` = hôm nay + interval (chỉ set khi ≥ 🟢; chưa đủ 5 core → để **TRỐNG** → 📖 đang dở). **CHỈ đụng 3 field này; GIỮ NGUYÊN `learn_curriculum` + `learn_order` (đừng clobber → vỡ thứ tự dashboard).** |
| ② | **`learning-progress.md`** — TỰ SINH | emit **`$$REGEN_PROGRESS$$` ĐÚNG 1 LẦN** (plugin quét frontmatter mọi topic, tính lại cả bảng). KHÔNG sửa bảng tay; KHÔNG emit lặp; ngoài S3 khi giải thích thì viết "regen progress" chứ đừng viết nguyên cú pháp (kẻo plugin chạy thật). |
| ③ | **📇 Sổ index** `so-hoc-<domain>.md` | section topic `### N. [[topic]] — <icon> M/17`: 📘 kiến thức theo 17 token (nội dung THẬT, chưa đào → `_(chưa đào)_`) · ✍️ bằng chứng (câu user) · Mastery + gap + link buổi. Cập nhật ĐÚNG section đó (**tạo section nếu chưa có — topic mới activate**), cập nhật `> Buổi gần nhất:`. |
| ④ | **📖 Buổi rich** `buoi/<ngày>-<topic>.md` | giảng đầy đủ WHY→WHAT→HOW→SO WHAT + ví dụ + hỏi-đáp + chốt, **NHÚNG lại sơ đồ buổi**: block ```mermaid **(bắt buộc)** + `![[<slug>.excalidraw]]` **(CHỈ nếu đã có Excalidraw — KHÔNG bắt buộc tạo mới)**. *Đọc lại học lại được* — nơi giữ CHI TIẾT. **so-do đã do learning-mode `$APPEND$` ở L1 vào file canonical của domain → S3 CHỈ nhúng lại block vào buổi rich, KHÔNG append so-do lần 2. Không được tự tạo file sibling kiểu `8.TRACK/Learning/so-do-<domain>.md` nếu vault đã có path canonical theo domain folder (vd `8.TRACK/Learning/ai-pilot/so-do-ai-pilot.md`).** |
| ⑤ | **🃏 Đúc thẻ EngramQuest** (TUỲ CHỌN — CHỈ khi ≥🟢 · **xin duyệt**) — biến "vừa học" thành "có thẻ ôn ngay" | Xem §ĐÚC-THẺ. Nếu learning-mode đã đúc thẻ **progressive** trong buổi (LUẬT 4) → **RÀ SOÁT** bộ thẻ hiện có, chỉ **bổ sung thẻ còn thiếu** (không đúc trùng). Nếu CHƯA có thẻ progressive nào → soạn mới từ đầu: từ token đã có **bằng chứng** (ưu tiên 5 core) soạn **3–6 thẻ** (block `%%card%%` với `token:`/`Q:`/`A:` — xem §TOKEN-THẺ) test bản chất/cơ chế/ứng dụng vừa recall — câu hỏi TỰ ĐỨNG ĐƯỢC (có tên khái niệm), KHÔNG trivia → **hiện cho user duyệt/sửa** → ghi vào **TOPIC note**: `$$REPLACE$$` frontmatter thêm `flashcards/<learn_curriculum>` vào `tags` (giữ tag cũ) + `$$APPEND$$` thẻ dưới `## Flashcards`. Chưa đủ 5 core → chỉ progressive (nếu có), chưa Full (như `learn_next` trống). EngramQuest **tự bắt** (quét tag flashcards) → note thành Review Deck; Galaxy codex dòng "Ôn thẻ" sáng. |
| ⑥ | **🗺️ Cập nhật Quest domain** (CHỈ khi ≥🟢) — đóng vòng "học xong → quest phản ánh đúng tiến độ" | Xem **§QUEST-UPDATE** — gate, quy trình, cấu trúc node đầy đủ nằm ở đó, **KHÔNG chép lại vào ô này** (1 nguồn duy nhất, tránh drift). Tóm: tìm `quest-<domain>-*.md` → có instruction re-run → cập nhật NGAY trong S3, không để sang S4. |

**Interval ôn (spaced repetition):**

| Lần ôn | 1 (mới 🟢) | 2 | 3 | 4 | 5+ | fail (tụt <5 core) |
|---|---|---|---|---|---|---|
| Interval | +1d | +3d | +7d | +21d | +60d | về +1d, học lại chỗ hổng |

**Dừng giữa chừng (chưa đủ 5 core)** = vẫn chạy ĐỦ **4 việc lõi ①–④** (⑤⑥ bỏ qua vì chưa ≥🟢), chỉ khác mastery thấp + `learn_next` TRỐNG. Buổi rich (④) giữ phần ĐÃ giảng — **dừng sớm TUYỆT ĐỐI không bỏ** (bỏ = mất công học); sổ index ghi rõ dừng ở tiêu chí nào + gap buổi sau. Token đề xuất theo **bằng chứng đã có**, nhưng **vẫn xin user duyệt nhanh 1 câu trước khi ghi** — GATE C KHÔNG có ngoại lệ; dừng gấp chỉ rút gọn thành 1 câu duyệt, không bỏ duyệt.

> Khung đầy đủ 4 lớp: `$$READ$$` `_agent/skills/learning/templates.md`. Trước khi sang S4: rà 3 con số M/17 ở **frontmatter ≡ progress ≡ so-hoc** có KHỚP.

---

## §QUEST-UPDATE — việc ⑥ (đóng vòng học → quest)

**Mục đích:** Mỗi khi bài mới đạt ≥🟢, quest của domain phải phản ánh ngay — không để quest "trễ" so với tiến độ thật.

**GATE (không có ngoại lệ):**
1. **CHỈ chạy khi bài vừa đạt ≥🟢** (đủ 5 core). Ôn tập bài cũ → bỏ qua ⑥.
2. **Chạy TRONG S3**, trước khi sang S4 — không để sang phiên sau.
3. **Nếu domain chưa có quest** → **KHÔNG im lặng bỏ qua**: báo user + **ĐỀ XUẤT tạo quest đầu tiên** (`$$LOAD_SKILL: curriculum$$` → §ĐÓNG-GÓI-QUEST, gate ≥1 topic ≥🟢) rồi xin duyệt.
   > *Vì sao phải mở lời:* `curriculum` §ĐÓNG-GÓI-QUEST là **on-demand** — user phải tự gõ "đóng gói quest X". Nếu study cũng im lặng bỏ qua thì domain **không bao giờ** có quest và vòng học→ôn không khép được. Study **không tự tạo** quest (đó là việc của `curriculum`), nhưng **bắt buộc phải đề xuất**.

**Quy trình:**

| Bước | Việc | Cách |
|---|---|---|
| 1 | **Tìm quest file** | `$$SEARCH$$` `quest-<domain>` hoặc đọc thẳng nếu đã biết path (vd `8.TRACK/Learning/dataview-bases/quest-dataview-bases-2.md`) |
| 2 | **Đọc instruction** | `$$READ$$` quest file → tìm block *"Sau khi phá đảo"* hoặc *"re-run/update sau khi bài X ≥🟢"* |
| 3 | **Cập nhật nếu có instruction** | Thêm node mới cho bài vừa học (id, emoji, title, summary, points, challenge/quiz) · Mở rộng boss (thêm câu hỏi tổng hợp) · Cập nhật `source_topics` · Cập nhật `updated` · Sửa block *"Sau khi phá đảo"* → bài kế tiếp |
| 4 | **Không có instruction** | Ghi chú ngắn "quest không có instruction re-run" rồi sang S4 |

**Cấu trúc node quest chuẩn (thêm vào trước boss node):**
```yaml
  - id: <topic-basename>
    emoji: <emoji phù hợp>
    title: <Tên bài ngắn gọn>
    summary: <1 câu tóm bản chất + cơ chế chính>
    points:
      - title: Bản chất
        body: <essence + problem — KHÔNG dùng ký tự đặc biệt `:` `/` trong body>
      - title: Cơ chế
        body: <mechanism + gotcha quan trọng>
    challenge:
      type: quiz
      questions_json: [<3-4 câu trắc nghiệm từ token đã có bằng chứng>]
```

**Cập nhật boss node:**
- Đổi `title` → gộp thêm bài mới (vd "Boss — Dimension 2 hoàn thành (Table + List + Cards + Map)")
- Đổi `summary` → mô tả tổng hợp cả nhóm mới
- Thêm 1-2 câu quiz tổng hợp liên bài vào `questions_json`

**Quiz chuẩn (giống §ĐÚC-THẺ):**
- Câu hỏi TỰ ĐỨNG ĐƯỢC (có tên khái niệm, đủ ngữ cảnh)
- 4 lựa chọn, 1 đúng (`ans`: index 0-3)
- `explanation` giải thích vì sao đáp án đúng
- **`token`: token rubric 17 mà câu này kiểm tra** — BẮT BUỘC, cùng luật §TOKEN-THẺ (tên nguyên văn rubric, đúng 1 token/câu, khớp cái câu THỰC SỰ hỏi)
- **ĐỪNG mặc định `type: quiz` cho mọi câu.** Chọn DẠNG thử thách theo token cần đo (`order`/`match`/`cloze`/`text`/`auction`/`countdown`…) — bảng chọn + schema chính xác + chỗ khai `token` cho từng nhóm dạng: `$$READ$$` `_agent/skills/learning/quest-challenge-types.md`. Trắc nghiệm 4 đáp án là **nhận diện**, không phải truy hồi — độc canh `quiz` là đo non.
- Test bản chất/cơ chế/ứng dụng/phân biệt — KHÔNG trivia

*Mẫu 1 câu:*
```json
{"token":"mechanism","q":"Dataview xác định kiểu dữ liệu của property bằng cách nào?","opts":["Đọc types.json của Obsidian","Tự đoán theo format giá trị thật","Hỏi người dùng","Luôn coi là Text"],"ans":1,"explanation":"Dataview không đọc types.json — nó nhìn giá trị thật, không khớp ISO thì coi là Text."}
```

> **Vì sao bắt buộc `token`:** plugin lưu kết quả TỪNG CÂU theo token vào `engram-quest/state/<quest>.json` (`nodes.<id>.tokens = {mechanism:{ok,miss}}`). Vì `node.id` = slug topic note, thống kê này quy thẳng về mastery của topic đó. Không khai token → chơi xong chỉ biết "được 67%", **không biết sai ở KIỂU HIỂU nào** → S2 phiên sau lại phải hỏi lại từ đầu. Câu không khai token bị bỏ qua khi gom (không vỡ, chỉ mất tín hiệu).

---

## §ĐÚC-THẺ — việc ⑤ (ống nối sang EngramQuest)

**Mục đích:** học xong 1 bài → tự có flashcard để **ôn bằng active recall** trong EngramQuest, khỏi phải chạy skill riêng của nó. Đúng tinh thần `ao-giac-hieu`: thẻ = truy hồi chủ động, ĐỐI LẬP với đọc-lại-thấy-quen.

> **(2026-07-17)** Từ nay có **2 chế độ đúc thẻ**: **Progressive** (thẻ nhỏ ngay sau MỖI lớp WHY/WHAT/HOW/SO_WHAT — xem `learning-mode.md` LUẬT 4, chạy TRONG buổi, không đợi hết bài) và **Full** (⑤ dưới đây — rà soát + bổ sung cho đủ bộ khi lesson đạt ≥🟢, chạy ở S3). Định dạng thẻ (`%%card%%` Q:/A:) và vị trí ghi (`## Flashcards` trong TOPIC note) dùng CHUNG cho cả 2 chế độ — không tạo 2 định dạng khác nhau.

**GATE (không có ngoại lệ) — áp cho chế độ Full ⑤ dưới đây:**
1. **CHỈ đúc khi ≥🟢** (đủ 5 core). Chưa đủ → bỏ qua, không đúc nửa vời. *(Chế độ Progressive không chờ 5 core — xem gate riêng ở LUẬT 4 `learning-mode.md`, nhưng vẫn phải bằng chứng thật + xin duyệt.)*
2. **CHỈ từ token đã có BẰNG CHỨNG** (câu user tự nêu) — KHÔNG hỏi cái user chưa chứng minh hiểu, KHÔNG trivia (ngày tháng, con số vụn).
3. **XIN DUYỆT** — hiện trọn bộ thẻ cho user; user sửa/bỏ/thêm rồi mới ghi. (GATE C mở rộng — không tự ghi.)

**Soạn 3–6 thẻ**, ưu tiên phủ 5 core — **mỗi thẻ khai đúng 1 token nó kiểm tra** (xem §TOKEN-THẺ):
- 1 thẻ `essence`: "X là gì / bản chất X?" → đáp = 1 câu cốt lõi.
- 1 thẻ `mechanism`: "X hoạt động thế nào / vì sao X đúng?"
- 1 thẻ `application`: "Khi nào dùng X? Ví dụ?"
- (nếu có) `discrimination` X vs khái niệm gần · `teach-back` (câu hỏi bắt giải thích lại).
- **Câu hỏi TỰ ĐỨNG ĐƯỢC**: chứa tên khái niệm + đủ ngữ cảnh để hiểu **không cần mở note** (vd ❌ "Có mấy bước?" → ✅ "First Principles gồm mấy bước, mỗi bước làm gì?"). **Đáp án thực chất** — không chỉ 1 con số/tên.

**Ghi (sau khi duyệt) — vào chính TOPIC note:**
- **a.** `$$REPLACE$$` frontmatter: thêm `flashcards/<learn_curriculum>` vào mảng `tags` (**giữ nguyên tag cũ**; đây là cách EngramQuest phát hiện deck — không cần cấu hình gì thêm). Deck gom theo domain (vd `flashcards/ai-pilot`).
- **b. Định dạng (chôm chuẩn EngramQuest — AN TOÀN NHẤT):** mỗi thẻ 1 **block `%%card%%`**, bên trong `token:` (xem §TOKEN-THẺ) rồi `Q:` (câu hỏi) rồi `A:` (đáp án, được nhiều dòng), đóng bằng `%%card%%`. Block này **bất khả xâm phạm bởi prose** — KHÔNG dùng bare `X :: Y` (prose có `::` sẽ thành thẻ rác). Cloze `{{c1::đáp án}}` chỉ khi có 1 chỗ trống rõ. Ghi các block dưới heading `## Flashcards` (tạo nếu chưa có). *Mẫu:*

```
%%card%%
token: essence
Q: First Principles là gì?
A: Phương pháp bỏ mọi giả định, quay về sự thật cơ bản nhất rồi xây lại từ đó.
%%card%%
```
- Log mutation vào `_agent/log.md`.

**Kết quả:** EngramQuest tự thấy note thành Review Deck (FSRS lên lịch riêng), Galaxy codex hiện "Ôn thẻ N tới hạn" → bấm vào luyện. Vòng học khép kín thật (Bob dạy → thẻ → luyện → bản đồ sáng).

---

## §TÍN-HIỆU-NGƯỢC — đọc kết quả thực chiến trước khi chấm (S2)

**Vấn đề nó giải:** trước đây mastery chỉ đi MỘT chiều — Bob chấm token, ghi vào `learn_understood`, xong là đóng băng. Anh chơi quest sai, ôn thẻ sai, không gì chảy ngược. Có ca thật: `kieu-du-lieu-metadata` được **67%** ở quest ngày 17/07 (sai 1/3 câu) mà `learn_understood` vẫn đủ 10 token, không ai biết; `ban-do-ai` phải **6 lượt** mới 100%, cũng không ai biết.

**Nguồn đọc:** `engram-quest/state/<questPath có / đổi thành __>.json`. Trong đó:
```json
"nodes": { "<topic-slug>": { "scorePct": 75, "attempts": 2,
    "tokens": { "discrimination": {"ok":0,"miss":1}, "essence": {"ok":1,"miss":0} } } }
```
**`node.id` CHÍNH LÀ slug topic note** → tra thẳng, không cần map gì thêm.

**Cách dùng ở S2 (trước khi đề xuất token):**

| Tín hiệu | Nghĩa | Động tác |
|---|---|---|
| token có `miss > 0` **và** đang nằm trong `learn_understood` | tick cũ không còn đúng — thực chiến sai | **ĐỀ XUẤT HẠ tick đó** + hỏi lại đúng kiểu hiểu ấy trong phiên. Không tự hạ — vẫn GATE C. |
| token có `miss > 0`, chưa tick | chưa đạt, đã biết | không tick; nêu ra làm chỗ cần đào |
| `attempts` cao mà `scorePct` mới lên 100 | chật vật, không phải nắm chắc | nêu ra; **không** dùng riêng nó để tick |
| không có `tokens` (quest cũ / chưa chơi) | không có tín hiệu | bỏ qua — **KHÔNG suy từ `scorePct` tổng** |

**Hạ tick kéo theo (S3 ①):** nếu hạ làm mất 1 trong **5 core** → topic tụt khỏi 🟢 → `learn_next` về **+1d** (đúng dòng "fail" ở bảng interval), và so-hoc ghi rõ token nào tụt + vì sao (sai ở quest nào, ngày nào).

⛔ **Chốt chặn:**
- KHÔNG tự hạ tick rồi mới báo — đề xuất trước, user duyệt (GATE C không có ngoại lệ, kể cả khi bằng chứng máy rất rõ).
- KHÔNG dùng `scorePct` tổng để suy ra token: 67% không nói sai ở KIỂU HIỂU nào. Chỉ `tokens` mới quy được.
- KHÔNG đọc file state khi topic không có quest — đừng `$$SEARCH$$` mò; không có thì thôi.

---

## §TOKEN-THẺ — mỗi thẻ khai token nó kiểm tra

**Vì sao:** thẻ VỐN đã được đúc *từ* một token cụ thể ("1 thẻ essence, 1 thẻ mechanism…") nhưng khi ghi ra file thì thông tin đó bị vứt đi. Hệ quả: ôn sai một thẻ, không ai quy được về token nào đang lung lay — `learn_understood` tick từ tháng trước cứ nằm đó dù thực tế đã quên. Khai `token:` là giữ lại thứ mình vốn đã biết, để vòng học đóng được chiều ngược (plugin → mastery).

**LUẬT (không có ngoại lệ):**

1. **`token:` phải nằm TRƯỚC dòng `Q:`**, ngay sau `%%card%%` mở. Đặt sau `A:` là nó **chui vào đáp án** và user sẽ thấy chữ "token: mechanism" hiện lên giữa lúc đang ôn.
   > *Cơ sở:* parser EngramQuest (`parseCommentCardBlock` / `parseFencedQA`) quét tìm dòng `Q:` đầu tiên rồi `A:` sau đó; mọi dòng **trước `Q:` bị bỏ qua sạch**, mọi dòng **sau `A:` gộp vào đáp án**. Nên thẻ có `token:` đặt đúng chỗ chạy được ngay trên plugin **chưa sửa dòng nào** — thẻ cũ không có token cũng không vỡ.
2. **Đúng 1 token/thẻ**, lấy **nguyên văn** từ rubric 17 (`learning-mode.md` §Rubric): `definition` `essence` `problem` `origin-context` `mechanism` `root-cause` `rationale` `scope-boundary` `tradeoffs` `consequences` `application` `measurement` `create` `connection` `discrimination` `metacognition` `teach-back`. **KHÔNG tự chế tên** (`co-che`, `ban-chat`… đều SAI — phải là `mechanism`, `essence`).
3. **Token phải khớp cái thẻ THỰC SỰ hỏi**, không phải token đang muốn tick. Thẻ hỏi "khi nào dùng X" = `application` dù buổi học đang đào `mechanism`.
4. Thẻ cũ chưa có `token:` — **không migrate hàng loạt**. Chỉ thêm khi tình cờ sửa/bổ sung thẻ của topic đó.

---

## ⛔ Chốt chặn (triệu chứng → việc)

| Nếu… | thì |
|---|---|
| định tick 5 core / `application` / `teach-back` mà thiếu bằng chứng user | KHÔNG tick |
| định bỏ learning-mode để "trả lời nhanh" | KHÔNG — phải qua cụm L |
| định ghi frontmatter trước khi user duyệt (GATE C) | KHÔNG |
| user dừng giữa chừng ("bận"/"để sau") | = KÍCH HOẠT S2 (xin duyệt nhanh) → S3 đủ **4 việc lõi** → rồi mới chào |
| định emit lệnh regen progress >1 lần, hoặc nhắc nguyên cú pháp directive ngoài S3 | chỉ emit ĐÚNG 1 lần ở S3 ②; khi giải thích viết "regen progress", không viết nguyên cú pháp |
| lĩnh vực mới chưa có curriculum | `$$LOAD_SKILL: curriculum$$` trước (study không tự scaffold domain) |
| định đúc thẻ (⑤) khi chưa đủ 5 core, hoặc thẻ hỏi cái user chưa chứng minh hiểu, hoặc chưa xin duyệt | KHÔNG — GATE §ĐÚC-THẺ: chỉ ≥🟢, chỉ từ bằng chứng, phải duyệt |
| định bỏ qua ⑥ hoặc để sang S4/phiên sau khi bài vừa đạt ≥🟢 | KHÔNG — ⑥ BẮT BUỘC trong S3 khi ≥🟢. Quy trình + gate đầy đủ: **§QUEST-UPDATE** (không lặp lại ở đây). |
| định ghi thẻ mà clobber `tags` cũ, hoặc dùng bare `::` thay vì block `%%card%%` | thêm `flashcards/<domain>` vào mảng tags (giữ tag cũ); thẻ luôn trong block `%%card%%` Q:/A: dưới `## Flashcards` (không bare `::`) |
| định ghi thẻ KHÔNG có `token:`, hoặc đặt `token:` sau `A:`, hoặc chế tên token ngoài rubric 17 | §TOKEN-THẺ: đúng 1 token/thẻ · **trước `Q:`** (sau `A:` = lọt vào đáp án) · tên nguyên văn rubric (`mechanism` không phải `co-che`) |

Mọi mutation append `_agent/log.md`.

## Phối hợp
`learning-mode` (cụm dạy, bắt buộc) · `curriculum` (lĩnh vực mới) · `ingest` (lưu phiên thành note) · `query` (lấy học liệu).
