Conversation
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…loads Opt-in via [tool.bdt.lint] sql_roots. Recognises literal and dynamic load_sql topic/name calls, repo-relative path literals and scoped bare filenames. Validated against OneSales (0 findings), CCMT2 (1) and MDMApp (13). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…calls Inventory from app.openapi() (recursing into mounted sub-apps, in a subprocess using only stdlib so a repo-local top-level package cannot shadow bdt) or a committed openapi.json. Callers are found in non-generated TS/JS/Vue only: hey-api SDK functions + react-query helpers, openapi-fetch calls and URL literals (nested templates handled). Excludes by prefix/tag/glob and an optional baseline ratchet. Validated against OneSales, CCMT2 and MDMApp. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…-api-usage sql-file-unreferenced: keyword loader args, segment-aligned path matching, Windows separators, report unparseable python files, reuse lint._iter_files, ignore the topic literal for dynamic names. lint-api-usage: per-frontend SDK scoping, method-exact openapi-fetch, JS/Vue generated+test exclusion, comments blanked via _mask, concatenated URLs, drop the reverse suffix match and bare '/', fail on empty inventory, validate config and baselines before writing, stale-baseline reasons, bounded regexes/recursion, subprocess timeout. Command-specific CLI output and docs/skill updates. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
aersam
marked this pull request as ready for review
October 1, 2026 08:36
…`bdt dead-code`
One command and one config table ([tool.bdt.dead_code]) for both dead-code checks:
`sql` (unreferenced .sql files, `sql_roots`) and `routes` (uncalled FastAPI routes,
`[[tool.bdt.dead_code.apps]]`). `--only sql|routes` runs one; `bdt lint` no longer
carries the SQL file rule and `bdt lint-api-usage` is gone.
A route the backend refers to by name -- `request.url_for("auth_callback")`,
`app.url_path_for(...)`, `{{ url_for('login') }}` in a template -- now counts as used
(auth redirects/OAuth callbacks have no frontend caller). The route name is recovered
from the operationId, so it works for included routers and mounted sub-apps too.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
One new command,
bdt dead-code, for dead code a linter can't see. Developed from an experiment run against OneSales, CCMT2 and MDMApp. Configured in one table,[tool.bdt.dead_code]; each check runs when configured,--only sql|routesruns one (the routes check imports the app, so it is the slow one).sql-- unreferenced.sqlfiles (opt-in viasql_roots)Reports
.sqlfiles undersql_rootsthat no Python code references: literal/keywordload_sql("topic","name"), dynamic names (stem appears as a literal in the calling file), segment-aligned repo-relative path literals, and bare filenames under the SQL folder's parent. Always scans the whole repo for references. Unparseable Python files are reported (their references are unknown).routes-- FastAPI operations nothing uses ([[tool.bdt.dead_code.apps]])Inventory from
app.openapi()(recursing into mounted sub-apps, in a stdlib-only subprocess so a repo-localbmsdnapackage can't shadow devtools) or a committedopenapi.json. An operation is used when:.GET("/x")(method-exact), URL/template literals (nested templates, concatenation). Generated code, tests and e2e specs never count; comments are masked;url_for/url_path_for(configurableurl_for_functions) in non-test Python files or Jinja-style templates underapp_dir-- how auth redirects and OAuth callbacks are wired (request.url_for("auth_callback")). The route name is recovered from theoperationId(FastAPI default form, bare name, or<prefix>-<name>), so included routers and mounted sub-apps work.Excludes by prefix/tag/glob; optional baseline ratchet with stale-entry detection (
--update-baseline, routes only).bdt lintis unchanged from main (no SQL-file rule, nolint-api-usage).Validated against real repos (harness only)
/external_api/*, 15 truly dead)akeneo_editor/backend/sql)These numbers predate the
url_forrule; routes like OneSales'auth_callback(request.url_for("auth_callback")) are no longer flagged. Also exercised end to end against a real FastAPI 0.142 app with an included router (url_forroute not reported).Known limitations (documented in README)
URL literals match every method of a path; SPA
<Link>targets can mask a route; server-provided URLs, fully computed paths and non-literalurl_fornames are invisible (exclude them or list SQL insql_unreferenced_ignore). Theurl_formatch is textual, so a call in a comment counts.🤖 Generated with Claude Code