Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .claude/skills/legals-licenses/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
name: legals-licenses
description: Use to check that everything a Floe Market feature (the current branch against main, or a named PR or branch) brings in may ship in a paid, closed Steam game, and is credited. Covers npm packages (GPL, LGPL, AGPL and other copyleft), fonts, emoji and icons, sounds, music and recordings (copyrighted songs hiding in them), images, textures and 3D models, real people's likenesses, brands and logos, and Settings → Credits & Copyrights. Triggers on "licence check", "license check", "can we use this", "is this credited", "legals-licenses", and is one of the three checks /legals-update runs.
---

# Licence check

Goes through every new or changed asset and dependency in a feature and says, for each, whether its licence allows
commercial use and redistribution and whether the game credits it.

**It reports and proposes. It doesn't edit the credits, remove assets or change packages unless the owner asks.**
Never commit Valve's Steamworks SDK; if the feature adds any of its files, that's a "can't use".

## 1. The feature

Work out what to read, in this order:
- A PR number: `gh pr view <n> --json state,files,mergeCommit` and `gh pr diff <n>`. For a merged PR, `git show <mergeCommit>`.
- A branch: `git diff main...<branch>`.
- Nothing named: the current branch, `git diff main...HEAD` plus `git diff HEAD` for what isn't committed.

List what it brings in: `package.json` and `package-lock.json` changes, and any added or replaced file under
`public/`, `src/sounds/`, `src/` (imported media), `scripts/fonts/` and `scripts/icons/`. Code the game draws or
synthesises itself (three.js scenes, `src/icons/*.ts`, the music in `src/audio.ts`) is the game's own: check only that
it doesn't copy someone else's (a real tune's melody, a real logo).

## 2. The sources of truth

- **npm packages**: `scripts/licences.ts` and the `licences()` plugin in `vite.config.ts`, from PR #209 (#149). The
build lists the packages it actually bundles (dev tools never ship; the Steam build leaves Firebase out), writes
`dist/licences.txt` and fills the `<!-- licences: listed by the build (scripts/licences.ts) -->` list under
**Open-source licences** in `#creditsCard`. It stops on GPL, LGPL, AGPL or a licence it can't read, unless the package
is in `APPROVED`; `PERMISSIVE` lists what passes. Tests: `test/licences.test.ts`.
- **Fonts**: `public/fonts/*.woff2`, each with its licence beside it (`OFL-*.txt`), built from pinned upstream files by
`scripts/fonts/build.py`; credited under **Fonts** in `#creditsCard`. From PR #210 (#148).
- **Emoji and icons**: every emoji is the game's own drawing (`src/icons.ts`, `src/icons/*.ts`, built into Floe Emoji,
`public/fonts/emoji.woff2`). `test/fonts.test.ts` fails on an emoji with no drawing. An emoji or icon from another set
(Noto, Twemoji, Apple, Font Awesome) is a finding. From PR #210.
- **Recordings**: `src/sounds/*.mp3` (the casino yacht), credited in `#creditsCard` under **The casino yacht's room
sound** and in docs/game.md's **Sound credits**; `public/sounds/*.mp3` (the ring's crowd), credited in
`public/sounds/CREDITS.md` and under **The ring's crowd**.
- **Credits & Copyrights**: `#creditsCard` in `index.html` (Settings → ©). `test/ui.test.ts` ("ends with Credits &
Copyrights…") checks its contents, so a credit change changes the test too.

## 3. The rules

- **Packages.** Find each new package's licence (`node -p "require('./node_modules/<pkg>/package.json').license"`, or
`npm view <pkg>@<version> license`), and its new dependencies' too (`package-lock.json`). Permissive (MIT, ISC, BSD,
Apache-2.0, Zlib, CC0, Unlicense…) is OK and the build credits it. GPL, LGPL, AGPL, MPL, EUPL, SSPL, "non-commercial"
or none is "can't use": Steam needs Valve's agreement for GPL and LGPL, and the game is closed. A dev-only tool is fine
unless what it makes ships under its licence.
- **Fonts.** OFL 1.1 or Apache-2.0, its licence text shipped beside it in `public/fonts`, and a line under **Fonts**.
Not "free for personal use".
- **Sounds and music.** CC0 is OK. CC BY is OK with a credit (title, author, licence link, what was changed). CC BY-NC,
CC BY-ND (the game cuts and loops), "personal use", unknown, YouTube or a ripped track: can't use. Freesound,
BigSoundBank and OpenGameArt pages show the licence; quote the URL.
- **Copyrighted music hiding in a recording** is the known risk: it happened twice, in the ring crowd's murmur and swell
(replaced October 2026, `public/sounds/CREDITS.md`) and in the casino's `slots.mp3`, which had "Blijf Bij Mij" by
Volumia! (replaced in PR #212, #147). Every new or changed recording of people, a room, a crowd, a bar or a casino
gets flagged for the owner's listen and a music-recognition scan (10 s windows, as on #147), unless that's already been
done and posted. Say which file and how long.
- **Images, textures, models.** Anything not drawn by the game's code needs its source and licence. Gemini or other AI
mockups never ship. Store art and screenshots come from the game's own engine.
- **People, brands, songs.** No real person's name or likeness, no real logo or brand, no real song's melody or lyrics
(the rain crooner stays unnamed for this reason).

## 4. Report

One line per thing brought in, each with one of three verdicts:

```
## Licences: no change | N updates
Target: <PR #n / branch / current branch at <sha>>
- OK: <thing> (<licence>, <source URL>), credited under <section> | credited by the build
- Missing credit: <thing> (<licence>, <source URL>). Add to index.html #creditsCard, <section>:
"<li>…</li>" (and docs/game.md / public/sounds/CREDITS.md where the others are)
- Can't use: <thing>: <why>. Replace with: <a named alternative, or what to look for>
- Needs a listen: <file> (<seconds>): a recording of <what>, not yet checked for music
Checked: <what you looked at, one line>
```

A feature that brings in nothing new (code only, drawn or synthesised by the game) is "no change". Match the existing
credit lines' wording: title in quotes, author, linked licence, then what was changed ("trimmed, levelled and made mono").
74 changes: 74 additions & 0 deletions .claude/skills/legals-privacy/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
name: legals-privacy
description: Use to check whether a Floe Market feature (the current branch against main, or a named PR or branch) changes what the game collects, stores, shares or shows about players, and so needs the privacy notice updated. Covers Firestore writes and rules, Google sign-in, scoreboards and the wall of shame, names shown to others, reports and their screenshots, local saves and localStorage, requests to other sites, analytics, and the Steam build's Steam IDs, Cloud and leaderboards. Triggers on "privacy check", "does this need the privacy notice", "legals-privacy", and is one of the three checks /legals-update runs.
---

# Privacy check

Compares what a feature does with players' data against the privacy notice, and lists the exact edits the notice needs,
or says "no change".

**It reports and proposes. It doesn't edit the notice, the short version or any other file unless the owner asks.** The
notice is the owner's text: every change needs their OK (docs/game.md, "Privacy notice").

## 1. The feature

Work out what to read, in this order:
- A PR number: `gh pr view <n> --json state,files,mergeCommit` and `gh pr diff <n>`. For a merged PR, `git show <mergeCommit>`.
- A branch: `git diff main...<branch>`.
- Nothing named: the current branch, `git diff main...HEAD` plus `git diff HEAD` for what isn't committed.

Read the changed files whole where the diff touches data, not just the hunks.

## 2. Where the notice lives

- **`public/privacy.html`**, the full notice, on the site at `/privacy.html`. Its parts: *The short version* (the
`.short` list), *Who I am*, *The web game* (*If you don't sign in*, *If you sign in with Google*, *Reports*, *Links to
other sites*), *The Steam version*, *Why I'm allowed to use it*, *Who else handles it*, *Your rights*, *Children*,
*Changes to this notice*. The `<p class="meta">` line carries **Last changed**. Added by PR #211 (#150).
- **The short version in Settings**: About → 🛡️ Privacy opens `#privacyCard` in `index.html`, with **Read the full notice**
(`#privacyFull`) opening the page in `#privacyDialog` (wired in `src/settings.ts`). Its list must match the notice's
`.short` list word for word; `test/ui.test.ts` ("opens Privacy into the notice's short version…") checks it. From
PR #214 (#213).
- **The report dialog's "What's sent" list**: `#reportWhat` in `index.html`, its kept-for line filled in by
`src/report.ts`. It's a privacy notice too, so it has to agree with the notice's *Reports* part.
- **docs/game.md**: *Privacy notice* (the rules above) and *Reports* (every Firestore collection and the intake's 30 days).

The web build keeps Firebase and Google sign-in. The Steam build stands alone: no Firebase, no Google, no Ko-fi
(`src/flags.ts`, `src/kofi.ts`; epic #142, issues #160, #170, #172). The notice covers both, in their own parts, so say
which version each finding is about.

## 3. What to look for

Search the feature's changed files (and anything new they call) for:

| Touches | Look in | Notice part |
| --- | --- | --- |
| Firestore: a new collection, a new field, a longer keep, a delete | `src/firebase.ts`, `src/cloud.ts`, `firestore.rules` (`saves/`, `scores/`, `shame/`, `reports/`, `limits/`, `config/`); `setDoc`, `updateDoc`, `addDoc`, `writeBatch`, `deleteDoc` | If you sign in with Google; Your rights |
| Sign-in, the account, what's read from Google | `src/firebase.ts`, `src/cloud.ts` | If you sign in with Google |
| A name or anything else other players see | `src/publicName.ts` ("Pat S."), the "Show me on the scoreboards" switch (`saves/{uid}.hidden`), scoreboards in `src/cloud.ts`, `src/wallOfShame.ts`, `src/worstBet.ts` | The short version; If you sign in |
| Reports: what goes, the picture, the save, how long | `src/report.ts`, `intake/` (private repo `ChefControl/floe-market-reports`) | Reports; `#reportWhat` |
| What stays on the device | `localStorage`, `sessionStorage`, IndexedDB, cookies (`src/save.ts`, `src/settings.ts`, `src/flags.ts` and others: `grep -rn localStorage src`) | If you don't sign in; The Steam version |
| A request to another site | `fetch(`, `XMLHttpRequest`, `new WebSocket`, `<script src=`, `<link href=`, `<iframe`, an image or font from another host, `window.open`, a new SDK in `package.json` | Links to other sites; Who else handles it |
| Analytics, crash reports, telemetry, ads | any new service or package doing this | Who else handles it; The short version |
| Steam: Steam ID or name, Steam Cloud, leaderboards, achievements, the report file | Steam build code (#160, #170, #172) | The Steam version |
| Who it's for | anything asking age or aimed at children | Children |

A feature that only changes gameplay, art or sound on the device, and sends or keeps nothing new, is "no change".
Don't flag code that only reads what the notice already covers.

## 4. Report

```
## Privacy: no change | N updates
Target: <PR #n / branch / current branch at <sha>>
- <file:line>: what the feature now keeps or sends (web | Steam | both)
Notice: public/privacy.html, <part>: <is wrong / says nothing>
Proposed: "<the new or changed sentence, in the notice's own voice>"
Also: short version + #privacyCard | #reportWhat | docs/game.md | firestore.rules published by the owner
Checked: <what you searched, one line>
```

Write proposed wording like the notice: first person ("I keep…"), plain words, short sentences, what, why, where, how
long and who sees it. Any update also moves **Last changed** to today's date, and a change to the short version changes
`#privacyCard` the same way. Say when a rules change has to be published to the live project by the owner.
77 changes: 77 additions & 0 deletions .claude/skills/legals-steam/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
name: legals-steam
description: Use to check whether a Floe Market feature (the current branch against main, or a named PR or branch) changes any answer in Steam's content survey or the store page's texts. Covers violence, blood, alcohol, tobacco, drugs, crime, crude humour, language, nudity, fear, gambling and casino games, in-game purchases, players talking to each other or making content, online play, personal data, and the AI-generated content disclosure, plus the store's mature content note and gambling text. Triggers on "Steam check", "content survey check", "does this change the store page", "legals-steam", and is one of the three checks /legals-update runs.
---

# Steam content survey check

Compares what a feature puts in the game with the agreed survey answers and store texts, and lists the answers or texts
to change, or says "no change".

**It reports and proposes. It doesn't edit the prep page, issue #151 or anything in Steamworks unless the owner asks.**
Only public facts go in the report: nothing from inside the Steamworks partner account and no NDA or SDA terms, in the
repo, the issues or the report.

## 1. The feature

Work out what to read, in this order:
- A PR number: `gh pr view <n> --json state,files,mergeCommit` and `gh pr diff <n>`. For a merged PR, `git show <mergeCommit>`.
- A branch: `git diff main...<branch>`.
- Nothing named: the current branch, `git diff main...HEAD` plus `git diff HEAD` for what isn't committed.

Only what ships in the **Steam build** counts. Dev and demo only code, and things behind a flag that's off on Steam
(`src/flags.ts`), don't change an answer, but say so if the feature puts them in reach.

## 2. The answers to compare with

- **The agreed texts**, on issue #151:
https://github.com/ChefControl/floe-market/issues/151#issuecomment-6457345824
(`gh issue view 151 --comments`). Four texts: the **mature content description** (four lines, shown on the store
page), **gambling in full**, the **AI disclosure: pre-generated** and **AI disclosure: live-generated** ("None").
- **The prep page**, with every topic's answer, why and where it is in the code, the Mature Content boxes, every gambling
activity and "things that would change the answers later": https://claude.ai/artifact/KJw9irr5qHtrmr5kRCKFkZ. Read it
with the Artifact tool's `read` action, never WebFetch or curl.
- **Is it submitted yet?** `gh issue view 151 --json state`. While #151 is open, a change means new texts on #151 and
the page before the owner submits. Once it's closed (submitted and approved), answers only change through a ticket to
Steam Support, so the report also drafts that ticket: what changed and how a tester reaches it.

The page's topics: gambling, violence, blood and gore, alcohol, tobacco, drugs, crime themes, crude humour, language,
nudity and sexual content, fear, discrimination, players talk to each other, online play, in-game purchases, shares
location or personal data, and the two AI answers. Australia is left out at launch (simulated gambling is R18+ there).

## 3. What to look for

- **Gambling.** A new game of chance, bet, loan, fix or payout, or a change to how in-game money is earned. It must stay
true that money can't be bought, cashed out or traded. Add it to the page's gambling table, and to "gambling in full"
if it's a new kind.
- **Violence, blood, fear.** New fighting, weapons, shooting, deaths, blood, gore, horror or jump scares (the ring:
`src/fight.ts`, `src/dohyo.ts`, `src/finishers/`; Cooking Hazard: `src/hazard.ts`, `src/hazardPlay.ts`,
`docs/cooking-hazard.md`). Realistic guns or blood would change the store note and maybe the Frequent Violence box.
- **Alcohol, tobacco, drugs.** A new drink, drunk effect, smoking on screen, cigarettes, pills, a drug reference.
- **Crime, crude humour, language, discrimination, nudity.** Grep new lines of text for swearing and slurs; look at new
outfits, jokes and scenes.
- **Players and online.** Any text one player writes that another sees, chat, voice, trading, co-op, shared levels, a
new online board (names and numbers only stay "no").
- **Purchases.** Real-money anything: DLC sold inside the game, microtransactions, loot boxes, ads, a link to pay.
- **Personal data.** Anything the privacy check would flag on the Steam side (sign-in beyond Steam, location).
- **AI.** Content made a new way: AI images, voices or models shipped as files (a Gemini mockup in the build), or any AI
call while the game runs, which turns "live-generated: None" into a yes. Code-drawn art, music and dialogue written
with Claude are already disclosed.
- **Real-world politics, people or brands** aren't survey topics, but note them for the owner (the page's "things that
would change the answers later" has the election-day example).

## 4. Report

```
## Steam: no change | N updates
Target: <PR #n / branch / current branch at <sha>>
#151: open (not submitted) | closed (needs a Support ticket)
- <file:line>: what the feature adds
Answer: <topic>: <was> → <now>
Text: <which of the four texts> → "<proposed new text>"
Page: <section of the prep page to update>
Checked: <topics looked at, one line>
```

Keep the proposed texts in the agreed style: the store note is one short line per item, no bullet marks, rating-board
words ("Use of alcohol", "Cartoon violence", "Simulated gambling"). Plain words, short sentences.
Loading
Loading