Repository navigation
Releases: ajitheee/mendr
Release list
mendr v0.3.0-alpha
mendr v0.3.0-alpha — private-repo trust, the GitHub App, JavaScript, and safe migrations
This is the release external partners should use. It supersedes v0.2.4-alpha,
which predates the Windows/PowerShell encoding fixes, the report hardening, and
everything below — do not send testers to the old tag.
What this claims
Mendr is a trustworthy AI model-retirement scanner and early-warning system.
It is not "fully self-maintaining" yet, and does not claim to be. It detects
retiring AI model dependencies, explains the evidence, keeps migration decisions
under human control, and never touches your default branch.
Since v0.2.4-alpha
JavaScript support — .js/.jsx/.mjs/.cjs are scanned with the same
conservative guards as TypeScript (first-party SDK resolution, proxy/Azure
detection, examples/catalogs kept informational, test files separate). A
JavaScript-only repo now reports real exposure instead of "inconclusive".
The migration sandbox and human-approved PRs — mendr migrate proves a
model-id swap in an isolated sandbox (a baseline-relative type-check and build,
your tests, an optional eval) and emits a portable mendr-migration/v1
artifact. The GitHub Action opens one idempotent PR only when the migration
verifies, built from that artifact. Mendr never merges; a human approves. The
button is "Prepare migration for review," not "Fix automatically".
The Mendr GitHub App — the hosted half, kept out of the code path. Your CI
runs the scan and posts only the findings (paths, line numbers,
classifications, redacted snippets, hashes), authenticated by the run's OIDC
token. The App holds checks: write + metadata: read only; it never clones or
reads your code. One-click "Set up the audit" connects a repo without any new
App permission. A five-part finding page (possible cause → evidence → confidence
boundary → migration evidence → next action), "Open in GitHub", and "Rerun
audit".
The trust package — a cross-package schema-compat test that blocks
incompatible releases; a stored-data inventory (no tokens, no source code);
field-level AES-256-GCM encryption at rest for stored findings with key
rotation; retention, on-demand deletion, and hard cleanup on uninstall; an
append-only audit log that never holds findings or secrets; an incident-response
plan; and privacy/security pages specific to the real system.
Scanner and report hardening — deterministic exit codes (0 completed,
1 scanner failure, 2 usage error, 3 inconclusive; --fail-on-exposure to
gate), so a broken or inconclusive scan never reads as clean. Test files are now
scanned as test-only references — surfaced as informational, never migration
candidates. Reader tie-back proves an env-var config selector is read in code.
"Nothing uploaded" is enforced by an offline guard and a build-time network-block
test. Windows/PowerShell encoding, contradictory informational actions, and long
reports were fixed in the hardening leading up to this release.
Validation
- Root suite 72 files / 974 tests; App suite 11 files / 67 tests; both builds
clean. The offline guarantee and the scanner↔App schema compatibility are
tested on every build. - Registry: verified-only auto-apply, claim-checked, human-promoted; no AI ever
writes a production registry record without review.
Known boundaries (unchanged, stated honestly)
- Repository scanning proves a model appears in code, not that production
calls it. Runtime evidence (OTel / usage export / your read-only key) is
optional and strengthens confidence; it is never required. - Coverage is TS/TSX, JavaScript, Python and config, for OpenAI, Anthropic and
Google. Other languages are reported as unanalyzed, never silently clean. - The hosted App has not yet been deployed publicly; standing it up and creating
the GitHub App from/setupare operator steps.
Freeze
After publishing, freeze this tag. New defects go into the next alpha; do not
move or overwrite v0.3.0-alpha.
Registry snapshot (rolling)
Signed, dated snapshot of registries/llm-deprecations.json for pinned scanners. Replaced on every publish; the manifest names the exact source commit. Verify with the public key in src/registry/trustedKeys.ts. See REGISTRY-FRESHNESS.md.
mendr v0.2.4-alpha — repository audit hardening
mendr v0.2.4-alpha
Focused hardening release driven by the first audits run outside this
project: five public repositories (Browser Use, Mem0, CrewAI, Agno, LiteLLM),
run on Windows PowerShell with v0.2.3-alpha. Every Review finding was read in
the code; the defects that surfaced are fixed here and the same five
repositories were re-run.
This is an alpha. Nothing is applied and nothing is merged by any command.
v0.2.3-alpha is unchanged and remains valid for what it contained.
What the five repositories showed
| repository | Patch | Review before → after | informational before → after |
|---|---|---|---|
| browser-use | 0 | 2 → 2 | 28 → 28 |
| mem0 | 0 | 4 → 3 | 8 → 7 |
| crewAI | 0 | 3 → 3 | 58 → 58 |
| agno | 0 | 1 → 2 | 23 → 22 |
| litellm | 0 | 19 → 3 | 57 → 73 |
- Zero PATCH ELIGIBLE findings, before and after. None of these codebases
passes a literal model id to a first-party provider SDK request that resolves
in the same file; their requests go through their own wrappers, routers or
Azure. That is the correct answer, and it was confirmed by reading every
first-party request shape in the five repositories. - Every remaining Review finding is a genuine runtime default or a deployable
configuration value, each one confirmed in code: a tool's default image
model that reachesimages.generate, a provider class default that reaches
the SDK, a Helm chart's default model, a CLI default, a moderation hook's
default, a GitHub workflow'smodel:input. - Sixteen review candidates in LiteLLM were not selectors and are now
informational: cookbook and example-config directories, a form field's
placeholder text (120 rows from one schema file), a gitignored developer
config, a CI/QA fixture config carrying mock flags, model literals handed to
tokenizers, cost calculators and logging payloads, and a capability-probe
sentinel inside a parameter-mapping helper. - Thirteen genuine defaults in Mem0 and one in Agno had been filed as
informational and are now review candidates:this.model = config.model || "…",getattr(config, "model", "…"),os.environ.get("…_MODEL", "…"),
DEFAULT_CONFIG = { model: … }, amodels/-prefixed id, and anidfield on
an embedder class.
The claim from v0.2.3-alpha stands and is not widened: zero incorrect PATCH
ELIGIBLE findings across the current validation corpus, which is now the
twelve repositories of the previous release plus these five. It is not a claim
of zero false positives anywhere.
What changed
- Templates and fixtures.
.env.example,*.example.*,*.sample.*,
*-template.*,example_*.yaml,cookbook/,benchmarks/,notebooks/,
example_*/andsample_*/directories, JSON Schema files, a config the
repository's own.gitignorenames, and a config carrying mock-testing flags
are informational. A fake-key or fake-model entry inside a real config demotes
that entry only. - Router
model_listidiom.model_namebesidelitellm_paramsis the
client-facing alias; the siblingmodel:is the selector. UI metadata keys
(*_placeholder,*_hint,label,description) never select. - Never a selector: model ids passed to tokenizer or encoding helpers; local
model assignments, parameter defaults and lookup fallbacks inside pricing,
cost, tokenizer, logging, metrics ormap_*_paramshelpers; a response's own
modelfield being read back. A traced request in the same function still
wins over any of these name rules. - Genuine defaults are review candidates: assignment expressions
(this.model = …), lookup fallbacks on a model-named key,model:inside a
default-configuration object or dict (unless it is catalog-shaped),idon a
model/embedder class, andmodels/orpublishers/google/models/prefixed
ids. - Report. An informational reference now says "No migration action
required from this reference. Monitor provider status." — never "migrate
now". A registry date with no provider notice on file is printed as
"registry date YYYY-MM-DD (N d past), UNVERIFIED" and the next action asks
you to verify it with the provider; it is never called OVERDUE. Informational
references are collapsed to a count and the first five by default;
--verboselists them all and--jsonalways carries everything. Each
location in the JSON now carries its owndisposition
(patch/review/informational) beside the model-level decision. - Windows. The report is plain ASCII whenever stdout is not a terminal on
Windows (Tee-Object, a file, a variable) or the terminal is not known to be
UTF-8;--plainforces it anywhere andMENDR_UNICODE=1forces glyphs.
Progress lines go to stderr only when stderr is a terminal, so PowerShell 5.1
no longer wraps them in NativeCommandError;--quiet/--no-progress
silence them everywhere.
Acceptance gate (all met on the five repositories)
- Zero incorrect PATCH ELIGIBLE findings.
- Zero example, template or catalog files elevated to Review.
- Genuine runtime defaults remain Review, with evidence.
- No contradictory instructions; no unverified date presented as overdue.
- Clean Windows PowerShell output through Tee-Object, exit code 0, no errors.
- Byte-identical results across repeated runs.
Honest limits — unchanged from v0.2.3-alpha
- JavaScript, JSX, MJS and CJS are not analyzed. Disclosed on every run.
- Report comprehension has not been validated with external partners. The
five repositories above were run by this project, not by their maintainers.
That measurement is still the next milestone. - Live provider reconciliation is incomplete; the runtime connectors remain
optional preview. Do not connect an organization Admin key to evaluate mendr. - A configuration finding is a candidate, never a proven runtime control.
- Test and spec files are counted but their ids are not examined, by rule.
- Registry facts are never edited by a model. The
@YYYYMMDDVertex spelling of
Anthropic ids (claude-sonnet-4@20250514) is not yet normalized to the
-YYYYMMDDregistry form; it is on the registry list.
Install
npx github:ajitheee/mendr#v0.2.4-alpha audit .On Windows, if you pipe or capture the output, it is already plain ASCII.
--verbose prints every informational reference; --json carries everything.
For design partners
Run it on a repository you own and tell us six things: any wrong finding (file
and line); any retiring model you know you depend on that it missed; whether the
summary and next action were clear on first read; any installation friction;
whether you would let it run on a schedule; and what a migration PR would have
to prove before you merged it.
mendr v0.2.3-alpha — repository audit hardening
mendr v0.2.3-alpha
Hardening release. The audit engine shipped in v0.2.2-alpha was run against
twelve real third-party repositories, every Tier-A location was checked by
reading the code, and every claimed defect was adversarially refuted before it
counted. The result was not good enough to ship a migration on: 60 of the 62
Tier-A locations checked were wrong. This release fixes every confirmed root
cause and re-proves the same corpus.
This is an alpha. It is offered to design partners for evaluation, not as a
finished product. Nothing is applied and nothing is merged by any command in it.
The claim, stated exactly
Zero incorrect PATCH ELIGIBLE findings across the current validation corpus.
That sentence is deliberately narrow. It is a statement about twelve
repositories and one decision class, not a general claim of zero false
positives. Mendr has not been validated on your repository until you run it.
The validation corpus
Twelve public repositories, chosen for heavy first-party LLM usage across the
supported languages, scanned in full (37,685 source files, 60 s of total scan
time before hardening):
| repository | what it is | source scanned |
|---|---|---|
| mckaywrigley/chatbot-ui | Next.js chat app | 253 TS |
| danny-avila/LibreChat | chat platform (JS backend, TS client) | 2,350 TS |
| ChatGPTNextWeb/NextChat | Next.js chat app | 148 TS |
| Mintplex-Labs/anything-llm | JS/JSX application | 22 TS (98% JavaScript) |
| vercel/ai | AI SDK monorepo | 5,188 TS |
| lobehub/lobe-chat | TS monorepo | 9,795 TS |
| open-webui/open-webui | Python backend, Svelte frontend | 341 TS + Python |
| infiniflow/ragflow | Python + TS | 2,006 |
| langflow-ai/langflow | Python + TS monorepo | 4,017 |
| langchain-ai/langchain | Python monorepo | 1,764 Python |
| continuedev/continue | TS monorepo | 1,283 TS |
| langgenius/dify-official-plugins | Python plugins | 2,107 Python |
Method: an independent boundary-aware text search located every registry model
id in every file, so the audit's output could be compared against ground truth
rather than against itself. One adjudicator per repository read the code behind
every Tier-A location and every unexplained occurrence in a supported file; two
independent skeptics per repository then tried to refute each claimed defect.
Only defects that survived both are in VALIDATION-2026-09-03.md.
What the corpus shows now
- All 12 previously identified incorrect PATCH ELIGIBLE locations are
eliminated. They were: LibreChatEditMessage.tsx:138; NextChat
app/constant.ts:424; vercel/aitool-order.ts:29and
anthropic-provider.test-d.ts:7,10,13; lobe-chatconst/src/llm.ts:8and
business-const/src/index.ts:7; open-webuiutils/index.ts:859; langchain
evaluation/loading.py:168; continuellms/llm.ts:57and
smoke-api-helpers.ts:53. Nine are now Tier-B review candidates, one is
informational (a mocked response body in a sample), and four are no longer
reported (type tests and a smoke-test helper are test support). The 183
further vercel/ai locations underexamples/are informational. - Exactly one Tier-A location remains in the corpus, chatbot-ui
app/api/command/route.ts:24, achat.completions.createcall on a
first-party OpenAI client constructed in the same file. It was manually
confirmed correct by the reviewers before and after hardening. - Four real defaults the previous release had filed as "no selector" are now
review candidates: open-webuiimages.py:205, langchain
chat_models/base.py:731andllms/base.py:176, lobe-chat
generate/image.ts:10. - 38 provider-prefixed selectors (
openai/gpt-5-nano,google/gemini-2.0-flash)
that were invisible are reported. - vercel/ai's conclusion changed from EXPOSURE DETECTED to NO EXPOSURE IN
COMPLETED SURFACES, which is the truth about itspackages/. anything-llm's
changed from NO EXPOSURE to INCONCLUSIVE, because 98% of its source is
JavaScript that mendr does not read.
Expect the same shift on your repository: fewer Tier-A findings and more
Tier-B review candidates than v0.2.2-alpha produced. That is the intended
direction. Uncertainty always reduces authority.
What changed
Full detail is in CHANGELOG.md. In one paragraph: the TypeScript scanner now
applies the same guards the Python scanner already had. A model argument earns
Tier A only when its call resolves, in the same file, to a first-party provider
SDK client with no proxy or Azure override, inside a function, with a matching
endpoint family. Model-named constants are judged by where they are used.
Example and sample trees are informational. LangChain factories are wrapper
surfaces. Real defaults are review candidates. Provider-prefixed ids are found.
"Verified" in the report is keyed on the tier and nothing else; patch
eligibility is stated per line; a repository mendr mostly cannot read concludes
inconclusive; skipped test files and unanalyzed languages are disclosed.
Honest limits — read this before evaluating
- JavaScript, JSX, MJS and CJS are not analyzed. This is the single largest
coverage gap: 2,947 JavaScript-family files across 11 of the 12 validation
repositories, including LibreChat's only production call to a model retiring
on 2026-10-23. Every run names the unanalyzed languages in its coverage
report. A repository that is mostly JavaScript concludes INCONCLUSIVE. - Report comprehension has not been validated with external partners. Every
clarity finding so far is a reviewer's inference from the text. Whether an
engineer opens the right file, runsfix-llmonly on the correct lines, and
ignores the fixture rows is unmeasured until people outside this project run
it. That measurement is the next milestone. - Live provider reconciliation has not been completed. The OpenAI and
Anthropic usage connectors remain optional preview functionality. Their
request and cost figures have not been validated against a non-empty
organization's provider dashboard. Do not rely on them as measured spend or
measured usage; do not connect an organization Admin key to evaluate mendr.
Repository auditing needs no key and is the product. - A configuration finding is a candidate, never a proven runtime control: reader
tie-back analysis does not exist yet. - Test and spec files are counted but their model ids are not examined, by rule.
The count is printed in every coverage report. - Absence from a runtime source is not proof that a model is unused. Provider
usage reads, where a customer chooses to connect one, cover chat/completions
only; Anthropic's usage API reports no request counts; Google/Vertex is not
supported. - mendr never claims a general "clean" result. The four possible conclusions are
exposure_detected,no_exposure_in_completed_surfaces,inconclusiveand
audit_failed; a skipped or failed surface stays visible and blocks any
no-exposure claim. - Three ids reported missing from the registry during validation
(gemini-1.0-pro-vision-latest,text-embedding-ada-002,
text-embedding-004) are not added here; registry facts go through the
registry process, never a silent edit. - Nothing is ever applied or merged. A PATCH ELIGIBLE decision means a reviewed
PR is possible, not that a change was made.
Install
npx github:ajitheee/mendr#v0.2.3-alpha audit .To keep one GitHub issue current per repository (contents: read,
issues: write, nothing else):
npx github:ajitheee/mendr#v0.2.3-alpha audit . --installFor design partners
Run the audit on a real repository and tell us six things:
- Any finding that is wrong, with the file and line.
- Any retiring model you know you depend on that the report missed.
- Whether the summary and the next action were clear on first read.
- Any friction installing or running it.
- Whether you would let it run on a schedule.
- What you would want a migration PR to prove before you merged it.
Those answers decide what gets built next. The classifier stays as it is unless
a partner audit exposes a real defect.
Version note
v0.2.2-alpha remains valid for what it contained. This release supersedes it
for every purpose; the classification changes above mean the two releases will
tier the same repository differently, on purpose.
Mendr v0.2.2-alpha — Repository-first AI dependency audit
mendr v0.2.2-alpha
Why not
v0.2.0-alpha? That tag was published on 2026-08-27 against a
commit that predates theauditcommand. Re-pointing a published tag would
silently change the code under anyone who pinned it — the exact hazard this
tool warns about — so this ships asv0.2.2-alphainstead.
This is an alpha. It is offered to design partners for evaluation, not as a
stable release. v0.1.0 remains the stable line (fix-llm, watch).
What this release is
Connect your repository and mendr locates retiring AI dependencies. If you
choose to connect runtime evidence, mendr can also verify which ones are live.
No provider key is required. The entry requirement is a repository.
mendr audit .It scans TypeScript, TSX, Python and supported configuration files, finds
provider call sites and model identifiers, joins them to the deprecation
registry, and reports each finding with its location, retirement deadline,
migration evidence, and a decision:
Deprecated model dependency located
Model: gpt-4
Location: src/ai/client.ts:42 — code call site (model argument)
Retirement: deprecated — 54d left (2026-10-23)
Migration evidence: gpt-4o [registry: verified] (evidence only — not applied here)
Production usage: not measured
Reader tie-back: not proven
Decision: REVIEW REQUIRED
Status: No change applied
GitHub-native report
mendr audit . --installScaffolds a workflow that runs in your CI and maintains one issue per
repository — created on the first run, updated in place afterwards, grouping
findings into new / continuing / resolved, with the exact scanned commit and a
coverage matrix. Findings have stable semantic identities, so a reformat does not
churn the issue.
Permissions requested: contents: read and issues: write. Nothing else. The
default branch cannot be modified, no PR is opened, and nothing is ever merged.
Optional runtime evidence — four ways, none required
- OpenTelemetry —
--runtime otel.json --runtime-source otel - Your own sanitized usage export —
--runtime export.csv - Your own read-only provider key, kept in your CI/secret manager
- Gateway / Sentry / Datadog / structured app logs —
--runtime logs.csv --runtime-source gateway_logs
mendr reads only provider, model, service, environment, timestamp, request
outcome and volume. Never prompts, never responses.
Honest limits — read this before evaluating
- Live provider reconciliation has NOT been completed. The OpenAI and
Anthropic connectors are available as optional preview functionality, but their
request and cost figures have not yet been validated against a non-empty
organization's provider dashboard. Do not rely on them as measured spend or
measured usage. We are not claiming validated live-usage or spending
measurement, and this release should not be evaluated on that basis.
(The connectors were repaired against the current provider documentation in
this release — including an Anthropic endpoint path that previously returned
zero rows for every request — but repaired-against-docs is not the same as
reconciled-against-a-real-account.) - A config finding is a candidate, not a proven control. Reader tie-back
analysis does not exist yet, so mendr says "candidate selector" and keeps every
config finding review-only. - Absence of runtime evidence is not proof a model is unused. It only means
liveness is unknown, or that the connected source did not record it. - mendr never claims a general "clean" result. The four possible conclusions
areexposure_detected,no_exposure_in_completed_surfaces,inconclusive,
andaudit_failed. A skipped or failed surface stays visible and blocks any
no-exposure claim. - A located call site is a verified direct provider call site, not proof that
production runs it. Source analysis proves the call exists in the code; only
runtime evidence can show it executes. The report says "Production usage was not
measured" whenever no runtime source is connected. patchmeans ELIGIBLE, not applied. The human report renders it as
PATCH ELIGIBLE/Status: No change applied; the JSON carries
patchEligibleand an always-falsepatchApplied.- Nothing is applied. A
patchdecision means a reviewed PR is possible for a
verified Tier-A code call site — not that a change was made. There is no
auto-merge, and PR generation is a separate, gated capability. - Language coverage is TypeScript, TSX and Python. Other languages are not
analyzed, and the coverage report says so. - Provider usage reads cover chat/completions only (not embeddings, images,
audio, batch, fine-tuning). Anthropic's usage API reports no request counts.
Google/Vertex is not supported.
For design partners
One command, no credentials, on a repository you care about:
npx github:ajitheee/mendr#v0.2.2-alpha audit .What we would like to learn:
- Did it find anything you did not already know about?
- Was any finding wrong — and specifically, was anything called a call site
that is not one? - Did it MISS a retiring model you know is in the codebase?
- Is the report readable enough to act on without asking us?
- Would you connect a runtime source, and which of the four would you accept?
Everything runs locally. Nothing is uploaded, and no key is ever sent to us.
v0.2.0-alpha — AI dependency audit (MEASURE + LOCATE)
v0.2.0-alpha — AI dependency audit (MEASURE + LOCATE)
Prerelease. Adds the read-only audit pair — usage-audit (MEASURE) and
config-scan (LOCATE) — on top of the stable v0.1.0 (fix-llm, watch). The
v0.1.0 install instructions remain the recommended path until v0.2.0-alpha is
verified from a fresh installation.
What's new
mendr usage-audit [provider]— per-model usage/spend from a provider's
read-only usage API, joined to the deprecation registry: which deprecated
models actually consume requests and money, with deadlines. Fixture path for
demo/test; live OpenAI/Anthropic via a read-only Admin key in an env var.mendr config-scan [path]— locate deprecated ids in config/IaC files,
separating live selectors (Tier B) from catalog definitions and references
(Tier C). Report-only.
Test evidence
- Build:
npm run build(tsc) — PASS. - Suite: 664 tests across 51 files — PASS (625 baseline + 17 config + 7 recon
- 15 positive-path render tests for the MEASURE/LOCATE reports).
- Registry integrity:
node scripts/validate-registry.mjs— 0 violations. - CI: GitHub Actions
build-and-test(ubuntu, node 22) — GREEN. Landing the
suite on Linux CI surfaced a pre-existing eval-gate bug: on POSIX the deadline
only signalled the shell, so ash -cthat forks the program orphaned it and
the run hung. Fixed by group-killing (detached+ negative-pid SIGKILL); the
timeout still reportsinconclusive, never a behavioralfail.
Real-repository validation — dify-official-plugins
- Scanned commit:
c62e9d4771e6a46296547c5a08e9b935f2fbff44 - Scale: 3,845 config files scanned, 75 deprecated ids found.
- Incorrect Tier B "selectors to change": 148 → 0 after the catalog-definition,
provider-surface, and verified-gating fixes. Every one of Dify's 75 ids is now a
Tier C catalog reference, which is correct — Dify defines models in catalogs, it
does not select them at a call site.
Known limitations (alpha)
config-scan: report-only (no fix writer); leaf key not full nested key path;
no override-precedence resolution; non-direct surfaces (Bedrock/Vertex/Azure/
proxy) → provider-ambiguous, no direct replacement; model-definition catalogs
are Tier C.usage-audit: chat/completions usage only; Google/Vertex not supported; the
live fetch follows the documented usage API and should be verified against a
live account; an empty live result reportsno_data/inconclusive, not clean.- MEASURE does not LOCATE; LOCATE does not verify behavioral safety. The report is
the deliverable — a human decides.
Fresh-install verification
Before promoting v0.2.0-alpha over the v0.1.0 instructions, verify from a clean
install:
npx github:ajitheee/mendr#v0.2.0-alpha config-scan <a-repo>
npx github:ajitheee/mendr#v0.2.0-alpha usage-audit --fixture examples/usage-fixture.example.json