Repository navigation
Releases: uptide-dev/uptide
Release list
v0.18.3
Patch Changes
-
#271
b66598eThanks @lucasbraum! -fixno longer hides an agent session that could not work. When the Anthropic API refuses the request (an invalid key, an empty credit balance, a model the key cannot use), the Agent SDK ends the session after one turn with nothing spent and the API's message; Uptide dropped that message, recorded "made no change" for every site and ran the feedback rounds into the same error. Now the task records the error (llm.tasks[].error, gateerror), no further session starts, and every task that leaves nothing says why inllm.tasks[].noChange: the API's error, no turn, no output, a refusal, a stop, or every edit rejected. When nothing the agent did stayed,report.json(llm.agentIdle), the terminal and the PR body say "The agent did not change anything: ", and the PR body no longer says the code was migrated when every site is still manual. -
#271
b66598eThanks @lucasbraum! - The lockfile check no longer stops an upgrade when the package manager moves an unchanged package's dependency onto the copy the upgrade installs. Upgrading express 4 to 5, pnpm can move another package'sqsoriconv-liteonto the newer copy express 5 brings: the old copy leaves the lockfile, and every package depending on it read as "same version, different resolution", so the run fell back to an agent-led draft. Such a move is now in scope when it stays in the same major (the same minor below 1.0) and never goes back, and the copy it left goes with it when nothing else needs it; the PR body and the terminal list each one as lockfile housekeeping ("onto the upgrade's copy"). A move to a release the upgrade did not bring, a downgrade, a major apart, or a change to what the repository declares itself is still refused. The same applies to npm (a nested copy dropped for the hoisted one) and Yarn Berry (a descriptor that now resolves to the upgrade's copy). -
#273
51d0370Thanks @lucasbraum! -fixandcheckin a checkout whose dependencies are not installed now stop before any analysis withPACKAGE_NOT_INSTALLED(exit 2), name thepackage.jsonthat declares the package, say whether nothing is installed or only that package is missing, and give the frozen install for the lockfile (npm ci,pnpm install --frozen-lockfile,yarn install --frozen-lockfile,yarn install --immutable). Before, anode_modulesin a directory above the project counted as the project's install, so a fresh clone under such a directory got past the check andfixfailed with a misleading "has no upgrade". Uptide still installs nothing in your checkout.check --jsonnow answers every refusal on stdout with{"error": {"code", "message"}}, asfix --jsondoes. When the package is already at or past the target,fixsays " is already at (target )". -
#271
b66598eThanks @lucasbraum! - The PR body titles each group of sites by what changed instead of an internal key: a pack rule's group by the pack's one-line summary of the rule (report.jsonkeeps them asruleSummaries), and sites no rule covers, keyed by the path of the declaration that changed (e.query), by what the compiler said there or by what changed ("e.querywas removed in express 5.3.0").
v0.18.2
Patch Changes
-
#267
907dffbThanks @lucasbraum! - The agent can no longer change dependencies outside the upgrade. An agent edit that changes or removes an existing dependency in anypackage.json, or touchesoverrides,resolutionsor thepnpmfield, is refused and reverted. Uptide sends the refusal back to the agent in the next feedback round, naming the package, and records it inreport.json(outOfScopeDependencyEdits). That includes the upgraded package and its planned companions, whose versions the engine wrote: only a rewrite to the same value is allowed. The agent may still add a new dependency: it is kept, recorded (agentAddedDependencies) and listed under "Added by the agent" in the PR body. Lockfiles,.npmrc,.yarnrc(.yml),.pnpmfile.cjs,pnpm-workspace.yamland newpackage.jsonfiles are read-only for the agent. -
#267
907dffbThanks @lucasbraum! - A companion that would move a new major is planned only when the upgraded package asks for it: its own manifest at the target pins the companion, the companion's manifest declares the upgraded package, or the upgraded package's pack names it. When a third package asks for it (@guardian/libs33 pinning@guardian/ophan-tracker-js3.1.0 during a typescript upgrade), Uptide no longer moves it. The PR lists it under "Blocked" with the declaring package, the manifest field and the range. Release pairs still move with their lead:react-domwithreact,@ai-sdk/*withai,@sentry/profiling-nodewith@sentry/node. -
#267
907dffbThanks @lucasbraum! - A package that does not move no longer drags another one through its pins:fix typescripton guardian/support-dotcom-components moved@guardian/ophan-tracker-js2.8.3 → 3.1.0 because@guardian/libs33.0.0, which stayed, pins it. A pin the same manifest also declares as a peer the install satisfies moves nothing either, and a pin reason now names the manifest field and the installed version. -
#266
a5e3f57Thanks @lucasbraum! -uptide fixno longer upgrades a peer blocker across a major that no migration pack covers. Before,redis5 → 6 next totypeorm0.3 (which peers on redis ^5) moved typeorm to 1.1.0 and ended in an agent-led draft. Now the blocker keeps its version, with a peer override scoped to it in package.json: npmoverrides.<blocker>.<peer>, pnpmpnpm.peerDependencyRules.allowedVersions, Yarnresolutions["<blocker>/<peer>"]. The lockfile scope check still covers the install. The PR body names the override, which release was not taken and why. Inreport.json, eachpeerConflictsentry now hasstrategy(override,blockedornone),declinedandoverride. If verification fails with the override, the blocker is reported as a blocker and is still not upgraded. A blocker you name on the command line, or one whose major a pack covers, is upgraded as before. -
#264
2089d0aThanks @lucasbraum! -uptide fixno longer stops when the package manager resolves a different version than the target. Yarn classic ignored the pin for a direct dependency and resolved a range such as^7.0.105to its newest match (7.0.146). Now the lockfile resolves exactly the target with npm, pnpm, Yarn classic and Yarn Berry, and the manifest keeps its range. If the package manager still resolves another version, the run continues only when that version is in the same major, inside the manifest range and covered by the pack. The PR body, the terminal summary andreport.json(resolvedVersion,lockfile.resolved) then name both versions. Otherwise the run stops with an error that names the target, the resolved version and the reason. -
#268
4cee03aThanks @lucasbraum! -fixcomputes the agent's cost itself, per model and token class, from Uptide's price table:report.jsonand--jsonlist each model's uncached input, cache read, 5-minute and 1-hour cache write and output tokens, the rate applied to each and the cost, so the total can be redone by hand. The Agent SDK's own figure is kept apart assdkReportedCostUsd;--max-costcounts the higher of the two, a gap above 5% is printed as a warning, and a model missing from the table uses the SDK's figure, marked unverified.llm.inputTokensnow counts uncached input only. -
#268
4cee03aThanks @lucasbraum! - Sonnet 5.5 cache reads are priced at the published $0.10 per million tokens (0.05x input), not $0.20. Every Anthropic rate in the price table was checked against Anthropic's pricing page on 2026-10-20, and a test now pins each one.
v0.18.1
Patch Changes
- #262
e72bb63Thanks @lucasbraum! - Pin the Action to v0.18.0.
v0.18.0
Minor Changes
-
#261
93f029eThanks @lucasbraum! - Sentry 10 → 11: report everySentry.initwhose data collection widens becausedataCollectionis unset, citing the migration guide, and give the agent the guide's exact v10 baseline. After a fix, a site counts as kept only when every category is at least that restrictive, so a partial edit such as a cookie deny list stays open in the PR instead of being reported as kept. The agent now keeps privacy settings at their most restrictive value, or leaves them as a decision, when no cited edit exists. -
#253
e48373dThanks @lucasbraum! - Find Stripe's clover billing-mode default change at subscription creation sites, across the six affected APIs. Respect request API-version pins, preserve classic billing at documented parameter paths, and report unresolved parameters or semantics as decisions. Verify quoted sources against full-page hashes at pack-build time without vendoring Stripe pages. Score the dms-saas silent billing change in UpgradeBench.
Patch Changes
-
#260
8ea1a87Thanks @lucasbraum! - A build that fails the same way before and after the upgrade (same command, status and output; only durations and clock times may differ) no longer fails verification. Builds are now compared to the baseline the same way tests are. The PR says⚠️ build: failing at baseline, not checked, and the verdict readsno new errors, notverification passed. A build that passed at baseline and fails after the upgrade still fails, and so does one that fails differently. Without a pack, a run like this still does not publish, because its build cannot verify the bump. -
#259
0db73c8Thanks @lucasbraum! - Let the agent add a property the upgraded types made required to a test fixture: only to the object the compiler's TS2739, TS2740 or TS2741 error points at, and only with a literal value. Every other test input change is still rejected. Each such property is listed under "Tests changed: review" in the PR body and in report.json (file, line, property and the value the agent chose). Name a test that asserts a dependency default the upgrade changed (Sentry'sdataCollectionandattachStacktrace) under "Decisions for you", instead of leaving it to fail unexplained. -
#251
773dbbeThanks @lucasbraum! - Calibrate the SDK pre-run cost estimate from recorded migrations, accounting for shared rule knowledge instead of charging a full session allowance per site. Keep the configured spending limit and per-call budget enforcement unchanged. -
#258
3a4898fThanks @lucasbraum! - Discover independent nested projects when fixing a dependency absent from the root project. Run installation, migration and verification in the selected project's directory, preserving its lockfile and package manager. When several projects declare the dependency, name their manifests and require an explicit directory. -
#257
7b9ed7fThanks @lucasbraum! - Run pinned npm through Corepack when local npm differs. When the pin is unavailable, allow local npm with a compatible v3 lockfile, record the fallback in the report, and reject frozen installs that rewrite the lockfile.
v0.17.2
Patch Changes
- #250
ec35174Thanks @lucasbraum! - Report matching candidate packs that the Action did not use, with their name and status, without changing which packs run.
v0.17.1
Patch Changes
-
#245
2945857Thanks @lucasbraum! -checkfinds the migration pack of any member of an upgrade group: the member a pack covers now leads the group, so react 18 → 19 named together with react-dom (as the Uptide Action names every used dependency) is analyzed by the react pack and reported asreact, verified, instead ofreact-domwith no pack. -
#249
5078510Thanks @lucasbraum! - setup PRs pin Action v0.17.0
v0.17.0
Minor Changes
- #244
c9d839dThanks @lucasbraum! - Behavior records: a silent change with a cited source and a usage site the type checker resolved (ADR 0017). The first, for zod 3 → 4: a zod object passed to the MCP SDK as a tool'sinputSchemalosesadditionalProperties: falsein the schema clients see.checklists each site,fixtells the agent the quotes and the edit (.strict()) and puts the record under "Decisions for you", saying it also makes the server reject unknown keys. The agent also gets the lines of the target's own CHANGELOG.md that name what the repository uses and say a behavior changed, read from the copy already installed.pack testscores "silent changes caught" against a newsilentground truth and fails on any false positive there.
Patch Changes
- #243
f1c4a89Thanks @lucasbraum! - A Stripe PR no longer says "none affect your code". It says how many API changes matched the code by field name and how many breaking changes can't be matched that way, and lists those breaking changes in the open, a new default first. The bundled Stripe changelog is regenerated, and "parameter" no longer tags an entry as a meter change.
v0.16.1
Patch Changes
- #240
4accd66Thanks @lucasbraum! - setup PRs pin Action v0.16.0
v0.16.0
Minor Changes
-
#237
717468aThanks @lucasbraum! -npx uptide fixgets the Agent SDK executor. The package stays as small as before:@anthropic-ai/claude-agent-sdkis not installed with Uptide. An SDK installed next to Uptide is used as it is; otherwise the firstfixthat needs it installs the version Uptide is tested with into Uptide's cache (~/.cache/uptide/agent-sdk/<version>), says so in one line with its size, and later runs reuse it. When that install fails (offline, a proxy) or the SDK cannot run,fixruns the patch executor and says so on the first line of its output and at the top of the PR body, with the reason and how to get the SDK executor.report.jsonrecordsllm.executorand, after a fallback, the reason inllm.sdkMissing. The privacy notice names the SDK only when the SDK will run, and the LLM line names the executor.--agent sdkwithout a usable SDK stops before any work instead of failing mid-run. -
#239
e1e8c40Thanks @lucasbraum! -uptide fixruns only with the Claude Agent SDK; if it can't, it doesn't run. Before the first download, an interactive terminal asks once:uptide fix needs the Claude Agent SDK (about 300 MB, downloaded once to <cache>). Download now? [Y/n](default yes). With--yes, or without a terminal, it downloads and says so in one line. Once cached, it never asks again. Answeringn, an SDK that can't be fetched or loaded (offline, a proxy, no binary for the platform), a missingANTHROPIC_API_KEY, another provider, orllm.enabled: false/executor: patchinuptide.ymlall stopfixwith exit 2 before any clone or spending. The run prints one message with the reason and the fix, and--jsonreturns it aserror.code: "SDK_UNAVAILABLE". There is no fallback to the patch executor anywhere: the Uptide Action stops the run with the same message.--no-llm,--agentand--providerare gone from help and docs.llm.sdkMissingis gone fromreport.json, anduptide initno longer writesexecutor.
Patch Changes
-
#236
9b35b9dThanks @lucasbraum! - A repository build that fails on the final head is no longer published as a ready PR. When it fails,fixbuilds the parent commit in the same clone to compare. If the parent fails too, the build line says "already failing before this upgrade" and nothing is blocked. If the parent passes, the upgrade broke the build: verification fails, and the PR opens only as a draft with "Build broken by this upgrade" at the top. If the parent can't be checked out, installed or built, verification still fails and the PR says "Build fails on this upgrade; the parent build could not be checked" with the reason, never that the parent passed. The GitHub Action opens these runs as draft PRs, the same way it opens agent-led runs. The head build also skips workspaces already built on that head, so a workspace whose output a consumer reads is no longer built twice. -
#233
1ad8071Thanks @lucasbraum! - The PR description's build check now gives the build's actual result: passed, failed with its first error, or not run and why. When a migration pack doesn't require a build,fixstill runs the repository's build once on the final head, anduptide verifyruns it again, and reports what happened. "Not required by the pack" now appears next to that result instead of replacing it. Before, the line read "build not required" even when the repository's build failed. A build the pack doesn't require still doesn't block verification or publishing. -
#238
6f07d3fThanks @lucasbraum! - An SDK session's edits are no longer thrown away because of one flaky test. Before the gate rejects a session on test failures, it runs the failing test files once more, alone, with their runner and the same isolation as the full run. A file that passes then is recorded as flaky (llm.tasks[].flakyinreport.json, and a line in the PR body's review list) and the edits stay. A file that fails twice still rejects them, and a failure that names no test file (a build, a timeout) is never rerun. Final verification keeps its full gate: it runs the flaky files again, and if one fails there, verification fails and the PR body says so.fixalso stops starting verification feedback sessions when what is left of--max-costis below the mean cost of the run's sessions so far, so it no longer starts a session it can't afford; the PR's feedback line says when this happened. -
#234
066deabThanks @lucasbraum! -fixon npm no longer loses a package the repo imports without declaring it when the ERESOLVE retry re-resolves the lockfile. If the retry drops such a package from the top ofnode_modules, it runs again keeping that package and the locked packages that require it at their old versions; if that conflicts, the first retry stands. Either way the summary and the PR body name the package under "Imported but not declared" and suggest adding it to package.json.fixnever adds it for you.
v0.15.1
Patch Changes
-
#220
cf86d65Thanks @lucasbraum! - With an assisting agent, a root pin Uptide cannot update safely (a nested override such asoverrides > pkg > peerDependencies > react) no longer stopsfixwith exit 2: the run continues as an agent-led draft that leaves the pin as written and names it, with its exact path and value, at the top of the PR body. The agent-led peer reason now names each blocker's first release that accepts the target, or says none does. An agent-led draft must pass the repository's clean install (npm cior the manager's frozen install) before delivery; if it does not, the PR says so at the top. Without an agent, with--no-llm, or on a safety refusal,fixstill exits 2. -
#232
e4a2885Thanks @lucasbraum! -uptide fixspends less wall time on test runs and dependency copies:- The agent's own
run_testscheck runs only its runner's related tests when thetestscript builds first and then runs a script that is just the runner (pnpm run build && pnpm run test:unit). The gate after the agent's edits and the final verification run exactly what they ran before. - The upgrade's install moves the installed
node_modulesout of its temporary worktree instead of copying it. - Each phase of the fix report lists the repository's commands it ran (installs, generators, builds, type-checks, tests, lint, format) with their count and summed wall time. An agent-led run's clean install has its own phase.
- The agent's own
-
#223
2dc2162Thanks @lucasbraum! -fixno longer stops with "baseline tests modified the working tree" when the test run only writes new untracked files, such as a junittest-report.xmlthat is not gitignored. Those files are recorded as test artifacts (testArtifactsin the report), kept out of every commit, the agent's diff and the pending-changes check, and removed before each later test run,uptide verifyincluded. A change to a tracked file during baseline tests still refuses the run. -
#215
abddcb3Thanks @lucasbraum! -checkno longer lists possible impact (type changes nothing confirmed as breaking) on its first screen: each package says it in one line,+N possible impact in M files, not counted as breaking, and--detailsand--jsonstill have every site. A package whose types were partly verified no longer repeats its coverage line in the heading, and a monorepo's unbuilt workspace chains are one count on that line. -
#213
2de3a18Thanks @lucasbraum! - A companion pack that moves with the lead's fix (react beside next) now gets its own scan context and inventory, and the PR body carries a section with its review notes. -
#212
733cfbeThanks @lucasbraum! -pack test --writerecords how many breaking sites a finding landed on at any severity and as breaking, out of all breaking sites it scored, and the pack tables show both ("Found, any severity", "Found as breaking") in place of the single recall column. Packs recorded before it show—. -
#224
09f68dfThanks @lucasbraum! -fixon npm no longer stops when the lock-only install hits ERESOLVE from the old lockfile. It retries without the lockfile entries of the moved packages, their companions and the packages whose peers they satisfy, and only then with the whole lockfile re-resolved; the report says which step worked, and the lockfile check reports the churn as usual. It never uses--legacy-peer-depsor--force. When every step fails,fixends blocked, naming the conflicting packages from npm's ERESOLVE report.fix --jsonnow prints JSON on every exit, a failure included; when the run already has its report (a PR body over GitHub's size limit), that report comes with the error. -
#221
ff8de8eThanks @lucasbraum! -fixno longer rejects an agent patch for test files the parent commit already failed, whichever test scope ran them: when the test script builds first and the build failed on the error being fixed, the start had no test results to compare with, so a correct patch was reverted every round. The patch's tests also run with the pack's follow-ups in place (a test asserting the old Stripe API version), whichfixstill applies and reports after the agent. When a PR body cannot fit, the stored report.json the error points to is now written first.checkandfixnow also analyze files that reach a package's wrapper through a barrel (import { getStripeClient } from '../stripe'withexport * from './client'). Edited files are formatted with oxfmt and dprint as well as biome and prettier, from the workspace that holds them, with its own configuration, else the root's. The stripe pack addsrequest-options: request options passed in the params slot (subscriptions.cancel(id, { idempotencyKey })), which SDK 22 rejects, move to the third argument. It runs assisted until a ground-truth repository exercises it. -
#226
448c3cbThanks @lucasbraum! -uptide fixjudges consumed workspace builds on the final head, not on the tree right after the bump. A build that failed after the bump and passes once the edits land no longer starts a feedback round, adds an "Agent-led draft" reason or shows "Build failed" in the PR body. The builds run again only when the tree changed since their last result, and not at all when the verification build already built those workspaces. The fix report'sbuildRunsgives the number of builds the run executed and their wall time. -
#218
13e343bThanks @lucasbraum! -checkfolds a compile error into the breaking site it comes from when the compiler traces its value there (anerrors.map(e => e.message)under aresult.error.errorsthat zod 4 no longer types, and the narrowing that depended on it). The rule's line shows+N downstream errors,--detailslists them under their site, and--jsoncarries them as that finding'sdownstream. They are no longer separate breaking sites.fixstill verifies against every error. -
#214
195ae10Thanks @lucasbraum! - A rewrite rule below 80% precision over at least 5 scored ground-truth sites now runs as assisted infix(react-routerdom-imports); smaller samples (nextmiddleware-proxy) stay mechanical and are flagged in the compatibility table. Pack status is unchanged. -
#218
13e343bThanks @lucasbraum! - pack test runs a ground-truth repository's code generators (prisma generate, local graphql-codegen) after its install, as fix does. It fetches the Prisma engines the locked version needs itself, so generators stay off the network. A repository whose generator still fails is incomplete and fails the pack, unless its ground truth declareswithoutGenerated -
#227
ae175a9Thanks @lucasbraum! - A migration whose evidence is larger than GitHub's PR description limit no longer stopsfixwith "Required migration evidence exceeds the PR body budget" and loses the run. Long required lists get a compact form when they do not fit. Lockfile churn shows counts per kind of change and the first packages. Manual sites are grouped by rule, with counts and the first locations. Remaining type errors show the first entries. Every full list stays in report.json and, in the Uptide Action, in the job summary, which the description links to. If even the compact form does not fit, the description is a short summary that says so at the top: the verdict, the checks, the counts and where the full report is. The branch and report.json are always kept.An agent's decisions under "Decisions for you" name the files the agent changed, five at most, and count the rest, instead of every file in the task's scope. A verification-feedback task scoped to the whole repository made each of its decisions a list of hundreds of files.
-
#219 [
12dc612](https://github.com/...