at.kotoba.lesson.pack
Lesson content the app drills. Append-only stack; latest = active. Free-form by design: a known core the UI reads + open `meta`/`defaults` round-tripped untouched (SPEC §3.1a). This record body IS the upload interchange shape (lessons/pack.schema.json).
Details · record, key tid
| Kind | record |
|---|---|
| Record key | tid |
| Authority | lesson.kotoba.at |
| Indexed |
Showing version bafyreigaixd5iwr5bjs2mrtgmpfs2i7as63hez5b5rce6jbgp6jb6r3ygq. Show the latest
Checks
Validunlimited-stringdefs.forms.properties.chauNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.imperativeNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.masuNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.naiNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.nakattaNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.nakyaNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.potentialNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.taNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.teNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.teruNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.tokuNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.forms.properties.volitionalNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.accept.itemsNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.answerNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.choices.itemsNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.confusableWith.itemsNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.glossNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.glyphNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.idNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.kanjiNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.promptNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.romajiNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.rowNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.item.properties.typeNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.createdAtNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.phaseNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.rationaleNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.script.itemsNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.titleNo maxLength, maxGraphemes or format limits this string.
{
"$type": "com.atproto.lexicon.schema",
"defs": {
"defaults": {
"description": "Pack-level drill defaults (SPEC §4). Open additional keys round-trip via the pack `meta`.",
"properties": {
"katakanaMultiplier": {
"description": "Queue weight multiplier for katakana. Fixed-point ×10000 (e.g. 1.5 -> 15000); no float type.",
"type": "integer"
},
"tapToTypeBox": {
"description": "Leitner box at/above which a glyph may graduate tap -> type.",
"maximum": 5,
"minimum": 1,
"type": "integer"
}
},
"type": "object"
},
"forms": {
"description": "Authored conjugation surfaces, keyed by the form names in src/drill/conjugate.ts. Kana only — the kanji surface is derived from the item's `kanji` form. A key this build does not know is ignored, so a form added later needs no lexicon change.",
"properties": {
"chau": {
"type": "string"
},
"imperative": {
"type": "string"
},
"masu": {
"type": "string"
},
"nai": {
"type": "string"
},
"nakatta": {
"type": "string"
},
"nakya": {
"type": "string"
},
"potential": {
"type": "string"
},
"ta": {
"type": "string"
},
"te": {
"type": "string"
},
"teru": {
"type": "string"
},
"toku": {
"type": "string"
},
"volitional": {
"type": "string"
}
},
"type": "object"
},
"item": {
"description": "A card. A discriminated union on `type` (#1), flattened into one object because lexicons have no oneOf: a RECOGNITION item (hiragana | katakana | kanji | word) requires glyph + romaji, a GRAMMAR item (particle | contraction | usage | sentence) requires id + prompt + answer. `conjugation` is a RECOGNITION type (#146): a derived verb surface, so it carries glyph + romaji like any word. Only `type` can be required here; the per-branch requiredness is enforced by lessons/pack.schema.json (JSON Schema if/then) and src/packs/validate.ts, which is what every reader of this record already routes through.",
"properties": {
"accept": {
"description": "GRAMMAR branch, optional. Alternative answers graded correct beside `answer` — casual forms routinely have two natural ones. Exact-match grading is unchanged; the accepted set just has more members.",
"items": {
"type": "string"
},
"type": "array"
},
"answer": {
"description": "GRAMMAR branch, required there. The one canonical answer; graded by exact compare after trim.",
"type": "string"
},
"choices": {
"description": "GRAMMAR branch, optional. Authored options for the choice grid (#145); contains `answer` when present. Never empty — the app drops an empty or wrong-typed list at the upload boundary rather than writing one.",
"items": {
"type": "string"
},
"type": "array"
},
"confusableWith": {
"description": "ROMAJI (not glyphs) of same-script confusers; cold-start distractor seed.",
"items": {
"type": "string"
},
"type": "array"
},
"forms": {
"description": "Authored kana surfaces for the forms no rule derives (#136) — an irregular's whole paradigm, or one form of an otherwise regular verb (iku's itte). A form with no entry falls back to the derivation.",
"ref": "#forms",
"type": "ref"
},
"gloss": {
"description": "English meaning; recommended for words/kanji, and for a grammar item it is the meaning of the whole line.",
"type": "string"
},
"glyph": {
"description": "RECOGNITION branch, required there. 1+ chars: single kana, word, or kanji.",
"type": "string"
},
"group": {
"description": "Verb conjugation class (#136): 1 godan, 2 ichidan, 3 irregular. Word items only. The app derives every form from it (src/drill/conjugate.ts) instead of the pack authoring them.",
"maximum": 3,
"minimum": 1,
"type": "integer"
},
"id": {
"description": "GRAMMAR branch, required there and unique within the pack. The SRS state map is glyph-keyed and a grammar item has no glyph, so it is keyed `grammar:<id>` (#145). Uniqueness is enforced by validate.ts, not here.",
"type": "string"
},
"kanji": {
"description": "Written form in kanji (or kanji + okurigana) of a kana word — にほんじん -> 日本人. The below-hint path is passive (#125); a usable ruby meaning prompt records the separate kanji-recognition lane (#171). Omit where there is no kanji form (gairaigo) or the word is normally written in kana.",
"type": "string"
},
"meta": {
"description": "Item-level open extension; UI ignores, round-trips.",
"type": "unknown"
},
"prompt": {
"description": "GRAMMAR branch, required there. The sentence, with the blank written by the author (U+FF3F). Opaque to this layer: it may carry `{kanji|kana}` ruby markup (#139).",
"type": "string"
},
"romaji": {
"description": "RECOGNITION branch, required there. Expected reading; lowercase Hepburn, exact case-insensitive match.",
"type": "string"
},
"row": {
"description": "Gojuon row label, single kana and combination kana (yoon + extended) only.",
"type": "string"
},
"type": {
"description": "Open. Recognition: hiragana | katakana | kanji | word | conjugation (#146, a derived verb surface). Grammar (#1): particle | contraction | usage | sentence.",
"type": "string"
},
"weight": {
"description": "Optional author priority override. Fixed-point ×10000 (e.g. 1.8 -> 18000); lexicons have no float type. App scales at the record edge (see README).",
"type": "integer"
}
},
"required": [
"type"
],
"type": "object"
},
"main": {
"description": "Lesson content the app drills. Append-only stack; latest = active. Free-form by design: a known core the UI reads + open `meta`/`defaults` round-tripped untouched (SPEC §3.1a). This record body IS the upload interchange shape (lessons/pack.schema.json).",
"key": "tid",
"record": {
"properties": {
"createdAt": {
"description": "ISO 8601. NOTE: the app currently stamps a date-only string (YYYY-MM-DD), not a datetime — left unformatted here pending reconciliation (see README).",
"type": "string"
},
"defaults": {
"ref": "#defaults",
"type": "ref"
},
"items": {
"items": {
"ref": "#item",
"type": "ref"
},
"type": "array"
},
"meta": {
"description": "Pack-level open extension; UI ignores, round-trips.",
"type": "unknown"
},
"phase": {
"description": "Open. kana | vocab | grammar.",
"type": "string"
},
"rationale": {
"type": "string"
},
"script": {
"description": "Declared scripts; drives chips + Focus. The scripts the glyphs are WRITTEN in — for a `word` item that is its kana script, not \"word\" (#99). Derived the same way if omitted; a word that is unsegmentable or mixes both kana falls back to \"word\". A declared script is cleaned by the app (#99): \"word\", junk and duplicates are dropped and the rest kept; \"word\" returns only if derivation finds an item with no derivable script.",
"items": {
"type": "string"
},
"type": "array"
},
"title": {
"type": "string"
}
},
"required": [
"title",
"items"
],
"type": "object"
},
"type": "record"
}
},
"id": "at.kotoba.lesson.pack",
"lexicon": 1
}