at.kotoba.session

kotoba.at

Schema Diff

+8 -4

From

CID
bafyreibciaumajm...
Indexed At
2026-06-15 20:02 UTC
View this version

To

CID
bafyreiau2yszsee...
Indexed At
2026-09-08 19:36 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

1 breaking change, 0 non-breaking changes.

Breaking Changes (1)
  • ConstraintTightened ConstraintTightened { vertex_id: "at.kotoba.session#card.mode", sort: "knownValues", old_value: "[\"tap\",\"type\"]", new_value: "[\"tap\",\"type\",\"meaning\",\"choice\"]" }

Migration Guidance

Constraint Changes

  • ConstraintTightened ConstraintTightened { vertex_id: "at.kotoba.session#card.mode", sort: "knownValues", old_value: "[\"tap\",\"type\"]", new_value: "[\"tap\",\"type\",\"meaning\",\"choice\"]" }
1 1
{
2 2
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "card": {
5 5
      "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).",
6 6
      "properties": {
7 7
        "answer": {
8 8
          "description": "What the user answered. Optional: may be absent on a skip/timeout (app-side `given` is nullable).",
9 9
          "type": "string"
10 10
        },
11 11
        "correct": {
12 12
          "type": "boolean"
13 13
        },
14 14
        "distractors": {
15 -
          "description": "Tap mode only; the romaji offered. Absent for type.",
15 +
          "description": "The other options offered beside the answer: romaji on a tap card, English glosses on a meaning card. Absent for type, which has no grid.",
16 16
          "items": {
17 17
            "type": "string"
18 18
          },
19 19
          "type": "array"
20 20
        },
21 21
        "glyph": {
22 +
          "description": "The item's SRS state key: the prompt glyph for a recognition card, `grammar:<id>` for a grammar one (which has no glyph).",
22 23
          "type": "string"
23 24
        },
24 25
        "mode": {
26 +
          "description": "How the card was answered. tap = pick the romaji reading, type = write it out, meaning = pick the English gloss (a word, or a derived verb form — see `type`), choice = pick the answer to a grammar prompt from its authored options.",
25 27
          "knownValues": [
26 28
            "tap",
27 -
            "type"
29 +
            "type",
30 +
            "meaning",
31 +
            "choice"
28 32
          ],
29 33
          "type": "string"
30 34
        },
31 35
        "parseMs": {
32 36
          "description": "render -> first response/keystroke.",
33 37
          "type": "integer"
34 38
        },
35 39
        "totalMs": {
36 40
          "description": "render -> submit (tap: == parseMs).",
37 41
          "type": "integer"
38 42
        },
39 43
        "ts": {
40 44
          "format": "datetime",
41 45
          "type": "string"
42 46
        },
43 47
        "type": {
44 -
          "description": "Open string; matches the pack item's type.",
48 +
          "description": "Open string; matches the pack item's type. `conjugation` is a de-conjugation card (#146) — a verb form derived at session time rather than authored in the pack, keyed on the conjugated surface.",
45 49
          "type": "string"
46 50
        }
47 51
      },
48 52
      "required": [
49 53
        "glyph",
50 54
        "type",
51 55
        "mode",
52 56
        "correct",
53 57
        "parseMs",
54 58
        "totalMs",
55 59
        "ts"
56 60
      ],
57 61
      "type": "object"
58 62
    },
59 63
    "config": {
60 64
      "description": "The setup choices that drove the session (enables Drill-again + analytics slicing).",
61 65
      "properties": {
62 66
        "cardStyle": {
63 67
          "description": "Open. genko | hanko | ma.",
64 68
          "type": "string"
65 69
        },
66 70
        "focus": {
67 71
          "description": "Open. all | hiragana | katakana.",
68 72
          "type": "string"
69 73
        },
70 74
        "length": {
71 75
          "description": "10 | 20 | full-count.",
72 76
          "type": "integer"
73 77
        },
74 78
        "recall": {
75 -
          "description": "Open. tap | mixed | type.",
79 +
          "description": "Open. tap | mixed | type | meaning | read (type + meaning).",
76 80
          "type": "string"
77 81
        }
78 82
      },
79 83
      "required": [
80 84
        "length",
81 85
        "focus",
82 86
        "recall",
83 87
        "cardStyle"
84 88
      ],
85 89
      "type": "object"
86 90
    },
87 91
    "main": {
88 92
      "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).",
89 93
      "key": "tid",
90 94
      "record": {
91 95
        "properties": {
92 96
          "cards": {
93 97
            "items": {
94 98
              "ref": "#card",
95 99
              "type": "ref"
96 100
            },
97 101
            "type": "array"
98 102
          },
99 103
          "config": {
100 104
            "ref": "#config",
101 105
            "type": "ref"
102 106
          },
103 107
          "endedAt": {
104 108
            "format": "datetime",
105 109
            "type": "string"
106 110
          },
107 111
          "packRef": {
108 112
            "description": "at:// URI of the lesson.pack record that drove this session.",
109 113
            "format": "at-uri",
110 114
            "type": "string"
111 115
          },
112 116
          "rollup": {
113 117
            "ref": "#rollup",
114 118
            "type": "ref"
115 119
          },
116 120
          "startedAt": {
117 121
            "format": "datetime",
118 122
            "type": "string"
119 123
          }
120 124
        },
121 125
        "required": [
122 126
          "startedAt",
123 127
          "endedAt",
124 128
          "cards",
125 129
          "rollup"
126 130
        ],
127 131
        "type": "object"
128 132
      },
129 133
      "type": "record"
130 134
    },
131 135
    "rollup": {
132 136
      "description": "Precomputed so range scans avoid touching the per-card array.",
133 137
      "properties": {
134 138
        "byType": {
135 139
          "description": "Map keyed by type string -> { n, correct }. `unknown` because lexicons have no dynamic-key map type (see README).",
136 140
          "type": "unknown"
137 141
        },
138 142
        "correct": {
139 143
          "type": "integer"
140 144
        },
141 145
        "medianParseMs": {
142 146
          "type": "integer"
143 147
        },
144 148
        "n": {
145 149
          "type": "integer"
146 150
        }
147 151
      },
148 152
      "required": [
149 153
        "n",
150 154
        "correct",
151 155
        "medianParseMs"
152 156
      ],
153 157
      "type": "object"
154 158
    }
155 159
  },
156 160
  "id": "at.kotoba.session",
157 161
  "lexicon": 1
158 162
}

Compare Other Versions

Lexicon Garden

@