AGENTS.md
Rama main · réplica de lectura del repositorio original.
# AGENTS.md
Guidance for coding agents working on Comic Chat Web.
Agent-assisted contributions are welcome, with caveats:
- All judgement and accountability falls to the named human contributor as the reviewer.
- If the user doesn't demonstrate understanding a change, it's not ready to merge.
- Code style here must still match house style.
- To the above, explicitly:
- wanton em-dash usage is not permitted.
- expositionary and excessive commenting is not permitted.
- when in doubt, do less. Comments are reserved for decision points, or unexpected gotchas, etc.
The general instructions must also still be followed, same as any contributor, and live in [CONTRIBUTING.md](CONTRIBUTING.md).
## Layout
- `src/engine/` - the composition engine, ported function-by-function from the original '96-'99 C++ (panels, balloons, poses, emotion wheel). Deterministic and trace-validated.
- `src/browser/` - client UI. `room.ts` is the app entry; canvas renderers and widgets live alongside it. `roomSession.ts` drives one live session's DOM and consumes a transport.
- `src/transports/` - network transports behind the `RoomTransport` seam (`types.ts`). `do/` owns the WebSocket, reconnect loop, heartbeat, and liveness watchdog. Imports only `src/protocol/`; enforced by `test/transportIsolation.test.ts`.
- `src/studio/` - the standalone strip editor served at `/studio`, sharing the engine and canvas renderers but none of the room's state. `script.ts` is the JSON strip format and its validator, `compose.ts` turns one into panels directly (explicit cast, order, facing, and camera; no auto panel breaking), `art.ts` probes every drawing a character owns and names it, `catalogJson.ts` publishes those names as `/assets/catalog.json` at build time, `studio.ts` is the page entry.
- `src/protocol/room.ts` - wire protocol, room defaults, and error-reason constants shared by client and worker.
- `worker/` - Cloudflare Worker. `room.ts` is the chat room Durable Object, `directory.ts` the room directory DO, `moderation.ts` the content filter.
- `worker/db/` - the room's SQL layer, kept out of `room.ts`. `events.ts` is the append-only IRC-style event log (chat, backgrounds, join/part/topic announces) behind a derived row contract; `migrations.ts` the per-room schema runner. DDL steps live as `.sql` in `worker/do_migrations/`.
- `tools/avb/` - asset pipeline: parses the original `.avb`/`.bgb` binaries into the committed PNGs and test fixtures.
- `test/` - vitest unit tests, node project. `test/worker/` - Durable Object tests, run in workerd. `test/browser/` - Playwright specs against the built app.
## Commands
- Unit tests: `npm test` (node and worker projects; `--project worker` for the Durable Object ones alone). Browser tests: `npm run test:browser` (builds, then serves a preview on :4173).
- Format and lint: `npm run format` then `npm run check` (Biome plus tsc for app, tools, worker, and worker tests).
- Dev: `npm run preview:worker` runs the built app with live rooms. `npm run dev` for UI-only hot reload; `npm run dev:api` alongside it if hot reload needs live rooms (vite proxies `/api` to :8787).
## Conventions
- Commit and PR titles use conventional style: `fix: ...`, `feat: ...`, `chore: ...`. Single-line subjects.
- Every behavior change ships with a test.
- `main` stays green. Contribute through normal PRs; releases are `v*` tags cut by the maintainer.
- Engine code tracks the original C++ for traceability (names and comments cite source lines like `balloon.cpp:397`). Match original behavior; don't restructure it to look nicer.
- Keep changes small and modular; match the surrounding style.
## Migrations
- Room storage is an append-only `events` log; the schema advances through numbered steps in `worker/db/migrations.ts`, each run once per room, in order, tracked in `_migrations`.
- Add a step by appending to `MIGRATIONS` - a `.sql` file in `worker/do_migrations/` for DDL, or a function for logic (e.g. `ensureColumns` to backfill columns an ancient room may lack). Steps are forward-only: never edit, reorder, or remove a shipped one.
- Columns read and written derive from `EVENT_SCHEMA` in `events.ts`; update the contract, not scattered SQL. `roomSchema.test.ts` guards that every contract field is backed by a real column.
- Ship the step with a worker test (`roomMigration.test.ts`), then `npm run check` and `npm test`. Migrations run live on real user rooms, so a dry run against exported data is worth it.
## Gotchas
- Asset regeneration (`assets:*`, `fixtures:avatars`) reads a sibling checkout at `../comic-chat` that CI and most machines don't have. The committed PNGs and fixtures are canonical; the build never needs the sibling.
- `vite preview` inherits the dev `/api` proxy, so a running `wrangler dev` leaks into browser tests. Playwright specs must stub `/api` routes to stay hermetic.
- The build has two entries (`index.html`, `studio.html`); Cloudflare Assets serves `studio.html` at `/studio`. Studio specs load `/studio.html` because `vite preview` has no such rewrite.
- DOM tests opt in per file with `// @vitest-environment jsdom`. jsdom has no 2D canvas context and serves `import.meta.url` over http, so `outgoingPose.test.ts` stubs `OffscreenCanvas` for the text measurer and loads fixtures from `process.cwd()`.