uptide 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -1,18 +1,21 @@
1
1
  # Uptide
2
2
 
3
- **Renovate updates the version. We update the code.**
3
+ **Migrations you can merge.**
4
4
 
5
- Uptide tells you which of your lines a dependency upgrade breaks, then migrates them on a
6
- branch it has verified with your own compiler and tests. TypeScript repositories; verified
7
- migrations for **zod 3 → 4** and **stripe** today.
5
+ [![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
6
+
7
+ Uptide finds what a dependency upgrade breaks in your code, migrates it, and proves it with
8
+ your compiler and tests. TypeScript repositories; verified migrations for **zod 3 → 4** and
9
+ **stripe** today.
8
10
 
9
11
  ## Quickstart (30 seconds)
10
12
 
11
- No account, no config. In your repository, with dependencies installed:
13
+ No account, no config. In your repository:
12
14
 
13
15
  ```sh
14
- npx uptide check # which of your lines the upgrade breaks
15
- npx uptide fix --only zod # migrate on a new branch, verified; nothing is pushed
16
+ npx uptide list # fast discovery; no install or compilation
17
+ npx uptide check zod # analyze one or more named dependencies (install first)
18
+ npx uptide fix zod # migrate on a new branch, verified; nothing is pushed
16
19
  npx uptide pr --branch uptide/zod-4.6.5 # prints the plan; add --yes to push and open the PR
17
20
  ```
18
21
 
@@ -28,38 +31,134 @@ tests. Everything below is real output from it.
28
31
  **Before: `check`.** What breaks, where, and who can fix it:
29
32
 
30
33
  ```console
31
- $ npx uptide check
32
- uptide check · storefront (pnpm, 2 packages) · 8.3s
33
-
34
- zod 3.25.76 → 4.6.5 major · latest on npm ✗ 28 breaking in 7 files 24 by rule · 4 by agent
35
- stripe (packages/api) 14.25.0 → 23.0.0 major · latest on npm ✗ 4 breaking in 3 files 1 by rule · 3 by agent
36
-
37
- zod
38
- ✗ New error API (required_error → error) 24 sites by rule
39
- ✗ ZodTypeDef removed 1 fix, 3 errors by agent
40
- ✗ .ip() removed monitoring.ts:6 by agent
41
- ! 15 deprecated calls (.uuid, .datetime, .email, ...) 8 by rule
42
-
43
- stripe
44
- ✗ Test fixture casts widened renewal.test.ts:7 by rule
45
- ✗ Subscription billing period moved to items 2 sites by agent
46
- ✗ apiVersion no longer matches the SDK client.ts:9 by agent
34
+ $ npx uptide check zod stripe
35
+ uptide check · storefront · pnpm · 8.5s
36
+
37
+ zod 3.25.76 → 4.6.5 major · latest on npm verified ✗ 28 breaking in 7 files 24 auto-fixable · 4 need the agent (LLM)
38
+ stripe (packages/api) 14.25.0 → 23.0.0 9 majors behind · latest on npm verified ✗ 4 breaking in 3 files 1 auto-fixable · 3 need the agent (LLM)
39
+
40
+ zod 28 breaking · compiled against 4.6.5: 28 new type errors
41
+ ✗ New error API (required_error → error) 24 sites auto-fixable
42
+ ✗ ZodTypeDef removed 1 fix, 3 errors needs the agent (LLM)
43
+ ✗ .ip() removed monitoring.ts:6 needs the agent (LLM)
44
+ ! 15 deprecated calls (.uuid, .datetime, .email, ...) 8 auto-fixable
45
+
46
+ stripe 4 breaking · compiled against 23.0.0: 4 new type errors
47
+ ✗ Test fixture casts widened renewal.test.ts:7 auto-fixable
48
+ ✗ Subscription billing period moved to items 2 sites needs the agent (LLM)
49
+ ✗ apiVersion no longer matches the SDK client.ts:9 needs the agent (LLM)
47
50
  1 API change since 2023-10-16 affects your code
48
51
 
49
52
  Next
50
- npx uptide fix --only zod migrate on a new branch, verify, no push
51
- npx uptide fix --only stripe migrate on a new branch, verify, no push
52
- npx uptide check --details every site and reason
53
+ npx uptide fix zod migrate on a new branch, verify, no push
54
+ npx uptide fix stripe migrate on a new branch, verify, no push
55
+ npx uptide plan --only 'zod,stripe' the order to upgrade in, with the effort
56
+ npx uptide check zod stripe --details every site and reason
53
57
  ```
54
58
 
59
+ `list` reads manifests, lockfiles, source imports and registry metadata. PRIORITIES come
60
+ first: up to five rows, most urgent first, each with a one-line reason and the command to run
61
+ (known advisories for the installed version, a deprecated version, a major line with no release
62
+ in a year, a peer range holding another upgrade back, two or more majors behind; cheaper
63
+ upgrades first among equals). When nothing is urgent it says so and suggests the cheap batch of
64
+ minor/patch upgrades that touch few files. The rules and weights are in
65
+ [docs/priorities.md](docs/priorities.md); nothing in `list` calls an LLM. Groups follow,
66
+ with a command such as `uptide check --group nestjs` to check their members together: a scope
67
+ is one family (`@radix-ui/*`), and packages also group across scopes when a peer range of one's
68
+ latest version needs the other, or when both pin the same exact version of a dependency
69
+ (`ai + @ai-sdk/*`). Each group says why.
70
+ External peers are members labeled by the package that requires them. Each member keeps its own
71
+ classification and evidence. A group header follows its lead; members with independent usage
72
+ appear in their own section, and the group command/JSON still includes the complete member list. Each row gives current → latest, upgrade
73
+ kind and major gap, verified/generic tier, importing files, calls, references and top symbols.
74
+ Workspace columns appear only in workspaces. Top symbols require `--details`; terminal
75
+ columns fit the available width, and only verified packages carry a tier tag. Minor/patch upgrades, tooling and possibly
76
+ unused packages are collapsed; `--all` expands them. Tools used by scripts/configs, runtime
77
+ types and required direct dependencies/peers are classified separately from possibly unused packages. This includes
78
+ package.json tool settings (including keys matching dependency names), tool rc file presence,
79
+ installed bin names (including collisions), hook/task commands, Karma plugin mappings and auto-loading, stylesheet
80
+ imports and HTML assets under node_modules. Expanded rows explain the evidence; “possibly
81
+ unused” means no usage was found by Uptide's scan, so verify before removing. Legacy lint-staged
82
+ `linters` maps and current flat glob maps both supply commands. Their `ignore` entries are
83
+ neither commands nor source-scan exclusions.
84
+
85
+ Registry settings use environment overrides, project and user `.npmrc` files, scoped
86
+ registries and host/path-scoped credentials. Known advisories come from one request to npm's
87
+ bulk advisory endpoint with the names and installed versions of packages served by the public
88
+ npm registry; packages from another registry or scope are never sent there. A failure or
89
+ timeout (5 s) says “advisories not checked” and never fails the run; `--no-advisories` (or
90
+ `"advisories": false` in `uptide.config.json`) never sends the request. Runtime dependencies
91
+ rank before dev-only ones, and an advisory row names its smallest fix (same major or not). Publish dates for the
92
+ support window come from the full registry document of packages with a newer major, under the
93
+ same 5-second deadline. Discovery otherwise uses abbreviated metadata with up to
94
+ 16 concurrent requests, a 10-second timeout per attempt (including response bodies), and one
95
+ retry for timeouts or HTTP 5xx. Only a host that returns 401, 403 or 405 is blocked for the
96
+ rest of that run. Credentials and registry responses are never written to the discovery cache.
97
+ Unresolved packages stay in JSON's `unknown` list, the summary reports the shared reason (e.g. “3 not checked (access denied)”)
98
+ or simply “N not checked” for mixed reasons,
99
+ and HTML keeps one named row per incomplete package. Repeated failures are grouped by host and
100
+ reason (more than five network errors, or multiple access failures); `--details` lists names.
101
+ Successful packages remain visible; incomplete discovery exits 2. Analysis commands retain
102
+ their normal retry policy.
103
+
104
+ Git/GitHub, local file/link/workspace dependencies and HTTP(S) sources are intentional skips,
105
+ including `npm:` aliases pointing to those sources. They appear as collapsed “not checked:
106
+ non-registry source (github)” lines (expand with `--all` or `--details`) and a collapsed HTML
107
+ section; JSON keeps them in `skipped`. They do not make discovery incomplete or change exit 0.
108
+ Registry aliases resolve the real package name, retaining their local dependency names for
109
+ usage scanning and adding `registryName` to aliased upgrade rows in JSON.
110
+ `--json` gives every row. `--html [--open]` creates a report styled like check, with copyable
111
+ commands and no source code or file paths by default; `--details` adds file lists.
112
+ Usage is syntactic: indirect aliases and reflection are not followed. With different locked
113
+ versions, usage is shown across the repository.
114
+
115
+ `list --verbose` prints phase timings and file counts to stderr: manifest read, registry,
116
+ source scan, config scan and render. Source scan includes file traversal and stylesheet/HTML
117
+ assets; config scan includes configuration parsing and classification. Render covers terminal/JSON
118
+ and optional HTML writing, excluding browser launch. With `--json`, verbose phase/count data is
119
+ also included under `timing`; default JSON stays unchanged. This helps distinguish registry
120
+ latency from repositories with many source/config files. Configs are read statically, never executed.
121
+
122
+ The scan skips only `node_modules`, `.git`, `coverage`, `dist`, `build`, `bower_components`,
123
+ `vendor`, generated-file patterns (`*.min.js`, `*.bundle.js`, `*.map`), and root/nested `.gitignore`
124
+ rules. Git patterns are relative to their declaring directory and support negation. Tool scopes
125
+ (`.prettierignore`, `.eslintignore`, `.stylelintignore`, `standard.ignore`, lint-staged `ignore`)
126
+ do not exclude application code: files a formatter or linter skips may still use dependencies.
127
+ A dependency-name text gate and lexer select candidates for full syntax parsing; bindings,
128
+ shadowing, calls and references still use the syntax parser. Large batches (at least 32
129
+ candidates / 8 MB) use up to four CPU workers; smaller batches avoid worker startup overhead.
130
+
131
+ If Git rules exclude **more than 50%** of candidate application JS/TS files, the summary,
132
+ HTML and `--verbose` warn with the matching patterns and counts. JSON includes `scanWarnings`;
133
+ a usage warning alone does not change the exit code. Candidates exclude built-in/generated
134
+ artifacts, declaration files and tool configs, and are counted before dependency text/lexer
135
+ filtering. Git-ignored subtrees get a filename-only audit without reading/parsing source;
136
+ built-in excluded directories are never enumerated. Verbose output shows candidates, excluded
137
+ sources, parsed files, workers and per-reason skip counts.
138
+
139
+ `check` requires names (`uptide check zod stripe`). With no names it points to `uptide list`
140
+ and exits 2 before doing work. It retains tiers and partial results per named package.
141
+
142
+ `uptide plan` uses discovery, with **unknown** effort until a matching check result is supplied:
143
+
144
+ ```sh
145
+ npx uptide check zod stripe --json > check.json
146
+ npx uptide plan --results check.json
147
+ ```
148
+
149
+ Planning never implicitly compiles every dependency or downloads tarballs. Matching saved
150
+ results (same repository, versions and workspaces) supply effort estimates; rerun `check`
151
+ after source changes. Registry peer metadata and available installed manifests constrain
152
+ the upgrade order. Missing peer metadata is disclosed.
153
+
55
154
  **After: `fix`**, one dependency at a time, each on its own verified branch:
56
155
 
57
156
  ```console
58
- $ npx uptide fix --only zod
157
+ $ npx uptide fix zod
59
158
  uptide fix · zod 3.25.76 → 4.6.5 (latest on npm) · verification passed · 36s
60
159
 
61
160
  Risk Medium: request validation in webhooks
62
- Changes 29 sites in 8 files · 25 by rule · 4 by agent
161
+ Changes 29 sites in 8 files · 25 auto-fixed · 4 fixed by the agent (LLM)
63
162
  Types ✅ 29 errors after the bump → 1 (1 pre-existing)
64
163
  Behavior ✅ 9 schemas identical · 2 not checked · 21/21 custom-message assertions
65
164
  Tests ✅ 5 tests in 3 files passed
@@ -75,11 +174,11 @@ pull request, so you can check that nothing else reads that text:
75
174
  ```
76
175
 
77
176
  ```console
78
- $ npx uptide fix --only stripe
177
+ $ npx uptide fix stripe
79
178
  uptide fix · stripe 14.25.0 → 23.0.0 (latest on npm) · verification passed · 41s
80
179
 
81
180
  Risk High: behavior changes
82
- Changes 6 sites in 3 files · 3 by rule · 3 by agent
181
+ Changes 6 sites in 3 files · 3 auto-fixed · 3 fixed by the agent (LLM)
83
182
  Types ✅ 5 errors after the bump → 1 (1 pre-existing)
84
183
  Behavior ⚠️ 1 of 570 API changes affects your code · 47 touch resources you use (8 breaking)
85
184
  Tests ✅ 3 tests in 2 files passed · the test script of packages/api
@@ -102,16 +201,18 @@ repository already had are subtracted, never blamed on the upgrade.
102
201
 
103
202
  ## What is supported
104
203
 
204
+ Every direct dependency can be discovered and selected for analysis. What differs is how much Uptide knows about it:
205
+
105
206
  | Tier | Dependencies | What you get |
106
207
  | --- | --- | --- |
107
- | **Verified** | zod 3 → 4, stripe 14 and newer | `check` with a migration plan per change, `fix` with rules written for that dependency, behavior checks (zod schemas compared on generated inputs; Stripe changelog filtered to what you call), a reviewed pull request body |
108
- | **Generic** | any other dependency, with `--only <package>` | `check` only: the API diff between the two versions, your usages of what changed, and the compiler's errors against the target. No migrations. |
208
+ | **Verified** | zod 3 → 4, stripe 14 and newer | A migration pack: rules written for that dependency, a guide for the agent, behavior checks (zod schemas compared on generated inputs; Stripe changelog filtered to what you call), and ground truth the pack is scored against. `fix` migrates by rule first, by agent for the rest. |
209
+ | **Generic** | any other dependency | The same analysis without a pack. A finding is called breaking only when your compiler or the runtime probe confirms it, or when it is a `require()` of an ESM-only package or an import of a removed export; everything else is in `--details`. `fix` migrates with the agent alone, under the same verification, and says so in the pull request. |
109
210
 
110
- Verified means a migration pack exists: rules, a guide for the assisted fixer, and ground
111
- truth from a real upgrade that the pack is scored against. Generic is the same analysis
112
- without that knowledge; it is frozen while the packs mature
113
- ([decision](docs/decisions/0010-check-freeze.md)), and generic *migrations* are planned,
114
- not shipped.
211
+ The tier is on every row of `check`, in the HTML report and in the pull request. A generic
212
+ `fix` needs a provider API key (there are no rules to fall back on; without a key it says
213
+ so and changes nothing), stops at `--max-cost` (default $1) and reports what it did not
214
+ complete. Its pull request opens with a note that no pack covers the package: every edit
215
+ was kept on the compiler's word and deserves a careful review.
115
216
 
116
217
  - **Languages:** TypeScript, and JavaScript the compiler can see (`allowJs`).
117
218
  - **Package managers:** `check` on npm, pnpm (workspaces and catalogs), Yarn classic and
@@ -119,6 +220,90 @@ not shipped.
119
220
  node-modules linker.
120
221
  - **Not supported:** Yarn Plug'n'Play, bun's binary lockfile, Deno.
121
222
 
223
+ ## Choosing a model
224
+
225
+ Assisted fixes support Anthropic, OpenAI and Gemini, with the same prompts, tool,
226
+ verification and publish gate. Set the chosen provider's key in your environment:
227
+ `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` or `GEMINI_API_KEY`. Never put keys in repository
228
+ config or command arguments.
229
+
230
+ ```sh
231
+ npx uptide fix zod --provider openai --model gpt-6.1-sol
232
+ UPTIDE_PROVIDER=gemini UPTIDE_MODEL=gemini-3.8-flash uptide fix stripe
233
+ npx uptide fix zod --max-cost 1
234
+ npx uptide fix zod --no-llm
235
+ ```
236
+
237
+ For each setting, precedence is flag → `UPTIDE_PROVIDER` / `UPTIDE_MODEL` → nearest
238
+ `uptide.config.json` up to the Git root. Without a provider setting, detection checks
239
+ `ANTHROPIC_API_KEY`, then `OPENAI_API_KEY`, then `GEMINI_API_KEY`; Anthropic remains the
240
+ overall default. An explicitly selected provider never falls back to another provider.
241
+ The selected provider/model prints before the fix starts, and spend prints at the end.
242
+
243
+ The optional config accepts **only** `provider` and `model` strings:
244
+
245
+ ```json
246
+ { "provider": "openai", "model": "gpt-6.1-sol" }
247
+ ```
248
+
249
+ Unknown fields, nested settings and key-like values are rejected, including when flags
250
+ would override them. Keys are read only from the environment. No key: a generic fix
251
+ exits before cloning, installing or creating a branch; migration packs still apply
252
+ rule-based fixes and leave assisted sites manual. `--no-llm` disables all model calls.
253
+
254
+ Defaults checked against official documentation on 2026-10-04:
255
+
256
+ | Provider | Default | Reference |
257
+ | --- | --- | --- |
258
+ | Anthropic | `claude-sonnet-5-5` (`medium` effort) | [Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview); selected after the storefront comparison |
259
+ | OpenAI | `gpt-6.1-sol` | [GPT-6.1 Sol](https://developers.openai.com/api/docs/models/gpt-6.1-sol), through the Responses API |
260
+ | Gemini | `gemini-3.8-flash` | [Gemini 3.8 Flash](https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash) |
261
+
262
+ Measured on storefront (2026-10-04; USD from returned usage). Each cell lists
263
+ **zod / Stripe**; every run has a $1 ceiling:
264
+
265
+ | Provider | Model | Verified | Agent sites | Attempts | Cost USD |
266
+ | --- | --- | --- | --- | --- | --- |
267
+ | Anthropic | `claude-sonnet-5-5 (medium)` | pass / pass | 4 / 3 | 2 / 2 | $0.013244 / $0.021592 |
268
+ | OpenAI | `gpt-6.1-sol` | pass / pass | 4 / 3 | 2 / 3 | $0.006806 / $0.018677 |
269
+ | Gemini | `gemini-3.8-flash` | fail / fail | 0 / 0 | 12 / 9 | $0.000000 / $0.000000 |
270
+
271
+ Gemini's serial reruns failed after HTTP 503/429 and transport errors, despite a
272
+ successful protocol smoke. Its zero confirmed cost excludes $0.473901 / $0.368667
273
+ retained for unreported usage; it is not a claim of zero possible billing. Full trials, reservations, times,
274
+ exact echoed IDs and the Sonnet 4.6/high/medium comparison are in the
275
+ [provider evaluation](docs/provider-evaluation.md). These single fixture trials are
276
+ not a general model ranking.
277
+
278
+ Tool choice follows each model’s capabilities. Sonnet 5.5 uses `auto` with a strict
279
+ `submit_patch` schema and a tool-only system instruction; Sonnet 4.6, OpenAI and Gemini
280
+ use forced tool calls. Missing or invalid calls consume an attempt and their reported
281
+ cost, then receive the feedback “respond only by calling submit_patch”. HTTP 429 is
282
+ reported as rate limiting, waits for `Retry-After` (60 seconds when absent), and retries
283
+ only when another reservation fits the budget.
284
+
285
+ `--max-cost` defaults to **$1 per package**, including zod and stripe. Before every
286
+ call and retry, Uptide reserves its worst-case input and maximum output cost. A call
287
+ that would exceed the remaining budget is never sent. Actual returned usage replaces
288
+ the reservation; failures without valid usage keep the full reservation, shown
289
+ separately as unknown spend. Rejected patches still consume budget. Unfinished sites
290
+ remain manual and cannot pass the publish gate. Unknown models use the provider's
291
+ highest listed rates with a warning. See [model pricing](docs/model-pricing.md) for
292
+ rates, token estimation and the scope of accounting.
293
+
294
+ `OPENAI_BASE_URL` selects an OpenAI **Chat Completions-compatible, not verified**
295
+ endpoint. Uptide appends `/chat/completions` to the supplied API base URL and uses
296
+ Bearer authentication, strict functions and forced `submit_patch`. The official OpenAI
297
+ endpoint uses Responses when this override is absent. HTTPS is required, except HTTP
298
+ localhost for local servers. Custom deployments must support this protocol and the
299
+ supplied model ID; Azure-specific authentication and routing are not inferred. Custom
300
+ endpoint prices may differ from the built-in OpenAI table.
301
+
302
+ **Privacy:** assisted fixes send the finding, enclosing code snippet and compiler
303
+ error to the provider you chose (or your `OPENAI_BASE_URL`). Your provider's data policy
304
+ applies. `--no-llm` keeps assisted fixes off. Anonymous telemetry, when enabled, adds
305
+ only the provider and a public model ID; private/custom model IDs become `custom`.
306
+
122
307
  ## How verification works
123
308
 
124
309
  `fix` never works in your checkout. It clones your repository into a temporary directory
@@ -129,7 +314,8 @@ and, there:
129
314
  produces the lockfile, with lifecycle scripts disabled; a lockfile change outside the
130
315
  upgraded dependency's subtree is rejected.
131
316
  3. **Rule-based fixes.** Deterministic rewrites, only at the sites `check` reported.
132
- 4. **Assisted fixes (optional).** Sites no rule covers go to the LLM one at a time. A patch
317
+ 4. **Assisted fixes (optional; all there is for a generic package).** Sites no rule covers
318
+ go to the LLM one at a time. A patch
133
319
  is kept only if it removes its compiler error, introduces none, and passes the pack's
134
320
  own validator; otherwise it is reverted and the site is left for you.
135
321
  5. **Verifies.** Type-checks with *your* TypeScript and subtracts the baseline; runs the
@@ -148,31 +334,70 @@ rewritten by rule.
148
334
 
149
335
  ## Privacy
150
336
 
151
- Analysis runs locally. Your code is sent only to the LLM provider (Anthropic), only
152
- for assisted fixes in `uptide fix`, and only with your own ANTHROPIC_API_KEY: for each
337
+ Analysis runs locally. Code snippets go to your chosen LLM provider (Anthropic, OpenAI or Gemini), only
338
+ for assisted fixes in `uptide fix`, and only with your own API key from ANTHROPIC_API_KEY,
339
+ OPENAI_API_KEY or GEMINI_API_KEY: for each
153
340
  site the rules cannot migrate, the finding, the enclosing function and the compiler
154
- error. `uptide fix --no-llm` turns assisted fixes off. No telemetry, no account.
155
- Other network use: your npm registry for package metadata and tarballs, and GitHub
156
- only when you pass `fix --pr` or run `pr-body`.
341
+ error. `uptide fix --no-llm` turns assisted fixes off. No account.
342
+ Anonymous telemetry is off by default and asks for consent in an interactive terminal.
343
+ Set UPTIDE_TELEMETRY=0 to disable it. No IP, code, paths or repo names are collected.
344
+ Other network use: your npm registry for package metadata and tarballs, npm's advisory
345
+ endpoint from `list` (public package names and installed versions; `--no-advisories` turns
346
+ it off), PostHog EU only
347
+ after telemetry opt-in, and GitHub when you pass `fix --pr` or run `pr` / `pr-body`.
157
348
 
158
- There is no Uptide server. In a table:
349
+ There is no Uptide server. With telemetry off (the default):
159
350
 
160
351
  | | Where it runs | What leaves your machine |
161
352
  | --- | --- | --- |
353
+ | `list`, `plan` | locally | package names/versions requested from your npm registry, and `list` sends public packages' names and installed versions to npm's advisory endpoint; metadata only, no source code |
162
354
  | `check` | locally | nothing of yours; it downloads package tarballs from your npm registry. No LLM call, and nothing in your repository is executed. |
163
355
  | `fix`, rules and verification | locally, in a temporary clone | nothing of yours |
164
- | `fix`, assisted fixes | Anthropic's API, with **your** `ANTHROPIC_API_KEY` | per site no rule covers: the finding, the enclosing function or declaration, and the compiler error |
356
+ | `fix`, assisted fixes | Your chosen provider's API, with **your** environment API key | per site no rule covers: the finding, the enclosing function or declaration, and the compiler error |
165
357
  | `pr`, `fix --pr` | GitHub, through your own `gh` | the branch and the pull request, when you say so |
166
358
 
167
359
  Without a key, or with `--no-llm`, those sites are listed for you instead. The full model, and how to report a problem, is in
168
360
  [SECURITY.md](SECURITY.md).
169
361
 
362
+ ## Optional anonymous telemetry
363
+
364
+ On your first interactive run, Uptide asks once whether to share anonymous usage;
365
+ pressing Enter means **no**. CI and piped/JSON runs never prompt. Use
366
+ `uptide telemetry on`, `off`, `status`, or `show` (the last sanitized event).
367
+ `UPTIDE_TELEMETRY=0` always disables collection. CI requires `UPTIDE_TELEMETRY=1`,
368
+ even when the saved preference is on.
369
+
370
+ With consent, events contain a random installation ID, a salted repository hash,
371
+ command/version, proven public npm package versions, aggregate counts, verification
372
+ result, timings and cost. No IP, code, paths, repository names or user names are
373
+ collected. Data is stored in **PostHog Cloud EU**, with a **90-day retention policy**.
374
+ Delivery is best effort in a short-lived background process; unavailable telemetry
375
+ never fails a command. Builds without a capture key send nothing.
376
+ See [the exact fields, controls and deployment requirements](docs/telemetry.md).
377
+
170
378
  ## Exit codes
171
379
 
172
380
  For scripts and CI: **0** nothing breaking, **1** breaking changes found,
173
381
  **2** uptide could not answer (bad arguments, unsupported repository, no network). When
174
382
  it cannot answer, it says why and prints the exact command to run next.
175
383
 
384
+ One dependency failing (a registry error, an analysis that ran out of memory) does not
385
+ empty the report: the others are shown and the failed one is named with its reason. The
386
+ exit code is then 1 if anything breaking was found, else 2, because the question was not
387
+ fully answered. `list` exits 2 when discovery is incomplete, while retaining successful rows.
388
+ `fix` and `verify` exit 0 when the migration verifies and 1 when it does not; `plan` exits
389
+ 0 with a plan, or 2 when discovery is incomplete.
390
+
391
+ Analysis concurrency uses CPU count and available memory (including reclaimable memory
392
+ reported by the OS), reserving at most about 60% for worker heaps and estimated overhead.
393
+ Named checks build their baseline and target programs from the files importing those packages;
394
+ TypeScript follows their imports. Workspaces with no such imports load no program. The estimate
395
+ uses only that reachable graph. Workspaces run serially with the full reservation when they
396
+ cannot fit in parallel; unexpected parallel memory failures get one serial retry. Only a scoped
397
+ program that cannot fit alone is skipped, with its workspace, estimate and available budget.
398
+ `--workspaces` and `UPTIDE_WORKER_HEAP_MB` can lower limits, never bypass the memory cap.
399
+ Compiler allocations are estimates; unexpected worker failures still preserve other results.
400
+
176
401
  ## Documentation
177
402
 
178
403
  - [CLI reference](docs/cli.md): flags, the HTML report, each step of `fix`, pull request
@@ -186,4 +411,9 @@ it cannot answer, it says why and prints the exact command to run next.
186
411
 
187
412
  ## License
188
413
 
189
- [MIT](LICENSE).
414
+ [Apache-2.0](LICENSE). Releases up to and including 0.3.0 were published under the MIT
415
+ license; 0.4.0 and later are Apache-2.0.
416
+
417
+ The published CLI is one bundle: it inlines its dependencies. The notice for every package
418
+ in that bundle, with the full text of its license, ships in the npm package as
419
+ `THIRD-PARTY-NOTICES` and is generated from the bundle itself at build time.