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
17 changes: 17 additions & 0 deletions .cursor/environment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "rapbattle",
"install": "bash .cursor/install.sh",
"terminals": [
{
"name": "wrangler dev",
"command": "npx wrangler dev --local --ip 0.0.0.0 --port 8787",
"description": "Local Cloudflare Worker (miniflare) serving the arena UI + MCP endpoint on http://localhost:8787. --local keeps D1/R2/KV/DO in-process; the Workers AI (TTS) binding is disabled locally, so /speak audio routes need a real CLOUDFLARE_API_TOKEN and are the only feature not available offline."
}
],
"ports": [
{
"name": "wrangler dev",
"port": 8787
}
]
}
25 changes: 25 additions & 0 deletions .cursor/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Idempotent bootstrap for the rapbattle Cloudflare Worker dev environment.
set -euo pipefail
cd "$(dirname "$0")/.."

# Exact, lockfile-pinned dependencies (mirrors the typecheck CI workflow).
npm ci

# The Worker's ensureSchema() (src/beats.ts) only ALTERs the base tables and
# creates the auxiliary ones at runtime; the base tables themselves come from
# src/db/schema.sql. Seed them into the local (miniflare) D1 that
# `wrangler dev --local` uses so the arena has real tables on first boot.
# CREATE TABLE IF NOT EXISTS keeps this safe to re-run.
npx wrangler d1 execute rapbattle --local --file=./src/db/schema.sql

# Local-only secret that unlocks the /admin/* seed + repair routes
# (see src/admin.ts). It never touches production: .dev.vars is git-ignored and
# only read by `wrangler dev`. Without it the app still runs; you just can't use
# the one-shot arena seeder.
if [ ! -f .dev.vars ]; then
cat > .dev.vars <<'EOF'
# Local development secrets for `wrangler dev` only. Git-ignored, non-production.
ADMIN_SECRET="local-dev-secret"
EOF
fi
45 changes: 45 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# AGENTS.md

rapbattle is a single Cloudflare Worker (`src/index.ts`) serving the arena UI + an OAuth-gated MCP endpoint, backed by D1, R2, KV, Workers AI (TTS), and a bound-but-unused Durable Object.

## Cursor Cloud specific instructions

The Cloud Agent environment is repository-managed via `.cursor/environment.json`.

### Install

`install` runs `.cursor/install.sh`, which:

- runs `npm ci` (lockfile-pinned; matches the typecheck CI),
- applies `src/db/schema.sql` to the local (miniflare) D1 so the base tables exist — the Worker's `ensureSchema()` in `src/beats.ts` only ALTERs those tables and creates the auxiliary ones at runtime,
- writes a git-ignored `.dev.vars` with a local `ADMIN_SECRET` (`local-dev-secret`) so the `/admin/*` seed routes work offline.

To bootstrap manually: `bash .cursor/install.sh` (idempotent).

### Dev server

`npx wrangler dev --local --ip 0.0.0.0 --port 8787`

This runs as the `wrangler dev` terminal and serves the app on http://localhost:8787.

**Why `--local` is required:** the remote Workers AI binding (`env.AI`) makes `wrangler dev` open a remote proxy that demands a `CLOUDFLARE_API_TOKEN`, which fails in a non-interactive environment. `--local` disables remote bindings so dev works fully offline (D1/R2/KV/DO are emulated in-process). The only feature unavailable locally is `/speak` TTS audio, since Workers AI has no local emulator.

### Seed + confirm it works

Seed the arena (needs the local `ADMIN_SECRET` from `.dev.vars`):

```
curl -s -X POST "http://127.0.0.1:8787/admin/seed-rift?secret=local-dev-secret"
```

Then confirm:

- `GET /health` → `{"status":"live",...}`
- `GET /` → arena home renders
- `GET /battle/battle-001` → seeded verse renders (contains "Rift")
- `GET /leaderboard` → Rift on the board
- `GET /stage` → Rift's intro + stage call

### CI check

`npm run typecheck` (`tsc --noEmit`) — this is the check run by `.github/workflows/typecheck.yml`.
Loading