SeaWolf-AI commited on
Commit
add1d2d
·
verified ·
1 Parent(s): 981e3a9

S1 revision: lowest-energy ranking, larger systems, validity gate, anchors/metric updated

Browse files
Files changed (1) hide show
  1. app.py +280 -280
app.py CHANGED
@@ -1,280 +1,280 @@
1
- # -*- coding: utf-8 -*-
2
- """Open Quantum Challenge (OQC) — submission intake + live leaderboard.
3
-
4
- Thin by design, exactly like the Open Discovery Challenge it mirrors. Nothing here scores.
5
- Entries land in a private dataset ledger (FINAL-Bench/oqc-ledger); a worker on the GPU box
6
- polls that ledger, scores each entry against a frozen private answer key, and writes the
7
- result and the rolled-up leaderboard back. One entrant can never block the service, and the
8
- yardstick stays private while the harness that produces entries is fully public.
9
-
10
- Layout in the ledger (shared with the worker):
11
- submissions/<board>/<id>.json written here when an entry is accepted
12
- results/<board>/<id>.json written by the worker
13
- leaderboard/<board>.json rolled up by the worker; the page reads one file
14
-
15
- Boards: qsim (Season 1), qec (Season 2).
16
- """
17
- import base64
18
- import hashlib
19
- import hmac
20
- import json
21
- import os
22
- import secrets
23
- import time
24
- import urllib.parse
25
- import urllib.request
26
-
27
- from fastapi import FastAPI, HTTPException, Request
28
- from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
29
- from pydantic import BaseModel
30
-
31
- import gates
32
- import seasons
33
- import store
34
-
35
- HERE = os.path.dirname(os.path.abspath(__file__))
36
- CACHE = store.Cached(ttl=int(os.environ.get("OQC_CACHE_TTL", "30")))
37
-
38
- OAUTH_ID = os.environ.get("OAUTH_CLIENT_ID", "")
39
- OAUTH_SECRET = os.environ.get("OAUTH_CLIENT_SECRET", "")
40
- OAUTH_ISS = os.environ.get("OPENID_PROVIDER_URL", "https://huggingface.co")
41
- SPACE_HOST = os.environ.get("SPACE_HOST", "")
42
- COOKIE = "oqc_session"
43
- IN_FRAME = bool(SPACE_HOST)
44
- COOKIE_KW = ({"samesite": "none", "secure": True} if IN_FRAME
45
- else {"samesite": "lax", "secure": False})
46
- SESSION_KEY = os.environ.get("OQC_SESSION_KEY") or secrets.token_hex(16)
47
- DAILY_CAP = int(os.environ.get("OQC_DAILY_CAP", "50"))
48
- CAP_TZ_OFFSET = 9 * 3600
49
-
50
- app = FastAPI(title="Open Quantum Challenge")
51
-
52
-
53
- class Submission(BaseModel):
54
- board: str # "qsim" or "qec"
55
- display_name: str
56
- method: str = ""
57
- predictions: dict = {}
58
-
59
-
60
- # ----------------------------------------------------------------- session (HF OAuth, optional)
61
- def _sign(payload):
62
- raw = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
63
- sig = hmac.new(SESSION_KEY.encode(), raw.encode(), hashlib.sha256).hexdigest()[:32]
64
- return raw + "." + sig
65
-
66
-
67
- def _unsign(token):
68
- try:
69
- raw, sig = (token or "").rsplit(".", 1)
70
- except ValueError:
71
- return None
72
- good = hmac.new(SESSION_KEY.encode(), raw.encode(), hashlib.sha256).hexdigest()[:32]
73
- if not hmac.compare_digest(sig, good):
74
- return None
75
- pad = "=" * (-len(raw) % 4)
76
- try:
77
- return json.loads(base64.urlsafe_b64decode(raw + pad))
78
- except Exception:
79
- return None
80
-
81
-
82
- def current_user(request):
83
- return _unsign(request.cookies.get(COOKIE))
84
-
85
-
86
- def _redirect_uri(request):
87
- if SPACE_HOST:
88
- return "https://%s/auth/callback" % SPACE_HOST
89
- return str(request.base_url).rstrip("/") + "/auth/callback"
90
-
91
-
92
- @app.get("/")
93
- async def index():
94
- return FileResponse(os.path.join(HERE, "index.html"))
95
-
96
-
97
- @app.get("/api/me")
98
- def me(request: Request):
99
- u = current_user(request)
100
- return {"signed_in": bool(u), "user": u,
101
- "oauth_configured": bool(OAUTH_ID and OAUTH_SECRET)}
102
-
103
-
104
- @app.get("/login")
105
- def login(request: Request):
106
- if not (OAUTH_ID and OAUTH_SECRET):
107
- raise HTTPException(503, "OAuth is not configured (add hf_oauth in README)")
108
- state = secrets.token_urlsafe(16)
109
- q = urllib.parse.urlencode({
110
- "client_id": OAUTH_ID, "redirect_uri": _redirect_uri(request),
111
- "response_type": "code", "scope": "openid profile", "state": state})
112
- r = RedirectResponse("%s/oauth/authorize?%s" % (OAUTH_ISS.rstrip("/"), q))
113
- r.set_cookie("oqc_state", state, max_age=600, httponly=True, **COOKIE_KW)
114
- return r
115
-
116
-
117
- @app.get("/auth/callback")
118
- def callback(request: Request, code: str = "", state: str = ""):
119
- saved = request.cookies.get("oqc_state")
120
- if not code or not saved or state != saved:
121
- raise HTTPException(400, "sign-in failed — please try again (third-party cookies may be blocked)")
122
- body = urllib.parse.urlencode({
123
- "client_id": OAUTH_ID, "client_secret": OAUTH_SECRET,
124
- "grant_type": "authorization_code", "code": code,
125
- "redirect_uri": _redirect_uri(request)}).encode()
126
- with urllib.request.urlopen(urllib.request.Request(
127
- OAUTH_ISS.rstrip("/") + "/oauth/token", data=body,
128
- headers={"Content-Type": "application/x-www-form-urlencoded"}), timeout=20) as r:
129
- tok = json.loads(r.read().decode())
130
- with urllib.request.urlopen(urllib.request.Request(
131
- OAUTH_ISS.rstrip("/") + "/oauth/userinfo",
132
- headers={"Authorization": "Bearer " + tok["access_token"]}), timeout=20) as r:
133
- ui = json.loads(r.read().decode())
134
- user = {"name": ui.get("preferred_username") or ui.get("name"),
135
- "picture": ui.get("picture"), "at": int(time.time())}
136
- resp = RedirectResponse("/")
137
- resp.set_cookie(COOKIE, _sign(user), max_age=60 * 60 * 24 * 14, httponly=True, **COOKIE_KW)
138
- resp.delete_cookie("oqc_state")
139
- return resp
140
-
141
-
142
- @app.get("/logout")
143
- def logout():
144
- r = RedirectResponse("/")
145
- r.delete_cookie(COOKIE)
146
- return r
147
-
148
-
149
- # ----------------------------------------------------------------- seasons / leaderboard
150
- @app.get("/api/seasons")
151
- def season_list():
152
- return {"seasons": seasons.listing(), "default": seasons.DEFAULT}
153
-
154
-
155
- def _board_json(board):
156
- return CACHE.get("board:%s" % board,
157
- lambda: store.read("leaderboard/%s.json" % board, default={}) or {})
158
-
159
-
160
- def _sub_ids(board):
161
- return CACHE.get("ids:%s" % board, lambda: store.listdir("submissions/%s" % board))
162
-
163
-
164
- @app.get("/api/leaderboard")
165
- def leaderboard(request: Request):
166
- board = (request.query_params.get("board") or "qsim").lower()
167
- s = seasons.by_board(board)
168
- if not s:
169
- raise HTTPException(404, "unknown board")
170
- data = _board_json(board)
171
- entries = data.get("entries") or []
172
- anchors, ranked = [], []
173
- for e in entries:
174
- u = e.get("user", "") or ""
175
- row = {"participant": u, "method": e.get("method", ""),
176
- "score": e.get("score"), "verified": bool(e.get("verified"))}
177
- if u.startswith(("baseline-", "reference-", "anchor-")):
178
- row["anchor"] = True
179
- anchors.append(row)
180
- else:
181
- ranked.append(row)
182
- # reference anchors mark the ladder; they do not climb it (ODC-style)
183
- if board == "qsim":
184
- anchors.insert(0, {"participant": "exact diagonalization", "anchor": True,
185
- "method": "theoretical floor (reference)", "score": 0.0, "verified": True})
186
- elif board == "qec":
187
- anchors.append({"participant": "near-optimal MLE bound", "anchor": True,
188
- "method": "information-theoretic reference (not a submission)", "score": None, "verified": True})
189
- ranked.sort(key=lambda r: (r["score"] is None, r["score"] if r["score"] is not None else 1e18))
190
- for i, r in enumerate(ranked, 1):
191
- r["rank"] = i
192
- return {"season": seasons.public(s), "anchors": anchors, "entries": ranked,
193
- "updated": data.get("updated"), "n": len(ranked)}
194
-
195
-
196
- @app.get("/api/queue")
197
- def queue(request: Request):
198
- board = (request.query_params.get("board") or "qsim").lower()
199
- ids = _sub_ids(board)
200
- scored = {e.get("user") for e in (_board_json(board).get("entries") or [])}
201
- return {"submitted": len(ids), "ranked": len(scored)}
202
-
203
-
204
- @app.get("/api/totals")
205
- def totals():
206
- subs = 0
207
- users = set()
208
- for n in seasons.SEASONS:
209
- b = seasons.SEASONS[n]["board"]
210
- for e in (_board_json(b).get("entries") or []):
211
- subs += 1
212
- if e.get("user"):
213
- users.add(e["user"])
214
- return {"ranked": subs, "participants": len(users)}
215
-
216
-
217
- # ----------------------------------------------------------------- submit
218
- @app.post("/api/submit")
219
- def submit(sub: Submission, request: Request):
220
- board = (sub.board or "").lower()
221
- s = seasons.by_board(board)
222
- if not s:
223
- raise HTTPException(400, "unknown board %r" % sub.board)
224
- if not seasons.accepting(s):
225
- if s.get("open"):
226
- raise HTTPException(403, "Season %d is closed (deadline %s)." % (s["number"], s["closes"]))
227
- raise HTTPException(403, "Season %d is not open yet (opens %s)." % (s["number"], s["opens"]))
228
- user = current_user(request)
229
- if (OAUTH_ID and OAUTH_SECRET) and not user:
230
- raise HTTPException(401, "Hugging Face sign-in required")
231
- who = (user or {}).get("name") or (sub.display_name or "").strip()[:60]
232
- if not who:
233
- raise HTTPException(400, "display name required")
234
-
235
- v = gates.check(board, sub.predictions)
236
- if not v["admitted"]:
237
- return JSONResponse({"accepted": False, "reasons": v["reject"]}, status_code=422)
238
-
239
- # wrong-track guard: predictions whose keys are clearly for the other board
240
- keys = list(sub.predictions.keys())
241
- if keys:
242
- qec_like = sum(k.startswith("shot_") for k in keys) > len(keys) // 2
243
- qsim_like = sum(k.startswith("hub_") for k in keys) > len(keys) // 2
244
- if board == "qsim" and qec_like:
245
- return JSONResponse({"accepted": False, "reasons": [
246
- "This looks like a QEC submission (shot_* keys). Please select Season 2 - QEC Decoder."]}, status_code=422)
247
- if board == "qec" and qsim_like:
248
- return JSONResponse({"accepted": False, "reasons": [
249
- "This looks like a QSIM submission (hub_* keys). Please select Season 1 - Quantum Simulation."]}, status_code=422)
250
-
251
- # daily cap via a small tally file (not a tree walk)
252
- day = time.strftime("%Y-%m-%d", time.gmtime(time.time() + CAP_TZ_OFFSET))
253
- quota_path = "quota/%s/%s.json" % (board, day)
254
- quota = store.read(quota_path, default={}) or {}
255
- if DAILY_CAP > 0 and int(quota.get(who, 0)) >= DAILY_CAP:
256
- return JSONResponse({"accepted": False, "daily_cap": DAILY_CAP,
257
- "reasons": ["daily submission cap reached (%d). Resets at KST midnight." % DAILY_CAP]},
258
- status_code=429)
259
-
260
- safe = "".join(c for c in who if c.isalnum() or c in "-_")[:40] or "anon"
261
- sid = "%s_%s_%s" % (time.strftime("%Y%m%d_%H%M%S"), safe, secrets.token_hex(2))
262
- rec = {"hf_user": who, "display_name": (sub.display_name or who)[:60],
263
- "method": (sub.method or "").strip()[:200], "predictions": sub.predictions,
264
- "board": board, "season": s["number"], "spec": "oqc-v1",
265
- "n_items": v["n_items"], "submitted_at": int(time.time())}
266
- quota[who] = int(quota.get(who, 0)) + 1
267
- try:
268
- store.write_many([("submissions/%s/%s.json" % (board, sid), rec),
269
- (quota_path, quota)],
270
- summary="oqc %s entry %s" % (board, sid))
271
- except store.Busy:
272
- return JSONResponse({"accepted": False, "retryable": True,
273
- "reasons": ["the ledger was busy — please submit again in a moment"]},
274
- status_code=503)
275
- CACHE.drop()
276
- ids = _sub_ids(board)
277
- scored = {e.get("user") for e in (_board_json(board).get("entries") or [])}
278
- ahead = len([i for i in ids if i not in scored])
279
- return {"accepted": True, "submission_id": sid, "queue_position": ahead,
280
- "note": "scored by a GPU worker against the private key; the board updates within a few minutes."}
 
1
+ # -*- coding: utf-8 -*-
2
+ """Open Quantum Challenge (OQC) — submission intake + live leaderboard.
3
+
4
+ Thin by design, exactly like the Open Discovery Challenge it mirrors. Nothing here scores.
5
+ Entries land in a private dataset ledger (FINAL-Bench/oqc-ledger); a worker on the GPU box
6
+ polls that ledger, scores each entry against a frozen private answer key, and writes the
7
+ result and the rolled-up leaderboard back. One entrant can never block the service, and the
8
+ yardstick stays private while the harness that produces entries is fully public.
9
+
10
+ Layout in the ledger (shared with the worker):
11
+ submissions/<board>/<id>.json written here when an entry is accepted
12
+ results/<board>/<id>.json written by the worker
13
+ leaderboard/<board>.json rolled up by the worker; the page reads one file
14
+
15
+ Boards: qsim (Season 1), qec (Season 2).
16
+ """
17
+ import base64
18
+ import hashlib
19
+ import hmac
20
+ import json
21
+ import os
22
+ import secrets
23
+ import time
24
+ import urllib.parse
25
+ import urllib.request
26
+
27
+ from fastapi import FastAPI, HTTPException, Request
28
+ from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
29
+ from pydantic import BaseModel
30
+
31
+ import gates
32
+ import seasons
33
+ import store
34
+
35
+ HERE = os.path.dirname(os.path.abspath(__file__))
36
+ CACHE = store.Cached(ttl=int(os.environ.get("OQC_CACHE_TTL", "30")))
37
+
38
+ OAUTH_ID = os.environ.get("OAUTH_CLIENT_ID", "")
39
+ OAUTH_SECRET = os.environ.get("OAUTH_CLIENT_SECRET", "")
40
+ OAUTH_ISS = os.environ.get("OPENID_PROVIDER_URL", "https://huggingface.co")
41
+ SPACE_HOST = os.environ.get("SPACE_HOST", "")
42
+ COOKIE = "oqc_session"
43
+ IN_FRAME = bool(SPACE_HOST)
44
+ COOKIE_KW = ({"samesite": "none", "secure": True} if IN_FRAME
45
+ else {"samesite": "lax", "secure": False})
46
+ SESSION_KEY = os.environ.get("OQC_SESSION_KEY") or secrets.token_hex(16)
47
+ DAILY_CAP = int(os.environ.get("OQC_DAILY_CAP", "50"))
48
+ CAP_TZ_OFFSET = 9 * 3600
49
+
50
+ app = FastAPI(title="Open Quantum Challenge")
51
+
52
+
53
+ class Submission(BaseModel):
54
+ board: str # "qsim" or "qec"
55
+ display_name: str
56
+ method: str = ""
57
+ predictions: dict = {}
58
+
59
+
60
+ # ----------------------------------------------------------------- session (HF OAuth, optional)
61
+ def _sign(payload):
62
+ raw = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
63
+ sig = hmac.new(SESSION_KEY.encode(), raw.encode(), hashlib.sha256).hexdigest()[:32]
64
+ return raw + "." + sig
65
+
66
+
67
+ def _unsign(token):
68
+ try:
69
+ raw, sig = (token or "").rsplit(".", 1)
70
+ except ValueError:
71
+ return None
72
+ good = hmac.new(SESSION_KEY.encode(), raw.encode(), hashlib.sha256).hexdigest()[:32]
73
+ if not hmac.compare_digest(sig, good):
74
+ return None
75
+ pad = "=" * (-len(raw) % 4)
76
+ try:
77
+ return json.loads(base64.urlsafe_b64decode(raw + pad))
78
+ except Exception:
79
+ return None
80
+
81
+
82
+ def current_user(request):
83
+ return _unsign(request.cookies.get(COOKIE))
84
+
85
+
86
+ def _redirect_uri(request):
87
+ if SPACE_HOST:
88
+ return "https://%s/auth/callback" % SPACE_HOST
89
+ return str(request.base_url).rstrip("/") + "/auth/callback"
90
+
91
+
92
+ @app.get("/")
93
+ async def index():
94
+ return FileResponse(os.path.join(HERE, "index.html"))
95
+
96
+
97
+ @app.get("/api/me")
98
+ def me(request: Request):
99
+ u = current_user(request)
100
+ return {"signed_in": bool(u), "user": u,
101
+ "oauth_configured": bool(OAUTH_ID and OAUTH_SECRET)}
102
+
103
+
104
+ @app.get("/login")
105
+ def login(request: Request):
106
+ if not (OAUTH_ID and OAUTH_SECRET):
107
+ raise HTTPException(503, "OAuth is not configured (add hf_oauth in README)")
108
+ state = secrets.token_urlsafe(16)
109
+ q = urllib.parse.urlencode({
110
+ "client_id": OAUTH_ID, "redirect_uri": _redirect_uri(request),
111
+ "response_type": "code", "scope": "openid profile", "state": state})
112
+ r = RedirectResponse("%s/oauth/authorize?%s" % (OAUTH_ISS.rstrip("/"), q))
113
+ r.set_cookie("oqc_state", state, max_age=600, httponly=True, **COOKIE_KW)
114
+ return r
115
+
116
+
117
+ @app.get("/auth/callback")
118
+ def callback(request: Request, code: str = "", state: str = ""):
119
+ saved = request.cookies.get("oqc_state")
120
+ if not code or not saved or state != saved:
121
+ raise HTTPException(400, "sign-in failed — please try again (third-party cookies may be blocked)")
122
+ body = urllib.parse.urlencode({
123
+ "client_id": OAUTH_ID, "client_secret": OAUTH_SECRET,
124
+ "grant_type": "authorization_code", "code": code,
125
+ "redirect_uri": _redirect_uri(request)}).encode()
126
+ with urllib.request.urlopen(urllib.request.Request(
127
+ OAUTH_ISS.rstrip("/") + "/oauth/token", data=body,
128
+ headers={"Content-Type": "application/x-www-form-urlencoded"}), timeout=20) as r:
129
+ tok = json.loads(r.read().decode())
130
+ with urllib.request.urlopen(urllib.request.Request(
131
+ OAUTH_ISS.rstrip("/") + "/oauth/userinfo",
132
+ headers={"Authorization": "Bearer " + tok["access_token"]}), timeout=20) as r:
133
+ ui = json.loads(r.read().decode())
134
+ user = {"name": ui.get("preferred_username") or ui.get("name"),
135
+ "picture": ui.get("picture"), "at": int(time.time())}
136
+ resp = RedirectResponse("/")
137
+ resp.set_cookie(COOKIE, _sign(user), max_age=60 * 60 * 24 * 14, httponly=True, **COOKIE_KW)
138
+ resp.delete_cookie("oqc_state")
139
+ return resp
140
+
141
+
142
+ @app.get("/logout")
143
+ def logout():
144
+ r = RedirectResponse("/")
145
+ r.delete_cookie(COOKIE)
146
+ return r
147
+
148
+
149
+ # ----------------------------------------------------------------- seasons / leaderboard
150
+ @app.get("/api/seasons")
151
+ def season_list():
152
+ return {"seasons": seasons.listing(), "default": seasons.DEFAULT}
153
+
154
+
155
+ def _board_json(board):
156
+ return CACHE.get("board:%s" % board,
157
+ lambda: store.read("leaderboard/%s.json" % board, default={}) or {})
158
+
159
+
160
+ def _sub_ids(board):
161
+ return CACHE.get("ids:%s" % board, lambda: store.listdir("submissions/%s" % board))
162
+
163
+
164
+ @app.get("/api/leaderboard")
165
+ def leaderboard(request: Request):
166
+ board = (request.query_params.get("board") or "qsim").lower()
167
+ s = seasons.by_board(board)
168
+ if not s:
169
+ raise HTTPException(404, "unknown board")
170
+ data = _board_json(board)
171
+ entries = data.get("entries") or []
172
+ anchors, ranked = [], []
173
+ for e in entries:
174
+ u = e.get("user", "") or ""
175
+ row = {"participant": u, "method": e.get("method", ""),
176
+ "score": e.get("score"), "verified": bool(e.get("verified"))}
177
+ if u.startswith(("baseline-", "reference-", "anchor-")):
178
+ row["anchor"] = True
179
+ anchors.append(row)
180
+ else:
181
+ ranked.append(row)
182
+ # reference anchors mark the ladder; they do not climb it (ODC-style)
183
+ if board == "qsim":
184
+ anchors.insert(0, {"participant": "exact minimum (floor)", "anchor": True,
185
+ "method": "lowest achievable total energy over all systems (reference)", "score": -36.4448, "verified": True})
186
+ elif board == "qec":
187
+ anchors.append({"participant": "near-optimal MLE bound", "anchor": True,
188
+ "method": "information-theoretic reference (not a submission)", "score": None, "verified": True})
189
+ ranked.sort(key=lambda r: (r["score"] is None, r["score"] if r["score"] is not None else 1e18))
190
+ for i, r in enumerate(ranked, 1):
191
+ r["rank"] = i
192
+ return {"season": seasons.public(s), "anchors": anchors, "entries": ranked,
193
+ "updated": data.get("updated"), "n": len(ranked)}
194
+
195
+
196
+ @app.get("/api/queue")
197
+ def queue(request: Request):
198
+ board = (request.query_params.get("board") or "qsim").lower()
199
+ ids = _sub_ids(board)
200
+ scored = {e.get("user") for e in (_board_json(board).get("entries") or [])}
201
+ return {"submitted": len(ids), "ranked": len(scored)}
202
+
203
+
204
+ @app.get("/api/totals")
205
+ def totals():
206
+ subs = 0
207
+ users = set()
208
+ for n in seasons.SEASONS:
209
+ b = seasons.SEASONS[n]["board"]
210
+ for e in (_board_json(b).get("entries") or []):
211
+ subs += 1
212
+ if e.get("user"):
213
+ users.add(e["user"])
214
+ return {"ranked": subs, "participants": len(users)}
215
+
216
+
217
+ # ----------------------------------------------------------------- submit
218
+ @app.post("/api/submit")
219
+ def submit(sub: Submission, request: Request):
220
+ board = (sub.board or "").lower()
221
+ s = seasons.by_board(board)
222
+ if not s:
223
+ raise HTTPException(400, "unknown board %r" % sub.board)
224
+ if not seasons.accepting(s):
225
+ if s.get("open"):
226
+ raise HTTPException(403, "Season %d is closed (deadline %s)." % (s["number"], s["closes"]))
227
+ raise HTTPException(403, "Season %d is not open yet (opens %s)." % (s["number"], s["opens"]))
228
+ user = current_user(request)
229
+ if (OAUTH_ID and OAUTH_SECRET) and not user:
230
+ raise HTTPException(401, "Hugging Face sign-in required")
231
+ who = (user or {}).get("name") or (sub.display_name or "").strip()[:60]
232
+ if not who:
233
+ raise HTTPException(400, "display name required")
234
+
235
+ v = gates.check(board, sub.predictions)
236
+ if not v["admitted"]:
237
+ return JSONResponse({"accepted": False, "reasons": v["reject"]}, status_code=422)
238
+
239
+ # wrong-track guard: predictions whose keys are clearly for the other board
240
+ keys = list(sub.predictions.keys())
241
+ if keys:
242
+ qec_like = sum(k.startswith("shot_") for k in keys) > len(keys) // 2
243
+ qsim_like = sum(k.startswith("hub_") for k in keys) > len(keys) // 2
244
+ if board == "qsim" and qec_like:
245
+ return JSONResponse({"accepted": False, "reasons": [
246
+ "This looks like a QEC submission (shot_* keys). Please select Season 2 - QEC Decoder."]}, status_code=422)
247
+ if board == "qec" and qsim_like:
248
+ return JSONResponse({"accepted": False, "reasons": [
249
+ "This looks like a QSIM submission (hub_* keys). Please select Season 1 - Quantum Simulation."]}, status_code=422)
250
+
251
+ # daily cap via a small tally file (not a tree walk)
252
+ day = time.strftime("%Y-%m-%d", time.gmtime(time.time() + CAP_TZ_OFFSET))
253
+ quota_path = "quota/%s/%s.json" % (board, day)
254
+ quota = store.read(quota_path, default={}) or {}
255
+ if DAILY_CAP > 0 and int(quota.get(who, 0)) >= DAILY_CAP:
256
+ return JSONResponse({"accepted": False, "daily_cap": DAILY_CAP,
257
+ "reasons": ["daily submission cap reached (%d). Resets at KST midnight." % DAILY_CAP]},
258
+ status_code=429)
259
+
260
+ safe = "".join(c for c in who if c.isalnum() or c in "-_")[:40] or "anon"
261
+ sid = "%s_%s_%s" % (time.strftime("%Y%m%d_%H%M%S"), safe, secrets.token_hex(2))
262
+ rec = {"hf_user": who, "display_name": (sub.display_name or who)[:60],
263
+ "method": (sub.method or "").strip()[:200], "predictions": sub.predictions,
264
+ "board": board, "season": s["number"], "spec": "oqc-v1",
265
+ "n_items": v["n_items"], "submitted_at": int(time.time())}
266
+ quota[who] = int(quota.get(who, 0)) + 1
267
+ try:
268
+ store.write_many([("submissions/%s/%s.json" % (board, sid), rec),
269
+ (quota_path, quota)],
270
+ summary="oqc %s entry %s" % (board, sid))
271
+ except store.Busy:
272
+ return JSONResponse({"accepted": False, "retryable": True,
273
+ "reasons": ["the ledger was busy — please submit again in a moment"]},
274
+ status_code=503)
275
+ CACHE.drop()
276
+ ids = _sub_ids(board)
277
+ scored = {e.get("user") for e in (_board_json(board).get("entries") or [])}
278
+ ahead = len([i for i in ids if i not in scored])
279
+ return {"accepted": True, "submission_id": sid, "queue_position": ahead,
280
+ "note": "scored by a GPU worker against the private key; the board updates within a few minutes."}