CommitLore
Memoria de decisiones nativa de Git para agentes de codificación, almacenada como trailers de Git y refs/notes.
Documentación
CommitLore
Deja de revisar la misma mala idea.
Autoridad de decisiones para agentes de código, propiedad de Git.
Mantén restricciones, alternativas rechazadas y advertencias en Git — y luego entrega
solo lo que sigue vigente, para que un agente no reciba una decisión que el
repositorio ya revirtió.
Sin memoria alojada. El repositorio es dueño del registro.
Instala una vez. Luego inicializa cada repositorio donde quieras que funcione.
curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.7.3/install.sh | sh -s v1.7.3
¿Prefieres leer el instalador primero?
curl -fsSLO https://raw.githubusercontent.com/MongLong0214/commitlore/v1.7.3/install.sh
sh install.sh v1.7.3
# Or skip the script: the checkout it makes is one you can make yourself.
git clone --depth 1 --branch v1.7.3 https://github.com/MongLong0214/commitlore
node commitlore/dist/commitlore.mjs --version
Instala una copia fija del código fuente y un envoltorio que ejecuta
node <checkout>/dist/commitlore.mjs — sin descarga compilada, sin paso de compilación.
El código sobrevive. El juicio no.
Un agente propone un enfoque. Tu equipo lo rechaza por una restricción no obvia. El código final preserva el resultado, pero normalmente no el porqué se rechazó la alternativa. Un agente posterior ve solo el código y propone la misma idea otra vez.
CommitLore mantiene ese juicio junto al código.
Qué hace CommitLore
| Comportamiento | Ruta del producto | |
|---|---|---|
| Captura | Preserva restricciones, alternativas rechazadas y advertencias que un diff no puede mostrar. Los candidatos se verifican contra la transcripción de la sesión y el diff preparado. | commitlore capture |
| Preserva | Almacena registros aceptados en trailers o notas de Git en lugar de una base de datos de memoria alojada. | hooks de commit · refs/notes/commitlore |
| Rastrea ciclo de vida | Mantiene distintas las decisiones activas, superadas y expiradas. | commitlore stale |
| Alcance | Selecciona decisiones para la ruta que un agente está a punto de editar. | commitlore context |
| Clasifica confianza | Entrega registros como directivas, afirmaciones o contenido retenido. | modo predeterminado / firmado |
| Entrega | Da a los agentes compatibles contexto actual antes de una edición. | hook de plugin · MCP |
La mayoría de los commits no deberían llevar ningún registro. CommitLore es para juicios que el código no puede preservar, no para narrar cada cambio.
60 segundos para agentes conscientes de decisiones
1. Instala la CLI
macOS y Linux:
curl -fsSL https://raw.githubusercontent.com/MongLong0214/commitlore/v1.7.3/install.sh | sh -s v1.7.3
Windows:
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/MongLong0214/commitlore/v1.7.3/install.ps1))) v1.7.3
Requiere Node.js 22.23.2+ y Git. El script verifica ambos antes de escribir nada.
2. Conecta tu agente
Claude Code:
/plugin marketplace add MongLong0214/commitlore
/plugin install commitlore@commitlore
Codex:
commitlore plugin install-codex
El plugin no pone commitlore en PATH, así que los comandos de abajo necesitan
también la instalación de la CLI. Los instaladores también detectan y conectan
hosts MCP compatibles donde pueden hacerlo de forma segura; la matriz exacta
está abajo.
3. Inicializa un repositorio
cd your-repository
commitlore init
commitlore context .
Inicia una nueva sesión de agente después de instalar o actualizar un plugin: una sesión en ejecución mantiene el runtime que cargó.
Luego trabaja y haz commits normalmente. En integraciones de habilidades compatibles, CommitLore se considera durante solicitudes de commit ordinarias y permanece en silencio cuando no hay nada que valga la pena preservar. No necesitas nombrar CommitLore en cada commit.
¿Quieres que los registros aceptados se preparen sin un aviso por registro? El
repositorio puede optar una vez con commitlore auto on. Esa política es propiedad
del repositorio y se aplica al equipo, por lo que no se habilita silenciosamente
desde esta página.
Qué recibe el agente
Antes de editar src/pricing.ts:
commitlore: active records for src/pricing.ts
Limit
[claim] r-price01 a1b2c3d4 calculatePrice owns final checkout pricing only
Ruled-out
[claim] r-price01 a1b2c3d4 Reuse it for admin quotes | eligibility and rounding semantics differ
[claim] significa "considera esto como información". Un repositorio puede
optar por el modo más fuerte de autoridad firmada. La entrega da contexto al
agente; no bloquea la edición.
¿Por qué Git?
El repositorio debería ser dueño del juicio detrás de su código.
CommitLore almacena registros en trailers y notas ordinarios de Git, para que se ramifiquen, fusionen, clonen, revisen y sobrevivan a cambios de proveedor junto con el código que explican.
SQLite es solo un índice reconstruible. Bórralo y Git aún conserva el registro.
Encontrar una decisión antigua no es suficiente
Un sistema general de memoria o recuperación pregunta:
¿Qué texto antiguo parece relacionado?
CommitLore pregunta:
¿Qué decisiones registradas siguen aplicando a esta ruta ahora?
Una decisión superada puede ser muy relevante y aun así estar equivocada como guía actual. Relevancia y autoridad son preguntas diferentes.
Cómo funciona
- Captura — un agente redacta solo el contexto de decisión que el diff no puede mostrar.
- Verifica — CommitLore comprueba el borrador contra la sesión y el diff preparado.
- Preserva — el registro aceptado vive en Git con identidad y ciclo de vida.
- Entrega — antes de una edición posterior, solo se devuelven los registros activos para esa ruta.
La mayoría de los commits no llevan ningún registro. El hook de commit valida un registro cuando está presente; no lo inventa.
Un hook existente no se sobrescribe. commitlore init respeta core.hooksPath,
mueve cualquier hook ya instalado a <hook>.commitlore-chained, y lo llama
primero; commitlore hooks uninstall lo devuelve.
Qué sucede automáticamente
| Host | Entrega previa a la edición | Flujo de captura verificado | Captura determinista en cada commit |
|---|---|---|---|
| Claude Code | Automática a través del plugin | Disponible a través de la habilidad del plugin | No certificado |
| Codex | Automática a través del plugin | Disponible a través de la habilidad del plugin | No certificado |
| Hermes | Disponible después de commitlore hermes install | Disponible después de la instalación del host | No certificado |
| Gemini CLI, Cursor, Windsurf, opencode | Entrega MCP donde el host usa el registro | Procedimiento expuesto sobre MCP | No |
AGENTS.md hosts | Solo procedimiento | Solo procedimiento | No |
"Disponible" significa que existe el flujo de trabajo preparar → verificar → preparar. No significa que cada commit elegible se evalúe automáticamente.
Los usuarios en hosts con habilidades compatibles no necesitan decir "registra esto en CommitLore" en cada commit. La limitación restante es la iniciación del host, no un comando de usuario requerido por registro.
Repositorios con fusión squash
Una fusión squash reemplaza los commits de una rama con un nuevo commit, y ese commit no lleva los trailers de la rama. Si tu repositorio se fusiona con el botón de squash, un registro hecho en una rama se descarta en la fusión a menos que algo lo lleve al commit que lo aplastó.
Dos rutas cubren esto, y una de ellas necesita una configuración única:
| Cómo ocurre el squash | Qué lleva el registro | Configuración |
|---|---|---|
git merge --squash localmente | El hook prepare-commit-msg instalado, desde SQUASH_MSG | Ninguna — commitlore init ya lo hizo |
| Botón Squash and merge de GitHub | La acción de GitHub action/preserve | El flujo de trabajo de abajo |
GitHub realiza esa fusión en sus propios servidores, donde no se ejecuta ningún hook local de git, así que el hook local no puede verlo. La Acción es el único lugar que tiene lo que necesita en ese momento: la solicitud de extracción, sus commits y el commit en el que se aplastaron.
Añade .github/workflows/commitlore-preserve.yml:
name: CommitLore squash inheritance
# pull_request_target, not pull_request: a pull request from a fork gets a
# read-only token on pull_request, so the job would build the record and then
# fail to publish it.
on:
pull_request_target:
types: [closed]
permissions:
contents: write # the one push to refs/notes/commitlore
concurrency:
group: commitlore-notes
cancel-in-progress: false
jobs:
preserve:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# the merge commit is on the base branch, and a closed pull request
# has no merge ref left to check out
ref: ${{ github.event.pull_request.base.ref }}
fetch-depth: 0
# the mirror this action writes; publishing from a checkout that never
# read it would fork the notes history
- run: git fetch --no-tags origin '+refs/notes/commitlore:refs/notes/commitlore'
# a squash merge usually deletes the branch, and then the pull request's
# own ref is the only one still reaching the commits that carry records
- run: git fetch --no-tags --force origin
'+refs/pull/${{ github.event.pull_request.number }}/head:refs/commitlore/pr-head'
# The action runs CommitLore from a checkout of this repository: the
# package is private, so there is no published npm name to fall back to.
# `dist/` is committed (ADR-0011), so nothing needs building.
- uses: actions/checkout@v4
with:
repository: MongLong0214/commitlore
ref: v1.7.3
path: .commitlore-cli
persist-credentials: false
- uses: MongLong0214/commitlore/action/preserve@v1.7.3
with:
cli-path: .commitlore-cli/dist/cli.js
Dos reglas para quien edite esto a continuación, porque pull_request_target se
ejecuta con un token escribible: nunca hagas checkout de la cabeza de la
solicitud de extracción aquí, y nunca ejecutes nada alcanzable desde
refs/commitlore/pr-head. Los commits del fork llegan como datos para leer trailers, no
como código para ejecutar.
commitlore doctor informa si esto está activado, bajo
squash inheritance. Lo dice antes de que se pierda un registro;
squash conservation es la fila que informa registros ya perdidos.
Si fusionas con commits de fusión o rebase, los registros sobreviven por sí solos y esta configuración es innecesaria.
Un informe de campo, no una medición
Una ejecución, en un repositorio no relacionado, por alguien que instala v1.2.1 por primera vez. Nada aquí fue medido y nada de esto está en los registros de evidencia. Está en esta página porque el párrafo anterior afirma un bucle que ninguna tabla aquí cubre.
Pidieron a un agente que arreglara un error de redondeo, mencionaron de paso que una biblioteca decimal ya se había considerado y descartado, y terminaron con "haz el commit". CommitLore nunca fue nombrado. Parte de lo que llevó el commit:
Ruled-out: adopting a decimal library such as Decimal.js | the backend is a
number contract, so it is meaningless
Warn: do not revert the test file to console.assert: it exits 0 even on
failure, so CI passes silently
Provenance: drafted
El Warn no fue dictado al agente. Cayó en la trampa mientras
trabajaba y lo dejó para quien viniera después. Provenance: drafted registra que
ningún humano leyó el registro, lo que lo clasifica como claim —
entregado como un informe para considerar, no una orden.
Una sesión posterior sin historial compartido recibió la tarea de adoptar la
biblioteca decimal después de todo. No lo hizo, y nombró el registro como su
razón. También leyó la clasificación: un claim no es una
instrucción, así que verificó la razón declarada contra el código antes de
estar de acuerdo.
A diferencia del almacenamiento de memoria
| Memoria general / RAG | CommitLore | |
|---|---|---|
| Pregunta principal | ¿Qué texto antiguo está relacionado? | ¿Qué decisiones siguen aplicando aquí ahora? |
| Autoridad | Almacén de memoria o proveedor | Git |
| Alcance | Similitud semántica | Rutas del repositorio |
| Ciclo de vida | A menudo solo añade | Activa · superada · expirada |
| Confianza | Texto recuperado | Directiva · afirmación · bloqueada |
| Captura | Transcripción o almacenamiento de notas | Registro de decisión verificado con evidencia |
| Portabilidad | Dependiente del backend | Git ordinario |
CommitLore es intencionalmente más estrecho. No es un sistema general de memoria de usuario, archivo de conversación o reemplazo de base de datos vectorial.
Evidencia
| Pregunta | Resultado medido | Límite |
|---|---|---|
| ¿El contexto de grado afirmación cambió la re-propuesta en el estudio registrado? | 2.8% (16/580) con CommitLore vs 18.8% (109/579) sin | un modelo, un arnés, tareas construidas |
| ¿El filtrado de ciclo de vida entregó registros retirados en la proyección activa medida? | 0 registros retirados | los registros superados estaban presentes; la expiración no |
| ¿La búsqueda indexada escala? | 496 ms p50 a 100k commits | el respaldo sin índice es mucho más lento |
El tiempo de construcción del índice sigue el número de registros, no el número de commits: la pasada costosa se ejecuta una vez por registro, así que un historial largo con poco registrado se construye más rápido que uno corto denso en registros.
El alcance de ruta es lo que mantiene un historial grande fuera del modelo. En el corpus #167, solo 2 de 10,002 registros lo hicieron:
| ruta | registros visibles al modelo | registros relevantes | tokens visibles al modelo |
|---|---|---|---|
| inyectar todo | 10,002 | 2/2 | 1,004,554 |
| léxico top-k | 2 | 1/2 | 190 |
| alcance de ruta CommitLore | 2 | 2/2 | 335 |
Eso mide exposición y recuperación en un presupuesto fijo de dos registros — no costo de tokens, costo facturado, precisión o comportamiento del agente. Un corpus, una consulta, un modelo de incrustación fijado.
El estudio de agentes no establece un efecto universal del modelo. La entrega no es prueba de que un modelo leyó o siguió un registro.
Métodos, tablas completas, exclusiones y resultados negativos →
Límites, confianza y privacidad
- La captura es asistida, no determinista. Las habilidades compatibles consideran solicitudes de commit ordinarias, pero ningún host está certificado para evaluar cada commit elegible.
- El modo de directiva predeterminado no es autenticación. Coincide con el
encabezado del autor del commit, y cualquiera que pueda escribir un commit puede
establecer ese encabezado — por lo que un
[directive]en modo predeterminado es metadatos de política, no prueba de identidad. El modo de firma además requiere el estado verificado propio de Git y una coincidencia en la lista de permitidos decommitlore.trustedSignerlocal al repositorio; una lista de permitidos de firmantes ausente, vacía o ilegible no autoriza a nadie, por lo que el modo falla de forma cerrada. - Guard es un aviso experimental, no una red de seguridad: precisión 44.8% (IC de Wilson del 95%: 32.7%–57.5%), recall 22.0% en el corpus de 417 decisiones. Un resultado vacío de Guard no es un veredicto de seguridad.
- La entrega gasta tokens en cada llamada de herramienta coincidente. El hook
previo a la edición se activa en
Readasí como enEdit,Write,MultiEdityNotebookEdit, por lo que se ejecuta con mucha más frecuencia de la que un agente de edición hace commits. Cada activación gasta hasta el presupuesto de carga útil — 800 tokens por defecto, modificado con--budget. Un repositorio sin registros no gasta nada, lo que significa que este es un costo que llega con la adopción, no con la instalación. - Una respuesta puede ser parcial. La cobertura se divulga; la ausencia en un
resultado parcial no es prueba de que no exista ningún registro.
commitlore coverageinforma lo que alcanzó un escaneo. - Los trailers de commit viajan con un clon; las notas no. Git no obtiene
refs/notes/*por defecto, por lo que un registro enrefs/notes/commitloreestá ausente de un clon ordinario hasta quecommitlore initconfigura ese espejo. - No hay backend alojado. Pero una vez que el servidor o hook devuelve contexto, el host maneja ese contexto bajo su propia política; CommitLore no controla ese flujo de datos.
Seguridad · Compatibilidad · Evidencia
Modelo de seguridad y confianza
Los registros no son confiables hasta que se califican. La coincidencia de autor predeterminada es metadatos de política, no autenticación. El modo de directiva firmada requiere verificación de Git y una lista de permitidos de firmantes local al repositorio; una lista ausente o ilegible no autoriza a nadie. La carga útil con forma de inyección se retiene de las rutas legibles por modelos.
Instalación, actualizaciones y generaciones antiguas de hooks
El instalador CLI no puede reescribir hooks dentro de repositorios que no conoce,
y las sesiones de host en ejecución conservan el runtime que cargaron. commitlore doctor names both states and their repair, and commitlore upgrade informa
si existe una versión más reciente.
Protocolo y almacenamiento de Git
Los registros son trailers o notas ordinarios de Git. El protocolo 2.0 define el ciclo de vida, los grados de confianza, la validación y la compatibilidad.
Evidencia y resultados negativos
El repositorio publica los métodos, las exclusiones, las mediciones fallidas y los casos donde el benchmark o diagnóstico original era incorrecto.
Pruébalo en un repositorio con historial.
Cuéntanos dónde falla el alcance de ruta, el ciclo de vida, la captura o la instalación.
Reporta un caso de fallo · Lee la autoauditoría
Documentación
- Instalar, actualizar y desinstalar
- Referencia de CLI
- Flujo de trabajo de captura
- Protocolo de registros
- Modelo de seguridad
- Evidencia y limitaciones
- Contrato de producción
Contribuciones
CONTRIBUTING.md cubre el protocolo de registros al que este repositorio se adhiere, la puerta de lanzamiento y cómo reproducir la evidencia.
Licencia
MIT — ver LICENSE.