Skip to content

Releases: MauricioPerera/game-protocol

v2.18.0 - pagina del protocolo (ES/EN/PT) + auditoria de datos

Choose a tag to compare

@MauricioPerera MauricioPerera released this 09 Jul 17:31

[2.18.0] — 2026-07-09

Release aditivo sobre 2.17.0 (bump minor, SPEC §7.0): la página del
protocolo en GitHub Pages con soporte ES/EN/PT, y una auditoría de datos que corrige 4
inconsistencias documentales (conteo de perfiles en demos.html/CONTRIBUTING.md,
perfiles faltantes en llms.txt, hints faltantes en tools/rule-hints.js) y agrega un
test que gatea la cobertura de hints a futuro. La versión del protocolo sigue en 0.1.

Added — página del protocolo (GitHub Pages) + soporte ES/EN/PT

  • index.html pasa de "listado de demos" a landing explicativa: el problema (datos
    mezclados con lógica), la idea (un archivo, dos lectores — front-matter + doc), el
    pipeline real (lintexport → consumir, con el fallback embebido), un snippet real
    de monster-rpg, los 14 perfiles con badge para los puro-datos, y 4 razones concretas
    de por qué importa. Publicada en GitHub Pages: https://mauricioperera.github.io/game-protocol/
  • El listado de demos existente se preserva intacto en demos.html (mismo contenido,
    mismas rutas relativas), ahora linkeado desde el nav/footer de la nueva home.
  • Soporte multi-idioma (ES/EN/PT) en ambas páginas: selector en el nav, detección por
    navigator.language (fallback ES) persistida en localStorage bajo la clave
    compartida gp-lang — el idioma elegido se mantiene al navegar entre index.html y
    demos.html. 71 claves traducidas en index.html, 24 en demos.html; el código real
    de GAME.md (tokens del protocolo) no se toca, solo la prosa explicativa.
  • README actualizado con los links a la página y a los demos.

Fixed — auditoría de datos del protocolo

  • demos.html decía "9 perfiles de referencia desde la spec" en los 3 idiomas
    mientras index.html (mismo sitio) dice correctamente "14 perfiles" — corregido.
  • llms.txt listaba 12 de los 14 perfiles reales — se agregan sudoku y
    peg-solitaire (ambos puro-datos, como quiz/shooter).
  • tools/rule-hints.js le faltaban 23 hints de reglas reales (verificado contra
    test/conformance.js): papers-please, crafting, platformer, voxel y la familia
    grids (scene-rows entre otras) quedan cubiertas. Nuevo test en
    conformance.js gatea que todo rule-id real tenga hint, para que el gap no
    vuelva a aparecer en silencio. De paso, 5 hints ya existentes que estaban mal
    etiquetados bajo el comentario "roguelike" quedan reordenados a su sección real.
  • CONTRIBUTING.md decía que test/buildGame-content.js cubre "9 perfiles" —
    corregido a los 14 reales.
  • CHANGELOG.md (este archivo) estaba desactualizado respecto a HEAD.

v2.17.0 - familias grids/refs cross-coleccion + roguelike a lo grande

Choose a tag to compare

@MauricioPerera MauricioPerera released this 09 Jul 03:35

[2.17.0] — 2026-07-08

Release aditivo sobre 2.16.0 (bump minor, SPEC §7.0): dos frentes
independientes. En el core, la familia declarativa grids y el agregado
cross-colección en refs cierran la tercera etapa de reglas puras-de-datos (SPEC §11),
migrando los 4 perfiles que duplicaban esta lógica en JS. En roguelike, mecánicas
100% data-driven (llaves/puertas, jefe, progresión, permadeath), un solo generador
compartido entre los dos motores, mazmorra en mundo continuo 3D con minimapa, y guardado
persistente. La versión del protocolo sigue en 0.1.

Added — familias declarativas grids + agregado cross-colección en refs (SPEC §11, segunda y tercera etapa)

  • Familia grids declarativa en el core: { rule, emptyRule?, collection|singleton, shape?: { singleton, rowsField?, colsField? }, legend?: { rule, tileTarget, palField?, palMax? } } — valida filas de mapa/escena de ancho uniforme (autoconsistente contra la
    primera fila, o contra una forma fija externa como platform.rows/.cols vía shape) y
    resuelve cada símbolo de legend/fill contra tiles+paleta, sin ejecutar código de perfil.
  • 4 perfiles migrados (mismos rule-ids, cero cambio de comportamiento observable):
    adventure/dungeon (scene-rows/scene-dims/scene-legend-ref, autoconsistente) y
    monster-rpg/tower-defense (map-dims/map-legend-ref, forma fija vía platform) —
    la misma lógica estaba duplicada en JS en los 4.
  • refs[].target acepta agregado cross-colección: arrayField (+ itemField) además
    de collection — el set válido se junta escaneando un array anidado en TODAS las
    entradas de la colección, no solo Object.keys. Cubre "algún X entre N filas otorga el
    valor Y" como dato en vez de código a mano.
  • dungeon.warp-lock migrado: warp.locked exige un item que ALGÚN pickup, en
    CUALQUIER escena, otorgue — antes un Set armado a mano en ruleScenes, ahora una
    entrada declarativa de refs.
  • SPEC §6.1/§11 actualizado (grids + agregado cross-colección documentados; queda como
    "tercera etapa" de reglas puras-de-datos — lo que sigue en rules es lógica genuinamente
    no reducible a forma declarativa sin volverse un DSL). test/profile-descriptor.js cubre
    las formas nuevas del descriptor (31 chequeos, de 28). Suite sin regresiones: mismas 136
    reglas, 190 casos de conformidad, mutation audit 20/20.

Added — roguelike a lo grande: mecánicas por datos, un solo generador, mundo continuo

  • Mecánicas nuevas 100% data-driven en el perfil roguelike y su ejemplo:
    llaves y puertas cerradas (generator.lockChance/keyChance + tiles key/
    lockedDoor; cerraduras mutuas entre salas; la llave abre AMBOS lados de forma
    permanente), jefe custodiando el cofre (boss: tile/hp/damage — bloquea la
    victoria hasta caer), progresión por experiencia (progression.killsPerAtk/
    maxBonus: el ataque sube con las bajas) y permadeath declarativo
    (progression.permadeath). 3 reglas nuevas de perfil (generator-chance,
    boss-fields, progression-fields) → 136 reglas.
  • Solvencia por construcción: toda sala conserva ≥1 salida SIN cerrar, y como el
    cofre aparece donde exploras (generación perezosa), nunca queda tras una puerta
    cerrada — las llaves abren atajos y zonas extra. Verificado como invariante por BFS
    en npm test.
  • Un solo generador, dos motores POR CONSTRUCCIÓN: el visor 2D
    (examples/roguelike.html) deja de duplicar la generación y pasa a importar la
    misma lógica pura
    (game3d-logic.mjs) que usa game3d — renderer fino sobre
    funciones testeadas. build-standalone aprende a inlinear imports relativos de
    módulos ESM (+2 chequeos) y el standalone sigue autocontenido.
  • game3d, mazmorra en mundo continuo: las salas se añaden contiguas a la escena
    al explorar (comparten muro fronterizo, sin celdas duplicadas) y los pisos se
    apilan físicamente en vertical
    — la cámara viaja con el jugador. Minimapa 3D
    del grafo explorado (cubos por sala, pisos apilados, conexiones cerradas en rojo,
    escaleras en azul) renderizado en una segunda pasada. Guardado automático de la
    run en localStorage (rgSave/rgLoad puros y testeados; N = nueva partida; el
    guardado se limpia al ganar o caer en permadeath) y estadísticas de run en los
    overlays (salas, bajas, caídas, profundidad máxima).
  • +17 chequeos en npm test y CI (171 de lógica): solvencia por BFS, cerraduras
    y llaves generadas, unlock que abre ambos lados, jefe que bloquea/daña/cae,
    levelup con tope, permadeath → gameover, save/load ida y vuelta, y el bot
    explorador ONLINE que gana jugando
    (rutea por el grafo conocido, toma salidas
    inexploradas y derrota al jefe antes del cofre).
  • Verificado en navegador en ambos motores: el 2D con la lógica compartida
    (puerta cerrada/llave con los textos del GAME.md) y game3d con guardado +
    restauración tras recargar, nueva partida con N y victoria del explorador por
    eventos de teclado reales — misma firma de run que el test de Node (6 salas,
    1 baja, prof. 5): mismo mundo otra vez.
  • Nota: añadir tiradas al generador cambia los mundos respecto a v2.16.0 — la
    paridad garantizada es entre motores, no con releases anteriores.

v2.16.0 — visor advance-wars: los 14 perfiles con runtime

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 04:44

Release aditivo sobre 2.15.0 (bump minor, SPEC §7.0): el visor
advance-wars completa el tablero — los 14 perfiles del repo tienen runtime en
game3d
. Donde el perfil solo modela arte, el runtime no inventa gameplay: esa es la
tesis del protocolo aplicada hasta el final. La versión del protocolo sigue en 0.1.

Added — runtime advance-wars en game3d (visor): los 14 perfiles con runtime

  • Runtime advance-wars (14º y último perfil con runtime): visor 3D del arte
    extraído
    — desfile de las unidades 4bpp sobre la rejilla que declara platform
    (12×10), cámara orbital, cursor con flechas, Enter coge/suelta (recolocación con
    bloqueo por ocupación) e inspección en el HUD (nombre, dimensiones, paleta).
  • Honestidad por diseño: este perfil modela solo arte (PALETTES + UNITS; sus
    reglas son unit-dims/unit-palette-ref/unit-tiledata-range) — no hay vocabulario de
    gameplay (stats, daño, terreno, mapa), así que el runtime no inventa combate:
    gameplay as data significa que sin datos no hay gameplay (SPEC §8). El propio HUD
    lo dice. Si se quisiera batalla real, el camino es extender perfil+ejemplo con
    tokens de gameplay.
  • Lógica pura en game3d-logic.mjs (awDecode/awInit/awCursor/awAct,
    +16 chequeos en npm test y CI): decode 4bpp de las 4 unidades reales validado
    contra su paleta (color a color), errores en unidad inexistente/tileData roto,
    desfile dentro de la rejilla sin solapes, topes de cursor, coger/soltar con bloqueo.
  • Verificado en navegador: boot, coger en vacío bloqueado, inspección de
    INFANTRY, soltar sobre TANK bloqueado y recolocación a (0,0) — todo con eventos de
    teclado reales.
  • Con esto, los 14 perfiles del repo tienen runtime en game3d.

v2.15.0 — runtime roguelike en game3d

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 04:23

Release aditivo sobre 2.14.0 (bump minor, SPEC §7.0): el artefacto
roguelike ya generado se vuelve jugable en game3d con la generación portada tal
cual
del visor 2D — el mismo GAME.md produce el mismo mundo procedural en ambos
motores, verificado en vivo. La versión del protocolo sigue en 0.1.

Added — runtime roguelike en game3d

  • Runtime roguelike (13º perfil jugable): mazmorra procedural 3D — salas
    reconstruidas al cruzar puertas (misma planta) y escaleras ▲▼ (otro piso), enemigos
    patrullando, ítems y cofre como billboards del TILE_ART, parpadeo de
    invulnerabilidad, flechas + Espacio.
  • La generación es un PORT EXACTO del visor 2D (examples/roguelike.html): mismo
    mulberry32, mismo hash de coordenadas, mismas reglas de puertas/escaleras mutuas y
    cofre en la primera sala a profundidad ≥ maxDepth. El mismo GAME.md produce el
    mismo mundo en ambos motores
    — verificado en vivo: la ruta al cofre del test de
    Node y la del navegador coinciden sala a sala.
  • Lógica pura en game3d-logic.mjs (rgGenRoom/rgEnter/rgInit/rgMove/
    rgAttack/rgPatrol, +16 chequeos en npm test y CI): determinismo, invariantes
    por BFS sobre ~100 salas generadas (toda sala tiene salida; puertas y escaleras
    mutuas; cofre único a profundidad ≥ maxDepth), combate con hp del ENEMY_POOL,
    caída con respawn en el origen, pociones con tope y armas que solo mejoran
    (ITEM_POOL), y el cofre GANADO jugando movimiento a movimiento (BFS de salas +
    caminado real, 39 acciones).
  • Verificado jugando en navegador: bot por eventos de teclado reales hasta el
    overlay de victoria con el WIN.text del GAME.md.

v2.14.0 — runtime crafting en game3d

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 03:58

Release aditivo sobre 2.13.0 (bump minor, SPEC §7.0): el artefacto
crafting ya generado se vuelve jugable en game3d — meta derivada de los datos
(recetario completo), ganada y perdida en Node con conservación exacta por material.
La versión del protocolo sigue en 0.1.

Added — runtime crafting en game3d

  • Runtime crafting (12º perfil jugable): el artefacto ya generado corre en
    game3d sin tocar core ni datos — taller DOM (materiales con teclas 1..N, estación
    con M, recetas con A..Z coloreadas por disponibilidad, objetos e inventario) sobre
    fragua 3D (yunque y brasas que laten), overlays de victoria/derrota.
  • Lógica pura en game3d-logic.mjs (crInit/crGather/crMove/crCraft,
    +12 chequeos en npm test y CI): stack por MATERIALS, estación e inputs por
    RECIPES, valor por outputValue. Recetario completado y perdido en Node;
    conservación exacta por material (recolectado − consumido = inventario); craftear
    sin estación / en la equivocada / sin materiales → blocked; stack se detiene
    en el tope declarado.
  • Semántica del motor documentada (SPEC §8): la meta es completar el recetario
    (craftear cada receta ≥1 vez — derivada de los datos, sin números inventados) con
    presupuesto de CR_ACTIONS = 30 acciones; recolectar/moverse/craftear cuestan 1;
    derrota al agotarlas.
  • Verificado jugando en navegador: craft en vacío bloqueado, recolección por
    teclas, cambio de estación y recetario completo hasta el overlay de victoria
    (valor 90, 22 acciones sobrantes).

v2.13.0 — runtime platformer en game3d

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 03:49

Release aditivo sobre 2.12.0 (bump minor, SPEC §7.0): el artefacto
platformer ya generado se vuelve jugable en game3d — geometría procedural salvable
por construcción y verificada por test contra PHYSICS, con partida ganada por bot en
Node. La versión del protocolo sigue en 0.1.

Added — runtime platformer en game3d

  • Runtime platformer (11º perfil jugable): el artefacto ya generado corre en
    game3d sin tocar core ni datos — vista lateral 3D con cámara que sigue al jugador,
    suelo coloreado por tileset, enemigos por hp, bandera en goal.x, parpadeo de
    invulnerabilidad; ←/→ corre y Espacio/↑ salta (teclas mantenidas). Expone
    step()/held para pilotar desde harnesses.
  • Lógica pura en game3d-logic.mjs (pfJumpReach/pfLevelGeom/pfInit/pfTick,
    +16 chequeos en npm test y CI): física por ticks desde PHYSICS (gravity/jump/
    runSpeed), pisotón (KOOPA aguanta 2, hp desde ENEMIES), daño lateral con
    invulnerabilidad, caída al hueco con respawn, niveles encadenados hasta la victoria.
    Partida ganada por bot en Node (2 niveles) y perdida por contacto repetido.
  • Semántica del motor documentada (SPEC §8): los niveles no declaran geometría, así
    que el suelo son segmentos con huecos por LCG determinista salvables por
    construcción
    — y el test lo verifica contra PHYSICS: hueco máximo ≤ 60% del
    alcance de salto derivado (12.2 unidades con los datos del ejemplo).
  • Verificado jugando en navegador: partida completa pilotando las teclas
    mantenidas del propio runtime hasta el overlay con el TEXT.win del GAME.md.

v2.12.0 — runtime tower-defense en game3d

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 03:39

Release aditivo sobre 2.11.0 (bump minor, SPEC §7.0): el artefacto
tower-defense ya generado se vuelve jugable en game3d — simulación por ticks sin
azar, ganada y perdida en Node, con tablero 3D completo. La versión del protocolo
sigue en 0.1.

Added — runtime tower-defense en game3d

  • Runtime tower-defense (10º perfil jugable): el artefacto ya generado corre en
    game3d sin tocar core ni datos — tablero 3D completo (rejilla 12×8, camino, torres
    como cilindros por tipo, enemigos como esferas por blindaje), cursor con flechas,
    construir con 1..N, vender con S (a sellRatio), oleadas con Espacio, overlays de
    victoria/derrota. El runtime expone step() para pilotar ticks desde harnesses.
  • Lógica pura en game3d-logic.mjs (tdPath/tdPos/tdInit/tdBuild/tdSell/
    tdStartWave/tdTick, +11 chequeos en npm test y CI): simulación por ticks sin
    azar
    (spawns por count/gap, targeting al enemigo más avanzado en rango, daño por
    DMG_CHART[dmgType][armor]). Partida ganada y perdida en Node: 4 rifles
    centrales superan las 2 oleadas (15/15 abatidos, 0 fugas) y sin torres se pierde;
    conservación verificada en cada tick (aparecidos = muertos + fugados + vivos);
    venta a floor(cost·sellRatio); construir sobre el camino o sin oro → blocked.
  • Semántica del motor documentada (SPEC §8): el ejemplo no declara MAPS, así que el
    camino es una ruta en S fija sobre 12×8; 30 ticks ≈ 1 s (speed = celdas/s, rate =
    disparos/s, gap en ticks); recompensa y luego interés al limpiar la oleada.
  • Verificado jugando en navegador: torres construidas con teclado real, intento
    ilegal sobre el camino rechazado, 2 oleadas pilotando step() hasta el overlay de
    victoria (oro final 186, vidas 20/20).

v2.11.0 — runtime papers-please en game3d

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 03:30

Release aditivo sobre 2.10.0 (bump minor, SPEC §7.0): el artefacto
papers-please ya generado se vuelve jugable en game3d — sin tocar core ni datos, con
la evaluación por RULES verificada contra las decisiones declaradas del ejemplo. La
versión del protocolo sigue en 0.1.

Added — runtime papers-please en game3d

  • Runtime papers-please (9º perfil jugable): el artefacto ya generado
    (examples/papers-please.generated.js) corre en game3d sin tocar core ni datos —
    ventanilla DOM (documentos del solicitante como fichas) sobre fondo 3D (muro
    fronterizo y barrera que se alza al aprobar), teclas A/D, cita de la regla violada
    en cada veredicto, renta al cierre del día y overlays de victoria/despido.
  • Lógica pura en game3d-logic.mjs (ppEval/ppInit/ppEntrant/ppDecide,
    +14 chequeos en npm test y CI): los 4 tipos de regla (require-document,
    ban-country, require-field-match, not-expired) evaluados desde datos. Oráculo de
    autoría
    : la evaluación por RULES reproduce la decision declarada de los 4
    solicitantes. Partida completa ganada y perdida en Node con contabilidad
    verificada (money = aciertos×salary − fallos×penaltyFee − días×rent).
  • Semántica del motor documentada (SPEC §8): fecha de corte PP_TODAY = 1983.01
    para not-expired, derrota al 3er error, money como marcador (puede ser negativo).
  • Verificado jugando en navegador: turno completo con error deliberado (multa),
    cita de regla, renta por día y overlay de victoria con la contabilidad exacta.

v2.10.0 — Senku (peg-solitaire) + sudoku, ambos puro-datos

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 01:44

Release aditivo sobre 2.9.0 (bump minor, SPEC §7.0): dos géneros
nuevos de punta a punta sin tocar el core — el Senku real (perfil puro-datos
peg-solitaire, tableros solubles por construcción, soluciones rejugadas en npm test)
y el perfil sudoku, nacido de un malentendido del nombre y conservado como género
propio. La versión del protocolo sigue en 0.1.

Added — perfil peg-solitaire (puro-datos) + Senku

  • profiles/peg-solitaire.json (14º perfil, cuarto puro-datos): senku/solitario de
    clavijas — tableros como 7 filas de 7 caracteres (_ fuera, o peg, . hueco),
    goal por enum (clear = dejar 1 peg | center = dejarlo en el centro),
    difficulty por enum y player.start por broken-ref. Límite documentado: la forma
    7×7 y el alfabeto de los strings no caben en las familias declarativas (dims exige
    matrices de arrays) — los valida pegCheck en la simulación y en npm test (tercer
    caso para SPEC §11: validadores de patrón/longitud de string).
  • examples/senku.GAME.md (+ generated): 3 tableros solubles por construcción
    — B1 y B2 generados por movimientos inversos desde un único peg (LCG determinista),
    B3 es el inglés clásico (32 pegs, hueco central, goal center) resuelto por el solver
    DFS del generador en 4 ms. Ni una celda escrita a mano. Lint 0/0 a la primera.
  • Lógica pura en game3d-logic.mjs (pegCheck/pegInit/pegMoves/pegMove,
    +21 chequeos en npm test y CI): los 3 tableros reales validados y sus soluciones
    rejugadas hasta la victoria
    (B3: 31 saltos con el último peg en el centro),
    conservación (pegs = iniciales − saltos en cada paso), saltos ilegales bloqueados,
    derrota por bloqueo y derrota específica de goal: center.
  • Runtime peg-solitaire en game3d (8º perfil jugable): tablero DOM 7×7 sobre
    fondo 3D, flechas + Enter/Espacio (elegir peg y saltar) + Escape, overlays de
    victoria/derrota. Verificado jugando en navegador.

Added — perfil sudoku (puro-datos) + Sudoku

  • Nacido de una interpretación errónea de «senku» (es el solitario de clavijas, no el
    sudoku); el trabajo quedó completo y verificado, así que se conserva como perfil
    propio con el juego renombrado a examples/sudoku.GAME.md.
  • profiles/sudoku.json (13º perfil, tercer puro-datos): puzzles como strings de
    81 caracteres (grid con . + solution), difficulty por enum, player.start
    por broken-ref y balance (lives/hints). Límite documentado: longitud/patrón de los
    strings y la consistencia grid↔solution no caben en las familias declarativas
    las valida sudokuCheck en la simulación de referencia y en npm test (segundo caso
    concreto para SPEC §11: validadores de patrón/longitud de string).
  • examples/sudoku.GAME.md (+ generated): 3 puzzles generados por script con
    verificación de unicidad
    (backtracking + conteo de soluciones; easy 40 / normal 32
    / hard 27 pistas) — ni un dígito escrito a mano. Lint 0/0 a la primera.
  • Lógica pura en game3d-logic.mjs (sudokuCheck/sudokuInit/sudokuSet/
    sudokuHint, +14 chequeos en npm test y CI): los 3 puzzles reales validados
    (consistencia + validez por filas/columnas/cajas), victoria rellenando la solución,
    derrota al agotar vidas, pistas dadas inmutables, hint con descuento.
  • Runtime sudoku en game3d (7º perfil jugable): tablero DOM 9×9 sobre fondo 3D,
    flechas + dígitos + H para pista, overlays de victoria/derrota. Verificado jugando
    en navegador
    : pista inmutable, fallo que descuenta vida, hint, y tablero resuelto
    hasta el overlay de victoria.
  • README: 128 → 133 reglas (reconteo por script tras ambos perfiles).

v2.9.0 — shooter: perfil puro-datos + Neon Swarm + simulación testeada en Node

Choose a tag to compare

@MauricioPerera MauricioPerera released this 08 Jul 01:10

Release aditivo sobre 2.8.1 (bump minor según SPEC §7.0): un género nuevo de punta a punta sin tocar el core — la tesis del protocolo, ejecutada otra vez, ahora con simulación verificable. La versión del protocolo sigue en 0.1.

Added — shooter: perfil puro-datos + Neon Swarm + simulación testeada + runtime

  • profiles/shooter.json (12º perfil, segundo puro-datos): arena shmup vertical — ships, weapons, enemies con behavior (enum chaser/drifter), waves, powerups (heal/rapid/shield), arena continua y balance. 4 refs con mensajes por defecto, 14 bounds, 2 enums — cero funciones, dataOnly: true. Límite documentado: bounds no alcanza campos dentro de arrays (spawns[].count/gap — primer caso concreto para los "agregados anidados" de SPEC §11).
  • Neon Swarm: 2 naves, 2 armas, 4 enemigos, 5 oleadas, 3 powerups. Lint 0/0 a la primera.
  • Simulación pura (shooterInit/shooterTick + LCG en game3d-logic.mjs): determinista, un tick = un frame — el juego entero se gana y se pierde en Node dentro de npm test (+9 chequeos): victoria de la IA sobre las 5 oleadas, derrota sin input, invariante de conservación kills+leaked+lost == spawns (que cazó un hueco de contabilidad real al escribirlo), rapid a mitad de cooldown, shield y heal con tope.
  • Runtime shooter en game3d: render Three.js de la simulación (input mantenido, HUD, overlays). Verificado además sobre el estado vivo del navegador: victoria con 920 pts y conservación exacta (46+5+4=55). Nota operativa: el RAF pausa en pestañas ocultas — los harnesses pilotan los ticks directamente.
  • Conformance 179 casos (+13), 16 pares de ejemplos, 12 hints nuevos, 128 reglas, 12 perfiles; footer de index y nota SPEC §6 sin enumeraciones (principio anti-drift).

Changelog completo: CHANGELOG.md