name: jlpt-doc-hieu-tong-hop
description: >
Generate JLPT "đọc hiểu tổng hợp" (integrated / comparative comprehension / 統合理解)
reading items as styled HTML files and output CSV training data for AI fine-tuning. Each
item contains TWO short Japanese passages A and B (total 600–800 characters) on the
same topic — with contrasting / complementary / debating viewpoints — tested via 2
multiple-choice questions per item that probe comparison and integration across A and B.
All questions use the fixed label question_comprehensive_understanding.
This skill applies ONLY to N1 (≈600-750 chars total) and N2 (≈600-800 chars total). Other
JLPT levels do NOT have this reading type.
Skill này bao gồm TOÀN BỘ luồng: gen → QC loop (checklist PASS/FAIL) → sửa. Gen từng bài
một, kiểm tra đến khi đạt chất lượng mới chuyển sang bài tiếp theo. Output chỉ gồm HTML +
CSV (không có screenshot PNG).
Use this skill whenever the user wants to: gen bài đọc hiểu tổng hợp, tạo nội dung
integrated / comparative reading, generate JLPT 統合理解 / comparative passages, produce
AI fine-tuning data for the "đọc hiểu tổng hợp" section of JLPT N1 or N2.
Also trigger when the user mentions: gen bài đọc hiểu tổng hợp, tạo bài so sánh AB,
generate JLPT 統合理解, 2-đoạn comparative reading N1/N2, integrated comprehension,
advice format 相談者 + 回答者A + 回答者B.
JLPT 統合理解 / Đọc Hiểu Tổng Hợp — Workflow
🔒 NGUYÊN TẮC CỐT LÕI — ZERO-TOLERANCE (BẮT BUỘC):
- Gen từng bài một — không batch rồi QC sau
- Agent tự QC — đọc lại bài + câu hỏi, tự đánh giá từng mục, log PASS/FAIL
- 🚨 1 FAIL = CHƯA XONG — sửa → QC lại TỪ ĐẦU → lặp đến khi ALL PASS. TUYỆT ĐỐI CẤM:
- Skip mục FAIL hoặc mark "tạm thời để đó"
- Tự ý sang bài tiếp khi còn ≥ 1 FAIL ở bài hiện tại
- Ghi PASS mà không thực sự đọc lại nội dung và verify
- "Hợp lý hoá" lỗi (vd "char count chỉ vượt 5 ký tự thì OK") — nếu rule nói FAIL thì là FAIL
- 🔒 5 GATE bắt buộc giữa các BƯỚC (0→1, 1→2, 2→3, 3→4, 4→5) — KHÔNG qua gate = KHÔNG được sang bước tiếp. Mỗi gate phải log explicit "GATE X→Y PASSED" trước khi tiếp tục.
Cấu trúc file
| File | Nội dung | Đọc khi |
|---|---|---|
SKILL.md (file này) |
Workflow + QC Checklist | Luôn đọc đầu tiên |
rules/content.md |
R1 chủ đề N1/N2 (A↔B relationship) + R2 char count/Q count/paragraph count/A-B balance + R7 formats (standard + advice) + R8 visual (label A/B, marker, <u>, 注) |
Gen HTML |
rules/vocabulary.md |
R3 từ vựng/ngữ pháp + R4 furigana (N1/N2) | Gen HTML + QC |
rules/questions.md |
R5 2 câu hỏi + label CỐ ĐỊNH + Q2 compare RULE + R6 đáp án/6 bẫy (role reversal, single-side, ...) | Gen Q&A + QC |
rules/technical.md |
R9 HTML template 780px (2-section + advice 3-section) + R10 clean HTML + R11 CSV schema + R12 QC automation | Gen HTML + CSV |
references/html-patterns.md |
Template chi tiết per level + AB balance patterns + advice format | Tra cứu khi gen HTML |
references/sample-analysis.md |
Phân tích định lượng data mẫu N1/N2 | Hiểu tần suất pattern |
scripts/process_html.py |
Xử lý HTML → CSV + count (total + per-section) + validate + 2-question support | Gen CSV + QC |
scripts/fill_qa.py |
Điền Q&A vào CSV (quote an toàn, 2 câu, FIXED_LABEL rule) | Sau khi gen Q&A |
scripts/load_references.py |
Load sample JSON để calibrate | BƯỚC 0 chuẩn bị |
scripts/check_furigana.py |
Auto-check furigana coverage vs kanji_jlpt_sensei.csv |
BƯỚC 1 sau gen HTML + QC |
scripts/check_csv_fields.py |
Auto-check required CSV fields (_id, level, tag, kind, question_label_*, Q slots) |
BƯỚC 1 sau khi tạo CSV + QC |
scripts/check_spacing.py |
Auto-check わかち書き spacing (N5 BẮT BUỘC có khoảng trắng, N1-N4 BẮT BUỘC không có) | BƯỚC 1 sau gen HTML + QC |
scripts/check_answer_punctuation.py |
Auto-check dấu 。 cuối lựa chọn (Phần 5.8): câu hoàn chỉnh → cần 。; mệnh đề phụ/kanji-noun → không 。; nhất quán trong 1 Q |
BƯỚC 1 sau khi tạo CSV + QC |
Outputs Per Item
- Styled HTML →
assets/html/doc_hieu_tong_hop/{LEVEL}_{uuid}.html - Clean HTML → CSV column
text_read(no attributes, no<rt>content) - CSV row →
sheets/samples_v1.csvvới 2 câu hỏi populate (question_3, question_4, question_5 + related cols empty)
KHÔNG có screenshot PNG. CSV column general_image luôn "".
Scope — CHỈ N1 và N2
| Level | Có "đọc hiểu tổng hợp"? | Q Count | Char Range (A + B) | Focus spec |
|---|---|---|---|---|
| N1 | ✅ có | 2 | 600–750 | so sánh và tổng hợp đa quan điểm |
| N2 | ✅ có | 2 | 600–800 | so sánh và tổng hợp đa quan điểm |
| N3 | ❌ KHÔNG có | — | — | — |
| N4 | ❌ KHÔNG có | — | — | — |
| N5 | ❌ KHÔNG có | — | — | — |
⛔ KHÔNG gen N3, N4, N5 cho dạng đọc hiểu tổng hợp — sẽ bị reject bởi spec.
Số câu hỏi per level (BẮT BUỘC)
| Level | Q Count | Slots populate | Slots empty | Label CỐ ĐỊNH | Q2 rule |
|---|---|---|---|---|---|
| N1 | 2 | question_{1,2} |
question_{3,4,5} |
question_comprehensive_understanding |
Q2 compare A vs B |
| N2 | 2 | question_{1,2} |
question_{3,4,5} |
question_comprehensive_understanding |
Q2 compare A vs B |
⛔ LABEL RULE: Cả Q1 và Q2 (2 level) ĐỀU PHẢI là
question_comprehensive_understanding. Không có label khác. Pipeline warn và override nếu sai. ⛔ Q2 COMPARE RULE: Q2 PHẢI test tích hợp A + B (hỏi về cả 2 đoạn). Cấm Q2 chỉ về A hoặc chỉ về B. ⛔ DIVERSITY RULE: Q1 và Q2 PHẢI test 2 khía cạnh KHÁC NHAU (Q1 common → Q2 compare khác biệt; Q1 focus 1 đoạn → Q2 compare tổng thể).
A/B Balance Rule (đặc thù đọc hiểu tổng hợp)
| Rule | Yêu cầu |
|---|---|
| Mỗi đoạn chiếm | 40–60% tổng chars |
| Chênh lệch | ≤ 30% (abs(A_chars - B_chars) / max(A_chars, B_chars) ≤ 0.30) |
| Section | <section class="passage-a"> + <section class="passage-b"> (hoặc advice 3-section) |
| Topic | A và B cùng 1 topic, quan điểm khác/bổ sung nhau |
WORKFLOW
BƯỚC 0: CHUẨN BỊ (1 lần cho batch)
- Đọc
rules/rule_doc_hieu.md— Bộ Tiêu Chí Đánh Giá Đọc Hiểu JLPT toàn diện từ giáo viên (source-of-truth, 11 phần: 4 tiêu chí, 程度 ±, 書き下ろし/による, nhãn A/B, 文体の統一 (thể chia), furigana per level, 8 loại câu hỏi, 7 loại bẫy (5 chuẩn + Single-side ĐẶC TRƯNG cho 統合理解 + Peripheral Source cho N1 khi 注 dài), tiêu chí chi tiết per level). Phần áp dụng trực tiếp cho dạng đọc hiểu tổng hợp (統合理解) — CHỈ N1 và N2:- Phần 1 (Tổng quan & Nguyên tắc 程度) — biên ± per level; ~600字 tổng A+B (mỗi bài 250–360字)
- Phần 2 (Hình thức) — nhãn A/B rõ ràng; không ①② cho câu so sánh; có gạch chân khi câu hỏi chi tiết về A hoặc B
- Phần 2.4 (Thể chia nhất quán 文体の統一) — N1/N2 dùng 普通形 (だ・である). Cả bài A và bài B + câu hỏi + 4 đáp án phải thống nhất thể — toàn bộ 普通形. (Văn phong A và B có thể khác nhau chút về sắc thái nhưng cùng level và cùng thể.)
- Phần 2.5 (Khoảng cách わかち書き) — Chỉ N5 dùng. N5 BẮT BUỘC dùng 全角スペース (U+3000), CẤM 半角スペース (U+0020). N4-N1 KHÔNG dùng wakachi-gaki.
- Phần 3 (Furigana — Quy tắc A/B/C) — A: bắt buộc
<ruby>tag; B: rắc toàn từ, KHÔNG rắc 1 phần (vd:<ruby>確証<rt>かくしょう</rt></ruby>chứ KHÔNG確<ruby>証<rt>しょう</rt></ruby>); C: chỉ lần đầu xuất hiện, kể cả 注. - Phần 5.8 (Dấu
。cuối lựa chọn) — Câu hoàn chỉnh (kết bằng である/だ/です/べきだ) → cần。. Mệnh đề phụ (kết bằng から/ため/ので) hoặc danh từ kanji-ending → KHÔNG。. 4 options trong 1 Q phải nhất quán. - Phần 3 (Furigana) — bảng quy tắc per level
- Phần 4 (8 loại câu hỏi) — đặc biệt
comprehensive_understanding(LABEL CỐ ĐỊNH cho cả 2 câu), 2 form chuẩn: 「AとBが共通して述べていることは何か」 + 「○○について、AとBはどのように述べているか」 - Phần 5 (7 loại bẫy = 5 chuẩn + Single-side ĐẶC TRƯNG + Peripheral Source) — đặc biệt Single-side (bẫy đặc trưng riêng cho 統合理解) + Cross-swap (gán ý A cho B / ngược lại) cho Q2
- Phần 9.3 (N2 統合理解 ~600字, 2 câu), Phần 10.4 (N1 統合理解 ~600字, 2 câu) — tiêu chí chi tiết 4 chiều; A và B đối lập hoặc bổ sung
- Phần 11 (Bảng so sánh tổng hợp) — tra cứu nhanh.
- Đọc rules skill:
rules/content.md+rules/vocabulary.md+rules/technical.md+rules/questions.md - Đọc
rules/kanji_jlpt_sensei.csv— dùng để tra level từng kanji khi quyết định furigana - Scan
sheets/samples_v1.csvvàdata/doc_hieu_tong_hop_n{1,2}_clean.json— xem format, topic đã dùng → chọn format chưa/ít dùng - Load 2-3 sample calibrate style:
python3 .claude/skills/jlpt-reading-integrated/scripts/load_references.py --level N1 --count 2 python3 .claude/skills/jlpt-reading-integrated/scripts/load_references.py --level N2 --count 2 - Lập kế hoạch batch: mỗi bài gán format + topic + combo A↔B relationship (contrast/complement/debate/advice) khác nhau. Topic chọn tiếng Anh từ cột
encủarules/topic.json(đa dạng ≥ 2 category trong batch > 3 bài). Mỗi topic phải phù hợp cho CẢ A và B viewpoints.
🔒 GATE 0→1 — KHÔNG QUA = KHÔNG ĐƯỢC GEN
Trước khi bắt đầu BƯỚC 1, agent PHẢI confirm bằng cách tick từng item:
- Đã đọc
rules/rule_doc_hieu.md(đặc biệt Phần 1, 2, 2.4 thể chia, 3, 4, 5, các phần per-level applicable, 11) - Đã đọc đủ 4 file:
rules/content.md+rules/vocabulary.md+rules/technical.md+rules/questions.md - Đã đọc
rules/kanji_jlpt_sensei.csv(sẵn sàng tra furigana) - Đã chạy
load_references.py --level {LEVEL} --count 2và đọc samples - Đã scan
sheets/samples_v1.csvđể biết topic + label đã dùng - Đã có kế hoạch batch (format + topic + label per bài)
❌ Bất kỳ item nào CHƯA tick → quay lại BƯỚC 0, KHÔNG được gen.
✅ Khi 6/6 tick → log GATE 0→1 PASSED — ready to gen rồi sang BƯỚC 1.
BƯỚC 1→5: LẶP CHO TỪNG BÀI
BƯỚC 1: GEN HTML + 2 CÂU HỎI
Đọc:
rules/content.md+rules/vocabulary.md+rules/technical.md+rules/questions.mdTham khảo:references/html-patterns.mdcho template per level + advice format
- Gen
_id={LEVEL}_{uuid.uuid4().hex}(full 32-char hex). Level ∈ {N1, N2}. - Chọn format từ R7 (
rules/content.md):- Standard 2-section: A + B, cùng topic, khác quan điểm (phổ biến nhất)
- Advice 3-section: 相談者 + 回答者A + 回答者B (tư vấn; chỉ N2; ~5% data)
- Chọn
tag(topic) — tiếng Anh từ cộtencủarules/topic.json, đa dạng trong batch - Chọn A↔B relationship type (R1.2):
- Contrast: A vs B đối lập (VD A khen vs B chê)
- Complement: A và B nhìn 2 khía cạnh khác của cùng issue
- Debate: A đưa argument, B phản biện / counter
- Advice: 相談者 → A, B đưa 2 lời khuyên khác
- Plan 2 viewpoints + common thread — viết trước:
- Topic chung là gì?
- A nói gì (thesis + 1-2 supporting points)
- B nói gì (thesis + 1-2 supporting points)
- Điểm chung của A và B là gì? Điểm khác biệt ở đâu?
- Chọn combo 2 câu hỏi (R5.3):
- Combo 1 — Common + Compare (50%+ dùng): Q1
AとBで共通して述べられているのはどれか。→ Q2XについてAとBはどのように述べているか。 - Combo 2 — Compare + Compare: Q1 compare X → Q2 compare Y
- Combo 3 — A-focus + Compare (có marker ①): Q1
①...とあるが、どのようなことか。→ Q2AとBに共通する考え方はどれか。 - Combo 4 — Advice + Compare: Q1 hỏi về 相談者 → Q2
「相談者」の相談に対するA、Bの回答について、正しいものはどれか。
- Combo 1 — Common + Compare (50%+ dùng): Q1
- Gen HTML theo rules → save
assets/html/doc_hieu_tong_hop/{LEVEL}_{uuid}.html- Container
max-width: 780px; margin: 0 auto; padding: 40px 20px; line-height: 1.9 word-break: keep-all,line-break: strict- 2 (hoặc 3)
<section>— mỗi section có<span class="label">A|B|相談者|回答者A|回答者B</span>ở đầu <p>thuần, KHÔNG<br>giữa câu- Paragraph per section: 2–4
<p>per section (bài ngắn, súc tích) - A/B balance: mỗi đoạn 40–60% tổng chars
- Marker ①② chỉ khi Q1 là A-focus (Combo 3); Q2 KHÔNG dùng marker (vì compare tổng thể)
- Furigana chỉ cho từ vượt level (tra
rules/kanji_jlpt_sensei.csv) — data 0% nên ưu tiên 0 ruby - Source line: hầu như KHÔNG dùng (data N1:4%, N2:0%)
- Annotation 注: hiếm (data N1:4%, N2:0%)
- KHÔNG dùng
<br>giữa câu, KHÔNG dùng<table>layout
- Container
- Gen 2 câu hỏi + 4 đáp án mỗi câu theo
rules/questions.md:- 4 options ngăn cách
\n, KHÔNG số thứ tự1.,①,1) correct_answer_i= integer 1-4- Mỗi distractor PHẢI dùng info/ý THẬT từ bài (1 trong 6 loại bẫy: Role reversal A/B / Single-side / Mix A+B / Scope / Extreme / Extraneous)
- BẮT BUỘC ≥ 2 distractor dạng Role reversal hoặc Single-side cho Q2 compare
- Paraphrase: đáp án đúng KHÔNG copy > 4 từ (N1) hoặc > 5 từ (N2) liên tiếp
- Giải thích
explain_vn_i+explain_en_itheo format 3 phần - Cả Q1 và Q2:
question_label=question_comprehensive_understanding(CỐ ĐỊNH) - Q2 PHẢI compare A vs B (tích hợp 2 đoạn)
- 4 options ngăn cách
- [BẮT BUỘC] Auto-check furigana ngay sau khi save HTML — chạy:
python3 .claude/skills/jlpt-reading-integrated/scripts/check_furigana.py \ --file assets/html/doc_hieu_tong_hop/{LEVEL}_{uuid}.html \ --level {LEVEL} \ --csv rules/kanji_jlpt_sensei.csv- Nếu báo
MISSING FURIGANA→ BẮT BUỘC thêm<ruby><rt>cho mỗi kanji bị thiếu, KHÔNG sang bước Q+A. - Nếu báo
REDUNDANT FURIGANA→ cân nhắc bỏ ruby thừa (kanji ≤ level không cần furigana). - Nếu báo
UNKNOWN KANJI→ tra cứu kanji hiếm, thường cần ruby ở mọi level. - Chỉ khi script chạy không có
MISSING FURIGANA→ mới sang bước tạo CSV.
- Nếu báo
- Tạo CSV row bằng
process_html.pyhoặcfill_qa.py(⚠️ dùng script, KHÔNG sửa CSV tay):
# Recommended cho 2 câu: JSON
python3 .claude/skills/jlpt-reading-integrated/scripts/process_html.py \
--file assets/html/doc_hieu_tong_hop/{LEVEL}_{uuid}.html \
--csv sheets/samples_v1.csv \
--tag "{topic_vn}" \
--questions-json /tmp/qs.json
Hoặc dùng fill_qa.py với flags per-question:
⛔ KHÔNG ĐƯỢC sửa CSV bằng tay. Commas + newlines trong nội dung (
100,000円,A\nB\nC\nD) sẽ làm vỡ cột.
# Ví dụ N1 (2 câu)
python3 .claude/skills/jlpt-reading-integrated/scripts/fill_qa.py \
--csv sheets/samples_v1.csv --row-id {LEVEL}_{uuid} --level N1 \
--q1 "AとBで共通して述べられているのはどれか。" --a1 "A\nB\nC\nD" --ca1 2 --evn1 "..." --een1 "..." \
--q2 "XについてAとBはどのように述べているか。" --a2 "A\nB\nC\nD" --ca2 3 --evn2 "..." --een2 "..."
(Label tự động điền question_comprehensive_understanding — không cần flag --q1-label.)
🔒 GATE 1→2 — KHÔNG QUA = KHÔNG ĐƯỢC QC
Trước khi sang BƯỚC 2 (QC), agent PHẢI confirm:
- File HTML đã save vào
assets/html/doc_hieu_tong_hop/{LEVEL}_{uuid}.html(verify file tồn tại) - CSV row đã tạo bằng
process_html.py(KHÔNG sửa CSV tay) -
_idđúng format{LEVEL}_{uuid32}(không tạm thời, không placeholder) - Tất cả Q + 4 đáp án + correct_answer + explain_vn + explain_en đã fill (không "TODO", không empty)
- Đã đọc lại file HTML vừa gen (mở file, đọc content) — KHÔNG dựa vào "tôi nhớ tôi đã gen"
- Đã chạy
check_furigana.py --file ... --level ... --csv rules/kanji_jlpt_sensei.csvvà KHÔNG cóMISSING FURIGANA— auto-check bắt buộc, log output - Đã chạy
check_csv_fields.py --csv sheets/samples_v1.csv --kind integratedvà row mớiALL ROWS VALID— auto-check required fields (_id,level,tag,kind,question_label_*, Q slots) - Đã chạy
check_spacing.py --file ... --level ...và spacing OK — N5 BẮT BUỘC わかち書き (ratio ≥ 3%), N1-N4 BẮT BUỘC không có space giữa kanji/kana (ratio ≤ 0.5%)
❌ Bất kỳ item nào CHƯA confirm → quay lại BƯỚC 1 fix, KHÔNG được QC.
✅ Khi 8/8 tick → log GATE 1→2 PASSED — ready to QC rồi sang BƯỚC 2.
BƯỚC 2: ⛔ QC — AGENT TỰ ĐÁNH GIÁ CHECKLIST
ĐÂY LÀ BƯỚC QUAN TRỌNG NHẤT. KHÔNG ĐƯỢC BỎ QUA.
Agent phải đọc lại file HTML vừa gen + TOÀN BỘ 2 câu hỏi/đáp án trong CSV, rồi tự đánh giá từng mục bên dưới. Log kết quả theo format:
QC: {_id} | Level: N1 | Q count: 2/2 | Labels: [comprehensive_understanding × 2] ──────────────────────────────── [ 1] ✅ PASS — Char count (687 chars, range 600-750) [ 2] ✅ PASS — A/B balance (A=338, B=349, diff 3%) [ 3] ❌ FAIL — Q2 compare rule (Q2 chỉ hỏi về A, không đề cập B) ... ──────────────────────────────── ⚠️ 1 FAIL → sửa rồi QC lại⛔ KHÔNG ĐƯỢC tự PASS mà không đọc lại nội dung. Phải confirm từng mục cho CẢ 2 câu hỏi.
🔒 GATE 2→3 — KHÔNG QUA = KHÔNG ĐƯỢC ĐÁNH GIÁ CHECKLIST
Trước khi vào BƯỚC 3 (đánh giá 34 mục checklist), agent PHẢI cam kết:
- TÔI SẼ kiểm tra ĐẦY ĐỦ 34 mục — không skip, không "tạm bỏ qua", không "mục này hiển nhiên PASS"
- TÔI SẼ đọc lại HTML + CSV thực tế trước khi tick mục — KHÔNG dựa vào "tôi đoán/nhớ"
- TÔI SẼ log explicit PASS/FAIL cho từng mục với evidence (số ký tự, dòng nội dung, trích dẫn)
- TÔI SẼ KHÔNG markup hàng loạt PASS — phải đánh giá độc lập từng mục
- TÔI SẼ đặc biệt cẩn thận mục self-solve (BẮT BUỘC giải lại bài từ đầu, không nhìn correct_answer)
❌ Bất kỳ cam kết nào CHƯA tick → quay lại BƯỚC 2 (đọc lại checklist instructions).
✅ Khi 5/5 tick → log GATE 2→3 PASSED — bắt đầu đánh giá 34 mục checklist.
BƯỚC 3: ⛔ CHECKLIST — TẤT CẢ PHẢI PASS
Quy tắc: 1 FAIL = chưa xong. Sửa → QC lại từ đầu → lặp đến khi ALL PASS. Tổng: 38 checks (34 manual + 4 auto-script) ở 4 phần (A HTML + AB balance 13, B content 6, C questions/answers + C2 verify 11, D integrated-compare coverage 4).
PHẦN 0: AUTO-CHECK SCRIPTS — 3 checks BẮT BUỘC chạy đầu tiên
🔒 BẮT BUỘC chạy 3 script trước khi đánh giá manual checklist. Nếu BẤT KỲ script nào FAIL → quay lại BƯỚC 4 sửa, KHÔNG đánh giá tiếp các mục manual.
| # | Check | Cách verify | PASS nếu |
|---|---|---|---|
| 0a | Auto furigana | python3 .claude/skills/jlpt-reading-integrated/scripts/check_furigana.py --file assets/html/doc_hieu_tong_hop/<file>.html --level <LEVEL> --csv rules/kanji_jlpt_sensei.csv |
Exit code 0. Output KHÔNG có MISSING FURIGANA. (Auto-detect kanji vượt level thiếu ruby) |
| 0b | Auto CSV fields | python3 .claude/skills/jlpt-reading-integrated/scripts/check_csv_fields.py --csv sheets/samples_v1.csv --kind integrated |
Exit code 0. Output ALL ROWS VALID. (Auto-check _id, level, tag, kind, question_label_*, Q slots đầy đủ) |
| 0c | Auto spacing | python3 .claude/skills/jlpt-reading-integrated/scripts/check_spacing.py --file assets/html/doc_hieu_tong_hop/<file>.html --level <LEVEL> |
Exit code 0. Status OK. (N5 BẮT BUỘC わかち書き ratio ≥ 3%; N1-N4 BẮT BUỘC ratio ≤ 0.5%) |
| 0d | Auto answer 。 | python3 .claude/skills/jlpt-reading-integrated/scripts/check_answer_punctuation.py --csv sheets/samples_v1.csv |
Exit code 0. Output ALL ROWS VALID. (Phần 5.8: câu hoàn chỉnh → cần 。; mệnh đề từ / kanji-noun → không 。; nhất quán trong 1 Q) |
CẤM bỏ qua 3 mục này — đây là enforce mạnh nhất. Auto-scripts không thể đoán → phải pass thực sự.
PHẦN A: HTML + A/B BALANCE (13 checks)
Agent đọc lại file HTML và kiểm tra:
| # | Check | Cách verify | PASS nếu |
|---|---|---|---|
| 1 | Scope level | Đọc filename {LEVEL}_... |
Level ∈ {N1, N2}. N3/N4/N5 = FAIL ngay, không apply |
| 2 | Char count (tổng A+B) | Chạy process_html.py --count-only --file ... |
Trong Target Range: N1 600-750, N2 600-800 |
| 3 | Không Hard Reject | So với Hard Reject threshold | ≥ 570 (cả 2 level) |
| 4 | A/B balance | Đếm chars riêng mỗi <section> + tính tỷ lệ |
Mỗi đoạn 40–60% tổng; chênh lệch ≤ 30% |
| 5 | 2 sections A và B | Xem HTML structure | Có <section class="passage-a"> + <section class="passage-b"> (HOẶC 3 sections advice: 相談者+回答者A+回答者B) |
| 6 | Nhãn A/B hiển thị | Xem HTML | Mỗi section có <span class="label">A</span> / <span class="label">B</span> (hoặc 相談者 / 回答者A / 回答者B) |
| 7 | Flow text | Tìm 。<br> trong HTML |
Không có 。<br> nào (dùng <p> thuần) |
| 8 | Container CSS | Xem CSS | max-width: 780px, margin: 0 auto, padding: 40px 20px, line-height: 1.9, word-break: keep-all |
| 9 | White section background | Xem CSS | .passage-a, .passage-b có background: white, border #e5e7eb, border-radius 6px |
| 10 | Paragraph count per section | Đếm <p> trong mỗi section |
Mỗi section 2–4 <p> (bài ngắn, súc tích) |
| 11 | Furigana format | Tìm ngoặc 漢字(かんじ) hoặc 漢字【かんじ】 |
Không có — tất cả furigana dùng <ruby><rt> |
| 12 | Ruby có <rt> không rỗng |
Xem mọi <ruby>...</ruby> |
Tất cả đều có <rt> chứa furigana không rỗng (vd <ruby>未曾有<rt>みぞう</rt></ruby>). CẤM <ruby>未曾有</ruby> (thiếu rt) hoặc <ruby>未曾有<rt></rt></ruby> (rt rỗng). Auto-check: process_html.py --validate |
| 13 | Ruby count đúng level | Đếm <ruby> |
N1 ≤ 3, N2 ≤ 5. Ưu tiên 0 (data gốc = 0%) |
PHẦN B: NỘI DUNG & TỪ VỰNG (6 checks)
| # | Check | Cách verify | PASS nếu |
|---|---|---|---|
| 14 | Chủ đề đúng level | Đọc nội dung, đối chiếu R1 | N1: triết học/văn hóa/xã luận cao cấp. N2: văn hóa đời sống/công nghệ/giáo dục/môi trường |
| 15 | A và B CÙNG topic | So 2 đoạn | A và B bàn về CÙNG 1 vấn đề (VD AI; SNS; giáo dục), chỉ khác quan điểm/góc nhìn |
| 16 | A ↔ B có relationship rõ | Đọc 2 đoạn | Xác định được: contrast / complement / debate / advice. Không được A và B nói 2 chủ đề không liên quan |
| 17 | Không mơ hồ (test 2 cách hiểu) | Đọc từng câu, thử hiểu theo cách 2 | Chỉ có DUY NHẤT 1 cách hiểu hợp lý cho từng câu hỏi |
| 18 | Từ vựng đúng level | Đọc từng từ, đối chiếu R3 | Key terms ≤ level, không dùng ngữ pháp vượt level. N1 văn luận thuyết cao cấp (~にほかならない/~ざるを得ない). N2 formal trung cấp (~に伴い/~を踏まえて) |
| 19 | Furigana đúng từ (tra CSV) | Chạy python3 .claude/skills/jlpt-reading-integrated/scripts/check_furigana.py --file <file.html> --level <LEVEL> --csv rules/kanji_jlpt_sensei.csv |
Output KHÔNG có dòng MISSING FURIGANA. Mọi kanji vượt level đều có <ruby><rt>. Cấm dạng "Ab" (媒たい). |
PHẦN C: CÂU HỎI & ĐÁP ÁN (11 checks — áp dụng cho TỪNG câu hỏi)
Agent đọc TOÀN BỘ 2 câu hỏi + 4 đáp án từ CSV và đánh giá từng câu (Q1, Q2):
| # | Check | Cách verify | PASS nếu |
|---|---|---|---|
| 20 | Số câu hỏi đúng level | Xem CSV đếm slot đã fill | Cả N1 và N2: Q1+Q2 có content, Q3+Q4+Q5 empty |
| 21 | Label CỐ ĐỊNH (cả 2 câu) | Xem question_label_1 + question_label_2 |
CẢ 2 phải là question_comprehensive_understanding. KHÔNG label nào khác |
| 22 | Q2 compare A vs B (BẮT BUỘC) | Đọc Q2 | Q2 test tích hợp 2 đoạn (có cụm AとB, AもBも, AとBで共通, AとBの違い hoặc tương đương). Cấm Q2 chỉ về A, chỉ về B, hoặc kiến thức ngoài bài |
| 23 | Q1 và Q2 test khía cạnh khác nhau | So nội dung Q1 vs Q2 | Q1 ≠ Q2 về khía cạnh: VD Q1 common → Q2 compare difference; Q1 focus 1 đoạn → Q2 compare tổng thể |
| 24 | Marker khớp câu hỏi (nếu có) | So marker trong HTML với câu hỏi | Nếu Q1 có marker (①...とあるが): HTML phải có <span class="marker">①</span> trong A hoặc B. Q2 KHÔNG có marker (vì compare tổng thể) |
| 25 | Answer format (mỗi câu) | Xem 4 đáp án trong CSV | Đúng 4 options ngăn cách \n, KHÔNG 1./①/1) prefix. Độ dài tương đương (ratio < 2.0) |
| 26 | correct_answer (mỗi câu + batch) | Xem giá trị correct_answer_i |
Integer 1-4. Scan batch: không lặp cùng vị trí ≥ 3 bài liên tiếp |
| 27 | Paraphrase đáp án đúng (mỗi câu) | So đáp án đúng với bài gốc | KHÔNG trùng cụm ≥ 4 từ liên tiếp (N1) hoặc ≥ 5 từ (N2) |
| 28 | Distractor đa dạng bẫy (mỗi câu) | Phân loại 3 distractor | Đa dạng ≥ 3 loại (6 loại: Role reversal A/B / Single-side / Mix A+B / Scope / Extreme / Extraneous). Q2 BẮT BUỘC ≥ 2 distractor dạng Role reversal HOẶC Single-side |
| 29 | Distractor có căn cứ trong bài (mỗi câu) | Với mỗi đáp án sai: trích được câu/vị trí trong A hoặc B để bác bỏ | KHÔNG bịa. Mỗi distractor dùng info/concept từ bài nhưng sai ngữ cảnh |
| 30 | Explanations 3 phần (mỗi câu) | Đọc explain_vn_i + explain_en_i |
Có đủ 3 phần: đáp án đúng (trích A + B cho Q2) + đáp án sai (nêu loại bẫy, đặc biệt Role reversal) + tóm tắt. Cả VN và EN đầy đủ |
PHẦN C2: VERIFY ĐÁP ÁN (⛔ QUAN TRỌNG NHẤT) — 2 checks
Agent tự giải từng câu từ đầu — KHÔNG nhìn đáp án đã gen. Đây là bước bắt lỗi distractor bịa, câu hỏi ambiguous, sai
correct_answer, đặc biệt distractor đảo vai A/B.
| # | Check | Cách verify | PASS nếu |
|---|---|---|---|
| 31 | Tự giải Q1 + Q2 | Đọc A + B + từng câu hỏi, tự chọn đáp án từ đầu (KHÔNG nhìn correct_answer_i) |
CẢ 2 kết quả tự chọn KHỚP với correct_answer_i trong CSV |
| 32 | Distractor self-test (toàn bộ câu) | Với TỪNG đáp án sai trong TỪNG câu: trích dẫn chính xác câu/vị trí trong A hoặc B dùng để bác bỏ. Kiểm tra distractor Role reversal: thứ tự chủ thể trong distractor phải ngược với bài | Mọi distractor đều trích được. Không trích được = BỊA → FAIL |
PHẦN D: INTEGRATED-COMPARE COVERAGE (2 checks)
Đặc biệt quan trọng cho đọc hiểu tổng hợp: Q2 phải compare tổng thể 2 đoạn, Q1 + Q2 không trùng khía cạnh.
| # | Check | Cách verify | PASS nếu |
|---|---|---|---|
| 33 | Q2 tích hợp cả A và B | Xác định đáp án đúng Q2 có dựa trên cả A và B | Đáp án đúng Q2 PHẢI cần info từ CẢ A + B để chọn. Nếu chỉ cần A hoặc chỉ cần B → FAIL |
| 34 | Common thread rõ ràng | Xác định được điểm chung / điểm khác giữa A và B | Có thể tóm tắt trong 1 câu: "A và B cùng ... nhưng khác ở ..." HOẶC "A cho rằng X, B cho rằng Y". Nếu A và B không có relationship rõ → FAIL |
🔒 GATE 3→4 — KHÔNG QUA = KHÔNG ĐƯỢC SỬA
Sau khi đánh giá 34 mục, agent PHẢI confirm trước khi vào fix loop:
- Đã hoàn tất đánh giá ĐẦY ĐỦ 34/34 mục (không thiếu mục nào)
- Đã liệt kê chính xác danh sách các mục FAIL (số mục + lý do FAIL)
- Mỗi FAIL có diagnosis cụ thể (sửa cái gì, ở đâu, theo rule nào)
- Phân biệt rõ fix HTML (cần
--refreshCSV sau) vs fix CSV (chỉ cầnfill_qa.py) vs fix Q&A logic (gen lại distractor)
🚨 LƯU Ý ĐẶC BIỆT:
- Nếu ≥ 50% mục FAIL → bài này hỏng tổng thể → GEN LẠI TỪ ĐẦU (giữ
_id), KHÔNG fix vá- Nếu mục #25/#26 (self-solve) FAIL → đáp án có vấn đề logic → BẮT BUỘC review lại bài + Q+A, có thể GEN LẠI
- Nếu char count FAIL > Hard Reject → GEN LẠI HOÀN TOÀN (giữ
_id)
❌ Bất kỳ item nào CHƯA tick → quay lại BƯỚC 3 đánh giá lại.
✅ Khi 4/4 tick → log GATE 3→4 PASSED — fix list: [#x, #y, #z] với diagnoses rồi sang BƯỚC 4.
BƯỚC 4: SỬA & LẶP LẠI
⛔ Khi sửa HTML, CẬP NHẬT CSV — chạy lại
process_html.py --refreshđể cập nhậttext_read,jp_char_counttrong CSV.🚨 ĐẶC BIỆT khi sửa
<ruby>thiếu/rỗng<rt>: Đây là lỗi PHỔ BIẾN — agent hay chỉ sửa HTML mà QUÊN refresh CSV → CSV cộttext_readvẫn chứa ruby hỏng → AI fine-tuning data BỊ HỎNG. Workflow BẮT BUỘC khi sửa ruby:
- Sửa HTML: thay
<ruby>未曾有</ruby>→<ruby>未曾有<rt>みぞう</rt></ruby>- BẮT BUỘC chạy:
python3 .claude/skills/jlpt-reading-integrated/scripts/process_html.py --refresh --html-dir assets/html/doc_hieu_tong_hop --csv sheets/samples_v1.csv- Verify:
python3 .claude/skills/jlpt-reading-integrated/scripts/process_html.py --validate --html-dir assets/html/doc_hieu_tong_hop --csv sheets/samples_v1.csv— output PHẢI có dòng✅ CSV ...: 0 row với broken ruby. Nếu vẫn báo🚫 CSV ... có N row với broken ruby→ CSV chưa sync, chạy lại--refresh.Không có screenshot nên KHÔNG cần chạy lại screenshot script.
| Nếu FAIL | Hành động | Sau đó |
|---|---|---|
| #0a (auto furigana FAIL) | Đọc output check_furigana.py: thêm <ruby><rt> cho mỗi kanji bị MISSING; bỏ ruby thừa cho REDUNDANT |
Chạy lại check_furigana.py → QC lại |
| #0b (auto CSV fields FAIL) | Đọc output check_csv_fields.py: fix từng field bị MISSING bằng fill_qa.py (KHÔNG sửa CSV tay) |
Chạy lại check_csv_fields.py → QC lại |
| #0c (auto spacing FAIL) | N5 MISSING_WAKACHI: thêm khoảng trắng giữa cụm từ. N1-N4 UNEXPECTED_WAKACHI: bỏ khoảng trắng giữa kanji/kana | Chạy lại check_spacing.py → --refresh CSV → QC lại |
| #0d (auto answer 。 FAIL) | Đọc output check_answer_punctuation.py: câu hoàn chỉnh thiếu 。 → thêm; mệnh đề/kanji-noun có 。 → bỏ; mix style → đồng bộ 4 options |
Chạy lại check_answer_punctuation.py → QC lại |
| #1 (scope level) | Level sai → REJECT, không gen lại — đọc hiểu tổng hợp chỉ có N1/N2 | Không tiếp tục |
| #2, #3 (chars) | Bổ sung/cắt nội dung. Nếu Hard Reject → gen lại hoàn toàn | Chạy --refresh → QC lại |
| #4 (A/B balance) | Cân bằng 2 đoạn (đoạn quá ngắn bổ sung, đoạn quá dài cắt) | Chạy --refresh → QC lại |
| #5, #6 (sections/label A/B) | Sửa HTML: thêm <section class="passage-a|b"> + <span class="label">A|B</span> |
Chạy --refresh → QC lại |
| #7 (flow text) | Sửa <br> → </p><p> |
Chạy --refresh → QC lại |
| #8, #9 (CSS/structure) | Sửa CSS (780px, 40px 20px, line-height 1.9) + background/border | Chạy --refresh → QC lại |
| #10 (paragraph count) | Chia/gộp paragraph đạt 2–4 per section | Chạy --refresh → QC lại |
| #11, #12, #13 (ruby) | Sửa ruby tags (tra lại rules/kanji_jlpt_sensei.csv). Ưu tiên thay từ thay vì rắc furigana |
Chạy --refresh → QC lại |
| #14-#16 | Gen lại nội dung (giữ _id): đảm bảo A/B cùng topic + quan điểm khác + relationship rõ | Chạy --refresh → QC lại |
| #17 (mơ hồ) | Sửa từ ngữ câu có 2 cách hiểu | Chạy --refresh → QC lại |
| #18 (từ vựng) | Thay từ/ngữ pháp về đúng level | Chạy --refresh → QC lại |
| #19 (furigana tra CSV) | Sửa ruby tags | Chạy --refresh → QC lại |
| #20 (số câu hỏi) | Thêm/xóa câu bằng fill_qa.py để đúng 2 slot |
QC lại |
| #21 (label cố định) | Sửa label trong fill_qa.py về question_comprehensive_understanding cho cả 2 câu |
QC lại |
| #22 (Q2 compare) | Viết lại Q2 để test A vs B — dùng AとB/AもBも/AとBで共通/AとBの違い |
QC lại |
| #23 (Q1 trùng Q2) | Viết lại Q1 hoặc Q2 để test khía cạnh khác | QC lại |
| #24 (marker ko khớp) | Thêm/bớt marker trong HTML hoặc sửa câu hỏi. Q2 không được có marker | Chạy --refresh nếu sửa HTML → QC lại |
| #25, #26, #27 (đáp án) | Sửa đáp án bằng fill_qa.py |
QC lại |
| #28 (distractor bẫy) | Viết lại distractor dùng 6 loại bẫy. Q2 phải có ≥ 2 Role reversal / Single-side | QC lại |
| #29 (distractor bịa) | Viết lại distractor dùng info thật từ A hoặc B | QC lại |
| #30 (explanation) | Viết lại explain 3 phần đầy đủ cho từng câu, trích dẫn A + B cho Q2 | QC lại |
| #31, #32 (self-solve + distractor) | Đáp án có thể sai → xem lại bài vs. đáp án, đặc biệt kiểm tra Role reversal | Sửa đáp án hoặc bài. QC lại |
| #33 (Q2 không tích hợp) | Viết lại Q2 để cần CẢ A + B để trả lời | QC lại |
| #34 (common thread yếu) | Gen lại A hoặc B để có relationship rõ hơn | Chạy --refresh → QC lại |
Lệnh refresh CSV sau khi sửa HTML:
Lệnh auto-check furigana sau khi sửa ruby:
python3 .claude/skills/jlpt-reading-integrated/scripts/check_furigana.py --file <file.html> --level <LEVEL> --csv rules/kanji_jlpt_sensei.csv
Output PHẢI không có MISSING FURIGANA. Nếu còn → sửa tiếp ruby.
python3 .claude/skills/jlpt-reading-integrated/scripts/process_html.py \
--refresh \
--file assets/html/doc_hieu_tong_hop/{LEVEL}_{uuid}.html \
--csv sheets/samples_v1.csv
Vòng lặp BẮT BUỘC: sửa → refresh CSV (nếu sửa HTML) → quay lại BƯỚC 2 (QC lại TẤT CẢ 34 mục TỪ ĐẦU, KHÔNG chỉ check mục đã FAIL) → nếu còn FAIL thì lặp lại. Tối đa 5 vòng. Sau 5 vòng vẫn FAIL → báo lỗi cho user, KHÔNG bỏ qua, KHÔNG sang bài tiếp.
🚨 CẤM TUYỆT ĐỐI:
- Mark "đủ tốt rồi" khi còn ≥ 1 FAIL
- Bỏ qua mục FAIL với lý do "minor"
- Sang bài tiếp khi bài hiện tại chưa ALL PASS
- QC lại chỉ mục đã sửa mà không check lại 34 mục (vì sửa 1 chỗ có thể làm vỡ chỗ khác)
🔒 GATE 4→5 — KHÔNG QUA = KHÔNG ĐƯỢC HOÀN THÀNH
Trước khi log "ALL PASSED", agent PHẢI confirm:
- Đã chạy QC checklist 38 mục TRỌN VẸN (gồm 4 auto-script + 34 manual) ở vòng cuối (không skip)
- TẤT CẢ 38/38 mục đều PASS — bao gồm 4 auto-script đều exit 0 (không có FAIL nào, không có "skip", không có "n/a")
- Nếu có sửa HTML trong loop → đã chạy
process_html.py --refreshđể sync CSV - Đã chạy
process_html.py --validatecho file hiện tại — KHÔNG có broken ruby trong cả HTML lẫn CSV - Self-solve thực sự thực hiện: agent tự giải bài + chọn đáp án mà không nhìn correct_answer → KHỚP
❌ Bất kỳ item nào CHƯA tick → quay lại BƯỚC 4 sửa tiếp. ✅ Khi 5/5 tick → cho phép sang BƯỚC 5.
BƯỚC 5: ✅ HOÀN THÀNH → BÀI TIẾP THEO
Chỉ khi TẤT CẢ 37 checks PASS + GATE 4→5 PASSED → log:
🎉 ALL PASSED (38/38) — {_id} hoàn thành — 2 câu hỏi (comprehensive_understanding × 2)
GATE 4→5 PASSED — bài này hoàn tất, sang bài tiếp.
→ Chuyển sang bài tiếp theo (quay lại GATE 0→1 nếu là bài đầu batch, hoặc BƯỚC 1 nếu cùng batch).
Batch size: 5 bài/lần (bài ngắn 600-800 chars, structure đơn giản 2 sections).
BƯỚC CUỐI: VERIFY BATCH (sau khi gen xong TẤT CẢ bài)
Sau khi hoàn thành toàn bộ batch, chạy verify toàn bộ:
# 1. Validate tất cả file HTML (char count + A/B balance + broken ruby)
python3 .claude/skills/jlpt-reading-integrated/scripts/process_html.py \
--validate --html-dir assets/html/doc_hieu_tong_hop
# 1b. Auto-check furigana coverage cho TẤT CẢ file HTML
python3 .claude/skills/jlpt-reading-integrated/scripts/check_furigana.py \
--html-dir assets/html/doc_hieu_tong_hop \
--csv rules/kanji_jlpt_sensei.csv
# 1c. Auto-check required CSV fields cho TẤT CẢ rows
python3 .claude/skills/jlpt-reading-integrated/scripts/check_csv_fields.py \
--csv sheets/samples_v1.csv \
--kind integrated
# 1e. Auto-check dấu `。` cuối lựa chọn cho TẤT CẢ rows
python3 .claude/skills/jlpt-reading-integrated/scripts/check_answer_punctuation.py \
--csv sheets/samples_v1.csv
# 1d. Auto-check わかち書き spacing cho TẤT CẢ file HTML
python3 .claude/skills/jlpt-reading-integrated/scripts/check_spacing.py \
--html-dir assets/html/doc_hieu_tong_hop
# 2. Đếm số rows trong CSV + check số câu hỏi + label CỐ ĐỊNH rule
python3 -c "
import csv
expected_q = {'N1': 2, 'N2': 2}
FIXED_LABEL = 'question_comprehensive_understanding'
with open('sheets/samples_v1.csv', 'r', encoding='utf-8') as f:
rows = list(csv.DictReader(f))
print(f'Total rows: {len(rows)}')
bad = 0
for r in rows:
lv = r.get('level')
if lv not in expected_q:
continue
want = expected_q[lv]
got = sum(1 for i in range(1, 6) if r.get(f'question_{i}', '').strip())
if got != want:
bad += 1
print(f\" ❌ {r['_id']} ({lv}): {got} câu, expected {want}\")
continue
bad_lbl = False
for i in range(1, want + 1):
lbl = r.get(f'question_label_{i}', '')
if lbl != FIXED_LABEL:
bad += 1
bad_lbl = True
print(f\" ❌ {r['_id']} ({lv}): câu {i} label = {lbl}, expected {FIXED_LABEL}\")
break
print(f'Multi-question + label OK: {len(rows) - bad}/{len(rows)}')
for level in ['N1','N2']:
n = sum(1 for r in rows if r.get('level') == level)
print(f' {level}: {n}')
"
Batch-level checklist
- Mỗi bài có
_idunique, đúng format{LEVEL}_{uuid}, Level ∈ {N1, N2} -
kind=đọc hiểu tổng hợptrong tất cả rows -
levelchỉ là N1 hoặc N2 (KHÔNG có N3/N4/N5) -
general_image=""(empty) — KHÔNG có PNG -
general_audio=""(empty) - Char count (tổng A+B) trong Target Range (N1:600-750, N2:600-800)
- Không bài nào dưới Hard Reject threshold (570)
- A/B balance ≤ 30% — mỗi đoạn 40–60% tổng chars
- Bài có 2 sections A + B (hoặc 3 sections advice 相談者+回答者A+回答者B)
- Mỗi section có
<span class="label">A|B</span>(hoặc nhãn advice) - Paragraph per section 2–4
<p> - Furigana chỉ cho từ vượt level, không dạng "Ab", mọi
<ruby>có<rt> - Ruby tags count ≤ expected (N1:3, N2:5). Ưu tiên 0.
- Mỗi bài có đúng 2 câu hỏi (cả N1 và N2) — Q3, Q4, Q5 slot empty
- Cả Q1 và Q2 có
question_label=question_comprehensive_understanding(CỐ ĐỊNH cho toàn dạng này) - Q2 BẮT BUỘC compare A vs B (không chỉ về A, không chỉ về B)
- Q1 và Q2 test 2 khía cạnh khác nhau
- Mỗi câu hỏi có 4 đáp án ngăn cách
\n(KHÔNG số thứ tự) -
correct_answer_iphân bố đều 1-4 trong batch - Distractor dùng info từ bài (không bịa), đa dạng 6 loại bẫy
- Q2 có ≥ 2 distractor dạng Role reversal A/B hoặc Single-side
-
explain_vn_i+explain_en_iđủ 3 phần cho cả 2 câu - Q2 explanation trích dẫn CẢ A + B để chứng minh đáp án đúng
- Bài có A ↔ B relationship rõ ràng (contrast/complement/debate/advice)
- A và B CÙNG topic, khác quan điểm/góc nhìn
-
text_readclean — không attribute, không class, không<rt>content -
<p>thuần, không<br>giữa câu, không<table> - Trong batch, tag đa dạng ≥ 2 category (nếu batch > 3)
- Trong batch, relationship types đa dạng ≥ 2 loại (contrast/complement/debate/advice)
Reference Data & Samples
Data mẫu có sẵn trong data/:
| Level | File | Samples |
|---|---|---|
| N1 | doc_hieu_tong_hop_n1_clean.json |
21 |
| N2 | doc_hieu_tong_hop_n2_clean.json |
37 |
N3, N4, N5 KHÔNG CÓ file data cho đọc hiểu tổng hợp — không applicable.
Load bằng:
# Stats N1/N2
python3 .claude/skills/jlpt-reading-integrated/scripts/load_references.py --stats
# 2 random samples N1
python3 .claude/skills/jlpt-reading-integrated/scripts/load_references.py --level N1 --count 2
LƯU Ý khi đọc data gốc:
- Data gốc N1 100% có A/B labels, N2 62% — skill LUÔN dùng
<section class="passage-a\|b">với<span class="label">. - Data gốc N2
<table>27% — legacy noise. Skill KHÔNG dùng<table>(dùng<section>). - Data gốc
<br>N1:28%, N2:13% — thói quen xấu. Output HTML skill dùng<p>thuần. - Data gốc N1 95% có 2 câu (khớp spec). N2 59% có 2 câu, 38% có 3 câu — skill FOLLOW SPEC (2 câu) không bắt chước data 3q.
- Data gốc ruby = 0% cả 2 level — skill giữ ruby cực ít (ưu tiên 0).
- Data gốc source line N1:4%, N2:0% — skill KHÔNG dùng source line.
- Data gốc annotation 注 N1:4%, N2:0% — skill hiếm khi dùng.
- Advice format (相談者/回答者) chỉ có ~5% data N2 — optional, mỗi batch ≤ 1 bài.
Chi tiết phân tích từng level xem references/sample-analysis.md.
Common errors (dạng đọc hiểu tổng hợp hay gặp)
- Gen level ngoài N1/N2 — SAI, skill này CHỈ N1/N2 (spec JLPT đọc hiểu tổng hợp không có N3/N4/N5)
- Gen 1 hoặc 3 câu — SAI, đọc hiểu tổng hợp = đúng 2 câu cho cả 2 level
- Dùng label khác
question_comprehensive_understanding— SAI. CẢ 2 câu đều phải là label này - Cả 2 câu chỉ về A hoặc chỉ về B — SAI. Q2 PHẢI compare A vs B
- Q1 và Q2 trùng khía cạnh — SAI, phải test 2 aspects khác nhau
- Char count < 570: bài quá ngắn — gen lại từ đầu
- A/B chênh lệch > 30%: 1 đoạn quá dài — cân bằng lại
- Chỉ có 1 đoạn (không có A và B) — SAI. Phải có cả 2 sections
- A và B nói chủ đề khác nhau — SAI. A và B PHẢI cùng topic, chỉ khác quan điểm/góc nhìn
- Dùng
<table>cho layout — KHÔNG, dùng<section class="passage-a\|b"> - Dùng
<br>giữa câu — KHÔNG, dùng<p>thuần - Thiếu nhãn A/B — phải có
<span class="label">A</span>/<span class="label">B</span> - Distractor weak — thiếu dạng "Role reversal A/B" hoặc "Single-side". Q2 BẮT BUỘC có ≥ 2
- Q2 dùng marker ①② — SAI, Q2 compare tổng thể, không marker
- Quên
question_prefix trong label — label phải làquestion_comprehensive_understanding(đủ prefix) - Q2 có thể trả lời chỉ bằng A hoặc chỉ bằng B — SAI, Q2 PHẢI cần cả 2 đoạn
- A và B không có relationship rõ — SAI. Phải contrast / complement / debate / advice
- Abuse ruby (> 3 N1, > 5 N2) — đọc hiểu tổng hợp thực tế gần như không có ruby. Ưu tiên 0
Cảnh báo bảo mật dữ liệu
🚫 KHÔNG ĐƯỢC GHI VÀO THƯ MỤC
rules/—rules/question_sheet.csv,rules/topic.json,rules/kanji_jlpt_sensei.csv,rules/question_format.json,rules/kind_mission_mapping.json,rules/mission.json,rules/rule_doc_hieu.mdlà file tham chiếu, chỉ đọc. Mọi dữ liệu gen phải ghi vàosheets/samples_v1.csv.