depdesk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- depdesk-0.1.0/LICENSE +21 -0
- depdesk-0.1.0/PKG-INFO +316 -0
- depdesk-0.1.0/README.md +288 -0
- depdesk-0.1.0/depdesk/__init__.py +3 -0
- depdesk-0.1.0/depdesk/__main__.py +292 -0
- depdesk-0.1.0/depdesk/catalog.py +181 -0
- depdesk-0.1.0/depdesk/data/catalog.json +989 -0
- depdesk-0.1.0/depdesk/py.typed +0 -0
- depdesk-0.1.0/depdesk/report.py +382 -0
- depdesk-0.1.0/depdesk/scan.py +286 -0
- depdesk-0.1.0/depdesk/upstream.py +248 -0
- depdesk-0.1.0/depdesk/usage.py +131 -0
- depdesk-0.1.0/depdesk.egg-info/PKG-INFO +316 -0
- depdesk-0.1.0/depdesk.egg-info/SOURCES.txt +18 -0
- depdesk-0.1.0/depdesk.egg-info/dependency_links.txt +1 -0
- depdesk-0.1.0/depdesk.egg-info/entry_points.txt +2 -0
- depdesk-0.1.0/depdesk.egg-info/top_level.txt +1 -0
- depdesk-0.1.0/pyproject.toml +49 -0
- depdesk-0.1.0/setup.cfg +4 -0
- depdesk-0.1.0/tests/test_depdesk.py +285 -0
depdesk-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wendel Ortiz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
depdesk-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: depdesk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Know which of your model calls are on a clock.
|
|
5
|
+
Author: Wendel Ortiz
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Ort0x36/deprecation-desk
|
|
8
|
+
Project-URL: Source, https://github.com/Ort0x36/deprecation-desk
|
|
9
|
+
Project-URL: Issues, https://github.com/Ort0x36/deprecation-desk/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Ort0x36/deprecation-desk/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: llm,llmops,deprecation,model-deprecation,model-lifecycle,openai,anthropic,claude,gpt,ai-engineering,static-analysis,linter,cli,ci,migration,technical-debt
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# depdesk
|
|
30
|
+
|
|
31
|
+
**Know which of your model calls are on a clock.**
|
|
32
|
+
|
|
33
|
+
[](https://github.com/Ort0x36/deprecation-desk/actions/workflows/ci.yml)
|
|
34
|
+
[](https://pypi.org/project/depdesk/)
|
|
35
|
+
[](https://www.python.org/downloads/)
|
|
36
|
+
[](pyproject.toml)
|
|
37
|
+
[](LICENSE)
|
|
38
|
+
|
|
39
|
+
Providers retire models on their schedule, not yours. The notice arrives by
|
|
40
|
+
email, to one person, months before anything breaks, and then it is forgotten
|
|
41
|
+
until a request starts failing in production. `depdesk` crosses the deprecation
|
|
42
|
+
notices you did not read with the models your code actually calls, and fails
|
|
43
|
+
your build while there is still time to do something about it.
|
|
44
|
+
|
|
45
|
+
Zero dependencies. Python 3.9 or newer. Anthropic and OpenAI today, and any
|
|
46
|
+
provider you write a catalog entry for.
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install depdesk
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Try it in thirty seconds
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
depdesk check .
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
That is the whole setup. Point it at a repository and it reports every model
|
|
61
|
+
identifier it finds, crossed against the provider's published deprecation
|
|
62
|
+
dates. There is a deliberately broken sample in
|
|
63
|
+
[`examples/legacy-app`](examples/legacy-app) if you want to see a failing run
|
|
64
|
+
before pointing it at your own code.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
$ depdesk check . --fail-in 60
|
|
68
|
+
depdesk: 2 files scanned in .
|
|
69
|
+
catalog verified 2026-09-20 (2 days ago)
|
|
70
|
+
|
|
71
|
+
ALREADY RETIRED
|
|
72
|
+
|
|
73
|
+
claude-opus-4-1-20250805
|
|
74
|
+
provider: anthropic
|
|
75
|
+
retirement: 2026-08-05 (48 days ago)
|
|
76
|
+
announced: 2026-06-05
|
|
77
|
+
replacement: claude-opus-4-8
|
|
78
|
+
app/legacy.py:1: OLD = "claude-opus-4-1-20250805"
|
|
79
|
+
|
|
80
|
+
RETIRES SOON
|
|
81
|
+
|
|
82
|
+
gpt-5.4-cyber
|
|
83
|
+
provider: openai
|
|
84
|
+
retirement: 2026-10-01 (9 days left)
|
|
85
|
+
announced: 2026-09-11
|
|
86
|
+
replacement: gpt-5.6-cyber
|
|
87
|
+
app/legacy.py:2: CYBER = "gpt-5.4-cyber"
|
|
88
|
+
|
|
89
|
+
DEPRECATED PARAMETERS
|
|
90
|
+
|
|
91
|
+
temperature
|
|
92
|
+
behaviour: Returns a 400 error when set to a non-default value.
|
|
93
|
+
replacement: Omit the parameter and steer behaviour through prompting.
|
|
94
|
+
sdk: The Python SDK (v1.0 and later) removes temperature, top_p
|
|
95
|
+
and top_k, so passing them raises a TypeError.
|
|
96
|
+
app/legacy.py:9: temperature=0,
|
|
97
|
+
file also names: claude-opus-5
|
|
98
|
+
|
|
99
|
+
Summary: 1 already retired, 1 retires soon.
|
|
100
|
+
$ echo $?
|
|
101
|
+
2
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Every line of that output is real: it is the tool running against a two file
|
|
105
|
+
sample, not a mockup.
|
|
106
|
+
|
|
107
|
+
## What it finds
|
|
108
|
+
|
|
109
|
+
**Models on a clock.** Identifiers written anywhere in the tree, including
|
|
110
|
+
`.env` files and config, matched against the provider's own retirement dates.
|
|
111
|
+
Each finding carries the announcement date, the retirement date, the
|
|
112
|
+
replacement the provider names, and the exact lines where you use it.
|
|
113
|
+
|
|
114
|
+
**Deprecated parameters.** Model retirement is the loud failure. The quiet one
|
|
115
|
+
is a parameter that starts returning 400 on newer models while your code keeps
|
|
116
|
+
passing it, which is what happened to `temperature`, `top_p` and `top_k` on
|
|
117
|
+
Claude Opus 4.7 and later. No changelog files that under "deprecation", and
|
|
118
|
+
nothing in your test suite catches it if your tests never hit the new model.
|
|
119
|
+
`depdesk` parses your Python with the standard library `ast` module, so it
|
|
120
|
+
finds the keyword argument itself, not a string that looks like one.
|
|
121
|
+
|
|
122
|
+
**Endpoints and products** that the provider has put on notice, matched the
|
|
123
|
+
same way.
|
|
124
|
+
|
|
125
|
+
Where the provider's own wording is ambiguous about which models a rule covers,
|
|
126
|
+
`depdesk` says so and downgrades the finding to review instead of guessing.
|
|
127
|
+
|
|
128
|
+
## Put it in CI
|
|
129
|
+
|
|
130
|
+
This is the point of the exit codes: the build starts failing the day a
|
|
131
|
+
provider gives you notice, not the day the model dies.
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
# .github/workflows/depdesk.yml
|
|
135
|
+
name: model deprecations
|
|
136
|
+
on:
|
|
137
|
+
push:
|
|
138
|
+
schedule:
|
|
139
|
+
- cron: "0 7 * * 1" # Monday morning, so notice arrives before the deadline
|
|
140
|
+
|
|
141
|
+
jobs:
|
|
142
|
+
check:
|
|
143
|
+
runs-on: ubuntu-latest
|
|
144
|
+
steps:
|
|
145
|
+
- uses: actions/checkout@v4
|
|
146
|
+
- uses: actions/setup-python@v5
|
|
147
|
+
with: { python-version: "3.12" }
|
|
148
|
+
- run: pip install depdesk
|
|
149
|
+
- run: depdesk check . --fail-in 60
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
| code | meaning |
|
|
153
|
+
| --- | --- |
|
|
154
|
+
| 0 | nothing needs attention |
|
|
155
|
+
| 1 | something is deprecated, but outside the `--fail-in` window |
|
|
156
|
+
| 2 | something is already retired, or retires within `--fail-in` |
|
|
157
|
+
| 3 | the tool could not do its job |
|
|
158
|
+
|
|
159
|
+
## Weight it by real traffic
|
|
160
|
+
|
|
161
|
+
Scanning code tells you what is referenced. It does not tell you what is hot.
|
|
162
|
+
Point `--usage` at an export and every finding gains a share of traffic, so you
|
|
163
|
+
can tell a dead constant from 40% of production.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
depdesk check . --usage usage.csv
|
|
167
|
+
depdesk check . --usage usage.csv --usage-count-column input_tokens
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
ALREADY RETIRED
|
|
172
|
+
|
|
173
|
+
claude-3-5-sonnet-20241022 [3.3% of measured calls]
|
|
174
|
+
provider: anthropic
|
|
175
|
+
retirement: 2025-10-28 (329 days ago)
|
|
176
|
+
announced: 2025-08-13
|
|
177
|
+
replacement: claude-sonnet-4-6
|
|
178
|
+
seen in usage data but not found anywhere in the scanned tree
|
|
179
|
+
|
|
180
|
+
claude-opus-4-1-20250805 [15.3% of measured calls]
|
|
181
|
+
provider: anthropic
|
|
182
|
+
retirement: 2026-08-05 (48 days ago)
|
|
183
|
+
announced: 2026-06-05
|
|
184
|
+
replacement: claude-opus-4-8
|
|
185
|
+
app/legacy.py:1: OLD = "claude-opus-4-1-20250805"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
That first finding is the one worth the flag: a retired model still taking
|
|
189
|
+
traffic from code that is not in this repository at all.
|
|
190
|
+
|
|
191
|
+
For Anthropic: Claude Console, **Usage**, **Export**. The CSV has an API key
|
|
192
|
+
column and a model column, and `depdesk` sniffs them. CSV and JSON both work.
|
|
193
|
+
|
|
194
|
+
## Ask what breaks later
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
depdesk check . --today 2027-01-01
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
More useful than it sounds: it answers "what breaks over the holidays" before
|
|
201
|
+
anyone leaves.
|
|
202
|
+
|
|
203
|
+
## When a finding is not a finding
|
|
204
|
+
|
|
205
|
+
Documentation, changelogs and migration notes legitimately name models that are
|
|
206
|
+
dead. A tool you cannot silence on a line you have already judged is a tool
|
|
207
|
+
people stop running, so there are two escapes, both deliberate:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
OLD = "claude-opus-4-1-20250805" # depdesk: ignore
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
depdesk check . --exclude "CHANGELOG.md" --exclude "*/migrations/*"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The marker silences one line, in any file type, in whatever comment syntax that
|
|
218
|
+
file uses, because it is matched as text. `--exclude` takes a glob, matched
|
|
219
|
+
against the path and the file name, and repeats. Neither has a project level
|
|
220
|
+
config file on purpose: an ignore list nobody reads is how a tool like this
|
|
221
|
+
starts lying.
|
|
222
|
+
|
|
223
|
+
## Commands and flags
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
depdesk check [PATH ...] scan a tree and report what is dying
|
|
227
|
+
depdesk upstream ask whether the provider pages moved
|
|
228
|
+
depdesk list print the catalog
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| flag on `check` | what it does |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `--fail-in DAYS` | how close a retirement has to be to fail the build (default 90) |
|
|
234
|
+
| `--sunset-in DAYS` | also report active models with an announced earliest retirement inside this window |
|
|
235
|
+
| `--usage FILE` | weight findings by real call volume |
|
|
236
|
+
| `--usage-model-column`, `--usage-count-column` | override the sniffed columns |
|
|
237
|
+
| `--today YYYY-MM-DD` | ask what this repository looks like on a future date |
|
|
238
|
+
| `--locations N` | how many source lines to print per finding (default 3) |
|
|
239
|
+
| `--json` | machine readable output |
|
|
240
|
+
| `--exclude GLOB` | skip paths matching this glob, repeatable |
|
|
241
|
+
| `--no-unknown` | stop reporting identifiers the catalog does not know |
|
|
242
|
+
| `--catalog FILE` | use your own catalog, for a provider we do not cover |
|
|
243
|
+
|
|
244
|
+
## The catalog, and why you can trust it
|
|
245
|
+
|
|
246
|
+
The only thing that makes this tool worth anything is whether the dates in it
|
|
247
|
+
are true. So they are not hidden: [`depdesk/data/catalog.json`](depdesk/data/catalog.json)
|
|
248
|
+
is plain JSON, every entry was transcribed from the provider's own page, and
|
|
249
|
+
the file records when that happened. `depdesk check` prints a warning when the
|
|
250
|
+
catalog is more than 30 days old.
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
depdesk upstream # did the provider pages change since then?
|
|
254
|
+
depdesk upstream --save # record the current state as the new baseline
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
`upstream` does not parse the page into a catalog. An earlier version hashed
|
|
258
|
+
the whole page and produced a different digest on three consecutive fetches of
|
|
259
|
+
the same unchanged content, because provider docs carry per-request markup. So
|
|
260
|
+
it extracts the model identifiers and the dates, compares those against the
|
|
261
|
+
catalog, and prints what appeared and what disappeared. A human decides what it
|
|
262
|
+
means. A scraper that half works would produce a catalog that looks maintained
|
|
263
|
+
and is not, which is the exact failure this tool exists to prevent.
|
|
264
|
+
|
|
265
|
+
`upstream` exits 1 when a page moved, 3 when it could not be fetched, and 0
|
|
266
|
+
otherwise. It prints, but does not fail on, the identifiers a page names that
|
|
267
|
+
the catalog does not mention: the OpenAI page alone names 35 of those and
|
|
268
|
+
always will, because a deprecation page also lists models that are not being
|
|
269
|
+
deprecated. That is a standing difference, not an event, and a weekly alarm
|
|
270
|
+
that fires on it stops being read. Pass `--strict` if you do want those to
|
|
271
|
+
fail.
|
|
272
|
+
|
|
273
|
+
This repository runs `upstream` every Monday and
|
|
274
|
+
[opens an issue](.github/workflows/catalog-drift.yml) when a provider page
|
|
275
|
+
moves, so drift lands in front of a person instead of in a log nobody reads.
|
|
276
|
+
|
|
277
|
+
## What it does not do
|
|
278
|
+
|
|
279
|
+
Being plain about the limits, because the whole point is to be trustworthy:
|
|
280
|
+
|
|
281
|
+
- **It does not know your provider's private schedule.** It knows what is on the
|
|
282
|
+
public deprecation pages, transcribed by hand.
|
|
283
|
+
- **It only covers Anthropic and OpenAI today.** Other providers are a catalog
|
|
284
|
+
entry away, and pull requests are welcome. `--catalog` takes your own file.
|
|
285
|
+
- **It finds identifiers written as text.** A model id assembled at runtime from
|
|
286
|
+
string pieces will not be found by the scanner. The `--usage` path catches
|
|
287
|
+
that case, which is part of why it exists.
|
|
288
|
+
- **It reads `.env` files**, because that is where model configuration lives. It
|
|
289
|
+
prints only lines that matched a model identifier, but if that bothers you,
|
|
290
|
+
scan a narrower path.
|
|
291
|
+
- **It will not edit your code.** Migrating a prompt is a judgement call and this
|
|
292
|
+
tool has no opinion about your prompts.
|
|
293
|
+
|
|
294
|
+
## Contributing
|
|
295
|
+
|
|
296
|
+
Catalog out of date? A pull request editing `depdesk/data/catalog.json` is the
|
|
297
|
+
fastest path, and the diff is readable by anyone. Want a provider we do not
|
|
298
|
+
cover? Open an issue with a link to their public deprecation page. See
|
|
299
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
300
|
+
|
|
301
|
+
## Development
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
python3 -m pytest -q tests/
|
|
305
|
+
python3 -m depdesk check .
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The test suite pins the behaviour that matters: that `gpt-4-turbo` does not
|
|
309
|
+
match inside `gpt-4-turbo-preview`, that an active model stays silent, that the
|
|
310
|
+
parameter rule needs an affected model in the same file before it fires, and
|
|
311
|
+
that the fingerprint survives cosmetic markup changes but not a changed date.
|
|
312
|
+
|
|
313
|
+
## Licence
|
|
314
|
+
|
|
315
|
+
MIT. Built by [Wendel Ortiz](https://github.com/Ort0x36) while running an LLM
|
|
316
|
+
product in production.
|
depdesk-0.1.0/README.md
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# depdesk
|
|
2
|
+
|
|
3
|
+
**Know which of your model calls are on a clock.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/Ort0x36/deprecation-desk/actions/workflows/ci.yml)
|
|
6
|
+
[](https://pypi.org/project/depdesk/)
|
|
7
|
+
[](https://www.python.org/downloads/)
|
|
8
|
+
[](pyproject.toml)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
Providers retire models on their schedule, not yours. The notice arrives by
|
|
12
|
+
email, to one person, months before anything breaks, and then it is forgotten
|
|
13
|
+
until a request starts failing in production. `depdesk` crosses the deprecation
|
|
14
|
+
notices you did not read with the models your code actually calls, and fails
|
|
15
|
+
your build while there is still time to do something about it.
|
|
16
|
+
|
|
17
|
+
Zero dependencies. Python 3.9 or newer. Anthropic and OpenAI today, and any
|
|
18
|
+
provider you write a catalog entry for.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install depdesk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Try it in thirty seconds
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
depdesk check .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
That is the whole setup. Point it at a repository and it reports every model
|
|
33
|
+
identifier it finds, crossed against the provider's published deprecation
|
|
34
|
+
dates. There is a deliberately broken sample in
|
|
35
|
+
[`examples/legacy-app`](examples/legacy-app) if you want to see a failing run
|
|
36
|
+
before pointing it at your own code.
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
$ depdesk check . --fail-in 60
|
|
40
|
+
depdesk: 2 files scanned in .
|
|
41
|
+
catalog verified 2026-09-20 (2 days ago)
|
|
42
|
+
|
|
43
|
+
ALREADY RETIRED
|
|
44
|
+
|
|
45
|
+
claude-opus-4-1-20250805
|
|
46
|
+
provider: anthropic
|
|
47
|
+
retirement: 2026-08-05 (48 days ago)
|
|
48
|
+
announced: 2026-06-05
|
|
49
|
+
replacement: claude-opus-4-8
|
|
50
|
+
app/legacy.py:1: OLD = "claude-opus-4-1-20250805"
|
|
51
|
+
|
|
52
|
+
RETIRES SOON
|
|
53
|
+
|
|
54
|
+
gpt-5.4-cyber
|
|
55
|
+
provider: openai
|
|
56
|
+
retirement: 2026-10-01 (9 days left)
|
|
57
|
+
announced: 2026-09-11
|
|
58
|
+
replacement: gpt-5.6-cyber
|
|
59
|
+
app/legacy.py:2: CYBER = "gpt-5.4-cyber"
|
|
60
|
+
|
|
61
|
+
DEPRECATED PARAMETERS
|
|
62
|
+
|
|
63
|
+
temperature
|
|
64
|
+
behaviour: Returns a 400 error when set to a non-default value.
|
|
65
|
+
replacement: Omit the parameter and steer behaviour through prompting.
|
|
66
|
+
sdk: The Python SDK (v1.0 and later) removes temperature, top_p
|
|
67
|
+
and top_k, so passing them raises a TypeError.
|
|
68
|
+
app/legacy.py:9: temperature=0,
|
|
69
|
+
file also names: claude-opus-5
|
|
70
|
+
|
|
71
|
+
Summary: 1 already retired, 1 retires soon.
|
|
72
|
+
$ echo $?
|
|
73
|
+
2
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Every line of that output is real: it is the tool running against a two file
|
|
77
|
+
sample, not a mockup.
|
|
78
|
+
|
|
79
|
+
## What it finds
|
|
80
|
+
|
|
81
|
+
**Models on a clock.** Identifiers written anywhere in the tree, including
|
|
82
|
+
`.env` files and config, matched against the provider's own retirement dates.
|
|
83
|
+
Each finding carries the announcement date, the retirement date, the
|
|
84
|
+
replacement the provider names, and the exact lines where you use it.
|
|
85
|
+
|
|
86
|
+
**Deprecated parameters.** Model retirement is the loud failure. The quiet one
|
|
87
|
+
is a parameter that starts returning 400 on newer models while your code keeps
|
|
88
|
+
passing it, which is what happened to `temperature`, `top_p` and `top_k` on
|
|
89
|
+
Claude Opus 4.7 and later. No changelog files that under "deprecation", and
|
|
90
|
+
nothing in your test suite catches it if your tests never hit the new model.
|
|
91
|
+
`depdesk` parses your Python with the standard library `ast` module, so it
|
|
92
|
+
finds the keyword argument itself, not a string that looks like one.
|
|
93
|
+
|
|
94
|
+
**Endpoints and products** that the provider has put on notice, matched the
|
|
95
|
+
same way.
|
|
96
|
+
|
|
97
|
+
Where the provider's own wording is ambiguous about which models a rule covers,
|
|
98
|
+
`depdesk` says so and downgrades the finding to review instead of guessing.
|
|
99
|
+
|
|
100
|
+
## Put it in CI
|
|
101
|
+
|
|
102
|
+
This is the point of the exit codes: the build starts failing the day a
|
|
103
|
+
provider gives you notice, not the day the model dies.
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
# .github/workflows/depdesk.yml
|
|
107
|
+
name: model deprecations
|
|
108
|
+
on:
|
|
109
|
+
push:
|
|
110
|
+
schedule:
|
|
111
|
+
- cron: "0 7 * * 1" # Monday morning, so notice arrives before the deadline
|
|
112
|
+
|
|
113
|
+
jobs:
|
|
114
|
+
check:
|
|
115
|
+
runs-on: ubuntu-latest
|
|
116
|
+
steps:
|
|
117
|
+
- uses: actions/checkout@v4
|
|
118
|
+
- uses: actions/setup-python@v5
|
|
119
|
+
with: { python-version: "3.12" }
|
|
120
|
+
- run: pip install depdesk
|
|
121
|
+
- run: depdesk check . --fail-in 60
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
| code | meaning |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| 0 | nothing needs attention |
|
|
127
|
+
| 1 | something is deprecated, but outside the `--fail-in` window |
|
|
128
|
+
| 2 | something is already retired, or retires within `--fail-in` |
|
|
129
|
+
| 3 | the tool could not do its job |
|
|
130
|
+
|
|
131
|
+
## Weight it by real traffic
|
|
132
|
+
|
|
133
|
+
Scanning code tells you what is referenced. It does not tell you what is hot.
|
|
134
|
+
Point `--usage` at an export and every finding gains a share of traffic, so you
|
|
135
|
+
can tell a dead constant from 40% of production.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
depdesk check . --usage usage.csv
|
|
139
|
+
depdesk check . --usage usage.csv --usage-count-column input_tokens
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
ALREADY RETIRED
|
|
144
|
+
|
|
145
|
+
claude-3-5-sonnet-20241022 [3.3% of measured calls]
|
|
146
|
+
provider: anthropic
|
|
147
|
+
retirement: 2025-10-28 (329 days ago)
|
|
148
|
+
announced: 2025-08-13
|
|
149
|
+
replacement: claude-sonnet-4-6
|
|
150
|
+
seen in usage data but not found anywhere in the scanned tree
|
|
151
|
+
|
|
152
|
+
claude-opus-4-1-20250805 [15.3% of measured calls]
|
|
153
|
+
provider: anthropic
|
|
154
|
+
retirement: 2026-08-05 (48 days ago)
|
|
155
|
+
announced: 2026-06-05
|
|
156
|
+
replacement: claude-opus-4-8
|
|
157
|
+
app/legacy.py:1: OLD = "claude-opus-4-1-20250805"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
That first finding is the one worth the flag: a retired model still taking
|
|
161
|
+
traffic from code that is not in this repository at all.
|
|
162
|
+
|
|
163
|
+
For Anthropic: Claude Console, **Usage**, **Export**. The CSV has an API key
|
|
164
|
+
column and a model column, and `depdesk` sniffs them. CSV and JSON both work.
|
|
165
|
+
|
|
166
|
+
## Ask what breaks later
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
depdesk check . --today 2027-01-01
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
More useful than it sounds: it answers "what breaks over the holidays" before
|
|
173
|
+
anyone leaves.
|
|
174
|
+
|
|
175
|
+
## When a finding is not a finding
|
|
176
|
+
|
|
177
|
+
Documentation, changelogs and migration notes legitimately name models that are
|
|
178
|
+
dead. A tool you cannot silence on a line you have already judged is a tool
|
|
179
|
+
people stop running, so there are two escapes, both deliberate:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
OLD = "claude-opus-4-1-20250805" # depdesk: ignore
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
depdesk check . --exclude "CHANGELOG.md" --exclude "*/migrations/*"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The marker silences one line, in any file type, in whatever comment syntax that
|
|
190
|
+
file uses, because it is matched as text. `--exclude` takes a glob, matched
|
|
191
|
+
against the path and the file name, and repeats. Neither has a project level
|
|
192
|
+
config file on purpose: an ignore list nobody reads is how a tool like this
|
|
193
|
+
starts lying.
|
|
194
|
+
|
|
195
|
+
## Commands and flags
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
depdesk check [PATH ...] scan a tree and report what is dying
|
|
199
|
+
depdesk upstream ask whether the provider pages moved
|
|
200
|
+
depdesk list print the catalog
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
| flag on `check` | what it does |
|
|
204
|
+
| --- | --- |
|
|
205
|
+
| `--fail-in DAYS` | how close a retirement has to be to fail the build (default 90) |
|
|
206
|
+
| `--sunset-in DAYS` | also report active models with an announced earliest retirement inside this window |
|
|
207
|
+
| `--usage FILE` | weight findings by real call volume |
|
|
208
|
+
| `--usage-model-column`, `--usage-count-column` | override the sniffed columns |
|
|
209
|
+
| `--today YYYY-MM-DD` | ask what this repository looks like on a future date |
|
|
210
|
+
| `--locations N` | how many source lines to print per finding (default 3) |
|
|
211
|
+
| `--json` | machine readable output |
|
|
212
|
+
| `--exclude GLOB` | skip paths matching this glob, repeatable |
|
|
213
|
+
| `--no-unknown` | stop reporting identifiers the catalog does not know |
|
|
214
|
+
| `--catalog FILE` | use your own catalog, for a provider we do not cover |
|
|
215
|
+
|
|
216
|
+
## The catalog, and why you can trust it
|
|
217
|
+
|
|
218
|
+
The only thing that makes this tool worth anything is whether the dates in it
|
|
219
|
+
are true. So they are not hidden: [`depdesk/data/catalog.json`](depdesk/data/catalog.json)
|
|
220
|
+
is plain JSON, every entry was transcribed from the provider's own page, and
|
|
221
|
+
the file records when that happened. `depdesk check` prints a warning when the
|
|
222
|
+
catalog is more than 30 days old.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
depdesk upstream # did the provider pages change since then?
|
|
226
|
+
depdesk upstream --save # record the current state as the new baseline
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
`upstream` does not parse the page into a catalog. An earlier version hashed
|
|
230
|
+
the whole page and produced a different digest on three consecutive fetches of
|
|
231
|
+
the same unchanged content, because provider docs carry per-request markup. So
|
|
232
|
+
it extracts the model identifiers and the dates, compares those against the
|
|
233
|
+
catalog, and prints what appeared and what disappeared. A human decides what it
|
|
234
|
+
means. A scraper that half works would produce a catalog that looks maintained
|
|
235
|
+
and is not, which is the exact failure this tool exists to prevent.
|
|
236
|
+
|
|
237
|
+
`upstream` exits 1 when a page moved, 3 when it could not be fetched, and 0
|
|
238
|
+
otherwise. It prints, but does not fail on, the identifiers a page names that
|
|
239
|
+
the catalog does not mention: the OpenAI page alone names 35 of those and
|
|
240
|
+
always will, because a deprecation page also lists models that are not being
|
|
241
|
+
deprecated. That is a standing difference, not an event, and a weekly alarm
|
|
242
|
+
that fires on it stops being read. Pass `--strict` if you do want those to
|
|
243
|
+
fail.
|
|
244
|
+
|
|
245
|
+
This repository runs `upstream` every Monday and
|
|
246
|
+
[opens an issue](.github/workflows/catalog-drift.yml) when a provider page
|
|
247
|
+
moves, so drift lands in front of a person instead of in a log nobody reads.
|
|
248
|
+
|
|
249
|
+
## What it does not do
|
|
250
|
+
|
|
251
|
+
Being plain about the limits, because the whole point is to be trustworthy:
|
|
252
|
+
|
|
253
|
+
- **It does not know your provider's private schedule.** It knows what is on the
|
|
254
|
+
public deprecation pages, transcribed by hand.
|
|
255
|
+
- **It only covers Anthropic and OpenAI today.** Other providers are a catalog
|
|
256
|
+
entry away, and pull requests are welcome. `--catalog` takes your own file.
|
|
257
|
+
- **It finds identifiers written as text.** A model id assembled at runtime from
|
|
258
|
+
string pieces will not be found by the scanner. The `--usage` path catches
|
|
259
|
+
that case, which is part of why it exists.
|
|
260
|
+
- **It reads `.env` files**, because that is where model configuration lives. It
|
|
261
|
+
prints only lines that matched a model identifier, but if that bothers you,
|
|
262
|
+
scan a narrower path.
|
|
263
|
+
- **It will not edit your code.** Migrating a prompt is a judgement call and this
|
|
264
|
+
tool has no opinion about your prompts.
|
|
265
|
+
|
|
266
|
+
## Contributing
|
|
267
|
+
|
|
268
|
+
Catalog out of date? A pull request editing `depdesk/data/catalog.json` is the
|
|
269
|
+
fastest path, and the diff is readable by anyone. Want a provider we do not
|
|
270
|
+
cover? Open an issue with a link to their public deprecation page. See
|
|
271
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
272
|
+
|
|
273
|
+
## Development
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
python3 -m pytest -q tests/
|
|
277
|
+
python3 -m depdesk check .
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The test suite pins the behaviour that matters: that `gpt-4-turbo` does not
|
|
281
|
+
match inside `gpt-4-turbo-preview`, that an active model stays silent, that the
|
|
282
|
+
parameter rule needs an affected model in the same file before it fires, and
|
|
283
|
+
that the fingerprint survives cosmetic markup changes but not a changed date.
|
|
284
|
+
|
|
285
|
+
## Licence
|
|
286
|
+
|
|
287
|
+
MIT. Built by [Wendel Ortiz](https://github.com/Ort0x36) while running an LLM
|
|
288
|
+
product in production.
|