After merging PRs #2221 (ModelSync shared loopback readiness gate + IPv4 force)
and #2219 (Antigravity loadCodeAssist bootstrap + fetchAvailableModels fallback)
into release/v3.8.0, two test suites needed updates to match the new routing:
- tests/unit/model-sync-route.test.ts:
* resetStorage() now calls __resetLoopbackReadinessForTests() so the
module-level __loopbackReadyPromise cache does not leak between tests.
* Every fetch mock now answers the /__readiness_probe__/ URL with 404 so
the gate opens immediately (any HTTP response satisfies the probe).
* Self-fetch target URL assertions updated from http://localhost/...
to http://127.0.0.1:20128/... per PR #2221's IPv4-force.
- tests/unit/provider-models-route.test.ts:
* The Antigravity discovery-retry test now treats loadCodeAssist calls as
non-fatal failures so the discovery path is still exercised.
* The expected discovery URL sequence is updated to the new
fetchAvailableModels-first order introduced by PR #2219.
The local-aliases-precedence path used `typeof aliases[parsed.model] === "string"`
to guard string-only operations, but TypeScript does not narrow the variable
`directTarget` from that index-expression test — the variable retained the union
type ModelAliasValue (string | object), so `indexOf`/`slice` were typed as
property accesses on the object branch and the strict-core typecheck failed.
Refactors to capture `directTarget` first and run `typeof directTarget === "string"`
on the variable, which TS does narrow. No runtime semantics change — local-aliases
tests still pass.
Wires the new platform-overhaul gates into the Detailed Checklist used by
the release-cut workflow:
Documentation block:
npm run check:docs-all (umbrella over sync, counts, env-doc, deprecated, doc-links)
npm run check:env-doc-sync (code ↔ .env.example ↔ ENVIRONMENT.md parity)
npm run check:doc-links (no broken internal markdown refs)
i18n block (replaces stale `scripts/i18n-check.mjs` mention):
npm run i18n:check (drift between source docs and .i18n-state.json)
npm run i18n:check-ui-coverage (every locale ≥ 80% UI key coverage)
npm run i18n:sync-ui:dry (0 missing keys across 40 locales)
Note about running npm run i18n:run when source English docs change.
These are the same checks newly enforced by the docs-sync-strict and
i18n-ui-coverage CI jobs added in commit acf6b93d.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an Unreleased entry summarizing the nine-phase platform overhaul that
ships in v3.8.x: scripts cleanup, .env audit, /docs subfolder restructure,
diagrams folder, hash-based docs translation pipeline, UI key sync,
/src/app/docs drift fixes + frontmatter + openapi feed, and the new CI
gates (env-doc-sync strict, doc-links, docs-sync-strict workflow,
i18n-ui-coverage workflow). Also records the Fixed entry for the 270
broken-link sweep.
No version bump — that is intentionally left for the release-cut workflow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The FASE 7 frontmatter sync touched docs/architecture/ARCHITECTURE.md but
.i18n-state.json was not refreshed, so npm run i18n:check reported
source-changed drift on every subsequent run.
Resolution: re-ran the hash-based translator end-to-end (npm run i18n:run
-- --locale=pt-BR --files=docs/architecture/ARCHITECTURE.md) which:
- retranslated the source through the production backend (14 chunks,
75 KB pt-BR output);
- persisted the new source/target SHA-256 pair in .i18n-state.json
(target_hash now matches the regenerated translation);
- left every other source/locale pair untouched.
After the run:
npm run i18n:check → PASS - all sources and targets match recorded hashes.
The pre-commit i18n drift advisory will no longer warn for this file.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The FASE 3 /docs restructure moved files into 8 subfolders (architecture,
guides, reference, frameworks, routing, security, compression, ops) but left
several link categories with stale relative paths. The new check:doc-links
gate (FASE 8) surfaced these and produced this exhaustive fix sweep.
Categories repaired (counts before → after, total broken: 270 → 0):
i18n-relative (241 → 0): docs in subfolders now reference translations
under docs/i18n/<locale>/docs/<subfolder>/<FILE>.md (one extra "../"
plus the docs/<subfolder>/ segment). Affects ARCHITECTURE, FEATURES,
USER_GUIDE, TROUBLESHOOTING, UNINSTALL, VM_DEPLOYMENT_GUIDE,
API_REFERENCE, and the I18N.md self-reference table.
parent-relative (14 → 0): refs like ../CLAUDE.md, ../CONTRIBUTING.md,
../AGENTS.md, ../Tuto_Qdrant.md, ../open-sse/..., ../electron/...,
../src/... promoted from one to two parent hops (../ → ../../) to
reach repo root from docs/<subfolder>/.
screenshots (9 → 0): FEATURES.md PNG refs rewritten to ../screenshots/
(assets live at docs/screenshots/ unchanged).
missing-rfc (2 → 0): RFC-AUTO-ASSESSMENT.md was deleted earlier in the
overhaul; replaced refs in EVALS.md with pointers to the live
AUTO-COMBO.md scoring doc plus an in-prose mention of
src/domain/assessment/.
other (4 → 0): ENVIRONMENT.md → ../../.env.example,
SETUP_GUIDE.md → ../../{open-sse/mcp-server,src/lib/a2a}/README.md,
PROVIDER_REFERENCE.md → ../../src/shared/... and ../../open-sse/...,
VM_DEPLOYMENT_GUIDE.md omnirouteCloud reference replaced with a
pointer to in-repo TUNNELS_GUIDE.md (omnirouteCloud lives in a
separate companion repo).
Validation:
npm run check:doc-links → PASS (501 internal links, 0 broken)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds two strict drift gates that mirror (and harden) the new pre-commit
advisories from FASE 8:
- docs-sync-strict: runs `npm run check:docs-all` (docs version sync,
counts, env-doc contract, deprecated versions, and the new internal
doc-links checker) plus the i18n translation-drift check in strict
mode.
- i18n-ui-coverage: enforces ≥80% UI message coverage across every
configured locale.
Both jobs slot in immediately after `lint`, reusing the existing
setup-node@v6 + cache pattern. They are also wired into ci-summary
(`needs` + dashboard table) so the dashboard surfaces their status.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-commit now runs three additional drift checks beyond the existing
docs-sync + any-budget gates:
1. check-env-doc-sync (strict) — blocks commits that drift the env
contract across code, .env.example, and ENVIRONMENT.md.
2. check-translation-drift --warn — advisory only; prints a hint when
docs/i18n mirrors are stale so devs can run `npm run i18n:run`
before pushing. CI enforces strict mode in the new gate.
3. check-ui-keys-coverage --threshold=80 — pre-commit prints a hint
when any locale dips below 80%, but does not block. CI enforces
strict mode.
End-to-end pre-commit duration: ~28s on a clean tree (40 locales).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expose `npm run check:doc-links` and add it to the end of `check:docs-all`
so the new internal-link gate runs alongside the other documentation
sync checks. Pre-existing broken links (272) will be tracked and fixed
under FASE 9; the CI strict gate added in this phase makes the debt
visible without blocking pre-commit (which still runs only check:docs-sync).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds scripts/check/check-doc-links.mjs that scans every docs/**/*.md
(excluding i18n mirrors, screenshots, exported diagrams, and superpowers
plans) and verifies that every internal markdown/HTML link resolves to a
file on disk. External URLs (http/https/mailto/tel), anchor-only links,
and fenced code blocks are ignored.
Supports --report (informational, exit 0), --json (machine-readable),
and --help. Default mode exits 1 when any broken link is found, so this
can be wired as a CI gate. Initial baseline reveals ~270 pre-existing
broken links carried over from prior reorgs (i18n relative paths,
removed RFC drafts, stale screenshot refs) that FASE 9 will clean up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- scripts/docs/gen-openapi-module.mjs (new): build helper that loads
docs/reference/openapi.yaml via js-yaml, flattens paths × methods, and
emits src/app/docs/lib/openapi.generated.ts with strongly-typed
OPENAPI_ENDPOINTS, OPENAPI_TAGS, OPENAPI_VERSION, OPENAPI_TITLE plus
the OpenApiEndpoint interface (no `any`, deterministic ordering).
By default it skips internal management paths (anything under /api/
that isn't /api/v1/*) so the Api Explorer focuses on the OpenAI-
compatible public surface — 19 endpoints for v3.8.0 (Chat, Messages,
Responses, Embeddings, Images, Audio, Moderations, Rerank, Models,
System). Add --include-management to emit all 121 paths if needed.
- src/app/docs/components/ApiExplorerClient.tsx: drop the 13-entry
hardcoded API_ENDPOINTS array; the component now imports from
@/app/docs/lib/openapi.generated. Tags come from the spec; the
"Try It" form picks an example body keyed by full path (8 well-known
bodies pre-seeded, everything else starts empty). The header pill
now shows endpoint count + OpenAPI version, and an "auth" pill is
rendered next to operations whose spec declares non-empty security.
- package.json: prebuild:docs now chains gen-openapi-module after the
docs index generator so `next build` always sees a fresh module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every .md under docs/{architecture,guides,reference,frameworks,routing,
security,compression,ops,diagrams} plus docs/README.md now opens with:
---
title: "<inferred from first H1>"
version: 3.8.0
lastUpdated: 2026-05-13
---
46 files updated (no docs were skipped — none had pre-existing
frontmatter). [slug]/page.tsx already reads frontmatter.version and
frontmatter.lastUpdated via gray-matter and renders a "v3.8.0" pill
plus a "Last updated" caption, so the UI picks these up automatically.
Helper: scripts/docs/add-frontmatter.mjs — idempotent (skips files that
already start with `---`), falls back to a humanized basename when no
leading H1 exists. Excludes docs/i18n/, docs/screenshots/,
docs/superpowers/, docs/diagrams/exported/. Re-runnable safely.
Also regenerated src/app/docs/lib/docs-auto-generated.ts: 44 docs across
8 sections (Architecture / Guides / Reference / Frameworks / Routing /
Security / Compression / Ops), which now includes the 14 docs that were
missing from the v3.7 sidebar (Cloud Agents, Guardrails, Memory, Skills,
Webhooks, Evals, Authz, Agent Protocols, Repository Map, Provider
Reference, Reasoning Replay, Stealth Guide, Tunnels Guide, Electron
Guide).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ARCHITECTURE.md and CODEBASE_DOCUMENTATION.md: 179 → 177 registered
providers (canonical from src/shared/constants/providers.ts).
- FEATURES.md and en.json wizard step: 13 → 14 routing strategies; lists
all 14 explicitly including reset-aware (the missing one).
- llm.txt root: combo strategy count corrected in 3 places (UI tree,
dashboard summary, fallback semantics).
- MCP-SERVER.md: 37 tool count was already correct; added a "Related
Frameworks (v3.8.0)" section pointing to Cloud Agents
(docs/frameworks/CLOUD_AGENT.md) and Guardrails
(docs/security/GUARDRAILS.md), both sibling frameworks intentionally
outside the MCP tool catalog.
- scripts/i18n/sync-llm-mirrors.mjs (new): idempotent helper to push
root llm.txt body into the 40 docs/i18n/<locale>/llm.txt mirrors
while preserving each locale's heading + language bar prefix; ran
it to refresh all 40 mirrors so `check:docs-sync` is green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reads the current request locale via `getLocale()` from next-intl and
prefers a translated markdown copy under
`docs/i18n/<locale>/docs/<fileName>` when one exists. Falls back to
the English source otherwise, so locales with partial coverage stay
readable instead of 404ing.
Path resolution is hardened: every read is resolved against an
absolute docs root and verified to live inside it, so a stray
filename in the docs index cannot escape the directory.
This is the runtime counterpart to the DocsI18n removal: the locale
preference set by the shared LanguageSelector in the docs layout now
materially affects what content the page renders.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The cosmetic DocsI18n.tsx shim duplicated the locale catalog that
already lives in config/i18n.json and consumed it through a separate
client hook (useDocsLocale + a 10-entry hard-coded SECTION_LABELS
map). It only ever translated sidebar section titles — the docs
content itself was always English.
Now the /docs page uses the same `LanguageSelector` component as the
rest of the dashboard, backed by next-intl + config/i18n.json. The
locale cookie set there is consumed by the [slug] page server
component (next commit) to actually serve translated markdown.
Removed:
- src/app/docs/components/DocsI18n.tsx (203 lines)
Updated:
- src/app/docs/layout.tsx — swaps DocsLocaleSwitcher for the shared
LanguageSelector
- tests/unit/docs-site-overhaul.test.ts — replaces the DocsI18n
importability assertions with checks that (a) the shared next-intl
config covers the same locales, (b) the global LanguageSelector
is the new docs switcher, and (c) the DocsI18n module is gone.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ran `npm run i18n:sync-ui` against every non-English locale to
replicate the full key tree from `src/i18n/messages/en.json`. Missing
strings now show up as `__MISSING__:<english_value>` placeholders,
which:
- keep the catalogs the same shape as the source-of-truth, so a
runtime `useTranslations('feature.x')` call no longer falls back
to the English bundle for every drifted key;
- are visible to reviewers (and to the optional `--translate-markers`
pass in sync-ui-keys.mjs) so the drift can be paid down
incrementally.
Volume summary (40 locales):
- 25,234 placeholders inserted in total
- zh-CN closest to parity (+105)
- most European/Asian locales (+710)
- pt-BR slightly ahead (+589)
- bn/fa/gu/in/mr/sw/ta/te/ur (+445)
No existing translated strings were touched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New script `scripts/i18n/check-ui-keys-coverage.mjs` compares every
`src/i18n/messages/<locale>.json` against `en.json` and reports
per-locale coverage: missing keys, __MISSING__ placeholder counts,
and real translated coverage percentage.
Modes:
- default: fail with exit 1 if any locale falls below `--threshold`
(default 80%)
- `--report`: print the same table but always exit 0 (informational)
- `--json`: machine-readable output for CI dashboards
Wired into `i18n:check-ui-coverage` npm script (added in the previous
commit). FASE 8 will decide whether to make this a pre-push gate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New script `scripts/i18n/sync-ui-keys.mjs` replicates keys present in
`src/i18n/messages/en.json` into every other locale catalog, marking
missing strings with a `__MISSING__:<english_value>` sentinel so the
drift is auditable and recoverable.
The script also accepts `--translate-markers` to call the OmniRoute
translation backend (same env vars as run-translation.mjs) and replace
those placeholders with real translations. Bounded concurrency, fail-
fast on missing env vars, and a `--dry-run` mode mirror the existing
docs translation pipeline.
Adds the matching `i18n:sync-ui` / `i18n:sync-ui:dry` npm scripts and
`i18n:check-ui-coverage` (next commit) wiring placeholder so the JSON
files can be backfilled with `npm run i18n:sync-ui`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a tiny built-in dotenv loader at the top of run-translation.mjs that
parses the repo-root .env file into process.env (without pulling dotenv
as a dependency). Existing process.env values still take precedence, so
shell/CI overrides keep working.
Before: `npm run i18n:run` failed with "Missing required env var:
OMNIROUTE_TRANSLATION_API_URL" unless the operator exported the vars in
the current shell.
After: the npm scripts (i18n:run, i18n:run:dry) pick up .env automatically.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds OMNIROUTE_TRANSLATION_API_URL, OMNIROUTE_TRANSLATION_API_KEY,
OMNIROUTE_TRANSLATION_MODEL, OMNIROUTE_TRANSLATION_TIMEOUT_MS, and
OMNIROUTE_TRANSLATION_CONCURRENCY to both .env.example (commented placeholders)
and docs/reference/ENVIRONMENT.md (new 'Docs translation pipeline' subsection).
Restores the env-doc-sync contract reported by the strict checker added in
FASE 2 — these vars are now referenced by scripts/i18n/run-translation.mjs
introduced in this branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates docs/guides/I18N.md with a 'Translation pipeline (recommended)' section
documenting the npm run i18n:run / :check / :run:dry flow, required env vars,
state file semantics, and the legacy-script deprecation notice. The legacy
Quick-Reference row for the Python translator is replaced with the new npm
script entry.
Re-translates two sources end-to-end through the new pipeline:
- CLAUDE.md (1 chunk, 23k chars)
- docs/architecture/ARCHITECTURE.md (14 chunks, 74k chars, one timeout retry)
Both translations now have a fresh language bar regenerated from
config/i18n.json (41 locales), an H1 heading with the native language tag,
and prose translated into Brazilian Portuguese while preserving markdown
syntax, code blocks, command names, env var identifiers, and version
numbers verbatim.
.i18n-state.json records the SHA-256 hash for each source and target. A
second invocation with no source changes correctly reports
'work units: 0 (skipped up-to-date: 2 of 2)' and `npm run i18n:check`
exits 0 — confirming the hash-based incremental + drift detection paths
both work as designed.
- Elapsed: ~10 min total at concurrency=4
- Cost: ~75k chars output through the configured backend
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
src/i18n/config.ts is now a thin adapter that reads config/i18n.json
(canonical locale list) and exports the same shape — LOCALES, LANGUAGES,
RTL_LOCALES, DEFAULT_LOCALE, Locale type, LOCALE_COOKIE — that
LanguageSelector, layout.tsx, request.ts, and the rest of the codebase
already consume. No call-site changes were required. Adds
DOCS_TARGET_LOCALES and getLanguage() helpers for new code.
The legacy scripts now print a deprecation warning on stderr at startup:
- scripts/i18n/i18n_autotranslate.py (banner + module-level warn)
- scripts/i18n/generate-multilang.mjs (banner + console.warn)
They keep working for messages and readme modes (UI strings / root README
variants), which are still outside the new pipeline's scope. Both will be
removed in v3.10.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds scripts/i18n/check-translation-drift.mjs — a deterministic CI gate that
verifies every source recorded in .i18n-state.json still hashes to the same
SHA-256 on disk and every produced translation target exists with its
recorded hash. No API calls.
Modes: --strict (default, exit 1 on any drift), --warn (exit 0 with report),
--json (machine-readable report).
Also adds three npm scripts:
- i18n:run run the translator (incremental, hash-based)
- i18n:run:dry preview what would happen (no API calls, no writes)
- i18n:check drift checker (used in CI / pre-merge)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds scripts/i18n/run-translation.mjs — the new docs translation pipeline.
Reads sources from CLAUDE.md, GEMINI.md, AGENTS.md, CONTRIBUTING.md, SECURITY.md,
CODE_OF_CONDUCT.md, README.md at the repo root, plus all .md files under
docs/<subfolder>/ (recursing one level). Writes targets to
docs/i18n/<locale>/<source-path>.
Behavior:
- SHA-256 hash per source + per target stored in .i18n-state.json
- Re-runs only retranslate sources whose hash changed (or whose target file
is missing)
- Excludes docs/i18n/, docs/screenshots/, docs/superpowers/, docs/diagrams/,
docs/reports/ subtrees + I18N.md and README.md filenames
- Backend reads OMNIROUTE_TRANSLATION_* env vars (URL, API key, model,
timeout, concurrency); never logs the API key
- Chunks markdown on top-level ## headings before sending to the LLM
- Pre-formats translator output with Prettier so lint-staged commit hooks
cannot mutate file content out from under the hash registry
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds config/i18n.json (41 locales) + JSON-Schema as the single source of
truth for the locale list, RTL set, and docs-translation policy. This file
is consumed by:
- The runtime UI config in src/i18n/config.ts (next commit).
- The docs translation pipeline (scripts/i18n/run-translation.mjs, added in
a later commit).
- The drift checker (scripts/i18n/check-translation-drift.mjs).
Fields:
- default: source locale (en)
- rtl: locale codes rendered right-to-left
- uiOnly: locales shipped in UI but not target of docs translation
- docsExcluded: locales NOT receiving docs translations (source language)
- locales[]: code, label, name, native, english, flag
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>