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 logo

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.

Your coding model learned your libraries before they changed. Claude Opus 4.6 on one sample project, measured with since-cutoff 0.1.0: on 7 of 16 probed API changes it used a name or parameter that has since been removed; with the notes, 5% to 65% of 20 held-out tasks were correct. Try it: uvx since-cutoff scan (no model calls, no API key).

PyPI Python 3.10+ CI License: MIT Status: beta

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):

bibliotecaversión en el cortefijadaqué cambió
anthropic0.60.01.8.0messages.create(temperature=..., top_p=..., top_k=...) ya no se acepta
huggingface-hub0.34.32.0.0hf_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-core0.3.721.6.5retriever.get_relevant_documents() y llm.predict() eliminados
openai1.98.03.19.221 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):

Bar chart: for each of 21 models from 8 vendors, how many of 36 Python AI libraries broke their public API and how many are on a new major version since the model's training cutoff. From 21 of 36 for GPT-4o (13 of the libraries did not exist yet) to 33 of 36 for models with early-2025 cutoffs, and 20 of 36 for Claude Opus 5.5 (June 2026).

since-cutoff hace tres cosas al respecto:

  1. scan encuentra, 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.
  2. run pide 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.
  3. 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:

since-cutoff scan --model anthropic:claude-sonnet-4-5 on the sample project: 7 of 9 dependencies changed their API after the cutoff; static diff: 317 breaking changes, 23 new deprecations; a table of each package's pinned version, version at the cutoff and number of changes, and one example change per package

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 scan o llama a la herramienta MCP project_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

--modelusanecesita
claude-code (predeterminado cuando ninguna configuración nombra un modelo)tu inicio de sesión de Claude Code (suscripción o clave), modelo actualla CLI de claude
claude-code:sonnet, claude-code:claude-haiku-4-5un modelo específico de Claudela CLI de claude
anthropic:<model>API de AnthropicANTHROPIC_API_KEY
openai:<model>API de OpenAIOPENAI_API_KEY
openrouter:<vendor/model>OpenRouterOPENROUTER_API_KEY
deepseek:<model>API de DeepSeekDEEPSEEK_API_KEY
ollama:<model>Ollama localOllama 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"):

  1. SINCE_CUTOFF_MODEL (una especificación completa como openai:gpt-5.4) siempre gana.
  2. Dentro de Claude Code (que establece CLAUDECODE=1 para los comandos que ejecuta), solo cuenta la configuración de Claude Code: ANTHROPIC_MODEL, luego el .claude/settings.local.json y .claude/settings.json del proyecto, luego ~/.claude/settings.json.
  3. En otros lugares, la configuración más específica gana: primero ANTHROPIC_MODEL o AIDER_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:
agenteconfiguración del proyectoconfiguració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
OpenCodeopencode.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.5Claude Opus 4.6
corte de entrenamientoFeb 2025May 2025
cambios de API probados2016
obsoletos / incorrectos / deprecados / correctos5 / 1 / 2 / 127 / 0 / 3 / 6
bibliotecas con uso obsoleto3 de 5 probadas2 de 4 probadas
notas escritas (con un ejemplo que pasa la verificación de tipos)8 (7), alrededor de 391 tokens10 (7), alrededor de 437 tokens
correctos reservados, sin -> con notas14% -> 57% (14 pares)5% -> 65% (20 pares)
APIs previamente correctas después de las notas6/6 aún correctas6/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.

since-cutoff 0.1.0 run on Claude Opus 4.6: stale API use in 2 of 4 probed dependencies; 16 API changes probed: 7 stale, 0 wrong, 3 deprecated, 6 correct; 10 notes; held-out tasks correct without -> con notas: 5% -> 65% (20 tareas emparejadas); una lista de las llamadas obsoletas

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)

since-cutoff 0.1.0 run on Claude Haiku 4.5: stale API use in 3 of 5 probed dependencies; 20 API changes probed: 5 stale, 1 wrong, 2 deprecated, 12 correct; 8 notes; held-out tasks correct without -> con notas: 14% -> 57% (14 tareas emparejadas)

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:

herramientarespuestas
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
entradapredeterminado
modelrequeridoprovider:model como para --model; solo se usa su corte de entrenamiento
working-directory.el directorio del proyecto
only, excludenombres de PyPI separados por comas
cutoffanula el corte de entrenamiento (YYYY-MM o YYYY-MM-DD)
fail-on-changesfalsefalla el paso cuando una dependencia cambió su API después del corte
step-summarytrueañade el resumen de Markdown al resumen del trabajo
cachetrueconserva 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)
argsmás argumentos de since-cutoff scan, p. ej. --all-deps --limit 20
since-cutoff-version0.3.2la 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:

Three stages. Scan, with no model calls: the lockfile gives your exact versions, then the release at the model's cutoff, then a static API diff with griffe. Probe: short tasks that need the change, the model answers from memory, basedpyright checks the answer against both versions. Fix and verify: a model-written note is kept only if its example type-checks, otherwise the change is stated from the API diff; held-out tasks are answered without and with the notes, and --apply writes a block into AGENTS.md.

resultadosignificado
obsoletoel 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ó
incorrectoinválido para tu versión, pero no explicado por un cambio (API alucinada o mal utilizada)
deprecadoválido, pero usa una API marcada @deprecated en tu versión
correctoválido para tu versión y realmente usa la API cambiada
intacto / fuera de tarea / inválido / errorno 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 path la muestra, since-cutoff cache clear la elimina). Con --apply escribe un bloque marcado en AGENTS.md/CLAUDE.md y deja el resto del archivo byte por byte sin cambios; since-cutoff unapply elimina el bloque.
  • Sin telemetría, sin cuenta, sin datos personales. Las re-ejecuciones provienen de la caché, por lo que son gratuitas y reproducibles (--fresh vuelve 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. scan tambié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__, pero run no 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 mediante run, 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.

herramientaqué hacecó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-serverBúsqueda de documentación para agentes, en el momento de la respuesta; docs-mcp-server puede indexar documentación localmenteIgual que Context7.
library-skillsBibliotecas 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 bibliotecaEscritas 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/skillsComplementos de Claude Code, Codex y Cursor y archivos SKILL.md para Pydantic, Pydantic AI y Logfire, instalados desde el repositorioGuí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, DependabotAbren solicitudes de extracción que actualizan tus versiones fijadasLa 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, LibEvolutionEvalMiden modelos en conjuntos de tareas fijos construidos a partir de cambios de versiones reales, o sintéticos (CodeUpdateArena); GitChameleon 2.0 ejecuta pruebas unitariasComparan 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 run las 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 run vuelve 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:

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