AdithyaSK HF Staff commited on
Commit
4de8125
·
verified ·
1 Parent(s): 5e37aca

Rename to Scott Wu Math; add eval results; mobile layout fixes

Browse files
Dockerfile CHANGED
@@ -1,14 +1,14 @@
1
- # Card Arithmetic: OpenEnv server + play page. Pure Python, no GPU.
2
- # docker build -t card-arithmetic . && docker run -p 7860:7860 card-arithmetic
3
  FROM python:3.12-slim
4
 
5
  ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 PORT=7860
6
  RUN useradd -m -u 1000 user
7
  WORKDIR /home/user/app
8
 
9
- COPY --chown=user . ./card_arithmetic
10
- RUN pip install --no-cache-dir ./card_arithmetic
11
 
12
  USER user
13
  EXPOSE 7860
14
- CMD ["sh", "-c", "uvicorn card_arithmetic.server.app:app --host 0.0.0.0 --port ${PORT} --proxy-headers --forwarded-allow-ips='*'"]
 
1
+ # Scott Wu Math: OpenEnv server + play page. Pure Python, no GPU.
2
+ # docker build -t scott-wu-math . && docker run -p 7860:7860 scott-wu-math
3
  FROM python:3.12-slim
4
 
5
  ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 PORT=7860
6
  RUN useradd -m -u 1000 user
7
  WORKDIR /home/user/app
8
 
9
+ COPY --chown=user . ./scott_wu_math
10
+ RUN pip install --no-cache-dir ./scott_wu_math
11
 
12
  USER user
13
  EXPOSE 7860
14
+ CMD ["sh", "-c", "uvicorn scott_wu_math.server.app:app --host 0.0.0.0 --port ${PORT} --proxy-headers --forwarded-allow-ips='*'"]
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Card Arithmetic
3
  emoji: 🃏
4
  colorFrom: green
5
  colorTo: gray
@@ -7,7 +7,7 @@ sdk: docker
7
  app_port: 7860
8
  pinned: false
9
  license: apache-2.0
10
- short_description: Make the year from 8 playing cards with + − × ÷. OpenEnv.
11
  tags:
12
  - openenv
13
  - reinforcement-learning
@@ -15,12 +15,15 @@ tags:
15
  - reasoning
16
  ---
17
 
18
- # Card Arithmetic
19
 
20
  Deal some playing cards, name a number, and make that number from the cards with + − × ÷, using every
21
  card exactly once. People and language models play the same environment: the page at `/` drives the
22
  same OpenEnv session over `/ws` that an agent does.
23
 
 
 
 
24
  ## Where it comes from
25
 
26
  In a clip filmed at a pub, Cognition's CEO Scott Wu explains the game he plays with a deck of cards.
@@ -92,9 +95,9 @@ more than getting it right.
92
  ## Use it
93
 
94
  ```python
95
- from card_arithmetic import CardAction, CardArithmeticEnv
96
 
97
- with CardArithmeticEnv(base_url="https://fineenvs-cardarithmetic.hf.space").sync() as env:
98
  obs = env.reset(split="video", index=1).observation
99
  print(obs.prompt)
100
  result = env.step(CardAction(expression="(((12 - 10) * (6 + 4) * 10 + 8) * 11 - 7) * 3"))
@@ -104,10 +107,10 @@ with CardArithmeticEnv(base_url="https://fineenvs-cardarithmetic.hf.space").sync
104
  Over plain WebSocket (what the play page does): connect to `/ws`, send
105
  `{"type": "reset", "data": {"level": "four-digit"}}`, then `{"type": "step", "data": {"expression": "..."}}`.
106
 
107
- Task discovery follows OpenEnv's Task API: `GET /card_arithmetic/splits`, `POST /card_arithmetic/tasks`
108
  with `{"split": "test"}`, and so on. Task listings leave out the reference solutions.
109
 
110
- For text-only RL (no server), `card_arithmetic.game.reward.grade(expression, card_values, target)` and
111
  `extract_answer(completion)` are the same grader as a plain function, and `game.prompts.messages(cards, target)`
112
  builds the same prompt.
113
 
@@ -125,15 +128,49 @@ non-negative number, the way people play; a second pass allows fractions.
125
 
126
  ```bash
127
  pip install -e .
128
- uvicorn card_arithmetic.server.app:app --port 8012 # play at http://localhost:8012
129
  python scripts/build_tasks.py # rebuild data/tasks (deterministic)
130
  pytest
131
  ```
132
 
133
  ## Evaluations
134
 
135
- `eval/rollout.py` in the [FineEnvs repository](https://github.com/adithya-s-k/FineEnvs/tree/main/12-card-arithmetic)
136
  runs OpenAI, Anthropic and open models on Hugging Face Inference Providers against a running server, in
137
  parallel, one OpenEnv session per episode.
138
 
139
- <!-- results -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Scott Wu Math
3
  emoji: 🃏
4
  colorFrom: green
5
  colorTo: gray
 
7
  app_port: 7860
8
  pinned: false
9
  license: apache-2.0
10
+ short_description: Scott Wu's card game as an OpenEnv RL environment
11
  tags:
12
  - openenv
13
  - reinforcement-learning
 
15
  - reasoning
16
  ---
17
 
18
+ # Scott Wu Math
19
 
20
  Deal some playing cards, name a number, and make that number from the cards with + − × ÷, using every
21
  card exactly once. People and language models play the same environment: the page at `/` drives the
22
  same OpenEnv session over `/ws` that an agent does.
23
 
24
+ Named after the game Scott Wu plays in the clip below, as a fan tribute. It is not affiliated with or
25
+ endorsed by Scott Wu or Cognition.
26
+
27
  ## Where it comes from
28
 
29
  In a clip filmed at a pub, Cognition's CEO Scott Wu explains the game he plays with a deck of cards.
 
95
  ## Use it
96
 
97
  ```python
98
+ from scott_wu_math import CardAction, ScottWuMathEnv
99
 
100
+ with ScottWuMathEnv(base_url="https://fineenvs-scottwumath.hf.space").sync() as env:
101
  obs = env.reset(split="video", index=1).observation
102
  print(obs.prompt)
103
  result = env.step(CardAction(expression="(((12 - 10) * (6 + 4) * 10 + 8) * 11 - 7) * 3"))
 
107
  Over plain WebSocket (what the play page does): connect to `/ws`, send
108
  `{"type": "reset", "data": {"level": "four-digit"}}`, then `{"type": "step", "data": {"expression": "..."}}`.
109
 
110
+ Task discovery follows OpenEnv's Task API: `GET /scott_wu_math/splits`, `POST /scott_wu_math/tasks`
111
  with `{"split": "test"}`, and so on. Task listings leave out the reference solutions.
112
 
113
+ For text-only RL (no server), `scott_wu_math.game.reward.grade(expression, card_values, target)` and
114
  `extract_answer(completion)` are the same grader as a plain function, and `game.prompts.messages(cards, target)`
115
  builds the same prompt.
116
 
 
128
 
129
  ```bash
130
  pip install -e .
131
+ uvicorn scott_wu_math.server.app:app --port 8012 # play at http://localhost:8012
132
  python scripts/build_tasks.py # rebuild data/tasks (deterministic)
133
  pytest
134
  ```
135
 
136
  ## Evaluations
137
 
138
+ `eval/rollout.py` in the [FineEnvs repository](https://github.com/adithya-s-k/FineEnvs/tree/main/12-scott-wu-math)
139
  runs OpenAI, Anthropic and open models on Hugging Face Inference Providers against a running server, in
140
  parallel, one OpenEnv session per episode.
141
 
142
+ ### Results (2026-10-23)
143
+
144
+ Twelve models on the first five `test` deals of each level (20 deals, one sample each) and on the two
145
+ `video` hands (three samples each), in three modes:
146
+
147
+ - **Reasoning**: the model's own reasoning at high effort, up to 32k output tokens.
148
+ - **No reasoning**: reasoning switched off, or as low as the API allows (`*`), up to 32k tokens, so the
149
+ model may still work it out in its visible reply.
150
+ - **At once**: no reasoning, a system line asking for the answer tag alone, and 300 output tokens: the
151
+ mental-arithmetic version of the game.
152
+
153
+ | Model | Reasoning | No reasoning | At once | Video hands: reasoning / none / at once |
154
+ |---|---|---|---|---|
155
+ | GPT-6.1 Sol | 20/20 | 20/20* | 14/20* | 6/6 / 6/6 / 3/6 |
156
+ | Claude Opus 5.5 | 20/20 | 19/20* | 8/20* | 6/6 / 6/6 / 5/6 |
157
+ | GLM-5.3 | 17/20 | 19/20 | 5/20 | 6/6 / 5/6 / 0/6 |
158
+ | Qwen3.8 2.4T | 20/20 | 19/20 | 4/20 | 6/6 / 5/6 / 0/6 |
159
+ | Claude Sonnet 5.5 | 20/20 | 15/20 | 4/20 | 6/6 / 4/6 / 0/6 |
160
+ | Claude Haiku 5.5 | 20/20 | 11/20 | 3/20 | 6/6 / 5/6 / 0/6 |
161
+ | Kimi K2.6 | 19/20 | 20/20 | 2/20 | 6/6 / 6/6 / 0/6 |
162
+ | DeepSeek V4 Pro | 20/20 | 10/20 | 2/20 | 6/6 / 3/6 / 0/6 |
163
+ | gpt-oss-120b | 16/20 | 6/20* | 2/20* | 6/6 / 1/6 / 0/6 |
164
+ | GPT-6 Luna | 20/20 | 2/20 | 2/20 | 5/6 / 0/6 / 0/6 |
165
+ | Qwen3.8 27B | 18/20 | 20/20 | 1/20 | 6/6 / 6/6 / 0/6 |
166
+ | Gemma 4 31B | 19/20 | 18/20 | 1/20 | 5/6 / 5/6 / 0/6 |
167
+
168
+ `*` lowest effort the API allows: GPT-6.1 Sol and gpt-oss-120b at `low`, Claude Opus 5.5 at `low` (its
169
+ thinking cannot be disabled). Open models ran on Hugging Face Inference Providers (Qwen3.8 2.4T and Kimi
170
+ K2.6 on DeepInfra; DeepSeek V4 Pro, GLM-5.3 and Qwen3.8 27B on Novita; gpt-oss-120b on Cerebras; Gemma 4
171
+ 31B on DeepInfra). Gemma and Kimi each lost one or two episodes to provider errors, counted as failures.
172
+
173
+ With reasoning the game is close to solved: every model makes 6,843 on the first try. Answering at once
174
+ separates them: only GPT-6.1 Sol and Claude Opus 5.5, which still reason briefly at their lowest effort,
175
+ get far; most other models start working out loud and run out of room. That gap, and the no-reasoning
176
+ column for the smaller models, is where there is something to train.
__init__.py CHANGED
@@ -1,6 +1,6 @@
1
- """Card Arithmetic: an OpenEnv environment for mental arithmetic with playing cards."""
2
 
3
- from .client import CardArithmeticEnv
4
  from .models import CardAction, CardObservation, CardState
5
 
6
- __all__ = ["CardAction", "CardArithmeticEnv", "CardObservation", "CardState"]
 
1
+ """Scott Wu Math: an OpenEnv environment for mental arithmetic with playing cards."""
2
 
3
+ from .client import ScottWuMathEnv
4
  from .models import CardAction, CardObservation, CardState
5
 
6
+ __all__ = ["CardAction", "ScottWuMathEnv", "CardObservation", "CardState"]
client.py CHANGED
@@ -1,8 +1,8 @@
1
- """Client for a running Card Arithmetic server (local, Docker or a Hugging Face Space).
2
 
3
- from card_arithmetic import CardAction, CardArithmeticEnv
4
 
5
- with CardArithmeticEnv(base_url="http://localhost:8012").sync() as env:
6
  obs = env.reset(level="four-digit", seed=7).observation
7
  print(obs.prompt)
8
  result = env.step(CardAction(expression="..."))
@@ -19,7 +19,7 @@ from openenv.core.env_client import EnvClient
19
  from .models import CardAction, CardObservation, CardState
20
 
21
 
22
- class CardArithmeticEnv(EnvClient[CardAction, CardObservation, CardState]):
23
  def _step_payload(self, action: CardAction) -> Dict[str, Any]:
24
  return action.model_dump(exclude={"metadata"})
25
 
 
1
+ """Client for a running Scott Wu Math server (local, Docker or a Hugging Face Space).
2
 
3
+ from scott_wu_math import CardAction, ScottWuMathEnv
4
 
5
+ with ScottWuMathEnv(base_url="http://localhost:8012").sync() as env:
6
  obs = env.reset(level="four-digit", seed=7).observation
7
  print(obs.prompt)
8
  result = env.step(CardAction(expression="..."))
 
19
  from .models import CardAction, CardObservation, CardState
20
 
21
 
22
+ class ScottWuMathEnv(EnvClient[CardAction, CardObservation, CardState]):
23
  def _step_payload(self, action: CardAction) -> Dict[str, Any]:
24
  return action.model_dump(exclude={"metadata"})
25
 
models.py CHANGED
@@ -1,4 +1,4 @@
1
- """Action, observation and state of the Card Arithmetic environment."""
2
 
3
  from __future__ import annotations
4
 
 
1
+ """Action, observation and state of the Scott Wu Math environment."""
2
 
3
  from __future__ import annotations
4
 
openenv.yaml CHANGED
@@ -1,6 +1,6 @@
1
  spec_version: 1
2
- name: card_arithmetic
3
  type: space
4
  runtime: fastapi
5
- app: card_arithmetic.server.app:app
6
  port: 8000
 
1
  spec_version: 1
2
+ name: scott_wu_math
3
  type: space
4
  runtime: fastapi
5
+ app: scott_wu_math.server.app:app
6
  port: 8000
pyproject.toml CHANGED
@@ -3,7 +3,7 @@ requires = ["setuptools>=61", "wheel"]
3
  build-backend = "setuptools.build_meta"
4
 
5
  [project]
6
- name = "card-arithmetic"
7
  version = "0.1.0"
8
  description = "OpenEnv environment: make a target number from playing cards with + - * /, every card once"
9
  requires-python = ">=3.11"
@@ -19,16 +19,16 @@ dev = ["pytest>=8.0.0", "httpx>=0.27.0", "websockets>=12.0"]
19
  eval = ["openai>=1.50.0", "python-dotenv>=1.0.0"]
20
 
21
  [project.scripts]
22
- card-arithmetic-server = "card_arithmetic.server.app:main"
23
 
24
  [tool.setuptools]
25
  include-package-data = true
26
- packages = ["card_arithmetic", "card_arithmetic.server", "card_arithmetic.game"]
27
- package-dir = { "card_arithmetic" = ".", "card_arithmetic.server" = "server", "card_arithmetic.game" = "game" }
28
 
29
  [tool.setuptools.package-data]
30
- card_arithmetic = ["data/tasks/*.jsonl", "README.md", "openenv.yaml"]
31
- "card_arithmetic.server" = ["web/*"]
32
 
33
  [tool.pytest.ini_options]
34
  testpaths = ["tests"]
 
3
  build-backend = "setuptools.build_meta"
4
 
5
  [project]
6
+ name = "scott-wu-math"
7
  version = "0.1.0"
8
  description = "OpenEnv environment: make a target number from playing cards with + - * /, every card once"
9
  requires-python = ">=3.11"
 
19
  eval = ["openai>=1.50.0", "python-dotenv>=1.0.0"]
20
 
21
  [project.scripts]
22
+ scott-wu-math-server = "scott_wu_math.server.app:main"
23
 
24
  [tool.setuptools]
25
  include-package-data = true
26
+ packages = ["scott_wu_math", "scott_wu_math.server", "scott_wu_math.game"]
27
+ package-dir = { "scott_wu_math" = ".", "scott_wu_math.server" = "server", "scott_wu_math.game" = "game" }
28
 
29
  [tool.setuptools.package-data]
30
+ scott_wu_math = ["data/tasks/*.jsonl", "README.md", "openenv.yaml"]
31
+ "scott_wu_math.server" = ["web/*"]
32
 
33
  [tool.pytest.ini_options]
34
  testpaths = ["tests"]
scripts/build_tasks.py CHANGED
@@ -1,6 +1,6 @@
1
  """Build the fixed task splits in data/tasks/.
2
 
3
- python -m card_arithmetic.scripts.build_tasks # or: python scripts/build_tasks.py from the env dir
4
 
5
  test: 50 deals per level (200), seed 2026
6
  train: 1,000 deals per level (4,000), seed 7, none sharing an id with test
@@ -16,9 +16,9 @@ from pathlib import Path
16
 
17
  HERE = Path(__file__).resolve().parents[1]
18
  sys.path.insert(0, str(HERE.parent))
19
- from card_arithmetic.game.cards import Card # noqa: E402
20
- from card_arithmetic.game.expr import parse, steps, to_text # noqa: E402
21
- from card_arithmetic.game.tasks import LEVELS, make_task # noqa: E402
22
 
23
  OUT = HERE / "data" / "tasks"
24
 
 
1
  """Build the fixed task splits in data/tasks/.
2
 
3
+ python -m scott_wu_math.scripts.build_tasks # or: python scripts/build_tasks.py from the env dir
4
 
5
  test: 50 deals per level (200), seed 2026
6
  train: 1,000 deals per level (4,000), seed 7, none sharing an id with test
 
16
 
17
  HERE = Path(__file__).resolve().parents[1]
18
  sys.path.insert(0, str(HERE.parent))
19
+ from scott_wu_math.game.cards import Card # noqa: E402
20
+ from scott_wu_math.game.expr import parse, steps, to_text # noqa: E402
21
+ from scott_wu_math.game.tasks import LEVELS, make_task # noqa: E402
22
 
23
  OUT = HERE / "data" / "tasks"
24
 
server/app.py CHANGED
@@ -1,6 +1,6 @@
1
  """FastAPI app: the OpenEnv API (/reset, /step, /state, /ws, /schema, task routes) plus the play page at /.
2
 
3
- uvicorn card_arithmetic.server.app:app --port 8012
4
  """
5
 
6
  from __future__ import annotations
@@ -13,7 +13,7 @@ from fastapi.staticfiles import StaticFiles
13
  from openenv.core.env_server.http_server import create_app
14
 
15
  from ..models import CardAction, CardObservation, CardState
16
- from .environment import CardArithmeticEnvironment
17
 
18
  WEB = Path(__file__).resolve().parent / "web"
19
  README = Path(__file__).resolve().parents[1] / "README.md"
@@ -22,10 +22,10 @@ README = Path(__file__).resolve().parents[1] / "README.md"
22
  os.environ["ENABLE_WEB_INTERFACE"] = "false"
23
 
24
  app = create_app(
25
- CardArithmeticEnvironment,
26
  CardAction,
27
  CardObservation,
28
- env_name="card_arithmetic",
29
  max_concurrent_envs=int(os.getenv("MAX_CONCURRENT_ENVS", "256")),
30
  state_cls=CardState,
31
  )
 
1
  """FastAPI app: the OpenEnv API (/reset, /step, /state, /ws, /schema, task routes) plus the play page at /.
2
 
3
+ uvicorn scott_wu_math.server.app:app --port 8012
4
  """
5
 
6
  from __future__ import annotations
 
13
  from openenv.core.env_server.http_server import create_app
14
 
15
  from ..models import CardAction, CardObservation, CardState
16
+ from .environment import ScottWuMathEnvironment
17
 
18
  WEB = Path(__file__).resolve().parent / "web"
19
  README = Path(__file__).resolve().parents[1] / "README.md"
 
22
  os.environ["ENABLE_WEB_INTERFACE"] = "false"
23
 
24
  app = create_app(
25
+ ScottWuMathEnvironment,
26
  CardAction,
27
  CardObservation,
28
+ env_name="scott_wu_math",
29
  max_concurrent_envs=int(os.getenv("MAX_CONCURRENT_ENVS", "256")),
30
  state_cls=CardState,
31
  )
server/environment.py CHANGED
@@ -1,4 +1,4 @@
1
- """Card Arithmetic: deal cards, name a target, make it with + - * / using every card once.
2
 
3
  One episode is one deal and one graded submission. `reset` deals (from a split of the task set,
4
  from a level, or for a custom target or hand); `step` takes the final expression, grades it once,
@@ -36,7 +36,7 @@ def load_split(split: str) -> list[dict]:
36
  return _TASKS[split]
37
 
38
 
39
- class CardArithmeticEnvironment(Environment[CardAction, CardObservation, CardState]):
40
  SUPPORTS_CONCURRENT_SESSIONS = True
41
 
42
  def __init__(self) -> None:
 
1
+ """Scott Wu Math: deal cards, name a target, make it with + - * / using every card once.
2
 
3
  One episode is one deal and one graded submission. `reset` deals (from a split of the task set,
4
  from a level, or for a custom target or hand); `step` takes the final expression, grades it once,
 
36
  return _TASKS[split]
37
 
38
 
39
+ class ScottWuMathEnvironment(Environment[CardAction, CardObservation, CardState]):
40
  SUPPORTS_CONCURRENT_SESSIONS = True
41
 
42
  def __init__(self) -> None:
server/web/app.css CHANGED
@@ -239,7 +239,9 @@ dialog p { font-size: 14px; }
239
  .table { padding: 14px 12px; min-height: 0; }
240
  .target { font-size: 28px; }
241
  .piles { gap: 10px 8px; }
242
- .pile { --cw: clamp(60px, calc((100cqw - 3 * 8px) / 4), 84px); }
 
 
243
  .typed { flex-wrap: wrap; }
244
  .typed label { flex-basis: 100%; }
245
  .steps.compact { padding-left: 22px; }
 
239
  .table { padding: 14px 12px; min-height: 0; }
240
  .target { font-size: 28px; }
241
  .piles { gap: 10px 8px; }
242
+ .pile { --per: min(var(--n, 8), 5); --cw: clamp(54px, calc((100cqw - (var(--per) - 1) * 8px) / var(--per)), 84px); }
243
+ .controls { display: grid; grid-template-columns: 1fr 1fr; }
244
+ .controls .grow { display: none; }
245
  .typed { flex-wrap: wrap; }
246
  .typed label { flex-basis: 100%; }
247
  .steps.compact { padding-left: 22px; }
server/web/app.js CHANGED
@@ -280,7 +280,7 @@
280
  }
281
 
282
  // ---- per-browser record --------------------------------------------------------
283
- const STORE = "card-arithmetic-stats-v1";
284
  function load() { try { return JSON.parse(localStorage.getItem(STORE)) || {}; } catch { return {}; } }
285
  function record(task, solved, secs) {
286
  const all = load(), key = task.task_id.startsWith("video-") ? "video" : task.level;
 
280
  }
281
 
282
  // ---- per-browser record --------------------------------------------------------
283
+ const STORE = "scott-wu-math-stats-v1";
284
  function load() { try { return JSON.parse(localStorage.getItem(STORE)) || {}; } catch { return {}; } }
285
  function record(task, solved, secs) {
286
  const all = load(), key = task.task_id.startsWith("video-") ? "video" : task.level;
server/web/card.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Card Arithmetic · Environment card</title>
7
  <link rel="stylesheet" href="/static/app.css">
8
  <style>
9
  .doc { max-width: 820px; margin: 0 auto; padding: 24px 24px 64px; }
@@ -23,7 +23,7 @@
23
  </head>
24
  <body>
25
  <header class="bar">
26
- <div class="brand"><a href="/" style="text-decoration:none">Card Arithmetic</a></div>
27
  <nav><a href="/">Play</a><a href="/static/card.html" aria-current="page">Environment card</a><a href="/docs">API</a></nav>
28
  </header>
29
  <article class="doc" id="doc">Loading…</article>
 
3
  <head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Scott Wu Math · Environment card</title>
7
  <link rel="stylesheet" href="/static/app.css">
8
  <style>
9
  .doc { max-width: 820px; margin: 0 auto; padding: 24px 24px 64px; }
 
23
  </head>
24
  <body>
25
  <header class="bar">
26
+ <div class="brand"><a href="/" style="text-decoration:none">Scott Wu Math</a></div>
27
  <nav><a href="/">Play</a><a href="/static/card.html" aria-current="page">Environment card</a><a href="/docs">API</a></nav>
28
  </header>
29
  <article class="doc" id="doc">Loading…</article>
server/web/index.html CHANGED
@@ -3,14 +3,14 @@
3
  <head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Card Arithmetic</title>
7
  <meta name="description" content="Make the target from playing cards with + − × ÷, every card once. An OpenEnv environment people and language models play the same way.">
8
  <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='5' y='2' width='22' height='28' rx='3' fill='%23fff' stroke='%23222' stroke-width='2'/%3E%3Ctext x='16' y='22' font-size='14' text-anchor='middle' fill='%23c0392b'%3E%E2%99%A5%3C/text%3E%3C/svg%3E">
9
  <link rel="stylesheet" href="/static/app.css">
10
  </head>
11
  <body>
12
  <header class="bar">
13
- <div class="brand">Card Arithmetic</div>
14
  <nav>
15
  <a href="#rules" id="rules-link">Rules</a>
16
  <a href="/static/card.html">Environment card</a>
 
3
  <head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Scott Wu Math</title>
7
  <meta name="description" content="Make the target from playing cards with + − × ÷, every card once. An OpenEnv environment people and language models play the same way.">
8
  <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='5' y='2' width='22' height='28' rx='3' fill='%23fff' stroke='%23222' stroke-width='2'/%3E%3Ctext x='16' y='22' font-size='14' text-anchor='middle' fill='%23c0392b'%3E%E2%99%A5%3C/text%3E%3C/svg%3E">
9
  <link rel="stylesheet" href="/static/app.css">
10
  </head>
11
  <body>
12
  <header class="bar">
13
+ <div class="brand">Scott Wu Math</div>
14
  <nav>
15
  <a href="#rules" id="rules-link">Rules</a>
16
  <a href="/static/card.html">Environment card</a>