Three unit-1.1 lessons with gpt-oss-20b through LM Studio and the server —
the first real model on the reworked turn. The letter-level check went out
right, and the +25 clamp held: a reported 80 on the first answer was stored
as 25. What failed was how the model wrote its blocks, a different way each
session. All three transcripts are in test/fixtures/, verbatim, and each
failure below is a test against them.
Marks lost. The prompt asks for `여덟 | wrong | 여덜`. The first session wrote
`we | wrong | 우라 → 우리`, English prompt first; the second wrote no ::result
at all and marked only in prose, `✗ 나 | I (humble) → 저`. evidence.ts keys on
the first field of a ::result row, so nothing was ever recorded — no
evidence, no schedule, no confusions, and a 다지기 review that could never
close. The artifact would have lost them the same way. domain/marking.ts
attaches each mark to its word only where that is unambiguous: one Korean
word first, or through a prompt of the exercise he answered, read via that
exercise's ::words as the letter check reads it. With no ::result block the
✓/✗ lines are read on the same terms, so a mark can never name a word the
exercise did not ask for; a mark on a whole sentence is still dropped. What
he mistook a word for is taken from what he actually wrote whenever the mark
itself gives no other word — the third session put the right answer there.
Its third session, marked through all of this: 20 evidence rows, 20 cards.
Progress on requests. The prompt allows marks, ::confirmed and ::progress
only in reply to an answer. The model wrote ::progress on every message, and
three requests for a new exercise took the unit from 50% to 80% with nothing
answered. A reply to anything but an answer now changes none of them.
Feedback swallowed. The model closed no blocks, so lib read what followed
each one as rows: "your score is about 5%" became a result row the student
never saw, and a "---" became a recall item he was asked to write in 한글.
Another session fenced every block in ```. gloss.ts now decides every
block's extent from the raw text — at "::", the next block, a rule or fence
line, a blank line with no row after it, or for the piped blocks the first
line without a "|" — and hands lib the blocks properly closed. The gate
audit, now run through the parser the lesson uses, still flags 7 and 2.
Answers given away. Translate rows came with their meanings ("나 | I") and
recall hints were the answers ("two | 이"). A translate row keeps only its
Korean line, and a recall hint that is the expected word, or any word the
message declares, is dropped.
Also: the spelling a recall prompt expects now keeps its qualifiers. With 나
"I, me (casual)" and 저 "I, me (humble)" in one list, "I (humble)" matched
나: no letter check was sent, and the mark for 저 was filed under 나.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
70 lines
9.1 KiB
JSON
70 lines
9.1 KiB
JSON
{
|
||
"source": "gpt-oss-20b (LM Studio) through server/src/backends/openai.ts, unit 1.1, 16 Sep 2026, second session. The whole transcript, verbatim. The model marked in prose only, with no ::result block, and wrote ::progress on messages that answered nothing.",
|
||
"turns": [
|
||
{
|
||
"role": "user",
|
||
"body": "Let's start unit 1.1 자음과 모음 (Consonants & vowels). Give me the full introduction, then a first exercise."
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "Welcome! I’m your reading tutor for the very first lesson in Korean, unit 1.1 자음과 모음 (Consonants & vowels). \nThis unit is all about **how a block is built**: one initial consonant + one vowel. The blocks you will read are the simplest syllables in Korean – no final consonants, no compound vowels, no tense or aspirated sounds. \n\n### Why this rule matters \nEvery Korean word is made of these blocks stacked together. If you can read a block, you already know how to decode every other block that follows it. The first step is therefore the most fundamental: recognizing and saying the consonant‑vowel pair. \nThe ten basic vowels are ㅏ ㅑ ㅓ ㅕ ㅗ ㅛ ㅜ ㅠ ㅡ ㅣ. \nThe plain consonants you will see in this unit are ㄱ ㄴ ㄷ ㄹ ㅁ ㅂ ㅅ ㅇ ㅈ ㅎ. \n\n### A quick example of a block \nTake **나**: it is made of the consonant ㄴ and the vowel ㅏ, written together as 하나의 블록. \nWhen you see this block, you read “na”. \nThe same idea applies to every other block: \n- **너** (ㄴ+ㅓ) → “neo” \n- **이** (ㅇ+ㅣ) → “i” (the ㅇ is silent at the start) \n- **그** (ㄱ+ㅡ) → “geu” \n- **저** (ㅈ+ㅓ) → “jeo”\n\n### Common mistake \nA new learner often mixes up ㄴ and ㄹ because they look similar. If you read a block that starts with ㄴ but sound it like ㄹ, the meaning will be wrong. Practice the shapes and sounds of each consonant separately.\n\n### New words for this unit \nThe words we’ll use in your exercises are all simple blocks that fit the rule: **나 너 이 그 저**. \n\nYou’re ready to start reading! Let’s practice by writing these words from English prompts.\n\n---\n\n::task recall\nI | 나\nyou (casual) | 너\ntwo (Sino) | 이\nthat (near you) | 그\nI (humble) | 저\n\n::words\n나 | I | ㄴ+ㅏ\n너 | you (casual) | ㄴ+ㅓ\n이 | two (Sino) | ㅇ+ㅣ\n그 | that (near you) | ㄱ+ㅡ\n저 | I (humble) | ㅈ+ㅓ"
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "My written answers:\nI → 나\nyou (casual) → 너\ntwo (Sino) → 이\nthat (near you) → 그\nI (humble) → 나\n\n════ LETTER-LEVEL CHECK — computed by the app ════\nThis is the actual jamo comparison. Use it exactly. Do NOT work out for yourself which letter was wrong, and never call a letter wrong that is listed as correct.\n• I (humble)\n wanted 저 [저=ㅈ+ㅓ]\n wrote 나 [나=ㄴ+ㅏ]\n syllable 1 (나 for 저) — WRONG: first consonant: wrote ㄴ, should be ㅈ; vowel: wrote ㅏ, should be ㅓ — CORRECT, do not call these mistakes: batchim none\n\n(No lookups.)"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "✓ 나 | I \n✓ 너 | you (casual) \n✓ 이 | two (Sino) \n✓ 그 | that (near you) \n✗ 나 | I (humble) → 저\n\n::words\n나 | I | ㄴ+ㅏ\n너 | you (casual) | ㄴ+ㅓ\n이 | two (Sino) | ㅇ+ㅣ\n그 | that (near you) | ㄱ+ㅡ\n나 | I (humble) | ㄴ+ㅏ\n\n::progress 80 | You’re reading most of the simple blocks correctly! Keep practicing to get all five right."
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "새 문제 주세요. Give me a new exercise."
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "Here’s a new practice set. Write the Korean words from the English prompts.\n\n---\n\n::task recall\nthe sea | 바다 \nbridge | 다리 \nI (humble) | 저 \nyou (casual) | 너 \none | 하나\n\n::words\n나 | I | ㄴ+ㅏ\n너 | you (casual) | ㄴ+ㅓ\n이 | two (Sino) | ㅇ+ㅣ\n그 | that (near you) | ㄱ+ㅡ\n저 | I (humble) | ㅈ+ㅓ\n바다 | the sea | ㅂ+ㅏ + ㄷ+ㅏ \n다리 | bridge | ㄷ+ㅏ + ㄹ+ㅣ \n하나 | one | 하(ㅎ+ㅏ) + 나(ㄴ+ㅏ)"
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "My written answers:\nthe sea → 바다\nbridge → 나\nI (humble) → 나\nyou (casual) → 너\none → 하나\n\n════ LETTER-LEVEL CHECK — computed by the app ════\nThis is the actual jamo comparison. Use it exactly. Do NOT work out for yourself which letter was wrong, and never call a letter wrong that is listed as correct.\n• bridge\n wanted 다리 [다=ㄷ+ㅏ · 리=ㄹ+ㅣ]\n wrote 나 [나=ㄴ+ㅏ]\n length differs: 2 syllables expected, 1 written | syllable 1 (나 for 다) — WRONG: first consonant: wrote ㄴ, should be ㄷ — CORRECT, do not call these mistakes: vowel ㅏ, batchim none\n• I (humble)\n wanted 저 [저=ㅈ+ㅓ]\n wrote 나 [나=ㄴ+ㅏ]\n syllable 1 (나 for 저) — WRONG: first consonant: wrote ㄴ, should be ㅈ; vowel: wrote ㅏ, should be ㅓ — CORRECT, do not call these mistakes: batchim none\n\n(No lookups.)"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "✓ 바다 | the sea \n✗ 나 | bridge → 다리 \n✗ 나 | I (humble) → 저 \n✓ 너 | you (casual) \n✓ 하나 | one \n\n::words\n바다 | the sea | ㅂ+ㅏ + ㄷ+ㅏ \n다리 | bridge | ㄷ+ㅏ + ㄹ+ㅣ \n하나 | one | 하(ㅎ+ㅏ) + 나(ㄴ+ㅏ) \n너 | you (casual) | ㄴ+ㅓ \n이 | two (Sino) | ㅇ+ㅣ \n그 | that (near you) | ㄱ+ㅡ \n저 | I (humble) | ㅈ+ㅓ \n나 | wrong | ㄴ+ㅏ \n\n::progress 60 | You’re reading most of the simple blocks correctly! Keep practicing to get all five right."
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "새 문제 주세요. Give me a new exercise."
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "Here’s a fresh practice set. Write the Korean word that matches each English prompt.\n\n---\n\n::task recall\nhere | 여기 \nthere | 거기 \nover there | 저기 \ntree | 나무 \nsound | 소리\n\n::words\n여기 | here | ㅇ+ㅕ \n거기 | there | ㄱ+ㅓ + 기(ㄱ+ㅣ) \n저기 | over there | ㅈ+ㅓ + 기(ㄱ+ㅣ) \n나무 | tree | ㄴ+ㅏ + 무(ㅁ+ㅜ) \n소리 | sound | ㅅ+ㅗ + 리(ㄹ+ㅣ) \n\n::progress 65 | You’re getting more comfortable reading simple blocks! Keep practicing to nail all five."
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "My written answers:\nhere → 여기\nthere → 여기\nover there → 여기\ntree → 나무\nsound → 소리\n\n════ LETTER-LEVEL CHECK — computed by the app ════\nThis is the actual jamo comparison. Use it exactly. Do NOT work out for yourself which letter was wrong, and never call a letter wrong that is listed as correct.\n• there\n wanted 거기 [거=ㄱ+ㅓ · 기=ㄱ+ㅣ]\n wrote 여기 [여=ㅇ+ㅕ · 기=ㄱ+ㅣ]\n syllable 1 (여 for 거) — WRONG: first consonant: wrote ㅇ, should be ㄱ; vowel: wrote ㅕ, should be ㅓ — CORRECT, do not call these mistakes: batchim none\n• over there\n wanted 저기 [저=ㅈ+ㅓ · 기=ㄱ+ㅣ]\n wrote 여기 [여=ㅇ+ㅕ · 기=ㄱ+ㅣ]\n syllable 1 (여 for 저) — WRONG: first consonant: wrote ㅇ, should be ㅈ; vowel: wrote ㅕ, should be ㅓ — CORRECT, do not call these mistakes: batchim none\n\n(No lookups.)"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "✓ 여기 | here \n✗ 여기 | there → 거기 \n✗ 여기 | over there → 저기 \n✓ 나무 | tree \n✓ 소리 | sound \n\n::words\n여기 | here | ㅇ+ㅕ \n거기 | there | ㄱ+ㅓ + 기(ㄱ+ㅣ) \n저기 | over there | ㅈ+ㅓ + 기(ㄱ+ㅣ) \n나무 | tree | ㄴ+ㅏ + 무(ㅁ+ㅜ) \n소리 | sound | ㅅ+ㅗ + 리(ㄹ+ㅣ) \n\n::progress 70 | You’re reading most of the simple blocks correctly! Keep practicing to get all five right."
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "새 문제 주세요. Give me a new exercise."
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "You’re doing great! Let’s keep practicing by writing the Korean words that match each English prompt. \n\n---\n\n::task recall\nI (humble) | 저 \nyou (casual) | 너 \ntree | 나무 \nsound | 소리 \nthe sea | 바다\n\n::words\n저 | I (humble) | ㅈ+ㅓ \n너 | you (casual) | ㄴ+ㅓ \n나무 | tree | ㄴ+ㅏ + 무(ㅁ+ㅜ) \n소리 | sound | ㅅ+ㅗ + 리(ㄹ+ㅣ) \n바다 | the sea | ㅂ+ㅏ + 다(ㄷ+ㅏ) \n\n::progress 75 | Keep up! You’re reading most of these simple blocks correctly."
|
||
},
|
||
{
|
||
"role": "user",
|
||
"body": "새 문제 주세요. Give me a new exercise."
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"body": "Here’s a fresh practice set. Write the Korean word that matches each English prompt.\n\n---\n\n::task recall\nI (humble) | 저 \nyou (casual) | 너 \nchild | 아이 \nmother | 어머니 \nhead | 머리\n\n::words\n저 | I (humble) | ㅈ+ㅓ \n너 | you (casual) | ㄴ+ㅓ \n아이 | child | 아(ㅇ+ㅏ) + 이(ㅇ+ㅣ) \n어머니 | mother | 어(ㅇ+ㅓ) + 머(ㅁ+ㅔ?) + 니(ㄴ+ㅣ) \n머리 | head | 머(ㅁ+ㅔ?) + 리(ㄹ+ㅣ) \n\n::progress 80 | You’re reading most of these simple blocks correctly! Keep practicing to get all five right."
|
||
}
|
||
]
|
||
}
|