Repository navigation
Conversation
Adds a dependency-manager agent orchestrating a 5-stage pipeline (dependency-audit / toolchain-audit -> dependency-update-audit safety gate -> dependency-update-apply -> dependency-doc-sync -> dependency-update-pr) under .claude/. Language/framework agnosticism is achieved via per-ecosystem adapter files (Dart/Flutter shipped, npm/etc can be added without editing any skill). Policy lives in .claude/rules/dependencies.md.
Replaces per-package registry/advisory/changelog tool calls in dependency-audit with a single stdlib-only Python script per manifest (scripts/fetch_updates.py), fixing several real bugs found testing it live: pub.dev's changelog is rendered HTML not markdown, pub outdated's field shapes, SDK pseudo-dependencies colliding with unrelated manifest lines, and no-lockfile manifests producing noisy no-op candidates. Adds bump_manifest.py and bump_toolchain_file.py so version bumps are applied as precise scripted edits instead of free-form text edits, guaranteeing a pin's existing style (exact vs range) is preserved. Adds an `upgradable` field so the audit reports both the zero-edit-cost update and the further one requiring a pin change, when they differ. Adds a batch-verification step to dependency-update-audit: after every candidate in a tier passes individually, apply them all together on one scratch branch to catch transitive conflicts a one-at-a-time check can't see, attributing any failure back to the specific candidate(s) responsible via the same verdict/evidence fields already used everywhere else.
Persists the candidates.json + printed-summary example (real flutter_secure_storage/sqflite audit output) as a reference file instead of only living in a PR description, so the target output shape stays documented alongside the skill.
- Loosen the dependency-manager agent and toolchain-audit descriptions to lead with adapter-driven capability instead of naming Flutter as the only supported ecosystem. - Replace the Claude-authorship line in PR bodies with a generic "generated by an automated agent" disclaimer. - Rewrite the Flutter/Dart toolchain adapter to drop hard references to this repo's specific PR/branch/commit history (which won't exist if this pipeline is reused elsewhere), replacing the worked example with a self-contained illustrative one, and correct its stale SDK/AGP/ Kotlin/Gradle version numbers to match the repo's actual current pins. - Drop a stale OPEN QUESTION comment in the dart-flutter adapter about CLAUDE.md's git history, now resolved.
fedecor9
commented
Sep 15, 2026
- Generalize the remaining Flutter/repo-name hardcoding in the live .claude/agents/dependency-manager.md (this repo name, package-manager examples, toolchain component lists, never-auto-update package names, verification-command path) so it points at adapters/rule files instead. - Add plugin/dependency-manager/: a self-contained Claude Code plugin bundling the agent and all six pipeline skills, with the remaining repo-specific script/CI assumptions (checks.sh, fastlane lane, pr-title-checker config) genericized to "whatever this repo's verification_cmd/adapter/rule file defines." - Ship the Dart/Flutter ecosystem and toolchain adapters plus a filled dependencies.md as a bundled worked example under examples/, so a new Flutter repo has a running-start reference to copy. - Add a local marketplace manifest (plugin/.claude-plugin/marketplace.json) and a plugin README covering structure, the adapter pattern, and install/adoption steps for a new repo.
fedecor9
marked this pull request as ready for review
September 21, 2026 15:56
…tion
- Add bundled ecosystem adapters for python-pip, python-poetry, python-uv,
npm, yarn, and pnpm alongside the existing dart-flutter one, each a
worked-example .md + machine-readable .json pair.
- Generalize scripts/fetch_updates.py, which previously hardcoded pub's
exact outdated-command JSON shape (nested {"version": ...} fields, a
literal "pubspec.yaml", YAML-only dependency section headers) and would
not have actually worked against any of the new adapters. It now
dispatches on a config-driven outdated_shape (pub / npm-style object /
flat array / yarn's table envelope / poetry's array) and config-driven
manifest_filename/manifest_section_headers, verified against fixture data
for every shape plus an end-to-end offline run.
- Add two-location adapter resolution to every skill that loads one:
.claude/dependency-manager/ecosystems|toolchains/<name> in the *target*
repo first (repo-local override, or where a newly detected ecosystem's
adapter gets drafted), falling back to this plugin's own bundled copy.
Never write into ${CLAUDE_PLUGIN_ROOT} — it's a shared, read-only cache
across every repo the plugin is installed in. New refusal rule in
agents/dependency-manager.md codifies this.
- Update README.md and the ecosystem/toolchain _template.md files to
document the bundled adapter list and the resolution/drafting mechanism.
Addresses PR review comment on .claude/agents/dependency-manager.md:3 — reword "(Dart/Flutter via pub today; any ecosystem with an adapter)" so it's clear the Flutter reference is this repo's current ecosystem, not a hardcoded assumption, matching the phrasing already used in the plugin package's copy of this file.
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.
What this is
A self-contained dependency- and toolchain-maintenance system for this repo,
built entirely as Claude Code configuration under
.claude/— no applicationcode changes. It's a
dependency-manageragent orchestrating five skillsthat each own one stage of a pipeline: audit what's outdated, prove an
update is actually safe before touching anything, apply it, keep the
pipeline's own docs in sync, and open a PR with the evidence as the
description.
It's built to be language/framework-agnostic: everything ecosystem-specific
(pub.dev URLs, OSV.dev's ecosystem name, Dart's version-suffix quirks) lives
in a small adapter file pair, not in the skills themselves. Adding a new
ecosystem later is one new
.md+ one new.json, no skill edited.How it works
dependency-audit— read-only inventory. Runs a script(
scripts/fetch_updates.py) once per manifest that checks what'soutdated, queries the registry and security advisories, and fetches the
relevant changelog excerpt — then grades each finding on two independent
axes: urgency (security-driven — why you'd want this) and risk
(breaking-change-driven — what it costs). A critical CVE fixed by a
trivial patch is
urgency: critical, risk: none— those aren't the samequestion.
toolchain-audit— the same idea for the Flutter/Dart SDK, AGP,Kotlin, and the Gradle wrapper, kept separate since a toolchain bump's
blast radius (native project files, CI config) is nothing like a package
bump.
dependency-update-audit— the safety gate. Applies the candidate ona throwaway scratch branch, runs
./scripts/checks.shfor real, and onlythen writes a verdict — "the changelog looked fine" is never accepted
as evidence. Also runs a batch check when a tier has multiple candidates,
since packages that are each safe alone can still conflict when bumped
together.
dependency-update-apply— applies whichever tier a human hasexplicitly approved, on its own branch, re-verifying for real before
committing.
dependency-doc-sync— after a bump lands, fixes any of thepipeline's own docs that just went stale (e.g. a toolchain adapter's
hardcoded "current version" note).
dependency-update-pr— opens one PR per safety tier (draft foranything with breaking changes), with the audit evidence as the PR body.
The agent never applies or opens a PR without an explicit human go-ahead per
tier — audit and safety-gate are the only stages that run unattended.
Example: input → output
Given this repo's real
pubspec.yaml(flutter_secure_storage: ^10.3.1),running
dependency-auditproduces (full worked example, including theprinted summary, in
.claude/skills/dependency-audit/references/example-output.md):{ "package": "flutter_secure_storage", "current": "10.3.1", "upgradable": "10.3.4", "latest_compatible": "11.1.1", "bump": "major", "urgency": "maintenance", "risk": "medium", "tier": "review", "breaking_changes": [ "11.0.0: items deprecated in v10 were removed; data saved with a deprecated algorithm becomes unusable unless the app already passed through v10 to migrate it.", "Android: removed KeyCipherAlgorithm.RSA_ECB_PKCS1Padding, StorageCipherAlgorithm.AES_CBC_PKCS7Padding, and the encryptedSharedPreferences/sharedPreferencesName AndroidOptions fields.", "Android: raised minSdk to 24 and compileSdk to 37." ] }which the skill renders as:
Note
upgradable(10.3.4) vslatest_compatible(11.1.1) — the reportsurfaces both a free, zero-risk bump and the further one that requires
accepting the breaking changes, rather than only showing whichever is
"furthest." Verified deterministic: two independent runs against the same
repo state produced byte-identical structured fields and near-identical
breaking_changesprose.The scripts (why they exist)
Pushing deterministic work into small, stdlib-only Python scripts — rather
than having the agent hand-run and parse commands itself — fixes real bugs
found while testing this live: pub.dev's changelog is rendered HTML, not
markdown;
pub outdated's output has quirks (a non-JSON banner prefix,inconsistent fields); and free-form text edits to a manifest can silently
turn an exact pin into a range under pressure.
dependency-audit/scripts/fetch_updates.py— one call per manifestreplaces dozens of individual registry/advisory/changelog calls. Batches
the security-advisory check (OSV.dev) into a single request instead of one
per package.
dependency-update-apply/scripts/bump_manifest.py— edits exactly oneversion number on one manifest line, preserving whatever pin style (exact
or range) was already there. Refuses rather than guesses on any ambiguous
match.
dependency-update-apply/scripts/bump_toolchain_file.py— the samediscipline for toolchain files, which span three incompatible formats
(
.fvmrc's JSON,settings.gradle's Groovy DSL, a version embedded in aURL) that no single parser handles — so this does a literal, disambiguated
substitution instead.
Status
Built and tested this session: the audit path (read-only) has been run live
against this repo's real dependencies multiple times, including two parallel
clean-context trial runs confirming consistent output. The safety-gate →
apply → PR path has been validated on isolated synthetic candidates, not yet
run end-to-end against a real multi-package tier. Opening as a draft for
that reason.