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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
108 changes: 108 additions & 0 deletions .claude/skills/reset-total/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
name: reset-total
description: >-
Cierra la sesión antes de compactar o reiniciar: vuelca el estado del trabajo en Vitrina a un .md
de continuidad en docs/sessions/, pasa las reglas durables a CLAUDE.md y entrega el prompt para
reanudar. Úsala cuando Sergio diga "reset-total", "reset total", "voy a compactar", "voy a
colapsar", "guarda todo antes de compactar", "cierra la sesión", "prepárame para reiniciar",
antes de un /compact, o cada ~350k tokens en una sesión autónoma larga.
---

# reset-total — guardar la sesión antes de compactar

Objetivo: que después de compactar o de abrir una sesión nueva no se pierda nada que importe, y
que Sergio no tenga que volver a dictar las instrucciones de siempre.

Tres salidas, siempre las tres: **un .md de estado**, **CLAUDE.md al día**, y **un prompt de
reanudación**.

## Procedimiento

### 1. Recoger lo que hay que salvar

Sale de la conversación actual. No se reconstruye de memoria ni se inventa. Seis cajones:

1. **Pendiente de cerrar**: cambios sin commit, commits sin push, PR abiertas o pedidas, checks
rojos, preguntas hechas a Sergio que esperan respuesta. Para cada uno: qué es, estado real
(escrito, probado, commiteado, pusheado) y dónde está.
2. **Estado del trabajo**: rama, último commit (hash corto), qué ha cambiado en esta sesión por
capa (`src/domain`, `src/generation`, `src/server`, `src/studio`, `src/ui`, `src/app`, docs,
infra), y el resultado exacto de la última pasada de `pnpm lint`, `pnpm typecheck`,
`pnpm test`, `pnpm build`, `pnpm test:e2e` (número de tests, verde o rojo).
3. **Correcciones de datos**: cualquier cosa que se creía y resultó falsa (una API que no se
comporta como se suponía, un flag que no existe, una versión incompatible). Esto es lo que más
valor tiene, porque es lo que se vuelve a colar si se pierde.
4. **Decisiones tomadas**: producto, arquitectura, nombres, precios, alcance descartado — con el
motivo en una línea. Lo que Sergio decidió, separado de lo que decidió el agente.
5. **Reglas nuevas** que Sergio haya dado durante la sesión.
6. **Entregables generados**: rutas de ficheros y URLs (rama, PR, artefactos).

### 2. Verificar antes de escribir

- **Comprobar que cada ruta existe** con `ls` antes de listarla. Un fichero que no existe no se
lista.
- **Comprobar git**: `git status --short`, `git log --oneline -5`, `git log origin/<rama> -1`.
Nada se da por commiteado o pusheado si no consta ahí.
- Si hay en `docs/sessions/` ficheros de estado **que no se escribieron en esta sesión**, se listan
marcados como "de otra sesión" y **no se describe lo que no se ha leído**.
- **Releer `CLAUDE.md`**: si otra sesión añadió reglas desde que empezó esta, cruzarlas con los
pendientes; una regla nueva puede cambiar un cambio que está a punto de salir.
- **Repasar el scratchpad** de la sesión (`CONTEXT.md` si existe) y absorber lo que siga vigente.

### 3. Escribir el .md de estado

Ruta: `docs/sessions/estado-sesion-<AAAA-MM-DD>.md` (fecha de hoy). Si ya hay uno de hoy, se
sustituye y la cabecera dice que sustituye al anterior.

Estructura fija, en este orden:

1. Pendiente de cerrar (tabla: qué · estado real · dónde está)
2. Estado del trabajo (rama, commit, cambios por capa, resultado de los checks)
3. Correcciones de datos
4. Decisiones tomadas
5. Reglas nuevas
6. Entregables (tabla con rutas y URLs verificadas)
7. Herramientas y estado técnico (servidores en marcha, puertos, env local, mock, Chromium,
lo que no se pudo probar y por qué)
8. Límites duros (lo que no se hace sin preguntar: push a otra rama, PR, borrar, producción)

### 4. Persistir

- El .md va en el repo: `git add docs/sessions/... && git commit` **solo del .md**, nunca mezclado
con código a medias. Se pushea a la rama de trabajo si esa rama ya se pusheaba en la sesión.
- Si hay código sin commit que Sergio no ha pedido commitear, se deja como está y se anota en
"Pendiente de cerrar".

### 5. CLAUDE.md

Solo si hay una **regla nueva y durable** o una **corrección de algo que ya está escrito**:

- Regla nueva → una línea en "Rules of the house" (o un comando nuevo en la tabla).
- Corrección → editar la línea existente, no añadir otra que la contradiga.
- No guardar lo que ya está en el repo, en el git o en el propio .md de estado.

### 6. Entregar el prompt de reanudación

En un bloque de código, listo para pegar. Tiene que:

- Nombrar el .md de estado y pedir que se lea primero, junto con `CLAUDE.md`.
- Nombrar la rama y el último commit.
- Resumir en cinco o seis líneas lo imprescindible: pendientes, checks rojos y límites duros.
- **No** repetir el .md entero.

## Reglas duras

- **Nunca escribir secretos** en el .md, en CLAUDE.md ni en el prompt: `APP_SECRET`, claves de
plataforma, tokens de Stripe, contraseñas de cuentas de prueba. Si se detectó uno durante la
sesión, se nombra el problema, no el valor. `.env` no se cita por contenido.
- Hashes, rutas, cifras y números de tests exactos. Lo no verificado se marca como tal.
- Cero emojis e iconos.
- Esta skill **no pushea código, no abre PR y no toca producción**. Solo guarda el estado.
- Si el commit del .md falla, el .md y el prompt se entregan igual. La persistencia nunca bloquea
la entrega.

## Salida al usuario

Corta. Tres líneas como mucho sobre qué se ha guardado y dónde, y el bloque con el prompt de
reanudación. Si al releer CLAUDE.md o el scratchpad ha salido algo que cambia un pendiente, se
dice en una línea.
51 changes: 51 additions & 0 deletions .claude/skills/wipe-local/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: wipe-local
description: Reset the local Vitrina environment to a clean slate — local database, uploads, build output and test artifacts (optionally node_modules) — then recreate the database. Use when the dev database is corrupted or full of test junk, migrations diverged, the build cache misbehaves, or you want to reproduce a first-run experience. Never for a deployed environment.
---

# wipe-local

Wipes everything local and regenerated, keeps everything authored.

## What it removes

| Path | Why |
| --- | --- |
| `data/` (or `DATA_DIR`) | The libsql database file and local uploads |
| `.next/` | Build output and Turbopack cache |
| `test-results/`, `playwright-report/` | e2e artifacts |
| `node_modules/` | Only with `--deps`; reinstalled from the lockfile |

Kept: `.env`, source, git history, `drizzle/` migrations.

## Steps

1. Confirm the target is local. The script refuses when `DATABASE_URL` is not a
`file:` URL — a remote (Turso) database is never reset from here. If the
user seems to be on a deployed environment, stop and say so.
2. Stop running servers first (`pnpm dev`, `pnpm start`, `pnpm mock:platform`):
an open libsql handle can recreate the file mid-reset.
3. Preview, then run:

```bash
node scripts/wipe-local.mjs --dry-run # lists what would go
node scripts/wipe-local.mjs --yes # data + build + artifacts
node scripts/wipe-local.mjs --yes --deps # also node_modules, then pnpm install
node scripts/wipe-local.mjs --yes --keep-uploads # keep data/uploads, drop the DB
```

Without `--yes` the script asks to type `RESET` when run interactively.
4. The script ends by running the migrations, so the database exists and is
at the current schema. Start `pnpm dev` and register a fresh account
(30 trial credits); to skip Stripe, grant credits with
`pnpm credits <email> <n>`.
5. Report what was removed and that the studio is empty.

## Rules

- This is destructive and unrecoverable for local runs and uploads: when the
user did not explicitly ask for a reset, ask before running anything but
`--dry-run`.
- Do not "reset" by deleting individual tables or editing the database by
hand; the script is the one path so the migration journal stays consistent.
- Do not touch `.env`; a broken environment file is fixed by hand, not by reset.
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules
.next
.git
data
test-results
playwright-report
.env
.env.*
!.env.example
17 changes: 0 additions & 17 deletions .gitattributes

This file was deleted.

66 changes: 66 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: CI

on:
push:
branches: [main, master]
pull_request:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
checks:
name: Lint, types, unit tests, build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build
env:
APP_SECRET: ci-build-secret
- uses: actions/upload-artifact@v4
with:
name: next-build
path: .next
retention-days: 1
include-hidden-files: true

e2e:
name: End-to-end (mock platform)
runs-on: ubuntu-latest
needs: checks
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/download-artifact@v4
with:
name: next-build
path: .next
- run: pnpm exec playwright install --with-deps chromium
- run: pnpm test:e2e
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: |
playwright-report
test-results
retention-days: 7
64 changes: 18 additions & 46 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,47 +1,19 @@
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# =========================
# Operating System Files
# =========================

# OSX
# =========================

node_modules
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
.next
out
dist
*.local
.env
.env.*
!.env.example
.vercel
tsconfig.tsbuildinfo

.env*
.idea

# local database and uploads
data/
test-results/
playwright-report/
52 changes: 52 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Vitrina — working notes for agents

Next.js 16 (App Router, Turbopack) · React 19 · TypeScript strict · plain CSS ·
Zustand · Drizzle + libsql · better-auth · Stripe · vitest · Playwright · pnpm.

## Commands

| Command | Purpose |
| --- | --- |
| `pnpm dev` | Dev server on :3000 (migrations run on boot) |
| `pnpm mock:platform` | Stand-in generation API on :4010 — point `HF_API_BASE_URL` at it |
| `pnpm lint` / `pnpm typecheck` / `pnpm test` | ESLint, `tsc --noEmit`, vitest |
| `pnpm build` | Production build (standalone output) |
| `pnpm test:e2e` | Playwright against a fresh prod build + mock platform |
| `pnpm db:generate` | New migration after editing `src/db/schema.ts` |
| `pnpm credits <email> <n>` | Grant credits without Stripe |
| `pnpm wipe:local [--deps] [--keep-uploads] [--yes] [--dry-run]` | Wipe local DB, uploads, build and test artifacts, then re-migrate (skill `wipe-local`) |

## Skills

- `reset-total` — close the session before a compact or restart: state file in
`docs/sessions/`, durable rules into this file, resume prompt.
- `wipe-local` — destructive local reset of data, build and artifacts.

Set `PLAYWRIGHT_CHROMIUM_PATH` to reuse a Chromium already on disk.

## Where things live

- `src/domain/` — the vertical as data: channels, presets, prompt compiler,
pricing, plans. Pure, unit-tested, no I/O. Change the industry here.
- `src/generation/` — the engine inherited from open-higgsfield: catalog,
platform client, request mapper, poll loop, server actions (`actions.ts`).
- `src/server/` — DB-backed services and `actions/*` server actions. Every
action starts with `requireViewer()`; pages start with `viewerOrRedirect()`.
- `src/studio/` — the studio surface (composer, gallery, viewer, job rail).
`use-generation.ts` is the run lifecycle shared with the campaign page.
- `src/ui/` — app pages' client components and `app.css`.
- `src/app/` — routes. `/` marketing, `/login`, `/register`, `/app/*` behind
the session, `/api/*` auth, uploads, files, billing webhook.

## Rules of the house

- The catalog is the source of truth for what a model takes; presets and
channels only choose among what it declares. `resolveSettings` must always
produce something `parseSettings` accepts (there is a test for it).
- Credits are integers, reserved before the platform is asked, refunded once
per request. Never touch `credit_balance` outside `src/server/credits.ts`.
- Server actions in `"use server"` files export async functions only; put
helpers in a plain module (`src/server/validation.ts` is the pattern).
- CSS classes are prefixed `vt-`; tokens live on `.vt` in `studio.css`.
- Keep the design principles from the original README: accent is state, not
decoration; every control ships all its states; nothing loops decoratively.
Loading
Loading