25.6 KB · updated 2026-07-06 · md

v0.2.0.es.md

docs/i18n/release-notes/v0.2.0.es.md

Tesserae v0.2.0 — Recuperación tipada, grafo de código, evolución de ontología

<!-- translations:start -->

English · 한국어 · 中文 · 日本語 · Русский · Français · Deutsch

<!-- translations:end -->

Publicado el 2026-05-21 · PyPI · Versión en GitHub · pip install --upgrade tesserae

Tesserae 0.2.0 es la primera versión con nuevas funcionalidades sobre la línea v0.1.0 y entrega seis funcionalidades aditivas sin cambios disruptivos. La versión lleva la superficie de recuperación de Tesserae desde "BM25 sobre un grafo tipado" hasta un recuperador híbrido al estilo HippoRAG 2 con expansión de semillas mediante Personalized PageRank (PageRank personalizado), sienta las bases para un enfoque de código-como-grafo que conecta los hallazgos en prosa con los símbolos del código fuente, y añade dos pases de evolución de la ontología (resúmenes de comunidades y decaimiento de memoria) más un informe de deriva de esquema. Las funcionalidades se corresponden con tres puntos en el flujo de trabajo del usuario: mejor recall en tiempo de consulta (graph_ppr, búsqueda híbrida con search_nodes), nodos más ricos en tiempo de compilación (ingest-code, resúmenes de comunidades, decay/supersedes), y un ciclo de iteración más rápido sobre la propia ontología (schema-drift).

Tabla de contenidos:

  1. MD0 — Personalized PageRank sobre el grafo tipado
  2. MD0 híbrido — BM25 + léxico + embedding mediante RRF
  3. MD0 — AST de Python → grafo de código tipado
  4. Resúmenes de comunidades — Louvain + LLM (opcional)
  5. Puntuación de decaimiento + MD0 + MD1
  6. MD0 — propuestas de enums mediante EDC
  7. Actualización desde v0.1.0
  8. Contexto estratégico

1. graph_ppr — Personalized PageRank sobre el grafo tipado

Qué es

Una nueva herramienta MCP que ejecuta Personalized PageRank (PPR) sembrado en uno o más IDs de nodo y devuelve los top-k nodos más relevantes por masa de distribución estacionaria. El paseo es consciente del tipo: las aristas se ponderan según su tipo de relación, y el perfil por defecto da mayor peso a los cuatro tipos de aristas que portan la señal más "real" en un grafo de Tesserae — derived_from_session, discussed_in, references y supersedes. Es la misma primitiva de expansión multi-salto de semillas usada por HippoRAG 2, pero adaptada a las aristas tipadas de Tesserae en lugar de a un grafo de co-ocurrencia a nivel de pasaje.

Concretamente, graph_ppr responde a la pregunta "¿cuál es el vecindario de este nodo, ponderado por las relaciones que realmente me importan?" de un modo que un BFS simple o BM25 no pueden. Una semilla Decision traerá las sesiones que la produjeron, las preguntas que respondió, los documentos a los que reemplazó y los conceptos sobre los que esos documentos hablaron — incluso si ninguno de esos nodos menciona las mismas palabras clave.

Cómo usarla

La herramienta se registra automáticamente al iniciar el servidor MCP de Tesserae. Desde cualquier cliente MCP:

// Semilla en un único nodo, α=0.15 por defecto, top-10 como resultado
{
  "tool": "graph_ppr",
  "arguments": {
    "seed_node_id": "decision-2026-05-12-switch-to-hybrid-retrieval",
    "top_k": 10
  }
}

// Semilla en múltiples nodos (un "clúster de conceptos"), α y pesos de aristas personalizados
{
  "tool": "graph_ppr",
  "arguments": {
    "seed_node_ids": ["concept-rrf", "concept-bm25", "concept-embedding-fusion"],
    "top_k": 25,
    "alpha": 0.2,
    "edge_type_weights": {
      "derived_from_session": 3.0,
      "discussed_in": 2.0,
      "references": 1.5,
      "supersedes": 1.5
    }
  }
}

La herramienta devuelve un arreglo de registros {node_id, score, kind, title} ordenados por masa estacionaria. Desde una sesión de Claude Code, basta con pedir al agente "usa graph_ppr sembrado en <node> con top-k 15" y la skill using-tesserae enrutará la llamada.

Cuándo usarla

Recurra a graph_ppr cuando:

  • Tenga un nodo bien identificado (una decisión, un artículo, un hallazgo de sesión) y necesite su vecindario en términos de distancia en el grafo, no sus hermanos coincidentes por palabras clave.
  • Quiera recall multi-salto — p. ej., "todo lo que esté a dos o tres relaciones de distancia de este concepto, sesgado hacia hallazgos derivados de sesiones".
  • search_nodes simple devuelve el nodo correcto pero su contexto vinculado por references resulta demasiado estrecho.

Para una consulta de texto libre que parta de una frase, prefiera search_nodes híbrido (funcionalidad 2); para recuperar el contexto textual de un nodo conocido, prefiera node_context.

Dónde vive

Implementación principal: MD0. Registro de la herramienta: tesserae/mcp_server.py.

Advertencias

  • El α=0.15 por defecto (probabilidad de reinicio) y el tope de 50 iteraciones están ajustados para grafos en el rango de 5k–50k nodos, típico de la memoria de un proyecto. Grafos muy grandes (>250k nodos) pueden requerir un α menor y una inicialización consciente del grado de los nodos; eso queda como seguimiento.
  • Los pesos de las aristas se aplican simétricamente; aún no se expone un perfil asimétrico (p. ej., ponderar references de forma distinta a su inversa).
  • La implementación es Python puro y no añade nuevas dependencias en tiempo de ejecución; si tiene un bucle activo llamando a graph_ppr miles de veces en una sola sesión, considere cachear la matriz columna-estocástica entre llamadas.

2. search_nodes híbrido — BM25 + léxico + embedding mediante RRF

Qué es

La herramienta MCP existente search_nodes incorporó un parámetro mode y un recuperador fusionado por debajo. El nuevo valor por defecto, mode="hybrid", ejecuta tres recuperadores en paralelo — BM25 (la base de v0.1.0), léxico (solapamiento de tokens / subcadena) y embedding (similitud semántica) — y los fusiona mediante Reciprocal Rank Fusion (RRF(d) = Σ 1/(k + rank_i(d)), k=60, la constante de Cormack et al. 2009). Es la misma receta de fusión empleada por la búsqueda local de Microsoft GraphRAG y por el modo híbrido de LightRAG.

El parámetro mode acepta:

ModoRecuperadores usados
hybrid (por defecto)BM25 + léxico + embedding, fusionados por RRF
lexicalSolo léxico
bm25Solo BM25
embeddingSolo embedding
legacyEl ranking exacto de v0.1.0 — preservado bit a bit

El backend de embeddings autodetecta en este orden: si sentence-transformers es importable, carga sentence-transformers/all-MiniLM-L6-v2 (384-dim, ~80MB, licencia MIT, sin llamadas de red tras la primera descarga). Si no, recurre a una proyección determinista de hash-bucket — utilizable, sin dependencias y reproducible, pero con menor recall semántico.

Una nueva herramienta MCP complementaria, embedding_status, informa qué backend está activo, de modo que pueda confirmar si sus puntuaciones híbridas se benefician de embeddings reales o están funcionando sobre el fallback de hash-bucket.

Cómo usarla

// Nuevo valor por defecto — fusionado, devuelve top 10
{
  "tool": "search_nodes",
  "arguments": { "query": "RRF fusion constant choice", "top_k": 10 }
}

// Forzar un único recuperador para una ablación
{ "tool": "search_nodes", "arguments": { "query": "RRF fusion", "mode": "bm25" } }

// Volver al comportamiento de v0.1.0 bit a bit
{ "tool": "search_nodes", "arguments": { "query": "RRF fusion", "mode": "legacy" } }

// Comprobar qué backend de embeddings está activo
{ "tool": "embedding_status", "arguments": {} }

Para obtener el backend real de sentence-transformers en lugar del fallback de hash-bucket:

pip install 'sentence-transformers>=2.7'
# La primera llamada descarga los pesos de MiniLM (~80MB) al caché de HF; las llamadas posteriores son offline.

Cuándo usar cada modo

  • hybrid para todo por defecto. RRF es robusto frente a que un recuperador devuelva basura, porque el amortiguamiento por rango-recíproco acota la contribución de cualquier recuperador individual.
  • bm25 cuando la consulta es esencialmente una etiqueta o un slug estructural (concept-rrf, decision-2026-05-12-…) — la coincidencia exacta domina y los embeddings añaden ruido.
  • embedding cuando la consulta es una paráfrasis o una pregunta y los nodos coincidentes usan un vocabulario muy distinto.
  • legacy para ablaciones contra una línea base de v0.1.0, o como vía de escape si aparece alguna regresión puntual.

Dónde vive

Implementación principal: MD0.

Advertencias

  • El fallback de hash-bucket es reproducible pero tiene un recall semántico limitado en paráfrasis — embedding_status hace visible la elección.
  • La constante RRF actual está fijada en 60; hacerla configurable por llamada es un seguimiento pequeño si desea probar otros valores.
  • El cacheo de embeddings es por proceso; un almacén persistente de embeddings (Lance/SQLite-vec) es un candidato a futuro para v0.3.

3. tesserae project ingest-code — AST de Python → grafo de código tipado

Qué es

Un nuevo subcomando de la CLI que recorre un repositorio Python usando el módulo ast de la biblioteca estándar y acuña cinco tipos de nodos y cinco tipos de aristas:

NodosAristas
CODE_FILE, CODE_MODULE, CODE_CLASS, CODE_FUNCTION, CODE_METHODcontains, calls, imports, inherits_from, declared_in

El resultado se persiste en .tesserae/code-graph.json y es ingerido por el siguiente tesserae project compile, de modo que los símbolos de código se convierten en nodos de primera clase del grafo a los que puede enlazar desde prosa, buscar mediante search_nodes, expandir mediante graph_ppr y visualizar junto a conceptos y artículos. Esto sienta las bases para vincular decisiones con los símbolos que las implementaron — un nicho que ninguna otra herramienta PKM-AI cubre actualmente.

Cómo usarla

# Desde un proyecto Tesserae activado
tesserae project ingest-code

# O contra una raíz arbitraria
tesserae project ingest-code --root ./my-package

# Luego un compile normal recoge el nuevo code-graph.json
tesserae project compile

Tras el siguiente compile, los nodos de código se vuelven buscables:

tesserae ask "Where is the RRF fusion implemented?"

…y el agente puede caminar desde un nodo Decision en prosa hasta la CODE_FUNCTION que la implementa a través de las aristas references / declared_in.

Cuándo usarla

  • Quiere que las decisiones y los hallazgos se enlacen a los símbolos reales de los que tratan, no solo al README que menciona esos símbolos.
  • Quiere recuperación consciente del código sin montar un índice de búsqueda de código separado — las mismas herramientas search_nodes + graph_ppr cubren ahora prosa y código.
  • Está usando la integración Understand-Anything pero quiere un grafo de código más ligero, sin dependencias, que viva en el grafo principal de Tesserae en vez de en un JSON adyacente.

Dónde vive

Implementación principal: MD0.

Advertencias

  • Solo Python en v0.2.0. El extractor está estructurado para añadir más adelante walkers por lenguaje; TypeScript / Rust / Go están en la hoja de ruta de v0.3.
  • Las aristas calls se resuelven por búsqueda de nombre dentro del ámbito del propio módulo; la resolución de llamadas entre módulos usa los alias de import pero no realiza inferencia de tipos completa. Espere una tasa moderada de falsos positivos en nombres muy sobrecargados — adecuado para recuperación, no para refactorización.
  • Los decoradores se registran como atributos del nodo decorado pero (todavía) no acuñan su propio tipo de arista.

4. Resúmenes de comunidades — Louvain + LLM (opcional)

Qué es

Un pase post-compile opcional que ejecuta detección de comunidades Louvain sobre el grafo tipado y luego pide al LLM que produzca un resumen de un párrafo por cada comunidad de tamaño ≥ 4. Cada resumen se materializa como un nodo COMMUNITY_SUMMARY, enlazado a sus miembros por aristas summarizes, y se cachea por el SHA de la lista de IDs de miembros, de modo que un re-compile solo vuelve a resumir las comunidades cuya pertenencia haya cambiado realmente. Es el mismo patrón que Microsoft GraphRAG utiliza para hacer aflorar "¿de qué trata este clúster?" en tiempo de consulta.

Una nueva herramienta MCP, list_communities(min_size, limit), devuelve los nodos de resumen de comunidades ordenados por número de miembros para que pueda explorar la macro-estructura del grafo sin cargarlo.

Cómo usarla

Actívela mediante una variable de entorno y luego compile:

export TESSERAE_COMMUNITY_SUMMARIES=true
tesserae project compile

Después consulte los resúmenes resultantes:

{ "tool": "list_communities", "arguments": { "min_size": 5, "limit": 20 } }

O siga las aristas summarizes de un nodo de resumen de comunidad hacia atrás hasta sus miembros mediante node_context.

Cuándo activarla

  • Tiene un grafo de tamaño medio a grande (la regla práctica es >500 nodos) y quiere una tabla de contenidos a nivel de clúster.
  • Quiere etiquetas de clúster escritas por el LLM que se adjunten a los grupos de color de la vista de grafo en el sitio estático.
  • Está produciendo resúmenes periódicos (semanales / mensuales) y quiere una sección de "macro-estructura" que se actualice solo cuando la pertenencia realmente haya cambiado.

Si su grafo es pequeño (un README de un único proyecto + un puñado de documentos), los nodos estructurales Synthesis ya cubren esto — los resúmenes de comunidades añaden ruido, no señal.

Dónde vive

Implementación principal: MD0.

Advertencias

  • Desactivado por defecto — Louvain + resumen con LLM añaden tiempo de ejecución, y el coste del LLM no es trivial para grafos con muchas comunidades. El caché amortiza esto entre re-compiles.
  • La pertenencia a comunidades es no determinista a través de distintas semillas de Louvain; el pase fija la semilla para reproducibilidad dentro de un proyecto, pero las comparaciones de IDs de comunidad entre proyectos no son significativas.
  • El prompt de resumen es genérico; las sobrescrituras de prompt por dominio son un seguimiento planificado.

5. Puntuación de decaimiento + supersedes + fresh_insights

Qué es

Dos primitivas complementarias, ambas inspiradas en el modelo de memoria con decaimiento de Ebbinghaus de A-MEM:

La puntuación de decaimiento asigna a cada nodo de hallazgo de sesión (Insight / Decision / Question / TODO / Hypothesis / Takeaway) un decay_score ∈ (0, 1] continuo usando la curva clásica del olvido:

decay_score = exp(-ln(2) · age_days / half_life)

La vida media por defecto es de 14 días, y un incremento de access_count (cada vez que el nodo aflora mediante ask o fresh_insights) ralentiza aún más el decaimiento. Las marcas de tiempo de las decisiones estructurales se derivan de la sesión padre, de modo que los hallazgos retroalimentados obtienen una edad sensata.

El pase supersedes es un paso post-compile opcional que encuentra hallazgos de sesión casi duplicados mediante similitud de Jaccard sobre shingles de título + contenido, y luego pide al LLM que juzgue si el más reciente realmente reemplaza al más antiguo. Un par confirmado obtiene una arista supersedes y el decay_score efectivo del nodo más antiguo queda suprimido.

Una nueva herramienta MCP, fresh_insights(limit, kind), devuelve los hallazgos principales por decay_score actual, excluyendo los nodos reemplazados. Es la consulta canónica de "¿qué debería priorizar el agente de las sesiones pasadas?".

Cómo usarla

La puntuación de decaimiento se ejecuta automáticamente en cada compile. Para habilitar el pase de supersedes:

export TESSERAE_SUPERSEDE_PASS=true
tesserae project compile

Después consulte los hallazgos más frescos no reemplazados:

{
  "tool": "fresh_insights",
  "arguments": { "limit": 15, "kind": "Decision" }
}

U omita kind para obtener un feed mixto de todos los tipos de hallazgos de sesión.

Cuándo habilitar el pase de supersedes

  • Está acumulando sesiones cada semana y sus consultas de Decision / Hypothesis empiezan a devolver entradas obsoletas contradictorias.
  • Quiere que el flujo de recall using-tesserae del agente se sesgue hacia "este es el pensamiento actual sobre X" en lugar de "todo lo que alguna vez pensamos sobre X".
  • El coste es aceptable: cada compile paga un pase Jaccard (barato) más N llamadas de juicio al LLM para los pares candidatos por encima del umbral de Jaccard (cacheadas por hash de contenido).

Si solo tiene unas pocas semanas de sesiones, el decaimiento por sí solo suele bastar — la arista supersedes es una optimización para grafos más antiguos y densos.

Dónde vive

  • Puntuación de decaimiento: MD0
  • Pase de supersedes: MD0

Advertencias

  • La vida media de 14 días es un valor por defecto razonable para proyectos de investigación activos; los grafos de archivo de horizonte largo pueden requerir 60-90 días. Una tabla de vida media por tipo es una funcionalidad planificada para v0.3.
  • La generación de candidatos por Jaccard usa un tamaño de shingle fijo de 5; los hallazgos muy cortos (Takeaways de una sola frase) pueden quedar sub-agrupados.
  • El juez LLM de supersedes es conservador por diseño — los falsos negativos (duplicados no detectados) pesan más que los falsos positivos (aristas supersedes incorrectas).

6. tesserae project schema-drift — propuestas de enums mediante EDC

Qué es

Un nuevo subcomando de la CLI que ayuda a que la ontología evolucione junto con el corpus. Implementa el patrón EDC (Extract-Define-Canonicalize, EMNLP'24): para cada tipo de nodo de alto volumen, agrupa por Jaccard los miembros mediante shingles de título+contenido, y luego pide al LLM que proponga subtipos en PascalCase con una breve justificación y tres previsualizaciones representativas de miembros por clúster. La salida se escribe en .tesserae/schema-drift.md como una lista de verificación con adiciones de enum copiables y pegables hacia los archivos de ontología en ontology/.

Las propuestas del LLM se cachean atómicamente (escribir-temp-y-renombrar) y se indexan por el SHA de los IDs de miembros del clúster, de modo que volver a ejecutar el pase es barato y converge a las mismas propuestas cuando el corpus no ha cambiado.

Cómo usarla

tesserae project schema-drift
# → escribe .tesserae/schema-drift.md

Luego abra el informe, revise los enums propuestos (cada bloque es un literal de Python copiable y pegable) y pegue los aceptados en el archivo correspondiente bajo ontology/. El siguiente tesserae project compile validará contra el esquema actualizado.

Cuándo usarla

  • Tras un gran lote de nuevos documentos / sesiones, antes de promover un nuevo valor de tipo de nodo a un enum de primera clase.
  • Periódicamente (mensual) en proyectos de larga duración para hacer aflorar deriva de ontología — el informe es rápido y de solo lectura.
  • Como artefacto de traspaso: el markdown es autocontenido, de modo que puede entregarlo a un revisor (u otro agente) sin necesidad de configurar la CLI completa de Tesserae.

Dónde vive

Implementación principal: MD0.

Advertencias

  • Las propuestas son sugerencias — el humano (o un agente posterior) sigue decidiendo qué clústeres se convierten en valores de enum reales. El pase deliberadamente no muta ontology/ por su cuenta.
  • La agrupación por Jaccard comparte el mismo supuesto de tamaño de shingle que el pase de supersedes; los miembros muy cortos pueden agruparse con menos nitidez.
  • El pase se centra en tipos de alto volumen; los tipos raros (≤ 3 miembros) se omiten para evitar enums especulativos.

Actualización desde v0.1.0

pip install --upgrade tesserae

Esa es toda la actualización — v0.2.0 es aditiva y sin cambios disruptivos. Conviene conocer un puñado de ajustes opcionales:

Variables de entorno para los pases opcionales:

# Habilita el pase post-compile de resúmenes de comunidades (funcionalidad 4)
export TESSERAE_COMMUNITY_SUMMARIES=true

# Habilita el pase de near-duplicates con supersedes (funcionalidad 5)
export TESSERAE_SUPERSEDE_PASS=true

El único cambio en la superficie MCP que debería conocer: search_nodes ahora usa por defecto mode="hybrid". Si tiene automatizaciones que dependían del ranking exacto de v0.1.0, pase mode="legacy" — la ruta legacy se conserva bit a bit.

Nueva dependencia opcional de Python para el backend real de embeddings:

pip install 'sentence-transformers>=2.7'

Si la omite, search_nodes mode="hybrid" sigue funcionando (fallback de hash-bucket); embedding_status reportará hash-bucket en lugar de minilm-l6-v2, de modo que la elección es observable.

Nuevos subcomandos de la CLI para añadir a la memoria muscular:

tesserae project ingest-code      # acuña nodos de código (funcionalidad 3)
tesserae project schema-drift     # propone enums de ontología (funcionalidad 6)

Nuevas herramientas MCP que el agente tiene ahora disponibles:

  • graph_ppr (funcionalidad 1)
  • embedding_status (funcionalidad 2)
  • list_communities (funcionalidad 4)
  • fresh_insights (funcionalidad 5)

Todo lo demás — slash commands, hooks, ask, la proyección de wiki / Obsidian — permanece inalterado.


Contexto estratégico

v0.2.0 sitúa a Tesserae estructuralmente al nivel del estado del arte de GraphRAG / memoria de agente de 2026:

  • La recuperación híbrida (BM25 + léxico + embedding mediante RRF) es la misma receta de fusión empleada por la búsqueda local de Microsoft GraphRAG y por el modo híbrido de LightRAG.
  • La expansión de semillas con Personalized PageRank es la primitiva multi-salto en el núcleo de HippoRAG 2, adaptada aquí a aristas tipadas en vez de a co-ocurrencia de pasajes.
  • Los resúmenes de comunidades replican el nivel de resumen-por-clúster de Microsoft GraphRAG — la capa que da una respuesta rápida y estructural a la pregunta "¿de qué trata este corpus en términos generales?".
  • La puntuación de decaimiento + supersedes es el modelo Ebbinghaus de A-MEM aplicado a la memoria de proyecto; el pase de supersedes está más cerca en espíritu de las operaciones de memoria "ADD / UPDATE / DELETE" de Mem0, pero expresado como una arista pura en vez de una reescritura in situ.
  • La deriva de esquema mediante EDC es la misma idea Extract-Define-Canonicalize de EMNLP'24, aplicada a la evolución de la ontología en lugar de a la extracción de relaciones.

Lo que sigue siendo específico de Tesserae y un nicho defendible: aristas tipadas en todas partes, hallazgos de sesión como nodos de primera clase del grafo, y (ahora) símbolos de código dentro de ese mismo grafo. La mayoría de los competidores en el panorama de 2026 carecen por completo de aristas tipadas; entre los que las tienen, ninguno enlaza decisiones en prosa con símbolos de código — la base de feat/code-graph sentada en v0.2.0 es donde ese nicho empieza a componerse.

Véase también: