Files
Hankan/data/hangul.json
MechaCat02 b80deb2f6f chore: scaffold, CI, and the export bundle verbatim
The export bundle is the input to this port, not a sketch: the curriculum,
the tutor prompt and the five logic modules are finished and tested. They
land here byte-identical and stay that way.

  diff -r export/data data && diff -r export/lib lib
  diff -r export/prompt prompt && diff export/validate.mjs validate.mjs

data/, lib/, prompt/ and validate.mjs sit at the repo root so validate.mjs
runs verbatim with no path edits. All four are excluded from lint and
formatting — they are not ours to restyle. Types for lib/ live alongside in
types/ rather than as sibling .d.ts files, so the verbatim check stays a
plain directory diff.

CI runs the curriculum gate first, before anything else can pass:

  node validate.mjs   PASS — 0 blocking, 0 advisory

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 19:11:40 +02:00

492 lines
8.9 KiB
JSON

{
"consonants": [
{
"jamo": "ㄱ",
"roman": "g / k",
"name": "기역",
"tense": false
},
{
"jamo": "ㄲ",
"roman": "kk",
"name": "쌍기역",
"tense": true
},
{
"jamo": "ㄴ",
"roman": "n",
"name": "니은",
"tense": false
},
{
"jamo": "ㄷ",
"roman": "d / t",
"name": "디귿",
"tense": false
},
{
"jamo": "ㄸ",
"roman": "tt",
"name": "쌍디귿",
"tense": true
},
{
"jamo": "ㄹ",
"roman": "r / l",
"name": "리을",
"tense": false
},
{
"jamo": "ㅁ",
"roman": "m",
"name": "미음",
"tense": false
},
{
"jamo": "ㅂ",
"roman": "b / p",
"name": "비읍",
"tense": false
},
{
"jamo": "ㅃ",
"roman": "pp",
"name": "쌍비읍",
"tense": true
},
{
"jamo": "ㅅ",
"roman": "s",
"name": "시옷",
"tense": false
},
{
"jamo": "ㅆ",
"roman": "ss",
"name": "쌍시옷",
"tense": true
},
{
"jamo": "ㅇ",
"roman": "— / ng",
"name": "이응",
"tense": false
},
{
"jamo": "ㅈ",
"roman": "j",
"name": "지읒",
"tense": false
},
{
"jamo": "ㅉ",
"roman": "jj",
"name": "쌍지읒",
"tense": true
},
{
"jamo": "ㅊ",
"roman": "ch",
"name": "치읓",
"tense": false
},
{
"jamo": "ㅋ",
"roman": "k",
"name": "키읔",
"tense": false
},
{
"jamo": "ㅌ",
"roman": "t",
"name": "티읕",
"tense": false
},
{
"jamo": "ㅍ",
"roman": "p",
"name": "피읖",
"tense": false
},
{
"jamo": "ㅎ",
"roman": "h",
"name": "히읗",
"tense": false
}
],
"vowels": [
{
"jamo": "ㅏ",
"roman": "a",
"kind": "basic"
},
{
"jamo": "ㅑ",
"roman": "ya",
"kind": "basic"
},
{
"jamo": "ㅓ",
"roman": "eo",
"kind": "basic"
},
{
"jamo": "ㅕ",
"roman": "yeo",
"kind": "basic"
},
{
"jamo": "ㅗ",
"roman": "o",
"kind": "basic"
},
{
"jamo": "ㅛ",
"roman": "yo",
"kind": "basic"
},
{
"jamo": "ㅜ",
"roman": "u",
"kind": "basic"
},
{
"jamo": "ㅠ",
"roman": "yu",
"kind": "basic"
},
{
"jamo": "ㅡ",
"roman": "eu",
"kind": "basic"
},
{
"jamo": "ㅣ",
"roman": "i",
"kind": "basic"
},
{
"jamo": "ㅐ",
"roman": "ae",
"kind": "compound"
},
{
"jamo": "ㅒ",
"roman": "yae",
"kind": "compound"
},
{
"jamo": "ㅔ",
"roman": "e",
"kind": "compound"
},
{
"jamo": "ㅖ",
"roman": "ye",
"kind": "compound"
},
{
"jamo": "ㅘ",
"roman": "wa",
"kind": "compound"
},
{
"jamo": "ㅙ",
"roman": "wae",
"kind": "compound"
},
{
"jamo": "ㅚ",
"roman": "oe",
"kind": "compound"
},
{
"jamo": "ㅝ",
"roman": "wo",
"kind": "compound"
},
{
"jamo": "ㅞ",
"roman": "we",
"kind": "compound"
},
{
"jamo": "ㅟ",
"roman": "wi",
"kind": "compound"
},
{
"jamo": "ㅢ",
"roman": "ui",
"kind": "compound"
}
],
"batchim": [
{
"sound": "ㄱ",
"roman": "k",
"writtenAs": "ㄱ ㅋ ㄲ ㄳ ㄺ"
},
{
"sound": "ㄴ",
"roman": "n",
"writtenAs": "ㄴ ㄵ ㄶ"
},
{
"sound": "ㄷ",
"roman": "t",
"writtenAs": "ㄷ ㅅ ㅆ ㅈ ㅊ ㅌ ㅎ"
},
{
"sound": "ㄹ",
"roman": "l",
"writtenAs": "ㄹ ㄼ ㄽ ㄾ ㅀ"
},
{
"sound": "ㅁ",
"roman": "m",
"writtenAs": "ㅁ ㄻ"
},
{
"sound": "ㅂ",
"roman": "p",
"writtenAs": "ㅂ ㅍ ㅄ ㄿ"
},
{
"sound": "ㅇ",
"roman": "ng",
"writtenAs": "ㅇ"
}
],
"soundRules": [
{
"n": "Liaison",
"k": "연음",
"p": "A batchim followed by a silent ㅇ slides across into the next block. This is why written Korean and spoken Korean look so different.",
"a": "한국어",
"b": "한구거",
"r": "han-gu-geo"
},
{
"n": "Nasalisation",
"k": "비음화",
"p": "Before ㄴ or ㅁ, a stop batchim turns nasal: ㄱ→ㅇ, ㄷ→ㄴ, ㅂ→ㅁ.",
"a": "감사합니다",
"b": "감사함니다",
"r": "gam-sa-ham-ni-da"
},
{
"n": "Lateralisation",
"k": "유음화",
"p": "ㄴ next to ㄹ, in either order, becomes ㄹㄹ.",
"a": "신라",
"b": "실라",
"r": "sil-la"
},
{
"n": "Aspiration",
"k": "격음화",
"p": "ㅎ meeting ㄱ ㄷ ㅈ ㅂ fuses into the aspirated ㅋ ㅌ ㅊ ㅍ.",
"a": "좋다",
"b": "조타",
"r": "jo-ta"
},
{
"n": "Tensification",
"k": "경음화",
"p": "After a ㄱ ㄷ ㅂ batchim, a following ㄱ ㄷ ㅂ ㅅ ㅈ tenses to ㄲ ㄸ ㅃ ㅆ ㅉ.",
"a": "학교",
"b": "학꾜",
"r": "hak-kkyo"
},
{
"n": "Palatalisation",
"k": "구개음화",
"p": "A ㄷ or ㅌ batchim before 이 becomes 지 or 치.",
"a": "같이",
"b": "가치",
"r": "ga-chi"
},
{
"n": "ㅎ dropping",
"k": "ㅎ 탈락",
"p": "ㅎ between vowels, or after ㄴ ㄹ ㅁ ㅇ, is simply not pronounced.",
"a": "좋아요",
"b": "조아요",
"r": "jo-a-yo"
}
],
"soundPairs": [
{
"written": "한국어",
"spoken": "한구거",
"rule": "연음"
},
{
"written": "음악",
"spoken": "으막",
"rule": "연음"
},
{
"written": "읽어",
"spoken": "일거",
"rule": "연음"
},
{
"written": "앉아",
"spoken": "안자",
"rule": "연음"
},
{
"written": "꽃이",
"spoken": "꼬치",
"rule": "연음"
},
{
"written": "옷을",
"spoken": "오슬",
"rule": "연음"
},
{
"written": "앞에",
"spoken": "아페",
"rule": "연음"
},
{
"written": "낮에",
"spoken": "나제",
"rule": "연음"
},
{
"written": "있어",
"spoken": "이써",
"rule": "연음"
},
{
"written": "없어",
"spoken": "업써",
"rule": "연음"
},
{
"written": "맛있어",
"spoken": "마시써",
"rule": "연음"
},
{
"written": "끝났어",
"spoken": "끈나써",
"rule": "비음화"
},
{
"written": "감사합니다",
"spoken": "감사함니다",
"rule": "비음화"
},
{
"written": "입니다",
"spoken": "임니다",
"rule": "비음화"
},
{
"written": "십만",
"spoken": "심만",
"rule": "비음화"
},
{
"written": "국물",
"spoken": "궁물",
"rule": "비음화"
},
{
"written": "작년",
"spoken": "장년",
"rule": "비음화"
},
{
"written": "백만",
"spoken": "뱅만",
"rule": "비음화"
},
{
"written": "몇 명",
"spoken": "면 명",
"rule": "비음화"
},
{
"written": "독립",
"spoken": "동닙",
"rule": "비음화"
},
{
"written": "설날",
"spoken": "설랄",
"rule": "유음화"
},
{
"written": "신라",
"spoken": "실라",
"rule": "유음화"
},
{
"written": "좋다",
"spoken": "조타",
"rule": "격음화"
},
{
"written": "못해",
"spoken": "모태",
"rule": "격음화"
},
{
"written": "같아요",
"spoken": "가타요",
"rule": "연음"
},
{
"written": "학교",
"spoken": "학꾜",
"rule": "경음화"
},
{
"written": "할 수 있어",
"spoken": "할 쑤 이써",
"rule": "경음화"
},
{
"written": "밥 먹어",
"spoken": "밤머거",
"rule": "비음화"
},
{
"written": "같이",
"spoken": "가치",
"rule": "구개음화"
},
{
"written": "좋아요",
"spoken": "조아요",
"rule": "ㅎ 탈락"
},
{
"written": "싫어",
"spoken": "시러",
"rule": "ㅎ 탈락"
},
{
"written": "많이",
"spoken": "마니",
"rule": "ㅎ 탈락"
},
{
"written": "좋은",
"spoken": "조은",
"rule": "ㅎ 탈락"
},
{
"written": "넣어",
"spoken": "너어",
"rule": "ㅎ 탈락"
}
]
}