# mbinv — contexto para Claude

## ⚠️ Antes de tocar nada: leé `REGLAS-EQUIPO.md`

Es la **fuente única** de las reglas del equipo para correcciones y cambios (las lee
cualquier cuenta de Claude que trabaje acá). Solo Andrea o Manuel pueden reescribirlas.

Lo más importante, en corto:

- **LEY: nada sin tiquete.** Nunca corregir/modificar sin uno; si hay algo en curso sin
  tiquete, crearlo.
- **Sin evidencia no se pide review.** Antes/después, en pruebas (nunca producción);
  `php -l` no es prueba. Los comentarios del bot los resuelve quien hace el fix.
  **Se prueba por el camino que usa la gente**: si es una pantalla, clic real en el
  navegador — un `curl` en 200 no prueba que el botón sirva. Si solo se pudo probar por
  API, decirlo al entregar.
- **Trabajo aislado por rama:** cada quien en su worktree (`git worktree add`), nunca
  cambiar de rama en el directorio principal, nunca `git add -A` en repo compartido.
  Para probar: `probar-rama.sh <rama>` (repo `oci-dr`) da un ambiente aislado con URL.
- **Asignación:** PT → Andrea, BO → el programador del módulo (mapa en `REGLAS-EQUIPO.md`).
  Escala a Manuel si urgente y sin respuesta.
- **Flujo:** En Desarrollo → Pruebas de QA → merge → Resuelto → Soporte actualiza al
  cliente → visto bueno del cliente → Cerrado. Nunca Cerrado sin OK del cliente.
- **Dominio:** las ventas se hacen solo desde el PT, no desde el BO.

El detalle completo, la escalación, los horarios y el mapa de dominios están en
`REGLAS-EQUIPO.md`.

Las convenciones personales de Claude con Manuel —modelo a usar, cuándo pedir revisión de
Codex, `/clear` vs `/compact`, etc.— viven en @CONVENCIONES-CLAUDE.md.

---

## El mapa: dónde corre esto y qué te puede morder

> Arriba están las **reglas**. Acá está el **terreno**: qué entorno es cuál, qué se
> despliega dónde, y las trampas que ya costaron caídas de sitios de clientes.

### ⚠️ Producción corre PHP 5.6. Tu Mac corre PHP 7.1

Medido el 12-ago-2026:

```
producción   PHP 5.6.40
pruebas      PHP 5.6.40
Mac local    PHP 7.1.33
```

**Cualquier sintaxis de PHP 7 pasa desapercibida en tu máquina y truena en el cliente.**
Nada de `??`, `<=>`, tipos de retorno, `list()` con claves, ni `catch (\Throwable)` — este
último ni siquiera da error: **simplemente no atrapa nada** en 5.6, así que el `catch` queda
mudo y el error se pierde.

Antes de dar algo por listo, comprobalo con el PHP que corre de verdad, no con el de tu Mac.

### Los entornos, que se confunden fácil

Los tres tienen "pruebas" en el nombre en algún lado. No son lo mismo:

| | qué es | cómo se llega |
|---|---|---|
| **Mac local** | desarrollo. El PHP corre en vivo acá, contra MySQL local (`mbinvmacrobase`) | — |
| **oci-mbinv** | **PRUEBAS**. ~250 vhosts de clientes, Apache. IP directa `129.80.4.9` | `ssh oci-mbinv` |
| **producción** | los sitios reales, detrás del balanceador | `ssh -A -p 4072 macrobase@132.226.40.48` |
| **base de pruebas** | el bastión del DB System, puerto **3310** | `ssh -p 4074 macrobase@132.226.40.48` |

> Que un servidor tenga cientos de vhosts con nombres de clientes reales **no significa que
> sea producción**. `oci-mbinv` los tiene y es pruebas. Antes de tocar una base o decir "ya
> está desplegado", confirmá de cuál de los tres se está hablando.

### Los sitios de clientes: 163 checkouts distintos

En producción, cada cliente es su propio checkout en `/var/www/html/<cliente>/mbinv`, **cada
uno en el commit en que quedó la última vez**. Algunos están en versiones de 2024.

Se actualizan con **`/usr/bin/mbactualizar`**, parado dentro del directorio del proyecto.
Dos cosas que hay que saber de ese programa:

- **Hace `git reset --hard`.** Descarta *todo* lo que alguien haya editado a mano en ese
  sitio, sin listar qué descartó. Sólo `web/logo.jpg` sobrevive, porque lo respalda y lo
  restaura a propósito.
- **No está en ningún repo.** Existe únicamente en el disco de producción.

### Un parámetro nuevo puede tumbar a los clientes viejos — y hay un piso que lo evita

`config.yml` y `security.yml` usan parámetros que viven en `app/config/parameters.yml`, que
**no está versionado**. Si el repo empieza a usar uno nuevo, las instalaciones viejas no lo
tienen → `ParameterNotFoundException` → **no arranca el contenedor de servicios**, así que no
degrada una pantalla: cae el sitio entero, login incluido.

> Pasó el 28-jul-2026 con `%session_cookie_name%`: `demoanitalara` devolvió 500 en todas sus
> rutas. Alcance medido base por base: **117 de 163 sitios** se habrían caído.

**Ya está resuelto, y hay que saber cómo:** existe `app/config/parameters_defaults.yml`,
versionado, que se importa **antes** que `parameters.yml`. Da el piso para lo que una
instalación vieja no tenga, sin pisar el valor de la que sí lo tiene — lo que se importa
después gana.

**Así que al agregar un parámetro nuevo, ponele su valor por defecto ahí.** Si no, volvés a
crear el mismo problema para las instalaciones que no lo tengan.

### Las dos bases que se parecen y no son

- **`mbinvestructura`** — base de REFERENCIA en pruebas (`3310`). **Es la que se toca**, y
  todo `ALTER` va acá. ⚠️ **No es sólo estructura:** también guarda la **plantilla general
  del Diccionario**, que es dato vivo. `DicController` la lee al *importar plantilla* en un
  cliente y la **sobrescribe** al *exportar plantilla*. Borrar sus filas `dic_*` creyendo
  que son relleno de esquema se lleva puesta configuración que los clientes importan.
- **`mbinvinstalar`** — la PLANTILLA real, en **producción**. Se clona entera (estructura y
  datos) al crear un cliente nuevo. **El equipo de programación no está autorizado a
  tocarla.** Llevarle contenido es siempre un paso manual de una persona autorizada.

Si aparece una `mbinvinstalar` en el servidor de pruebas, es una homónima sin relación. No
la uses para nada que vaya a producción.

### El instalador no sólo cambia el esquema: corrige DATOS

`Instalacion.php::installData()` hace `UPDATE` sobre tablas de clientes, no sólo `ALTER`.
Correrlo no es inocuo. La opción «Sólo revisar» sí los suprime.

### Trabajar el repo sin pisar a nadie

**Nunca cambies de rama en `/Users/manuelbustamante/proyectosweb/mbinv`.** Manuel la tiene
abierta en su VSCode y cambia de rama entre tiquetes; un `checkout -b` ahí se lleva puestas
las otras ventanas.

```bash
git worktree add ../mbinv-<tema> -b claude/<AAAA-MM-DD>-<tema>
```

Y **nunca `git add -A`**: listá los archivos uno por uno. Con varias ventanas trabajando, lo
que otra sesión tenía a medias termina commiteado bajo un mensaje ajeno.

**Ojo con `vendor/` en un worktree nuevo:** no lo enlaces entero — PHP resuelve `__DIR__` por
la ruta real del enlace y el autoloader termina apuntando a la carpeta original. Enlazá
paquetes sueltos, dejá `vendor/composer/` y `vendor/autoload.php` como copias reales, y corré
`composer dump-autoload` desde el worktree.

### ⚠️ La migración a Symfony: la referencia es `origin/lts/sf54`, y NO hay carpeta

Si venís a trabajar el estrangulamiento (#23436) y buscás `~/proyectosweb/mbinv_hermana`:
**ya no existe, y no lo recrees.** Se borró el 15-ago-2026.

**Por qué.** No era un repositorio aparte — era un `git worktree` de este mismo repo,
compartiendo el `.git`. O sea que no estaba aislado de nada: un commit ahí entraba a
`mbinv`, aparecía en el `git worktree list` de todas las ventanas, y ocupaba el primer
puesto del tablero de riesgo todos los días tapando los riesgos de verdad. Sus 1.974
archivos "preparados" resultaron diferir de `origin/lts/sf54` en **un solo archivo**.

Consultá la referencia sin ninguna carpeta:

```bash
git show origin/lts/sf54:<ruta/del/archivo>            # leer un archivo
git ls-tree -r --name-only origin/lts/sf54 | grep X    # buscar dónde está algo
git diff main origin/lts/sf54 -- <ruta>                # cómo quedó allá vs hoy
```

Y si hay que leer muchos archivos, un worktree **temporal** que se borra al terminar —
nunca uno permanente, que es exactamente lo que produjo el problema:

```bash
git worktree add ../ref-sf54 origin/lts/sf54
git worktree remove ../ref-sf54
```

**Dos trampas de estas ramas, que ya costaron trabajo repetido:**

- **Un conteo de commits contra la base equivocada no significa nada.**
  `fix/deploy-docs-symlink-public` mostraba *583 commits únicos* contra `lts/sf54` sólo
  porque había nacido de `main`: su aporte real era 1 commit con un solo archivo. Antes de
  asustarte por un número, mirá contra qué base se midió.
- **Estar en `origin` no es estar mergeado.** El 14-ago se rescataron 19 líneas de
  `DEPLOY.md` a una rama que se subió y quedó anotada como "listo" — nunca tuvo PR, así
  que al día siguiente seguían sin estar en ninguna rama viva y hubo que rescatarlas otra
  vez (#831).

### Cosas que nacen mal si no te acordás

- **Las rutas nuevas nacen públicas.** Hay que declararlas en `security.yml` o quedan sin
  autenticación.
- **`parameters.yml` no se versiona**, y ninguna de sus variantes: el `.gitignore` cubre
  `parameters*.yml*` porque un `.bak` se coló por esa rendija (#23073).
- **Producción no tiene las tablas `dic_*`.** Cualquier código que las consulte tiene que
  pasar por `Dic::estaInstalado()` antes.
