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
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.
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):
| biblioteca | versão no corte | fixada | o que mudou |
|---|---|---|---|
| anthropic | 0.60.0 | 1.8.0 | messages.create(temperature=..., top_p=..., top_k=...) não é mais aceito |
| huggingface-hub | 0.34.3 | 2.0.0 | hf_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-core | 0.3.72 | 1.6.5 | retriever.get_relevant_documents() e llm.predict() removidos |
| openai | 1.98.0 | 3.19.2 | 21 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):
O since-cutoff faz três coisas sobre isso:
scanencontra, 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.runpede 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.- 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:
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 scanou chama a ferramenta MCPproject_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
--model | usa | precisa |
|---|---|---|
claude-code (padrão quando nenhuma configuração nomeia um modelo) | seu login do Claude Code (assinatura ou chave), modelo atual | a CLI claude |
claude-code:sonnet, claude-code:claude-haiku-4-5 | um modelo Claude específico | a CLI claude |
anthropic:<model> | API da Anthropic | ANTHROPIC_API_KEY |
openai:<model> | API da OpenAI | OPENAI_API_KEY |
openrouter:<vendor/model> | OpenRouter | OPENROUTER_API_KEY |
deepseek:<model> | API da DeepSeek | DEEPSEEK_API_KEY |
ollama:<model> | Ollama local | Ollama 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"):
SINCE_CUTOFF_MODEL(uma especificação completa comoopenai:gpt-5.4) sempre vence.- Dentro do Claude Code (que define
CLAUDECODE=1para os comandos que executa), apenas as configurações do Claude Code contam:ANTHROPIC_MODEL, depois o.claude/settings.local.jsone.claude/settings.jsondo projeto, depois~/.claude/settings.json. - Em outros lugares, a configuração mais específica vence: primeiro
ANTHROPIC_MODELouAIDER_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:
| agente | configurações do projeto | configuraçõ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 |
| OpenCode | opencode.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.5 | Claude Opus 4.6 | |
|---|---|---|
| corte de treinamento | fev 2025 | mai 2025 |
| mudanças de API sondadas | 20 | 16 |
| desatualizadas / erradas / obsoletas / corretas | 5 / 1 / 2 / 12 | 7 / 0 / 3 / 6 |
| bibliotecas com uso desatualizado | 3 de 5 sondadas | 2 de 4 sondadas |
| notas escritas (com um exemplo que passa na verificação de tipos) | 8 (7), cerca de 391 tokens | 10 (7), cerca de 437 tokens |
| corretas reservadas, sem -> com notas | 14% -> 57% (14 pares) | 5% -> 65% (20 pares) |
| APIs anteriormente corretas após as notas | 6/6 ainda corretas | 6/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.
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)
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:
| ferramenta | respostas |
|---|---|
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
| entrada | padrão | |
|---|---|---|
model | obrigatório | provider:model como para --model; apenas seu corte de treinamento é usado |
working-directory | . | o diretório do projeto |
only, exclude | nomes PyPI separados por vírgula | |
cutoff | substituir o corte de treinamento (YYYY-MM ou YYYY-MM-DD) | |
fail-on-changes | false | falhar o passo quando uma dependência mudou sua API após o corte |
step-summary | true | adicionar o resumo Markdown ao resumo do job |
cache | true | manter metadados PyPI, fontes de pacotes e diffs de API entre execuções (também quando fail-on-changes falha o job) |
args | mais argumentos since-cutoff scan, ex. --all-deps --limit 20 | |
since-cutoff-version | 0.3.2 | o 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:
| resultado | significado |
|---|---|
| desatualizado | o 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 |
| errado | inválido para sua versão, mas não explicado por uma mudança (API alucinada ou mal usada) |
| obsoleto | válido, mas usa uma API marcada @deprecated em sua versão |
| correto | válido para sua versão e realmente usa a API alterada |
| intocado / fora da tarefa / inválido / erro | nã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/.pyisã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 pathmostra,since-cutoff cache clearremove). Com--applyele escreve um bloco marcado emAGENTS.md/CLAUDE.mde deixa o resto do arquivo inalterado byte por byte;since-cutoff unapplyremove o bloco. - Sem telemetria, sem conta, sem dados pessoais. Re-execuções vêm do cache, então são gratuitas
e reproduzíveis (
--freshpergunta 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.
scantambé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__, masrunnã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 porrun, 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.
| ferramenta | o que faz | como 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-server | Busca de documentação para agentes, no momento da resposta; docs-mcp-server pode indexar documentação localmente | Igual ao Context7. |
| library-skills | Bibliotecas 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 biblioteca | Escritas 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/skills | Plugins para Claude Code, Codex e Cursor e arquivos SKILL.md para Pydantic, Pydantic AI e Logfire, instalados do repositório | Orientaçã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, Dependabot | Abrem pull requests que atualizam suas versões fixadas | A 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, LibEvolutionEval | Medem 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 unidade | Eles 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 runas 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 runre-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:
- Rode em seu projeto e poste o que encontrou, incluindo falsos positivos, em Compartilhe seus resultados.
- Pegue uma boa primeira issue: tarefas pequenas e autocontidas, como outro formato de lockfile ou um preset de provedor.
- Peças maiores são rotuladas help wanted, por exemplo suporte a TypeScript.
- Reporte um bug ou um resultado estranho nas issues.
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