Repository navigation
feat(packs): AI SDK (ai) 6 → 7, the first pack built with pack new and pack test - #39
Merged
Merged
Conversation
…implement it Pack (meta with sources and maintainer, rules that claim check's findings and rewrite one site, behavior notes with how they are reported, agent instructions) on top of MigrationPack. check, fix, list and verify take their packs from a generated registry, verified ones only. Zod's rules carry their own rewrite; stripe declares the rules its evidence classifies. Outputs on the storefront fixture and the corpus unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
pack new scaffolds a pack that lints and passes its tests as written and registers it. pack test runs its fixtures, then check with the pack on each ground-truth repository (fetched shallow at the pinned commit, installed with scripts off, cached), and prints precision and recall per rule, overall and for breaking findings, with every false positive and false negative. --json for CI. pnpm uptide runs the CLI from source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
… Packs workflow docs/packs.md with zod as the reference; CONTRIBUTING.md "Write a pack"; a pack pull request template and the pack request issue form; ADR 0015; packs/queue.json from public npm data (pnpm packs:queue); a Packs workflow that runs pack test for every pack with the ground-truth cache. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
pnpm packs:truth lists, for one public repository, the diagnostics its own TypeScript reports with the target linked in and not without it (errors and deprecations), and the lines its upgrade commit changed. Ground truth can name a project directory inside the repository; an install whose lockfile was already out of sync falls back to an unfrozen install, scripts still off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
zod: AwesomeIntune, PATH and band-sdk-typescript at the commit before their zod 4 upgrade; stripe: unkey and saas-starter before their stripe-node majors; both also scored on the storefront fixture. No false positive among breaking findings (zod 57 sites, recall 76%; stripe 18 sites, recall 90%). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
- pack new rendered the registry's imports in an order biome rejects when the new directory sorts before contract.ts; sorted by path now. - A rule can match on the compiler's message (a compiler-only finding's path is only its code), and the plan files a contract pack's sites under the rule that claims them, rewrite or not (ruleOf). - Fixture markers take message:"..."; pack test --update-fixtures writes after.ts from the rules; --fixtures-only says ground truth was skipped instead of "no repository yet". - Breaking recall counts a miss by its rule's severity. - A site found by detect carries the name the code writes. - Ground-truth repositories can install with bun (and the Packs job sets it up). - packs:truth links the target with its own dependencies at the versions it declares, and --also links what the upgrade moved with it; runs of changed lines split where the change does. - fix took its list of packs from two hard-coded lists (CLI and isolate); both ask the registry now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
Five more sites in PATH, all changes its upgrade made (a cast to a removed type, _def.typeName reads zod 4 no longer has). Still no false positive; recall recorded again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
…a/morphic Built with pack new and pack test only. Rules rewrite the renamed options (system, onFinish, onStepFinish, experimental_telemetry), stepCountIs, fullStream, totalUsage and the removed experimental_* options; telemetry metadata, tool context and the stream result helpers go to the agent; what the compiler cannot see is listed for review. Ground truth from each repository's own upgrade commit and compiler: no false positive, 47 of 61 sites (chatbot 27 of 27). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
…h it `fix ai` bumped ai alone: ai and the @ai-sdk/* packages pin the same @ai-sdk/provider, so ai 7 next to @ai-sdk/react 3 was an install no real upgrade has, and verification on vercel/chatbot failed with ~45 errors that came from the install, not the code. check now finds the group `list` already draws (family, peer link, shared pin) among the installed dependencies and moves each member to the version that agrees with the target: the version the target pins, else the installed one when it already accepts the target, else its newest release that pins or accepts it, else one whose exact pins agree. The report carries `companions` and `companionConflicts`; check's plan, the fix summary (`With`) and the PR description say which and why. fix bumps and installs them in one step and one commit; the lock guard allows changes inside any of their subtrees only. npm and pnpm resolve the exact version first, so `^4.0.1` keeps the 4.0.1 ai pins. A member with no release that agrees stops fix before it writes anything. Ground-truth entries take `with`, the packages the repository's own upgrade moved; pack test prints what check moves and fails, and the pack is not verified, when check would leave one behind. The ai pack's ground truth records them for vercel/chatbot and miurla/morphic, and its "companion packages" review note is gone. On a copy of vercel/chatbot, `fix ai --target 7.0.9 --no-llm --include-deprecated` now passes verification (1 error after the bump -> 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
main is this branch's base (#38, squash-merged) plus #40: the result keeps this branch's tree and applies #40's changes on top. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi Signed-off-by: Claude <noreply@anthropic.com>
Collaborator
Author
|
Retargeted to Final All three are verified with no false positive. zod's PATH entry has 51 expected sites here, against 46 in #38: this PR refines the one-site-per-change rule, so zod's ground truth changed and its Generated by Claude Code |
Merged
lucasbraum
pushed a commit
that referenced
this pull request
Oct 8, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## uptide@0.5.0 ### Minor Changes - [#39](#39) [`b9f9974`](b9f9974) Thanks [@lucasbraum](https://github.com/lucasbraum)! - A verified migration pack for the AI SDK (`ai`) 6 → 7: the renamed options (`system` → `instructions`, `onFinish` → `onEnd`, `onStepFinish` → `onStepEnd`, `experimental_telemetry` → `telemetry`), `stepCountIs` → `isStepCount`, `fullStream` → `stream`, `totalUsage` → `usage` and the removed `experimental_*` options are rewritten by rule; telemetry `metadata`, tool `context` and the stream result helpers go to the agent with the guide; what the compiler cannot see (telemetry registration, results that now cover every step, rejected system messages) is listed for review. Scored against vercel/chatbot and miurla/morphic at the commit before their own upgrade: no false positive. `uptide pack test` gains `--update-fixtures`, fixture markers take the compiler's `message`, and ground-truth repositories can use bun. - [#39](#39) [`b9f9974`](b9f9974) Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` and `fix` upgrade a package together with the packages that must move with it, using the groups `list` already draws (family, peer link, shared pin), each at the version that agrees with the target. `fix ai` also bumps `@ai-sdk/react`, `@ai-sdk/provider` and the installed `@ai-sdk/*` providers in one install and one commit; check's plan, the fix summary and the PR description say which and why, and `fix` stops before changing anything when a member has no release that agrees. npm and pnpm installs resolve the exact version first, so a `^` range keeps the version the target pins. Ground-truth entries take `with`, the packages the real upgrade moved, and `pack test` fails when check would leave one behind. - [#38](#38) [`adaf8f9`](adaf8f9) Thanks [@lucasbraum](https://github.com/lucasbraum)! - Migration packs are a public, testable contract (docs/packs.md). `uptide pack new` scaffolds a pack (an example rule, a fixture pair, a test, empty ground truth) and registers it; `uptide pack test` scores packs against their fixtures and against public repositories at the commit before their upgrade, with precision and recall per rule, every false positive and false negative, and `--json` for CI. A pack is labeled verified only with ground truth from at least two public repositories and no false positive among its breaking findings; otherwise it ships as a candidate and `check`, `list` and `fix` treat the dependency as generic. ### Patch Changes - [#44](#44) [`b4cc21f`](b4cc21f) Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` no longer dies with "Manipulation error: A syntax error was inserted." on packages whose type aliases give their type parameters defaults (`type-fest` 4 → 5, `i18next` 23 → 26): the alias body is read after the parameter list, not at the first default's ` = `, so these aliases are compared by the checker instead of breaking the comparison program. - [#40](#40) [`3e3a5fa`](3e3a5fa) Thanks [@lucasbraum](https://github.com/lucasbraum)! - `fix` verifies with the repository's own TypeScript (its `node_modules/typescript`, or an ancestor's) or the bundled one, and never with a TypeScript that `NODE_PATH` or Node's global folders happen to provide. A machine with a global TypeScript 6 made verification report TS5107 deprecations the repository never sees. - [#37](#37) [`3e7f744`](3e7f744) Thanks [@lucasbraum](https://github.com/lucasbraum)! - Gemini is labelled experimental: in `fix --help`, in the `LLM:` line `fix` prints, and in the docs. Its evaluation runs on the storefront fixture failed on service errors (HTTP 503/429), so its migration quality is not established yet. Co-authored-by: uptide-release[bot] <338861287+uptide-release[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pack
ai>=6 <7→>=7 <8(most recent breaking major: 7.0.0, 2026-06-25). Scaffolded withuptide pack new ai --from ">=6 <7" --to ">=7 <8"and scored only withuptide pack test ai.Sources
Rules and behavior notes
detectthrough imports fromai, so another library'ssystem:or@ai-sdk/react'sonFinishis never touched):instructions(system),on-end(onFinishon generateText/streamText/ToolLoopAgent/UI message streams),on-step-end,telemetry(experimental_telemetry),is-step-count(stepCountIs, import and references; an alias keeps its local name).full-stream(deprecatedfullStream→stream; a destructured local is renamed only where no otherstreamis declared),total-usage, andremoved-experimental-option(breaking:experimental_activeTools/prepareStep/output, matched on the compiler's message).ui-message-stream(result helpers become standalone functions),telemetry-metadata(breaking:metadata→runtimeContext+includeRuntimeContext),tool-context(breaking:contextin tool execute options).registerTelemetry), results covering every step, system messages rejected,prepareStepcarrying forward, redacted UI stream errors, ESM-only/Node 22.fix aiupgrades the whole groupaiand the@ai-sdk/*packages pin the same@ai-sdk/provider, so bumpingaialone leaves an install no real upgrade has.checknow takes the grouplistalready draws (family, peer link, shared pin) among the installed dependencies and moves each member to the version that agrees with the target (check/companions.ts): the version the target pins, else the installed one when it already accepts the target, else its newest release that pins or accepts it, else one whose exact pins agree.fixbumps and installs them in one step and one commit (the lock guard allows changes inside their subtrees only), and stops before writing anything when a member has no release that agrees. check's plan (↑ upgrades with …), the fix summary (With) and the PR description name each companion and why. npm and pnpm resolve the exact version first, so^4.0.1keeps the 4.0.1 that ai pins rather than a second copy at 4.0.24 (found on the end-to-end run below).Ground-truth entries take
with: the packages the repository's own upgrade moved (from its package.json).pack testprints what check moves and fails, and the pack is not verified, when check would leave one behind. For both repositories check moves exactly the packages the maintainers moved.Tests:
check/companions.test.ts(the case where onlyaiwould move today:ai6 with@ai-sdk/react,@ai-sdk/provider,@ai-sdk/openaiinstalled → all three move,zoddoesn't; a member with no agreeing release is a conflict; a member that already accepts the target stays),fix/generic.test.ts(one install withalso, both manifests bumped, commit and PR body; a conflict changes nothing),text-lock.test.ts(several targets: the group may move,aialone may not drag@ai-sdk/react, nothing else may move),format-check.test.ts(the plan line).Ground-truth repositories
Expected findings were drafted with
pnpm packs:truth(the repo's own TypeScript with ai and the companions its upgrade moved, versions from its lockfile; plus the upgrade diff) and read by hand. Each entry'swithlists the packages its upgrade moved with ai. Excluded: morphic'sexperimental_throttle(@ai-sdk/react), comments, and pure insertions.uptide pack testoutputThe output for zod, stripe and ai, run on this branch after it was merged with
main, is in this comment. ai:zod and stripe still pass and stay verified, with nothing moving alongside them (band-sdk's
@modelcontextprotocol/sdkalready accepts zod 4, so it stays). zod's PATH entry gained 5 sites from the refined one-site-per-change rule.Extra end-to-end check:
uptide fix ai --target 7.0.9 --no-llm --include-deprecatedon a copy of vercel/chatbot applied 26 sites by rule. The rewritten files match the maintainers' own upgrade byte for byte (e.g.artifacts/code/server.ts→ blobbeb7f35, the same blob as their commit). Before the group upgrade, verification failed with 46 → 45 errors. It now passes:Upgrade commit:
chore: upgrade ai to 7.0.9 with @ai-sdk/provider 4.0.1, @ai-sdk/react 4.0.10, with one@ai-sdk/provider(4.0.1) in the lockfile. The PR description opens with:Where the tooling or docs got in the way, and what this PR does about it
messageto PackRule.rewritenever shows under its id in check's plan (sites fall back to the compiler code), so pack test scores themgeneric. Added MigrationPack.ruleOf, implemented by definePack, used by the plan before the zod/stripe-specific classification.messagecould not be fixture-tested). Addedmessage:"..."to markers.pack test --update-fixtures(writes after.ts from the rules, reviewed in the diff like a snapshot update).streamcollision check reads declarations from the AST.aidoes), so the scaffold failed pnpm lint; the e2e test used toy-lib, which sorts after. The renderer now sorts every import by path, and the test scaffolds a name that sorts first.ai:instructions,ai:is-step-count) instead of what the code says. A detected site can carry the name as written (system,stepCountIs), and check shows that.fix ai --no-llmrefused with "ai has no migration pack" although the registry has it verified. fix now asks the registry (activePacks); its --only help names the verified packs from it. The no-argument overview still lists zod and stripe only (unchanged).(core fix/isolate.ts had the same list:
['zod', 'stripe'].includes(only).)aialone: release groups are one scope (@aws-sdk/*), soai+@ai-sdk/*never formed one, and verification on vercel/chatbot failed with ~45 errors from the install, not the code. Fixed here (see "fix aiupgrades the whole group"); the pack's "companion packages" review note is gone.^range bumped to a companion's agreeing version (^4.0.1) let pnpm resolve the newest in range (4.0.24), a second provider copy. npm already resolved exact-then-range; pnpm now does too.Checklist
meta.sourceskeep)pnpm uptide pack testpasses for ai, stripe and zod on this branch merged withmain;verification.jsonwritten with--writepnpm lint && pnpm typecheck && pnpm testpass (core 874 passed, 15 skipped; CLI 344/344)fix aiupgrades the group; ground truth records what each real upgrade moved (with).changeset/ai-pack.md,.changeset/companion-upgrades.md, minor)🤖 Generated with Claude Code
https://claude.ai/code/session_01B2T8GmEVnZwfNrugajEMqi