These are real memories from production projects. This is what your AI tools see at the start of every session. The context that prevents mistakes.
A typical web app with authentication, API routes, and a database
NEVER construct message objects manually as {id, text, type}. ALWAYS import msg/systemMsg/errorMsg from lib/messages.ts. These were extracted from 10 duplicate definitions.
All API routes return { error: string, code: string, status: number } on failure. Use the shared errorResponse() helper from lib/api-utils.ts. Never throw raw errors from route handlers.
Chose Supabase Auth over NextAuth. Rationale: built-in RLS integration, no adapter boilerplate, GitHub OAuth out of the box. Trade-off: vendor lock-in on auth, but acceptable since DB is already Supabase.
Supabase handles JSONB serialization automatically. Passing JSON.stringify() to a JSONB column double-encodes it, causing parse failures on read. Two production outages from this.
Adding an API route: 1) Create file in app/api/<path>/route.ts. 2) Export async function for HTTP method (GET, POST, etc). 3) Add Zod validation for request body. 4) Use createClient() from lib/supabase/server.ts for DB access. 5) Add rate limiting if public-facing.
A text-based game with combat, inventory, factions, and 271 hand-crafted rooms
NEVER add a field to _savePlayer() without a matching Supabase migration. Two production outages caused by this. ALWAYS create migration FIRST. NEVER JSON.stringify() JSONB fields.
When adding spawnable entities to rooms (enemies, NPCs, bosses), add spawn data directly to room definitions in data/rooms/<zone>.ts. NEVER create a separate spawn system. Rooms own their spawn tables.
6 status effects: bleed, burn, stun, frighten, poison, weaken. Hemorrhagic shock = bleed+burn combo. This is the ONLY condition combo. Do not add more. Conditions tick each combat round.
Adding a command: 1) Register verb + aliases in lib/parser.ts. 2) Add case in lib/gameEngine.ts dispatch switch. 3) Create handler in lib/actions/<domain>.ts. 4) Import handler in gameEngine.ts. All three files must be updated.
ALWAYS use rt helper for terminal output: rt.item(), rt.npc(), rt.enemy(), rt.condition(), rt.keyword(). NEVER output raw text for game entities. The terminal parser colorizes tagged content.
A TypeScript monorepo with CLI, server, shared types, and a dashboard
Supabase returns PromiseLike not Promise. MUST wrap with Promise.resolve() for .catch(). Multiple past type errors from this.
Server must be built before CLI. CLI has cross-package imports that reference server/src/ with @ts-ignore. pnpm build handles order, but pnpm --filter cli build alone will fail.
Hot: SQLite (better-sqlite3) for sub-10ms local queries. Warm: Supabase Postgres with pg_trgm + pgvector. Cold: Archive table for stale memories. WAL recovery on crash.
Procedural generation was built and then deleted. Replaced with hand-crafted content for better quality. Do NOT reintroduce. This was a deliberate design decision.
Two commands. Your agents start remembering.