We’ve all been there. You open your repository on Monday morning and there are a dozen dependency update PRs waiting. Some are patch updates, some are minor, one is a major version bump buried in the middle. CI is green on all of them.
You merge them. What could go wrong?
Note: The skills shown here reflect my stack and conventions at the time of writing. They improve over time as the workflow learns from daily use. Your project will have different tools, different security concerns, different quality bars. These are examples of what’s possible, not prescriptions. Fork them, adjust them, or use them as inspiration for your own.
The maze of dependency updates
The problem with automated dependency tools isn’t that they update packages. It’s that they update packages without understanding what changed. They see version numbers. They don’t see your code.
Here’s what that looks like in practice:
The silent behavioral change. Newtonsoft.Json v12 to v13 looks like a normal major bump. Dependabot creates a PR, your tests pass, you merge. But v13 changed the default MaxDepth from null (unlimited) to 64. If your API handles deeply nested JSON from external systems, requests start failing in production. No compiler error. No test failure. Just a 500 in your logs two weeks later.
The “which one broke it?” problem. You update twenty packages at once because Renovate grouped them by “minor updates.” The build passes. But in staging, one endpoint returns different data. You now need to bisect twenty package changes to find which one caused it. An afternoon gone.
The transitive vulnerability. Microsoft.Bcl.Memory has CVE-2026-26127, a high-severity out-of-bounds read in Base64Url decoding. But you don’t reference it directly. It comes in through another package. Dependabot might catch the direct dependency, but the transitive chain? That depends on how deep it looks.
The deprecated package you’re still using. Microsoft.AspNetCore.Mvc.NewtonsoftJson has been deprecated in favor of System.Text.Json. Renovate will keep bumping its version. It won’t tell you to stop using it.
These aren’t hypothetical scenarios. They’re Tuesday.
A different approach
In part 1 of this series, I introduced the agentic dev workflow: a framework that gives AI coding assistants persistent memory and directed sessions. One of its skills is /dev-dependency, and it handles updates very differently from Renovate or Dependabot.
The core difference: it doesn’t just bump version numbers. It reads release notes, checks for breaking changes, analyzes how your code uses the package, and walks you through the update in risk order. It feels like a helping hand instead of a maze.
Let me show you what that looks like.
Running /dev-dependency on a .NET project
You type /dev-dependency in your AI agent session. The skill detects your .csproj files and starts with an audit.
Step 1: The audit
It runs the equivalent of dotnet list package --outdated, --vulnerable, and --deprecated, then classifies everything by risk. The AI adapts how it presents this: sometimes as a text report, sometimes as a table. Both carry the same information.
Text format:
DEPENDENCY UPDATE REPORT — Backend (.NET)
==========================================
Security (fix immediately):
🔒 Microsoft.Bcl.Memory 9.0.3 → 9.0.14 (CVE-2026-26127, High)
Patch (safe):
Aspire.Hosting.AppHost 13.1.0 → 13.1.2
Aspire.Hosting.Redis 13.1.0 → 13.1.2
Aspire.Hosting.PostgreSQL 13.1.0 → 13.1.2
Minor (review):
Polly 8.2.0 → 8.4.0
Serilog.Sinks.Console 5.0.0 → 5.1.0
Major (BREAKING — needs confirmation):
⚠ Newtonsoft.Json 12.0.3 → 13.0.3
⚠ xUnit 2.7.0 → 3.0.0
Deprecated:
⚠ Microsoft.AspNetCore.Mvc.NewtonsoftJson
→ Deprecated: migrate to System.Text.Json
Or as a table:
| Risk | Package | Current | Latest | Notes |
|---|---|---|---|---|
| 🔒 Security | Microsoft.Bcl.Memory | 9.0.3 | 9.0.14 | CVE-2026-26127, High |
| Patch | Aspire.Hosting.AppHost | 13.1.0 | 13.1.2 | |
| Patch | Aspire.Hosting.Redis | 13.1.0 | 13.1.2 | |
| Patch | Aspire.Hosting.PostgreSQL | 13.1.0 | 13.1.2 | |
| Minor | Polly | 8.2.0 | 8.4.0 | |
| Minor | Serilog.Sinks.Console | 5.0.0 | 5.1.0 | |
| ⚠ Major | Newtonsoft.Json | 12.0.3 | 13.0.3 | Breaking changes |
| ⚠ Major | xUnit | 2.7.0 | 3.0.0 | Breaking changes |
| Deprecated | Microsoft.AspNetCore.Mvc.NewtonsoftJson | — | — | Migrate to System.Text.Json |
Either way, it’s a risk-stratified plan. Security first, patches next, then minor, then major. Each category gets handled differently.
Step 2: Security fixes first
The skill starts with Microsoft.Bcl.Memory. It doesn’t just update the version. It tells you what the vulnerability is:
🔒 Microsoft.Bcl.Memory 9.0.3 → 9.0.14
CVE-2026-26127: Out-of-bounds read in Base64Url decoding
Severity: High (CVSS 7.5)
Disclosed: March 10, 2026
This is a transitive dependency pulled in by
Microsoft.Extensions.Caching.StackExchangeRedis.
Impact on your code: Your API uses Base64Url encoding
in the JWT token validation middleware (TokenService.cs:42).
Applying patch...
Running dotnet build... ✅
Running dotnet test... ✅ (127 passed)
Dependabot and Renovate will include release notes and changelogs in their PRs when available. But they won’t search your codebase for affected patterns. The difference is knowing that a CVE exists vs knowing that it affects TokenService.cs:42 in your project.
Step 3: Patch updates
Next, the Aspire packages. These are patch updates within the same minor version, so the risk is minimal. But instead of updating them one by one, the skill groups related packages that should move together:
Updating Aspire 13.1.x packages as a group:
Aspire.Hosting.AppHost 13.1.0 → 13.1.2
Aspire.Hosting.Redis 13.1.0 → 13.1.2
Aspire.Hosting.PostgreSQL 13.1.0 → 13.1.2
These packages share a release cycle and should
stay on the same version.
Applying patches...
Running dotnet build... ✅
Running dotnet test... ✅ (127 passed)
Renovate and Dependabot can group packages too. Renovate ships with built-in presets for known families and allows you to extend them. Dependabot supports grouping by name patterns in dependabot.yml. The difference here is that the AI agent recognizes package families from its understanding of the .NET ecosystem without upfront configuration. But credit where it’s due: for well-known package families, the existing tools handle this fine.
Step 4: Minor updates with review
For minor updates, the skill slows down. The AI agent draws on its knowledge of popular packages to flag anything noteworthy or you can ask it to looking the information online:
Minor: Polly 8.2.0 → 8.4.0
Release notes: Added ResiliencePipelineBuilder.AddTimeout
overload with CancellationToken support. New telemetry
enrichment options for OpenTelemetry integration.
No deprecations. No behavioral changes.
Applying...
Running dotnet build... ✅
Running dotnet test... ✅ (127 passed)
Each minor update is applied and verified separately. If Polly breaks something, you know it was Polly. Not Polly plus Serilog plus three other packages in the same PR.
Step 5: Major updates — full stop
This is where the real difference shows. The skill hits Newtonsoft.Json v12 to v13 and stops:
⚠ MAJOR VERSION UPDATE: Newtonsoft.Json 12.0.3 → 13.0.3
Breaking changes detected:
1. Default MaxDepth changed from null (unlimited) to 64
→ Your code: ApiController.cs:28 deserializes external
webhook payloads that can nest 100+ levels deep.
This WILL break.
2. JsonExtensionData behavior changed for properties
without setters.
→ Your code: AuditEvent.cs:15 uses [JsonExtensionData]
on a read-only dictionary. Verify deserialization
still works.
Migration guide:
https://www.newtonsoft.com/json/help/html/upgradeGuide.htm
Affected files: 4
src/Api/Controllers/ApiController.cs
src/Api/Models/AuditEvent.cs
src/Api/Middleware/JsonSettings.cs
tests/Api.Tests/Serialization/JsonTests.cs
Do you want to proceed? [y/n/skip]
Dependabot would have created a PR that said “Bump Newtonsoft.Json from 12.0.3 to 13.0.3.” Your tests would pass because they don’t test with 100-level-deep JSON. You’d merge and overlooked one crucial unexpected point. Production would break.
The skill caught it because it read the breaking changes documentation and then scanned your code for affected patterns. It found the deep nesting in ApiController.cs and the JsonExtensionData usage in AuditEvent.cs. It told you before you committed.
Step 6: Deprecated packages
Finally, it flags the deprecated package:
⚠ Microsoft.AspNetCore.Mvc.NewtonsoftJson is deprecated.
Recommended: migrate to System.Text.Json
This package is still functional but won't receive
new features or non-critical fixes.
Your code uses it in:
Program.cs:14 (.AddNewtonsoftJson())
Startup extensions
This is a migration, not a version bump.
Consider creating a /dev-blueprint for this.
Renovate would warn you about the deprecation and may even suggest a replacement for known migrations. But it won’t look at your codebase to assess the migration scope or suggest a structured plan. The skill connects the dots: deprecated package, here’s where you use it, here’s how to plan the migration with /dev-blueprint.
Running /dev-dependency on an Angular project
The same principles apply to the frontend, but the tooling and risks are different. When /dev-dependency detects a package.json, it routes to the npm workflow.
The audit
DEPENDENCY UPDATE REPORT — Frontend (Angular)
===============================================
Security:
🔒 express 4.18.2 → 4.19.2 (CVE-2024-29041)
Patch (safe):
rxjs 7.8.0 → 7.8.1
zone.js 0.14.3 → 0.14.4
@angular/material 17.3.0 → 17.3.4
Minor (review):
@ngrx/store 17.1.0 → 17.2.0
@angular-eslint/builder 17.2.0 → 17.5.0
Major (BREAKING — needs confirmation):
⚠ @angular/core 17.3.0 → 18.0.0
⚠ @angular/cli 17.3.0 → 18.0.0
⚠ typescript 5.3.3 → 5.5.0
⚠ rxjs 7.8.1 → 8.0.0
Deprecated:
⚠ @types/jasmine
→ Deprecated: Vitest or Jest recommended over Jasmine/Karma
Security fixes
Same as the backend: security comes first. But here the skill adds a critical warning:
🔒 express 4.18.2 → 4.19.2
CVE-2024-29041: Open redirect vulnerability in express
Severity: Medium
This is a dev dependency (used by @angular-devkit/build-angular
for the dev server). Not exposed in production builds, but
should still be patched.
⚠ Note: npm audit fix would fix this safely.
npm audit fix --force would NOT be safe — it can silently
install breaking major versions of unrelated packages.
Applying safe fix...
Running ng build... ✅
Running ng test --watch=false... ✅ (84 passed)
That warning about npm audit fix --force matters. It’s a common mistake. Developers run --force when npm audit fix doesn’t resolve everything, and suddenly Angular jumps two major versions.
Patch and minor updates
Patches are grouped and applied safely. For minor updates, the skill checks for anything noteworthy:
Minor: @ngrx/store 17.1.0 → 17.2.0
Release notes: Added createFeature() overload for
signal-based selectors. New withDevtools() function
for standalone stores.
No deprecations. No behavioral changes.
Applying...
Running ng build... ✅
Running ng test --watch=false... ✅ (84 passed)
Major updates: where npm gets painful
Angular itself has ng update schematics that handle a lot of migration automatically. But most npm packages don’t have that luxury. The major version bumps that really hurt are the ones where you’re on your own.
RxJS 7 → 8:
⚠ MAJOR VERSION UPDATE: rxjs 7.8.1 → 8.0.0
Breaking changes detected:
1. Import paths changed: 'rxjs/operators' removed
→ Your code: 14 files import from 'rxjs/operators'.
All pipe operators must be imported from 'rxjs' directly.
Before: import { map, filter } from 'rxjs/operators';
After: import { map, filter } from 'rxjs';
2. Operator renames:
→ pluck() removed. Use map() instead.
Found in: user.service.ts:23, settings.store.ts:41
→ toPromise() removed. Use firstValueFrom() or lastValueFrom().
Found in: auth.service.ts:67, api.client.ts:15, api.client.ts:89
3. Subscription handling changed:
→ Your code: 3 files use .add() for teardown logic.
Use takeUntilDestroyed() or DestroyRef instead.
Found in: dashboard.component.ts, chart.component.ts,
notifications.component.ts
No migration schematics available.
Affected files: 22
Do you want to proceed? [y/n/skip]
There’s no rxjs update command that fixes these for you. Renovate would bump the version, CI would fail with twenty import errors across fourteen files, and you’d spend an hour fixing them manually. The skill tells you exactly which files need which changes before you commit.
ESLint 8 → 9:
⚠ MAJOR VERSION UPDATE: eslint 8.57.0 → 9.0.0
Breaking changes detected:
1. Configuration format completely changed
→ .eslintrc.json found in your project root.
ESLint 9 uses flat config (eslint.config.js).
Your existing config will be IGNORED.
2. Multiple plugins need compatible versions:
→ @angular-eslint/builder 17.5.0 — check compatibility
→ @typescript-eslint/parser 7.1.0 → needs v8+ for ESLint 9
→ eslint-plugin-import 2.29.0 → not yet compatible with
flat config (open issue: eslint-plugin-import#2948)
3. Formatter removed from core:
→ Your CI script uses eslint --format stylish.
Formatters are now separate packages.
This is a complex migration with ecosystem dependencies.
Some plugins may not support ESLint 9 yet.
Recommendation: defer this update until
eslint-plugin-import releases flat config support.
Run /dev-dependency --security to handle urgent
fixes without touching ESLint.
Do you want to proceed anyway? [y/n/skip]
This is the kind of update where Renovate creates a PR, CI fails, and you close it because you don’t have time to deal with it today. Then it creates the same PR next week. And the week after. The skill actually checks whether the ecosystem is ready for the migration and recommends deferring when key plugins aren’t compatible yet. That’s not a version check. That’s judgment.
Deprecated packages
⚠ @types/jasmine is deprecated.
Recommended: migrate to Vitest or Jest.
You already have Vitest partially configured:
vitest.config.ts exists with 12 test files.
karma.conf.js still present with 84 Jasmine tests.
This is a migration, not a version bump.
Consider running /dev-blueprint to plan the
Jasmine → Vitest migration.
The skill notices you’re already partway through a migration. It doesn’t just flag the deprecated package, it tells you where you are in the transition.
What the skill does vs what the AI agent does
An important distinction: the /dev-dependency skill is a structured procedure. It defines the audit commands, the risk classification, the update order, the verification steps. But the AI executing that procedure adds intelligence on top. The code-level impact analysis, the package family recognition, the breaking change reasoning: that’s your AI agent reading your code and applying its training knowledge.
This means the quality of analysis varies. For well-known packages like Newtonsoft.Json, EF Core, or RxJS, the AI agent has deep knowledge of breaking changes between versions. For niche packages, it might have less to say. The skill provides the structure. The AI agent provides the depth.
Getting started
The /dev-dependency skill is part of the agentic-dev-workflow. If you’ve already set up the workflow from part 1, the skill is ready to use.
Run it with flags to control scope:
/dev-dependency # Full audit and update
/dev-dependency --audit # Report only, no changes
/dev-dependency --security # Security fixes only
/dev-dependency --patch # Patch updates only
/dev-dependency nuget # .NET packages only
/dev-dependency npm # Frontend packages only
/dev-dependency --interactive # Step through each package
For .NET projects with multiple solutions, consider running /dev-dependency --cpm first to convert to Central Package Management. This consolidates all version declarations into a single Directory.Packages.props file, making updates cleaner across your entire solution.
Learning from your upgrades
As covered in part 1, the agentic dev workflow has a self-learning loop. This applies to dependency management too.
Every time you run /dev-dependency and hit a breaking change, the decisions you make get logged in your daily memory. Maybe you discovered that Polly v8.4.0 changed how retry policies interact with HttpClientFactory in your setup. That goes into your session notes. Over time, /meta-continuous-learning picks up these patterns and can improve the skill itself.
Next time a colleague runs the same upgrade on a different project, the skill already knows to watch for that Polly interaction. The knowledge compounds. Your team’s upgrade history becomes part of the workflow, not just a memory in someone’s head.
This is something no external tool can do. Renovate and Dependabot have no concept of your team’s upgrade history. They treat every project as if it’s the first time.
In summary
Dependency management isn’t a version number problem. It’s a “what does this change mean for my code” problem.
Renovate and Dependabot are good tools. They keep your versions current, show release notes, warn about deprecations, and provide risk signals. They deserve credit for what they do well.
What they can’t do is read your code. They can’t tell you that a MaxDepth default change will break your specific webhook handler, or trace a transitive CVE to your JWT middleware, or recommend deferring an ESLint upgrade because the plugin ecosystem isn’t ready.
The /dev-dependency skill bridges that gap. Not by replacing your existing tools, but by adding the code-level context and interactive judgment that turns a list of version bumps into an informed upgrade session.
Next time you see a dozen dependency PRs on a Monday morning, try running /dev-dependency --audit first. The report might change which ones you merge.