framework-upgrade-risk-review
Assess breaking-change and regression risk for a same-framework major-version upgrade (React, Next.js, Angular, Vue, or core build tooling), grounding every claimed breaking change in the framework's official release notes/migration guide, and separate upgrade-blocking issues fro
Install
npx skills add https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/tree/master/skills/frontend/framework-upgrade-risk-review
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install vincentchuwaichow-vanguard-frontier-agentic@llmmart
git clone https://github.com/VincentChuWaiChow/vanguard-frontier-agentic.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole vincentchuwaichow/vanguard-frontier-agentic collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Framework Upgrade Risk Review
Purpose
Framework major-version upgrades fail in production not because the upgrade was a bad idea, but because the breaking-change surface was assessed from stale memory instead of the actual release notes for the actual installed version. This skill exists to ground every claimed breaking change in current official docs and separate what will actually break the build/runtime from what is merely deprecated-but-still-working — without stuffing every framework's entire changelog history into every response.
When to use
Use this skill when the user asks to:
- assess risk before upgrading a framework or core build tool to a new major version,
- explain what specifically will break when moving from version X to version Y,
- decide whether a security-driven forced upgrade (CVE fix in a new major version) outweighs the migration effort,
- triage a failing build/test suite after an upgrade attempt to determine which failures are upgrade-caused vs. pre-existing.
Lean operating rules
- Always resolve the exact currently-installed version from the lockfile (
package-lock.json,pnpm-lock.yaml,yarn.lock) before assessing risk; "upgrading React" without knowing the current pinned version produces meaningless risk output. - Query Context7/official release notes for the target version's actual breaking-change list before writing any risk assessment — never assemble this from training-data memory alone, since breaking-change lists change per release and are exactly the kind of fact that goes stale.
- Separate hard breaking changes (code will not compile/run) from soft deprecations (still works, warns, scheduled for future removal) — conflating them causes both false alarm and false confidence.
- Treat a breaking change tied to a security fix as a forced-upgrade driver that overrides normal cost/benefit sequencing; also flag if the current pinned version is already past its security-support window regardless of migration effort.
- Do not assume a codemod exists for a given breaking change unless it is named in the official migration guide; do not invent codemod commands, CLI flags, or config keys.
- Treat multi-major-version jumps (e.g. React 16 → 19, Next.js 12 → 15) as requiring sequential per-major risk assessment, not a single diffed comparison — intermediate majors carry their own breaking changes that compound.
- Load
references/breaking-change-triage.mdonly when classifying specific breaking changes as blocking vs. non-blocking and mapping them to affected code paths. - Load
references/dependency-compatibility-matrix.mdonly when third-party dependencies (not the core framework itself) are the upgrade blocker.
Context7 Documentation Protocol
Every framework-specific breaking-change claim, codemod name, removed API, or "recommended migration path" statement in a response must be traceable to one of:
- Context7-verified — resolved via
mcp__Context7__resolve-library-idthen confirmed withmcp__Context7__query-docsagainst the specific library (e.g./reactjs/react.dev,/vercel/next.js) in this session or a prior verification you can cite by source URL. - Official docs (direct citation) — a specific docs/changelog URL, used when Context7 has no coverage for that library/version.
- Inference — explicitly labeled as such and flagged for human verification against the installed toolchain; never presented as a verified breaking change.
Do not invent codemod names, CLI flags, or config keys. If Context7 and official docs both lack coverage for a specific claim (e.g. an exact flag for a niche bundler plugin), say so and mark it inference — verify against installed tooling rather than guessing. Re-verify before citing if the last check is not from the current session — breaking-change lists and codemod tooling are actively evolving (React ships incremental React Compiler / Server Components guidance; Next.js has shipped multiple async-API and caching-default changes across recent majors).
Confirmed in this skill's authoring session (re-verify if stale):
- React 19 requires migrating
ReactDOM.rendertocreateRoot/hydrateRoot, removespropTypes/defaultPropssupport on function components (replace with TypeScript types/ES6 default parameters), and removes string refs in favor of ref callbacks. React shipsnpx codemod@latest react/19/migration-recipeas a combined codemod, plus a targetednpx codemod@latest react/19/replace-string-ref. Source:reactjs/react.devdocs (blog/2024/04/25/react-19-upgrade-guide.md). - Next.js 15 makes previously synchronous dynamic APIs (
cookies(),headers(),draftMode(), andparams/searchParamsin pages, layouts, andgenerateMetadata/generateViewport) asynchronous — all call sites mustawaitthem or useReact.use()in Client Components. Next.js shipsnpx @next/codemod@latest next-async-request-api .to automate this migration. Source:vercel/next.jsdocs (01-app/02-guides/upgrading/version-15.mdx,01-app/02-guides/upgrading/codemods.mdx). - Next.js 15 also changes the default caching behavior:
fetchrequests are no longer cached by default and require explicit{ cache: 'force-cache' }to opt back into the previous caching behavior. This is a runtime/behavioral breaking change, not a compile-time one, so it will not surface as a build failure — it surfaces as stale-vs-fresh data regressions. Source:vercel/next.jsdocs (01-app/02-guides/upgrading/version-15.mdx).
References
Load these only when needed:
- Breaking-change triage — use to classify each breaking change from the official migration guide as build-blocking, runtime-blocking, or cosmetic-deprecation, and to map each to affected code paths via repo search.
- Dependency compatibility matrix — use when the risk driver is a third-party library's peer-dependency constraint rather than the core framework's own breaking changes.
Response minimum
Return, at minimum:
- the exact current version and target version being assessed (sourced from the lockfile, not assumed),
- the breaking-change list sourced from official release notes/Context7 (with citation), split into blocking vs. cosmetic,
- any security-advisory-driven upgrade urgency or security-support-window expiration,
- an estimated blast radius (files/modules touching each blocking change, found via repo search),
- evidence level for every claimed breaking change (Context7-verified, official-docs-cited, or inference — inference must be flagged for human verification against the installed toolchain).
Files (vanguard-frontier-agentic)
-
references
-
breaking-change-triage.md 5.3 KB
# Breaking-Change Triage Use this reference when classifying specific breaking changes from an official migration guide into blocking vs. cosmetic buckets, and when mapping each change to the code paths it actually touches. > Version note: breaking-change lists are per-release and change across minor/patch versions within a major too (e.g. deprecation warnings added in a `.1` release ahead of removal in the next major). Re-pull the current official migration guide for the exact source and target versions before triaging — do not reuse a prior session's list without re-verifying it still matches. ## What people get wrong The naive assumption is: > "The migration guide lists N breaking changes, so there are N things to fix, roughly equal effort each." Wrong. Migration guides mix at least three fundamentally different categories of severity, and treating them as equivalent produces either false alarm (blocking a low-risk upgrade over a warning) or false confidence (shipping an upgrade that silently changes runtime behavior). ## The three-tier classification ### 1. Build-blocking The code will not compile or the build will fail outright. These are the safest category paradoxically — the build tells you immediately, and CI catches them before merge. Examples grounded in official docs: - React 19 removing `propTypes`/`defaultProps` on function components — this is a type/lint-level break in TypeScript codebases, not always a hard compile failure in plain JS, so verify whether the project uses TypeScript strict mode or just runtime PropTypes checks before calling it "build-blocking" vs. "silently degraded." - Any removed export, removed CLI flag, or removed config key — grep the repo for the literal symbol/flag name to confirm actual usage before flagging it as in-scope; do not flag "this symbol was removed" as risk if the repo never imports it. ### 2. Runtime-blocking (behavioral break, not compile break) The code compiles and builds fine, but behaves differently or throws at runtime. These are more dangerous than build-blocking changes because CI without adequate integration/e2e coverage will not catch them before production. Grounded example: Next.js 15 making `cookies()`, `headers()`, `draftMode()`, and `params`/`searchParams` asynchronous. Old synchronous call sites do not necessarily fail to build in JS (they may still "work" until the returned Promise is used incorrectly) — they fail or misbehave at runtime, and the failure mode may only surface on paths exercised by real traffic, not by every test. Grounded example: Next.js 15 changing `fetch` to be uncached by default. This produces no build error and no runtime crash — it produces a silent regression in data freshness or, more dangerously, in cache-hit-dependent performance/cost assumptions. This class of change is the one triage must not under-weight, because there is no error to signal it happened. For every runtime-blocking change, identify: - the specific API/behavior that changed (cite the migration guide section), - whether an automated codemod exists and is officially named for it (do not assume — check `references/dependency-compatibility-matrix.md`-adjacent codemod listings in the framework's own upgrade docs), - what test coverage (if any) would actually exercise the changed code path — if none, say so explicitly as a residual risk, not a solved problem. ### 3. Cosmetic deprecation The code still works exactly as before; the framework emits a warning (console warning, lint warning, or doc note) that the API is scheduled for removal in a *future* major, not this one. Do not present these as this-upgrade risk. List them separately as "deprecation debt to schedule before the *next* major," since conflating them with real blockers dilutes attention from what actually needs fixing before merge. ## Mapping to blast radius For every build-blocking and runtime-blocking item (never cosmetic-only items, to keep the list actionable): 1. Identify the literal API/symbol/config key changed. 2. Search the repo (`Grep`) for actual usage of that symbol — imports, JSX usage, config keys, CLI invocations in `package.json` scripts. 3. Count distinct files/modules touched; do not estimate — enumerate. 4. Flag any usage inside test fixtures or mocks separately from production source, since test-only usage changes the risk profile (breaks CI, not production). 5. If the symbol is re-exported or wrapped by an internal abstraction layer, note that fixing the wrapper once may resolve many call sites — do not multiply file count by naive per-callsite fix cost. ## When to push back Push back if the user asks you to://"just estimate the risk without checking the actual official migration guide for this version" — a risk assessment built from memory of a different major version (or a different framework entirely) is not a risk assessment, it is a guess wearing a risk assessment's clothes. Push back if the user wants to skip the blast-radius search step because "it's probably fine" — "probably fine" is exactly the failure mode this skill exists to replace with an enumerated count. Push back if the user wants to bundle a same-framework major upgrade together with unrelated dependency upgrades in one PR — that makes the blast radius of a failure ambiguous (which upgrade caused the regression?) and should be flagged as a review/rollback risk, not silently accepted. -
dependency-compatibility-matrix.md 4.6 KB
# Dependency Compatibility Matrix Use this reference when the actual upgrade blocker is a third-party dependency's peer-dependency constraint, not a breaking change in the core framework itself. ## What people get wrong The naive assumption is: > "The framework's own migration guide says the upgrade is straightforward, so the upgrade is straightforward." Wrong. The framework's own breaking-change list only covers the framework. It says nothing about whether the state-management library, UI component library, testing library, or build plugin the project actually depends on has published a compatible release yet. A framework-major upgrade is frequently blocked not by the framework's own breaking changes but by an ecosystem library that has not shipped peer-dependency support for the new major, sometimes for months after the framework's release. ## The actual compatibility surface For a same-framework major upgrade, the dependencies most likely to gate the upgrade are: - **UI component libraries** built directly against the framework's internals (not just its public API) — these are the most common blockers because internal API changes (e.g. React's internal fiber/reconciler changes, Angular's internal change-detection changes) can break a component library even when the library's *usage* of the public API looks unchanged. - **State-management libraries** with framework-version-pinned peer dependencies. - **Testing-library integrations** (React Testing Library, Angular TestBed harnesses, Vue Test Utils) — these often require a matching major version to support new rendering/hydration internals, and a stale version can produce misleading green tests that do not reflect real runtime behavior. - **Build-tool plugins/loaders** that wrap the framework's compiler (e.g. a bundler plugin implementing framework-specific fast-refresh or SSR transforms) — these must track framework-internal changes closely and are a common source of "works with `next dev` but breaks under the plugin" issues. - **Meta-framework version coupling** — e.g. Next.js major versions are coupled to a specific React major/minor floor; do not assess a Next.js upgrade's React compatibility from memory, check the specific Next.js major's stated React peer-dependency range in its own official docs for that release. ## Procedure 1. Enumerate the project's direct dependencies with the framework's own package as a peer dependency (read `package.json` `peerDependencies` fields of the top N most framework-coupled packages actually installed, not a generic list). 2. For each, check whether a release compatible with the target framework major has shipped. Prefer checking the dependency's own official changelog/release notes over inferring from its semver range, since a library may have shipped a compatible peer-dependency range before actually fixing all the runtime breakage that range implies is safe. 3. If a dependency has *not* shipped compatible support, this is a hard blocker independent of how clean the framework's own breaking-change list is — say so explicitly and do not let a clean framework migration guide imply a clean overall upgrade. 4. If a dependency requires a beta/RC release to get compatibility, flag that as an elevated-risk path (pinning to a pre-release for a production dependency) rather than presenting it as equivalent to a stable compatible release. 5. Distinguish "peer-dependency range technically allows the new major" from "the maintainer has stated they tested against the new major" — a permissive semver range is not evidence of compatibility, it is often just an unmaintained range that was never tightened. ## When to push back Push back if the user wants to force-install (`--legacy-peer-deps` / `--force`) past a peer-dependency conflict as the resolution rather than as a temporary unblock — that suppresses the signal that a real incompatibility may exist and should be logged as residual risk, not treated as "resolved." Push back if the user assumes a component library "probably still works" because it hasn't announced incompatibility — the absence of an announcement is not evidence of compatibility, especially for internal-API-coupled libraries; recommend an actual smoke test of the specific components in use. Push back if the plan is to upgrade the framework and defer checking ecosystem-dependency compatibility until after merge — for framework-internal-coupled dependencies (UI kits, test harnesses, build plugins) this ordering inverts the actual risk: the framework's own official migration guide is usually the well-tested, well-documented part, while third-party catch-up compatibility is the least-documented and most likely source of surprise regressions.
-
-
metadata.json 1.2 KB
{ "id": "framework-upgrade-risk-review", "name": "Framework Upgrade Risk Review", "type": "skill", "provider": "frontend", "harnesses": [ "claude-code", "cursor", "codex", "gemini", "kiro", "other" ], "summary": "Assesses the breaking-change and regression risk of a same-framework major-version upgrade (React, Angular, Vue, Next.js, build tooling) by grounding every claimed breaking change in the framework's official changelog/migration guide via Context7, and separates upgrade-blocking issues from cosmetic deprecation warnings.", "source_type": "original", "official_docs": [ "https://react.dev/blog", "https://nextjs.org/docs/app/guides/upgrading", "https://angular.dev/reference/releases", "https://vuejs.org/guide/introduction.html" ], "security_notes": "Prioritize any breaking change tied to a security advisory (e.g. a CVE fixed by the new major version) as a forced-upgrade driver, and flag if the current pinned version is past its security-support window regardless of migration effort. Never invent codemod names, CLI flags, or config keys.", "last_verified": "2026-07-02", "path": "skills/frontend/framework-upgrade-risk-review", "author": "github: VincentChuWaiChow", "version": "0.1.0" } -
SKILL.md 7.1 KB
--- name: framework-upgrade-risk-review description: Assess breaking-change and regression risk for a same-framework major-version upgrade (React, Next.js, Angular, Vue, or core build tooling), grounding every claimed breaking change in the framework's official release notes/migration guide, and separate upgrade-blocking issues from cosmetic deprecation noise. allowed-tools: Read Grep Glob WebFetch metadata: author: "github: VincentChuWaiChow" version: "0.1.0" updated: "2026-07-02" category: resilience --- # Framework Upgrade Risk Review ## Purpose Framework major-version upgrades fail in production not because the upgrade was a bad idea, but because the breaking-change surface was assessed from stale memory instead of the actual release notes for the actual installed version. This skill exists to ground every claimed breaking change in current official docs and separate what will actually break the build/runtime from what is merely deprecated-but-still-working — without stuffing every framework's entire changelog history into every response. ## When to use Use this skill when the user asks to: - assess risk before upgrading a framework or core build tool to a new major version, - explain what specifically will break when moving from version X to version Y, - decide whether a security-driven forced upgrade (CVE fix in a new major version) outweighs the migration effort, - triage a failing build/test suite after an upgrade attempt to determine which failures are upgrade-caused vs. pre-existing. ## Lean operating rules - Always resolve the exact currently-installed version from the lockfile (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`) before assessing risk; "upgrading React" without knowing the current pinned version produces meaningless risk output. - Query Context7/official release notes for the target version's actual breaking-change list before writing any risk assessment — never assemble this from training-data memory alone, since breaking-change lists change per release and are exactly the kind of fact that goes stale. - Separate hard breaking changes (code will not compile/run) from soft deprecations (still works, warns, scheduled for future removal) — conflating them causes both false alarm and false confidence. - Treat a breaking change tied to a security fix as a forced-upgrade driver that overrides normal cost/benefit sequencing; also flag if the current pinned version is already past its security-support window regardless of migration effort. - Do not assume a codemod exists for a given breaking change unless it is named in the official migration guide; do not invent codemod commands, CLI flags, or config keys. - Treat multi-major-version jumps (e.g. React 16 → 19, Next.js 12 → 15) as requiring sequential per-major risk assessment, not a single diffed comparison — intermediate majors carry their own breaking changes that compound. - Load `references/breaking-change-triage.md` only when classifying specific breaking changes as blocking vs. non-blocking and mapping them to affected code paths. - Load `references/dependency-compatibility-matrix.md` only when third-party dependencies (not the core framework itself) are the upgrade blocker. ## Context7 Documentation Protocol Every framework-specific breaking-change claim, codemod name, removed API, or "recommended migration path" statement in a response must be traceable to one of: 1. **Context7-verified** — resolved via `mcp__Context7__resolve-library-id` then confirmed with `mcp__Context7__query-docs` against the specific library (e.g. `/reactjs/react.dev`, `/vercel/next.js`) in this session or a prior verification you can cite by source URL. 2. **Official docs (direct citation)** — a specific docs/changelog URL, used when Context7 has no coverage for that library/version. 3. **Inference** — explicitly labeled as such and flagged for human verification against the installed toolchain; never presented as a verified breaking change. Do not invent codemod names, CLI flags, or config keys. If Context7 and official docs both lack coverage for a specific claim (e.g. an exact flag for a niche bundler plugin), say so and mark it `inference — verify against installed tooling` rather than guessing. Re-verify before citing if the last check is not from the current session — breaking-change lists and codemod tooling are actively evolving (React ships incremental React Compiler / Server Components guidance; Next.js has shipped multiple async-API and caching-default changes across recent majors). Confirmed in this skill's authoring session (re-verify if stale): - React 19 requires migrating `ReactDOM.render` to `createRoot`/`hydrateRoot`, removes `propTypes`/`defaultProps` support on function components (replace with TypeScript types/ES6 default parameters), and removes string refs in favor of ref callbacks. React ships `npx codemod@latest react/19/migration-recipe` as a combined codemod, plus a targeted `npx codemod@latest react/19/replace-string-ref`. Source: `reactjs/react.dev` docs (`blog/2024/04/25/react-19-upgrade-guide.md`). - Next.js 15 makes previously synchronous dynamic APIs (`cookies()`, `headers()`, `draftMode()`, and `params`/`searchParams` in pages, layouts, and `generateMetadata`/`generateViewport`) asynchronous — all call sites must `await` them or use `React.use()` in Client Components. Next.js ships `npx @next/codemod@latest next-async-request-api .` to automate this migration. Source: `vercel/next.js` docs (`01-app/02-guides/upgrading/version-15.mdx`, `01-app/02-guides/upgrading/codemods.mdx`). - Next.js 15 also changes the default caching behavior: `fetch` requests are no longer cached by default and require explicit `{ cache: 'force-cache' }` to opt back into the previous caching behavior. This is a runtime/behavioral breaking change, not a compile-time one, so it will not surface as a build failure — it surfaces as stale-vs-fresh data regressions. Source: `vercel/next.js` docs (`01-app/02-guides/upgrading/version-15.mdx`). ## References Load these only when needed: - [Breaking-change triage](references/breaking-change-triage.md) — use to classify each breaking change from the official migration guide as build-blocking, runtime-blocking, or cosmetic-deprecation, and to map each to affected code paths via repo search. - [Dependency compatibility matrix](references/dependency-compatibility-matrix.md) — use when the risk driver is a third-party library's peer-dependency constraint rather than the core framework's own breaking changes. ## Response minimum Return, at minimum: - the exact current version and target version being assessed (sourced from the lockfile, not assumed), - the breaking-change list sourced from official release notes/Context7 (with citation), split into blocking vs. cosmetic, - any security-advisory-driven upgrade urgency or security-support-window expiration, - an estimated blast radius (files/modules touching each blocking change, found via repo search), - evidence level for every claimed breaking change (Context7-verified, official-docs-cited, or inference — inference must be flagged for human verification against the installed toolchain).
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.