Selvedge

Seguimiento de cambios para bases de código de la era de la IA: captura el porqué detrás de cada cambio a medida que el agente lo realiza.

Documentación

selvedge

selvedge.sh  ·  PyPI  ·  GitHub

Tests PyPI License: MIT

Memoria a largo plazo para bases de código escritas por IA, incluyendo lo que ya se intentó y se rechazó.

La atribución de líneas te dice quién escribió algo. Selvedge le dice a tu agente qué no escribir a continuación: los enfoques que esta base de código ya probó, revirtió y por qué. Es un git blame para agentes de IA, para el porqué en lugar de qué modelo tocó qué línea — capturado en vivo, por el agente, a medida que ocurre el cambio, para que nada posterior tenga que adivinarlo.

Selvedge es un servidor MCP local. Los agentes de codificación con IA (Claude Code, Codex, Copilot, Cursor, Gemini CLI y Windsurf) lo invocan mientras trabajan para registrar eventos de cambio estructurados con su razonamiento. Tus datos permanecen en un archivo SQLite bajo .selvedge/ junto a tu código.

Local-primero por defecto, servidor de equipo por elección, cero-LLM siempre.


Hace seis meses, tu agente de IA añadió una columna llamada user_tier_v2. No sabes por qué. git blame apunta a un commit de claude-code con un mensaje generado que dice "Actualizar esquema." La sesión que hizo el cambio ya no existe — y también el prompt que lo produjo.

Con Selvedge, ejecutas esto en su lugar:

$ selvedge blame user_tier_v2

  user_tier_v2
  Changed     2025-10-14 09:31:02
  Agent       claude-code
  Commit      3e7a991
  Reasoning   User asked to add a grandfathering flag for legacy free-tier
              users during the pricing migration. Stores the original tier
              so we can backfill discounts without touching billing history.

Ese razonamiento fue capturado por el agente en el momento — escrito en Selvedge desde el mismo contexto que produjo el cambio. No inferido del diff posteriormente por un segundo LLM. No es un mensaje de commit escrito a mano.



Para quién es Selvedge

Selvedge tiene dos audiencias. Misma herramienta, mismo pip install, mismo archivo SQLite bajo .selvedge/. Diferente escala de dolor.

Equipos que gestionan bases de código a largo plazo escritas por IA. Cuando el proyecto es lo suficientemente grande como para que tú (o alguien más) lo retomes en seis meses, doce meses, tres años — pero la mayor parte fue escrita por un agente cuyo contexto se evaporó el día en que cada PR se publicó. git blame te dice qué cambió. Selvedge te dice por qué — incluso después de que la sesión del agente, la plantilla de prompt, el desarrollador que lo solicitó y la versión del modelo hayan desaparecido. Este es el caso de uso original: bases de código de producción, decisiones de esquema, migraciones, cambios de dependencias que necesitan un rastro de auditoría que sobreviva a la rotación.

Desarrolladores en solitario que usan Claude Code en proyectos cotidianos. Proyectos secundarios, builds de fin de semana, la pequeña herramienta interna que sigues tocando. No necesitas gobernanza empresarial — solo necesitas recordar por qué tú (o tu agente) hiciste lo que hiciste ayer, la semana pasada, el último sprint. Ejecuta selvedge init una vez. Añade cuatro líneas a tu CLAUDE.md. A partir de entonces, selvedge blame es memoria muscular — una forma de hablar con tu yo pasado cuando tu yo pasado era un LLM.

Si alguna vez has vuelto a tu propio proyecto construido con IA y has pensado "¿para qué era esto otra vez?", Selvedge es la pieza que faltaba.


El problema

El código escrito por humanos filtra intención por todas partes — mensajes de commit, descripciones de PR, comentarios en línea, el hilo de Slack que lo precedió. El código escrito por IA no. El agente tiene claridad perfecta sobre por qué tomó cada decisión, pero ese contexto vive en el prompt y se evapora cuando la conversación termina.

Seis meses después, tu equipo está depurando una decisión de esquema sin rastro. git blame te dice qué cambió y cuándo. No puede decirte por qué.

Selvedge captura el porqué — en vivo, por el propio agente, a medida que se hace el cambio. El diff es trabajo de git. El porqué es de Selvedge.


Novedades en v0.3.14

Las búsquedas explícitas de siete días funcionan como se documenta.

La herramienta MCP prior_attempts ahora acepta window_minutes=10080, coincidiendo con su valor predeterminado de siete días. Anteriormente, enviar ese valor explícitamente fallaba la validación porque la ventana de tiempo compartía incorrectamente el límite de paginación de 1,000 resultados. La ventana permitida es de 1 a 10,080 minutos; los límites de resultados siguen limitados a 1,000. Sin nuevas dependencias, migraciones ni herramientas MCP.


Novedades en v0.3.13

Mantén el contexto de revisión con un rechazo registrado.

  • Los resúmenes de inicio de sesión muestran cuándo una decisión ha expirado o necesita revisión manual, incluso en la sección de rechazos.
  • Las decisiones superadas abandonan la lista de revisión sin ocultar decisiones no relacionadas en la misma ruta. El historial permanece intacto; la reapertura sigue siendo explícita.
  • Guía de comentarios y correcciones: cómo los informes se convierten en decisiones de producto y cómo reabrir un rechazo erróneo usando supersede.

Dónde encaja Selvedge

Where Selvedge fits in the broader AI-coded-codebase tooling stack

Los agentes de IA invocan a Selvedge mientras trabajan. Selvedge captura el porqué en un almacén duradero y consultable y lo emite de vuelta — como registros de Agent Trace para lectores entre herramientas, como metadatos de observabilidad que se enlazan con trazas de pila de Sentry/Datadog, y como artefactos de cumplimiento para auditorías de SOC 2 y la Ley de IA de la UE.

Selvedge no reemplaza a git (qué/cuándo a nivel de línea), herramientas de revisión de PR (calidad en el momento de la revisión), observabilidad de agentes (trazas de llamadas LLM) ni funciones de IA generales del host de código. Se sitúa entre ellos — la capa de procedencia como ciudadano de primera clase a la que todo lo demás hace referencia.


Cómo se compara Selvedge

Existe una categoría de rápido crecimiento de "git blame para agentes de IA". Aquí es donde encaja Selvedge — y donde deliberadamente no lo hace.

Rutas rechazadasFuente de razonamientoGranularidadMecanismoAgrupaciónAlmacenamiento
SelvedgeConsultableprior_attempts devuelve probado → revertido → reabiertoCapturado en vivo, por el agente en el mismo contexto que produjo el cambioEntidad — columna de BD, tabla, variable de entorno, dependencia, ruta de API, funciónServidor MCP — el agente lo invoca mientras ocurre el trabajoChangesets — slugs de características/tareas nombradas en muchas entidadesSQLite, cero dependencias
OpenLorePurgado — rejected es un estado inactivo, eliminado del almacén consultable después de cada sincronización de decisión (la anotación sobrevive en el markdown de especificación sincronizado)Derivado — análisis estático tree-sitter del estado del código, más notas de decisión limitadas por commitNodo AST (18 lenguajes + 12 IaC)Servidor MCP — índice único + certificados en el momento del commitBordes de grafo de llamadasGrafo SQLite en .openlore/
AgentDiff (sunilmallya)NingunaInferido post-hoc por Claude Haiku a partir del diff al final de la sesiónLíneaHooks de ciclo de vida de Claude Code → demonio localSesión/tareaJSONL en disco
AgentDiff (codeprakhar25)NingunaProcedencia entre agentes firmada con ed25519LíneaHooks de editor por agente + hooks de git (firma en el commit)NingunaTrazas firmadas en refs de git
OriginNinguna — rework marca código de IA revertido post-hoc, sin justificaciónRecibos de prompt, capturados en vivo por turnoLíneaHooks de ciclo de vida del agente + hook post-commit de gitNingunaNotas de git + rama de sesiones
Git AINingunaMetadatos de atribuciónLíneaCheckpoint invocado por el agente → notas de git en el commitNingunaNotas de git
BlamePromptNingunaRecibos de prompt — prompt, costo, herramientas; sin justificación declaradaLíneaHooks de ciclo de vida del agente + hook post-commitNingunaNotas de git

Por qué importan las "rutas rechazadas" — la que no se puede copiar. El fallo costoso no es olvidar por qué existe una columna. Es un agente reimplementando con confianza algo que el equipo ya eliminó por una buena razón, seis meses después de que todos los que lo sabían salieran de la ventana de contexto. Ninguna de las herramientas de atribución de líneas anteriores muestra rutas rechazadas en absoluto, y no es una brecha de funcionalidad que puedan cerrar en una versión — un almacén orientado a líneas no tiene noción de una entidad que persistió a través de un ciclo probar → revertir → reintentar. Ver docs/demos/prior-attempts.md.

Por qué importa el determinismo. El razonamiento de Selvedge es la intención propia del agente, escrita desde la misma ventana de contexto que produjo el cambio. No hay ningún modelo en la ruta de almacenamiento o recuperación, por lo que la misma consulta devuelve la misma respuesta hoy y dentro de dos años, entre versiones de modelos. Las herramientas que infieren razonamiento post-hoc están ejecutando un segundo LLM que nunca vio el prompt original: lo que produce es paráfrasis, y re-ejecutarlo puede producir categorías diferentes para el mismo cambio. Como dijo un comentarista de Hacker News sobre un enfoque competidor, "grep no encontrará tu commit porque rechazaste 'oauth-library'… a menos que haya aplicación determinista" (0x457).

El determinismo por sí solo ya no es un diferenciador — OpenLore también es determinista de forma nativa, y lo dice. El compuesto que separa es testimonio de solo-append: razonamiento que el agente escribió él mismo, mantenido en un almacén donde un rechazo es un registro de primera clase en lugar de un estado inactivo que se barre.

Por qué importa el "nivel de entidad". La mayoría de las herramientas atribuyen líneas. Selvedge atribuye cosas que realmente buscas: users.email, env/STRIPE_SECRET_KEY, api/v1/checkout, deps/stripe. La primera pregunta después de git blame suele ser "¿cuál es el historial de esta columna?", no "¿cuál es el historial de las líneas 40–48 de users.py?".

Por qué importa "capturado en vivo". No es un diferenciador por sí solo — cada herramienta aquí afirma alguna variante — pero es el mecanismo que hace confiable el razonamiento. Escribir en el momento del cambio, desde el contexto que lo produjo, es la razón por la que no hay un segundo modelo en la ruta que pueda alucinar una explicación. Un campo reasoning vacío es en sí mismo una señal honesta: el agente no tenía una.

Comparación actualizada al 2026-08-05; OpenLore en v2.1.8 / 265★, verificado contra su fuente. Las correcciones son bienvenidas como issue.

Por qué importan los "changesets". Un despliegue de facturación de Stripe toca la tabla users, dos nuevas variables de entorno, tres nuevas rutas de API, una dependencia y cuatro funciones en toda la base de código. Etiqueta cada evento con changeset:add-stripe-billing y podrás recuperar todo el alcance más tarde — incluso si el PR original se dividió en ocho más pequeños durante un mes.

Selvedge ↔ Agent Trace. Agent Trace es un formato de formato abierto de atribución de código de IA publicado por Cursor (RFC, enero 2026). Su hogar original en GitHub dio 404 en agosto de 2026 y el impulso multi-vendedor detrás de él se ha desvanecido, pero la especificación y el esquema aún se resuelven en agent-trace.dev, congelados en v0.1.0. Desde v0.3.9, selvedge export --format agent-trace emite registros de Agent Trace v0.1.0 y selvedge import --format agent-trace los lee de vuelta — un formato de intercambio portátil y documentado para atribución de IA por archivo/línea, con razonamiento y procedencia a nivel de entidad en los metadatos dev.selvedge de cada registro. El mapeo está en docs/agent-trace-interop.md; Selvedge incluye el esquema y no tiene dependencia de tiempo de ejecución del proyecto upstream.


Inicio rápido

Claude Code — instala el plugin (recomendado)

Dos comandos, dentro de Claude Code. Sin pip install previo — el plugin arranca el servidor él mismo vía uvx (o pipx):

/plugin marketplace add masondelan/selvedge
/plugin install selvedge@selvedge

Esa es toda la superficie orientada al agente en un solo paso:

  • el servidor MCP — 8 herramientas (log_change, prior_attempts, blame, diff, history, changeset, search, stale_decisions);
  • una habilidad que le dice al agente cuándo invocarlas — antes de editar una entidad rastreada, después de cualquier cambio sustancial;
  • el hook de aplicación PreToolUse — las ediciones de esquema/migración se bloquean hasta que prior_attempts se haya verificado en esta sesión, con el razonamiento previo en el mensaje de bloqueo;
  • comandos de barra/selvedge:status, /selvedge:blame <entity>, /selvedge:history, /selvedge:prior-attempts <entity>. El almacén (.selvedge/selvedge.db) se crea a sí mismo en el primer cambio registrado. Dos extras opcionales permanecen del lado de la CLI: el hook post-commit que sella cada evento con su hash de commit (selvedge install-hook), y — si quieres el comando selvedge en tu propio shell PATHpip install selvedge, que el lanzador prefiere sobre uvx para una versión fijada exacta.

¿Plugin o selvedge setup para Claude Code? Elige uno. Ambos conectan el servidor MCP; ejecutar ambos lo registra dos veces. El plugin es la ruta más ligera y la que se actualiza a sí misma. Si estás en el plugin y solo quieres el sellado de hash de commit post-commit, ejecuta selvedge install-hook por sí solo.

Elige tu agente de codificación

Con uv instalado:

uv tool install --upgrade selvedge
selvedge demo
cd your-project
selvedge setup --agent codex

Usa codex, claude-code, cursor, copilot, gemini o windsurf. Repite --agent para múltiples herramientas, u omítelo para detectar agentes instalados. ¿Prefieres pip? Usa python -m pip install --upgrade selvedge en un entorno virtual. El ejecutable selvedge-server debe estar en el PATH de tu editor; lanza el editor desde ese entorno o usa la ruta absoluta del ejecutable en su configuración MCP.

La configuración pregunta antes de cambiar archivos, respalda el contenido existente, instala MCP e instrucciones del agente, inicializa el proyecto y ofrece un hook post-commit de Git. Para Codex escribe .codex/config.toml y AGENTS.md; Gemini CLI obtiene .gemini/settings.json y GEMINI.md; Copilot obtiene .vscode/mcp.json y .github/copilot-instructions.md. Las entradas TOML personalizadas de Codex requieren reconciliación manual, incluso con --force.

Reinicia tu agente en el proyecto y aprueba las herramientas de Selvedge si se te solicita. Codex debe confiar en el proyecto para cargar la configuración a nivel de proyecto. Pregunta al agente:

Usa Selvedge para registrar un enfoque que consideramos y rechazamos en este proyecto. Incluye por qué, y qué cambiaría nuestra opinión. Luego búscalo con prior_attempts.

Inicia una nueva sesión y busca la misma entidad para verificar que la decisión se transmite. El acceso MCP no captura automáticamente cada decisión: las instrucciones instaladas guían al agente para usarlo. Los hooks de entrega y aplicación de sesión son actualmente integraciones de Claude Code.

Para arranque de CI o devcontainer.json postCreateCommand:

selvedge setup --non-interactive --yes

Verifica la conexión — abre una segunda terminal en el mismo proyecto:

selvedge watch

Haz cualquier cambio en tu herramienta de IA — añade una columna, renombra una función, añade una variable de entorno. selvedge watch debería imprimir el nuevo evento dentro de un segundo de que el agente llame a log_change. Si no llega nada, ejecuta selvedge doctor para una verificación de salud de un solo comando que te dice qué paso está silenciosamente roto.

Consulta tu historial:

selvedge status                        # recent activity + missing-commit count
selvedge diff users                    # all changes to the users table
selvedge diff users.email              # changes to a specific column
selvedge blame payments.amount         # what changed last and why
selvedge history --since 30d           # last 30 days of changes
selvedge history --since 15m           # last 15 minutes ('m' = minutes)
selvedge changeset add-stripe-billing  # all events for a feature/task
selvedge search "stripe"               # full-text search
selvedge stats                         # log_change coverage report (per-agent)
selvedge import migrations/            # backfill from migration files
selvedge export --format csv           # dump history to CSV
Instalación manual — si prefieres conectarlo tú mismo

Si no quieres ejecutar el asistente, los cuatro pasos manuales que automatiza:

1. Inicializa en tu proyecto

cd your-project
selvedge init

2. Registra el servidor MCP

Selvedge es un servidor MCP estándar de stdio, por lo que funciona con cualquier cliente MCP — Claude Code, Cursor, Windsurf, Codex CLI, Gemini CLI y más. Consulta Funciona con cualquier cliente MCP para la configuración exacta por cliente. Para Claude Code:

claude mcp add selvedge -- selvedge-server

3. Dile a tu agente que lo use

selvedge prompt --install CLAUDE.md

Apunta --install al archivo de prompt que tu cliente lea — el bloque en sí es idéntico entre clientes:

ClienteArchivo de prompt
Claude CodeCLAUDE.md
Codex CLI (y otras herramientas compatibles con AGENTS.md)AGENTS.md
Cursor.cursor/rules/selvedge.md (o legado .cursorrules)
Gemini CLIGEMINI.md

Esto instala el bloque canónico de instrucciones del agente, delimitado por centinelas (<!-- selvedge:start --> / <!-- selvedge:end -->) para que futuras llamadas a --install actualicen la región delimitada sin perturbar nada más en el archivo. O canalízalo:

selvedge prompt | tee -a CLAUDE.md

¿Prefieres copiar y pegar? El mismo bloque está a un clic en el sitio web: selvedge.sh/prompt-block — con un botón de copiar y notas sobre lo que tu agente hace con él.

4. Instala el hook post-commit

selvedge install-hook

Esos son los mismos cuatro pasos que ejecuta el asistente.


Funciona con cualquier cliente MCP

Selvedge es un servidor MCP estándar de stdio — su comando de lanzamiento es selvedge-server, puesto en tu PATH por pip install selvedge. Cualquier cliente compatible con MCP puede ejecutarlo. Elige el tuyo:

Claude Code
claude mcp add selvedge -- selvedge-server

O confirma un .mcp.json a nivel de proyecto para que todo tu equipo lo tenga:

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

Documentación: https://code.claude.com/docs/en/mcp

Cursor

.cursor/mcp.json (proyecto) o ~/.cursor/mcp.json (global):

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

El esquema más nuevo de Cursor también acepta un "type": "stdio" explícito; la forma solo con command también funciona (Cursor infiere stdio de command). Documentación: https://cursor.com/docs/mcp

Windsurf

~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

Windsurf recarga el archivo en caliente — no se necesita reinicio. El botón Plugins → Ver configuración raw en la aplicación abre el archivo exacto que Cascade lee. Documentación: https://docs.windsurf.com/windsurf/cascade/mcp

Codex CLI

~/.codex/config.toml:

[mcp_servers.selvedge]
command = "selvedge-server"

O ejecuta codex mcp add selvedge -- selvedge-server. Documentación: https://developers.openai.com/codex/config-reference

Gemini CLI

~/.gemini/settings.json (o .gemini/settings.json por proyecto):

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

O ejecuta gemini mcp add -s user selvedge selvedge-server. Documentación: https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md

Cualquier otro cliente MCP

La mayoría de los clientes comparten la misma forma JSON — apunta el tuyo a:

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

Si selvedge-server no se encuentra, usa su ruta absoluta (which selvedge-server).


Cómo funciona

Selvedge se ejecuta como un servidor MCP. Los agentes de IA en herramientas como Claude Code llaman a las herramientas de Selvedge mientras trabajan — registrando eventos de cambio estructurados en una base de datos SQLite local.

Cada evento registra:

  • Qué cambió (ruta de entidad, tipo de cambio, diff)
  • Cuándo (marca de tiempo)
  • Quién (agente, ID de sesión)
  • Por qué (razonamiento — capturado del contexto del agente en el momento)
  • Dónde (commit de git, proyecto)

El diff es trabajo de git. El por qué es de Selvedge.


Selvedge rastrea su propia historia

Este repositorio usa Selvedge en sí mismo: su .selvedge/selvedge.db está confirmado, por lo que un clon nuevo viene con el historial de porqués de Selvedge. Clónalo y pregunta por qué cambió cualquier parte de Selvedge:

git clone https://github.com/masondelan/selvedge
cd selvedge
selvedge status                       # recent changes to Selvedge itself
selvedge search "telemetry"           # why the opt-in heartbeat shipped
selvedge blame selvedge/semantic.py   # why semantic search was added

Cada evento fue registrado por los agentes que construyeron Selvedge — las mismas llamadas a log_change que este README te pide hacer en tu propio proyecto.


Convenciones de ruta de entidad

users.email           DB column (table.column)
users                 DB table
src/auth.py::login    Function in a file (path::symbol)
src/auth.py           File
api/v1/users          API route
deps/stripe           Dependency
env/STRIPE_SECRET_KEY Environment variable

Las consultas de prefijo funcionan en todas partes: users devuelve users, users.email, users.created_at y cualquier otra entidad bajo el espacio de nombres users..


Herramientas MCP

Cuando está conectado como servidor MCP, Selvedge expone:

HerramientaDescripción
log_changeRegistra un evento de cambio con entidad, diff y razonamiento. rename_from + change_type="rename" registra el patrón de renombrado de doble evento; change_type="supersede" reabre una decisión revertida (solo añade); constraint / stale_when opcionales mantienen consultable el principio de la decisión y su condición de invalidación
diffHistorial para una entidad o prefijo de entidad, cada fila anotada con superseded_by
blameCambio más reciente + contexto para una entidad exacta, más la decisión derivada status (activa / revertida / reabierta)
historyHistorial filtrado en todas las entidades
changesetTodos los eventos agrupados bajo un slug de característica/tarea nombrada
searchBúsqueda de texto completo en todos los eventos
prior_attemptsIntentos de cambio previos en una entidad + resultado inferido (intentado → revertido → reabierto) — llámalo antes de editar. La consulta opcional fuzzy añade registros semánticamente similares (necesita el extra semantic; recurre a subcadena)
stale_decisionsDecisiones pendientes de revisión: pasadas su revisit_after y aún en uso activo (flag="revisit_due"), o cuya condición stale_when coincidió con un cambio posterior (flag="review_suggested")

Referencia de CLI

selvedge init [--path PATH]               Initialize in project
selvedge status                           Recent activity summary
selvedge diff ENTITY [--limit N]          Change history for entity
selvedge blame ENTITY                     Most recent change + context
selvedge history [--since SINCE]          Browse all history
              [--entity ENTITY]
              [--project PROJECT]
              [--changeset CS]
              [--summarize]
              [--limit N]
selvedge changeset [CHANGESET_ID]         Show events in a changeset
                  [--list]                or list all changesets
                  [--project NAME]
                  [--since SINCE]
selvedge search QUERY [--limit N]         Full-text search
selvedge prior-attempts ENTITY            Prior attempts + inferred outcome,
                       [--description T]   with the tried → reverted →
                       [--all]             re-opened trail + status line
                       [--window 7d]       (--all widens recall)
                       [--fuzzy TEXT]      add semantic matches (needs the
                                           semantic extra; substring fallback)
selvedge supersede ENTITY                 Re-open a reverted decision —
                  --reasoning TEXT         append-only, links the prior
                  [--constraint TEXT]      reverted event (or --supersedes ID)
                  [--stale-when TEXT]
                  [--supersedes ID]
selvedge index [--model NAME]             Build/update the optional semantic
              [--json]                     embeddings index (selvedge[semantic])
selvedge stale [--entity ENTITY]          Decisions due for a revisit: past
              [--project NAME]            revisit_after + still in use, or
              [--agent NAME]              stale_when matched by a later change
              [--json]                    ("review suggested")
selvedge stats [--since SINCE]            Tool call coverage report (per-tool, per-agent)
selvedge doctor [--json]                  Health check: DB path, schema, hook, MCP wiring
selvedge install-hook [--path PATH]       Install git post-commit hook
                     [--window MIN]       (default 60 minutes)
selvedge backfill-commit --hash HASH      Backfill git_commit on recent events
                        [--window MIN]    (default 60 minutes)
selvedge import PATH                      Import migrations (SQL / Alembic) or
              [--format auto|sql|         an Agent Trace file (agent-trace)
                 alembic|agent-trace]
              [--from-git]                or walk git history for reverts:
              [--since REF|DATE]          revert-message commits + deletions
              [--project NAME]            become change_type="revert" events
              [--dry-run]                 (idempotent on commit + entity)
selvedge export [--format json|csv|       Export history (agent-trace =
                 markdown|agent-trace]      Agent Trace v0.1.0 records;
                                            markdown = reviewable digest)
              [--since SINCE]
              [--entity ENTITY]
              [--ndjson]                  agent-trace: one record per line
              [--collapse-by-session]     agent-trace: merge a session into one
              [--output FILE]
selvedge log ENTITY CHANGE_TYPE           Manually log a change
             [--diff TEXT]                CHANGE_TYPE: add, remove, modify,
             [--reasoning TEXT]           rename, retype, create, delete,
             [--agent NAME]               index_add, index_remove, migrate,
             [--commit HASH]              revert, supersede
             [--project NAME]
             [--changeset CS]
             [--revisit-after WHEN]       ISO date or offset (e.g. 90d)
             [--rename-from OLD]          OLD path when CHANGE_TYPE is 'rename'
             [--constraint TEXT]          the principle behind the decision
             [--stale-when TEXT]          what would invalidate it
             [--supersedes ID]            with CHANGE_TYPE 'supersede'
selvedge migrate-paths                    Re-canonicalize stored entity paths
                      [--apply]           (dry-run by default; --apply writes)
                      [--json]

Todos los comandos de lectura admiten --json para salida legible por máquina.

Tiempo relativo en --since:

  • 15m → últimos 15 minutos (m = minutos)
  • 24h → últimas 24 horas
  • 7d → últimos 7 días
  • 5mo → últimos 5 meses (mo o mon = meses)
  • 1y → último año

Las entradas no analizables (p. ej., --since yesterday) salen con un error claro en lugar de devolver silenciosamente resultados vacíos. Las marcas de tiempo ISO 8601 también se aceptan y se normalizan a UTC.


Configuración

MétodoFormatoEjemplo
Variable de entornoSELVEDGE_DB=/path/to/dbAnulación por sesión
Inicialización de proyectoselvedge initCrea .selvedge/selvedge.db en el directorio de trabajo actual
Respaldo global~/.selvedge/selvedge.dbSe usa si no se encuentra una base de datos de proyecto
Globs de vigilancia de hooks.selvedge/config.toml[hook]
watch_globs = ["**/migrations/**", "db/**/*.sql"] — reemplaza los globs predeterminados de esquema/migración del hook de aplicación
Configuración de proyecto.selvedge/config.tomlConsulta la lista de claves a continuación — retención, límites de tamaño, patrones de redacción
Configuración global~/.selvedge/config.tomlMismas claves; el archivo de proyecto gana donde ambos establecen una
Omisión de hookSELVEDGE_HOOK_DISABLE=1Desactiva el hook de aplicación PreToolUse para el shell
Extra semánticopip install "selvedge[semantic]"Habilita selvedge index + prior-attempts --fuzzy (incrustaciones locales model2vec, ~30 MB; el núcleo nunca depende de él)

.selvedge/config.toml

Cada clave es opcional; un archivo faltante significa los valores predeterminados a continuación. La precedencia es bandera de CLI → variable de entorno → .selvedge/config.toml de proyecto → ~/.selvedge/config.toml global → predeterminado. SELVEDGE_DB es la única excepción: siempre gana para la resolución de la base de datos, porque el archivo de configuración se encuentra mediante la resolución de esa ruta. selvedge doctor imprime el valor efectivo y el paso que lo produjo para cada configuración.

retention_days_events     = 0       # 0 = never delete events (the default)
retention_days_tool_calls = 90      # local telemetry retention
backup_keep_last          = 7
diff_bytes                = 65536   # truncate oversized diffs at log time
reasoning_bytes           = 32768   # truncate oversized reasoning
db_size_warn_mb           = 500     # doctor warns above this
stale_days                = 0       # 0 = off
digest_max_bytes          = 4096    # cap on the session-start digest
redaction_patterns        = []      # extra secret shapes to warn about

[hook]
watch_globs = ["**/migrations/**", "db/**/*.sql"]

Cada clave también tiene una anulación de entorno (SELVEDGE_DIFF_BYTES, SELVEDGE_RETENTION_DAYS_EVENTS, …).


Revisión de la intención capturada en una solicitud de extracción

.selvedge/selvedge.db es un archivo SQLite, por lo que el razonamiento dentro de él no aparece en un diff. Exporta un resumen Markdown junto a él y confirma ambos:

selvedge export --format markdown -o .selvedge/DECISIONS.md
git add .selvedge/

El resumen está agrupado por entidad con decisiones revertidas primero, y es determinista — regenerarlo sin nuevos eventos produce un diff de cero líneas, por lo que sigue siendo revisable en lugar de convertirse en ruido que todos aprenden a omitir. Los anclajes de encabezado derivan de la ruta de entidad, por lo que los enlaces hacia él siguen funcionando a medida que crece. Regenera en el mismo commit que el código, o desde un hook pre-commit.


Verificación de cobertura

¿Te preguntas con qué frecuencia tu agente realmente llama a log_change? Dos formas de verificarlo:

# Quick summary in the terminal
selvedge stats

# Cross-reference against git commits
python scripts/coverage_check.py --since 30d

El script de cobertura compara tu registro de git con los eventos de Selvedge y muestra qué commits tienen eventos de cambio asociados. La baja cobertura generalmente significa que el prompt del sistema necesita fortalecerse — consulta docs/fallbacks.md para obtener orientación.

En CI (GitHub Action)

La misma verificación se distribuye como la acción compuesta Selvedge Coverage Check, por lo que puedes rastrear la cobertura del agente en cada push — y opcionalmente fallar la compilación cuando baje:

# .github/workflows/selvedge-coverage.yml
name: Selvedge coverage
on: [push, pull_request]
jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0            # full history so commits can be matched
      - uses: masondelan/selvedge@v0.3.14   # pin to a release tag (or @main for latest)
        with:
          since: 30d
          fail-under: "0.5"         # optional: fail below 50% coverage; omit to report only

Escribe un resumen de cobertura al resumen del trabajo y expone coverage-ratio, covered y total como salidas del paso. La acción contrasta tu historial de git con el registro de eventos de Selvedge, por lo que el runner necesita el .selvedge/selvedge.db del proyecto (hazle commit, o restáuralo antes de este paso) y el historial completo de git (fetch-depth: 0). Entradas: since, window, limit, fail-under, selvedge-version, python-version, working-directory, db-path.


Contribuciones

Lee el proceso de comentarios y revisión para informar problemas, evaluar solicitudes de funciones y dar seguimiento a las discusiones.

git clone https://github.com/masondelan/selvedge
cd selvedge
pip install -e ".[dev]"
pytest

Consulta CLAUDE.md para detalles de la arquitectura y la hoja de ruta de fases.


Licencia

MIT — consulta LICENSE.