Open source · MIT · built on FalkorDB

Every merge can make a tutorial lie. Staleproof finds which one, proves it, and fixes it.

Paste a pull request. Staleproof follows the changed code through a FalkorDB graph of every repository you own — code, docs and the decisions your maintainers made — to the paragraphs it can make false. It runs those examples before and after the change, and proposes the docs fix with the evidence behind each edit.

$npx -y staleproof check https://github.com/FalkorDB/falkordb-py/pull/262
FalkorDB/falkordb-py#262fix: only forward accepted kwargs from Is_Cluster to redis.Redis
  1. changedIs_Clusterfalkordb-py
  2. called byFalkorDB.__init__falkordb-py
  3. used inREADME · Asynchronous Examplefalkordb-py
before the PRfailsTypeError: Redis.__init__() got an unexpected keyword argument 'himport_registry'
after the PRpassesexit 0

The README's async example was broken until this PR fixed it. A name search finds nothing: no doc mentions Is_Cluster. The call graph does.

What it found on FalkorDB's own repositories

Every number comes from FACTS.md, generated from the graph
43
doc sections one pull request can falsify — 41 of them in other repositories
falkordb-py#276
0 / 47
sections a grep for the changed names finds, of the 47 the graph reaches
falkordb-py #262 · #267 · #276
120 vs 30
sections reached by the graph vs found by grep, which also matches 227 unrelated ones
all 4 checked pull requests
21
docs examples tried at both commits of one PR: 10 pass both times, 6 were already broken
falkordb-py#276

falkordb-py#267 fixed the execution-plan parser

The path ExecutionPlan._operation_tree ← ExecutionPlan.__init__ ← Graph.explain led into a different repository: the docs site's GRAPH.EXPLAIN page. Its example fails on a fresh server before and after the PR — it explains a query on a graph the page never creates. Not caused by the PR; already broken, and now known.

falkordb-py#276 changed four asyncio symbols

They reach 43 doc sections through paths like AsyncGraph.query ← FalkorDBConnection.query (GraphRAG-SDK) ← … ← GraphRAG-SDK README. Of the 21 examples run at both commits, 10 pass both times, 6 were already broken, 3 can't be installed together at those commits (version skew) and 2 can't run as written.

Try it

Check any pull request

Paste a pull request from any public Python, TypeScript or JavaScript repository on GitHub: the first check indexes it, in seconds for most projects. Or pick one of FalkorDB's. The trace streams every tool call and the Cypher it ran on FalkorDB.

Agent mode

A model chooses which tools to call, reads each affected section, and writes a verdict or an edit for every one of them.

Graph mode

The same tools in a fixed order with no model and no API key: impact, clearance, ranking, and a sample of up to three example runs. Deterministic and free.

The interactive demo needs JavaScript. These are the pull requests it opens with:

The problem

Docs drift where review can't see it

The paragraph is in another repository

A change to the client breaks a tutorial in the SDK and a page on the docs site. Code review only sees the repository the PR is in.

Nobody greps for the right name

The README calls FalkorDB(), whose constructor calls the function you changed. The docs never name that function, so search finds nothing.

Nobody re-runs the examples

Tutorials are code that never runs in CI. They break silently, and readers find out first.

How it works

From a pull request to a proven docs fix

Each step is a tool that runs Cypher on FalkorDB and returns the queries it ran. The agent decides the order; graph mode runs them in a fixed one.

  1. 01

    Index

    Clone your repositories into one graph: Python and TypeScript functions and the calls between them across repositories, every docs section and code example (Markdown, MDX or Sphinx), and the code each one mentions or calls — with every call checked against the signature it reaches.

  2. 02

    Trace the impact

    From each function the PR changed, walk back up to three callers, in any repository, to the docs that mention or run them.

    Evidence path: the chain from the changed function to the paragraph — the reason it is flagged, shown for every hit.

  3. 03

    Clear the rest

    Changed functions that no doc reaches within three calls are listed as cleared, with the grep a reviewer can run to double-check.

    Clearance: a proof of absence: the graph shows no path from the change to any doc, so you can skip it with confidence.

  4. 04

    Prove it

    Run each affected example at the commit before the PR and at the PR, in a sandbox. Passes before, fails after: the PR broke it. Fails both: it was already broken.

  5. 05

    Judge and fix

    Every affected section ends with a verdict. Edits are refused without a graph path, and come out as a git apply-able docs patch with the evidence per section.

    Verdict: stale (with the edit), ok, governed by a maintainer decision, or skipped — always with the reason.

  6. 06

    Remember

    Verdicts, example runs and maintainers' decisions are written back to the graph. The next PR reads them before judging.

    Verdict memory: a decision like "keep the old kwargs until 2.0" is cited instead of being re-flagged on every PR.

The question is a graph question

"Which paragraphs, in which repositories, can this change make false?" is reachability over call edges that cross repositories. It is one Cypher pattern, and on FalkorDB it answers in about a millisecond.

The graph model and every query
impact (excerpt)
MATCH (pr:PullRequest {url: $pr})<-[c:CHANGED_IN]-(s:Symbol)
WHERE c.kind <> 'added'
MATCH p = (s)<-[:CALLS*0..3]-(t:Symbol)<-[:MENTIONS|USES]-(d)
WHERE (d:DocSection OR d:CodeExample) AND d.status = 'live'
RETURN d.id, length(p) AS hops,
       [n IN nodes(p) | coalesce(n.qualname, n.id)] AS evidence
Use cases

Built for teams whose docs live apart from their code

SDK and client-library teams

Ship a client change without breaking the docs site

Your client, the SDK built on it and the docs site live in three repositories. One graph spans them, so a change in the client surfaces the pages in the other two.

On falkordb-py#276, 41 of the 43 reachable sections were in other repositories.

DevRel and docs teams

Know what a release falsified, most-read page first

Check every merged pull request, rank the affected sections by PageRank over your docs' own links, and ship one patch with the evidence for each edit.

Open-source maintainers

A docs-impact comment on every pull request

Each PR gets a comment listing the docs it can falsify, the path for each, and the changed functions no doc reaches. Graph mode needs no LLM key.

Use it viaGitHub Action
AI coding agents

Let Claude Code fix the docs in the same session as the code

Over MCP, your coding agent asks which docs depend on a function before changing it (docs_for_symbol), which examples its edits break before anything is pushed (check_changes), and produces the docs patch.

Anyone with docs today

Find the examples that are already broken, with no pull request

An audit checks every call in every example against the current code, across repositories, scores the docs and lists the public API no page covers. Weekly in the Action, with one issue kept up to date.

On FalkorDB's docs it finds client.create_constraint, a method FalkorDB doesn't have; on Flask's, as_view() without its required name.

Platform teams

One graph per organisation, many on one server

Each organisation gets its own graph on the same FalkorDB. Serve the API to your tools, or embed the library in your own pipeline.

A second graph from encode/httpx runs next to FalkorDB's on the same server.

Use it viaHTTP APILibrary

Read the use-case guides

Setup, commands and what to expect for each scenario.

Use cases in the docs
Why teams use it

Fewer broken tutorials, with receipts

Across every repository

Call edges are resolved across repositories through imports, re-exports, attribute types and return annotations.

Proof by execution

Examples run at both commits in a sandbox, so "this PR broke it" is a test result, not a guess.

Evidence for every paragraph

Each flagged section carries the path that reached it. No path, no edit: the tool refuses.

Proof of absence

Clearance lists changed functions no doc reaches, so reviewers know what they can skip.

Remembers decisions

Maintainer decisions and past verdicts are cited on the next PR instead of re-flagged.

Most-read pages first

PageRank over your docs' links orders the work, so the page readers land on gets fixed first.

With or without a model

Agent mode uses Claude or any Anthropic-compatible API; graph mode needs no key at all.

Every query in the open

Every result lists the Cypher it ran and how long it took. Nothing is hidden behind a score.

Integrations

Plug it in where your docs already break

One npm package, five ways in, and two ways to host it. Everything runs against your own FalkorDB.

One command from nothing to a checked pull request

No install and no Docker: the first check starts FalkorDB locally from a Python wheel and indexes the repository (--with adds a docs repository). Add ANTHROPIC_API_KEY for agent mode, or pass --no-agent.

Read the CLI guide
bash
$ npx -y staleproof check https://github.com/FalkorDB/falkordb-py/pull/262 --no-agent

# an organisation's repositories in one graph, then the docs patch
$ npx -y staleproof index FalkorDB/falkordb-py FalkorDB/GraphRAG-SDK FalkorDB/docs
$ npx -y staleproof check https://github.com/FalkorDB/falkordb-py/pull/262
$ npx -y staleproof patch https://github.com/FalkorDB/falkordb-py/pull/262
Compared

Why not grep, or a vector store?

Both find text. The question here is reachability, and whether the example still runs.

grep / code searchVector search over docsStaleproof
Finds docs that reach the change through other functionsNo — only the names you search forNo — similarity, not reachabilityYes — up to 3 call hops, in any repository
Proves a change broke an exampleNoNoYes — runs it before and after
Proves a change touches no docsNo — no match is not proofNoYes — clearance over the graph
Says why a paragraph is flaggedThe matching lineA similarity scoreThe evidence path
Remembers what maintainers decidedNoNoYes — decisions and verdicts on the graph
Noise on FalkorDB’s 4 checked PRs227 unrelated matches—Only sections the change reaches
FAQ

Questions developers ask first

Which languages does it understand?

Code: Python, TypeScript and JavaScript (tree-sitter), across repositories. Docs: Markdown, MDX and reStructuredText (Sphinx), in any repository. Python examples are run before and after a pull request; JavaScript and TypeScript examples are linked and checked statically, not run.

Do I need a pull request?

No. Audit any public repository to see which examples no longer fit the code today, npx -y staleproof check with no pull request checks your working tree before you push, and docs-for lists the docs that depend on a function before you change it.

Do I need an LLM API key?

No. Graph mode runs impact, clearance, PageRank ranking and up to three example runs with no model. Agent mode adds a model that reads each section and writes the verdicts and edits; it needs ANTHROPIC_API_KEY.

Which models does agent mode support?

Claude by default (claude-sonnet-5-5), or any Anthropic-compatible API through ANTHROPIC_BASE_URL. The live demo runs deepseek-v4-pro through DeepSeek's Anthropic-compatible endpoint.

Will it open pull requests on its own?

No. It proposes edits; patch prints a git apply-able diff, and patch --open-pr opens it in your fork only when you ask (--upstream targets the original repository).

Is running docs examples safe?

Each example runs with no inherited secrets, a temporary HOME and a timeout, and its outbound connections are refused except a disposable scratch FalkorDB. The install step that builds the repositories at the PR's commits gets only an allow-listed environment, so PR build code never sees your credentials. It is a guard, not a security boundary: for untrusted code, run it in a container.

Does my code leave my machine?

With the CLI or the GitHub Action, indexing, the graph and example runs stay wherever you run them, and private repositories work with a token. In agent mode, tool results (doc text, signatures, run output) go to the model provider you configure; graph mode sends nothing to a model. The hosted site and MCP server index public repositories only.

What does it cost?

Nothing: it is MIT licensed. You run FalkorDB (locally, in Docker, or on FalkorDB Cloud's free tier) and pay your model provider in agent mode.

Why does it need a graph database?

Impact is a variable-length path across repositories, clearance is the same pattern negated, decisions govern code transitively, and ranking is PageRank. Take FalkorDB out and it is a grep over one repository.

More in Troubleshooting and FAQ.

Check your next pull request before your readers do.

Add the workflow once; every pull request after that gets its docs impact, with proof.