since-cutoff
Informa a tu agente de codificación qué cambió en la API pública de una biblioteca de Python desde su fecha límite de entrenamiento. Herramientas: api_changes (un paquete, por modelo o fecha límite) y project_changes (cada dependencia en el archivo de bloqueo de un proyecto). Diff estático, stdio local, sin clave API.
Documentación
since-cutoff
Para proyectos de Python escritos con un agente de codificación: since-cutoff encuentra las APIs de dependencias que cambiaron después del corte de entrenamiento del modelo, mide cuáles de ellas el modelo falla, y corrige esas con notas cortas de AGENTS.md, cada una verificada por un verificador de tipos o tomada directamente del diff de la API.
English | 简体中文 | Español | Français
El problema
Cada modelo tiene un corte de entrenamiento; tu lockfile sigue avanzando. Cuando una biblioteca cambia su API pública después del corte, un modelo que aprendió la versión anterior sigue escribiendo las llamadas antiguas. Parte de ese código falla al importar o al llamar. Parte aún se ejecuta, porque la ruta antigua solo está obsoleta.
Algunos de los cambios que since-cutoff scan encuentra para Claude Sonnet 4.5 (corte de entrenamiento de julio
2025) en el proyecto de ejemplo,
que fija seis de sus nueve dependencias a versiones actuales (para las otras tres, que no están
fijadas, la herramienta usa la última versión):
| biblioteca | versión en el corte | fijada | qué cambió |
|---|---|---|---|
| anthropic | 0.60.0 | 1.8.0 | messages.create(temperature=..., top_p=..., top_k=...) ya no se acepta |
| huggingface-hub | 0.34.3 | 2.0.0 | hf_hub_download(resume_download=..., force_filename=..., local_dir_use_symlinks=...) salió de la firma en 1.0 (2.0.0 aún los acepta en tiempo de ejecución, los ignora y advierte) |
| langchain-core | 0.3.72 | 1.6.5 | retriever.get_relevant_documents() y llm.predict() eliminados |
| openai | 1.98.0 | 3.19.2 | 21 cambios importantes, 6 nuevas obsolescencias |
En ese proyecto, 7 de 9 dependencias cambiaron su API pública después del corte. El diff estático marca 317 cambios importantes y 23 nuevas obsolescencias; algunos son internos, que las sondas omiten.
No es un modelo ni un proveedor. En 36 bibliotecas de IA de Python ampliamente utilizadas y 21 modelos de OpenAI, Anthropic, Google, xAI, DeepSeek, Qwen, Moonshot y Mistral, incluso el modelo más nuevo probado (Claude Opus 5.5, corte de junio de 2026) es anterior a una ruptura de API pública en 20 de las 36 (resultados completos):
since-cutoff hace tres cosas al respecto:
scanencuentra, para cada dependencia, la versión más reciente en o antes del corte del modelo y compara su API pública con la versión que fijas. Sin llamadas de modelo, sin clave de API.runpide al modelo tareas de codificación cortas que necesitan las APIs cambiadas, sin herramientas y sin documentación, y puntúa cada respuesta con un verificador de tipos contra ambas versiones: obsoleta, incorrecta, deprecada o correcta. Ningún LLM juzga nada.- Notas: para cada fallo escribe una nota de una línea en AGENTS.md / CLAUDE.md. Mantiene una nota escrita por el modelo solo si su ejemplo pasa la verificación de tipos contra tu versión; de lo contrario, usa una declaración simple del cambio del diff de la API. Luego vuelve a probar el modelo en tareas reservadas con y sin las notas.
El mismo diff está disponible para agentes a través de un servidor MCP y para CI a través de una Acción de GitHub y un hook de pre-commit.
Inicio rápido
# list API changes since your model's cutoff (no model calls, no API key)
uvx since-cutoff scan
# probe the model, write notes, and add them to AGENTS.md
uvx since-cutoff run --apply
O instálalo con pipx install since-cutoff (o pip install since-cutoff) y ejecuta
since-cutoff. Ejecútalo desde la raíz de tu proyecto: lee uv.lock, poetry.lock, pdm.lock,
pylock.toml, Pipfile.lock, requirements*.txt, pyproject.toml, Pipfile o un .venv
(no setup.py o setup.cfg). Sin --model prueba el modelo con el que tu agente de codificación está configurado,
desde la configuración de Claude Code, Codex, OpenCode o Aider; para cualquier otro modelo, pasa
--model (ver Elegir el modelo).
scan es gratuito; run envía prompts al proveedor del modelo y usa tus créditos de API o el uso de Claude
Code.
Lo que scan imprime para el proyecto de ejemplo:
En Claude Code
/plugin marketplace add MohammadHijjawi97/since-cutoff
/plugin install since-cutoff@since-cutoff
Luego pide a Claude que "verifique en cuáles de nuestras dependencias estás desactualizado", o ejecuta
/since-cutoff:since-cutoff. La habilidad ejecuta la CLI; la medición en sí la hace una copia nueva,
sin herramientas, del modelo, por lo que el agente no puede calificarse a sí mismo. El plugin también inicia el
servidor MCP, para que
Claude pueda buscar los cambios de una biblioteca antes de escribir código.
En otros agentes de codificación
npx skills add MohammadHijjawi97/since-cutoff
Esto instala la misma habilidad a través de la CLI abierta de skills
para Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode y otros agentes que leen
SKILL.md. since-cutoff lee el modelo de la configuración de Codex, OpenCode y Aider también; para
otros agentes, indícale qué modelo probar, por ejemplo since-cutoff scan --model openai:gpt-5.4.
Agrega el servidor MCP como se muestra a continuación.
Prompts que funcionan bien:
- "¿Cuáles de nuestras dependencias cambiaron su API pública después de tu corte de entrenamiento?" El agente
ejecuta
since-cutoff scano llama a la herramienta MCPproject_changes. - "Mide cuáles de esos cambios realmente fallas, y agrega las notas a AGENTS.md." El
agente te pregunta primero, luego ejecuta
since-cutoff run --quick --apply. - "Antes de escribir el código de httpx, verifica qué cambió en httpx desde tu corte." El agente
llama a la herramienta MCP
api_changes.
Elegir el modelo
--model | usa | necesita |
|---|---|---|
claude-code (predeterminado cuando ninguna configuración nombra un modelo) | tu inicio de sesión de Claude Code (suscripción o clave), modelo actual | la CLI de claude |
claude-code:sonnet, claude-code:claude-haiku-4-5 | un modelo específico de Claude | la CLI de claude |
anthropic:<model> | API de Anthropic | ANTHROPIC_API_KEY |
openai:<model> | API de OpenAI | OPENAI_API_KEY |
openrouter:<vendor/model> | OpenRouter | OPENROUTER_API_KEY |
deepseek:<model> | API de DeepSeek | DEEPSEEK_API_KEY |
ollama:<model> | Ollama local | Ollama en ejecución |
openai-compatible:<model> | cualquier servidor compatible con OpenAI | --base-url, opcional OPENAI_API_KEY |
Sin --model, since-cutoff 0.3.0 y posteriores prueban el modelo con el que tu agente de codificación está configurado, y
la línea del modelo indica de dónde proviene ("modelo de .claude/settings.json"):
SINCE_CUTOFF_MODEL(una especificación completa comoopenai:gpt-5.4) siempre gana.- Dentro de Claude Code (que establece
CLAUDECODE=1para los comandos que ejecuta), solo cuenta la configuración de Claude Code:ANTHROPIC_MODEL, luego el.claude/settings.local.jsony.claude/settings.jsondel proyecto, luego~/.claude/settings.json. - En otros lugares, la configuración más específica gana: primero
ANTHROPIC_MODELoAIDER_MODEL, luego la configuración del proyecto, la carpeta más cercana primero, desde la carpeta escaneada hasta la raíz del repositorio (nunca la carpeta de inicio), luego la configuración del usuario. En una carpeta, los agentes cuentan en este orden:
| agente | configuración del proyecto | configuración del usuario |
|---|---|---|
| Claude Code | .claude/settings.local.json, .claude/settings.json | ~/.claude/settings.json |
| Codex | .codex/config.toml, con su perfil seleccionado | $CODEX_HOME/config.toml o ~/.codex/config.toml |
| OpenCode | opencode.json, opencode.jsonc | ~/.config/opencode/ |
| Aider | .aider.conf.yml, con los alias de Aider (4o, flash, r1, ...) | ~/.aider.conf.yml |
Cuando ninguna configuración nombra un modelo, prueba el modelo predeterminado de Claude Code y lo dice. Solo se leen
los campos del modelo, y un nombre de modelo que no puede ubicar detiene la ejecución con un mensaje que nombra la
configuración. Un modelo al que un agente llega a través de otro servicio (GitHub Copilot, Amazon Bedrock,
Vertex AI) se nombra por su fabricante, por lo que run llama a la API del fabricante (openai: necesita
OPENAI_API_KEY).
Los cortes de entrenamiento provienen de models.dev (una instantánea está incluida para uso
sin conexión). since-cutoff models sonnet los lista; --cutoff 2025-07 anula la fecha, y
since-cutoff scan --cutoff 2025-07 sin --model escanea contra esa fecha sola. scan
solo necesita el corte, por lo que también acepta un id de modelo sin proveedor (claude-haiku-4-5,
sonnet) o con cualquier proveedor que models.dev liste (google:gemini-2.5-pro, incluidos los ids de Amazon Bedrock y
Vertex AI); run necesita un proveedor de la tabla anterior.
Resultados
Dos modelos de Claude en el proyecto de ejemplo de 9 dependencias en
examples/agent-app,
medidos con since-cutoff 0.1.0, con Claude Opus 4.6 escribiendo las tareas y notas:
| Claude Haiku 4.5 | Claude Opus 4.6 | |
|---|---|---|
| corte de entrenamiento | Feb 2025 | May 2025 |
| cambios de API probados | 20 | 16 |
| obsoletos / incorrectos / deprecados / correctos | 5 / 1 / 2 / 12 | 7 / 0 / 3 / 6 |
| bibliotecas con uso obsoleto | 3 de 5 probadas | 2 de 4 probadas |
| notas escritas (con un ejemplo que pasa la verificación de tipos) | 8 (7), alrededor de 391 tokens | 10 (7), alrededor de 437 tokens |
| correctos reservados, sin -> con notas | 14% -> 57% (14 pares) | 5% -> 65% (20 pares) |
| APIs previamente correctas después de las notas | 6/6 aún correctas | 6/6 aún correctas |
Reservadas son tareas parafraseadas de la tarea con la que se probó cada cambio fallido; cada una se responde dos veces, sin y con las notas, y se puntúa de la misma manera. La última fila vuelve a verificar las APIs que el modelo ya acertó, para detectar notas que empeoran las cosas.
En este ejemplo, el modelo más fuerte no fue más seguro: Opus 4.6 escribió APIs que se eliminaron después de su
corte, incluido anthropic.HUMAN_PROMPT con client.completions. Código obsoleto de ambas ejecuciones,
cada uno válido para la versión de comparación y rechazado por el verificador de tipos para la fijada:
messages.create(temperature=...) (anthropic 1.8), hf_hub_download(resume_download=...),
local_dir_use_symlinks=..., force_filename=... y proxies=... (huggingface-hub 2.0), y
client.beta.vector_stores (openai 3.x). En tiempo de ejecución, anthropic 1.8.0 lanza TypeError para
temperature; huggingface-hub 2.0.0 aún acepta esos cuatro argumentos de descarga, los ignora
y advierte.
Las notas escritas en la ejecución de Claude Haiku 4.5 (extracto, textual):
<!-- since-cutoff:start -->
## Library changes after the model's training cutoff
**anthropic 1.8.0**
- `temperature=...` was removed from `messages.create()` in anthropic 1.8.0. Omit the `temperature` parameter entirely; there is no replacement.
**huggingface-hub 2.0.0**
- `hf_hub_download(..., resume_download=True)`: The `resume_download` parameter was removed in huggingface-hub 2.0.0. Omit it; downloads resume automatically.
**openai 3.19.2**
- `client.beta.vector_stores` is removed in openai 3.19.2. Use `client.vector_stores` instead.
<!-- since-cutoff:end -->
La nota de huggingface-hub no es del todo correcta: resume_download salió de la firma en 1.0, no
2.0.0, y 2.0.0 aún lo acepta en tiempo de ejecución, lo ignora y advierte
(fuente).
Omitirlo sigue siendo el consejo correcto.
El resumen de terminal de la ejecución de Claude Opus 4.6, registrado con 0.1.0. Los resultados de la sonda son los
de la tabla anterior. Los conteos de diff en la tarjeta son los de 0.1.0 ("725 cambios marcados"); después
de las correcciones al diff, scan en 0.2.0 informa 513 cambios importantes y 48 nuevas obsolescencias para el
mismo corte. El conteo de "cambios corregidos" de la tarjeta y su IC del 95% también siguen a 0.1.0: el intervalo
pertenece a ese conteo, no a las tasas del 5% -> 65%, y las versiones hasta 0.2.0 contaban un cambio como
corregido incluso cuando una respuesta reservada ya era correcta sin las notas.
El mismo resumen para la ejecución de Claude Haiku 4.5 (también 0.1.0; el escaneo en 0.2.0 informa 491 cambios importantes y 50 nuevas obsolescencias para su corte)
Muestras pequeñas, dos modelos, un proyecto: trátalo como una demostración del método, no como un
punto de referencia. Cada ejecución escribe su informe completo (cada tarea, respuesta y error del verificador de tipos) en
.since-cutoff/report.md. Para repetir el experimento con la versión actual (su diff y
ranking cambiaron, por lo que las sondas no serán idénticas):
cd examples/agent-app && since-cutoff run --model claude-code:claude-haiku-4-5 --task-model claude-code:claude-opus-4-6.
Desde 0.3.0, una ejecución también puede guardar sus tareas: añade --tasks-out tasks.json, y cualquiera
puede repetir la ejecución exactamente en las mismas tareas con --tasks-from tasks.json, para otro modelo u
otro conjunto de notas. Los nombres de archivo que escribieron las tareas (modelo, versión del prompt, versión de since-cutoff),
y una ejecución sobre tareas reutilizadas lo informa
(detalles).
Los resultados de tus propios proyectos son muy bienvenidos en
Comparte tus resultados.
Cómo funciona la medición y qué muestran y qué no muestran estos números, con más detalle: el artículo.
Úsalo desde cualquier agente (MCP)
since-cutoff mcp es un servidor MCP que permite a un agente de codificación preguntar "¿qué cambió en esta biblioteca
desde mi corte de entrenamiento?" antes de escribir código. Tiene tres herramientas de solo lectura:
| herramienta | respuestas |
|---|---|
api_changes(package, model, symbol=...) | qué cambió en una biblioteca entre la versión en el corte del modelo y la última (o una dada), primero las rupturas duras |
project_changes(project_dir, model) | lo mismo para cada dependencia de un proyecto en su versión fijada, comenzando con las APIs que tu código ya usa |
model_cutoff(model) | el corte de entrenamiento de un modelo, desde models.dev |
El agente pasa su propio id de modelo, por lo que la respuesta cubre qué cambió después del corte de entrenamiento de ese modelo. Las herramientas leen PyPI y las fuentes de los paquetes estáticamente: sin llamadas a modelos, sin clave de API, sin ejecutar código de paquetes.
Claude Code
claude mcp add --scope user since-cutoff -- uvx since-cutoff@latest mcp
Codex (~/.codex/config.toml)
[mcp_servers.since-cutoff]
command = "uvx"
args = ["since-cutoff@latest", "mcp"]
startup_timeout_sec = 60
tool_timeout_sec = 900
Cursor (~/.cursor/mcp.json) y Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"since-cutoff": { "command": "uvx", "args": ["since-cutoff@latest", "mcp"] }
}
}
VS Code (.vscode/mcp.json)
{
"servers": {
"since-cutoff": { "type": "stdio", "command": "uvx", "args": ["since-cutoff@latest", "mcp"] }
}
}
Gemini CLI
gemini mcp add --scope user since-cutoff uvx since-cutoff@latest mcp
# or as an extension, which starts the same server:
gemini extensions install https://github.com/MohammadHijjawi97/since-cutoff
@latest hace que uvx recoja nuevas versiones en lugar de reutilizar la primera versión que almacenó en caché (el
propio .mcp.json del plugin fija la versión exacta). Si el cliente no puede encontrar uvx, instala
uv o da la ruta completa (which uvx). El servidor está listado en el
Registro MCP como io.github.MohammadHijjawi97/since-cutoff.
La primera llamada a project_changes en un proyecto más grande descarga las ruedas de cada dependencia
que cambió y puede tardar varios minutos (paquetes muy grandes como transformers son los que más
tardan). Los resultados se almacenan en caché, por lo que las llamadas posteriores tardan segundos. Para calentar la caché, ejecuta
since-cutoff scan en el proyecto una vez; comparte la caché con el servidor. Los clientes con un
tiempo de espera de herramienta predeterminado corto pueden necesitar uno más largo, como en el ejemplo de Codex anterior.
project_changes mantiene su respuesta por debajo de aproximadamente 24,000 caracteres: las dependencias cambiadas que no
caben reciben una línea cada una, y pasarlas en only lista sus cambios.
Lo que api_changes("huggingface-hub", model="claude-haiku-4-5") devolvió en 0.2.0 (salida real,
recortada; las versiones posteriores refinan el diff, por lo que sus recuentos difieren ligeramente):
# huggingface-hub 0.29.1 -> 2.0.0
- From 0.29.1 (2025-02-20): the newest release on or before 2025-02-28 (training cutoff of claude-haiku-4-5, from models.dev)
- To 2.0.0 (2026-09-24): the latest release on PyPI
- 116 breaking changes, 0 new deprecations (removed or moved 62, parameters removed 43, parameters now required 9, changed kind 1, now keyword-only or positional-only 1)
## Removed or moved
- `huggingface_hub.InferenceApi` was removed; similar names now: `inference`, `InferenceEndpoint`, `InferenceClient`
...
## Parameters removed
- `huggingface_hub.snapshot_download(resume_download=...)`: parameter `resume_download` was removed; similar parameters now: `force_download`
- `huggingface_hub.file_download.hf_hub_download(force_filename=...)`: parameter `force_filename` was removed; similar parameters now: `filename`
...
Not listed: 76 breaking changes, 0 new deprecations (removed or moved 47, parameters removed 29). Narrow with symbol="..." or raise limit.
Con symbol="hf_hub_download" lista solo los 8 cambios a esa función (resume_download=,
force_filename=, local_dir_use_symlinks= y proxies=, en la función y en HfApi).
symbol también toma una llamada tal como el código la escribe: client.messages.create encuentra los cambios
a Messages.create. El diff lee solo firmas: estos cuatro parámetros salieron de la firma en
huggingface-hub 1.0, pero 2.0.0 todavía los acepta en tiempo de ejecución, los ignora y advierte.
Uso en CI
Acción de GitHub
Escanea el proyecto en cada solicitud de extracción y añade un resumen a la página del trabajo: por dependencia, la
versión en el corte del modelo, la versión que fijas y los cambios principales, con los cambios a los nombres
que tu código usa primero. Como scan, solo lee PyPI y models.dev: sin llamadas a modelos, sin clave de API.
# .github/workflows/since-cutoff.yml
name: since-cutoff
on:
pull_request:
paths: ["**/*.lock", "**/pylock*.toml", "**/requirements*.txt", "**/pyproject.toml"]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: MohammadHijjawi97/since-cutoff@v0
with:
model: anthropic:claude-sonnet-4-5 # the model your team codes with
| entrada | predeterminado | |
|---|---|---|
model | requerido | provider:model como para --model; solo se usa su corte de entrenamiento |
working-directory | . | el directorio del proyecto |
only, exclude | nombres de PyPI separados por comas | |
cutoff | anula el corte de entrenamiento (YYYY-MM o YYYY-MM-DD) | |
fail-on-changes | false | falla el paso cuando una dependencia cambió su API después del corte |
step-summary | true | añade el resumen de Markdown al resumen del trabajo |
cache | true | conserva los metadatos de PyPI, las fuentes de los paquetes y los diffs de API entre ejecuciones (también cuando fail-on-changes falla el trabajo) |
args | más argumentos de since-cutoff scan, p. ej. --all-deps --limit 20 | |
since-cutoff-version | 0.3.2 | la versión de since-cutoff a ejecutar, o latest |
Salidas: changed-packages (separadas por comas), changes (cambios rupturistas), deprecations,
markdown (la ruta del resumen, por ejemplo para publicarlo como comentario en una solicitud de extracción) y report
(la ruta del informe completo). Un cambio alcanzable bajo varias rutas de importación se cuenta una vez.
pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/MohammadHijjawi97/since-cutoff
rev: v0.3.2
hooks:
- id: since-cutoff-scan
args: [--model=anthropic:claude-sonnet-4-5] # add --fail-on-changes to block the commit
El hook se ejecuta cuando un archivo de bloqueo, un archivo de requisitos o pyproject.toml cambia, e imprime el
escaneo. Dale --model en args. Necesita PyPI, así que omítelo en pre-commit.ci
(ci: {skip: [since-cutoff-scan]}).
Otro CI
# Markdown summary for any CI; exit code 3 if a dependency changed its API after the cutoff
since-cutoff scan --model anthropic:claude-sonnet-4-5 --markdown summary.md --fail-on-changes
# measure the model as well (needs its API key, or the claude CLI)
since-cutoff run --quick --fail-on-stale --json > since-cutoff.json
--markdown - imprime el resumen en stdout, y solo el progreso y la ruta del informe en
stderr, como hace --json. En un archivo, una tubería o un registro de CI no hay barra de progreso en vivo, y la
salida se dispone a 160 columnas de ancho (COLUMNS establece otro ancho). Códigos de salida: 0 ok, 1
error (por ejemplo, run no pudo sondear ningún cambio de API o puntuar ninguna respuesta de modelo), 2 error de uso,
3 uso de API obsoleto encontrado con run --fail-on-stale, o cambios de API encontrados con
scan --fail-on-changes, 141 la salida se cerró temprano (canalizado a head, por ejemplo).
Cómo funciona
Tres etapas. La primera no necesita modelo; en las otras dos, un verificador de tipos puntúa cada respuesta y verifica cada nota que el modelo escribe:
| resultado | significado |
|---|---|
| obsoleto | el código es válido para la versión de comparación (la del corte del modelo) e inválido para la tuya, y el error involucra una API que cambió |
| incorrecto | inválido para tu versión, pero no explicado por un cambio (API alucinada o mal utilizada) |
| deprecado | válido, pero usa una API marcada @deprecated en tu versión |
| correcto | válido para tu versión y realmente usa la API cambiada |
| intacto / fuera de tarea / inválido / error | no se cuenta en ninguna tasa, y siempre se informa |
Desde 0.3.0, el resultado reservado da las tasas a nivel de tarea sin -> con notas (con el número de tareas emparejadas y cambios de API detrás de ellas), su diferencia con un intervalo bootstrap del 95% que remuestrea los cambios de API, los cambios que las notas corrigieron (incorrecto sin, correcto con) con un intervalo de Wilson del 95%, los cambios que rompieron, una prueba de signo exacta de corregido contra roto, y los pares reservados no contados, por razón. La verificación de regresión informa cuántas APIs previamente correctas siguen siendo correctas con las notas.
run --compare template,signatures (0.3.0 y posteriores) también responde las tareas reservadas y
verificaciones de regresión con notas de referencia que no necesitan modelo: template establece cada cambio fallido en
una oración del diff de API, y signatures da la nueva firma y el primer párrafo de docstring
de cada API cambiada, o del reemplazo que su biblioteca nombra. Todos los bloques se puntúan en
los mismos pares, contra las mismas respuestas sin notas, y el tamaño de cada bloque se muestra en tokens,
por lo que una ejecución muestra qué añaden las propias notas de since-cutoff sobre ellos.
Todo se puntúa con un verificador de tipos contra las versiones exactas de los paquetes, cada una en un entorno
aislado con las dependencias de tiempo de ejecución de ese paquete. Ningún LLM juzga nada, y cada
número se remonta a results.json. Detalles: docs/how-it-works.md.
Qué ejecuta, envía y almacena
- No ejecuta código de paquetes ni código escrito por modelos. Los paquetes se leen estáticamente (griffe con
inspección desactivada; solo se extraen archivos
.py/.pyi, con comprobaciones de ruta y tamaño). Las respuestas del modelo solo se verifican de tipos, localmente, con basedpyright. - Obtiene metadatos públicos de paquetes y ruedas de PyPI, y cortes de modelos de models.dev (una instantánea está incluida para uso sin conexión). Las dependencias de git, ruta, espacio de trabajo e índices privados nunca se buscan en PyPI público por nombre.
- Envía prompts solo en
run, y solo al proveedor de modelos que elijas: nombres de paquetes, versiones, firmas públicas y docstrings de las APIs cambiadas, las tareas generadas y, para notas, las propias respuestas del modelo. Nunca tu código fuente.scan, el servidor MCP, la Acción de GitHub y el hook de pre-commit no envían nada a ningún modelo. - Almacena resultados en
.since-cutoff/en tu proyecto (se ignora a sí mismo en git) y una caché local (since-cutoff cache pathla muestra,since-cutoff cache clearla elimina). Con--applyescribe un bloque marcado enAGENTS.md/CLAUDE.mdy deja el resto del archivo byte por byte sin cambios;since-cutoff unapplyelimina el bloque. - Sin telemetría, sin cuenta, sin datos personales. Las re-ejecuciones provienen de la caché, por lo que son gratuitas
y reproducibles (
--freshvuelve a preguntar al modelo). Ver PRIVACY.md.
Limitaciones
- Solo Python por ahora. TypeScript (diffs de
.d.ts,tsc) es lo siguiente (#1). - Un verificador de tipos ve nombres incorrectos, parámetros incorrectos y deprecaciones PEP 702. No puede ver
cambios de comportamiento detrás de una firma sin cambios, o deprecaciones que solo advierten en tiempo de ejecución.
scantambién lista deprecaciones declaradas con el decorador propio de una biblioteca (nombre que contiene "deprecat") y nombres eliminados que un módulo aún sirve con una advertencia a través de__getattr__, perorunno los sondea. - El diff cubre la API pública: nombres de
_private, y suites de pruebas, benchmarks y ejemplos incluidos dentro de un paquete, se omiten. - Las sondas cubren una muestra clasificada de los cambios rupturistas (símbolos que tu código ya usa primero), no todos.
- "La versión de comparación" es la versión más reciente en o antes de la fecha de corte. Los modelos conocen menos bien las versiones recientes, por lo que la obsolescencia real puede comenzar antes.
- Las tareas reservadas son paráfrasis del mismo cambio: muestran que una nota corrige ese cambio, no que el modelo mejoró en general.
Para qué se usa el corte de entrenamiento
La fecha de corte elige un punto de comparación. No es una afirmación sobre lo que un modelo memorizó.
since-cutoff toma la fecha de models.dev (o --cutoff); un mes significa su último día
(2025-07 es 31 de julio de 2025). Para cada dependencia toma la versión final más reciente, no retirada, subida
en o antes de esa fecha (una pre-versión solo si el paquete no tenía versión final para entonces,
nunca una versión de desarrollo), y compara la API pública de esa versión contra tu versión bloqueada.
Ese diff es una lista de candidatos: cambios de API que los datos de entrenamiento del modelo probablemente no
incluyen.
La fecha decide tres cosas:
- qué paquetes se comparan en absoluto: un paquete cuya versión bloqueada no es más nueva que esa versión no tiene nada que comparar, y un paquete publicado por primera vez después de la fecha se lista como nuevo;
- en
run, con qué versiones de las dependencias propias de esa versión se verifica de tipos el lado antiguo (la más nueva que cada requisito permitía en esa fecha); - el lado "antiguo" de cada sonda en
run, por lo que una respuesta que es válida allí e inválida para tu versión, con el error en una API cambiada, es "obsoleta" en lugar de "incorrecta". Un modelo puede conocer una versión publicada después de su fecha de corte declarada, o no conocer versiones publicadas poco antes de ella, por lo que el escaneo puede listar cambios que el modelo ya maneja y omitir algunos que no maneja. Si el modelo realmente escribe la API antigua solo se muestra medianterun, que le pregunta: sin herramientas, indicándole qué versión fija el proyecto.
Cómo se compara
since-cutoff responde una pregunta para un proyecto: ¿qué APIs públicas de las versiones que fijas cambiaron desde la versión a la que apunta la fecha de corte del entrenamiento de un modelo, empezando por las que usa tu código? since-cutoff run añade dos preguntas opcionales: ¿este modelo realmente las falla, y una nota breve lo corrige? La mayoría de las herramientas siguientes responden una pregunta diferente ("¿qué dicen los documentos de la biblioteca ahora?") y funcionan bien junto a ella.
| herramienta | qué hace | cómo se relaciona since-cutoff |
|---|---|---|
Context7 (servidor MCP y CLI ctx7) | El agente llama a resolve-library-id y query-docs para traer fragmentos de documentación a su contexto mientras trabaja. Sirve una versión específica (/org/project/version) cuando los propietarios de la biblioteca han añadido esa versión (etiquetas o ramas de git, como máximo 20); de lo contrario, sirve la rama indexada. Funciona sin clave de API con un límite de tasa anónimo más bajo. | Complementaria. Context7 proporciona documentación; no lee tus versiones bloqueadas ni revisa el código que escribe el agente. since-cutoff lista cuáles de tus APIs fijadas cambiaron después de la fecha de corte del modelo, las que usa tu código primero, para que sepas dónde se necesita una consulta o una nota. Cuando preguntes a Context7, nombra la versión que fijas. |
| Otros servidores de documentación: Ref, docs-mcp-server | Búsqueda de documentación para agentes, en el momento de la respuesta; docs-mcp-server puede indexar documentación localmente | Igual que Context7. |
| library-skills | Bibliotecas como FastAPI y Streamlit incluyen habilidades de agente dentro de sus paquetes; uvx library-skills enlaza las habilidades de las versiones que tienes instaladas en .agents/skills o .claude/skills, de modo que se actualizan con la biblioteca | Escritas por los mantenedores y en sintonía con tu versión instalada: cuando una biblioteca incluye una, úsala. since-cutoff cubre paquetes que no incluyen guía, y solo indica cambios en la superficie de la API. |
| Complementos de habilidades de proveedores, p. ej. pydantic/skills | Complementos de Claude Code, Codex y Cursor y archivos SKILL.md para Pydantic, Pydantic AI y Logfire, instalados desde el repositorio | Guía de mantenedores sobre cómo usar bien una biblioteca; publicada con el repositorio del complemento, no con la versión que fijas. Las notas de since-cutoff están escritas para tu archivo de bloqueo. |
Codemods: reglas de ast-grep, openai migrate de OpenAI (Grit) | Reescriben código que ya existe con reglas sintácticas escritas a mano; el catálogo de ast-grep tiene una migración del SDK de OpenAI (openai.Completion.create(...) a client.completions.create(...)) | Para migrar código que ya tienes, un codemod es la herramienta adecuada. since-cutoff trata sobre el código que un asistente escribe a continuación: encuentra los cambios a partir del diff de la API en lugar de reglas escritas por alguien, y solo sugiere; no reescribe nada. |
| Bots de dependencias: Renovate, Dependabot | Abren solicitudes de extracción que actualizan tus versiones fijadas | La acción de GitHub puede ejecutarse en esas solicitudes de extracción y listar las APIs cambiadas, las que usa tu código primero. |
| Benchmarks: GitChameleon 2.0, VersiCode, CodeUpdateArena, LibEvolutionEval | Miden modelos en conjuntos de tareas fijos construidos a partir de cambios de versiones reales, o sintéticos (CodeUpdateArena); GitChameleon 2.0 ejecuta pruebas unitarias | Comparan modelos en general, y algunos verifican el comportamiento ejecutando pruebas. since-cutoff examina las versiones fijadas de un proyecto, de forma estática: un verificador de tipos ve nombres, parámetros y deprecaciones, no comportamiento. |
--compare signatures en since-cutoff run da al modelo la firma de la nueva versión y el primer párrafo de su docstring. Es un sustituto local de una consulta de documentación, no Context7.
Dos herramientas más pequeñas trabajan en el mismo problema: cutoff sondea una biblioteca que mantienes ejecutando programas escritos por el modelo contra su versión actual, y postcut convierte un Gemfile.lock de Ruby en un resumen de cambios desde la fecha de corte. since-cutoff está construido sobre griffe, basedpyright, models.dev y rich.
Usar since-cutoff con Context7
since-cutoff scan te indica qué APIs consultar; Context7 puede proporcionar la documentación. Nombra la versión que fijas al preguntar ("anthropic 1.8.0"). Context7 la coincide solo cuando los propietarios de la biblioteca añadieron esa versión: el 2026-09-27, /openai/openai-python ofrecía v1.68.0, v1_105_0, v2.8.1 y v2.11.0, y /anthropics/anthropic-sdk-python no ofrecía ninguna, por lo que puedes obtener la documentación de la rama predeterminada.
Investigación relacionada
- APIs deprecadas en la finalización de código. Wang et al., LLMs Meet Library Evolution: Evaluating Deprecated API Usage in LLM-based Code Completion (ICSE 2025; arXiv:2406.09834, titulado inicialmente How and Why LLMs Use Deprecated APIs in Code Completion? An Empirical Study). 7 modelos, 145 mapeos de una API deprecada a su reemplazo en 8 bibliotecas de Python, 28,125 indicaciones de finalización. La mayoría de las finalizaciones no usaron ninguna de las dos APIs. De las que usaron una de las dos (las finalizaciones "plausibles" del artículo), el 25-38% usó la deprecada en todo el conjunto de datos: 70-90% cuando la indicación provenía de código que usaba la API deprecada, 9-18% cuando provenía de código actualizado. Se probaron dos correcciones de referencia en indicaciones actualizadas donde un modelo había usado la API deprecada. ReplaceAPI intercambia los tokens de la API deprecada por el reemplazo durante la decodificación y deja que el modelo termine la línea: el reemplazo se usó entonces en el 85.2-99.6% de los casos en los seis modelos abiertos (necesita control de la decodificación, por lo que no funciona con GPT-3.5). InsertPrompt añade el comentario
# {dep} is deprecated, use {rep} instead and revise the return value and arguments.y regenera: 25.7-97.2%, según el modelo, que los autores consideran aún no efectivo o preciso. Las notas de since-cutoff se acercan a InsertPrompt, movidas al archivo de instrucciones del proyecto;since-cutoff runlas mide en tareas reservadas en lugar de asumir que funcionan. - La documentación en contexto no es suficiente por sí sola. Ashik et al., When LLMs Lag Behind: Knowledge Conflicts from Evolving APIs in Code Generation (arXiv:2604.09515, preimpresión de 2026). 270 actualizaciones de API reales (45 deprecadas o eliminadas, 128 modificadas, 97 nuevas) de versiones de 8 bibliotecas de Python después de diciembre de 2023, y 11 modelos de 4 familias con fechas de corte de entrenamiento anteriores a esa fecha. Dada solo una descripción de la actualización, los modelos la adoptaron al menos parcialmente en el 74.64% de las respuestas (juzgado por GPT-5 mini), y el 42.55% de esas respuestas se ejecutaron en la versión de la biblioteca que introdujo la actualización; con la documentación de la API también, el 92.87% la adoptó y el 66.36% se ejecutó. Añadir indicaciones de cadena de pensamiento y autorreflexión elevó la tasa de ejecución en un 11.33% adicional, una ganancia relativa en lugar de puntos porcentuales. De las respuestas que no adoptaron la actualización, el 42.1% la ignoró por completo y el 16.4% usó la API antigua; de las respuestas que adoptaron pero aún fallaron al ejecutarse en la mejor configuración, la causa más común relacionada con la actualización fueron parámetros incorrectos (26.6% de esos fallos). Por eso since-cutoff verifica el código contra tu versión exacta, y por qué
since-cutoff runvuelve a probar el modelo con las notas en lugar de asumir que se siguen. - Benchmarks. GitChameleon 2.0: 328 problemas de finalización de Python, cada uno vinculado a versiones específicas de bibliotecas y verificado por pruebas unitarias ejecutables; los modelos empresariales alcanzan 48-51% en la línea base, la documentación recuperada añade hasta unos 10 puntos (GPT-4.1: 48.5% a 58.5%) y la autodepuración unos 10-20. VersiCode: finalización de código específica de versión y migración de código consciente de versión en más de 300 bibliotecas de Python y más de 2,000 versiones a lo largo de 9 años. CodeUpdateArena: edición de conocimiento para 54 funciones de 7 paquetes de Python, con actualizaciones sintéticas generadas por GPT-4 y 670 ejemplos de síntesis de programas; anteponer la documentación de la actualización no permitió que los modelos abiertos (DeepSeek, CodeLlama) la usaran. LibEvolutionEval (NAACL 2025): finalización en línea específica de versión en 8 bibliotecas; la documentación específica de versión recuperada y las indicaciones ayudan.
Estos estudios miden muchos modelos en conjuntos de tareas fijos; GitChameleon 2.0 y Ashik et al. ejecutan el código generado. since-cutoff hace algo más limitado: para un proyecto lista los cambios desde una versión de comparación, los que usa tu código primero, y run verifica las respuestas de un modelo de forma estática. No puede ver cambios de comportamiento detrás de una firma sin cambios, que las pruebas que ejecutan el código sí pueden.
Contribuir
since-cutoff es joven. La ayuda más útil ahora mismo:
- Ejecútalo en tu proyecto y publica lo que encuentre, incluidos los falsos positivos, en Comparte tus resultados.
- Toma un buen primer problema: tareas pequeñas y autónomas, como otro formato de archivo de bloqueo o un ajuste preestablecido de proveedor.
- Piezas más grandes están etiquetadas como se busca ayuda, por ejemplo soporte de TypeScript.
- Informa un error o un resultado extraño en los problemas.
CONTRIBUTING.md explica el diseño del código y las verificaciones; la suite de pruebas sin conexión ejecuta todo el flujo con una biblioteca de juguete y un modelo con guion, por lo que no se necesita clave de API. Problemas de seguridad: SECURITY.md.
Cita
Si usas since-cutoff en investigación, por favor cítalo (ver CITATION.cff).
Licencia
MIT © Mohammad Hijjawi