mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
* docs(free-tiers): correct the headline to the 1.37B the catalog actually computes
The 2026-06-17 honesty correction landed 1.54B, but v3.8.42 reclassified longcat
from a 150M/mo recurring grant to a one-time 10M signup credit and the doc was
never resynced. Verified against computeFreeModelTotals() at every release tag
from 3.8.13 to HEAD: no free provider was lost by mistake.
* feat(quality): gate the free-tier headline against the live catalog
The README headlined ~1.6B free tokens/mo for seven releases after the catalog had
already been corrected down to 1.37B. No gate watched that number, so the drift was
invisible — check:docs-counts only covered providers, locales, executors, strategies,
oauth, a2a skills and cloud agents.
Adds a STRICT check that runs computeFreeModelTotals() (the same function behind
/api/free-tier/summary) and fails the build when README.md or FREE_TIERS.md publish a
headline that no longer rounds to it. Degrades to a skip if tsx is unavailable rather
than going falsely red.
The extractor is a whitelist: the theoretical ceiling (~10B), the historical ~1.94B and
per-model rows (~1.00B) are legitimate figures that must never trip the gate.
Also adds the biweekly-audit note under the README headline, so readers know the number
moves both ways and is what the catalog computes rather than a rounded-up best case.
* feat(quality): extend the counts gate to engines, MCP tools/scopes and CLI tools
The v3.8.49 audit found four more numbers that had silently drifted, all invisible to
CI because check:docs-counts only watched providers/locales/executors/strategies/oauth/
a2a/cloud-agents: 10->11 compression engines, 94->104 MCP tools, 30->31 scopes,
26->33 CLI tools.
Adds a generic makeNumberClaimValidator that reads every fact in ONE tsx subprocess via
the same functions the app serves (ENGINE_IDS, countUniqueMcpTools, the live scope union,
CLI_TOOLS) — never a hardcoded copy — with DATA_DIR redirected to a throwaway dir so
importing the MCP tool modules can't touch the operator's SQLite. Each check declares a
skip pattern so legitimate non-aggregate figures never trip it: per-module tool counts
('Memory tool definitions (3 tools)') and the CLI catalog total sitting next to the MCP
total. Degrades to a skip when tsx is unavailable rather than a false red.
7 new unit tests (all pass) covering the exact stale values this audit found and proving
per-module counts are ignored.
* docs(diagrams): sync the animated cards and mermaid sources to the audited v3.8.49 numbers
The README text was fixed in #7795 but the SVG cards and mermaid sources kept the
old numbers baked in — exactly the drift the readers see first.
- compression-pipeline.svg: 10 -> 11 engine cells (Omniglyph added as #8, matching
the README alt text), re-spaced 51px cells, highlight cascade re-timed, the
Caveman kill-dot repositioned inside its cell, default-stack bracket recentered
- free-tier-budget.svg: bar and grid rebuilt from computeFreeModelTotals() — 21 -> 19
countable pools (LongCat-2.0 moved to one-time credit, Inclusion provider removed),
huggingchat entry is now ERNIE 4.5 VL, kiro shows Claude Sonnet 4.5, signup credits
~616M -> ~626M (+longcat 10M pill), aria said 'about 1.6 billion' -> 1.4/2.0,
lower sections shifted up 30px (viewBox 872 -> 842)
- promise-pillars.svg: 26 -> 33 coding agents
- mcp-tools-94.mmd -> mcp-tools-104.mmd: real per-collection unique contributions
(42 base + memory 3 + skill 4 + githubSkill 3 + pool 6 + gamification 8 + plugin 8
+ notion 6 + obsidian 22 + compression 2), exported SVG regenerated, zh-CN ref synced
- request-pipeline.mmd: 17 -> 18 strategies, exported SVG regenerated
- README free-tier alt + docs/diagrams/README.md synced to the same numbers
Both edited cards pass validate-svg.sh and were render-verified at 4 timestamps
(animation runs; first frame is the finished composition).
* docs(env): register the 4 env vars missing from the .env.example contract (base-red unblock)
FREE_PROXY_AUTO_SYNC_ENABLED / FREE_PROXY_AUTO_SYNC_INTERVAL_MS (scheduler.ts) and
MITM_ROOT_CA_ENABLED / MITM_CERT_MODE (mitm manager/server, #6684) landed on
release/v3.8.49 without their .env.example + ENVIRONMENT.md entries, turning the
docs-gates job red for every PR on the branch. Documented with their real defaults
and the set-by-manager caveat for MITM_CERT_MODE.
* fix(dashboard): narrow the Codex session ParseResult with an equality check (base-red unblock)
#7725 landed 'if (!result.ok)' in OAuthModal — under this repo's strict:false,
tsc 6 only narrows a discriminated union on the equality form, so the negation
raised TS2339 (Property 'error' does not exist on ParseResult) and turned the
dashboard-typecheck gate red for every PR on release/v3.8.49. Runtime semantics
are identical (ok is a strict boolean).
Also ratchets the frozen baseline down 260 -> 259: the real fix here plus 3
baselined errors that other merges already fixed (CostOverviewTab TS2304,
SidebarTab TS2322, FreePoolTab TS2304). Baseline diff is deletions-only.
* fix(dashboard): keep OAuthModal within the frozen file-size cap
The narrowing comment pushed the file to 1032 > 1030 frozen; the rationale lives
in the previous commit message and the dashboard-typecheck gate itself guards the
'=== false' form from being refactored back to '!result.ok'.
* test(providers): align the grok-web credential assertion with the #7567 hint (base-red unblock)
#7713 added hintKey/hintFallback (proactive cf_clearance/User-Agent guidance) to the
grok-web web-session metadata without touching this test's deepEqual, turning unit
shard 2/4 red for every PR on release/v3.8.49. Rewritten in the same contract-only
style the file already uses for lmarena: structural fields stay strictly asserted,
the hint asserts key + intent (cf_clearance / User-Agent) without freezing operator
copy. Net stronger than before — the old assertion never checked the hint at all.
* test(golden): regenerate translate-path snapshot for the notion-web endpoint move (base-red unblock)
#7768 switched notion-web to app.notion.com without regenerating the golden,
turning unit shard 3/4 red for every PR on release/v3.8.49. Two-line regen,
reflects the deliberate production change.
199 lines
7.6 KiB
TypeScript
199 lines
7.6 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert";
|
|
import { execFileSync } from "node:child_process";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import {
|
|
parseProviderTotal,
|
|
tallyDrift,
|
|
readProviderTotal,
|
|
countLocales,
|
|
} from "../../scripts/check/check-docs-counts-sync.mjs";
|
|
|
|
// Explicit types for the .mjs exports — keep the test at 0 no-explicit-any warnings.
|
|
const parse = parseProviderTotal as (text: string) => number;
|
|
const tally = tallyDrift as (
|
|
checks: {
|
|
label: string;
|
|
actual: number;
|
|
docKey: string;
|
|
strict: boolean;
|
|
files: string[];
|
|
}[],
|
|
getContent: (file: string) => string | null
|
|
) => { strict: number; soft: number; lines: string[] };
|
|
const readTotal = readProviderTotal as () => number;
|
|
const locales = countLocales as () => number;
|
|
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const GATE = path.resolve(here, "../../scripts/check/check-docs-counts-sync.mjs");
|
|
|
|
// --- parseProviderTotal (pure) -------------------------------------------------------
|
|
|
|
test("parses the canonical provider total from the auto-generated catalog text", () => {
|
|
assert.equal(parse("Total providers: **226**. See category breakdown below."), 226);
|
|
});
|
|
|
|
test("returns 0 when no total marker is present", () => {
|
|
assert.equal(parse("# Provider Reference\n\nNo total here."), 0);
|
|
assert.equal(parse(""), 0);
|
|
});
|
|
|
|
// --- tallyDrift (pure) ---------------------------------------------------------------
|
|
|
|
const strictCheck = {
|
|
label: "Provider count",
|
|
actual: 226,
|
|
docKey: "providers",
|
|
strict: true,
|
|
files: ["README.md", "AGENTS.md"],
|
|
};
|
|
|
|
test("no drift when every file mentions the real count", () => {
|
|
const { strict, soft } = tally([strictCheck], () => "we have 226 providers");
|
|
assert.equal(strict, 0);
|
|
assert.equal(soft, 0);
|
|
});
|
|
|
|
test("STRICT drift is counted when a file omits the real count", () => {
|
|
const { strict, soft } = tally([strictCheck], (f) =>
|
|
f === "README.md" ? "we have 226 providers" : "we have 177 providers"
|
|
);
|
|
assert.equal(strict, 1, "AGENTS.md (177) should register one strict drift");
|
|
assert.equal(soft, 0);
|
|
});
|
|
|
|
test("SOFT drift does not count as strict", () => {
|
|
const softCheck = { ...strictCheck, strict: false };
|
|
const { strict, soft } = tally([softCheck], () => "no number here");
|
|
assert.equal(strict, 0);
|
|
assert.equal(soft, 2, "both files miss → two soft drifts");
|
|
});
|
|
|
|
test("a check with actual=0 is skipped (source count undetermined)", () => {
|
|
const zero = { ...strictCheck, actual: 0 };
|
|
const { strict, soft } = tally([zero], () => null);
|
|
assert.equal(strict, 0);
|
|
assert.equal(soft, 0);
|
|
});
|
|
|
|
test("a missing file (null content) registers drift, not a crash", () => {
|
|
const { strict } = tally([strictCheck], () => null);
|
|
assert.equal(strict, 2);
|
|
});
|
|
|
|
// --- live source readers (smoke) -----------------------------------------------------
|
|
|
|
test("readProviderTotal reads a real, positive total from the catalog", () => {
|
|
assert.ok(readTotal() > 100, "provider catalog total should be > 100");
|
|
});
|
|
|
|
test("countLocales reads a real, positive locale count from config/i18n.json", () => {
|
|
assert.ok(locales() >= 40, "i18n config should define at least 40 locales");
|
|
});
|
|
|
|
// --- live gate smoke -----------------------------------------------------------------
|
|
|
|
test("the gate exits 0 against the current (synced) repo state", () => {
|
|
// Throws if exit code is non-zero; current docs are synced so this must pass.
|
|
assert.doesNotThrow(() => execFileSync("node", [GATE], { encoding: "utf8", stdio: "pipe" }));
|
|
});
|
|
|
|
// --- Free-tier headline gate ------------------------------------------------
|
|
// Regression guard for the drift found in the v3.8.49 README audit: the README
|
|
// headlined ~1.6B for seven releases after the catalog had already been corrected
|
|
// down to 1.37B, because no gate watched that number.
|
|
import {
|
|
checkFreeTierHeadline,
|
|
extractHeadlineClaims,
|
|
} from "../../scripts/check/check-docs-counts-sync.mjs";
|
|
|
|
const checkHeadline = checkFreeTierHeadline as (
|
|
content: string,
|
|
totals: { s: number; m: number; p: number }
|
|
) => { ok: boolean; detail: string };
|
|
const extractClaims = extractHeadlineClaims as (
|
|
content: string
|
|
) => { value: number; text: string }[];
|
|
|
|
const TOTALS = { s: 1_371_725_000, m: 1_998_225_000, p: 39 };
|
|
|
|
test("free-tier gate accepts a headline that rounds to the live catalog", () => {
|
|
assert.equal(checkHeadline("~1.4B free tokens per month", TOTALS).ok, true);
|
|
assert.equal(checkHeadline("up to ~2.0B in the first month", TOTALS).ok, true);
|
|
});
|
|
|
|
test("free-tier gate rejects the stale headlines this audit found", () => {
|
|
for (const stale of ["~1.6B free tokens/mo", "~1.54B free tokens per month"]) {
|
|
const r = checkHeadline(stale, TOTALS);
|
|
assert.equal(r.ok, false, `expected ${stale} to be rejected`);
|
|
assert.match(r.detail, /live catalog computes/);
|
|
}
|
|
assert.equal(checkHeadline("up to ~2.1B in the first month", TOTALS).ok, false);
|
|
});
|
|
|
|
test("free-tier gate ignores non-headline figures", () => {
|
|
// The theoretical ceiling, the historical value and per-model rows are legitimate
|
|
// and must never trip the gate — that is why the extractor is a whitelist.
|
|
const noise =
|
|
"counting every rate limit 24/7 would read ~10B; not published. " +
|
|
"Why this dropped from the previous ~1.94B. | `mistral` | recurring | ~1.00B |";
|
|
assert.deepEqual(extractClaims(noise), []);
|
|
assert.equal(checkHeadline(noise, TOTALS).ok, true);
|
|
});
|
|
|
|
test("free-tier gate passes when a file carries no headline at all", () => {
|
|
assert.equal(checkHeadline("no figures here", TOTALS).ok, true);
|
|
});
|
|
|
|
// --- Generic numeric-claim gate (engines / MCP tools / scopes / CLI) --------
|
|
// Extends the same drift guard to the counts that silently drifted in v3.8.49:
|
|
// 10→11 engines, 94→104 MCP tools, 30→31 scopes, 26→33 CLI tools.
|
|
import { makeNumberClaimValidator } from "../../scripts/check/check-docs-counts-sync.mjs";
|
|
|
|
const makeValidator = makeNumberClaimValidator as (
|
|
expected: number,
|
|
opts: { what: string; pattern: RegExp; skipBefore?: RegExp; skipAfter?: RegExp }
|
|
) => (content: string) => { ok: boolean; detail: string };
|
|
|
|
test("MCP-tools gate accepts the aggregate and rejects a stale one", () => {
|
|
const v = makeValidator(104, {
|
|
what: "MCP tools",
|
|
pattern: /(\d+) tools/gi,
|
|
skipBefore: /(tools?|definitions?)\s*\(\s*$/i,
|
|
skipAfter: /^\s*\(\d+ CLI/,
|
|
});
|
|
assert.equal(v("MCP Server (104 tools)").ok, true);
|
|
assert.equal(v("with 104 tools total").ok, true);
|
|
assert.equal(v("MCP Server (94 tools)").ok, false);
|
|
});
|
|
|
|
test("MCP-tools gate ignores per-module counts and the CLI catalog total", () => {
|
|
const v = makeValidator(104, {
|
|
what: "MCP tools",
|
|
pattern: /(\d+) tools/gi,
|
|
skipBefore: /(tools?|definitions?)\s*\(\s*$/i,
|
|
skipAfter: /^\s*\(\d+ CLI/,
|
|
});
|
|
// "Memory tool definitions (3 tools)" and "33 tools (25 CLI Code's)" are not the MCP total
|
|
assert.equal(v("Memory tool definitions (3 tools)").ok, true);
|
|
assert.equal(v("management tools (8 tools)").ok, true);
|
|
assert.equal(v("all 33 tools (25 CLI Code's + 8 CLI Agents)").ok, true);
|
|
});
|
|
|
|
test("compression-engines and CLI-tools gates catch their v3.8.49 drift", () => {
|
|
const eng = makeValidator(11, {
|
|
what: "compression engines",
|
|
pattern: /(\d+)[-\s](?:engine stack|composable engines|stacked engines)/gi,
|
|
});
|
|
assert.equal(eng("11-engine stack").ok, true);
|
|
assert.equal(eng("10-engine stack").ok, false);
|
|
|
|
const cli = makeValidator(33, {
|
|
what: "CLI tools",
|
|
pattern: /(\d+) tools(?=\s*\(\d+ CLI)/gi,
|
|
});
|
|
assert.equal(cli("all 33 tools (25 CLI Code's)").ok, true);
|
|
assert.equal(cli("all 26 tools (25 CLI Code's)").ok, false);
|
|
});
|