Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
a2490cb
chore(release): open v3.8.32 development cycle
diegosouzapw Jun 20, 2026
3cd1899
fix(cli): non-interactive confirm() + document the contexts workflow …
diegosouzapw Jun 20, 2026
fc57530
fix(sse): configurable round-robin combo queue depth for faster failo…
diegosouzapw Jun 20, 2026
4287a12
fix(guardrails): tighten system_prompt_leak heuristic to stop agent-t…
diegosouzapw Jun 20, 2026
51642dc
fix(translator): drop orphan tool results on the Claude->OpenAI reque…
diegosouzapw Jun 20, 2026
eb48e4d
feat(mcp): register web-session pool observability tools (#3368) (#4399)
diegosouzapw Jun 20, 2026
7309214
refactor(chatCore): extract resolveChatCoreRequestSetup (first setup-…
diegosouzapw Jun 20, 2026
d6c63c7
fix(sse): parse the chat request body once by threading it from the r…
diegosouzapw Jun 20, 2026
1a9d29a
fix(providers): register Firecrawl and Jina Reader API-key validators…
diegosouzapw Jun 20, 2026
23f3863
fix(providers): serve api.airforce live /models catalog instead of st…
diegosouzapw Jun 20, 2026
13288e2
feat(providers): expand openai/gemini direct registries with first-cl…
diegosouzapw Jun 20, 2026
d215079
fix(translator): inject placeholder message when Responses API input[…
diegosouzapw Jun 20, 2026
285608c
chore(quality): reconcile server.ts file-size baseline 1468->1509 (#3…
diegosouzapw Jun 20, 2026
7c56f47
chore: rebase PR #3455 onto release/v3.8.32 (autonomous monitor cycle…
oyi77 Jun 20, 2026
63095a5
docs(remote-mode): add a copy-paste end-to-end verification example (…
diegosouzapw Jun 20, 2026
3ad2043
feat(providers): web-cookie + no-auth provider validation with AUTH_0…
oyi77 Jun 20, 2026
95e6522
feat(compression): unified config panel — single source for engine on…
diegosouzapw Jun 20, 2026
9052c5a
fix(cli): non-interactive-safe prompts + singular `context` alias (#4…
diegosouzapw Jun 20, 2026
7f62e50
fix(catalog): add OpenAI gpt-4.1-mini/nano + o3-mini/o4-mini pricing …
diegosouzapw Jun 20, 2026
9d71670
fix(sse): use crypto-secure RNG for combo/deck load-balancing selecti…
diegosouzapw Jun 20, 2026
bda88db
fix(embeddings): forward output dimensions to Gemini (#4449)
diegosouzapw Jun 20, 2026
0225a0a
fix(translator): sanitize Read tool args from non-Anthropic models (#…
diegosouzapw Jun 20, 2026
84fd187
fix(usage): reuse Gemini CLI project ID for quota checks (#4454)
diegosouzapw Jun 20, 2026
3b25297
fix(pricing): align Claude Code (cc) model pricing with Anthropic (#4…
diegosouzapw Jun 20, 2026
53a3b59
fix(dashboard): surface manual config CTA when Claude CLI auto-detect…
diegosouzapw Jun 20, 2026
0403f29
fix(executors): granular reasoning_effort handling for Claude models …
diegosouzapw Jun 20, 2026
9708fed
fix(translator): strip Claude output_config before MiniMax (#4448)
diegosouzapw Jun 20, 2026
ce3909b
fix(executors): sanitize Anthropic-shape content for Copilot /chat/co…
diegosouzapw Jun 20, 2026
7abace5
feat(translator): OpenAI SSE → Gemini SSE conversion for /v1beta/mode…
diegosouzapw Jun 20, 2026
86fc1e4
fix(sse): refactor stall detection to reduce false positives on slow …
diegosouzapw Jun 20, 2026
3025a2a
feat(oauth): import accounts from CLIProxyAPI auth files (port from 9…
diegosouzapw Jun 20, 2026
0d673f7
fix(translator): forward OpenAI audio input to Gemini/Antigravity (po…
diegosouzapw Jun 20, 2026
b0e9cd4
fix(combo): model lockout honors long upstream quota reset (#4429)
diegosouzapw Jun 20, 2026
ee494d2
fix(antigravity): strip Anthropic-only output_config from Cloud Code …
diegosouzapw Jun 20, 2026
8284650
feat(routing): opt-in echo of requested alias/combo name in response …
diegosouzapw Jun 20, 2026
12bfca6
chore(quality): reconcile file-size + complexity baselines after /rev…
diegosouzapw Jun 20, 2026
1e72643
fix(providers): generic web-cookie validator must not shadow per-prov…
diegosouzapw Jun 21, 2026
92afce6
fix(compression): RTK compresses Anthropic-shape tool_result blocks (…
diegosouzapw Jun 21, 2026
b4dbf7b
fix(executors): synthesize x-opencode-request for custom-named OpenCo…
diegosouzapw Jun 21, 2026
0c47d13
fix(dashboard): resume request-log auto-refresh by gating the ghost i…
diegosouzapw Jun 21, 2026
1e2ef81
chore(release): v3.8.32 — 2026-06-21
diegosouzapw Jun 21, 2026
f4ffbbb
chore(quality): rebaseline deadExports 340->343 (v3.8.32 cycle drift)
diegosouzapw Jun 21, 2026
a7ebf0c
fix(sse): don't bypass web-search fallback for Anthropic-compatible p…
diegosouzapw Jun 21, 2026
3b69960
fix(sse): unbiased crypto.randomInt for combo selection (follow-up to…
diegosouzapw Jun 21, 2026
e95fab8
refactor(chatCore): extrai resolvers de service-tier do Codex para le…
diegosouzapw Jun 21, 2026
131474d
fix(usage): keep Kiro overage quotas routable (#4471)
CleanDev-Fix Jun 21, 2026
6c8c87d
feat(combo): per-combo stickyRoundRobinLimit override on the combos p…
adivekar-utexas Jun 21, 2026
3e980a0
fix(command-code): pass reasoning/thinking fields through to params (…
adivekar-utexas Jun 21, 2026
2f17be3
perf(dashboard): lazy-load usage analytics charts (#4466)
KooshaPari Jun 21, 2026
147b6a3
feat(cluster): add memory + bifrost opt-in profiles (#3932 follow-up)…
KooshaPari Jun 21, 2026
66909a8
fix(cli): omniroute update revalidates npm cache with --prefer-online…
diegosouzapw Jun 21, 2026
c3fd2b9
feat(usage): support quota fetch for kimi-coding-apikey (#4435)
janeza2 Jun 21, 2026
52e6a8b
fix: model-aware supportsRedactedThinking for mixed-format providers …
TF0rd Jun 21, 2026
404d9b3
perf(kiro): cut request-completion hot-path CPU + cap DB-lock event-l…
artickc Jun 21, 2026
620da16
feat(models): add opt-in low-noise /v1/models catalog mode (#4427)
Rahulsharma0810 Jun 21, 2026
fca66c6
docs(changelog): reconcile v3.8.32 bullets for late cycle PRs (#4435/…
Jun 21, 2026
912239f
feat(ui): expose targetFormat selector in custom-models form (#4475)
adivekar-utexas Jun 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -1625,6 +1625,12 @@ QUOTA_STORE_DRIVER=sqlite # sqlite | redis
# OPENCODE_API_KEY=

# ─── Bifrost Go sidecar (PR-4 in #3932) ──────────────────────────────────────
# Master kill switch for the bifrost sidecar proxy. When set to 0, the
# /api/v1/relay/chat/completions/bifrost route returns 503 with the
# X-Bifrost-Killswitch header and the operator is bounced to the TS path.
# Use this to disable the sidecar without redeploying (e.g. during a
# tier-1 router incident or a key rotation). Default: 1 (sidecar active).
# BIFROST_ENABLED=1
# When BIFROST_BASE_URL is set, /api/v1/relay/chat/completions/bifrost routes
# traffic to the Go gateway instead of the TS relay handler, removing TS from
# the hot path. Auth/rate-limit/injection-guard stay in the route (security not
Expand Down Expand Up @@ -1668,3 +1674,30 @@ QUOTA_STORE_DRIVER=sqlite # sqlite | redis
# Redis image used by the 1-click Redis launcher. Default: redis:7-alpine.
# Override to redis:8-alpine or a private registry mirror as needed.
# OMNIROUTE_REDIS_IMAGE=

# ── Cluster Profile: Qdrant Vector Memory (opt-in via `docker compose --profile memory up`) ──
# Qdrant is an OPTIONAL sidecar for deployments that need cosine-distance vector
# search at >1M embeddings. The default vector store is sqlite-vec
# (src/lib/memory/vectorStore.ts:108); flip this profile on only if you hit the
# sqlite-vec ceiling or want persistent cross-replica vector state. See
# docs/architecture/cluster-decisions.md § "Qdrant (memory profile)".
# QDRANT_HOST=qdrant
# QDRANT_PORT=6333
# QDRANT_GRPC_PORT=6334
# QDRANT_API_KEY=
# QDRANT_COLLECTION=omniroute-memory
# QDRANT_EMBEDDING_MODEL=text-embedding-3-small
# QDRANT_VECTOR_SIZE=1536
# QDRANT_HNSW_EF_CONSTRUCT=128

# ── Cluster Profile: Bifrost Tier-1 Router (opt-in via `docker compose --profile bifrost up`) ──
# Bifrost is an OPTIONAL Go-based Tier-1 router that handles the upstream-provider
# multiplexing layer. Default: OmniRoute's open-sse/executors/bifrost.ts in-process
# executor handles routing directly. Flip this profile on only if you want the
# gateway as a separate sidecar (helps in 3+ replica deployments where you want
# provider rotation centralised). See docs/architecture/cluster-decisions.md §
# "Bifrost (bifrost profile)".
# BIFROST_BASE_URL=http://bifrost:8080
# BIFROST_API_KEY=
# BIFROST_STREAMING_ENABLED=true
# BIFROST_TIMEOUT_MS=30000
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ For any non-trivial change, read the matching deep-dive first:
| Electron desktop | [`docs/guides/ELECTRON_GUIDE.md`](docs/guides/ELECTRON_GUIDE.md) |
| Release flow | [`docs/ops/RELEASE_CHECKLIST.md`](docs/ops/RELEASE_CHECKLIST.md) |
| Quality gates (35 gates, allowlist policy) | [`docs/architecture/QUALITY_GATES.md`](docs/architecture/QUALITY_GATES.md) |
| Cluster opt-in profiles (memory, bifrost) | [`docs/architecture/cluster-decisions.md`](docs/architecture/cluster-decisions.md) |

---

Expand Down
69 changes: 69 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,17 @@ Result: 4 layers of fallback = zero downtime

</div>

> Recent highlights from **v3.8.20 → v3.8.31**. Full history in [`CHANGELOG.md`](CHANGELOG.md).
> Recent highlights from **v3.8.20 → v3.8.32**. Full history in [`CHANGELOG.md`](CHANGELOG.md).

- **🤖 One-command CLI/agent setup** — a dedicated `setup-*` command configures each coding tool to route through OmniRoute (Claude Code, Codex, Cline, Continue, Cursor, Roo Code, Kilo Code, Crush, Goose, Qwen Code, Aider, OpenCode, Gemini CLI); `omniroute launch` / `omniroute launch-codex` are zero-config launchers. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
- **🛰️ Remote mode** — drive a remote OmniRoute from any machine with scoped access tokens (`omniroute connect` / `omniroute contexts` / `omniroute tokens`). → [Remote Mode](docs/guides/REMOTE-MODE.md)
- **🧭 Smarter auto-routing** — OpenRouter-style `auto/<category>:<tier>` combos (e.g. `auto/coding:fast`, `auto/reasoning:pro`), live Arena-ELO + models.dev model intelligence, and per-step account allowlists. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
- **🗜️ Pluggable compression** — an async compression pipeline with Compression Studios, a stable LLMLingua-2 ONNX engine, RTK, and delegated Anthropic Context Editing. → [Compression](docs/compression/COMPRESSION_ENGINES.md)
- **🗜️ Pluggable compression** — an async compression pipeline with Compression Studios, a stable LLMLingua-2 ONNX engine, RTK, delegated Anthropic Context Editing, and a unified settings panel that is the single source for per-engine on/off + level. → [Compression](docs/compression/COMPRESSION_ENGINES.md)
- **🕵️ Transparent MITM decrypt (TPROXY)** — capture & translate traffic from CLIs that ignore proxy env vars, with a per-SNI certificate authority and a trust-store installer. → [MITM/TPROXY](docs/security/MITM-TPROXY-DECRYPT.md)
- **💸 Cost telemetry everywhere** — `X-OmniRoute-*` cost/usage headers on every endpoint (including media), a non-token cost engine, a cache-HIT `X-OmniRoute-Cost-Saved` header, and per-key USD spend quotas. → [API Reference](docs/reference/API_REFERENCE.md)
- **🧠 Memory you control** — opt-in int8 vector quantization (Qdrant + sqlite-vec), memory off by default, and a per-request `x-omniroute-no-memory` header. → [Memory](docs/frameworks/MEMORY.md)
- **🛡️ Security** — a prompt-injection guard across every LLM route (backed by a red-team suite), plus a free DuckDuckGo last-resort web search. → [Guardrails](docs/security/GUARDRAILS.md)
- **🤝 More providers & agents** — Cursor Cloud Agent (a 4th cloud agent), a refreshed 231-provider catalog (OrcaRouter, Wafer AI, OpenAdapter, dit.ai, TokenRouter, …), and Vertex AI media generation (speech / transcription / music / video). → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **🤝 More providers & agents** — Cursor Cloud Agent (a 4th cloud agent), a refreshed 231-provider catalog (OrcaRouter, Wafer AI, OpenAdapter, dit.ai, TokenRouter, …), Vertex AI media generation (speech / transcription / music / video), and one-click account import from CLIProxyAPI (`~/.cli-proxy-api/`). → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **⚡ Local performance & infra** — a one-click local Redis launcher (`omniroute redis up`, plus a dashboard Redis panel) and an optional Bifrost Go sidecar that offloads the hottest relay path (`BIFROST_BASE_URL`, with automatic fallback to the TypeScript path on timeout). → [Environment](docs/reference/ENVIRONMENT.md)

<br/>
Expand Down Expand Up @@ -439,6 +439,7 @@ omniroute connect 192.168.0.15 # password → scoped token, saved as
omniroute models list # ← runs against the REMOTE server
omniroute configure codex # ← picks a remote model, writes a local Codex profile
omniroute tokens create --name ci --scope read # mint narrower tokens for other machines
omniroute contexts use default # ← switch back to the local server
```

Tokens are scoped `read` / `write` / `admin`; process-spawning routes stay loopback-only.
Expand Down Expand Up @@ -876,14 +877,14 @@ Compression: aggressive (~50%) → double your free quota · Cost: $0/mo

### 📘 Getting Started

| Document | Description |
| ---------------------------------------------- | ----------------------------------------------------------------------------- |
| [User Guide](docs/guides/USER_GUIDE.md) | Providers, combos, CLI integration, deployment |
| [Setup Guide](docs/guides/SETUP_GUIDE.md) | Full install methods, CLI tool configs, protocol setup, timeout tuning |
| [CLI Tools Guide](docs/reference/CLI-TOOLS.md) | Per-tool setup for Claude Code, Codex, Cursor, Cline, OpenClaw, Kilo, Copilot |
| [Remote Mode](docs/guides/REMOTE-MODE.md) | Drive a remote OmniRoute (VPS) from your laptop CLI via scoped access tokens |
| Document | Description |
| -------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| [User Guide](docs/guides/USER_GUIDE.md) | Providers, combos, CLI integration, deployment |
| [Setup Guide](docs/guides/SETUP_GUIDE.md) | Full install methods, CLI tool configs, protocol setup, timeout tuning |
| [CLI Tools Guide](docs/reference/CLI-TOOLS.md) | Per-tool setup for Claude Code, Codex, Cursor, Cline, OpenClaw, Kilo, Copilot |
| [Remote Mode](docs/guides/REMOTE-MODE.md) | Drive a remote OmniRoute (VPS) from your laptop CLI via scoped access tokens |
| [Claude Code Config](docs/guides/CLAUDE-CODE-CONFIGURATION.md) | Point Claude Code at OmniRoute (local/remote) with `launch` + per-model profiles |
| [Quick Start](README.md#-quick-start) | 3-step install → connect → configure |
| [Quick Start](README.md#-quick-start) | 3-step install → connect → configure |

### 🔧 Operations & Deployment

Expand Down
11 changes: 10 additions & 1 deletion bin/cli/commands/contexts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@ function authLabel(c) {
return "✗";
}

async function confirm(msg) {
export async function confirm(msg) {
// Non-interactive stdin (pipe, CI, EOF) cannot answer a [y/N] prompt. Asking
// anyway leaves the readline question pending forever — Node then warns about an
// "unsettled top-level await" at exit. Decline cleanly instead and point at the
// non-interactive escape hatch so scripted callers fail safe rather than hang.
if (!process.stdin.isTTY) {
process.stderr.write(`${msg} [y/N] (non-interactive stdin — declined; pass --yes to confirm)\n`);
return false;
}
const readline = await import("node:readline");
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const answer = await new Promise((r) => rl.question(`${msg} [y/N] `, r));
Expand All @@ -26,6 +34,7 @@ function maskKey(k) {
export function registerContexts(program) {
const ctx = program
.command("contexts")
.alias("context") // singular alias — docs/connect output historically said `context current`
.description(t("config.contexts.description") || "Manage server contexts/profiles");

ctx
Expand Down
8 changes: 6 additions & 2 deletions bin/cli/commands/update.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ export async function getCurrentVersion() {
}
}

async function getLatestVersion() {
// `--prefer-online` forces npm to revalidate its HTTP cache against the registry.
// Without it `npm view` can return a stale cached version (e.g. report 3.8.30 as
// "latest" after 3.8.31 was published), so the updater told users on an old build
// they were already on the latest version (#4376). `execFn` is injectable for tests.
export async function getLatestVersion(execFn = execFileAsync) {
try {
const { stdout } = await execFileAsync("npm", ["view", "omniroute", "version"], {
const { stdout } = await execFn("npm", ["view", "omniroute", "version", "--prefer-online"], {
timeout: 15000,
});
return stdout.trim();
Expand Down
31 changes: 27 additions & 4 deletions bin/cli/io.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,43 @@ export function createPrompt() {
output: process.stdout,
});

// Non-interactive stdin (pipe, CI, EOF via `< /dev/null`) cannot answer an
// interactive prompt. Without a guard, `rl.question` never fires its callback —
// the await stays pending and Node warns about an "unsettled top-level await" at
// exit. Resolving on the readline `close` event (which fires on stdin EOF)
// returns the default/empty instead of hanging. A genuinely piped line still
// arrives via the question callback first, so `echo value | omniroute …` keeps
// working — only the no-input EOF case falls back.
function ask(question, defaultValue = "") {
const suffix = defaultValue ? ` (${defaultValue})` : "";
return new Promise((resolve) => {
let settled = false;
const done = (v) => {
if (!settled) {
settled = true;
resolve(v);
}
};
rl.once("close", () => done(defaultValue));
rl.question(`${question}${suffix}: `, (answer) => {
const trimmed = answer.trim();
resolve(trimmed || defaultValue);
done(trimmed || defaultValue);
});
});
}

function askSecret(question) {
return new Promise((resolve) => {
let prompted = false;
let settled = false;
const saved = rl._writeToOutput.bind(rl);
const done = (v) => {
if (!settled) {
settled = true;
rl._writeToOutput = saved;
resolve(v);
}
};
let prompted = false;
rl._writeToOutput = function (str) {
if (!prompted) {
rl.output.write(str);
Expand All @@ -29,9 +52,9 @@ export function createPrompt() {
// Suppress character echo; allow only newlines through
if (str === "\r\n" || str === "\n" || str === "\r") rl.output.write("\n");
};
rl.once("close", () => done("")); // non-interactive EOF → empty secret, no hang
rl.question(`${question}: `, (answer) => {
rl._writeToOutput = saved;
resolve(answer.trim());
done(answer.trim());
});
});
}
Expand Down
3 changes: 2 additions & 1 deletion config/quality/complexity-baseline.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"_comment": "Catraca de complexidade (check-complexity.mjs, ESLint core rules complexity>=15 e max-lines-per-function>80 sobre src+open-sse+electron+bin via eslint.complexity.config.mjs). Conta total de violacoes; so pode cair. --update ratcheta.",
"count": 1900,
"count": 1905,
"_rebaseline_2026_06_20_reviewprs_mine_r2": "Reconciliacao release-volatil 1900->1905 (+5) apos o lote /review-prs 'apenas minhas' r2 (17 PRs meus mergeados em release/v3.8.32). Breakdown medido com `node scripts/check/check-complexity.mjs` + diff por-arquivo eslint complexity JSON entre o tip pre-lote (9052c5a78 = 1902) e o tip pos-lote (1905): (a) +2 JA latentes no tip pre-lote (1900->1902), drift de merges concorrentes de outras sessoes ANTERIORES a este lote (nao introduzidos por mim) que o fast-path do release nao rebaselina (check:complexity so roda release->main); (b) +3 deste lote, isolados em DOIS arquivos: open-sse/translator/helpers/geminiHelper.ts +1 (convertOpenAIContentToParts passou de 80->93 linhas pela branch de audio do #4426 — max-lines-per-function, funcao de dispatch coesa por tipo de content part) e open-sse/translator/response/openai-to-gemini-sse.ts +2 (translator SSE NOVO do #4453, openAIChunkToGeminiChunk + convertOpenAIResponseToGemini em complexity 19 cada — conversores de chunk SSE inerentemente ramificados, levemente acima de 15). Crescimento de feature legitimo recem-TDD'd, nao regressao; refatorar feature recem-mergeada so para raspar +3 seria over-engineering arriscado. Reducao fica como debt.",
"_rebaseline_2026_06_20_reviewprs_v3831_batch": "Reconciliacao release-volatil 1896->1900 (+4): drift do lote /review-prs v3.8.31 (25 PRs A+B+C + merges concorrentes). Condicionais NOVOS legitimos — sobretudo #4381 (rotas /api/local/redis/{start,stop,status} detectRuntime + guardas + bifrost relay) e #4366 (classificacao de exhaustion de erro entre os 2 dispatchers de combo). Medido 1900 ESTAVEL em fd1391c0b E f46c69f2a com `node scripts/check/check-complexity.mjs` (commit concorrente intermediario foi complexity-neutro). O fast-path do release nao roda check:complexity (so release->main), entao o ramo acumula sem rebaselinar. Mesma familia dos rebaselines anteriores — crescimento de feature legitimo, nao regressao; valor final reconciliado no release->main.",
"_rebaseline_2026_06_20_postlote_concurrent_drift": "Reconciliacao release-volatil: 1895->1896 (+1). Drift de condicional NOVO de PRs mergeados pela sessao concorrente APOS o #4338 ratchetar para 1895 (#4355 pricing gpt-5.x-pro / #4364 cli active-context cred / #4363 compliance cleanup / #4358 mitm mask / #4332 injection-guard-16KB). O fast-path do release nao roda check:complexity (so release->main), entao o ramo acumula sem rebaselinar. Medido com `node scripts/check/check-complexity.mjs` no tip cdfd71c17. Mesma familia — crescimento de feature legitimo, nao regressao.",
"_note_2026_06_20_4371_chatcore_heap_leaf": "PR #4371 (extract checkHeapPressureGuard leaf, god-file decomposition start) e complexity-NEUTRO: handleChatCore so PERDE codigo e o novo heapPressure.ts checkHeapPressureGuard fica sob o teto — a contagem permanece 1896 (medido no tip mesclado com check-complexity.mjs).",
Expand Down
Loading
Loading