CONCEPTOS

El modelo Event-Sourcing

ChainMemory sigue una arquitectura event-sourcing. Entender este patrón es clave para entender todo el sistema.

En sistemas tradicionales, guardás el estado actual y lo sobreescribís en cada cambio. En event-sourcing, guardás cada cambio como un evento inmutable, y el estado actual se deriva reproduciendo esos eventos.

En ChainMemory:

  • Las memorias son eventos — Cada memoria es un registro inmutable de algo que pasó: se tomó una decisión, se identificó un riesgo, se eligió una tecnología, se alcanzó un hito.
  • El Project State es una vista construida a partir de esos eventos — Un cliente lee las memorias y propone operaciones que las citan; el servidor las valida, las aplica y guarda cada versión resultante. El estado no se recalcula solo desde el log: cambia únicamente cuando un cliente consolida.
  • El anclaje es la prueba de existencia — Cuando un Project State se ancla on-chain, la blockchain certifica que esta vista materializada específica existía en ese block height exacto.
Patrón
Memoria #1 (evento) ─┐
Memoria #2 (evento) ─┤
Memoria #3 (evento) ─┼──→ ops de un cliente ──→ Project State v1 ──→ Anchor (bloque 120000)
Memoria #4 (evento) ─┤
Memoria #5 (evento) ─┘

Memoria #6 (evento) ─┐
Memoria #7 (evento) ─┼──→ ops de un cliente ──→ Project State v2 ──→ Anchor (bloque 123539)
Memoria #8 (evento) ─┘

Las memorias son la fuente de verdad y no cambian. Cada versión del estado registra en qué memorias se apoyó, así que cualquier ítem se puede rastrear hasta su evidencia. El anchor prueba qué estado existía en qué bloque.

Por qué importa Event-sourcing garantiza trazabilidad completa. Cada decisión en tu Project State se puede rastrear hasta la conversación específica donde se originó. Nada se pierde, nada se sobreescribe, y el historial siempre está disponible.

Qué es una memoria

Una memoria es la unidad fundamental de ChainMemory. Es un fragmento de información extraído de una conversación con IA que se considera valioso para el futuro del proyecto.

Cada memoria contiene:

  • Contenido — El texto de la conversación o nota
  • Hash — SHA-256 del contenido, inmutable
  • Proyecto — A qué proyecto pertenece
  • Tags — Etiquetas libres para organización (decisión, bug, arquitectura, idea, etc.). Los tags son para tu uso — el Project State tiene sus propios campos fijos (ver Project State)
  • Número — Secuencial dentro de tu cuenta (#1, #2...)
  • Fuente — Desde dónde se guardó (extensión, MCP, API)
  • Timestamp — Momento exacto de creación

Proyectos

Un proyecto agrupa memorias relacionadas. Cada proyecto tiene su propia línea de tiempo, estado consolidado, y ancla on-chain independiente.

Ejemplos de proyectos: mi-saas, tesis-ml, chainmemory, app-mobile.

Project State

El Project State (también llamado Project Brain) es la vista consolidada y versionada de un proyecto. No lo genera un motor en el servidor: un cliente — un modelo de IA que trabaja con update_project_state (MCP) o POST /v1/project/:name/state/ops (API) — propone operaciones, el servidor las valida contra una gramática cerrada, las aplica con un constructor determinístico y calcula el nuevo state_hash. Cada ítem registra las memorias que lo justifican.

Qué contiene el estado (versión de esquema 2)

CampoQué guardaValores cerrados
vision, phase, current_focusHacia dónde va el proyecto, en qué etapa está y qué importa ahora—
decisionsDecisiones con título, enunciado y estadostatus: proposed, confirmed, rejected, superseded
milestonesEntregablesstatus: planned, in_progress, done
risksAmenazas identificadasseverity: low, med, high — no medium ni critical; status: open, mitigated, closed
prioritiesTrabajo ordenado con un priority_score, vinculado a los riesgos que mitiga (mitigates)status: active, done, dropped
open_questionsPreguntas y, cuando se resuelven, su respuesta—
assumptions, constraintsLo que el proyecto da por supuesto y las reglas que debe respetar—
vocabulary, metricsTérminos compartidos y valores con nombre—
environmentHosts, servicios, repositorios y reglas de operación—
state_metaVersión, marca consolidated_until_event y previous_state_hash—
Conjuntos de valores cerrados Un valor fuera de estos conjuntos hace que la operación se rechace. El error más común es "severity": "medium": el motor solo acepta low, med o high.
Dos formas de leerlo El estado completo es JSON estructurado con cada id, su evidencia y su historia: get_project_state (MCP) o GET /v1/project/:name/state, y es lo que lee un cliente antes de proponer operaciones. El resumen (brief) es el mismo estado escrito como texto por relevancia y dentro de un presupuesto de caracteres, para orientarse o para trabajar en una prioridad: get_project_brief (MCP), GET /v1/project/:name/inject (API) y el botón Project Brain de la extensión. El resumen es público por defecto: las direcciones, puertos, rutas de servidor y reglas de seguridad se reservan.

Ciclo de vida del estado

El estado es incremental y append-only: cada consolidación parte de la versión anterior y aplica solo las operaciones nuevas. Cada versión lleva su state_hash (SHA3-256 del estado canónico, con separador de dominio CM_PROJECT_STATE_V<schema_version>) y, en state_meta, el hash de la versión anterior. Una vez escrita, el hash de la versión se ancla on-chain en el contrato ProjectStateAnchor, normalmente en menos de diez minutos.

Cadena de versiones
v85 ──previous_state_hash──▶ v86 ──previous_state_hash──▶ v87
 │                            │                            │
 └─ anchorId 89               └─ anchorId 90               └─ anchorId 94

Ejemplo: lo que devuelve GET /v1/project/:name/state (recortado)

JSON
{
  "project": "sistema-pagos",
  "schema_version": 2,
  "version": 4,
  "state_hash": "0x3f8c2a…e91d",
  "generated_at": "2026-09-13T22:02:35.000Z",
  "anchor": { "status": "anchored", "onchain_anchor_id": 12, "tx_hash": "0x…", "block_number": 681919 },
  "state": {
    "phase": "beta",
    "current_focus": "Revisión PCI antes de abrir a los primeros tenants",
    "decisions": [
      { "id": "dec_0002", "title": "PostgreSQL con RLS para multi-tenancy",
        "statement": "La seguridad por fila saca el filtrado por tenant de la capa de aplicación",
        "status": "confirmed", "superseded_by": null,
        "evidence_root": "0x9a41…c07e", "created_version": 2, "updated_version": 3 }
    ],
    "milestones": [
      { "id": "mil_0001", "title": "Schema de BD", "status": "done",
        "evidence_root": "0x5b2d…81fa", "created_version": 1, "updated_version": 2 }
    ],
    "risks": [
      { "id": "risk_0001", "title": "Performance de RLS con 100K tenants", "severity": "med", "status": "open",
        "evidence_root": "0xd7e0…2a19", "created_version": 3, "updated_version": 3 }
    ],
    "state_meta": { "version": 4, "consolidated_until_event": 150, "previous_state_hash": "0x7b2e…f4c0" }
  }
}

GET /v1/project/:name/state requiere la API key del dueño y siempre devuelve la versión más reciente. Las versiones anteriores se pueden verificar por hash (ver Hash y verificación), no volver a leer completas con este endpoint.

Buenas prácticas

  • Primero guardá la memoria, después consolidá — el estado cita memorias; una decisión que solo existe en la operación no tiene respaldo
  • Esperá el anclaje antes de citar — una memoria en texto plano recibe su event_hash al sincronizarse con la cadena, unos 30 segundos después de escribirla
  • Avanzá la marca — enviá consolidated_until_event con el número de memoria más alto que realmente revisaste
  • Reemplazá, no reescribas — una decisión reemplazada queda en el estado con su estado cambiado, así se conserva cómo evolucionó el proyecto
Estado multi-agente Varios agentes pueden consolidar el mismo proyecto, cada uno desde su cliente. Sus operaciones terminan en un único estado; las memorias citadas en cada ítem muestran qué agente aportó la evidencia. Ver Sistemas Multi-Agente.

Cadena de evidencia

Cuando un cliente propone una operación, cita las memorias que la respaldan en evidence_memory_ids — un array de números de memoria. El servidor resuelve cada una a su event_hash y guarda en el ítem resultante la raíz Merkle de esos hashes como evidence_root.

Operación que envía el cliente
{
  "op": "add_decision",
  "title": "Usar consenso Clique PoA",
  "statement": "Proof of Authority da un anclaje rápido y económico para una cadena soberana",
  "evidence_memory_ids": [12, 45, 67]
}
Ítem guardado en el estado
{
  "id": "dec_0001",
  "title": "Usar consenso Clique PoA",
  "statement": "Proof of Authority da un anclaje rápido y económico para una cadena soberana",
  "status": "proposed",
  "evidence_root": "0x028218d0…f082"
}

Esto crea una cadena de procedencia:

  • La decisión dec_0001 existe porque las memorias 12, 45 y 67 la respaldan; la respuesta de la consolidación lista sus event hashes
  • El event_hash de cada memoria se escribe on-chain cuando la memoria se sincroniza
  • El evidence_root compromete exactamente ese conjunto de hashes
  • El estado que contiene el ítem tiene un state_hash anclado en ProjectStateAnchor
La evidencia que no se puede resolver se rechaza, no se ignora Si alguna memoria citada no existe, no es tuya o todavía no está anclada, se rechaza la llamada entera con 422 evidence_unresolved, y no se escribe ni se cobra nada. Una operación que no cita nada se acepta, pero se guarda con evidence_root 0x000…0: estado sin procedencia. La cadena lo sella igual, porque verifica hashes, no que el contenido sea correcto.

Resolución de conflictos

Nada resuelve contradicciones automáticamente. No hay un motor que lea las memorias y decida cuál gana: decide el cliente que consolida, y la gramática hace que esa decisión quede explícita y auditable.

Reemplazar una decisión

Si una memoria más nueva cambia el rumbo, el cliente agrega la decisión nueva y marca la anterior con supersede_decision (id de la anterior, by_id de la nueva). Las dos quedan en el estado.

Estado de una decisión

Una decisión se crea como proposed. El cliente la pasa a confirmed o rejected con set_decision_status, y a superseded con supersede_decision.

Varios agentes en el mismo proyecto

Las operaciones se aplican sobre la versión vigente en el momento en que llega la llamada; /state/ops no comprueba una versión esperada. No se pierde nada — cada llamada crea una versión nueva — pero un agente que trabaja con una lectura vieja puede volver a agregar o contradecir lo que otro acaba de escribir. Leé el estado justo antes de consolidar. Cada llamada acepta hasta 100 operaciones.

Sin pérdida de datos Las decisiones reemplazadas o rechazadas nunca se eliminan. Quedan en el Project State con su estado cambiado, conservando cómo evolucionó la dirección del proyecto.

Gobernanza del estado

El ciclo de vida del Project State está gobernado por reglas claras:

Quién puede consolidar?

Solo el dueño del proyecto (la cuenta que lo creó) puede disparar una consolidación. Esto asegura que la extracción de conocimiento estructurado siempre esté controlada por el dueño de los datos.

Cuándo ocurre la consolidación?

  • La dispara el cliente — un modelo de IA propone operaciones vía update_project_state (MCP) o POST /v1/project/:name/state/ops (API). El servidor las valida y recién entonces se vuelven estado
  • No hay disparador automático — la consolidación nunca ocurre sola. Nada se escribe en tu estado si un cliente no lo propone

Se puede revertir?

Cada consolidación crea una nueva versión (v1, v2, v3...). Las versiones anteriores siguen accesibles. No podés borrar una versión, pero siempre podés consolidar de nuevo para producir un estado corregido. La cadena de versiones es append-only.

Snapshots

Cada versión del Project State es un snapshot. La combinación de número de versión + state_hash + ancla on-chain crea un checkpoint verificable. El dueño lee la versión más reciente con GET /v1/project/:name/state; el hash y el ancla on-chain de cualquier versión anterior son públicos en GET /v1/project/:name/state/anchor?version=2 y GET /v1/verify/:name.

AcciónQuiénCuándoReversible
ConsolidarDueño del proyectoSolo cuando un cliente propone operacionesSe crea nueva versión (append-only)
Anclar on-chainAutomático (wallet del operador)En ~10 minutos tras cada consolidaciónInmutable una vez anclado
Archivar memoriaDueño del proyectoCualquier momentoSe puede desarchivar
Leer el estado más recienteDueño del proyecto (API key)Cualquier momentoN/A (solo lectura)
Verificar el hash de cualquier versiónCualquiera (endpoint público)Cualquier momentoN/A (solo lectura)

Hash y verificación

Cada memoria genera un hash SHA-256 de su contenido. Este hash es la huella digital única e inmutable de esa memoria. El contenido no se puede modificar sin cambiar el hash.

El state hash es un hash del estado consolidado completo (todas las decisiones, hitos, riesgos, etc.). Este state hash se ancla en la blockchain mediante una transacción en el contrato ProjectStateAnchor.

Verificación pública

La verificación en ChainMemory es pública y sin permisos. Cualquier persona puede:

  1. Llamar a GET /v1/project/:name/state/anchor (no requiere API key)
  2. Obtener el state_hash y el tx_hash de la transacción
  3. Verificar en el explorer que la transacción existe
  4. Leer el contrato directamente en la blockchain para confirmar que el hash coincide

Esto demuestra que el estado del proyecto existía exactamente así en el momento del anclaje. No se puede falsificar retroactivamente.

Modelo de privacidad

Una preocupación común con sistemas basados en blockchain es la exposición de datos. ChainMemory aborda esto con una separación estricta:

Principio crítico El texto plano de una memoria nunca va on-chain. Lo que se escribe on-chain es su texto cifrado AES-256-GCM junto con los hashes de estado — y sin la llave del dueño nada de eso se puede leer.

Qué se guarda dónde

DatoUbicaciónAcceso
Contenido de memoriaBase de datos encriptada (off-chain) y texto cifrado AES-256-GCM on-chainTexto plano: solo el dueño. Texto cifrado: público pero ilegible sin la llave
Hash de memoria (SHA-256)Base de datos + on-chain cuando la memoria se sincroniza (~30 s)El hash es público pero no revela nada del contenido
Project State (estructurado)Base de datos (off-chain)Solo el dueño
State hashBlockchain (on-chain)Público — esta es la prueba verificable
Metadata del anchor (tx, bloque)Blockchain (on-chain)Público

Un ancla de estado contiene solo el identificador del proyecto hasheado, el número de versión, el hash del estado y un timestamp. Una transacción de memoria lleva además el contenido cifrado más su categoría, importancia y largo del texto plano. Desde cualquiera de las dos es imposible reconstruir el contenido sin la llave del dueño.

Este diseño significa que ChainMemory puede proveer verificación criptográfica sin comprometer la privacidad. La blockchain prueba que un estado existió, no qué contenía.