Skip to content
Castellan
Reeve's icon

Concept · Reeve

Read as

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
Written for Reeve 0.17.2. Reeve is at 0.17.3 now (1 small release since: what changed).

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.mod or a pinned requirements.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. importer picks 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). The docs-refresh job 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:

LayerHow
TypesThe project's own TypeScript reports every use of an API the installed packages mark @deprecated, with the package's note, usually the replacement.Exact
DocsSentences 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

PackageTarget
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/nodeThe newest of the project's Node major (.nvmrc, .node-version or engines.node)
A package whose latest is a prereleaseThe newest stable below it
A package another installed package's peer range refusesThe 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:

NoteWho decidesResult
A security fix for the package itselfcodeReported first
Labelled breaking by its authors (a "Breaking changes" section, BREAKING, feat!:, "Deprecated")codeAlways 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 notescodeListed under "read these notes by hand", with the link
Anything elseSkipped

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.

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.