com.gamethesky.fightthesky.run

gamethesky.com

Schema Diff

+69 -0

From

CID
bafyreihc4qkunn7...
Indexed At
2026-10-21 03:10 UTC
View this version

To

CID
bafyreieoqpksgez...
Indexed At
2026-10-22 00:39 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

5 breaking changes, 15 non-breaking changes.

Breaking Changes (5)
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#worn", src: "com.gamethesky.fightthesky.run#worn", tgt: "com.gamethesky.fightthesky.run#worn.image", kind: "prop", name: Some("image") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#worn", src: "com.gamethesky.fightthesky.run#worn", tgt: "com.gamethesky.fightthesky.run#worn.name", kind: "prop", name: Some("name") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#face", src: "com.gamethesky.fightthesky.run#face", tgt: "com.gamethesky.fightthesky.run#face.image", kind: "prop", name: Some("image") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#face", src: "com.gamethesky.fightthesky.run#face", tgt: "com.gamethesky.fightthesky.run#face.name", kind: "prop", name: Some("name") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#face", src: "com.gamethesky.fightthesky.run#face", tgt: "com.gamethesky.fightthesky.run#face.slot", kind: "prop", name: Some("slot") }
Non-Breaking Changes (15)
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face.image" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face.name" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face.slot" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#worn" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#worn.image" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#worn.name" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run:body.faces" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run:body.faces:items" }
  • AddedVertex AddedVertex { vertex_id: "com.gamethesky.fightthesky.run:body.worn" }
  • AddedEdge AddedEdge { src: "com.gamethesky.fightthesky.run:body", tgt: "com.gamethesky.fightthesky.run:body.faces", kind: "prop", name: Some("faces") }
  • AddedEdge AddedEdge { src: "com.gamethesky.fightthesky.run:body", tgt: "com.gamethesky.fightthesky.run:body.worn", kind: "prop", name: Some("worn") }
  • AddedEdge AddedEdge { src: "com.gamethesky.fightthesky.run:body.faces", tgt: "com.gamethesky.fightthesky.run:body.faces:items", kind: "items", name: None }
  • AddedEdge AddedEdge { src: "com.gamethesky.fightthesky.run:body.faces:items", tgt: "com.gamethesky.fightthesky.run#face", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "com.gamethesky.fightthesky.run:body.worn", tgt: "com.gamethesky.fightthesky.run#worn", kind: "ref", name: None }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face.image" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face.name" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#face.slot" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#worn" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#worn.image" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run#worn.name" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run:body.faces" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run:body.faces:items" }
  • AddedVertex { vertex_id: "com.gamethesky.fightthesky.run:body.worn" }

Additional Notes

  • Breaking: RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#worn", src: "com.gamethesky.fightthesky.run#worn", tgt: "com.gamethesky.fightthesky.run#worn.image", kind: "prop", name: Some("image") }
  • Breaking: RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#worn", src: "com.gamethesky.fightthesky.run#worn", tgt: "com.gamethesky.fightthesky.run#worn.name", kind: "prop", name: Some("name") }
  • Breaking: RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#face", src: "com.gamethesky.fightthesky.run#face", tgt: "com.gamethesky.fightthesky.run#face.image", kind: "prop", name: Some("image") }
  • Breaking: RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#face", src: "com.gamethesky.fightthesky.run#face", tgt: "com.gamethesky.fightthesky.run#face.name", kind: "prop", name: Some("name") }
  • Breaking: RequiredEdgeAdded { vertex_id: "com.gamethesky.fightthesky.run#face", src: "com.gamethesky.fightthesky.run#face", tgt: "com.gamethesky.fightthesky.run#face.slot", kind: "prop", name: Some("slot") }
  • Non-breaking: AddedEdge { src: "com.gamethesky.fightthesky.run:body", tgt: "com.gamethesky.fightthesky.run:body.faces", kind: "prop", name: Some("faces") }
  • Non-breaking: AddedEdge { src: "com.gamethesky.fightthesky.run:body", tgt: "com.gamethesky.fightthesky.run:body.worn", kind: "prop", name: Some("worn") }
  • Non-breaking: AddedEdge { src: "com.gamethesky.fightthesky.run:body.faces", tgt: "com.gamethesky.fightthesky.run:body.faces:items", kind: "items", name: None }
  • Non-breaking: AddedEdge { src: "com.gamethesky.fightthesky.run:body.faces:items", tgt: "com.gamethesky.fightthesky.run#face", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "com.gamethesky.fightthesky.run:body.worn", tgt: "com.gamethesky.fightthesky.run#worn", kind: "ref", name: None }
1 1
{
2 2
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "build": {
5 5
      "description": "A fighter's build: twelve points at most over four stats of 1–5, and a special. The build changes the sim, so a verifier replays with it and refuses one over budget. Shared by the run record and the fighter record.",
6 6
      "properties": {
7 7
        "guts": {
8 8
          "maximum": 5,
9 9
          "minimum": 1,
10 10
          "type": "integer"
11 11
        },
12 12
        "power": {
13 13
          "maximum": 5,
14 14
          "minimum": 1,
15 15
          "type": "integer"
16 16
        },
17 17
        "reach": {
18 18
          "maximum": 5,
19 19
          "minimum": 1,
20 20
          "type": "integer"
21 21
        },
22 22
        "special": {
23 23
          "knownValues": [
24 24
            "post",
25 25
            "ratio",
26 26
            "rush"
27 27
          ],
28 28
          "maxLength": 16,
29 29
          "type": "string"
30 30
        },
31 31
        "speed": {
32 32
          "maximum": 5,
33 33
          "minimum": 1,
34 34
          "type": "integer"
35 35
        }
36 36
      },
37 37
      "required": [
38 38
        "power",
39 39
        "speed",
40 40
        "reach",
41 41
        "guts",
42 42
        "special"
43 43
      ],
44 44
      "type": "object"
45 45
    },
46 +
    "face": {
47 +
      "description": "One of the player's own faces, as it fought in a run: which ladder slot, the name under it, and the picture.",
48 +
      "properties": {
49 +
        "image": {
50 +
          "accept": [
51 +
            "image/jpeg"
52 +
          ],
53 +
          "description": "The face: a 256×256 JPEG, 64 KB at most, cropped to the middle of the photo. Readers refuse a bigger one.",
54 +
          "maxSize": 65536,
55 +
          "type": "blob"
56 +
        },
57 +
        "name": {
58 +
          "description": "The name under the face, 40 characters at most.",
59 +
          "maxGraphemes": 40,
60 +
          "maxLength": 160,
61 +
          "type": "string"
62 +
        },
63 +
        "slot": {
64 +
          "description": "The ladder slot the face fought in, 0 the Lurker to 9 the Discourse. The slots are filled by `faces` at their slot numbers and then by the people the player follows in order, so a face sits ahead of them, as it did on the player's screen.",
65 +
          "maximum": 9,
66 +
          "minimum": 0,
67 +
          "type": "integer"
68 +
        }
69 +
      },
70 +
      "required": [
71 +
        "slot",
72 +
        "name",
73 +
        "image"
74 +
      ],
75 +
      "type": "object"
76 +
    },
46 77
    "ghost": {
47 78
      "description": "A ghost fight's opponent: a strong reference to another player's fighter record, pinned to the version fought, plus how the CPU drove it. The verifier fetches that exact version, replays with its build and style, and refuses the run if the version is gone, so an owner editing their fighter changes no old result.",
48 79
      "properties": {
49 80
        "cid": {
50 81
          "description": "The version of that record the fight was played against.",
51 82
          "format": "cid",
52 83
          "type": "string"
53 84
        },
54 85
        "skill": {
55 86
          "description": "How sharp the ghost's CPU was, the challenger's choice: the sim thinks skill/10 times the difficulty's, so 10 on Normal is as good as the CPU gets. A verifier must replay at the same skill.",
56 87
          "maximum": 10,
57 88
          "minimum": 1,
58 89
          "type": "integer"
59 90
        },
60 91
        "style": {
61 92
          "description": "Advisory: how the ghost fought, copied from its record so a card can say so without fetching it. A verifier uses the record's own style and refuses a run that disagrees.",
62 93
          "knownValues": [
63 94
            "rusher",
64 95
            "turtle",
65 96
            "zoner",
66 97
            "tricky"
67 98
          ],
68 99
          "maxLength": 16,
69 100
          "type": "string"
70 101
        },
71 102
        "uri": {
72 103
          "description": "The opponent's `com.gamethesky.fightthesky.fighter` record, in their repo.",
73 104
          "format": "at-uri",
74 105
          "type": "string"
75 106
        }
76 107
      },
77 108
      "required": [
78 109
        "uri",
79 110
        "cid",
80 111
        "skill"
81 112
      ],
82 113
      "type": "object"
83 114
    },
84 115
    "main": {
85 116
      "description": "One run of Fight the Sky, published by the player into their own repo: a climb up the ladder, or a single ghost fight (see `ghost`). The record stores the fighter's build and every input rather than a score: the sim is deterministic, so re-running the input log against the same seed with the same build reproduces the run exactly. Owning the record is the identity proof, and replaying it is the score proof — score, wins and the rest are advisory and never trusted by a leaderboard.",
86 117
      "key": "tid",
87 118
      "record": {
88 119
        "properties": {
89 120
          "build": {
90 121
            "description": "The fighter's build: twelve points at most over four stats of 1–5, and a special. The build changes the sim, so a verifier replays with it and refuses one over budget.",
91 122
            "ref": "#build",
92 123
            "type": "ref"
93 124
          },
94 125
          "createdAt": {
95 126
            "format": "datetime",
96 127
            "type": "string"
97 128
          },
98 129
          "difficulty": {
99 130
            "description": "How hard the run was. A verifier must replay at the same difficulty. Absent means normal. Each difficulty has its own daily board.",
100 131
            "knownValues": [
101 132
              "granny",
102 133
              "easy",
103 134
              "normal",
104 135
              "hard"
105 136
            ],
106 137
            "maxLength": 16,
107 138
            "type": "string"
108 139
          },
140 +
          "faces": {
141 +
            "description": "The player's own photo faces that fought on the ladder, included on purpose (the game asks, off by default) so a replay anywhere shows them; each photo is a public blob in the player's repo. Cosmetic, like `look`: a face takes its ladder slot ahead of the people the player follows, the opponents' play is the sim's, and a verifier ignores this field entirely. Six at most. Never on a ghost fight.",
142 +
            "items": {
143 +
              "ref": "#face",
144 +
              "type": "ref"
145 +
            },
146 +
            "maxLength": 6,
147 +
            "type": "array"
148 +
          },
109 149
          "ghost": {
110 150
            "description": "Present on a ghost fight: who the opponent was and how sharp. A run with this never ranks on a board, whatever its seed.",
111 151
            "ref": "#ghost",
112 152
            "type": "ref"
113 153
          },
114 154
          "hits": {
115 155
            "description": "Advisory: hits landed.",
116 156
            "minimum": 0,
117 157
            "type": "integer"
118 158
          },
119 159
          "inputs": {
120 160
            "description": "The whole run as the only input the game takes. Comma-separated `<dtick>.<code>` entries, or `<dtick>.<code>.<v>` for the held ones: dtick is 60 Hz ticks since the previous entry; code 0 is a jab, 1 a kick, 2 the special, 3 throws in the towel (the run ends on that entry), 4 sets the held direction (v is -1 left, 0 none, 1 right; absolute, not relative to facing), 5 crouches (v 1) or stands (v 0), 6 jumps, 7 holds guard (v 1) or lets go (v 0). Only inputs the sim accepted are logged; a verifier refuses a log the sim would not have accepted. Example: `100.4.1,40.0,8.1,30.4.0`.",
121 161
            "maxLength": 400000,
122 162
            "type": "string"
123 163
          },
124 164
          "look": {
125 165
            "description": "Cosmetic: the fighter's three paint colors, as `rrggbb.rrggbb.rrggbb` (body, trim, gloves). The sim never sees it.",
126 166
            "maxLength": 32,
127 167
            "type": "string"
128 168
          },
129 169
          "perfects": {
130 170
            "description": "Advisory: fights won without taking a hit.",
131 171
            "minimum": 0,
132 172
            "type": "integer"
133 173
          },
134 174
          "score": {
135 175
            "description": "Advisory: the final score.",
136 176
            "minimum": 0,
137 177
            "type": "integer"
138 178
          },
139 179
          "seed": {
140 180
            "description": "Which ladder: a date (YYYY-MM-DD, local to the player) for the daily ladder, or any other string for a practice one or a ghost fight. The sim seeds from the FNV-1a hash of this string.",
141 181
            "maxLength": 64,
142 182
            "type": "string"
143 183
          },
144 184
          "simVersion": {
145 185
            "description": "Which rules produced these inputs. A verifier must replay under the matching version or refuse the run.",
146 186
            "minimum": 1,
147 187
            "type": "integer"
148 188
          },
149 189
          "start": {
150 190
            "description": "The ladder slot the run started at: 1 for a full run, any other for practice against that opponent. Absent means 1. Only full runs of a daily ladder rank. A ghost fight is always 1.",
151 191
            "maximum": 10,
152 192
            "minimum": 1,
153 193
            "type": "integer"
154 194
          },
155 195
          "ticks": {
156 196
            "description": "Advisory: the tick the run ended.",
157 197
            "minimum": 1,
158 198
            "type": "integer"
159 199
          },
160 200
          "wins": {
161 201
            "description": "Advisory: fights won.",
162 202
            "minimum": 0,
163 203
            "type": "integer"
164 204
          },
165 205
          "won": {
166 206
            "description": "Advisory: the whole ladder was cleared; in a ghost fight, the ghost was beaten.",
167 207
            "type": "boolean"
208 +
          },
209 +
          "worn": {
210 +
            "description": "The photo face the player wore themself in this run, included on purpose under the same switch as `faces` (off by default), so a replay anywhere shows it in their corner, with its name, instead of their avatar. A public blob in the player's repo. Cosmetic: a verifier ignores it. Never on a ghost fight.",
211 +
            "ref": "#worn",
212 +
            "type": "ref"
168 213
          }
169 214
        },
170 215
        "required": [
171 216
          "seed",
172 217
          "simVersion",
173 218
          "inputs",
174 219
          "build",
175 220
          "score",
176 221
          "wins",
177 222
          "ticks",
178 223
          "createdAt"
179 224
        ],
180 225
        "type": "object"
181 226
      },
182 227
      "type": "record"
228 +
    },
229 +
    "worn": {
230 +
      "description": "The face the player wore: the name they fought under and the picture.",
231 +
      "properties": {
232 +
        "image": {
233 +
          "accept": [
234 +
            "image/jpeg"
235 +
          ],
236 +
          "description": "A 256×256 JPEG, 64 KB at most, cropped to the middle of the photo. Readers refuse a bigger one.",
237 +
          "maxSize": 65536,
238 +
          "type": "blob"
239 +
        },
240 +
        "name": {
241 +
          "description": "The name they fought under, 40 characters at most.",
242 +
          "maxGraphemes": 40,
243 +
          "maxLength": 160,
244 +
          "type": "string"
245 +
        }
246 +
      },
247 +
      "required": [
248 +
        "name",
249 +
        "image"
250 +
      ],
251 +
      "type": "object"
183 252
    }
184 253
  },
185 254
  "id": "com.gamethesky.fightthesky.run",
186 255
  "lexicon": 1
187 256
}

Compare Other Versions

Lexicon Garden

@