Skip to content

Milestone v1.3.0: Extension multilingual UI - #150

Open
LakshmanTurlapati wants to merge 56 commits into
mainfrom
LakshmanTurlapati/showcase-internationalization-languages
Open

LakshmanTurlapati wants to merge 56 commits into
mainfrom
LakshmanTurlapati/showcase-internationalization-languages

Conversation

@LakshmanTurlapati

@LakshmanTurlapati LakshmanTurlapati commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Summary

Milestone v1.3.0: Extension multilingual UI (Phases 66-71)
Goal: Every package-owned user-facing string in the Chrome extension can render in en, es, de, ru, ja, ko, zh-CN, and zh-TW.
Status: All six phase verifications passed. Two later review rounds found no blockers and their fixes are in. The language follows Chrome's language list, with the picker only in the control panel's Advanced settings. #155 (official Cline support) is merged into this branch, so the branch ships extension 0.9.95 and fsb-mcp-server 0.11.5, with 0.9.95 release notes covering both changes. Antigravity replaces Windsurf as an install target, and Muse, Grok Bot, and Dots are allowed client labels. #161 (dead MCP tools and background-agent leftovers) and #162 (Online-Mind2Web harness) are merged too, so 0.11.5 also stops registering three tools that did nothing useful, leaving 69. Russian is added to the extension interface and the showcase (Round 9). CI is green and the extension loads and switches language in Chrome. Not merged.

The extension resolves its UI locale at runtime through extension/utils/ui-locale.js and ships eight _locales catalogs with 1,241 keys each. The side panel, popup, options and control panel, onboarding, unlock, microphone permission, and FSB-authored overlay chrome read from those catalogs and fall back to English rather than a blank label. By default the language follows Chrome's language list (Settings › Languages). A Language card in the control panel's Advanced settings saves an fsbUiLocale override that applies without restarting Chrome; choosing Automatic clears it. User text, model output, page content, secrets, logs, and the MCP wire are unchanged. With #155 merged in, the branch moves the product version to 0.9.95 and fsb-mcp-server to 0.11.5.

Changes

Plan 66-01: Locale resolver, seed catalogs, and CI gate

The resolver maps public codes to Chrome folders (zh-CN to zh_CN), applies the showcase alias rules, prefers a saved override over the browser language, and never reads the website cookie. scripts/verify-extension-i18n.mjs fails on a missing key, an empty message, a placeholder mismatch between locales, copied English that is not on the hash-bound allowlist, or a dropped protected literal such as FSB.

Key files: extension/utils/ui-locale.js, extension/_locales/*/messages.json, extension/_locales/same-source-allowlist.json, scripts/verify-extension-i18n.mjs, tests/extension-ui-locale.test.js, tests/fixtures/extension-i18n/

Plan 67-01: Manifest, side panel, and popup

The manifest uses __MSG_ext_name__ and __MSG_ext_description__ with default_locale: en. Side-panel and popup resting chrome uses data-i18n, and exact runtime status text refreshes after the catalogs load.

Key files: extension/manifest.json, extension/ui/sidepanel.html, extension/ui/sidepanel.js, extension/ui/popup.html, extension/ui/popup.js, extension/ui/owner-chip.js

Plan 68-01: Options and control panel

All 336 control-panel keys resolve in every locale. Exact options status strings go through fsbUiSet, so vault, payment, pairing, and log messages refresh after boot. Provider names stay in English.

Key files: extension/ui/control_panel.html, extension/ui/options.js, extension/utils/panel-exact.js

Plan 69-01: Onboarding, entry pages, and overlay chrome

Onboarding, unlock, and microphone-permission copy come from the catalogs. Overlay controls such as Stop, Done, and the replay-speed caption are localized, while the task title and model summary stay raw. The locale module loads before visual-feedback.js in both content-script injection lists.

Key files: extension/ui/onboarding.js, extension/ui/unlock.*, extension/ui/microphone-permission.*, extension/content/visual-feedback.js, extension/background.js, extension/ws/ws-client.js

Plan 70-01: Coverage audit

scripts/verify-extension-copy.mjs fails when an in-scope UI file keeps a package-owned English sentence outside the catalog. Logs, provider names, and other producer-owned text are exempt. Leftover chrome was cataloged in all seven locales (Russian, added in Round 9, carries it too).

Key files: scripts/verify-extension-copy.mjs, extension/utils/copy-exact.js, tests/fixtures/extension-i18n/bad-sentence/ui.js

Plan 71-01: Language control

The control panel gets a Language card under Advanced settings › Appearance, listing Automatic, English, Español, Deutsch, 日本語, 한국어, 简体中文, and 繁體中文 (round 3 moved it there from the side panel and control panel headers). Open extension pages and registered overlay shadow roots re-render on chrome.storage.onChanged.

Key files: extension/utils/ui-locale.js, extension/ui/sidepanel.*, extension/ui/control_panel.html, extension/ui/options.*

Also in this branch

  • Product version 0.9.95 across the extension, showcase, skill, docs, and store metadata (taken from Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155, merged into this branch), with one 0.9.95 changelog entry for the multilingual interface and Cline support. fsb-mcp-server moves to 0.11.5 with Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155's Cline installer fix. /release-notes opens on 0.9.95 notes covering both changes, in all eight site languages.
  • npm test now starts with the three i18n checks, which also run alone as npm run test:extension-i18n.
  • scripts/sync-product-version.mjs keeps the __MSG_ tokens in the manifest. The name on chrome://extensions becomes FSB instead of FSB v<version>, and the description becomes "FSB is a universal AI-powered browser automation assistant."
  • Six existing tests update pinned hashes or string assertions for the locale markers, scripts, and manifest tokens.
  • Planning: the paused v0.9.91 milestone (human UAT still pending) is archived under .planning/milestones/v0.9.91-*, and the v1.3.0 roadmap, requirements, research, and phase records are added.

Requirements Addressed

  • Locale catalog: LOC-01 to LOC-05
  • Wire stability: WIRE-01
  • Catalog quality: QUAL-01 to QUAL-03
  • Shell chrome: SHELL-01 to SHELL-03
  • Settings: SET-01
  • Entry and overlay: ENTRY-01 to ENTRY-03
  • Coverage: COPY-01
  • Language control: LANG-01 to LANG-03

All 20 v1 requirements in .planning/REQUIREMENTS.md are mapped to these phases.

Verification

  • Phase verifications passed: 66 (5/5), 67 (4/4), 68 (3/3), 69 (4/4), 70 (3/3), 71 (4/4).
  • Re-run on this branch: tests/extension-ui-locale.test.js (261 passed), scripts/verify-extension-i18n.mjs (all seven locales), scripts/verify-extension-copy.mjs (13 files), plus the version-sync, delegation side panel, MCP session settings, onboarding provider clicks, remote-control rebrand, side-panel tab-aware smoke, and owner-chip tests. npm run version:check reports extension 0.9.95 and MCP 0.11.5.
  • MCP source and extension/ai/tool-definitions.js have no diff against the merge base, so MCP tool schemas and bridge message types are byte-stable. Under mcp/, only the README changes: the version sync rewrites its compatibility lines to the current extension version.
  • Load the unpacked extension in Chrome (first round, before the version moved). A headless Chrome for Testing 153 profile with all outbound network blocked loaded extension/: the service worker registered as "FSB 0.9.93", onboarding and the offscreen document opened, and no CSP or catalog errors were logged. The side panel, control panel, popup, onboarding, unlock, and microphone-permission pages rendered in English, then in Japanese after fsbUiLocale was set to ja. The side panel re-rendered live without a reload. The language select lists 8 options. A web page fetched _locales/ja/messages.json (1,146 keys), so content scripts can load the catalogs. The in-page overlay was not opened.

tests/trigger-cap-settings-ui.test.js fails the same 2 checks here and on main. It is not part of npm test.

CI: both previously failing jobs are fixed in 66409c33 and 87f59af7.

  • extension (validate + tests): tests/lattice-replay-playback.test.js evaluates ReplayPlayerOverlay on its own, so it now also loads the module's ov() helper that _renderSpeed calls. That failure had stopped the npm test chain early. With it fixed, tests/lattice-provider-bridge-smoke.test.js also failed, because background.js now loads utils/ui-locale.js. Its pins now expect 335 importScripts mentions and 331 call sites. Locally, every segment of npm test passes, and npm run validate:extension passes.
  • showcase (build + crawler smoke): messages.xlf now points releaseNotes.meta.title and releaseNotes.meta.description at lines 88 and 89, so ng extract-i18n has no diff. The build, hreflang, video SEO, marketing i18n SEO, and bundle-budget steps also pass locally.

Review findings (fixed)

A code review of this branch raised six findings. All six are fixed on the branch and were re-checked against the code:

  1. The extension failed to load. Every $NAME$-style placeholder now has a placeholders entry. A check against Chrome's catalog rules finds no undefined placeholders in any of the seven locales, and the extension loads in Chrome.
  2. Inline boot scripts were blocked by CSP. control_panel.html, unlock.html, and microphone-permission.html now start the locale module from ui/ui-locale-page.js.
  3. Content scripts could not fetch the catalogs. _locales/*/messages.json is in web_accessible_resources.
  4. Object substitutions reached chrome.i18n.getMessage. t() sends named substitutions down the English path instead.
  5. The blocked-origin hint lost its reason. The hint builds its text with fsbUiLine() and appends classified.reason.
  6. Static data-i18n overwrote JS-owned text. apply() re-translates a node only while it still shows a catalog message, and live nodes written by fill() are tracked separately.

Second review (fixed)

A later review found no blockers but some FSB-owned text still showing in English in a non-English UI, plus stale release text. Fixed in 63b5b262, 536d1aaa, 3121d8f6, and b7c46e1e:

  • Overlay status. The service worker builds phase labels and default details in English (Planning…, Acting…, Done, Task completed). The overlay now translates exact matches at write time and keeps the ellipsis. Task titles, model summaries, and AI status text stay as sent. The overlay container gets lang; the host page is untouched.
  • Stop tooltip. _restoreLegacyStopControl no longer writes English over the translated tooltip, and the pending "Stopping Automation…" label is translated.
  • Delegation copy. The consent heading, preflight failures, the start-rejection card (with its nine keyed reasons), the run error card, and the error bubble are $NAME$ templates, so the provider name stays raw and the sentence is translated.
  • Status and toast copy. Popup and side panel completion and status lines ("Task completed", "Automation stopped", "Replay error", "Step N complete", …), API card titles, and frequent control panel toasts are cataloged and reach their page's exact map. The side panel and popup status bubble now translate progress lines too.
  • lang attribute. Extension pages set <html lang> from the active UI language on boot and on change.
  • Catalog fixes. ja and ko keep "Grok Build" in the cleanup-blocked message; de no longer hyphenates LM Studio or FSB Grok Build. The i18n gate now protects provider and product names, so a dropped name fails CI.
  • Smaller fixes. Exact-map lookups use own keys only (line('constructor') threw); the service worker no longer loads the unused locale module (pins back to 334/330); an unused microphone helper and two stale comments are gone.
  • Release text. New release-notes section (written as 0.9.93, relabeled 0.9.95 after the Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155 merge) (hero plus five illustrated sections, 63 units, all seven site languages, reduced-motion final frames). CHANGELOG.md describes what 0.9.93 ships; mcp/CHANGELOG.md noted the 0.11.2 pairing (dropped after the Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155 merge, since 0.11.5 pairs with 0.9.95); the store listing summary matches the manifest description; the llms summary counts sixteen versions.

84 keys were added to each catalog (now 1,230). Checks on the combined branch: both i18n gates, extension-ui-locale (216/216), the targeted delegation, overlay, side panel, and smoke tests, the full npm test chain, all 14 showcase CI gates, and sync-xliff-targets as a byte-identical no-op. A headless Chrome for Testing run with network blocked confirmed <html lang> switches on all six pages, the stop tooltip stays translated, the Grok Build preflight heading renders in Japanese, Chrome accepts the three-placeholder message, and the overlay shows 操作中… / ブラウザ操作を実行中 while "Clicked the Submit button" stays English.

Round 3: automatic language, picker in Advanced settings

Fixed in 9303c1dc4, a28ba73a3, 3b8e9415b, and 92d9cb252:

  • Language follows Chrome's language list. Without a saved choice, FSB walks chrome.i18n.getAcceptLanguages() (falling back to navigator.languages) and uses the first language it supports. English counts, so English-first users stay in English. Regional variants map to the nearest catalog (es-MX → Spanish, zh-TW/zh-HK/zh-MO → Traditional, zh-CN/zh-SG → Simplified); a bare zh takes a regional zh-* later in the list, else the time zone (Taipei, Hong Kong, Macau → Traditional). If nothing in the list is supported, Chrome's UI language decides, then English.
  • Picker only in Advanced settings. The selects in the side panel header and the control panel header are gone; a Language card sits next to Theme under Advanced settings › Appearance, uses the themed dropdown, and applies immediately (outside the Save flow, so unsaved edits survive a switch). The default option reads "Automatic". sidepanel.css is byte-identical to main again.
  • Dashboard chart translated. Legend, axis titles, tooltip, and date ticks follow the UI language and re-label live on a switch.
  • Release notes and changelog describe the automatic choice and the new picker location; the side-panel picker mock is gone from the 0.9.93 illustration.

Verified: both i18n gates, extension-ui-locale (261/261 on Node 24 and 20), delegation-sidepanel-ui, settings-card-select-clipping, validate:extension, the full npm test chain, and all 14 showcase gates. In headless Chrome for Testing: a zh-TW,en language list with an English UI renders 繁體中文 with no saved choice; en-US,ja stays English; picking 日本語 in the Advanced settings dropdown re-renders the control panel and an open side panel without a reload and keeps an unsaved edit; Automatic clears the override; the chart reads 入力トークン/出力トークン.

Merged #155 (official Cline support)

118ca8ff2 merges #155 into this branch, and f662c7d49 updates the release notes. Versions follow #155: extension 0.9.95 and fsb-mcp-server 0.11.5.

  • Version files took Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155's numbers hunk by hunk, so this branch's other edits in those files were kept. The manifest keeps default_locale and the __MSG_ext_name__ / __MSG_ext_description__ tokens at version 0.9.95, and npm run version:check reports extension 0.9.95 and MCP 0.11.5.
  • CHANGELOG.md has one 0.9.95 entry for the multilingual interface and Cline support. mcp/CHANGELOG.md keeps Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155's 0.11.5 entry and drops this branch's note that 0.11.2 paired with 0.9.93.
  • The release-notes section is relabeled 0.9.95, and its unit ids move from v0993 to v0995. The hero now covers both changes, the version chips read 0.9.95 and 0.11.5, and a new section 06 covers Cline: the shared settings file, the 1,800-second timeout, the settings kept on reinstall, and the install --cline rerun for existing users. It is translated into all seven site languages.
  • Cline adds only a client entry to onboarding (no translatable copy), so the extension i18n gates pass unchanged. The showcase catalogs merged cleanly, and a fresh ng extract-i18n matches them.
  • Checks on the merge: validate:extension and the full npm test chain pass. All 14 showcase gates pass, with 2,498 units × 6 locales and no extraction diff. mcp-version-parity passes 202/202 and version-sync passes. No locale's prerendered /release-notes shows "notes pending".
  • Add official Cline support; ship extension 0.9.95 and MCP 0.11.5 #155 is closed. Its commit is included here unchanged, and its branch is kept until this PR merges.

Client labels and Antigravity

35cd5179a changes the MCP client labels and replaces Windsurf with Antigravity. Versions stay at extension 0.9.95 and fsb-mcp-server 0.11.5, which is not on npm yet, so both ship together.

  • Labels. The extension allowlist renames FSB Autopilot to Autopilot (the overlay badge reads "Autopilot"), drops Windsurf, and adds Muse, Grok Bot, and Dots. The MCP server list gets the same three and drops Windsurf; it still leaves Autopilot out so an outside client cannot claim it. Telemetry counts the new labels by name. The telemetry server keeps accepting Windsurf, because extensions older than 0.9.95 still send it and one unknown label rejects the whole batch.
  • Grok Bot plugin. plugins/grok-bot now tells Bot to send client: "Grok Bot". Until the Web Store extension updates to 0.9.95, the extension there still rejects that label.
  • Installer. install --antigravity replaces install --windsurf. It writes ~/.gemini/config/mcp_config.json, the global file in Antigravity's MCP docs, and falls back to ~/.gemini/antigravity/mcp_config.json, which older releases read, only when ~/.gemini/config does not exist. Antigravity creates that file empty, so the config writer now reads an empty file as {} instead of failing to parse it. The platform count stays 21, and setup prints an Antigravity section.
  • Everywhere else. Onboarding, the client alias map, the register-time chip label, the showcase home and agents pages, the support FAQ, llms.txt, both READMEs, the skill references, and docs/mcp-custom-icons.md say Antigravity. A single-color Antigravity mark replaces the Windsurf logo in both asset folders. The four showcase units that named Windsurf keep their ids and line numbers in all seven catalogs. Windsurf's default-model cost row is gone.
  • Checks. The targeted suites pass: installer 135/135 (including an empty-file install, a rerun, uninstall, and a retired --windsurf), visual-session contract, philosophy parity, telemetry allowlist, pricing, onboarding, merged clients view, and tab follow. All 15 showcase gates pass, with no extraction diff, and sync-xliff-targets is a no-op. version:check, mcp-version-parity (202/202), and version-sync pass. In headless Chrome for Testing, onboarding shows Antigravity with its logo and --antigravity in the client fan, and the built showcase renders the Antigravity chip on the home and agents pages in English and Japanese.

Round 5: copy that follows a language change

40ad76a10 keeps templated copy live, and 0d42f5af0 fixes the 8 places a review found still English or stuck in the old language.

  • Templates stay live. Delegation cards, the status line, and the automation runner hand markExact() the English template and its subs instead of a filled line, so the node keeps its catalog key and re-renders on a switch. The overlay remembers the English behind its pill, detail, log lines, and action counter and redraws them unless something replaced them since.
  • Substitutions that are catalog copy are translated. line() now translates a sub value that is itself catalog English ("this site", "Unknown error", "Selected provider", a start-failure reason). Domains, provider names, and other raw values stay as sent. The side panel map also resolves Unknown error and Card, which only the control panel map had.
  • The 8 findings:
    • the stopped-run heading ("Agent stopped, N tabs released") is a template with a singular form;
    • the start failure with no detail and no consent challenge is a template;
    • the No API Key detail keeps its key;
    • every Grok Build test result keeps its key and wins over the idle hint, with a cataloged no-message fallback;
    • the overlay action counter redraws on a switch;
    • an explorer exception uses the "failed to start" template;
    • the payment confirmation translates "on $DOMAIN$", "on this page", and the Card fallback, while brand names and the domain stay as sent.
  • Catalogs. Six keys were added to each catalog (now 1,240). The release notes, changelog, and all seven site catalogs say 1,240.
  • Checks.
    • Both i18n gates and extension-ui-locale (284/284) pass, as do delegation-sidepanel-ui, providers-panel-ui, and the overlay and side panel suites.
    • All 15 showcase gates pass, with no extraction diff, and sync-xliff-targets is a no-op.
    • In headless Chrome for Testing, the side panel and control panel render each fixed line in German through the real page functions. Switching the saved language to Japanese re-renders all of them without a reload.

Round 6: counters and labels a language change missed

f9be8f267 fixes 7 more places that kept the previous language until their next update. Each was written as a filled string, so nothing recorded the key it came from. No catalog keys were added; the count stays at 1,240.

  • Side panel.
    • The "N actions completed" count is written through markExact() with its template.
    • A language change re-runs the delegated Stop sync, so its accessible name and the "Stopping Automation…" label follow the switch. apply() only knew the idle tooltip.
  • Control panel.
    • The crawl card's progress line, page count and Stop label carry live keys.
    • A crawl failure with no domain says the translated "Unknown" instead of the English word "unknown". The popup's model fallback had the same bug and is fixed too.
  • Overlay. One writeKeyed() helper records the key, template and subs behind a text or attribute, and refreshOwnedChrome() redraws it unless something replaced it since. It covers:
    • the trigger badge counts (the badge is now a watched root);
    • the crawl overlay domain and page lines, which now pass the real templates instead of concatenated English;
    • the replay speed button's accessible name and tooltip;
    • the action counter from round 5, which this replaces.
  • Checks.
    • extension-ui-locale: 301/301. Its drift guard now also checks the writeKeyed() fallbacks against en/messages.json.
    • Both i18n gates, validate:extension, and all 16 pretest and 305 test segments pass. 9e3568b adds writeKeyed() to the replay-player harness in lattice-replay-playback, which rebuilds the class from its helpers.
    • In headless Chrome for Testing, the seven widgets are drawn in German through the real side panel, control panel and injected content scripts, then the saved language is switched to Japanese. Every one re-renders with no further update.

Round 7: the popup follows a language change too

00c4949d8 closes the two popup gaps that round 6 fixed in the side panel. No catalog keys were added.

  • Action count. The collapsed "N actions completed" count is written through markExact() with its template, so it keeps its key and apply() redraws it on a switch.
  • Owner header and tooltip.
    • Both carry the owning agent's name, so they are not keyed: fill() would translate a name that is also catalog copy, such as "Autopilot".
    • The popup now registers a language-change hook, _refreshOwnerCopy(). It rebuilds "Owned by …" and the locked composer tooltip from the stored owner name, and one helper, _ownerLockTitle(), builds the tooltip.
  • Checks.
    • extension-ui-locale passes 309/309 and owner-chip passes 90/90. owner-chip now asserts the tooltip, because refreshOwnerChip() swallows its own errors.
    • Both i18n gates, validate:extension, and all 16 pretest and 305 test segments pass.
    • In headless Chrome for Testing, the real popup draws the count, header and tooltip in German. They re-render in Japanese after the saved language changes, with no further calls.

Merged #161 and #162

3d170bfbd merges #161 (dead MCP tools and background-agent leftovers) and d9a927b0e merges #162 (Online-Mind2Web harness). Versions stay at extension 0.9.95 and fsb-mcp-server 0.11.5, so #161's tool removals ship in 0.11.5 as a patch.

Round 8: saved lines follow a language change

11a3c3ae0 fixes three side-panel lines that kept the language they were saved or drawn in, along with the messages built the same way. No catalog keys were added; the count stays at 1,241.

  • Progress history. The log saved "Step N complete" in English while the live status used its template. It now saves the source next to the readable text, so a return to the tab replays the step in the current language. Old English rows are recognised and translated too.
  • Saved notices. Catalog sentences such as "No active automation to stop." were translated in the bubble but saved in English, so a tab switch brought them back untranslated. Assistant rows now carry an optional uiMessage: { english, subs } source, and replay re-keys it. User text, model output and tool rows stay raw.
  • Delegated failure bubble. The failure line was filled in before it was attached to Error: $ERROR$, so a language change could not rebuild it. A substitution can now be a nested source, so the template and the reason translate together without mixing languages.
  • Same pattern elsewhere. The recon start/failure/complete lines, the replay and session errors, and the background-communication, generic and stop errors now pass their templates instead of pre-translated text. The last four were keyed only through text(), so they are added to the exact map; without that they would have regressed to English.
  • Checks.
    • extension-ui-locale passes 1,751/1,751. Its new keyed-error check fails 24/24 without the exact-map entries.
    • Both i18n gates and validate:extension pass.
    • sidepanel-message-log-smoke (61), sidepanel-progress-tick-setter-routing (14), owner-chip (90), sidepanel-background-tab-completion (54) and delegation-sidepanel-tab-follow (62) pass.
    • All 16 pretest and 305 test segments pass.

Merged main (#163)

40d045384 brings in #163 (the Online-Mind2Web benchmark on the home page and README), which had made this PR conflict with main.

  • Home page. Lead the showcase and README with the Online-Mind2Web benchmark #163 replaced the feature cards with the benchmark leaderboard, so the cards this branch had edited are gone with them. The home schema keeps Lead the showcase and README with the Online-Mind2Web benchmark #163's benchmark feature and this branch's Antigravity wording.
  • llms and tests. The llms sources keep the benchmark sentence with 69 tools and 0.9.95/0.11.5, and llms*.txt are regenerated. npm test and the phase contract run both branches' new suites.
  • Translations. messages.xlf is a fresh extraction of the merged templates. Each locale takes every unit's translation from the side whose English source matches: 2,475 units from this branch and 16 from Lead the showcase and README with the Online-Mind2Web benchmark #163. sync-xliff-targets preserves all 2,491 units, with nothing seeded, changed or left for review.
  • Checks.
    • version:check, mcp-version-parity (346/346), benchmark-assets-parity (55/55) and the phase contract (1,212/1,212) pass.
    • All 16 pretest and 306 test segments pass.
    • All 14 showcase gates pass: 2,491 units × 6 locales, no extraction diff, test:ci 98, hreflang 848, marketing SEO on 28 pages, and bundle budgets.
    • Every locale's prerendered home page shows the leaderboard, Antigravity and 69 tools, with no Windsurf and no 68.

Round 9: Russian

dad5f26d5 adds Russian to the extension interface and f853713af adds it to the showcase at /ru/. Both pickers list it as Русский after Deutsch.

  • Extension. extension/_locales/ru carries all 1,241 keys; only the brand keys (ext_name, locale_seed_brand) stay "FSB". ui-locale.js adds ru to the public list, folder map and labels, and ru, ru-RU and ru_RU resolve to it automatically. verify-extension-i18n.mjs gains ru in its own locale list; without that, the gate would not have read the new catalog.
  • Showcase. messages.ru.xlf translates 2,120 units, and the other 372 copy their source by rule (315 allLocales entries, 56 with no readable text, and the new Готово label). The Angular and Express registries, angular.json, the localized 404, the sitemap and llms files, and the scripts that keep their own lists (sync, hreflang, bundle budgets) all gain ru. Accept-Language: ru-* and a saved fsb-locale=ru open /ru/.
  • Not mapped to Russian. Ukrainian, Belarusian and Kazakh browser languages do not fall back to Russian, in the extension or on the server; tests pin both.
  • Plurals. Russian has one/few/many forms, but the code picks between two English templates (count === 1). Count messages use the counter form («Действий выполнено: $COUNT$», «Сайтов: 3»), which reads correctly for any number, so no code changed.
  • v0.9.95 copy. 0.9.95 is unreleased, so its release notes and changelog now say eight languages and 1,241 keys in every site language, which also fixes the stale 1,240. The release-notes Ready cycle gains Готово, and its keyframes stretch to eight 2-second slots (rnLoc8, 16s).
  • How it was translated.
    • A glossary and style guide came first: formal «вы», 200+ terms, Latin brand and protected names, and Chrome's own «Дополнительные настройки».
    • The catalogs were then translated in 20 batches. Each batch was reviewed by a separate agent, which changed 309 strings.
    • Three cross-batch consistency passes changed 141 strings, mostly aligning the archived privacy policies with the current one.
    • A blind back-translation of 293 high-visibility strings flagged 5. All five are fixed:
      • the onboarding pin button read the same in both states;
      • «Задачи» for GitHub Issues clashed with automation tasks, so it is now «Баг-трекер»;
      • the consent question overstated the request;
      • one button read as advice;
      • the release-notes title was singular.
    • Every batch passed a validator built from the CI gates' own functions before assembly.
  • Checks.
    • Extension: extension-ui-locale 1,952/0; both i18n gates across 8 locales; validate:extension.
    • Translation drift and quality: 2,492 units × 7 locales. sync-xliff-targets is a byte-for-byte no-op.
    • Showcase: all CI gates pass. That covers Karma 99/99, an empty extraction diff, an 88-route build, hreflang 1,057/0, video SEO, marketing SEO on 32 pages, bundle budgets (ru main 5.1 KB gzipped) and the local crawler smoke 310/0.
    • All 16 pretest and 306 test segments pass.
  • Looked at in Chrome.
    • The extension's side panel, popup, onboarding, unlock, microphone page and all nine control-panel sections, in Russian against English. One wrapped button was shortened; nothing else clips.
    • 14 site routes at desktop and phone width, with no new page overflow.
    • The language cycle frozen at each slot shows exactly one label, including Готово at 7s.
  • Not changed. No webfont was added. Outfit, Poppins and Space Mono have no Cyrillic, so those headings fall back to system fonts character by character, as CJK already does. A native Russian read before release is still worth doing.

Release

Merging lands extension 0.9.95 on main (from 0.9.92) and fsb-mcp-server 0.11.5. 0.11.5 is not on npm yet, so npm-publish.yml publishes it and creates the mcp-v0.11.5 release on that push. 0.11.5 also removes start_visual_session, end_visual_session and back (from #161); a client that still calls one gets its MCP host's unknown-tool error, and go_back replaces back. The showcase deploys automatically. The extension itself is only released when an extension-v0.9.95 tag is pushed. If #149 merges later, its 1.0.0 is the larger version and stands; keep this PR's __MSG_ manifest tokens and default_locale when resolving that merge.

Follow-ups

  • The 0.9.95 release notes say MCP tool schemas are "byte-for-byte unchanged" (releaseNotes.v0995.047). That describes the language work, but 0.11.5 now also removes three tools; rewording it touches all eight site languages.
  • Remove dead MCP tools, pin the tool count to 69, and finish retiring background agents #161's own follow-ups: the privacy page's legacy-sync wording, and tool-registry descriptions that still mention start_visual_session.
  • Re-render script-built HTML (lists, cards, history) when the language changes without reopening the page.
  • Rarer toasts, automationError's Error: … line, a few overlay reconnect strings, and delegation-feed.js, providers-panel.js, voice-input-settings.js, speech-to-text.js.
  • Harden the copy gate: short strings, exact-map reachability, and attribute text.
  • Retry a failed catalog fetch instead of caching an empty catalog; escape ov() output placed in overlay innerHTML.
  • Dashboard labels that switch to English after a time-range change ("Tokens (7 Days)", "Cost Today") and the Agent Concurrency "N of M active" line.

Key Decisions

  • The override is stored as fsbUiLocale in chrome.storage.local. The website fsb-locale cookie is not read.
  • Manifest __MSG_ strings follow the browser UI language, so the name on chrome://extensions does not follow the in-extension choice.
  • The eight autonyms are hardcoded rather than catalog messages, so they read the same in every locale.
  • User, AI, and action messages, task titles, and model summaries stay raw. Provider names that fill a whole text node stay in English.
  • A new key ships in all eight catalogs in the same change, and the gate is hard from Phase 66.

LakshmanTurlapati and others added 11 commits October 11, 2026 05:45
The control panel is the largest package-owned surface, so its labels, hints, and status text need the same catalog override as the side panel.

Co-authored-by: Cursor <cursoragent@cursor.com>
First-run pages and FSB-authored overlay controls need the same locale override, while task titles and model summaries stay on the raw payload.

Co-authored-by: Cursor <cursoragent@cursor.com>
Leftover package sentences now fail CI unless they are cataloged, and the side panel and control panel can store a locale without restarting Chrome.

Co-authored-by: Cursor <cursoragent@cursor.com>
Align the extension, showcase, skill, docs, and store metadata at 0.9.93
through sync-product-version, add the 0.9.93 changelog entry and the
release-notes rail entry, and update the v1.3.0 planning notes to match.
MCP stays at 0.11.1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-13T20:22:46.183921Z 4555cb7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

LakshmanTurlapati and others added 18 commits October 13, 2026 15:22
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Define placeholders for the 52 copy_* messages that used $NAME$-style
  tokens without one. Chrome rejects such catalogs ("Variable $NAME$ used
  but not defined."), which blocked the extension from loading. The catalog
  gate now fails on any undefined placeholder.
- Move the locale boot on the control panel, unlock, and microphone pages
  into ui/ui-locale-page.js. MV3's default CSP blocked the inline scripts,
  so the language select stayed empty and static markup never translated.
- Expose _locales/*/messages.json as web-accessible so the content-script
  overlay can load catalogs; content scripts load only the active locale
  and English, fetching others on a language switch.
- Skip the chrome.i18n.getMessage fallback for named substitutions, which
  Chrome drops ("Actions: " instead of "Actions: 5").
- Restore the denial reason in the blocked-origin consent hint.
- apply() now only re-translates static text and attributes that still show
  a catalog message, and live nodes whose text it last wrote. Counters,
  provider headings, and status lines set by page scripts are left alone,
  and markExact clears stale live keys.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Reuse the booted fsbUiLocale instance when content scripts are injected
  again, so the overlay keeps its catalogs and language override.
- Store site map memory text in English through siteMapMemoryText(); only
  the toast is localized. Drop the now-unused copy_00834dcdc3 message.
- Split the microphone instruction into lead, label, and tail keys so the
  bold label survives apply(), and skip keyed nodes with child markup.
- Prune detached overlay roots in watchChrome so they are not retained.
- Keep mounted language pickers in step with changes made elsewhere.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Load the browser-language catalog in content scripts so overlay text
  drawn through chrome.i18n before boot() finishes is recognised and
  switched to the chosen language.
- Wrap 59 cataloged but unkeyed control panel text runs in data-i18n
  spans, and key the theme toggle aria-label.
- Translate cloned consent and pending-request template rows, and keep
  the API test button label keyed when runFullApiTest rewrites it.
- Make verify-extension-copy require a data-i18n (or translate="no")
  hook for static HTML text, including short labels.
- Apply static translations on onboarding boot and key the header tag
  with a new entry_onboarding_tag message in all seven locales.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Resolve version conflicts between this branch's extension 0.9.93 bump
and main's MCP 0.11.2 release in mcp/README.md and the llms source and
public files. Keep main's wording and historical release notes, and
regenerate the current extension/MCP pair with
`sync-product-version.mjs extension 0.9.93` so the current release
lines read extension 0.9.93 with fsb-mcp-server 0.11.2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… messages

The autopilot statusUpdate handlers compared the shown status text against
English transient labels, but addStatusMessage() now renders them through
fsbUiLocale. In non-English locales every run logged the translated
"Starting automation..." as a completed action. Add fsbUiLocale.isLine() and
use it in the side panel and popup so translated labels are still skipped.

Onboarding passed four strings through obExact() that were not in the exact
map, so they stayed English. Use the keyed ob() form, reuse entry_key_valid,
and add entry_key_required, entry_discovering_models, and entry_no_models to
all seven catalogs.

The copy gate missed these because it skipped strings inside template ${...}
expressions and sentences that open with a placeholder. Scan both, and cover
the cases with fixture and isLine regression tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…in JS

The side panel login and payment prompts, the history list, and the
action count label wrote English straight into innerHTML, so they stayed
English in every locale. The payment prompt also rendered catalog strings
(state labels, the no-methods detail) without looking them up.

Route that copy through a new spLine() helper backed by the exact maps,
add escapeAttr() for attribute values, and add copy_* keys in all seven
catalogs. Count labels become whole messages with a $COUNT$ placeholder,
with a singular form. The popup count label and the onboarding LM Studio
"Loaded chat model" label get the same treatment.

Drop promptDetail, handoffDetail, and safeSubtext from showLoginPrompt:
authPrompt is always null and safeSubtext was never rendered.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The automation overlay header, the trigger watch badge, the element
inspector check rows, and the crawl overlay were written as English
markup, and the replay speed button carried hard-coded English labels.
refreshOwnedChrome() fixed some of these after the fact, but the badge,
inspector rows, and crawl title never changed language.

Render them through ov() with entry_* keys, reusing the existing
automating, stop, planning, initializing, replay speed, and pages
messages. The watch badge counts now use $COUNT$ messages in both the
template and show(). ov() also fills $NAME$ placeholders when the locale
module is missing, as ob() and fsbUiLine() already do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The connection test card, session list and log viewer, replay step
detail, credential and payment cards, site explorer and research views,
memory list and detail views, and the site graph legend all built their
labels as English markup in options.js, so none of them changed language.

Add fsbUiHtml() (escaped fsbUiLine() for templates), fsbUiEscape() (also
escapes quotes, for attributes), and fsbUiMarkup() for "Step $CURRENT$ of
$TOTAL$", whose placeholders hold the step counter spans. Add panel_* keys
in all seven catalogs and panel-exact.js, and turn count fragments
("12 pages", "(3 forms)", "...and 5 more") into whole messages with
placeholders and singular forms.

The research empty state now uses the control panel's cataloged sentence,
which names the Reconnaissance section, instead of "Site Explorer".
providers-panel-ui.test.js loads the new helpers into the sandbox it runs
runFullApiTest in.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
verify-extension-copy.mjs skipped every string containing < or >, so
English written inside markup that JS builds (the login prompt, control
panel views, overlay chrome) passed the gate untranslated. It also
stripped comments with a regex that read the // in /^https?:\/\// as a
comment, which shifted string scanning for the rest of the file and hid
three plain sentences in sidepanel.js.

Replace the comment stripper and string extractor with one tokenizer that
skips comments and regex literals and recurses into ${...} expressions.
Strings that contain markup now go through the HTML rule: text and
labelled attributes must reach a locale helper or sit in a data-i18n or
translate="no" element, and a catalog match alone does not count.
Partial tags at ${...} boundaries are trimmed, &lt;/&gt; are decoded,
trailing separators no longer make a token copy, and GitHub is a brand.

Add a bad-markup fixture that the old gate passes, a panel-exact parity
check, and a test that every literal passed to the control panel and side
panel copy helpers resolves to a catalog key on that page.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Move nav label keys onto the generated .nav-label leaf so apply() translates them.
- Re-copy translated native options into the custom dropdown menus after boot and on language change, via a new refresh() export.
- Translate the replay play/pause toggle label and refresh the crawl overlay title.
- Write early unlock and microphone page text with fill() so boot re-translates it.
- Point phase contract and version parity tests at the archived v0.9.91 planning paths.
- Note in the changelog that fsb-mcp-server stays at 0.11.2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tes line pins

- The replay interpolation test evaluates ReplayPlayerOverlay on its own,
  so it now also loads the module's ov() locale helper that _renderSpeed calls.
- messages.xlf points releaseNotes.meta.title and .description at lines 88
  and 89, where the 0.9.93 rail entry moved them, so ng extract-i18n has no diff.
…ts pins

background.js now loads utils/ui-locale.js, so the lattice bridge smoke test
expects 335 importScripts mentions and 331 call sites.
…atus copy

- Overlay translates the English phase labels and default details the service worker sends (exact matches only, active-phase ellipsis kept) and sets lang on its own container; the host page is untouched.
- Side panel: Stop tooltip and pending label, delegation consent, preflight and run-card copy as $NAME$ templates with keyed start-rejection reasons, status lines and error bubbles through the exact maps; popup and options status and toast copy cataloged.
- ui-locale: exact-map lookups use own keys only (fixes the line('constructor') crash) and <html lang> follows the UI language on extension pages; the service worker no longer loads the module.
- 84 new keys in all seven catalogs; ja/ko/de entries keep Grok Build and LM Studio, and the i18n gate now protects provider names.
- Tests cover overlay label drift, template fills in every locale, the Stop tooltip, status lines and lang sync; drop the unused microphone errorMessage helper.
The release-notes page opened on "notes pending" for the current release.
Add the 0.9.93 hero and five illustrated sections (language picker, live
switch, localized manifest name, what stays as written, catalog gates),
translate the 63 new units into es, de, ja, ko, zh-CN and zh-TW, allowlist
the 27 invariant samples and identifiers, and point the llms summary at it.
Replace the placeholder "Version bump" entry with what 0.9.93 ships, dated
2026-10-18, keeping the version-alignment sentence the parity test pins.
Note in the MCP changelog that 0.11.2 pairs with extension 0.9.93, and match
the store listing summary to the manifest description.
The overlay, status and delegation strings added 84 keys to each catalog,
so the release notes and changelog now say 1,230 instead of 1,146.
Current Cline (VS Code extension, JetBrains plugin, and CLI) reads one
shared settings file, ~/.cline/data/settings/cline_mcp_settings.json,
and imports its old VS Code extension-storage file only once. The
installer kept writing that old file, so install --cline reported
success while FSB never appeared. It now targets the shared file,
honoring Cline's CLINE_MCP_SETTINGS_PATH, CLINE_DATA_DIR, and CLINE_DIR
overrides, and uses the old file only when no shared settings directory
exists. Cline entries set timeout: 1800 so run_task outlives Cline's
fixed 60-second request timeout, and reinstalls keep the timeout,
disabled, and autoApprove settings Cline stores on the entry.

Cline also joins the first-class client surfaces: the onboarding and
showcase install pickers with its logo, the client alias table and
owner-chip label (VS Code reports "Cline", the CLI "@cline/core"), the
telemetry label on both the collector and the server allowlist, and a
conservative pricing fallback. Adding it to the home install picker
shifts $localize line numbers, so the seven xlf catalogs were
re-extracted and synced; only line numbers changed.

Versions move to extension 0.9.95 and fsb-mcp-server 0.11.5 through
version:set:mcp and version:set:extension, with matching changelog
entries, and the Grok Bot plugin now pins fsb-mcp-server@0.11.5.
Merging publishes fsb-mcp-server@0.11.5 to npm automatically.
…p the picker in Advanced settings

- With nothing saved, FSB takes the first supported entry in Chrome's preferred-languages list (English counts), region subtags pick the variant, and the time zone only settles a bare zh; no match falls back to the UI language
- The language picker moves out of the side panel and the control panel header into a Language card under Advanced settings > Appearance; "Automatic" clears the saved choice
- The themed dropdown rebuilds a select's menu when its options arrive after page start, so the picker renders as a custom dropdown
- Settings card titles take the rest of the header row so long descriptions wrap beside the icon
- Side panel HTML/CSS pins updated; sidepanel.css is back to main
- Legend, axis titles and the tooltip token count go through the locale helper; the service worker, which loads analytics.js without it, keeps English
- New panel keys for "Input Tokens", "Output Tokens" and "$COUNT$ tokens" in all seven catalogs (Spanish keeps "tokens", allowlisted)
- updateChartLocale() re-labels the chart in place on a language change, and weekday ticks use the UI language
FSB now picks its interface language from Chrome's language list and
keeps the picker only in the control panel under Advanced Settings, so
the release notes and changelog say so. The hero, the default-language
bullet (now two bullets), the picker location, and the Automatic option
are reworded and retranslated in all six site languages.

The section 01 side-panel mock loses its language dropdown and the seven
autonym units behind it, along with their allowlist entries; the header
shows the panel's icon buttons instead and the status word still cycles.
The Automatic hint and the token-chart strings added four keys to each
catalog, so the release notes and changelog now say 1,234.
Versions follow #155: extension 0.9.95 and fsb-mcp-server 0.11.5. The
manifest keeps its localized name and description tokens, and CHANGELOG.md
carries one 0.9.95 entry for both the multilingual interface and Cline.
…port

The multilingual interface and official Cline support ship together as
0.9.95, so the section written as 0.9.93 would have left the current
release on "notes pending". The rail entry, documented versions, both
template guards, and every unit id move to 0.9.95; the hero chips,
the fsb-mcp-server line, and the footer now cite extension 0.9.95 with
MCP 0.11.5.

The hero now names both changes, and a new section 06 covers Cline: the
shared settings file install --cline writes, the 1,800-second timeout,
the settings a reinstall keeps, Cline labeling, and the rerun command
for existing users. All seven locales are translated and the invariant
literals are allowlisted.
LakshmanTurlapati and others added 16 commits October 19, 2026 20:26
…abels

Client labels:
- The extension allowlist renames FSB Autopilot to Autopilot, drops
  Windsurf, and adds Muse, Grok Bot, and Dots. The MCP server list gets
  the same three and drops Windsurf; Autopilot stays off it so an outside
  client cannot claim the extension's own label.
- Telemetry counts the new labels by name. The telemetry server keeps
  accepting Windsurf, since extensions older than 0.9.95 still send it and
  one unknown label rejects the whole batch.
- The Grok Bot plugin sends client "Grok Bot".

Antigravity:
- install --antigravity replaces install --windsurf. It writes
  ~/.gemini/config/mcp_config.json and falls back to the older
  ~/.gemini/antigravity/mcp_config.json only when ~/.gemini/config does
  not exist. An empty config file now parses as {} because Antigravity
  creates its file empty.
- Onboarding, client aliases, the register-time chip label, the showcase
  home, agents, and support pages, llms.txt, READMEs, skill references,
  and the icon-support doc say Antigravity, with a single-color
  Antigravity mark in place of the Windsurf logo. The four showcase units
  that named Windsurf keep their ids and line numbers.
- Windsurf's default-model cost row is removed from both pricing copies.
Templated lines were filled with line() before markExact() saw them, so
they lost their catalog key and stayed in the old language after a switch.

- markExact(node, template, subs) keeps the template's key and stores the
  subs; fill() and apply() translate a sub that is catalog copy itself
  (a provider fallback, a start-failure reason) along with its template.
- Delegation consent, preflight failure, and run-header copy hand
  templates and subs to markExact() instead of filled lines.
- The side panel status line and automation runner pass the template and
  subs through, so "Step N complete" follows a switch.
- The overlay records the English behind its pill, detail, and log lines
  and redraws them on a language change unless they were replaced since.
- The Grok Build compatibility line is translated on success.
- line() translates a substitution that is catalog copy itself ("this
  site", "Unknown error"); domains and provider names stay as sent. The
  side panel map also resolves "Unknown error" and "Card".
- The stopped-run heading is a template with a singular form, so it keeps
  its key and re-renders on a switch.
- A delegated start that fails without a detail or a consent challenge
  shows a template instead of a concatenated sentence.
- The No API Key detail is passed unfilled, so it follows a switch with
  its title.
- Every Grok Build test result keeps a live key that wins over the idle
  hint, and the no-message fallback is cataloged.
- The overlay redraws its action counter on a language change.
- An explorer exception uses the "failed to start" template.
- The payment confirmation translates "on $DOMAIN$", "on this page", and
  the Card fallback; brand names and the domain stay as sent.

Six keys were added to each catalog (now 1,240), and the release notes,
changelog, and site catalogs say so.
Seven widgets kept the previous language until their next update because
they were written as filled strings with no record of their key.

- Side panel: the "N actions completed" count goes through markExact()
  with its template, and a language change re-runs the delegated Stop
  sync so its accessible name and "Stopping Automation…" label follow.
- Control panel: the crawl card's progress line, page count and Stop
  label carry live keys. A crawl failure with no domain says the
  cataloged "Unknown"; the popup's model fallback had the same bug.
- Overlay: writeKeyed() records the key, template and subs behind a
  text or attribute, and refreshOwnedChrome() redraws it unless it was
  replaced since. It covers the trigger badge (now a watched root), the
  crawl overlay domain and page lines, the replay speed name and
  tooltip, and the action counter it replaces.

No catalog keys were added.
The playback test rebuilds ReplayPlayerOverlay from ov() and the class
body. The speed labels now go through writeKeyed(), so the harness
includes it and its WeakMap too.
…background agents

The server registered 72 tools while the READMEs said 69 and the website,
llms files and onboarding said 68. start_visual_session and
end_visual_session have only returned TOOL_REMOVED since 0.9.0, and back
duplicated go_back, so all three are gone and the server lists exactly 69.
mcp-version-parity now counts the built server's tools and fails when any
published claim disagrees: both READMEs and their per-category tables,
onboarding, the showcase pages and every translation, and the llms files.

Background agents were retired in v0.9.45rc1 but their data and code
stayed. On extension update, background.js now deletes bgAgents,
fsb_sync_queue, the old notice flag and any fsb_agent_* alarms. The
control-panel list of old agent names, extension/agents/, about 4,700
lines of commented-out agent code across the extension and both
dashboards, and the unused executeAutomationTask are removed. The server
drops /api/agents and the agent-only /api/stats; server-py drops its
agents, stats and SSE routers. The agents and agent_runs tables stay.
- The collapsed "N actions completed" count is written through
  markExact() with its template, so apply() redraws it on a switch.
- The owner header and the locked composer tooltip carry the owning
  agent's name, which stays as sent, so they are not keyed. The popup
  now registers _refreshOwnerCopy() with fsbUiLocale.onChange to rebuild
  both from the stored name; _ownerLockTitle() builds the tooltip.
- owner-chip.test.js extracts the new helper and asserts the tooltip,
  because refreshOwnerChip() swallows its own errors.
The count check only read "N tools", "N MCP tools", "N registered (MCP)
tools" and "N-tool" in raw text, and a file with no matches passed. Five
live strings still said 68: the onboarding "68 available" row, "68 MCP
tools" on the home and agents pages (with MCP wrapped in a span), "68 MCP
browser tools" in the agents schema, and "68 granular tools" in the
support FAQ, plus their translations in every catalog.

The check now strips markup before matching, also reads "granular",
"MCP browser" and "Tools ... N available" claims, and fails when a source
that should state the count no longer contains one it can read. Before the
strings were fixed it failed on exactly those five sources and four
catalog units; now all of them say 69.
…uncements

A completed or restart-lost run, and the side panel's polite live region, stayed in English after a language change.

Co-authored-by: Cursor <cursoragent@cursor.com>
Popup owner labels stay as sent, including catalog words and dollar sequences, while error reasons that are catalog copy still follow the language.

Co-authored-by: Cursor <cursoragent@cursor.com>
A reinstall was rewriting Continue and Cline configs when only property order differed, because equality compared serialized JSON.

Co-authored-by: Cursor <cursoragent@cursor.com>
…d2web/

Moves the benchmark from bench/online-mind2web to a top-level mind2web/
folder: the Claude Code + FSB MCP harness, the WebJudge-based judge, the
calibration scripts, configs, schema, reports, and the three published
result folders (final-review, benchmark-publication, final-reviewed).
Raw trajectories and caches stay gitignored.

Paths that depended on the old folder depth are adjusted, the previous
"assisted" naming is replaced with "reviewed", and the sha256 seals,
audit, and result files are re-keyed to the new paths with hashes
recomputed only for the files this move edited.
On a fresh clone the gated Online-Mind2Web dataset cache, the pinned
Claude CLI and the local postmortem sample are not present, so the
tests that read them now skip with a stated reason, matching the
existing dataset skips. The two tests that exercise the real MCP error
mapper skip until mcp/src/errors.ts passes native outcome fields
through, and run automatically once it does.
… into the multilingual UI branch

start_visual_session, end_visual_session and back leave the server in
fsb-mcp-server 0.11.5, which stays a patch release; both changelogs fold
#161's notes into the 0.11.5 and 0.9.95 entries. The conflicts were where
this branch had translated text or code that #161 edits or deletes:

- The popup and side panel keep their locale boot block, which shared a
  hunk with the deleted agent comments.
- Onboarding keeps its catalog lookups, and its four tool-count messages
  read 69 in all seven catalogs.
- The support FAQ, its seven xlf units and the llms sources keep this
  branch's wording with 69 tools.
- The six catalog keys used only by the removed sunset notice and agent
  comments are gone from every catalog and key map.
…ultilingual UI branch

Adds mind2web/ unchanged: the Claude Code + FSB MCP harness, the WebJudge
judge and calibration scripts, configs, and the published result folders.
Nothing outside mind2web/ changes. config/fsb-tool-names.json still lists
the 72 tools the benchmark ran against, including the three #161 removes,
because it records the surface the published runs used. The harness tests
give the same result as on #162 alone: 357 pass, 0 fail, 24 skipped.
The side panel filled or stored some of its own copy as finished strings,
so a language change or a tab-switch replay could not translate it again:

- Progress history saved "Step N complete" in English while the live
  status used the catalog template.
- Catalog notices such as "No active automation to stop." were translated
  in the bubble but saved in English, and replay showed the saved text.
- The delegated failure bubble received a filled sentence with an already
  translated reason, so it kept the language it was drawn in.

Assistant rows now save their catalog source next to the readable text
(uiMessage: { english, subs }), and replay re-keys it; model output, user
text and tool rows stay raw. A substitution can be a nested source, so
"Error: $ERROR$" and its reason translate together. Legacy
"Step N complete" rows replay translated too.

The recon, replay and session messages that pre-translated their text now
pass the template instead. The background-communication, generic and stop
errors were keyed only through text(), so they are added to the exact map
to keep translating after that change. No catalog keys are added.
… branch

#163 replaced the home page feature cards with the benchmark leaderboard,
so the cards this branch had edited are gone with them. The home schema
keeps #163's benchmark feature and this branch's Antigravity wording, the
llms sources keep the benchmark sentence with 69 tools and 0.9.95/0.11.5,
and the test chain runs both branches' new suites.

messages.xlf is a fresh extraction of the merged templates. Each locale
takes every unit's translation from the side whose English source matches
(2,475 from this branch, 16 from #163), so sync-xliff-targets preserves all
2,491 units with nothing seeded, changed, or left for review.
Russian becomes the eighth extension UI language. extension/_locales/ru
carries all 1,241 keys; only the brand keys (ext_name, locale_seed_brand)
stay "FSB". The picker lists it as Русский after Deutsch, and the
automatic language resolves ru, ru-RU and ru_RU to it through the
existing primary-subtag rule.

- ui-locale.js: ru in PUBLIC_LOCALES, the folder map and the native
  labels.
- verify-extension-i18n.mjs: ru in DEFAULT_LOCALES. The gate reads that
  list, not the folders on disk, so without it the catalog would ship
  unchecked.
- Ukrainian, Belarusian and Kazakh are not mapped to Russian; a test
  pins that alongside the ru-RU case.
- Russian has one/few/many plurals while the code picks between two
  English templates, so count messages use the counter form
  ("Действий выполнено: $COUNT$") that reads correctly for any number.

The catalog was translated in batches against a shared glossary, each
batch reviewed independently, then checked for cross-batch consistency
and by a blind back-translation of the most visible strings.
Russian becomes the eighth showcase locale. messages.ru.xlf translates
2,120 units; the other 372 copy their source by rule (315 allLocales
entries, 56 units with no readable text, and the new Готово label).
sync-xliff-targets is a byte-for-byte no-op on every catalog.

- Registries (Angular and Express), angular.json, the localized 404 and
  the scripts that keep their own lists (sync, hreflang, bundle budgets)
  gain ru. Accept-Language ru-* and a saved fsb-locale=ru open /ru/.
- The sitemap and llms files carry the Russian variant of every
  marketing route; lastmod and generated dates are unchanged.
- v0.9.95 is unreleased, so its release notes and changelog now say
  eight languages and 1,241 keys (also correcting the stale 1,240) in
  every site language. The Ready cycle gains Готово, and its keyframes
  stretch to eight 2-second slots (rnLoc8, 16s).
- The translation-quality gate also rejects Russian translator notes
  such as «(англ.)».
- Tests: ru cases for Accept-Language and the legacy redirects (which
  were also missing ko), the build smoke and parity locale lists, and
  the hreflang spec now counts LOCALES.length + 1.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant