deprecated-tracker 2.2.0

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.
@@ -0,0 +1,23 @@
1
+ # Manifest for the pre-commit framework (pre-commit.com), which installs the
2
+ # package itself and passes the staged paths as arguments.
3
+ #
4
+ # repos:
5
+ # - repo: https://github.com/milad-hub/deprecated-tracker
6
+ # rev: v2.1.0
7
+ # hooks:
8
+ # - id: deprecated-tracker
9
+ - id: deprecated-tracker
10
+ name: Deprecated Tracker
11
+ description: Fails a commit that adds deprecated usage on the lines it changed.
12
+ entry: deprecated-tracker --files
13
+ language: node
14
+ files: \.(ts|tsx|js|jsx)$
15
+ pass_filenames: true
16
+
17
+ - id: deprecated-tracker-whole-files
18
+ name: Deprecated Tracker (whole files)
19
+ description: Fails a commit when a staged file rises above its baseline count.
20
+ entry: deprecated-tracker --files --whole-files
21
+ language: node
22
+ files: \.(ts|tsx|js|jsx)$
23
+ pass_filenames: true
package/CHANGELOG.md ADDED
@@ -0,0 +1,281 @@
1
+ # Change Log
2
+
3
+ All notable changes to the "Deprecated Tracker" extension will be documented in this file.
4
+
5
+ ## [2.2.0]
6
+
7
+ ### Added
8
+
9
+ - **`customTags` in the config file.** The CLI could only ever match `@deprecated`: custom tags live in VS Code's workspace storage, which nothing headless can read. A project standardised on `@legacy` therefore got a green CI and a green pre-commit hook over code full of items — a gate that silently passes. Put `"customTags": [{ "tag": "@legacy", "description": "…" }]` in `.deprecatedtrackerrc` (or the `deprecatedTracker` key in `package.json`) and the CLI counts them. Reserved JSDoc tags like `@param` are refused by the same check the settings page uses, so the two surfaces cannot disagree.
10
+ - **`ignoreMethods` in the config file.** With the CLI alone there is no "Ignore" button, so the only way past a known item was inflating the baseline — which weakens the ratchet for every other file. Takes regex sources, matched against the bare method name in every file. (`excludePatterns` remains how whole files are excluded.)
11
+ - **`--changed`** — everything uncommitted: staged, unstaged **and** untracked. `--staged` reads the index only, which is right for a pre-commit hook and wrong for a pre-push one or for an agent that has edited without staging. Changed-line ranges are the union of both sides of the index, since a file staged and then edited again has changes in each diff.
12
+ - **`--format markdown`** — a table to paste into a pull request. No generated-at line, so re-running produces the same bytes and a diff stays quiet.
13
+ - **An MCP server.** `deprecated-tracker mcp` serves the scanner over stdio, exposing `scan_project`, `scan_changes` and `scan_files`. Agents could already shell out; MCP gives them the verbs by name with schemas, structured results instead of parsed stdout, and calls that do not each trip a shell-command approval. `mcp install --agent claude-code|codex|all --scope project|user` registers it — through the agent's own CLI when that is on PATH, otherwise by merging into `.mcp.json` / `config.toml` without disturbing other servers. `mcp uninstall` removes only the scope named. Implemented directly rather than with `@modelcontextprotocol/sdk`, which pulls in express, hono, cors, jose, ajv and zod for a transport that is a handful of JSON-RPC methods over a pipe; the package still installs with no runtime dependencies.
14
+
15
+ ### Fixed
16
+
17
+ - **Path keys are now case-folded only where the filesystem is.** `stagedDiff`, `gitChanges` and `diffHunks` lowercased every path key unconditionally, matching Windows but not Linux, where `Foo.ts` and `foo.ts` are two files. They were merged into one entry, so a changed file could be dropped from a scan or filtered against the wrong file's line ranges. Now shares the rule `Scanner.getPathKey` and `IgnoreManager.canonicalize` already used.
18
+ - **A reserved JSDoc tag with a leading space is no longer accepted.** `normalizeTag` stripped the `@` before trimming, so `" @param "` normalised to `"@param"`, matched nothing in the reserved list and slipped through validation.
19
+ - **The MCP installer works on Windows.** `claude` and `codex` are `.cmd` shims there, which `execFileSync` cannot launch, so the agent-CLI path would have failed on every Windows machine and silently fallen back to editing config files.
20
+ - Config problems now reach the CLI's stderr instead of `console.warn`. Inside a hook a rejected `customTags` entry was invisible, and the run looked like a clean scan.
21
+
22
+ ### Changed
23
+
24
+ - The hook verdict reads `N deprecated item(s) on the lines you changed`. It counted declarations as "usages", and said "this commit" for runs that are not about a commit at all.
25
+ - A CI workflow runs the test suite and a packaged-CLI smoke test on Ubuntu, macOS and Windows: install the tarball, scan a real project, exercise `--changed`, custom tags, the MCP handshake and install/uninstall.
26
+
27
+ ## [2.1.0]
28
+
29
+ ### Added
30
+
31
+ - **`Deprecated Tracker: Scan Changes`** — scan only the files git reports as changed, across every repository in the workspace. Answers *"did the work I am about to commit add deprecated usage?"* without a full scan burying it in results you already knew about. A status bar button runs it in one click, and the command also appears as an icon in the Source Control title bar when git is the active provider.
32
+ - **A Scan Changes section in the settings page**, stored per workspace: **Staged** and **Unstaged** checkboxes (both on by default; unstaged also covers untracked files) and a **Whole modified files** / **Changed lines only** radio pair. Clearing both checkboxes is refused rather than saved — a setting that silently disables its own feature is a support ticket.
33
+ - Scan history records the **scope** of each scan (`project`, `folder`, `file`, `changed`).
34
+ - **A pre-commit hook mode for the CLI.** `deprecated-tracker --files <paths>` scans only the files it is handed and, by default, reports only the lines that commit staged — so touching a legacy file is free while adding a deprecated call to it fails the commit. Drops straight into lint-staged, which appends the staged paths: `{ "src/**/*.{ts,tsx,js,jsx}": "deprecated-tracker --files" }`. `--whole-files` switches to scanning each staged file completely and ratcheting it against its own baseline count, and `--root <dir>` sets the project root when paths follow `--files`. `--update-baseline` is refused in hook mode, since a baseline written from a subset would record zero for every file the run never saw.
35
+ - **`--staged`, for hook managers that pass no paths.** lint-staged, lefthook's `{staged_files}` and the `pre-commit` framework all hand over the staged files, but simple-git-hooks, a bare `.husky/pre-commit` and a raw `.git/hooks` script just run a command. `--staged` makes the CLI ask git itself (`--diff-filter=ACMR -z`, so deletions are skipped, renames report their new path, and paths containing spaces or non-ASCII characters survive). Non-scannable paths are dropped, so a `"*"` glob handing over stylesheets is harmless, and a commit with nothing scannable staged passes without scanning anything. A `.pre-commit-hooks.yaml` manifest ships for the `pre-commit` framework. With nothing staged, `--format json` / `--format sarif` emit an empty document rather than the plain-text `No staged files to scan.`, so a parser is never handed prose.
36
+
37
+ - **The CLI is usable by AI coding agents.** `deprecated-tracker --files <paths> --format json` returns the findings for exactly the files an agent has just written, with the `@deprecated` text in `items[].reason` so the agent knows what to replace. Unstaged edits need no staging first: a file with no staged hunks is read as entirely changed, so everything in it is reported.
38
+
39
+ ### Changed
40
+
41
+ - **The requirements page no longer opens by itself at startup.** Opening any folder without a `tsconfig.json` — a Python repo, a docs folder, anything — raised a full-page report about a tool the user had not invoked. It now appears when you actually reach for the extension: opening the Deprecated Tracker view, or running Scan Project, Scan Folder, Scan File or Scan Changes while something blocking is unmet. Those commands show the page instead of running a scan that could not have worked. *Deprecated Tracker: Check Requirements* still opens it on demand, and a requirements check that fails for its own reasons never blocks the scan.
42
+
43
+ ### Fixed
44
+
45
+ - **A changed-files scan that found nothing wiped the previous results.** Scanning 26 changed files, finding nothing in them, and being told *"No deprecated items found - your code is clean"* while the history row above still read *96 items* — with the **View Results** button gone and the editor squiggles cleared. A subset that comes back empty now keeps the previous scan's results, diagnostics and button, exactly as a clean working tree already did, and the sidebar reports the scan's own wording (*"Scanned 26 changed file(s) — 0 item(s) in changed lines"*) instead of claiming the project is clean. Scan Folder and Scan File also get their tailored message in the sidebar now rather than the generic one.
46
+ - **The trend chart mixed partial scans with full ones.** *Scan Folder* and *Scan File* both wrote to history and the dashboard plotted every entry, so a one-file scan dropped the line for a reason that had nothing to do with the codebase improving. The chart now plots project scans only; folder and file scans stay in the history list, where re-opening them is still useful. Entries recorded before this release have no scope and are read as project scans, which is what they mostly were.
47
+
48
+ ### Notes
49
+
50
+ - A changed-files scan is **not** written to history, so it never reaches the trend chart.
51
+ - *Changed lines only* is a filter on results, not a narrower scan — the scanner type-checks whole files either way, so it is not faster. It also hides work you just created: adding `@deprecated` to a function puts every call site on an unchanged line. The setting says so, and the notification reports how many items were filtered out.
52
+ - Nothing is scanned on save or on keystroke. This is a scan you ask for, over a smaller set of files.
53
+
54
+ ## [2.0.0]
55
+
56
+ ### Breaking
57
+
58
+ - **A results panel export now matches the results panel.** CSV, JSON and Markdown chosen from the panel's **Export ▼** menu previously wrote the entire workspace regardless of the column filters on screen; they now export exactly the rows shown, the way *Copy prompt for AI fix* already did. Filter to one folder and the file covers that folder. To export everything unconditionally, use the CLI — `deprecated-tracker --format json` — or the **Deprecated Tracker: Export Results** palette command, which is unfiltered by design.
59
+
60
+ ### Added
61
+
62
+ - **Ignore File in the Explorer context menu.** Right-click a file → *Ignore File*, beside *Scan File…*. The command also accepts the clicked file rather than always acting on the active editor.
63
+
64
+ ### Changed
65
+
66
+ - The results panel's rescan control moved out of the table header into the panel controls beside **Export ▼**, and is now labelled **Rescan** — the sidebar's **Refresh** redraws the tree, this one rescans changed files, and they no longer share a word.
67
+ - `deprecatedTracker.ignoreFile` is now titled *Deprecated Tracker: Ignore File* in the command palette, matching every other user-facing command.
68
+ - The history row's **Export ▼** menu says why it offers no AI prompt: a stored scan's line numbers may be stale.
69
+ - *Save as .txt* in the AI prompt dialog is a secondary button; **Copy** is the primary action.
70
+
71
+ ### Fixed
72
+
73
+ - **`--fail-on-any` no longer reads the baseline.** The option is documented as ignoring the baseline, but the run loaded it anyway, so a corrupt or out-of-date `.deprecated-tracker-baseline.json` sitting in the checkout exited `2` (bad usage) before the strict gate ever ran. It now skips the file entirely, and the report drops the baseline lines rather than claiming none was found.
74
+ - **Exporting while viewing a stored scan.** Opening a history entry with **View** replaced the table with that scan's rows but left the extension holding the live scan, so the header's **Export ▼** worked against the wrong set — it would refuse to export, or write a coincidental subset of the latest scan. The panel now tracks the result set it actually put on screen, and exports read that.
75
+ - **The `#` tooltip on the Export ▼ menu.** Both dropdowns built their entries as `<a href="#">`, so hovering one showed the browser's link target instead of nothing. They are `<button type="button" class="dropdown-item">` now — they were never links, and as buttons they are also reachable by keyboard.
76
+ - **The published npm package now contains the CLI bundle.** `out/` is git-ignored, so `npm pack` shipped `bin/deprecated-tracker.js` without the `out/cli.js` it requires — an `npm i -g` or `npx` install failed with `Cannot find module '../out/cli.js'` before the CLI started. A `files` allowlist ships both, and `prepack` builds the bundle so a publish cannot ship a stale one. The `.vsix` is unchanged: it carries the extension, not the CLI.
77
+
78
+ ### Removed
79
+
80
+ - The unused `$(gear)` icon on `deprecatedTracker.openSettings`, which appears in no menu, and the `.refresh-header` / `.btn-icon` styles left behind by the rescan move.
81
+
82
+ ## [1.6.0]
83
+
84
+ ### Added
85
+
86
+ - **`deprecated-tracker` CLI** — a headless entrypoint that runs the same scanner the extension uses, with no editor and no `vscode` dependency. `deprecated-tracker [path]` scans a project, reports what it finds, and sets an exit code.
87
+ - **Baseline ratcheting.** `--update-baseline` records the current count into `.deprecated-tracker-baseline.json`; later runs fail **only when the count rises above it**. `--max-new <n>` allows a deliberate increase, and `--fail-on-any` opts into the stricter "no deprecated code at all" gate.
88
+ - **Machine-readable output.** `--format json` for scripting and `--format sarif` for GitHub code scanning and any SARIF-consuming viewer; `--output <file>` writes to disk instead of stdout.
89
+ - **CI annotations.** `--annotate github` emits `::warning file=…` workflow commands, `--annotate azure` emits `##vso[task.logissue …]`. Only files whose count rose above the baseline are annotated, so a two-line regression is not buried under the whole backlog.
90
+ - Exit codes: `0` at or below the baseline, `1` above it, `2` bad usage or an unreadable baseline, `3` the scan itself failed.
91
+
92
+ ### Changed
93
+
94
+ - `Scanner` now depends on two small interfaces (`IgnoreChecker`, `CustomTagSource`) instead of the concrete `IgnoreManager` and `TagsManager`. Both classes satisfy them unchanged; the point is that the CLI can supply its own without pulling `vscode` into a Node process.
95
+
96
+ ### Notes
97
+
98
+ - **A first run with no baseline passes.** Failing a repository over debt it already had is the "any deprecated code is an error" behaviour that linters already provide; the report says no baseline was found and how to record one. Use `--fail-on-any` if that is genuinely what you want.
99
+ - **When the count falls, the run still passes** and prints how stale the baseline is, so the gain can be locked in with `--update-baseline` on a merge to the default branch.
100
+ - **The gate is the total, not per-file.** Removing five items in one file and adding five in another passes. Per-file counts are still recorded and drive both the "risen above baseline" report and which files get annotated.
101
+ - **Ignore rules and custom tags set in the editor do not apply.** They live in VS Code's workspace storage, which a CI process cannot read. The CLI honours `.deprecatedtrackerrc` / `package.json` config — `includePatterns`, `excludePatterns`, `trustedPackages`, `severity` — and nothing else.
102
+ - A corrupt or wrong-version baseline exits `2` rather than being treated as zero, which would silently fail every build afterwards.
103
+ - The CLI is not in the VSIX. It bundles its own copy of the TypeScript compiler (~3.5 MB) and belongs to the repository, not to the editor install.
104
+
105
+ ## [1.5.0]
106
+
107
+ ### Added
108
+
109
+ - **Copy prompt for AI fix** — a fourth entry in the results panel's Export menu. Instead of a save dialog it opens a modal holding a ready-to-paste brief for a coding agent: every deprecated symbol the panel is currently showing, where it is declared, what its deprecation note says, when it is due for removal, and every call site grouped under its file. **Copy** puts it on the clipboard, **Save as .txt** writes it to a file, **Close** dismisses it (as do the backdrop and `Escape`). The same entry is available from `Deprecated Tracker: Export Results`.
110
+ - `ai-prompt` is a real export format on `ResultExporter`, so the same text can be written to a file later without a second code path.
111
+
112
+ ### Notes
113
+
114
+ - The prompt covers exactly the rows the panel is showing. Filtering happens in the webview, so the panel sends the identity of its visible rows and the prompt is built from that subset — a filtered view never produces a prompt covering the whole workspace.
115
+ - Token cost was the design constraint. Usages are grouped under their file rather than repeated per line, paths are workspace-relative, urgency is a section heading rather than a field on every row, absent fields emit nothing, and each deprecation note is collapsed to one line and capped at 200 characters. The work list is capped at 8,000 characters of whole symbols, highest urgency first; when it truncates, the prompt says so and gives the real counts rather than implying a clean sweep.
116
+ - No source snippets and no guessed replacement text. The agent has the repo and reads it better than an excerpt would, and the replacement hint in the results table is regexes over English prose — fine as a hint, dishonest as an instruction.
117
+ - The extension still never edits code and never calls a model. The feature ends at text on the clipboard.
118
+
119
+ ## [1.4.0]
120
+
121
+ ### Added
122
+
123
+ - **Startup requirements check** — on activation the extension evaluates everything it needs, one requirement at a time. If something that would stop a scan is missing, a **Requirements** page opens listing every check with its state, what to do about it, and whether a window reload is needed. `Deprecated Tracker: Check Requirements` opens the same page on demand, so a healthy setup can be confirmed rather than only ever seen when broken.
124
+ - Remedy buttons on the page: **Open Folder**, **Reload Window**, and **Create tsconfig.json**, which writes a starter config into the first workspace folder. It refuses to overwrite a `tsconfig.json` that already exists.
125
+
126
+ ### Fixed
127
+
128
+ - The "no tsconfig" scan error said the file was not found in the workspace **root**. Config discovery has walked the whole tree for several releases, so a monorepo with configs only under `packages/*` was told to look in the one directory the file does not need to be in.
129
+
130
+ ### Notes
131
+
132
+ - The page opens by itself only for a requirement that actually blocks scanning — an untrusted workspace, a missing `tsconfig.json`/`jsconfig.json`, a non-Node extension host, or an editor older than 1.74.0. Having no folder open is listed as unmet but never opens the page on its own; there is nothing to scan and nothing broken.
133
+ - There is deliberately no "TypeScript installed" check. The compiler is bundled into the extension, so such a check could only ever print OK — and a list with a line that cannot fail teaches you to trust the whole list less.
134
+
135
+ ## [1.3.1]
136
+
137
+ ### Internal
138
+
139
+ - **The scanner no longer depends on `vscode`.** Every scan entry point now takes plain filesystem paths instead of `vscode.WorkspaceFolder`, and an `AbortSignal` instead of `vscode.CancellationToken`. `Scanner` and the `src/scanner` barrel import nothing from the extension host, so the scanning core loads and runs in plain Node — verified by loading the compiled scanner with `vscode` blocked at the module resolver and scanning a fixture project end to end.
140
+ - The sidebar now owns an `AbortController` rather than a `CancellationTokenSource`, and bridges VS Code's progress-notification cancellation to it. Cancelling a scan behaves exactly as before.
141
+ - `IgnoreManager` is no longer re-exported from `src/scanner`; import it from `src/scanner/ignoreManager`. It was the last thing pulling `vscode` into that barrel, and nothing imported it from there.
142
+
143
+ ### Notes
144
+
145
+ - No user-visible change. This is groundwork for a headless CLI: the scanning core can now be driven outside the extension host, which is what a CI entry point needs.
146
+
147
+ ## [1.3.0]
148
+
149
+ ### Added
150
+
151
+ - **Trend chart in the statistics dashboard** — deprecated *usage* count is now plotted across stored scan history, so the dashboard answers "is the number going up or down?" rather than only "what does it look like right now".
152
+ - A **baseline** marker on the chart, drawn at the oldest scan still in history, and a **delta badge** giving the change from that baseline to the latest scan. A decrease reads as an improvement.
153
+
154
+ ### Notes
155
+
156
+ - The series is read from the per-scan metadata that history already stores, not recomputed from each scan's saved results. This matters: stored results are capped at 500 items per scan, so a derived series would have silently undercounted any larger scan.
157
+ - Scan history retains the last 10 scans, so the chart shows at most 10 points and the baseline is the oldest *kept* scan. Once history rolls over, the baseline moves and the delta is measured from the new oldest scan — the badge is worded to say so.
158
+ - The dashboard is still reached from the sidebar's Dashboard button, which appears only when scan history is non-empty. Because opening it requires a latest scan with at least one result, a project that has driven deprecated usages to zero cannot currently view the chart proving it.
159
+
160
+ ## [1.2.0]
161
+
162
+ ### Added
163
+
164
+ - **Deprecation urgency** — the `@deprecated since 2.0, removed in 3.0` convention is now parsed instead of being kept only as opaque prose. Each item carries a `deprecationSchedule` with the parsed `since` and removal version or ISO date, and an urgency of `removed` (removal date already passed), `scheduled` (a removal version or a future removal date) or `announced` (a `since` marker only).
165
+ - The results panel gained an **Urgency** column and now orders items most-urgent first, so what disappears in the next major sorts above what merely has a high usage count.
166
+ - CSV export gained `Urgency`, `Since` and `Removal` columns; Markdown export gained `Urgency` and `Removal`. JSON export carries the whole `deprecationSchedule` object.
167
+
168
+ ### Notes
169
+
170
+ - Urgency is derived from the reason text alone. A removal *version* is not compared against the declaring package's installed version, so `removed in 3.0` ranks as `scheduled` whether or not 3.0 has shipped; only an ISO removal date can promote an item to `removed`.
171
+
172
+ ## [1.1.2]
173
+
174
+ ### Fixed
175
+
176
+ - **Cached TypeScript programs no longer accumulate for the whole session** — the scanner kept one `ts.Program` per discovered `tsconfig.json` with no bound, so repeated Scan Folder / Scan File runs over different parts of a monorepo grew memory until the window closed. Programs are now trimmed to a least-recently-used bound between scans. Note this bounds *retention across scans*, not peak memory *within* a single scan: one scan still holds every program it discovers, by design.
177
+
178
+ ### Internal
179
+
180
+ - Added regression tests for overlapping workspace roots — a root nested inside another root — covering the duplicate results, restarting progress counter and dropped refresh results fixed in 1.1.1. Verified against the pre-1.1.1 scanner: the new tests fail there and pass here.
181
+ - Added tests pinning program reuse (same `ts.Program` when nothing changed on disk) and mtime-based invalidation, which nothing previously covered.
182
+ - Removed `tests/unit/edge-cases/performance.test.ts`. It imported the scanner, never invoked it, and timed `Array.prototype.filter` over synthetic arrays.
183
+ - Raised the Jest timeout to 30s. Scanner tests build real `ts.Program` instances and several legitimately take 6-8s; under coverage instrumentation they intermittently exceeded the old 10s budget.
184
+
185
+ ## [1.1.1]
186
+
187
+ ### Fixed
188
+
189
+ - **Multi-root workspaces no longer report the same file twice** — all folders are now scanned in a single pass, so a file reachable from two overlapping roots appears once and scan progress counts up monotonically instead of restarting at each folder
190
+ - **Configuration is found outside the first workspace folder** — every folder is consulted in order and the first that defines a config wins; all folders' config files are watched
191
+ - **Configuration loads for folders added after startup** — the extension now reacts to workspace folder changes instead of binding to the folder set present at activation
192
+ - **Refreshing results keeps items from every root** — the refresh previously dropped results outside the first workspace folder, and no longer rebuilds the TypeScript programs of roots that hold none of the refreshed files
193
+ - **Viewing a historical scan updates editor diagnostics** to match the scan being shown
194
+ - Diagnostic squiggles use the span measured at the usage site rather than the declaration's name length
195
+ - Exclude/include glob patterns are matched case-insensitively on Windows
196
+ - CSV export quotes values containing a carriage return
197
+ - The custom-tag dialog stays open when the tag is rejected, instead of discarding what was typed
198
+ - Sidebar webview listeners and the settings panel are disposed with the extension
199
+
200
+ ### Changed
201
+
202
+ - **Removed the `ignoreDeprecatedInComments` option.** It never had any effect: deprecation tags are read via TypeScript's JSDoc parser, which only ever sees `/** ... */` comments, so tags in `//` and `/* */` comments were already ignored regardless of the setting. Leaving the key in your config is harmless.
203
+ - The results panel and the sidebar now share one `Scanner`, halving the memory held by cached TypeScript programs
204
+
205
+ ## [1.1.0]
206
+
207
+ ### Added
208
+
209
+ - **View Results button** in the sidebar to reopen the results panel after a scan
210
+ - **Editor diagnostics follow every results update** — ignoring an item now clears its squiggles immediately
211
+ - Historical scans refresh the sidebar state when viewed
212
+
213
+ ### Fixed
214
+
215
+ - Sidebar no longer gets stuck in the scanning state when a scan fails — every error path resets the UI
216
+ - Internal commands (Refresh, Open Results, Update Tree View) hidden from the Command Palette; invoking Update Tree View without arguments no longer breaks the sidebar
217
+ - Results panel Refresh reloads ignore rules first and syncs the refreshed results back to the sidebar and diagnostics
218
+ - Concurrent scans are refused ("A scan is already in progress") instead of racing each other's cancellation
219
+ - View Results button stays hidden after a scan that found nothing
220
+ - Webview templates no longer corrupt when saved filter text contains dollar-sign patterns
221
+ - Custom-tag descriptions can be cleared, and colors are validated when editing a tag
222
+ - Explorer context-menu entries show their proper command titles
223
+
224
+ ### Changed
225
+ - Project scans now discover every tsconfig/jsconfig in the workspace (nested projects included) and cover all folders of multi-root workspaces
226
+ - TypeScript programs are cached between scans and rebuilt only when the config or its files change, making rescans much faster
227
+ - Scans can now be cancelled between program builds in multi-project workspaces
228
+
229
+ - **~40 MB smaller VSIX**: TypeScript moved to devDependencies (already bundled) and packaging trimmed to the bundle + webview assets
230
+ - Scans yield to the event loop per file — the editor stays responsive and cancellation takes effect mid-scan
231
+ - Deprecation info is cached per declaration during a scan, speeding up projects with heavily-used deprecated symbols
232
+ - Export format handling consolidated into a single code path for the command, panel, and historical exports
233
+ - README and Marketplace description rewritten: usage-tracking positioning, and documentation for the Statistics Dashboard, Scan History, Editor Diagnostics, and configuration options
234
+
235
+ ## [1.0.0]
236
+
237
+ ### Initial Release
238
+
239
+ First release of Deprecated Tracker for VS Code.
240
+
241
+ #### Features
242
+
243
+ - **Smart Scanning**: Scan TypeScript and JavaScript projects for deprecated code using TypeScript Compiler API
244
+ - **Multiple Scan Modes**:
245
+ - Scan entire project
246
+ - Scan specific folders
247
+ - Scan individual files
248
+ - Right-click context menu integration
249
+ - **Custom Deprecation Tags**: Define custom tags beyond `@deprecated` (e.g., `@obsolete`, `@legacy`, `@experimental`)
250
+ - **Interactive Results Panel**: Clean table view with filtering and navigation
251
+ - **Filtering**: Filter results by name or file path
252
+ - **Ignore Management**:
253
+ - Ignore specific methods, properties, or classes
254
+ - Ignore entire files
255
+ - Manage ignored items through dedicated panel
256
+ - **Export Results**: Export scan results to CSV, JSON, or Markdown formats
257
+ - **Configuration Support**: Customize behavior via `.deprecatedtrackerrc` or `package.json`
258
+ - **Scan History**:
259
+ - View past scans
260
+ - Compare results over time
261
+ - Export historical scan data
262
+ - **State Persistence**: Filters and settings persist across VS Code sessions
263
+ - **Quick Navigation**: Jump directly to deprecated code locations with one click
264
+ - **Sidebar Integration**: Dedicated sidebar view for quick access
265
+
266
+ #### Configuration Options
267
+
268
+ - Custom trusted packages whitelist
269
+ - File exclude/include patterns
270
+ - Severity levels
271
+ - Custom deprecation tags
272
+
273
+ #### Supported Files
274
+
275
+ - TypeScript (`.ts`, `.tsx`)
276
+ - JavaScript (`.js`, `.jsx`, `.mjs`)
277
+
278
+ #### Requirements
279
+
280
+ - VS Code 1.74.0 or newer
281
+ - TypeScript project with `tsconfig.json` or JavaScript project with `jsconfig.json`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Milad Jokar
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.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # deprecated-tracker
2
+
3
+ Find deprecated code — and everywhere you still use it — in TypeScript and JavaScript projects, from the command line.
4
+
5
+ Most "find deprecated code" tools grep for `@deprecated` and show you the declarations. This one uses the TypeScript type checker, so it also finds every **usage** of a deprecated symbol, including calls into deprecated APIs from your dependencies. That's the part you need when planning a migration: not "what is deprecated", but "where am I still using it".
6
+
7
+ ```bash
8
+ npm install --save-dev deprecated-tracker
9
+ ```
10
+
11
+ No peer dependencies to install — the TypeScript compiler ships inside the bundle.
12
+
13
+ ## The ratchet
14
+
15
+ Failing a build on *any* deprecated code is useless once a codebase already has hundreds. This records today's count as a **baseline** and fails only when the number **rises**, so debt becomes something a team ratchets down instead of a wall it can never clear.
16
+
17
+ ```bash
18
+ npx deprecated-tracker --update-baseline # commit .deprecated-tracker-baseline.json
19
+ npx deprecated-tracker # exits 1 only if the count went up
20
+ ```
21
+
22
+ A first run with no baseline **passes** and tells you to record one. When the count falls it passes and prints how stale the baseline has become.
23
+
24
+ ## Gate a commit
25
+
26
+ Works with every popular Git hooks manager. It scans only the staged files and, by default, reports only the lines that commit actually wrote — so touching a legacy file is free, and adding a deprecated call to it is not.
27
+
28
+ ```json
29
+ // .lintstagedrc — lint-staged appends the staged paths
30
+ { "src/**/*.{ts,tsx,js,jsx}": "deprecated-tracker --files" }
31
+ ```
32
+
33
+ ```sh
34
+ # simple-git-hooks, a bare .husky/pre-commit, or .git/hooks/pre-commit —
35
+ # managers that pass no paths, so the CLI asks git itself
36
+ npx deprecated-tracker --staged
37
+ ```
38
+
39
+ Recipes for husky, lefthook and the `pre-commit` framework (which has a `.pre-commit-hooks.yaml` manifest here) are in the [full CLI reference](https://github.com/milad-hub/deprecated-tracker/blob/main/docs/CLI.md).
40
+
41
+ ## For AI coding agents
42
+
43
+ Register it once and Claude Code or Codex can call the scanner by name:
44
+
45
+ ```bash
46
+ npx deprecated-tracker mcp install # --agent claude-code|codex|all
47
+ ```
48
+
49
+ That exposes three tools — `scan_project`, `scan_changes` and `scan_files` — with schemas the agent can read, structured results, and no shell-approval prompt per call. Restart the agent afterwards; Claude Code will ask you to approve a project-scoped server the first time.
50
+
51
+ No install needed either way: point `--files` at what the agent just wrote and read the JSON off stdout. Unstaged edits are covered, since a file with no staged hunks is read as entirely changed.
52
+
53
+ ```bash
54
+ npx deprecated-tracker --files src/a.ts src/b.ts --format json
55
+ ```
56
+
57
+ ```json
58
+ {
59
+ "passed": false,
60
+ "total": 1,
61
+ "items": [
62
+ { "name": "oldApi", "kind": "usage", "file": "src/a.ts",
63
+ "line": 12, "character": 10, "reason": "Use newApi instead" }
64
+ ]
65
+ }
66
+ ```
67
+
68
+ `items[].reason` carries the `@deprecated` text — usually the replacement instruction, and the field to act on.
69
+
70
+ ## Options
71
+
72
+ | Option | Effect |
73
+ |---|---|
74
+ | `--files <file...>` | Scan only these files; everything after is a path |
75
+ | `--staged` | Ask git for the staged files, for hook managers that pass none |
76
+ | `--changed` | Everything uncommitted: staged, unstaged and untracked |
77
+ | `--whole-files` | With `--files` / `--staged`, scan each whole file and ratchet it per-file instead of reporting only changed lines |
78
+ | `--root <dir>` | Project root, so paths can follow `--files` |
79
+ | `--baseline <file>` | Baseline location (default `.deprecated-tracker-baseline.json`) |
80
+ | `--update-baseline` | Record the current counts and exit 0 |
81
+ | `--max-new <n>` | Allow a deliberate increase of `n` |
82
+ | `--fail-on-any` | Ignore the baseline; fail if anything is found |
83
+ | `--format text\|json\|sarif\|markdown` | Report shape (default `text`) |
84
+ | `--output <file>` | Write the report to a file instead of stdout |
85
+ | `--annotate github\|azure` | Emit inline CI annotations for files that rose |
86
+ | `--quiet`, `--help`, `--version` | — |
87
+
88
+ Exit codes: **0** at or below the baseline · **1** above it · **2** bad usage or unreadable baseline · **3** the scan failed. `1` is a verdict, not a crash.
89
+
90
+ ## Requirements
91
+
92
+ Node 18+, and a `tsconfig.json` or `jsconfig.json` somewhere in the project. Scans `.ts`, `.tsx`, `.js` and `.jsx`.
93
+
94
+ Configuration comes from `.deprecatedtrackerrc` or a `deprecatedTracker` key in `package.json` — trusted packages, include/exclude globs, severity. See the [full reference](https://github.com/milad-hub/deprecated-tracker/blob/main/docs/CLI.md).
95
+
96
+ ## Configuration
97
+
98
+ `.deprecatedtrackerrc`, or a `deprecatedTracker` key in `package.json`:
99
+
100
+ ```json
101
+ {
102
+ "trustedPackages": ["rxjs", "@angular/core"],
103
+ "excludePatterns": ["**/*.spec.ts"],
104
+ "customTags": [{ "tag": "@legacy", "description": "Kept for compatibility" }],
105
+ "ignoreMethods": ["^internal_"]
106
+ }
107
+ ```
108
+
109
+ - **`customTags`** tracks tags beyond `@deprecated`. Reserved JSDoc tags are refused.
110
+ - **`ignoreMethods`** takes regex sources, matched against the bare method name in every file.
111
+ - **`excludePatterns`** is how you ignore whole files.
112
+
113
+ A rejected key warns on stderr and the run continues — a typo should not fail a commit, but it should not be silent either.
114
+
115
+ ## Optionally, a VS Code extension
116
+
117
+ The same scanner with an interactive results table, a statistics dashboard, editor squiggles and scan history: [Deprecated Tracker on the Marketplace](https://marketplace.visualstudio.com/items?itemName=milad445.deprecated-tracker). It is not required — this package is complete on its own — and the two are configured separately: tags and ignore rules set in the editor live in VS Code workspace storage, which nothing headless can read.
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { run } = require("../out/cli.js");
5
+ const { version } = require("../package.json");
6
+
7
+ run(process.argv.slice(2), { version })
8
+ .then((code) => {
9
+ process.exitCode = code;
10
+ })
11
+ .catch((error) => {
12
+ process.stderr.write(`deprecated-tracker crashed: ${error && error.stack ? error.stack : error}\n`);
13
+ process.exitCode = 3;
14
+ });