__pycache__/
*.pyc
.pytest_cache/
.coverage
dist/

# Virtual environments and tool settings. Until now this machine's global settings
# were blocking them, and once public, somebody cloning has no such protection —
# written here, it applies to everybody.
.venv/
.claude/
.mcp.json

# Only typescript, but its whole dependency tree comes in with it. **package-lock.json
# is committed** — what came onto this machine has to stay in the repository.
node_modules/
borch-ts/dist/

# The golden is generated — stage 1 (native plus torch) freezes it and stage 2 reads it.
tests/golden.npz
#
# **`tests/golden.json` is not here. Deliberately.**
# The npz is made by our tools and read by our tools. The JSON is the opposite — it is
# made **for somebody who cannot run our tools to read**, so ignoring it removes its
# reason to exist: if the receiving side has to install Python and real torch, that is
# not language-neutral. It is 290KB, and when it goes stale the manifest hash diverges
# (tests/test_export_json.py catches that).

# One-off scripts that ask real torch about a convention.
#
# **Discarding them is right.** The answer gets frozen into the golden and the reason
# stays in a comment, so there is no cause to keep the asking procedure in the
# repository too — kept, it adds one more file for the next person to ask "why is this
# here" about. Writing it again is cheap if it has to be asked again.
tests/probe_*.py
tests/browser/probe_*.py
tests/fix_*.py

# The CIFAR-10 originals. The browser cannot fetch them directly because of CORS, so
# they are fetched locally and served.
cifar-10-*
cifar-batch*.bin
cifar-fake.bin

# Fetched from outside. **Only Pyodide is kept in the repository** — the `!` below is that.
#
# For a long time it was "keep the hash only". The basis for that decision was size,
# and measured, the six files are 8.4MB in the pack (26MB in the working tree). In this
# repository's history `tests/golden.json` alone takes 23.9MB and `.git` is 127MB — it
# was hard to say there is "no reason to accumulate" 8.4MB that goes in once and does
# not change. The price of this decision is the same amount again per version bump, and
# there is no plan to move off 0.27.2.
#
# What it buys: cloning makes Python mode simply work (a broken symlink bit us once),
# deployment and tests have no network dependency, and a commit fully determines the
# bytes that are served.
#
# The two TF.js files stay excluded here — hand-written WGSL replaced them, so they are
# no longer fetched.
vendor/*
!vendor/pyodide/

# The data subset the tutorials use (`site/assets/data/`) **is in the repository.**
#
# This used to say "site/fetch_data.py makes it — the same arrangement as vendor/", and
# that basis disappeared when vendor/ moved. Measured, the price was also large: one
# deployment took 34 minutes 20 seconds and **33 minutes 56 seconds** of it went to
# rebuilding this — fetching 170MB of originals from Toronto and processing 60,000
# images to produce **1.1MB**. There is no randomness, so the same input gives the same
# bytes (confirmed by regenerating), and CIFAR-10 does not change.
#
# The original batches (`cifar-batch*.bin`, 29MB) stay excluded — this subset exists
# precisely because those are large.
