Concept · Reeve
Version-pinned docs, docs lint and the upgrade scout
How Reeve answers questions about a library from the docs for the exact version your lockfile pins, finds deprecated APIs in your code, and tells you which dependency upgrades would break it.
- Article
- 1211
- Applies to
- Reeve 0.17.2
- Last reviewed
- For
- For developers
Why pinned docs#
A small model's own knowledge is older than most current libraries, and wrong about them. So Reeve never answers a library question from memory: only from docs stored on this PC, for the exact version the project's lockfile pins.
- Versions come from the lockfile: npm, pnpm, Cargo,
go.modor a pinnedrequirements.txt. Each workspace package is tracked on its own, so an app on one major version of a library and a site on another get an answer each, from the right docs.importerpicks one. - Docs come from the library's docs folder at its release tag, or its site's full-text feed, and always the package's own README and type declarations from
node_modules, which are exact for that version. - They're stored in
%USERPROFILE%\.reeve\docs\<name>@<version>, and indexed on first use (minutes per library, then seconds per question). Thedocs-refreshjob fetches new ones when a lockfile changes. - Answers are strict. Every quote, identifier, function call and number in an answer must appear in the docs. An answer that fails that check twice is withheld, and the passages come back instead.
Your assistant asks with docs (library, question, root), and docs_list with root shows which dependencies have docs stored.
Docs lint#
lint_docs (or lint-docs in a terminal) checks the code against the docs for the versions in the lockfile, from most certain to least:
| Layer | How | |
|---|---|---|
| Types | The project's own TypeScript reports every use of an API the installed packages mark @deprecated, with the package's note, usually the replacement. | Exact |
| Docs | Sentences in the pinned docs that say something is deprecated, removed or renamed, for names the project uses that types can't see: file conventions, config keys. | Checked |
The installed types have the final word on API names, and pages about other major versions are skipped, so a name that's deprecated in one place and current in another isn't flagged. Code reads which name is old and which new from the wording; the model only decides an unclear case. A run takes 30 to 60 seconds, and writes a report to %USERPROFILE%\.reeve\lint.
The upgrade scout#
upgrades reads the release notes between each outdated dependency's installed version and the version the project can move to, and reports the breaking changes that name APIs this code uses, with file and line.
The target isn't simply the latest
| Package | Target |
|---|---|
| Pinned by a framework (an Expo app's SDK modules, React, React Native and their kin) | The newest stable SDK's pin: what the framework's own installer would install |
@types/node | The newest of the project's Node major (.nvmrc, .node-version or engines.node) |
| A package whose latest is a prerelease | The newest stable below it |
| A package another installed package's peer range refuses | The newest version every such range accepts, or "upgrade together with" the package that lifts the limit |
A package already at its target while something newer exists is listed as held back, with the reason.
Reading the notes
Notes come from the package's changelog, its GitHub releases (through gh), or the changelog in the published package, and are kept in %USERPROFILE%\.reeve\changelogs. For an Expo app, the SDK announcement posts in range are added. Then:
| Note | Who decides | Result |
|---|---|---|
| A security fix for the package itself | code | Reported first |
Labelled breaking by its authors (a "Breaking changes" section, BREAKING, feat!:, "Deprecated") | code | Always reported |
| Unlabelled, with a change word ("removed", "renamed", "no longer", "now requires") | the model, one yes-or-no each: would an app using this package have to change? | Reported on yes, or when it names a key your config sets |
| Only a link to the notes | code | Listed under "read these notes by hand", with the link |
| Anything else | Skipped |
Code then pulls the API names out of each reported note and searches the files that import the package, and the app config that names it. A match the note's own condition rules out is marked with the reason, and stops counting.
The report
In order: security fixes; packages whose breaking notes name APIs this code uses (with file and line); packages with relevant notes but no matching code; packages with nothing relevant; notes to read by hand; held-back packages. The first run takes a few minutes; then the notes are cached.
Dependency health#
Once a day, the dependency-health job puts these together for each project: open security alerts, deprecated APIs in use, and upgrades that would break the code. Security alerts are checked against the checkout's own lockfile, so an alert a release branch has already fixed shows as fixed. An unfixed one names the installed parent whose version range refuses the patched version. A new high or critical alert raises an alert. See Reeve's rounds.
Related articles
Is this page right?
If something on it is wrong or out of date, tell us and we'll fix the page.
Still stuck? Write to support@castellan-software.com and mention article 1211. Every version of Reeve, and what changed in it, is in its release notes.