since-cutoff

Informa ao seu agente de codificação o que mudou na API pública de uma biblioteca Python desde o corte de treinamento. Ferramentas: api_changes (um pacote, por modelo ou data de corte) e project_changes (todas as dependências no lockfile de um projeto). Diff estático, stdio local, sem chave de API.

Documentação

since-cutoff logo

since-cutoff

Para projetos Python escritos com um agente de codificação: o since-cutoff encontra as APIs de dependências que mudaram após o corte de treinamento do modelo, mede quais delas o modelo erra e corrige essas com notas curtas em AGENTS.md, cada uma verificada por um verificador de tipos ou tirada diretamente do diff da 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

O problema

Todo modelo tem um corte de treinamento; seu lockfile continua avançando. Quando uma biblioteca muda sua API pública após o corte, um modelo que aprendeu a versão antiga continua escrevendo as chamadas antigas. Parte desse código falha na importação ou na chamada. Parte ainda funciona, porque o caminho antigo está apenas obsoleto.

Algumas das mudanças que o since-cutoff scan encontra para o Claude Sonnet 4.5 (corte de treinamento em julho de 2025) no projeto de exemplo, que fixa seis das nove dependências em versões atuais (para as outras três, que não estão fixadas, a ferramenta usa a versão mais recente):

bibliotecaversão no cortefixadao que mudou
anthropic0.60.01.8.0messages.create(temperature=..., top_p=..., top_k=...) não é mais aceito
huggingface-hub0.34.32.0.0hf_hub_download(resume_download=..., force_filename=..., local_dir_use_symlinks=...) saiu da assinatura em 1.0 (2.0.0 ainda os aceita em tempo de execução, os ignora e avisa)
langchain-core0.3.721.6.5retriever.get_relevant_documents() e llm.predict() removidos
openai1.98.03.19.221 mudanças que quebram, 6 novas deprecações

Nesse projeto, 7 de 9 dependências mudaram sua API pública após o corte. O diff estático sinaliza 317 mudanças que quebram e 23 novas deprecações; algumas são internas, que as sondas ignoram.

Não é um modelo ou um fornecedor. Em 36 bibliotecas de IA Python amplamente usadas e 21 modelos da OpenAI, Anthropic, Google, xAI, DeepSeek, Qwen, Moonshot e Mistral, até o modelo mais novo testado (Claude Opus 5.5, corte de junho de 2026) é anterior a uma quebra de API pública em 20 das 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).

O since-cutoff faz três coisas sobre isso:

  1. scan encontra, para cada dependência, a versão mais recente na data ou antes do corte do modelo e compara sua API pública com a versão que você fixa. Sem chamadas de modelo, sem chave de API.
  2. run pede ao modelo tarefas curtas de codificação que precisam das APIs alteradas, sem ferramentas e sem documentação, e pontua cada resposta com um verificador de tipos contra ambas as versões: desatualizada, errada, obsoleta ou correta. Nenhum LLM julga nada.
  3. Notas: para cada falha, escreve uma nota de uma linha em AGENTS.md / CLAUDE.md. Mantém uma nota escrita pelo modelo apenas se o exemplo dela passar na verificação de tipos contra sua versão; caso contrário, usa uma declaração simples da mudança do diff da API. Depois, testa novamente o modelo em tarefas reservadas com e sem as notas.

O mesmo diff está disponível para agentes por meio de um servidor MCP e para CI por meio de uma GitHub Action e um hook de pre-commit.

Início 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

Ou instale com pipx install since-cutoff (ou pip install since-cutoff) e execute since-cutoff. Execute a partir da raiz do seu projeto: ele lê uv.lock, poetry.lock, pdm.lock, pylock.toml, Pipfile.lock, requirements*.txt, pyproject.toml, Pipfile ou um .venv (não setup.py ou setup.cfg). Sem --model, ele testa o modelo com o qual seu agente de codificação está configurado, a partir das configurações do Claude Code, Codex, OpenCode ou Aider; para qualquer outro modelo, passe --model (veja Escolhendo o modelo). scan é gratuito; run envia prompts ao provedor do modelo e usa seus créditos de API ou uso do Claude Code.

O que o scan imprime para o projeto de exemplo:

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

No Claude Code

/plugin marketplace add MohammadHijjawi97/since-cutoff
/plugin install since-cutoff@since-cutoff

Depois peça ao Claude para "verificar em quais das nossas dependências você está desatualizado", ou execute /since-cutoff:since-cutoff. A skill executa a CLI; a medição em si é feita por uma cópia nova, sem ferramentas, do modelo, então o agente não pode se avaliar. O plugin também inicia o servidor MCP, para que o Claude possa consultar as mudanças de uma biblioteca antes de escrever código.

Em outros agentes de codificação

npx skills add MohammadHijjawi97/since-cutoff

Isso instala a mesma skill por meio da CLI aberta de skills para Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode e outros agentes que leem SKILL.md. O since-cutoff lê o modelo das configurações do Codex, OpenCode e Aider também; para outros agentes, diga a ele qual modelo testar, por exemplo since-cutoff scan --model openai:gpt-5.4. Adicione o servidor MCP como mostrado abaixo.

Prompts que funcionam bem:

  • "Quais das nossas dependências mudaram sua API pública após o seu corte de treinamento?" O agente executa since-cutoff scan ou chama a ferramenta MCP project_changes.
  • "Meça quais dessas mudanças você realmente erra e adicione as notas ao AGENTS.md." O agente pergunta primeiro e depois executa since-cutoff run --quick --apply.
  • "Antes de escrever o código httpx, verifique o que mudou no httpx desde o seu corte." O agente chama a ferramenta MCP api_changes.

Escolhendo o modelo

--modelusaprecisa
claude-code (padrão quando nenhuma configuração nomeia um modelo)seu login do Claude Code (assinatura ou chave), modelo atuala CLI claude
claude-code:sonnet, claude-code:claude-haiku-4-5um modelo Claude específicoa CLI claude
anthropic:<model>API da AnthropicANTHROPIC_API_KEY
openai:<model>API da OpenAIOPENAI_API_KEY
openrouter:<vendor/model>OpenRouterOPENROUTER_API_KEY
deepseek:<model>API da DeepSeekDEEPSEEK_API_KEY
ollama:<model>Ollama localOllama em execução
openai-compatible:<model>qualquer servidor compatível com OpenAI--base-url, opcional OPENAI_API_KEY

Sem --model, o since-cutoff 0.3.0 e versões posteriores testam o modelo com o qual seu agente de codificação está configurado, e a linha do modelo diz de onde veio ("modelo de .claude/settings.json"):

  1. SINCE_CUTOFF_MODEL (uma especificação completa como openai:gpt-5.4) sempre vence.
  2. Dentro do Claude Code (que define CLAUDECODE=1 para os comandos que executa), apenas as configurações do Claude Code contam: ANTHROPIC_MODEL, depois o .claude/settings.local.json e .claude/settings.json do projeto, depois ~/.claude/settings.json.
  3. Em outros lugares, a configuração mais específica vence: primeiro ANTHROPIC_MODEL ou AIDER_MODEL, depois as configurações do projeto, da pasta mais próxima até a raiz do repositório (nunca a pasta pessoal), depois as configurações do usuário. Em uma pasta, os agentes contam nesta ordem:
agenteconfigurações do projetoconfigurações do usuário
Claude Code.claude/settings.local.json, .claude/settings.json~/.claude/settings.json
Codex.codex/config.toml, com seu perfil selecionado$CODEX_HOME/config.toml ou ~/.codex/config.toml
OpenCodeopencode.json, opencode.jsonc~/.config/opencode/
Aider.aider.conf.yml, com os aliases do Aider (4o, flash, r1, ...)~/.aider.conf.yml

Quando nenhuma configuração nomeia um modelo, ele testa o modelo padrão do Claude Code e diz isso. Apenas os campos de modelo são lidos, e um nome de modelo que ele não consegue identificar interrompe a execução com uma mensagem nomeando a configuração. Um modelo que um agente alcança por meio de outro serviço (GitHub Copilot, Amazon Bedrock, Vertex AI) é nomeado pelo seu fabricante, então run chama a API do fabricante (openai: precisa de OPENAI_API_KEY).

Os cortes de treinamento vêm de models.dev (um snapshot é incluído para uso offline). since-cutoff models sonnet os lista; --cutoff 2025-07 substitui a data, e since-cutoff scan --cutoff 2025-07 sem --model verifica apenas contra essa data. scan precisa apenas do corte, então também aceita um id de modelo sem provedor (claude-haiku-4-5, sonnet) ou com qualquer provedor que o models.dev liste (google:gemini-2.5-pro, incluindo ids do Amazon Bedrock e Vertex AI); run precisa de um provedor da tabela acima.

Resultados

Dois modelos Claude no projeto de exemplo de 9 dependências em examples/agent-app, medidos com o since-cutoff 0.1.0, com o Claude Opus 4.6 escrevendo as tarefas e notas:

Claude Haiku 4.5Claude Opus 4.6
corte de treinamentofev 2025mai 2025
mudanças de API sondadas2016
desatualizadas / erradas / obsoletas / corretas5 / 1 / 2 / 127 / 0 / 3 / 6
bibliotecas com uso desatualizado3 de 5 sondadas2 de 4 sondadas
notas escritas (com um exemplo que passa na verificação de tipos)8 (7), cerca de 391 tokens10 (7), cerca de 437 tokens
corretas reservadas, sem -> com notas14% -> 57% (14 pares)5% -> 65% (20 pares)
APIs anteriormente corretas após as notas6/6 ainda corretas6/6 ainda corretas

Reservadas são paráfrases das tarefas com as quais cada mudança com falha foi sondada; cada uma é respondida duas vezes, sem e com as notas, e pontuada da mesma forma. A última linha verifica novamente APIs que o modelo já acertou, para detectar notas que pioram as coisas.

Neste exemplo, o modelo mais forte não foi mais seguro: o Opus 4.6 escreveu APIs que foram removidas após seu corte, incluindo anthropic.HUMAN_PROMPT com client.completions. Código desatualizado de ambas as execuções, cada um válido para a versão de comparação e rejeitado pelo verificador de tipos para a versão fixada: messages.create(temperature=...) (anthropic 1.8), hf_hub_download(resume_download=...), local_dir_use_symlinks=..., force_filename=... e proxies=... (huggingface-hub 2.0), e client.beta.vector_stores (openai 3.x). Em tempo de execução, o anthropic 1.8.0 levanta TypeError para temperature; o huggingface-hub 2.0.0 ainda aceita esses quatro argumentos de download, os ignora e avisa.

As notas escritas na execução do Claude Haiku 4.5 (trecho, verbatim):

<!-- 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 -->

A nota do huggingface-hub não está totalmente correta: resume_download saiu da assinatura em 1.0, não 2.0.0, e o 2.0.0 ainda o aceita em tempo de execução, o ignora e avisa (fonte). Omiti-lo ainda é o conselho certo.

O resumo do terminal da execução do Claude Opus 4.6, registrado com 0.1.0. Os resultados da sonda são os da tabela acima. As contagens de diff no cartão são as do 0.1.0 ("725 mudanças sinalizadas"); após correções no diff, o scan no 0.2.0 relata 513 mudanças que quebram e 48 novas deprecações para o mesmo corte. A contagem de "mudanças corrigidas" do cartão e seu IC de 95% também seguem o 0.1.0: o intervalo pertence a essa contagem, não às taxas de 5% -> 65%, e versões até 0.2.0 contavam uma mudança como corrigida mesmo quando uma resposta reservada já estava correta sem as 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 -> com notas: 5% -> 65% (20 tarefas pareadas); uma lista das chamadas desatualizadas

O mesmo resumo para a execução do Claude Haiku 4.5 (também 0.1.0; a verificação no 0.2.0 relata 491 mudanças que quebram e 50 novas deprecações para seu 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 -> com notas: 14% -> 57% (14 tarefas pareadas)

Amostras pequenas, dois modelos, um projeto: trate isto como uma demonstração do método, não um benchmark. Cada execução grava seu relatório completo (cada tarefa, resposta e erro do type-checker) em `.since-cutoff/report.md`. Para repetir o experimento com a versão atual (seu diff e ranking mudaram, então as sondas não serão 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, uma execução também pode salvar suas tarefas: adicione `--tasks-out tasks.json`, e qualquer pessoa pode repetir a execução exatamente nas mesmas tarefas com `--tasks-from tasks.json`, para outro modelo ou outro conjunto de notas. Os nomes de arquivo que escreveram as tarefas (modelo, versão do prompt, versão do since-cutoff), e uma execução em tarefas reutilizadas relata isso ([detalhes](https://github.com/MohammadHijjawi97/since-cutoff/blob/main/docs/how-it-works.md#2-probe)). Resultados dos seus próprios projetos são muito bem-vindos em [Compartilhe seus resultados](https://github.com/MohammadHijjawi97/since-cutoff/discussions/6).

Como a medição funciona e o que esses números mostram e não mostram, em mais detalhes: o texto explicativo.

Use-o de qualquer agente (MCP)

since-cutoff mcp é um servidor MCP que permite a um agente de codificação perguntar "o que mudou nesta biblioteca desde meu corte de treinamento?" antes de escrever código. Ele tem três ferramentas somente leitura:

ferramentarespostas
api_changes(package, model, symbol=...)o que mudou em uma biblioteca entre a versão no corte do modelo e a mais recente (ou uma versão dada), quebras graves primeiro
project_changes(project_dir, model)o mesmo para cada dependência de um projeto em sua versão fixada, começando com APIs que seu código já usa
model_cutoff(model)o corte de treinamento de um modelo, de models.dev

O agente passa seu próprio ID de modelo, então a resposta cobre o que mudou após o corte de treinamento daquele modelo. As ferramentas leem PyPI e fontes de pacotes estaticamente: sem chamadas de modelo, sem chave de API, sem execução de código de pacote.

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) e 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 faz o uvx pegar novos lançamentos em vez de reutilizar a primeira versão que armazenou em cache (o próprio .mcp.json do plugin fixa o lançamento exato). Se o cliente não conseguir encontrar uvx, instale uv ou forneça o caminho completo (which uvx). O servidor está listado no Registro MCP como io.github.MohammadHijjawi97/since-cutoff.

A primeira chamada project_changes em um projeto maior baixa os wheels de cada dependência que mudou e pode levar vários minutos (pacotes muito grandes como transformers levam mais tempo). Os resultados são armazenados em cache, então chamadas posteriores levam segundos. Para aquecer o cache, execute since-cutoff scan no projeto uma vez; ele compartilha o cache com o servidor. Clientes com um tempo limite de ferramenta padrão curto podem precisar de um maior, como no exemplo do Codex acima. project_changes mantém sua resposta abaixo de cerca de 24.000 caracteres: dependências alteradas que não cabem recebem uma linha cada, e passá-las em only lista suas mudanças.

O que api_changes("huggingface-hub", model="claude-haiku-4-5") retornou em 0.2.0 (saída real, aparada; versões posteriores refinam o diff, então suas contagens diferem ligeiramente):

# 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.

Com symbol="hf_hub_download" ele lista apenas as 8 mudanças nessa função (resume_download=, force_filename=, local_dir_use_symlinks= e proxies=, na função e em HfApi). symbol também aceita uma chamada da forma como o código a escreve: client.messages.create encontra as mudanças em Messages.create. O diff lê apenas assinaturas: esses quatro parâmetros saíram da assinatura no huggingface-hub 1.0, mas 2.0.0 ainda os aceita em tempo de execução, os ignora e avisa.

Use em CI

GitHub Action

Escaneia o projeto em cada pull request e adiciona um resumo à página do job: por dependência, a versão no corte do modelo, a versão que você fixa e as principais mudanças, com mudanças em nomes que seu código usa primeiro. Como scan, ele apenas lê PyPI e models.dev: sem chamadas de modelo, sem chave 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
entradapadrão
modelobrigatórioprovider:model como para --model; apenas seu corte de treinamento é usado
working-directory.o diretório do projeto
only, excludenomes PyPI separados por vírgula
cutoffsubstituir o corte de treinamento (YYYY-MM ou YYYY-MM-DD)
fail-on-changesfalsefalhar o passo quando uma dependência mudou sua API após o corte
step-summarytrueadicionar o resumo Markdown ao resumo do job
cachetruemanter metadados PyPI, fontes de pacotes e diffs de API entre execuções (também quando fail-on-changes falha o job)
argsmais argumentos since-cutoff scan, ex. --all-deps --limit 20
since-cutoff-version0.3.2o lançamento since-cutoff para executar, ou latest

Saídas: changed-packages (separadas por vírgula), changes (mudanças que quebram), deprecations, markdown (o caminho do resumo, por exemplo para postá-lo como comentário em pull request) e report (o caminho do relatório completo). Uma mudança alcançável por vários caminhos de importação é contada uma 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

O hook executa quando um lockfile, um arquivo de requisitos ou pyproject.toml muda, e imprime o escaneamento. Dê a ele --model em args. Ele precisa de PyPI, então pule-o no pre-commit.ci (ci: {skip: [since-cutoff-scan]}).

Outro 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 o resumo no stdout, e apenas o progresso e o caminho do relatório no stderr, como --json faz. Em um arquivo, um pipe ou um log de CI não há barra de progresso ao vivo, e a saída é disposta com 160 colunas de largura (COLUMNS define outra largura). Códigos de saída: 0 ok, 1 erro (por exemplo, run não conseguiu sondar nenhuma mudança de API ou pontuar nenhuma resposta de modelo), 2 erro de uso, 3 uso de API desatualizado encontrado com run --fail-on-stale, ou mudanças de API encontradas com scan --fail-on-changes, 141 a saída foi fechada cedo (canalizada para head, por exemplo).

Como funciona

Três estágios. O primeiro não precisa de modelo; nos outros dois, um type checker pontua cada resposta e verifica cada nota que o modelo escreve:

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
desatualizadoo código é válido para a versão de comparação (a do corte do modelo) e inválido para a sua, e o erro envolve uma API que mudou
erradoinválido para sua versão, mas não explicado por uma mudança (API alucinada ou mal usada)
obsoletoválido, mas usa uma API marcada @deprecated em sua versão
corretoválido para sua versão e realmente usa a API alterada
intocado / fora da tarefa / inválido / erronão contado em nenhuma taxa, e sempre relatado

Desde 0.3.0, o resultado retido dá as taxas em nível de tarefa sem -> com notas (com o número de tarefas pareadas e mudanças de API por trás delas), sua diferença com um intervalo bootstrap de 95% que reamostra mudanças de API, as mudanças que as notas corrigiram (errado sem, correto com) com um intervalo Wilson de 95%, as mudanças que quebraram, um teste de sinal exato de corrigido contra quebrado, e os pares retidos não contados, por motivo. A verificação de regressão relata quantas APIs anteriormente corretas ainda estão corretas com as notas.

run --compare template,signatures (0.3.0 e posteriores) também responde às tarefas retidas e verificações de regressão com notas de linha de base que não precisam de modelo: template declara cada mudança que falha em uma frase do diff de API, e signatures dá a nova assinatura e o primeiro parágrafo do docstring de cada API alterada, ou do substituto que sua biblioteca nomeia. Todos os blocos são pontuados nos mesmos pares, contra as mesmas respostas sem notas, e o tamanho de cada bloco é mostrado em tokens, então uma execução mostra o que as próprias notas do since-cutoff adicionam sobre eles.

Tudo é pontuado por um type checker contra as versões exatas dos pacotes, cada uma em um ambiente isolado com as dependências de tempo de execução desse pacote. Nenhum LLM julga nada, e cada número remonta a results.json. Detalhes: docs/how-it-works.md.

O que executa, envia e armazena

  • Não executa código de pacote nem código escrito por modelo. Pacotes são lidos estaticamente (griffe com inspeção desligada; apenas arquivos .py/.pyi são extraídos, com verificações de caminho e tamanho). As respostas do modelo são apenas type-checkadas, localmente, com basedpyright.
  • Busca metadados públicos de pacotes e wheels do PyPI, e cortes de modelos do models.dev (um snapshot é incluído para uso offline). Dependências de git, caminho, workspace e índices privados nunca são consultadas no PyPI público por nome.
  • Envia prompts apenas em run, e apenas para o provedor de modelo que você escolher: nomes de pacotes, versões, assinaturas públicas e docstrings das APIs alteradas, as tarefas geradas e, para notas, as próprias respostas do modelo. Nunca seu código-fonte. scan, o servidor MCP, o GitHub Action e o hook pre-commit não enviam nada para nenhum modelo.
  • Armazena resultados em .since-cutoff/ no seu projeto (ele se ignora no git) e um cache local (since-cutoff cache path mostra, since-cutoff cache clear remove). Com --apply ele escreve um bloco marcado em AGENTS.md/CLAUDE.md e deixa o resto do arquivo inalterado byte por byte; since-cutoff unapply remove o bloco.
  • Sem telemetria, sem conta, sem dados pessoais. Re-execuções vêm do cache, então são gratuitas e reproduzíveis (--fresh pergunta ao modelo novamente). Veja PRIVACY.md.

Limitações

  • Apenas Python por enquanto. TypeScript (diffs .d.ts, tsc) é o próximo (#1).
  • Um type checker vê nomes errados, parâmetros errados e deprecações PEP 702. Ele não pode ver mudanças de comportamento por trás de uma assinatura inalterada, ou deprecações que apenas avisam em tempo de execução. scan também lista deprecações declaradas com o decorador próprio de uma biblioteca (nome contendo "deprecat") e nomes removidos que um módulo ainda serve com um aviso através de __getattr__, mas run não os sonda.
  • O diff cobre a API pública: nomes _private, e suítes de teste, benchmarks e exemplos enviados dentro de um pacote, são ignorados.
  • As sondas cobrem uma amostra classificada das mudanças que quebram (símbolos que seu código já usa primeiro), não todas.
  • "A versão de comparação" é a versão mais recente na ou antes da data de corte. Modelos conhecem lançamentos recentes menos bem, então a desatualização real pode começar mais cedo.
  • Tarefas retidas são paráfrases da mesma mudança: elas mostram que uma nota corrige aquela mudança, não que o modelo melhorou em geral.

Para que o corte de treinamento é usado

A data de corte escolhe um ponto de comparação. Não é uma afirmação sobre o que um modelo memorizou. since-cutoff pega a data do models.dev (ou --cutoff); um mês significa seu último dia (2025-07 é 31 de julho de 2025). Para cada dependência, pega o lançamento final, não-yanked mais recente enviado na ou antes dessa data (um pré-lançamento apenas se o pacote não tinha lançamento final até então, nunca um lançamento de desenvolvimento), e difere a API pública desse lançamento contra sua versão bloqueada. Esse diff é uma lista de candidatos: mudanças de API que os dados de treinamento do modelo provavelmente não incluem.

A data decide três coisas:

  • quais pacotes são diferenciados: um pacote cuja versão bloqueada não é mais nova que esse lançamento não tem nada para diferenciar, e um pacote lançado pela primeira vez após a data é listado como novo;
  • em run, com quais versões das próprias dependências desse lançamento o lado antigo é type-checkado (as mais recentes que cada requisito permitia nessa data);
  • o lado "antigo" de cada sonda em run, então uma resposta que é válida lá e inválida para sua versão, com o erro em uma API alterada, é "desatualizada" em vez de "errada". Um modelo pode conhecer um lançamento após seu corte declarado ou não conhecer lançamentos pouco antes dele, então a varredura pode listar mudanças que o modelo já lida e perder algumas que não lida. Se o modelo realmente escreve a API antiga é mostrado apenas por run, que pergunta a ele: sem ferramentas, informado qual versão o projeto fixa.

Como se compara

since-cutoff responde uma pergunta para um projeto: quais APIs públicas das versões que você fixa mudaram desde o lançamento apontado pelo corte de treinamento de um modelo, começando pelas que seu código usa? since-cutoff run adiciona duas perguntas opcionais: este modelo realmente as erra, e uma nota curta corrige? A maioria das ferramentas abaixo responde uma pergunta diferente ("o que a documentação da biblioteca diz agora?") e funciona bem em conjunto.

ferramentao que fazcomo since-cutoff se relaciona
Context7 (servidor MCP e CLI ctx7)O agente chama resolve-library-id e query-docs para puxar trechos de documentação para seu contexto enquanto trabalha. Ele serve uma versão específica (/org/project/version) quando os mantenedores da biblioteca adicionaram essa versão (tags ou branches git, no máximo 20); caso contrário, serve o branch indexado. Funciona sem chave de API em um limite de taxa anônimo mais baixo.Complementar. Context7 fornece documentação; não lê suas versões travadas nem verifica o código que o agente escreve. since-cutoff lista quais das suas APIs fixadas mudaram após o corte do modelo, as que seu código usa primeiro, para você saber onde uma consulta ou nota é necessária. Ao perguntar ao Context7, nomeie a versão que você fixa.
Outros servidores de documentação: Ref, docs-mcp-serverBusca de documentação para agentes, no momento da resposta; docs-mcp-server pode indexar documentação localmenteIgual ao Context7.
library-skillsBibliotecas como FastAPI e Streamlit enviam habilidades de agente dentro de seus pacotes; uvx library-skills vincula as habilidades das versões que você instalou em .agents/skills ou .claude/skills, para que atualizem com a bibliotecaEscritas pelos mantenedores e em sintonia com sua versão instalada: quando uma biblioteca envia uma, use-a. since-cutoff cobre pacotes que não enviam orientação e apenas declara mudanças na superfície da API.
Plugins de habilidades de fornecedores, ex.: pydantic/skillsPlugins para Claude Code, Codex e Cursor e arquivos SKILL.md para Pydantic, Pydantic AI e Logfire, instalados do repositórioOrientação dos mantenedores sobre como usar bem uma biblioteca; lançada com o repositório do plugin, não com a versão que você fixa. As notas de since-cutoff são escritas para seu lockfile.
Codemods: regras de ast-grep, openai migrate da OpenAI (Grit)Reescrevem código que já existe com regras sintáticas escritas à mão; o catálogo do ast-grep tem uma migração do SDK da OpenAI (openai.Completion.create(...) para client.completions.create(...))Para migrar código que você já tem, um codemod é a ferramenta certa. since-cutoff é sobre o código que um assistente escreve em seguida: encontra as mudanças a partir do diff da API em vez de regras escritas por alguém, e apenas sugere; não reescreve nada.
Bots de dependências: Renovate, DependabotAbrem pull requests que atualizam suas versões fixadasA GitHub Action pode rodar nesses pull requests e listar as APIs alteradas, as que seu código usa primeiro.
Benchmarks: GitChameleon 2.0, VersiCode, CodeUpdateArena, LibEvolutionEvalMedem modelos em conjuntos de tarefas fixos construídos a partir de mudanças reais de versão, ou sintéticas (CodeUpdateArena); GitChameleon 2.0 roda testes de unidadeEles comparam modelos em geral, e alguns verificam comportamento rodando testes. since-cutoff olha as versões fixadas de um projeto, estaticamente: um verificador de tipos vê nomes, parâmetros e depreciações, não comportamento.

--compare signatures em since-cutoff run dá ao modelo a assinatura da nova versão e o primeiro parágrafo de sua docstring. É um substituto local para uma consulta de documentação, não o Context7.

Duas ferramentas menores trabalham no mesmo problema: cutoff testa uma biblioteca que você mantém rodando programas escritos por modelos contra sua versão atual, e postcut transforma um Gemfile.lock Ruby em um resumo de mudanças desde o corte. since-cutoff é construído sobre griffe, basedpyright, models.dev e rich.

Usando since-cutoff com Context7

since-cutoff scan diz quais APIs consultar; Context7 pode fornecer a documentação. Nomeie a versão que você fixa ao perguntar ("anthropic 1.8.0"). Context7 a corresponde apenas quando os mantenedores da biblioteca adicionaram essa versão: em 2026-09-27, /openai/openai-python ofereceu v1.68.0, v1_105_0, v2.8.1 e v2.11.0, e /anthropics/anthropic-sdk-python não ofereceu nenhuma, então você pode obter a documentação do branch padrão.

Pesquisa relacionada

  • APIs depreciadas em conclusão de código. Wang et al., LLMs Meet Library Evolution: Evaluating Deprecated API Usage in LLM-based Code Completion (ICSE 2025; arXiv:2406.09834, primeiro intitulado How and Why LLMs Use Deprecated APIs in Code Completion? An Empirical Study). 7 modelos, 145 mapeamentos de uma API depreciada para sua substituição em 8 bibliotecas Python, 28.125 prompts de conclusão. A maioria das conclusões não usou nenhuma das APIs. Daquelas que usaram uma das duas (as conclusões "plausíveis" do artigo), 25-38% usaram a depreciada em todo o conjunto de dados: 70-90% quando o prompt veio de código que usava a API depreciada, 9-18% quando veio de código atualizado. Duas correções de base foram testadas em prompts atualizados onde um modelo havia usado a API depreciada. ReplaceAPI troca os tokens da API depreciada pela substituição durante a decodificação e deixa o modelo terminar a linha: a substituição foi então usada em 85,2-99,6% dos casos nos seis modelos abertos (precisa de controle da decodificação, então não GPT-3.5). InsertPrompt adiciona o comentário # {dep} is deprecated, use {rep} instead and revise the return value and arguments. e regenera: 25,7-97,2%, dependendo do modelo, que os autores julgam ainda não eficaz ou preciso o suficiente. As notas de since-cutoff são próximas ao InsertPrompt, movidas para o arquivo de instruções do projeto; since-cutoff run as mede em tarefas retidas em vez de assumir que funcionam.
  • Documentação em contexto não é suficiente por si só. Ashik et al., When LLMs Lag Behind: Knowledge Conflicts from Evolving APIs in Code Generation (arXiv:2604.09515, preprint de 2026). 270 atualizações reais de API (45 depreciadas ou removidas, 128 modificadas, 97 novas) de lançamentos de 8 bibliotecas Python após dezembro de 2023, e 11 modelos de 4 famílias com cortes de treinamento antes dessa data. Dada apenas uma descrição da atualização, os modelos a adotaram pelo menos parcialmente em 74,64% das respostas (julgado por GPT-5 mini), e 42,55% dessas respostas rodaram na versão da biblioteca que introduziu a atualização; com a documentação da API também, 92,87% a adotaram e 66,36% rodaram. Adicionar prompts de cadeia de pensamento e autorreflexão elevou a taxa executável em mais 11,33%, um ganho relativo em vez de pontos percentuais. Das respostas que não adotaram a atualização, 42,1% a ignoraram completamente e 16,4% usaram a API antiga; das respostas adotantes que ainda falharam em rodar na melhor configuração, a causa mais comum relacionada à atualização foram parâmetros errados (26,6% dessas falhas). É por isso que since-cutoff verifica código contra sua versão exata, e por que since-cutoff run re-testa o modelo com as notas em vez de assumir que são seguidas.
  • Benchmarks. GitChameleon 2.0: 328 problemas de conclusão Python, cada um vinculado a versões específicas de bibliotecas e verificado por testes de unidade executáveis; modelos empresariais alcançam 48-51% na linha de base, documentação recuperada adiciona até cerca de 10 pontos (GPT-4.1: 48,5% a 58,5%) e autodepuração cerca de 10-20. VersiCode: conclusão de código específica de versão e migração de código ciente de versão em mais de 300 bibliotecas Python e mais de 2.000 versões ao longo de 9 anos. CodeUpdateArena: edição de conhecimento para 54 funções de 7 pacotes Python, com atualizações sintéticas geradas por GPT-4 e 670 exemplos de síntese de programas; antepor a documentação da atualização não permitiu que modelos abertos (DeepSeek, CodeLlama) a usassem. LibEvolutionEval (NAACL 2025): conclusão inline específica de versão em 8 bibliotecas; documentação específica de versão recuperada e prompting ajudam.

Esses estudos medem muitos modelos em conjuntos de tarefas fixos; GitChameleon 2.0 e Ashik et al. rodam o código gerado. since-cutoff faz algo mais restrito: para um projeto, lista as mudanças desde um lançamento de comparação, as que seu código usa primeiro, e run verifica as respostas de um modelo estaticamente. Não pode ver mudanças de comportamento atrás de uma assinatura inalterada, que testes que rodam o código podem.

Contribuindo

since-cutoff é jovem. A ajuda mais útil agora:

CONTRIBUTING.md explica o layout do código e as verificações; a suíte de testes offline roda todo o pipeline com uma biblioteca de brinquedo e um modelo roteirizado, então nenhuma chave de API é necessária. Problemas de segurança: SECURITY.md.

Citação

Se você usar since-cutoff em pesquisa, por favor cite-o (veja CITATION.cff).

Licença

MIT © Mohammad Hijjawi