Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .agents/skills/upgrade-packages/REFERENCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Reference — evidence artifact schema

The `upgrade-packages` skill runs `bun run upgrade-packages:evidence` (writes `scripts/upgrade-packages/artifact.json`) and reads the JSON artifact below. The agent never touches the registry, GitHub, or GHSA directly — every citation comes from artifact fields. The script requires network access (`gh api` + `bun pm view`); release/advisory data is cached to `scripts/upgrade-packages/.cache/` (1h TTL).

## Artifact shape

```jsonc
{
"generatedAt": "ISO timestamp",
"inventory": {
"direct": [{ "name", "version", "range": "exact|caret|tilde", "dev" }],
"transitiveDuplicates": [{ "pkg", "versions": [...] }] // direct-dep conflicts + semver-major splits only
},
"outdated": [{
"pkg", "current", "latest",
"bumpClass": "patch|minor|major|prerelease|no-op",
"coupledWith": [] // naive; agent confirms peer/dep coupling from deltas
}],
"audit": {
"bunAudit": <raw bun audit --json payload>,
"ghsa": [{ "pkg", "advisories": [{
"id", "cveId", "severity",
"vulnerableRange", "fixedIn",
"installedInRange": bool, // script-computed vs installed version
"verdict": "priority-bump|needs-higher-target|cleared-at-current|unpatched|check-failed",
"url", // github.com/advisories/<id>; empty + id:"error" on check-failed
"error" // optional — message on check-failed (gh/parse/cache failure)
}] }]
},
"deltas": {
"<pkg>": [{
"version", "date",
"breaking": [...], "deprecations": [...], "features": [...],
"security": [...], "peerEngine": [...], // best-effort regex hints — read releaseNotes for the authoritative text
"releaseNotes": "truncated body",
"diffUrl": "github.com/<o>/<r>/compare/<prevTag>...<tag>",
"changelogUrl": "github.com/<o>/<r>/releases/tag/<tag>",
"source": "github-release|none",
"error": null | "reason"
}]
},
"usage": {
"<pkg>": {
"importedSymbols": [...], "typeOnlySymbols": [...], // parsed imports (codemap) — type-only included
"sites": ["file:line", ...], // import locations
"callSites": ["file:line", ...], // reference locations (codemap only — blast radius)
"source": "codemap|grep" // grep = fallback when codemap unavailable
}
}
}
```

## How to read it

- **Verdict a package**: read `outdated[].bumpClass` + `audit.ghsa[].verdict` + `deltas[<pkg>][].breaking`/`security` + `usage[<pkg>].importedSymbols`. Cite `diffUrl` or `changelogUrl` for every claim.
- **`features`/`breaking` arrays are hints** — when a hint is empty but the delta is minor/major, read `releaseNotes` before concluding "no changes".
- **`error` on a delta** means the script couldn't fetch that version's release notes — usually a gh secondary rate-limit during a large multi-repo run, or a monorepo squashed release. `changelogUrl` is still provided (the repo's releases page) — **deep-dive it per-package** when `releaseNotes` is null. Only mark the bump **blocked** if the deep-dive still can't cover the range.
- **`cleared-at-current`** = the GHSA advisory's fix already ships at the installed version — no bump needed, record the URL as evidence.
- **Citations are artifact fields** — `diffUrl`, `changelogUrl`, `url`. Do not invent URLs.
76 changes: 76 additions & 0 deletions .agents/skills/upgrade-packages/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: upgrade-packages
description: >-
Delta-driven dependency upgrades — a script gathers the evidence, you read the artifact and judge. Use when the user asks to upgrade, bump, or CVE-audit dependencies.
---

# Upgrade packages

A script gathers every release delta, GHSA advisory, and codebase-usage site into one JSON artifact; you read it and judge. **Never touch the registry, GitHub, or GHSA directly** — every citation comes from the artifact (`diffUrl`, `changelogUrl`, advisory `url`), so no model priors sneak in. Sources of truth: the artifact, then the codebase. Cite where you read every claim.

This repo uses **bun** with **exact** pins in `package.json` — `bun update` alone bumps nothing. Lift an exact pin with `bun update <pkg>@<target>` (or `bun update <pkg> --latest` per package) / a `package.json` edit. Never `bun update --latest` across the board. The `check-updates` script is inventory-only.

## Phase 1 — Gather evidence

Run `bun run upgrade-packages:evidence` (defaults to `--out scripts/upgrade-packages/artifact.json`; pass `--out <path>` to override). **Requires network access** — the script calls `gh api` (GitHub releases + GHSA advisories) and `bun pm view`; a sandboxed network allowlist that blocks `api.github.com` will make every gh call fail (the artifact degrades to `error` markers with `changelogUrl` deep-dive links). Release/advisory data is cached to `scripts/upgrade-packages/.cache/` (1h TTL) so re-runs are fast and don't re-trip rate limits. Read the artifact. Schema + how-to-read: [`REFERENCE.md`](./REFERENCE.md).

**Done when:** the artifact exists and you've read `inventory`, `outdated`, `audit`, `deltas`, and `usage`.

## Phase 2 — Triage (judge the artifact)

For each `outdated` package, produce a cited verdict + band:

- **band** = `bumpClass` (patch/minor/major/prerelease). **Coupled deps:** if a patch bump's peer/dep requires a minor+ bump of another direct dep (check `deltas[<pkg>][].peerEngine` + the other package's `bumpClass`), move the coupled set up a band.
- **priority-bump** if `audit.ghsa` verdict is `priority-bump` — goes first within its band.
- **check-failed** if `audit.ghsa` verdict is `check-failed` (gh/parse/cache failure, `id:"error"`) — inconclusive, not a vuln; re-run evidence or deep-dive the `changelogUrl` before treating as blocked.
- **blocked** if any `deltas[<pkg>][].error` leaves the range uncovered and the missing version can't be sourced via its `diffUrl`, OR a `breaking`/`security`/`peerEngine` delta is a break-risk you can't resolve (see Phase 3).
- **deferred-major** for a major with an unresolved break — unless it clears a high/critical advisory, in which case surface the tradeoff to the user.

Cite the `diffUrl`/`changelogUrl`/advisory `url` for every verdict.

**Done when:** every outdated package has a cited verdict, a band, and a coupled-set tag; every `priority-bump` is flagged for Phase 3.

## Phase 3 — Fact-check break-risk against the codebase

For every **break-risk delta** (`breaking`, `deprecations`, `peerEngine`, or a behavior-changing fix in `security`/`features` — e.g. callback debounce, CVE patch altering semantics), cross-check `usage[<pkg>]`. Use `callSites` (codemap) for **blast radius** — where the symbol is actually called, not just imported; `importedSymbols` + `typeOnlySymbols` for what's in scope; `sites` for import locations. Classify: **no usage** / **code-aligned** / **breaks** (needs a code change first). Cite `callSites`/`sites` (file:line). A `breaks` with no code change → the bump is **blocked** or **deferred**.

**Done when:** every break-risk delta has a citation-backed `no usage | aligned | breaks` verdict; every `breaks` has a proposed code change.

## Phase 4 — Apply, gated by risk

Bands: patch → minor → major, verify after each per [`verify-after-each-step`](../../rules/verify-after-each-step.md). Within each band, **priority-bump** packages first; **coupled sets** move up together; **prereleases** go in the patch band (moving-target, same-major-line gate).

1. **Patch** — bump together (`bun update <pkg>@<target>` per package); run the CI mirror (below).
2. **Minor** — bump together; same checks.
3. **Major** — one at a time; land its `breaks` code change _first_, bump, then checks. Defer unresolved majors (cited reason) unless they clear a high/critical advisory.

A bumped parser/resolver/CSS package can change extraction output — re-run `bun run test:golden` and regenerate any affected goldens. Re-run `bun audit` after each band — a **new** advisory → revert that bump and re-research. Commit per band **only when the user asked to commit**.

**Done when:** CI mirror (`bun run check` + `bun run build`) green for patch + minor; every major green-and-committed/staged or deferred with a cited reason; no `breaks` unaddressed; final `bun audit` clean or every remaining advisory documented.

## Phase 5 — Verify (local CI mirror)

Run what `.github/workflows/ci.yml` runs — `ci.yml` is the SSOT:

- `bun run check` → build + format:check + lint:ci + test + test:scripts + typecheck + test:golden + test:agent-eval (5 of 6 CI jobs: Format, Lint, Typecheck, Test, Build)
- `bun run build` → covered by `check`, but re-run explicitly if a bump only touched build tooling (tsdown/oxc) — **do not skip**; dep upgrades break the bundler/codegen far more often than types
- `bun audit` → CI's audit job blocks on **high/critical** (it greps `bun audit` output for `high:` / `critical:`); treat any high/critical advisory as **blocking-with-triage**, lower severities as documented

## Phase 6 — Report

Produce: **security** (advisories → verdict, with GHSA id + URL + fixed-in), **consolidated changeset** (rolled up from `deltas` — per package `current → target`, bucketed breaking/deprecations/features/fixes/peer-engine, one line per delta), **adoption opportunities** (top ~5 `features` deltas the codebase isn't using — `usage` verdict + file:line + one-line why-adopt + follow-up; non-blocking), bumped packages (band → version → why-safe), deferred/blocked (cited reason + file:line), verification results. Every citation from the artifact. If the user asked to commit/PR, hand off to [`harden-pr`](../harden-pr/SKILL.md) full mode.

**Done when:** report accounts for every non-no-op package and advisory; every citation is real — no `possibly`, `likely`, or unstated assumptions.

## Anti-patterns

- ❌ Touching the registry/GitHub/GHSA directly — run the script, read the artifact.
- ❌ `bun update --latest` across the board — per-package `--latest`/`package.json` edit for exact pins.
- ❌ Treating `bun audit` as pass/fail — every advisory needs a cited verdict; a high/critical audit is blocking-with-triage.
- ❌ Skipping `bun run build` — bundler/codegen breakage beats type breakage for dep upgrades.

## Reference

- [`REFERENCE.md`](./REFERENCE.md) — evidence artifact schema + how to read it
- [`verify-after-each-step`](../../rules/verify-after-each-step.md) — per-band checks
- [`harden-pr`](../harden-pr/SKILL.md) — full mode before PR
5 changes: 5 additions & 0 deletions .changeset/deps-bump-clack-oxc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stainless-code/codemap": patch
---

Refresh dependency tree to latest compatible releases. Interactive `codemap agents init` note text stays dimmed.
1 change: 1 addition & 0 deletions .cursor/skills/upgrade-packages
10 changes: 9 additions & 1 deletion .oxfmtrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
"sortPackageJson": {
"sortScripts": true
},
"ignorePatterns": [".output", "node_modules", "dist", "coverage", "bun.lock"],
"ignorePatterns": [
".output",
"node_modules",
"dist",
"coverage",
"bun.lock",
"scripts/upgrade-packages/.cache",
"scripts/upgrade-packages/artifact.json"
],
"printWidth": 80
}
Loading