at.kotoba.session
{
"$type": "com.atproto.lexicon.schema",
"defs": {
"card": {
"description": "One answered card. `answer` is what the user produced (the correct reading is derivable by joining packRef+glyph; not stored, per SPEC §3.2).",
"properties": {
"answer": {
"description": "What the user answered. Optional: may be absent on a skip/timeout (app-side `given` is nullable).",
"type": "string"
},
"correct": {
"type": "boolean"
},
"distractors": {
"description": "Tap mode only; the romaji offered. Absent for type.",
"items": {
"type": "string"
},
"type": "array"
},
"glyph": {
"type": "string"
},
"mode": {
"knownValues": [
"tap",
"type"
],
"type": "string"
},
"parseMs": {
"description": "render -> first response/keystroke.",
"type": "integer"
},
"totalMs": {
"description": "render -> submit (tap: == parseMs).",
"type": "integer"
},
"ts": {
"format": "datetime",
"type": "string"
},
"type": {
"description": "Open string; matches the pack item's type.",
"type": "string"
}
},
"required": [
"glyph",
"type",
"mode",
"correct",
"parseMs",
"totalMs",
"ts"
],
"type": "object"
},
"config": {
"description": "The setup choices that drove the session (enables Drill-again + analytics slicing).",
"properties": {
"cardStyle": {
"description": "Open. genko | hanko | ma.",
"type": "string"
},
"focus": {
"description": "Open. all | hiragana | katakana.",
"type": "string"
},
"length": {
"description": "10 | 20 | full-count.",
"type": "integer"
},
"recall": {
"description": "Open. tap | mixed | type.",
"type": "string"
}
},
"required": [
"length",
"focus",
"recall",
"cardStyle"
],
"type": "object"
},
"main": {
"description": "One practice session: the full per-card interaction array, the config that drove it, and session-level rollups. Append-only stack; TID rkeys (time-ordered).",
"key": "tid",
"record": {
"properties": {
"cards": {
"items": {
"ref": "#card",
"type": "ref"
},
"type": "array"
},
"config": {
"ref": "#config",
"type": "ref"
},
"endedAt": {
"format": "datetime",
"type": "string"
},
"packRef": {
"description": "at:// URI of the lesson.pack record that drove this session.",
"format": "at-uri",
"type": "string"
},
"rollup": {
"ref": "#rollup",
"type": "ref"
},
"startedAt": {
"format": "datetime",
"type": "string"
}
},
"required": [
"startedAt",
"endedAt",
"cards",
"rollup"
],
"type": "object"
},
"type": "record"
},
"rollup": {
"description": "Precomputed so range scans avoid touching the per-card array.",
"properties": {
"byType": {
"description": "Map keyed by type string -> { n, correct }. `unknown` because lexicons have no dynamic-key map type (see README).",
"type": "unknown"
},
"correct": {
"type": "integer"
},
"medianParseMs": {
"type": "integer"
},
"n": {
"type": "integer"
}
},
"required": [
"n",
"correct",
"medianParseMs"
],
"type": "object"
}
},
"id": "at.kotoba.session",
"lexicon": 1
}
Metadata
- DID
-
did:plc:o5f3cgna5sku4p6iitld6mxs - CID
-
bafyreibciaumajmfax5prw4njafg2v4fs4ezjcowrq6tsaf7dd2is4ztq4 - Indexed At
- 2026-06-15 20:02 UTC
- AT-URI
-
at://did:plc:o5f3cgna5sku4p6iitld6mxs/com.atproto.lexicon.schema/at.kotoba.session
Version History (2 versions)
Similar Lexicons
Lexicons whose schemas describe something close to this one. Check them before publishing a new one that overlaps.
-
at.kotoba.lesson.pack record
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 interchang…
-
space.opendeck.session record
A finished study session. Written once; the source of study history and activity stats.