Skip to content

Commit 9d6f634

Browse files
Stream-JSON and a visual loop bench.
Eval prints one object per line. Stills must stay night stock. Docs rewritten so a first patch is obvious.
1 parent d1c0827 commit 9d6f634

14 files changed

Lines changed: 508 additions & 108 deletions

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ What beat does this change? (`home` `rip` `room` `foil` `lock` `card` `tray` `sa
55
## Proof
66

77
- [ ] `npm run test:pin` is green
8+
- [ ] `npm run test:vl` is green
89
- [ ] Live pack is not always Thunder 51
910
- [ ] `public/__grok/` untouched
1011
- [ ] NOTICE read if names / plates / crests moved

.github/workflows/pin.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77

88
jobs:
99
pin:
10-
name: House pin + walk
10+
name: House pin + visual loop
1111
runs-on: ubuntu-latest
1212
timeout-minutes: 10
1313
steps:
@@ -18,3 +18,4 @@ jobs:
1818
cache: npm
1919
- run: npm ci
2020
- run: npm run test:pin
21+
- run: npm run test:vl

CONTRIBUTING.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ Read [NOTICE](NOTICE) first if your change touches names, crests, or plates.
1717
| Copy the loop into another sport | [FORK.md](FORK.md) |
1818
| Fix copy, stills, or how-to | `HOW-TO-PLAY.md`, `docs/stills` |
1919
| Touch the mixer / house pin | Stop. See “Do not” below. |
20-
| Change foil, tray, or the card | One of those rooms. [docs/STUDIO.md](docs/STUDIO.md) |
20+
| Change foil, tray, or the card | One room. [docs/STUDIO.md](docs/STUDIO.md) |
21+
| Eval pipe / Stream-JSON | [docs/STREAM-JSON.md](docs/STREAM-JSON.md) |
22+
| Visual loop stills | [docs/BENCHMARKS.md](docs/BENCHMARKS.md) |
2123
| Add a test | [docs/TESTING.md](docs/TESTING.md) |
2224

2325
## Run it
@@ -26,6 +28,13 @@ Read [NOTICE](NOTICE) first if your change touches names, crests, or plates.
2628
npm install
2729
npm run dev
2830
npm run test:pin
31+
npm run test:vl
32+
```
33+
34+
Studio already running:
35+
36+
```bash
37+
npm run test:demo
2938
```
3039

3140
Node 22. Auth off. Database unused.
@@ -36,11 +45,13 @@ House pin must stay green:
3645
v1.OKC.positionless.even.51.chet~dort~hartenstein~jalenw~sga
3746
```
3847

48+
`test:demo` prints [Stream-JSON](docs/STREAM-JSON.md) (one object per line). `test:vl` fails if the card stills go cream.
49+
3950
## Pull requests
4051

4152
- One room per PR. Mixer + UI + a new mode is three PRs.
4253
- Title the loop, not the ticket. “Tray copies the walk” beats “fix share.”
43-
- Run `npm run test:pin`.
54+
- Run `npm run test:pin` and `npm run test:vl`.
4455
- If the face of the loop changed, run `npm run capture` and commit stills + tape.
4556
- Leave `public/__grok/` alone.
4657
- Do not add a shop, accounts, or a tracker that leaves the device.

README.md

Lines changed: 32 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22

33
**Rip a pack. Five names. Eighty-two nights. Send the card.**
44

5-
A browser basketball pack. Not a shop. Not a sportsbook. Not the NBA.
5+
A browser basketball pack you can fork. Not a shop. Not a sportsbook. Not the NBA.
66

7-
[Play](HOW-TO-PLAY.md) · [Fork](FORK.md) · [Contribute](CONTRIBUTING.md) · [MIT](LICENSE)
7+
[Play](HOW-TO-PLAY.md) · [Install](#install) · [Contribute](CONTRIBUTING.md) · [MIT](LICENSE)
88

9-
Private repo (log in as DigitalCurrensy):
10-
**https://github.com/DigitalCurrensy/first-bucket-studios**
11-
12-
Not the older `first-bucket-studio` (no *s*).
9+
Private: [github.com/DigitalCurrensy/first-bucket-studios](https://github.com/DigitalCurrensy/first-bucket-studios)
10+
(log in as DigitalCurrensy — not the older `first-bucket-studio`, no *s*)
1311

1412
---
1513

16-
## How to play
14+
## Play
1715

18-
About ninety seconds. Full sheet: [HOW-TO-PLAY.md](HOW-TO-PLAY.md).
16+
Ninety seconds. [HOW-TO-PLAY.md](HOW-TO-PLAY.md) is the sheet.
1917

2018
**1. Rip the pack.** A franchise, an era, and a luck lane land. No two pulls match.
2119

@@ -33,15 +31,15 @@ About ninety seconds. Full sheet: [HOW-TO-PLAY.md](HOW-TO-PLAY.md).
3331

3432
![Send](docs/stills/04-tray.jpg)
3533

36-
Tape of one pull: [docs/tape/demo.mp4](docs/tape/demo.mp4)
34+
Tape: [docs/tape/demo.mp4](docs/tape/demo.mp4)
3735

3836
| You click | What it does |
3937
| --- | --- |
40-
| **Rip the pack** | Deals a new room. New ten. |
41-
| **Lock five** | Walks 82 nights from those names. |
38+
| **Rip the pack** | New room. New ten. |
39+
| **Lock five** | 82 nights from those names. |
4240
| **Send the card** | Opens the tray. |
43-
| **Save the card** | Downloads `first-bucket-{team}-{wins}.png`. |
44-
| **Copy the walk** | Copies `/walk/v1.…` — paste it anywhere. |
41+
| **Save the card** | `first-bucket-{team}-{wins}.png` |
42+
| **Copy the walk** | `/walk/v1.…` — paste it anywhere. |
4543
| **Open the walk** | Same five, same nights, forever. |
4644

4745
There is no “copy image.” The file is the card. The URL is the walk.
@@ -68,77 +66,55 @@ npm run dev
6866
Then rip. If Save is swallowed, you are in a nested preview — open a top-level tab.
6967

7068
```bash
71-
npm run test:pin
69+
npm run test:pin # mixer lock + walk + stream-json
70+
npm run test:vl # stills + tape are night stock
71+
npm run test:demo # live pack, studio already running
7272
```
7373

7474
The house pin must stay green. That is the lock test.
7575

76-
More: [docs/STUDIO.md](docs/STUDIO.md) (update flow, themes).
77-
7876
---
7977

8078
## Documentation
8179

8280
| Doc | What it is |
8381
| --- | --- |
8482
| [HOW-TO-PLAY.md](HOW-TO-PLAY.md) | The ninety seconds |
85-
| [docs/TESTING.md](docs/TESTING.md) | E2E layers: pin, funnel, demo eval, stills |
86-
| [docs/ANALYTICS.md](docs/ANALYTICS.md) | Booth funnel. Local. No pixel. |
87-
| [docs/WALK.md](docs/WALK.md) | Walk certificate (the wire format) |
88-
| [docs/STUDIO.md](docs/STUDIO.md) | Specialists, themes, updates, performance, Action |
83+
| [docs/TESTING.md](docs/TESTING.md) | E2E layers |
84+
| [docs/STREAM-JSON.md](docs/STREAM-JSON.md) | NDJSON eval pipe |
85+
| [docs/BENCHMARKS.md](docs/BENCHMARKS.md) | Pin + visual loop (not VLMEvalKit) |
86+
| [docs/ANALYTICS.md](docs/ANALYTICS.md) | Booth funnel. Local. |
87+
| [docs/WALK.md](docs/WALK.md) | Walk certificate |
88+
| [docs/STUDIO.md](docs/STUDIO.md) | Rooms, themes, updates, performance |
8989
| [FORK.md](FORK.md) | Copy the loop. Swap the sport. |
9090
| [NOTICE](NOTICE) | MIT is the code, not the names |
9191
| [SUPPORT.md](SUPPORT.md) | How to ask |
9292
| [SECURITY.md](SECURITY.md) | How to report a hole |
9393
| [CONTRIBUTING.md](CONTRIBUTING.md) | How to land a patch |
9494

95-
### Install
96-
97-
See above. Node 22. `npm install` · `npm run dev`.
98-
99-
### Update flow
100-
101-
`git pull``npm install` if the lockfile moved → `npm run test:pin`. Walk `v1` is frozen. Mixer does not move. Details in [docs/STUDIO.md](docs/STUDIO.md#update-flow).
102-
103-
### Themes
104-
105-
Night arena (default) or light studio. Rail toggle. Stored on this device. Reduced motion skips the ticker.
106-
107-
### Walk certificate
108-
109-
`/walk/v1.{ABBR}.{era}.{luck}.{wins}.{five-ids}` is the save file. Nights recompute. [docs/WALK.md](docs/WALK.md).
110-
111-
### Specialists
112-
113-
Live pack, house pack, walk, foil, lithograph, tray, plates. One room per PR. [docs/STUDIO.md](docs/STUDIO.md#specialists).
114-
115-
### GitHub Action
116-
117-
[`.github/workflows/pin.yml`](.github/workflows/pin.yml) runs `npm run test:pin` on every push and pull request. Demo eval stays local (`npm run test:demo`) because it needs a running studio.
118-
119-
### Benchmarks
95+
**Update flow.** `git pull``npm install` if the lockfile moved → `npm run test:pin`. Walk `v1` is frozen. Mixer does not move.
12096

121-
The pin is the benchmark: house walk is 51–31, same five, same nights. Live packs must not collapse to that id. Funnel target: card in under 90s.
97+
**Themes.** Night arena (default) or light studio. Rail toggle. Reduced motion skips the ticker.
12298

123-
### Performance
99+
**Stream-JSON.** One object per line on stdout from `npm run test:demo`. Beats, then a walk, then a result. Same *pipe* as Claude’s stream-json. Different *types*. [docs/STREAM-JSON.md](docs/STREAM-JSON.md).
124100

125-
Foil is one WebGL layer with CSS fallback. Share is 2D canvas, not the foil. Ticker is 110ms/night, skipped on reduced motion. [docs/STUDIO.md](docs/STUDIO.md#performance).
101+
**Specialists.** Live pack, house pack, walk, foil, lithograph, tray, plates. One room per PR.
126102

127-
### Demo evals
103+
**GitHub Action.** [`.github/workflows/pin.yml`](.github/workflows/pin.yml) runs `test:pin` and `test:vl` on every push.
128104

129-
`npm run test:demo` — Playwright rips a live pack, asserts it is not the house pin, and opens the tray. [docs/TESTING.md](docs/TESTING.md).
105+
**Benchmarks.** Pin = Thunder 51–31. Visual loop = stills stay night stock (Y < 80). We do not run MMBench. [docs/BENCHMARKS.md](docs/BENCHMARKS.md).
130106

131107
---
132108

133109
## Community
134110

135-
Talk happens in **GitHub Discussions**. There is no Discord.
111+
Talk happens in **[GitHub Discussions](https://github.com/DigitalCurrensy/first-bucket-studios/discussions)**. There is no Discord.
136112

137113
| Category | Use it for |
138114
| --- | --- |
139-
| **Q&A** | Setup help, “how do I”, Save / Copy / Open |
140-
| **Ideas** | Feature proposals and design before any PR |
141-
| **Show and tell** | Forks, other sports, stills, workflows |
115+
| **Q&A** | Setup, Save / Copy / Open, “how do I” |
116+
| **Ideas** | Proposals before any PR |
117+
| **Show and tell** | Forks, other sports, stills |
142118
| **Announcements** | Releases from the maintainers |
143119

144120
For a good Q&A answer fast, include the walk URL if you have one, your OS and browser, how you ran it, and whether Save was in a top-level tab or a nested preview. See [SUPPORT.md](SUPPORT.md). Bugs belong in issues. Security reports follow [SECURITY.md](SECURITY.md), never a public thread.
@@ -147,9 +123,9 @@ For a good Q&A answer fast, include the walk URL if you have one, your OS and br
147123

148124
## Contributing
149125

150-
Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md), run `npm run test:pin`, and open a focused pull request.
126+
You are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md), run `npm run test:pin`, open a focused pull request.
151127

152-
Security reports should follow [SECURITY.md](SECURITY.md).
128+
Do not retune the mixer. Do not paste league marks. Leave `public/__grok/` in place.
153129

154130
---
155131

docs/BENCHMARKS.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Benchmarks
2+
3+
Two benches. Neither is a leaderboard.
4+
5+
## 1. Pin (mixer)
6+
7+
House Thunder 51–31, same five, same nights.
8+
9+
```
10+
v1.OKC.positionless.even.51.chet~dort~hartenstein~jalenw~sga
11+
```
12+
13+
`npm run test:pin` — GitHub Action on every push. If this goes red you retuned the mixer. Revert.
14+
15+
Live packs must **not** collapse to that id. That assert lives in `npm run test:demo`.
16+
17+
## 2. Visual loop (VL)
18+
19+
Not [VLMEvalKit](https://github.com/open-compass/VLMEvalKit). Not MMBench, MMMU, or VQA. Those score **vision-language models** answering questions about images.
20+
21+
This studio is a **game**. VL here means **visual loop**: home, foil, card, tray, tape.
22+
23+
```bash
24+
npm run test:vl
25+
```
26+
27+
| Check | Pass |
28+
| --- | --- |
29+
| Four stills exist | JPEG, over a size floor |
30+
| Tape exists | `docs/tape/demo.mp4`, `ftyp` |
31+
| Night stock | Mean luminance Y < 80 (ffmpeg, when present) |
32+
33+
Cream paper on the card fails. A 1×1 downscale of `03-result.jpg` should sit around Y 20, not Y 200.
34+
35+
Stills are in `docs/stills`. Recapture with `npm run capture` if the face of the loop changed.
36+
37+
## What we will not add
38+
39+
- VLMEvalKit / `run.py` / 80 multimodal datasets
40+
- Pixel-diff of live packs (every pull is a new franchise)
41+
- Off-device scoring
42+
43+
Funnel budgets (card in under 90s, a send after the tray) live in [ANALYTICS.md](ANALYTICS.md) and [TESTING.md](TESTING.md).

docs/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Docs
2+
3+
Start at the [root README](../README.md). Then pick a room.
4+
5+
| File | Room |
6+
| --- | --- |
7+
| [TESTING.md](TESTING.md) | E2E layers |
8+
| [STREAM-JSON.md](STREAM-JSON.md) | Eval pipe |
9+
| [BENCHMARKS.md](BENCHMARKS.md) | Pin + visual loop |
10+
| [ANALYTICS.md](ANALYTICS.md) | Booth funnel |
11+
| [WALK.md](WALK.md) | Certificate |
12+
| [STUDIO.md](STUDIO.md) | Specialists, themes, updates |
13+
| [stills/](stills/) | 01 home · 02 foil · 03 card · 04 tray |
14+
| [tape/demo.mp4](tape/demo.mp4) | One pull |

docs/STREAM-JSON.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Stream-JSON
2+
3+
One JSON object per line on stdout. Same *shape of pipe* as Claude Code’s `--output-format stream-json`. Different *types*. This is the ninety-second loop, not an MCP agent.
4+
5+
NDJSON. Flush every line. No pretty indent. `jq` can eat it.
6+
7+
## Why a stream
8+
9+
`npm run test:demo` used to dump one blob at the end. A booth, a CI job, or a wrapper wants beats *as they land*.
10+
11+
```bash
12+
npm run test:demo | jq -c 'select(.type=="result")'
13+
```
14+
15+
## Lines
16+
17+
| `type` | When | Fields |
18+
| --- | --- | --- |
19+
| `system` | Start | `subtype: "init"`, `studio: "first-bucket"`, `version: 1`, `at` |
20+
| `beat` | First hit of a funnel beat | `beat`, `ms`, optional `note` |
21+
| `walk` | Certificate known | `id`, `live` (false = house pin) |
22+
| `result` | End | `ok`, `ms`, `walk`, `funnel`, optional `error` |
23+
24+
Beats: `home` `rip` `room` `foil` `lock` `card` `tray` `save` `copy` `open`.
25+
26+
Example:
27+
28+
```
29+
{"type":"system","subtype":"init","version":1,"studio":"first-bucket","at":1788300094231}
30+
{"type":"beat","beat":"home","ms":0}
31+
{"type":"beat","beat":"rip","ms":400}
32+
{"type":"beat","beat":"card","ms":7000,"note":"v1.LAC.04-defense.even.17.…"}
33+
{"type":"walk","id":"v1.LAC.04-defense.even.17.…","live":true}
34+
{"type":"result","ok":true,"ms":8200,"walk":"/walk/v1.LAC.…","funnel":{"sent":true}}
35+
```
36+
37+
`live: false` means the eval collapsed to the house Thunder pin. That is a fail.
38+
39+
## Not Claude’s protocol
40+
41+
| Claude stream-json | This studio |
42+
| --- | --- |
43+
| `assistant` / `user` / `stream` deltas | `beat` |
44+
| `control` + MCP tools | none |
45+
| `result.total_cost_usd` | `result.ms` + `funnel` |
46+
| `--verbose` required | always on |
47+
| Bidirectional stdin | stdout only |
48+
49+
We borrowed the **pipe**, not the **agent**. Encode / decode: [`src/lib/stream-json.ts`](../src/lib/stream-json.ts).
50+
51+
Foreign lines (`assistant`, another `studio`) fail closed.
52+
53+
## Walk certificate
54+
55+
The walk **id** inside a `walk` line is still:
56+
57+
```
58+
v1.{ABBR}.{era}.{luck}.{wins}.{id~id~id~id~id}
59+
```
60+
61+
That URL is the save file. Stream-JSON is how the *eval* talks. See [WALK.md](WALK.md).

docs/STUDIO.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Studio rooms
22

3-
Specialists, themes, updates, performance. Touch one room at a time.
4-
53
## Specialists
64

75
| Room | File | Job |
86
| --- | --- | --- |
97
| **Live pack** | `src/lib/nba.ts` `dealFrom` | Fisher–Yates on mulberry32. New franchise every pull. |
108
| **House pack** | `src/lib/house-pack.ts` | A table. Thunder 51–31. Never shuffle this. |
119
| **Walk** | `src/lib/walk.ts` | Certificate encode / decode. |
10+
| **Stream-JSON** | `src/lib/stream-json.ts` | NDJSON eval pipe. Beats, walk, result. |
1211
| **Season** | `src/lib/sim.ts` | 82 nights from five ids. |
1312
| **Foil** | `src/components/foil-gl.tsx` | Small WebGL layer on the pack. CSS fallback. |
1413
| **Lithograph** | `src/lib/share-card.ts` | 2D canvas PNG. Not WebGL. Night stock. |
@@ -54,8 +53,8 @@ If the booth feels slow, look at click tax (foil should auto-turn the ten) and t
5453

5554
## GitHub Action
5655

57-
[`.github/workflows/pin.yml`](../.github/workflows/pin.yml) runs `npm run test:pin` on push and pull request. That is the mixer lock. Demo eval stays local because it needs a running studio.
56+
[`.github/workflows/pin.yml`](../.github/workflows/pin.yml) runs `npm run test:pin` and `npm run test:vl` on push and pull request. Demo eval stays local because it needs a running studio.
5857

5958
## Demo evals
6059

61-
See [TESTING.md](TESTING.md). The eval that matters: live pack ≠ house pin, tray opens, card beat fires.
60+
See [TESTING.md](TESTING.md). The eval that matters: live pack ≠ house pin, tray opens, card beat fires, Stream-JSON `result.ok` is true.

0 commit comments

Comments
 (0)