# Puzzle Game Template — Agent Instructions

You are helping a human collaborator build **one playable level** of a
mobile puzzle or casual web game. This document is the canonical
instruction set for the whole project. Re-read it whenever you're unsure.

---

## 1. Who your collaborator is

**Assume they are NOT a software engineer.** They may:

- Not know what npm, Node.js, the terminal, or a dev server is.
- Not have any developer tools installed on their computer.
- Be on macOS, Windows, or Linux.
- Not have a GitHub account, an editor configured, or any prior code.

You are not just a code generator — you are also their patient
**tech-support** for the duration of this project. Translate jargon. Run
commands for them. Summarize output. **Never paste raw terminal logs as
your reply** — interpret what happened in one or two sentences.

When something goes wrong or confuses the collaborator, **also log it in
`ISSUES.md`** (see section 6) so the skill author can polish the
template later.

---

## 2. The mission (in one sentence)

Co-design a mobile puzzle/casual game with the collaborator, ship **one
playable hand-crafted level** running in their browser at mobile portrait
aspect, and at the end hand off a clean `Level` data format that another
team can use to generate hundreds more levels.

---

## 3. The only hard constraint

You can be creative about everything — mechanics, art, UI, animations,
audio, framework idioms — **except this one thing**:

> You must abstract every level into a single TypeScript interface
> called `Level` exported from `src/core/level.ts`, and your finished
> demo must load its starting state from a JSON file at
> `src/levels/demo.json` that conforms to that interface.

The `Level` interface must satisfy all of:

1. **JSON-serializable.** No functions, classes, `Map`, `Set`,
   `undefined`, circular references. Plain numbers / strings / booleans /
   arrays / nested plain objects only.
2. **Complete.** Given only the JSON, the game must be able to
   reconstruct the initial playable state deterministically — no hidden
   state, no `Math.random()` during boot.
3. **Self-describing.** Every field's purpose is documented in
   `HANDOVER.md` in plain English.
4. **Stable.** Once you've shipped the demo, don't keep renaming or
   restructuring fields — downstream tooling will depend on the shape.

Everything else is your call.

---

## 4. Form factor — this is a mobile game

The starter is wired for a **portrait mobile viewport** at logical
`360 × 640` (9:16). On desktop browsers the canvas letterboxes (black
bars) and stays centered; on mobile it fills the screen.

**Do not change the aspect ratio.** Designing for landscape, ultrawide,
or arbitrary resize will break the downstream level-design pipeline.
Visual rules:

- All gameplay must fit inside the 360×640 logical area. Use
  `app.screen.width` / `app.screen.height` for layout, not `window.*`.
- Tap targets should be **at least 44×44 logical px** (thumb-friendly).
- Text should remain readable on a real phone screen — base font size
  `≥ 16px`, important text `≥ 24px`.
- Don't assume hover. Touch-only input. Click events fire on mobile too,
  so use `pointerdown` / `pointertap` in Pixi.

If you genuinely need a different aspect ratio (very rare — basically
never), discuss it with the collaborator, log it in `ISSUES.md`, and
update both `index.html` and `src/main.ts` accordingly.

---

## 5. Workflow

The project moves through five phases. **Maintain `PROGRESS.md` as you
go** — every time you finish a phase or make a notable decision, update
it. The collaborator should be able to glance at that file and know
where things stand.

### Phase 0 — Get the project running on the collaborator's machine

You're likely reading this SKILL.md from a raw URL with no local files
yet. Your first job is to get the project on disk and the dev server
showing a placeholder in the browser. The collaborator should see
something running before any design conversation happens.

#### 0a. Download the project

You're reading this `SKILL.md` from a URL of the form
`https://<host>/SKILL.md`. The full project is hosted on the **same
host** at `https://<host>/template.tar.gz` (and `.zip`). Use the host
that the URL you fetched lives on — don't substitute another one.

Pick a sensible folder on the collaborator's machine (e.g. their
Desktop or Documents), then download and unpack:

```sh
mkdir -p my-game && cd my-game
curl -fL https://<host>/template.tar.gz | tar -xz --strip-components=1
```

If `tar` isn't available (rare on macOS/Linux; older Windows), use the
zip instead:

```sh
# macOS / Linux
mkdir -p my-game && cd my-game
curl -fLO https://<host>/template.zip && unzip -q template.zip && rm template.zip

# Windows PowerShell
mkdir my-game; cd my-game
Invoke-WebRequest https://<host>/template.zip -OutFile t.zip
Expand-Archive t.zip .; Remove-Item t.zip
```

From here on, all paths in this document are relative to `my-game/` —
that's your working directory. You should see `package.json`,
`index.html`, `src/`, `example/`, and a local copy of `SKILL.md`. If
not, re-check the URL and try again.

> Side note for the agent: this skill is **not** distributed via a
> public git repo, so don't try `git clone` from a guessed GitHub URL.
> If the collaborator's `SKILL.md` URL stops working, ask them where
> they got it; only the skill's owner knows the current host.

#### 0b. Install Node.js + npm

1. **Check what's already installed.** Run `node --version` and
   `npm --version`. If both work and Node is ≥ 20, skip to 0c.
2. **If Node is missing**, install it.
   - **macOS:** `brew install node`.
   - **Windows:** `winget install OpenJS.NodeJS.LTS`, or guide them
     through the LTS installer from https://nodejs.org.
   - **Linux:** use the system package manager (`apt`, `dnf`,
     `pacman`), or https://nodejs.org.
   - In every case, briefly tell the collaborator what you just
     installed and why. Don't lecture.

#### 0c. Install dependencies + start the dev server

1. **`npm install`** — this can take a minute. Tell the collaborator
   it's downloading the libraries we use (Pixi.js for rendering, Vite
   for the dev server). Don't paste the npm log; summarize.
2. **`npm run dev`** — Vite prints a URL like `http://localhost:5173/`.
3. **Open that URL in their default browser** for them — don't ask
   them to copy/paste it:
   - **macOS:** `open http://localhost:5173/`
   - **Windows:** `start http://localhost:5173/`
   - **Linux:** `xdg-open http://localhost:5173/`
4. They should see a black portrait-shaped panel with the level title
   ("My first level") and a placeholder hint. Confirm they see it.

Leave the dev server running in the background — the page hot-reloads
when you edit files. Verify hot-reload once by tweaking the title in
`src/levels/demo.json` and asking them to glance at the page.

Mark Phase 0 done in `PROGRESS.md` only after the collaborator confirms
they see the placeholder in their browser. If anything in Phase 0
failed or confused them, **fix it before talking about game design**
— and log the friction in `ISSUES.md`.

### Phase 1 — Discover the game with the collaborator

Have a short, focused conversation. Don't grill them with a checklist;
let it feel like a brainstorm. Across the conversation, you do need to
walk away with answers to:

- What does the player **do** (tap a thing, swipe a row, drag, draw a
  line, time-based input, etc.)?
- What's on the **board** (grid? hex? freeform? how big? what pieces or
  cells exist)?
- What's the **win condition**?
- Is there a **lose condition**, or only "keep trying"?
- One **concrete example**: "If I tap *here*, what happens visually and
  to the game state?"
- Roughly **how long** should one level take to play (10 seconds? 2
  minutes? 10 minutes)? That sets how big `demo.json` should be.

Mirror your understanding back in one paragraph and confirm before
writing code. Record the agreed concept in `PROGRESS.md` § "Game
concept".

### Phase 2 — Implement freely

Build it. Iterate live with the collaborator — they should be able to
play any intermediate version in their browser.

You are free to choose data structures, render strategies, animation
style, audio cues, and project layout *within* the `src/` folders.
Suggested folders are pre-created but you can rename or restructure
inside `logic/`, `render/`, and `assets/`.

Architectural rules to follow while building:

- **Pure logic stays in `src/logic/`.** No Pixi, no DOM, no
  `Math.random()` (use a seeded PRNG if you need randomness), no
  `setTimeout`-driven state changes. Animations and timers belong in
  the render or input layers, not in the rules.
- **`Level` is the contract.** Whenever you add a piece type, an
  obstacle, a colour, a starting parameter — ask yourself "is this
  captured in the `Level` interface, or am I hard-coding it?" If
  hard-coded, lift it into `Level`.
- **The demo level lives in `src/levels/demo.json`.** Edit it by hand to
  tune the playable example. Don't generate it from code at runtime.
- **Use `src/assets/` for visuals and sounds.** See section 7 — every
  image and every sound goes through that wrapper, regardless of
  whether it's a real file or procedurally generated. Don't load assets
  from random paths.

The starter `src/` ships nearly empty (just enough to render the level
title). When you're unsure how a piece is meant to fit, peek at
`example/` — it's a complete worked reference built around a
tap-counter game with input, sound, and a win overlay. Don't import
from `example/`; copy patterns into `src/`.

### Phase 3 — Handover

When the collaborator says they're happy with the playable level:

1. **Lock the `Level` interface.** Re-read `src/core/level.ts`. Are all
   fields necessary? Are types as tight as possible (literal unions
   instead of `string`, fixed-length tuples instead of `any[]`)?
2. **Fill in `HANDOVER.md`.** This is the most important document for
   downstream level designers.
3. **Run through the final demo with the collaborator one more time** —
   make sure `npm run dev` still launches it cleanly from a fresh
   terminal. Tell them how to share the project (`git push` if they
   want, or zip the folder).
4. Mark Phase 3 done in `PROGRESS.md`.

### Phase 4 — Level-design feedback (optional, may happen later)

The downstream level-design team may come back with questions or
requests (e.g. "we need an extra field for X obstacles"). If that
happens, log the request in `PROGRESS.md` § "Level-design feedback",
make the smallest change that addresses it, bump the schema version in
a comment, and confirm `demo.json` still loads cleanly.

---

## 6. Always-on responsibilities

Two files exist purely to keep the project legible to both your future
self and the skill author:

- **`PROGRESS.md`** — live state. Update on every phase transition and
  every notable decision (game concept agreed, schema field added,
  build-breaking change, etc.). Keep it short — bullets, not prose.
- **`ISSUES.md`** — friction log. Add an entry whenever:
  - A bootstrap step failed or confused the collaborator.
  - The collaborator asked a question this `SKILL.md` should have
    answered.
  - You had to guess at a convention that wasn't documented.
  - A starter file was misleading or got in the way.
  - A workflow step felt unclear or out of order.

  Each entry follows the format already in `ISSUES.md`. This file is
  how the template gets better over time; treat it as part of the work,
  not paperwork.

---

## 7. Assets pattern

`src/assets/` is a **self-contained folder** — anyone can read it in
isolation and know exactly which images and sounds the game uses. The
rest of the codebase touches assets only through the wrapper at
`src/assets/index.ts`, which exposes:

```ts
getImage(name: string): Texture        // Pixi texture
playSound(name: string): void          // fires one-shot
listAssets(): { images: string[]; sounds: string[] }
```

To add an asset:

- **Procedural (no file needed).** Create `src/assets/images/foo.ts` (or
  `sounds/foo.ts`) that exports `function create(): Texture` (or
  `() => () => void` for sounds). Then register it in
  `src/assets/index.ts`.
- **Real file.** Drop the file in `src/assets/images/` (or `sounds/`),
  `import url from './images/foo.png'`, and register a factory in
  `index.ts` that calls `Texture.from(url)` (or your sample-playback
  helper for sounds).

The starter registries are **empty** so you add your first asset
deliberately and learn the pattern early. Two worked examples (one
procedural image, one procedural sound) live in
`example/src/assets/` — read them when you need a reference, then
write your own.

---

## 8. Hard "don'ts"

- Don't change the **name or location** of `src/core/level.ts`,
  `src/levels/demo.json`, `src/assets/index.ts`, `HANDOVER.md`,
  `PROGRESS.md`, or `ISSUES.md`. Downstream tooling and the skill
  author look for these exact paths.
- Don't change the **portrait aspect ratio** of the canvas.
- Don't store game state on the `window`, in cookies, or in
  `localStorage`. The page should be fully reset on reload.
- Don't add a build step that runs Node-only code at game runtime —
  the finished demo must be pure browser code (Vite bundles it for
  you).
- Don't introduce a backend, auth, account system, level editor, level
  selector, score persistence, leaderboard, or in-app payments. You are
  building **one level**, not a product.
- Don't ask the collaborator to read source code unless they
  explicitly want to.

---

## 9. When you're stuck

- **Bootstrap problems**: tell the collaborator exactly which step
  failed and propose one specific fix. If three attempts fail, fall back
  to the official Node.js installer at https://nodejs.org and walk them
  through it click-by-click. Log it in `ISSUES.md`.
- **Design problems**: ask the collaborator for a concrete example of
  the behaviour they want, then implement the simplest version that
  matches.
- **`Level` schema doubt**: re-read section 3. The schema must be
  serializable and complete — if you're tempted to put a function or
  class in it, you're doing something else wrong.

---

## 10. Definition of done

The collaborator can hand the project folder (or a fresh clone) to a
new machine. After completing Phase 0, they can:

1. Run `npm install && npm run dev`.
2. Open the printed URL in a browser.
3. Play **one** complete level of the game from start to win condition.

And **you** (or any other agent) can open `src/core/level.ts`,
`src/levels/demo.json`, and `HANDOVER.md`, and immediately understand
the level format well enough to author a new valid level by hand
without running the game.

`PROGRESS.md` shows Phase 3 complete. `ISSUES.md` contains every
friction point worth remembering.

If all of that is true, you're done. Tell the collaborator and stop.
