Repository navigation
El olvido respeta before_days también al borrar memorias
forgetborraba los episodios de una memoria de saliencia baja aunque alguno fuera más nuevo quebefore_days. Con los defaults demismem-forget(90 y 30 días), un episodio de 40 días atado a una memoria olvidable se borraba antes de los 90 que prometebefore_days. Ahora la memoria sólo es olvidable cuando todos sus episodios ya superaronbefore_days; mientras quede uno más nuevo, la memoria y sus episodios esperan. Las memorias sin episodios o con todos viejos se borran igual que antes, y sus episodios con ellas para queON DELETE SET NULLno los devuelva a pendientes.- El conteo de
dry_runsale de las mismas consultas que el borrado, y un test compara lo que anuncia con lo que después borra.
Embeddings: mejores valores por defecto para quien instala misMEM (#72)
-
Con
nomic-embed-textel corte semántico de 0,5 no cortaba nada: las 10 preguntas ajenas de la
medición traían 5 recuerdos cada una, así que el hook de inyección añadía recuerdos sin relación a
cada prompt. SinMISMEM_EMBEDDING_MIN_SCORE, el corte por defecto ahora depende del modelo: 0,65
paranomic-embed-text(también con etiqueta, p. ej.:latest) y 0,5 para el resto. Con 0,65 las
preguntas ajenas bajan a 0 recuerdos sin perder aciertos. Un valor explícito, incluido0, sigue
ganando siempre. -
scripts/install.sh: si hayllama-server, ofrece EmbeddingGemma 2 como opción recomendada.
Con memorias en castellano encontró 34 de 50 paráfrasis frente a 4 de 50 denomic-embed-text
(medición de la issue). Baja el GGUF (296 MB) sólo si el usuario dice que sí, dejallama-server
como servicio de systemd de usuario (mismem-embed, en CPU;--embeddings-gpuo la pregunta
interactiva lo pasan a la GPU) y escribe en~/.config/mismem/envel proveedor, los prefijos y el
corte 0,65.nomic-embed-textpor Ollama queda como alternativa ligera. Con--yesel modelo no
cambia salvo que se pida con--embeddings gemma|nomic: re-ejecutarlo conserva tal cual cualquier
configuración de embeddings que ya hubiera (otro modelo, otro servidor, prefijos, corte) y no duplica el
servicio. Si se vuelve a nomic, el serviciomismem-embedque montó el instalador se para y se
desactiva para no dejar ocupados el puerto y la memoria. Con EmbeddingGemma 2 elegido pero sin servidor
arrancado no se escribeMISMEM_EMBEDDINGS=off: la búsqueda degrada a palabras y se activa sola cuando
el servidor arranca. -
README y
DEPLOY.mddicen claro que con memorias que no estén en inglés la opción es EmbeddingGemma 2,
que connomic-embed-textel corte es 0,65 y no hay que esperar paráfrasis, y que el corte de
EmbeddingGemma 2 recomendado pasa de 0,68 a 0,65 (misma efectividad medida, con más recuerdos por
pregunta). -
El timeout de embeddings y el puerto HTTP dejan de aceptar valores imposibles: un negativo, basura, 0 o vacío vuelven a 3000 ms y a 3200 (antes
MISMEM_EMBEDDING_TIMEOUT_MS=-5hacía queAbortSignal.timeoutlanzaraRangeErrory unMISMEM_HTTP_PORTcon basura llegaba alistencomoNaN);prepublishOnlyusa pnpm.
jscpd sube a 5.4.1, y sus dos clones de más desaparecen
jscpdpasa de 4.3.0 a 5.4.1 (versión exacta). La 5 compara dos bloques que la 4 no veía:recally
recallHybridmontaban igual la lista de hits, ahora enfinalizeHits, yMemoryList/PendingList
repetían el<ul>y el pie de "cargar más", ahora enPagedList.pnpm dupsigue con umbral 0 y no
encuentra clones; no hay cambios de comportamiento ni visibles.
AGENTS.md como contrato de trabajo
AGENTS.mddeja de ser las antiguas instrucciones de Copilot: mapa del código actual, comandos, reglas duras con
su porqué, convenciones y trampas propias del repo, y enlaces al resto de la documentación en vez de copiarla.
Un estándar de contribución escrito, y comprobado
- Contribuir no tenía forma: ni formularios de issue, ni plantillas de PR, ni normas escritas, y el
README mezclaba la presentación con material de referencia y con la historia de cada iteración. Ahora
CONTRIBUTING.mdes la puerta de entrada (entorno, flujo trunk-based, estándar de issue y de PR,
etiquetas, releases) ydocs/standards/fija ramas, commits, comentarios, estilo, tests, seguridad y
releases, cada norma con su forma de comprobarla.docs/README.mddice qué documento es para quién y
qué no se documenta. .github/gana cuatro formularios de issue (error, mejora, documentación y medición de recall, cada
uno con su criterio de cierre), los issues en blanco desactivados con un enlace al reporte privado de
vulnerabilidades, una plantilla de PR por defecto y tres más (release,dependency,documentation),
release.ymlpara agrupar las notas por etiqueta yCODEOWNERS.- Las etiquetas que citan los formularios, las plantillas,
release.ymlyCONTRIBUTING.mdse declaran
en.github/labels.json.engine/tests/contribution-standard.test.tsfalla si alguno cita una que no
existe, o si un tipo se queda sin formulario ni excepción razonada; el workflowlabels.ymlcompara
ese fichero con las etiquetas que tiene GitHub. - Dependabot deja de proponer saltos de versión mayor de
nodeen el Dockerfile: los majors se mueven a
mano a una LTS. - El README pasa a ser una guía: qué es, un diagrama del sistema, el Quickstart primero y un mapa de la
documentación. Lo que era referencia se mueve sin perder nada: el comportamiento del recall y la
búsqueda por significado adocs/recall.md, los hooks adocs/hooks.md, y las capas, los componentes,
la saliencia y el índice hebbiano adocs/architecture.md. El roadmap por fases deengine/README.md
desaparece (la historia es este fichero) y la consolidación deja de repetir el despliegue deDEPLOY.md.
zod 4
- zod pasa de 3.25.76 a 4.6.7 (versión exacta):
.int()rechaza enteros fuera del rango seguro de JS (y elinputSchemadeforgetlo anuncia), los límites de longitud cuentan code points en vez de unidades UTF-16 y cambian los textos deZodError;tests/tool-schemas.test.tscompara conz.toJSONSchemaen vez de leer internos de zod 3.
Un solo diálogo de confirmación en el detalle
MemoryViewyTraitViewrepetían el pie del diálogo de confirmación y la forma de sus props. Ambos viven ahora enDetailParts.tsx(ConfirmDialogyDetailViewProps), sin cambios visibles, ypnpm duppasa a exigir umbral 0: ningún bloque copiado de 10 o más líneas.
@vitejs/plugin-react sube a 5.2.0
@vitejs/plugin-reactpasa de 4.7.0 a 5.2.0, fijado exacto.ui/vite.config.tsllama areact()
sin opciones y la 5.x sólo deja de añadirreact/react-domaresolve.dedupe, que aquí sobra.
Linter con Biome, y fuera las directivas de ESLint que no hacían nada
- No había linter ni formateador. Ahora Biome 2 es el único, sólo como linter:
pnpm linty un step
de CI justo después depnpm dup. El formato no se toca a propósito.biome.jsonlimita el
análisis asrc/,ui/src/ytests/en TypeScript, y deja fueraui/src/components/ui, que es
shadcn vendorizado, además de CSS, JSON y fixtures. - Las cinco directivas de supresión de ESLint no desactivaban nada: cuatro
no-consoleen
server-http.tsyused-cli.ts, y unno-explicit-anyenviewer-api.test.ts. Eseany
escondía dos huecos: el mock no implementaServerResponsey el cuerpo de la respuesta no tenía
tipo. Ahora el mock se ensancha una sola vez al pasarlo al handler y el cuerpo tieneApiBody. - Reglas recomendadas desactivadas, todas por patrones deliberados del repo:
noNonNullAssertion
(los guardas y los tests afirman con!justo después de comprobar longitud o nulidad; reescribir
los 24 usos serían cambios cosméticos),useSemanticElements(los rolessearch,groupy
meterson ARIA válido sobre elementos con estilos; cambiarlos porfieldset,metero
searchcambiaría el marcado y el CSS sin arreglar nada) ynoAutofocus(el formulario de
edición enfoca el campo al abrirse).useExhaustiveDependenciessigue activa pero no avisa de
dependencias de más:GraphViewrepitesize.widtha propósito para reaplicar el estado cuando
el canvas termina de montarse.biome.jsones JSON estricto y Biome no acepta comentarios ahí,
así que el porqué queda en esta entrada. - Los errores que sí eran defectos, arreglados: ocho
letsin tipo en los CLI y elentriesde
walk.ts, tresreturnque devolvían unvoidenviewer-static.ts, la comprobación de
content-typesin cadena opcional enhttp-body.ts, unbreakcon etiqueta que no hacía nada en
consolidation/run.ts, losanyde los tests y las claves por índice de los esqueletos de carga.
Errores, claves y ayudas en el idioma del producto
- Los errores que ven un cliente MCP o el viewer salían en inglés (
Unknown tool,not found,
is required,invalid layer) mientras el resto del producto responde en español. Ahora están en
español, con el mismo contenido y el mismo código de estado. - La confirmación de olvido mezclaba claves en los dos idiomas (
impacto,memorias_que_cita,
rasgos_que_la_citan,episodios). Pasan aimpact,memories_cited,traits_citingy
episodes; la UI y los tests leen las nuevas claves. - Las ayudas de
mismem-consolidate,mismem-forget,mismem-stats,mismem-migrate-engram,
mismem-obsidianymismem-embedusan los encabezadosUso:yVariables:, y la de
mismem-ingest, que estaba entera en inglés, también está en español. Los encabezados de las ayudas
pasan amisMEM: CLI de ..., el progreso demismem-migrate-engramy la cabecera demismem-stats
están traducidos, y los fallos de todos los CLIs salen con el prefijoERROR:en vez deFATAL:o
Error:. Los flags y lo que hace cada comando no cambian. - El servidor HTTP responde en español el 415 de
/mcp, el error de parseo de JSON-RPC (mismo
-32700), las acciones y endpoints desconocidos y los 404, también los del viewer. Los códigos de
estado, los identificadores y los nombres de tools no cambian.
Una conversación de ChatGPT sin texto no se importa
ingestChatGPTExportdecidía si saltarse una conversación mirando la cadena ya montada, y
flattenConversationsiempre emite la cabecera# títuloyCreated:. Una conversación con
todos los mensajes vacíos o de sistema se importaba como un episodio con sólo título y fecha.
Ahora la decisión se toma sobre los mensajes con texto y esa conversación cuenta comoskipped.
Una sola versión, y comprobada
- La versión estaba escrita a mano en
engine/package.json,server.json(dos campos) y
engine/src/server-core.ts, y nada comparaba las cuatro. Un release podía anunciar por MCP una
versión distinta de la publicada. Ahoraserver-core.tsleeengine/package.jsonal cargarse
(createRequire, que funciona igual desdesrc/con tsx que desdedist/), ytests/version.test.ts
falla si elserverInfoque ve un cliente MCP o cualquiera de los dos campos deserver.jsondeja de
coincidir con el paquete. DEPLOY.mdrecuerda que los tags van anotados (git tag -a vX.Y.Z -m 'misMEM X.Y.Z').
Higiene del repositorio: reportar en privado, dependencias y secretos
SECURITY.mddice cómo reportar una vulnerabilidad en privado (GitHub Private Vulnerability
Reporting), que sólo la última versión publicada recibe arreglos y qué cuenta como
vulnerabilidad acá: la autenticación del modo HTTP, y esa DB que tiene toda la memoria. Antes
no había ningún canal privado, así que el reporte terminaba en un issue público.- Las convenciones pasan de
.github/copilot-instructions.mdaAGENTS.md, que leen todos los agentes (Claude Code a través deCLAUDE.md, que lo importa); el fichero de Copilot desaparece.
install.shconfigura Claude Code y opencode, y hasta ahora sólo Copilot cargaba esas
convenciones: los otros dos agentes trabajaban sin ellas. .github/dependabot.ymlsaca la actualización de dependencias de la mano de nadie: npm en
engine/(minor y patch agrupados en un PR), los actions, que están fijados por SHA y sin
esto no se mueven nunca, y elnode:22-alpinedel Dockerfile.- El job
secret-scande CI corre gitleaks sobre todos los commits en cada PR y en cada push a
main, con la imagen fijada por digest. Nada buscaba una clave commiteada antes de que llegara
amain. .gitignorecubre*.db-journal, el diario que SQLite deja al lado de la DB cuando no
trabaja en modo WAL.
Ningún CLI se traga un flag mal escrito
mismem-embed,mismem-bench,mismem-statsymismem-migrate-engramignoraban los flags que no
entendían: un--scop daimonreindexaba o contaba todos los ámbitos, un--jsndejaba la salida en
texto, un--dryrunmigraba de verdad y un--batch abccaía al valor por defecto.mismem-ingest
hacía lo mismo con los posicionales de más. Ahora cada uno parsea en su<cli>-args.ts, como
consolidateyforget, y un flag o posicional inesperado corta conargumento desconocido: <x>y
exit 64. Un valor ausente (--scope,--batch,--limit,--source) también corta, un posicional
de ingest en blanco cuenta como ausente, y un subcomando demismem-ingestque no existe se rechaza
en vez de imprimir la ayuda.mismem-statsabría la base y, si una consulta fallaba, moría con la base abierta y sin mensaje.
Ahora la cierra en unfinallyy el fallo sale por stderr como[stats] FATAL: ...con exit 1.
La imagen y el paquete dejan de arrastrar lo que no usan
- Sin
engine/.dockerignore, undocker buildlocal mandaba al daemonnode_modules,dist,
coveragey cualquier.dbque hubiera enengine/. El Dockerfile no los usa: sólo copia
package.json,pnpm-lock.yaml,pnpm-workspace.yaml,tsconfig.json,srcyui. - Las dos etapas fijaban la base por tag (
node:22-alpine), así que un rebuild meses después
compilaba contra otra Alpine sin que nadie tocara el repositorio, ybetter-sqlite3es nativo.
Ahora van por digest, con el tag legible al lado. - La etapa runtime copiaba
node_modulesentero, con vite, typescript, react y vitest dentro de una
imagen que sólo ejecutadist/server-http.js. Traspnpm buildse hacepnpm prune --prod;
better-sqlite3es dependencia de producción y se queda (probado condocker build). - El paquete npm declaraba
MITsin llevar el texto de la licencia.engine/LICENSEes copia
literal de la raíz y entra enfiles. En CI,cmp LICENSE engine/LICENSEfalla si se separan, y
hadolint revisa el Dockerfile con la imagen fijada por digest.
mismem-http escucha sólo en loopback por defecto
- Sin
MISMEM_AUTH_*, el servidor escuchaba en0.0.0.0y la guarda deHostsólo frena el
DNS rebinding del navegador: cualquier cliente de la LAN puede mandarHost: localhost. Ahora el
valor por defecto deMISMEM_HTTP_HOSTes127.0.0.1. Para mantener el comportamiento anterior,
MISMEM_HTTP_HOST=0.0.0.0junto conMISMEM_AUTH_USERyMISMEM_AUTH_PASS. Los contenedores no
cambian: el Dockerfile y el ejemplo de compose ya fijan0.0.0.0. - El fichero SQLite, con toda la memoria, se creaba con el umask por defecto. Ahora queda en
0600
(y sus-waly-shm), y el directorio, si lo crea mismem, en0700. Un directorio que ya existía
no se toca.
Fuera el código muerto
- Se retiran
src/tools/dump-engram.ts,ingest-engram-dump.tsysmoke-recall.ts: scripts de una sola vez
que nada importaba ni documentaba, pero se compilaban dentro del paquete npm, y uno apagaba la
verificación TLS antes de mandar la cabeceraAuthorization. Para migrar desde Engram sigue
mismem-migrate-engram, que lee unengram.db.ENGRAM_URLyENGRAM_AUTHsalen de.env.example. pnpm knipcorre en CI: falla con ficheros, exports o dependencias sin uso.
El índice hebbiano empieza a existir
reinforcerecibía losmemory_idsjuntos —sabe que esos recuerdos se usaron en el mismo
turno— y lo colapsaba en un bump de saliencia por recuerdo. Tiraba justo la co-ocurrencia, que
es la señal hebbiana de verdad. Ahora la guarda:memories.use_countcuenta los turnos en que
cada recuerdo se usó, yco_use(memory_a, memory_b, n, last_at)cuenta cada par que se usó junto.- Se escribe desde
reinforcey no desdereinforceMemories, porque a esa última la llama
también el camino de recall, donde aparecer no es haberse usado. Con la reinyección por aparición
apagada (MISMEM_REINFORCE_ON_RECALL=off) la señal arranca limpia:use_counten 0 para todos. - Hacía falta porque
saliencehoy mide recencia, no uso: la pasada de decay escribe
salience_updated_aten las 3.738 memorias, así que el campo no distingue "se usó" de "se
marchitó". Medido sobre producción: de 1.351 memorias de más de 60 días sólo 14 tienen saliencia
por encima de 0,85, y entre ésas hay tres marcadores de ruido[pareto:l0]. Ordenar por
saliencia hoy pone arriba lo nuevo, no lo importante. - Migración aditiva, verificada sobre copia de la DB de producción: 15 ms,
integrity_checky
foreign_key_checkok, 3.738 memorias y 216 rasgos intactos. Los pares se van por cascada
cuando el recuerdo se borra. - Para qué: es la fase 1 del ordenador de memoria.
El refuerzo por uso ve lo que la inyección adelantó
- Los dos hooks no se enganchaban:
mismem-usedsólo reconocía resultados derecall, y lo que
mismem-injectadelanta llega como adjuntohook_additional_context, no comotool_result. Un
recuerdo inyectado y usado nunca sumaba saliencia. Medido sobre un transcript real: la inyección
había dejado 6 ids en el turno y se veían 0. parseInjectiones lo inverso deformatInjectiony vive en el mismo archivo, para que el
formato y su lectura no puedan derivar.reinforcecuenta los rasgos aparte (traits) en vez de meterlos enunknown. La inyección
también adelanta rasgos, así que mezclarlos dejaba esa alarma —la de "alguien manda ids
inventados"— sonando desde el primer día.- Aportado por @iDiagoValeta en #48, con el hallazgo de los
rasgos que quedaba abierto ahí.
El README dice lo que el código hace
- Seis gestos, no cinco: faltaba
reinforce, yrecallya no refuerza siempre. - Los binarios de los hooks (
mismem-inject,mismem-used) y una sección que explica para qué
sirven, qué no sale de la máquina y cómo se enciende el refuerzo por uso. - Dos lugares seguían diciendo cinco invocaciones mientras el título decía seis. Ahora los tres
dicen lo mismo. - El viewer: la API de sólo lectura ya expone los ámbitos, el origen de cada recuerdo, los rasgos
que lo citan y el grafo (/api/{scopes,memories,memory/:id,trait/:id,graph}), y el README
mencionaba sólo los tres endpoints originales. - La consolidación acepta OpenAI y cualquier servidor compatible desde #67, y tanto los
componentes como la sección de privacidad hablaban sólo de DeepSeek y OpenRouter. Importa
porque es lo que permite consolidar sin que el texto salga de la red propia. - Una sección para el índice hebbiano.
- El README y DEPLOY.md mandaban a
docker pull ghcr.io/lucasmella-stack/mismem-brain:latestcomo
camino recomendado, y esa imagen nunca se publicó: las tres corridas dedocker.ymlfallan
al empujar condenied: permission_denied: read_package, así que elpullrespondedenied.
Cualquiera que siguiera el README se chocaba con eso. Ahora el camino documentado es el build
local, que sí funciona, y la imagen publicada queda marcada como pendiente. - Una sección de agradecimiento con lo que trajo @iDiagoValeta,
que a esta altura es buena parte de lo que hace a misMEM instalable y auditable por alguien que
no sea su autor.
La memoria se puede exportar como bóveda de Obsidian
mismem-obsidianescribe la memoria como bóveda en<bóveda>/misMEM/: una nota por memoria,
rasgo y ámbito, enlazadas por origen y por parecido.- Re-exportar sólo borra las notas cuyo frontmatter sigue declarando el id del manifiesto, y se
niega si la base no tiene nada que exportar o el manifiesto no se puede leer: así una bóveda
migrada a mano no se vacía por error.
La interfaz deja de ser de sólo lectura
- UI React con shadcn y TanStack Query: listas, detalle, grafo 2D con filtros y búsqueda dentro
del grafo. viewer-actions.tsexpone POST desde el propio origen para corregir una memoria, deshacer su
consolidación, cristalizar y lanzar una consolidación.- Olvidar una memoria (con sus episodios) o un rasgo exige
MISMEM_VIEWER_ALLOW_DELETE=1y dos
pasos: el primero devuelve qué se perdería y un token de 60 s, y borra el segundo.
La búsqueda léxica rescata paráfrasis
- Sin capa semántica, una consulta estricta (todas las palabras) que no encontraba nada dejaba
fuera la paráfrasis que sí estaba. Ahorarecallreintenta con una consulta OR y conserva sólo
los candidatos que comparten al menos dos términos informativos (una con una consulta de una
palabra, el 30 % en las largas), con un tope de 3 por capa (rasgos, episodios y memorias). - El rescate sólo entra cuando la estricta no devolvió nada y no hay vectores comparables que
puntuar, para no alterar una búsqueda que ya funcionaba.
Instalación en Linux con un solo script
scripts/install.shinstala y configura misMEM: elige dónde vive la DB y con qué proveedor
consolidar, guarda la clave en~/.config/mismem/envcon permisos 600 y deja los clientes
llamando a~/.local/bin/mismem-run, sin credenciales en su configuración.
El servidor HTTP se protege sin auth
MISMEM_ALLOWED_HOSTS: sin auth, sólo se atiendenHostde loopback y el resto responde 403,
contra DNS rebinding.MISMEM_HTTP_MAX_BODY_BYTES:POST /mcpcorta el cuerpo en 4 MiB con 413 sin juntarlo en
memoria, y unContent-Typeque no es JSON responde 415 antes de leer.
El conectoma se puede mirar
/api/graph?co_use=1suma una segunda capa lateral. La que ya había,?related=1, une memorias
parecidas: sale de lo que cada una dice. Esta sale de lo que pasó: qué recuerdos usó junto
un mismo turno. Las dos juntas valen más que cada una —parecidas que nunca se usan juntas son
candidatas a que una reemplace a la otra— pero eso es otra entrada.- El peso no es el conteo crudo, es NPMI. Un recuerdo que se usa en todos los turnos co-ocurre
con todo, así que por conteo sería el centro del grafo sin orientar a nada: el mismo error de la
saliencia midiendo recencia. Con NPMI, 0 es "indistinguible del azar" y 1 "nunca aparecen
separados". Hay un test que construye el caso y falla si el ranking se ordena por grado;
comprobado mutando el comparador. - Hacía falta un denominador y no existía: la tabla
metaguarda el total de turnos de uso medido,
y se suma dentro de la misma transacción que los conteos deco_usepara que no pueda quedar
desfasado. Migración aditiva. - Con pocos datos la fuerza es ruido por construcción —dos recuerdos usados una sola vez, esa vez
juntos, dan 1—, así que cada arista viaja con sun,?co_use_min_n=kfiltra por soporte y el
resumen informa el tamaño de la muestra. Los costados de la interfaz tienen que poder decir "esto
todavía no significa nada" en vez de pintar ruido. - Sin el parámetro la respuesta no cambia: las aristas verticales no reciben campos nuevos y hay un
test que compara las dos respuestas. - Sobre copia de producción: migración en 18 ms,
integrity_checkyforeign_key_checkok, 3.805
memorias y 216 rasgos intactos, y las seis aristas existentes dan fuerza 0 porque el contador nace
ahora. Es correcto: son turnos que nadie midió, y 0 dice "no sé" en vez de inventar un número.
El contador de turnos nace con la cota que los datos permiten
- Un cerebro que ya venía midiendo co-uso con la versión anterior guarda
nyuse_countde turnos
que nadie contó. Con el contador en 0 toda fuerza vale 0, que es correcto —dice "no sé"—, pero
desde el primer turno medido después de actualizar el cocienten / turnosse acota a 1 y cada
par heredado se lee como asociación máxima: justo el club de los ricos que el peso existe para
evitar. Duraba hasta que el contador pasaba por arriba de cadan. - Al abrir, si el contador no existe, se siembra con el uso más alto registrado (
max(use_count)y
max(n)deco_use). Es una cota inferior de los turnos que hubo, porque cada uso ocupó un turno:
subestima, nunca infla. Sólo cuando falta: un contador andando es la medición de verdad y no se pisa. - Sobre copia de producción (2.527 memorias, 2.651 episodios, esquema previo a
use_count): migración
en 19 ms, nada perdido, y no siembra nada porque ahí no hay uso medido —un cerebro viejo no recibe un
contador inventado—. Con 40 turnos reinyectados sobre ids reales, el par identidad+acompañante da
0,112; sin semilla, el primer turno tras el deploy lo sube a 1; con semilla (38, la cota) vuelve a
0, que es la respuesta correcta para algo que acompaña a un recuerdo que está en todos los turnos.
El par poco usado se queda en 1 connde 3, y para eso está?co_use_min_n=k. - El test que lo cubre afirma las dos lecturas, la de antes y la de después, así que el artefacto queda
escrito en la suite en vez de en un comentario.
La imagen de GHCR existe
ghcr.io/lucasmella-stack/mismem-brainse publica de verdad:0.5.0,0.5ylatest, multi-arch
(linux/amd64ylinux/arm64), con pull anónimo. Es la primera imagen que llega al registro desde
que existe el repo, ylatestdeja de apuntar al0.2.0de julio de 2026.- No hacía falta cambiar nada del workflow. Los push de v0.1.0 y v0.2.0 habían creado el paquete en
julio, GitHub no lo vinculó al repositorio, y desde v0.3.0 todo push moría endenied: permission_denied: read_package. El paquete tampoco se veía en la lista de la cuenta por estar
privado y sin vincular. Dos cambios en Package settings: el repo con rol Write en Manage
Actions access, y la visibilidad a Public. - El Quickstart de Docker del README pasa a ser
docker run ghcr.io/...en vez de clonar y construir,
y enDEPLOY.mdla imagen publicada pasa a ser la opción A: el build en el servidor queda como la
alternativa para probar un cambio sin pasar por un release. El diagnóstico queda escrito ahí, con el
comando degh apique hace visible un paquete privado sin vincular y eldocker logout ghcr.io
para las máquinas con credenciales viejas.
What's Changed
Correcciones
- fix: read the last two numeric env vars through env.ts and publish with pnpm by @iDiagoValeta in #148
- fix(forget): keep a memory while any of its episodes is newer than before_days by @iDiagoValeta in #135
Novedades y cambios
- feat(embeddings): better defaults for whoever installs misMEM by @iDiagoValeta in #137
Documentación
- docs: standardize the contribution flow and rewrite the docs as a guide by @iDiagoValeta in #136
- docs: rewrite AGENTS.md as the operating contract for agents by @iDiagoValeta in #145
Limpieza e investigación
- refactor(viewer): share the confirmation dialog and allow no duplicated code by @iDiagoValeta in #133
- build: upgrade jscpd to 5.4.1 and remove the two clones it finds by @iDiagoValeta in #146
Dependencias
- build(deps): Bump better-sqlite3 from 12.11.1 to 13.0.3 in /engine by @dependabot[bot] in #112
- build: upgrade @vitejs/plugin-react to 5.2.0 by @iDiagoValeta in #132
- build: migrate to zod 4 by @iDiagoValeta in #134
- build(deps): Bump the actions group with 8 updates by @dependabot[bot] in #138
- build(deps): Bump the engine-minor group in /engine with 6 updates by @dependabot[bot] in #139
- build(deps-dev): Bump vitest from 2.1.9 to 5.0.4 in /engine by @dependabot[bot] in #140
- build(deps-dev): Bump @types/better-sqlite3 from 7.6.13 to 9.6.0 in /engine by @dependabot[bot] in #141
- build(deps-dev): Bump vite from 6.4.5 to 8.3.4 in /engine by @dependabot[bot] in #142
Otros cambios
- ci(docker):
latestsale sólo del tag estable más alto by @lucasmella-stack in #26 - feat(hooks): el hook de inyección se enciende solo cuando el servidor está listo by @lucasmella-stack in #27
- fix(hooks): el envoltorio quedó commiteado sin permiso de ejecución by @lucasmella-stack in #28
- fix(mcp): recall declara reinforce en su inputSchema by @lucasmella-stack in #29
- fix(hooks): el refuerzo por uso ve los recuerdos que la inyección adelantó by @lucasmella-stack in #55
- fix(consolidación): cada llamada al LLM tiene un tope de 120 s by @iDiagoValeta in #50
- fix(http): con una sola variable de auth el servidor no arranca by @iDiagoValeta in #31
- fix(http): sin auth sólo se atiende Host de loopback by @iDiagoValeta in #33
- feat: absorber los aportes de iDiagoValeta sobre el refuerzo por uso by @lucasmella-stack in #70
- feat(consolidación): OpenAI o cualquier API compatible, además de DeepSeek y OpenRouter by @iDiagoValeta in #67
- feat(install): instalar y configurar misMEM en Linux con un solo script by @iDiagoValeta in #69
- fix(http): POST /mcp corta el cuerpo en 4 MiB con 413 by @iDiagoValeta in #35
- fix(pareto): un hecho corto llega al LLM en vez de caer como ruido by @iDiagoValeta in #37
- fix(consolidación): "sin señal" suma un strike en vez de mandar la tanda a ruido by @iDiagoValeta in #39
- fix(forget-cli): un flag que no se entiende corta en vez de purgar by @iDiagoValeta in #42
- fix(consolidate-cli): flags inválidos cortan con error de uso by @iDiagoValeta in #44
- feat(viewer): API de sólo lectura para ver de dónde sale cada recuerdo by @iDiagoValeta in #52
- feat(hebbiano): contar el uso y el co-uso de los recuerdos (fase 1 del ordenador de memoria) by @lucasmella-stack in #73
- feat(viewer): interfaz v2 con shadcn/ui y grafo 2D al estilo Obsidian by @iDiagoValeta in #71
- feat(obsidian): exportar la memoria como bóveda de Obsidian by @iDiagoValeta in #65
- fix(recall): sin coincidencia exacta, rescate por dos palabras y raíz aproximada by @iDiagoValeta in #46
- fix(http): bind loopback by default and make the database owner-only by @iDiagoValeta in #90
- ci: type-check the tests and gate publishing on the suite by @iDiagoValeta in #91
- chore: remove dead code and keep knip watching for it by @iDiagoValeta in #92
- ci: pin actions, scope tokens and lint the workflows by @iDiagoValeta in #93
- docs: make the user docs describe the current code by @iDiagoValeta in #94
- docs: make comments, tool descriptions and agent rules match the code by @iDiagoValeta in #95
- build: pin the base image, ship only production deps and the license by @iDiagoValeta in #96
- fix(cli): reject unknown flags in every CLI by @iDiagoValeta in #98
- test: cover the MCP dispatch, the HTTP server and the importers by @iDiagoValeta in #100
- chore: add SECURITY.md, AGENTS.md, Dependabot and a secret scan by @iDiagoValeta in #99
- ci: build the image on main too and start it before calling it good by @iDiagoValeta in #102
- chore: read the version from package.json and check server.json agrees by @iDiagoValeta in #103
- docs: stop versioning personal design notes by @iDiagoValeta in #105
- refactor: define each helper, type and schema once by @iDiagoValeta in #106
- docs: keep the agent conventions in AGENTS.md only by @iDiagoValeta in #115
- test: stop the MIN_AGE_HOURS=0 case from racing the clock by @iDiagoValeta in #118
- fix(ingest): skip ChatGPT conversations that carry no message text by @iDiagoValeta in #116
- fix: user-facing messages in Spanish, JSON keys in English by @iDiagoValeta in #119
- chore: lint with Biome and drop the eslint directives that did nothing by @iDiagoValeta in #121
- chore(dependabot): only propose releases at least 14 days old by @iDiagoValeta in #123
- refactor: split the largest modules along their responsibilities by @iDiagoValeta in #126
- feat(conectoma): la capa lateral del grafo, pesada por asociación y no por conteo by @lucasmella-stack in #120
- fix(conectoma): el contador de turnos nace con la cota que los datos permiten by @lucasmella-stack in #149
- docs(docker): la imagen publicada pasa a ser el camino por defecto by @lucasmella-stack in #150
- chore(release): 0.6.0 by @lucasmella-stack in #151
New Contributors
- @iDiagoValeta made their first contribution in #50
- @dependabot[bot] made their first contribution in #112
Full Changelog: v0.5.0...v0.6.0