Shortcut facts (this is why the contract test moved):
docs/public-surface-facts.json declared both `Tab` and `Shift+Tab` as
`when: "composer idle"`, and web/lib/public-surface-contract.test.ts pinned
that string into README.md and docs/KEYBINDINGS.md. Both halves are false —
crates/tui/src/tui/ui.rs:6978 gates Tab on `!app.input.is_empty()`, and
ui.rs:6363-6367 gates Shift+Tab only on the modal stack. The matrix now says
"composer empty" / "always (suppressed only under a non-Config modal)" and the
test asserts the corrected wording plus a negative guard so the idle claim
cannot come back. docs/MODES.md:24 already said "when the composer is empty";
it was the matrix and the test that were stale.
/runtime rendered the Chinese-primary H1 for every locale:
web/app/[locale]/runtime/page.tsx:84-88 had two byte-identical ternary
branches, both `Runtime & 集成 Integrations`. That contradicts
web/lib/i18n/dictionaries/types.ts:33-46 ("Never hardcode Han characters at a
call site") and docs/LOCALIZATION.md:80-82 ("no locale renders another
language's script by accident"). Every other page follows the correct pattern
(constitution/page.tsx:60-65). Fixed both branches; same class, smaller blast
radius, in feed/page.tsx:114 ("Section 03 · 动态" hardcoded in the EN branch).
FAQ provider list was 25 hand-maintained names against 40 real routes:
web/lib/facts.generated.ts derives 40 providers from `pub enum ApiProvider`,
and models/page.tsx already renders `facts.providers.length`. The FAQ omitted
15, including xAI, Baidu Qianfan, Meta Model API, and all four Model Studio
routes. Because ja/ko/ru/es/pt-BR/uk/vi/id fall back to English page bodies,
9 of 10 locales saw the stale list. The count is now derived from FACTS and
the enumeration is explicitly a sample ("including …") pointing at /models.
Other corrected claims:
- docs/subagents/page.tsx omitted the `consultant` role. It is one of the eight
in FLEET_ROLE_SCHEMA_VALUES (crates/tui/src/tools/subagent/mod.rs:376-385),
advertised to the model, and already in web/lib/content/vocabulary.ts:183-186.
- lib/media-manifest.ts:99-100 promised a recording "from the v0.9.2 release
candidate" on a live page (/docs/guide via components/session-media.tsx:47).
v0.9.2 and v0.9.3 both shipped; restated against 0.9.4.
- lib/docs-map.ts:39-40 advertised Nix and Scoop as contents of /install. Both
are real (docs/INSTALL.md:356, :507) but the site page has neither; the
description now names what the page actually contains.
- web/README.md:99/101/122/127 — "en / zh, every page is bilingual" (10 locales
route and non-zh get English bodies), a home-page section list naming four
sections that do not exist, and "EN ↔ ZH toggle" for what
components/locale-switcher.tsx:13-14 builds as an N-locale dropdown.
- docs/LOCALIZATION.md stated three different TUI key counts (1248 in the table,
1,153 at :234). `python3 scripts/check-tui-locale-parity.py` prints 1299 for
every pack. The zh-Hant row claimed 499/1248 "missing keys fall back to
English at runtime" — it is 1299/1299, so nothing falls back; the row now says
so and flags the PARTIAL_PACKS promotion as an open decision. The web
reference shape said 51/60 keys twenty-three lines above its own correct
52/62; check:locales prints 52/62.
Deleted (verified zero importers, no barrel, no glob loader, no CI reference):
- components/stat-grid.tsx — pulled from community/page.tsx in c268cc375, which
added the guard at lib/public-copy.test.ts:141 asserting the page must NOT
use it. That guard reads page source as a string and is kept.
- components/mermaid-diagram.tsx — its only consumer was removed in 5abe250f3e
("Cut: … the Mermaid architecture diagram"). Removed with it: the dead
`.mermaid-frame` rules in app/globals.css and the `mermaid` production
dependency, via `npm uninstall mermaid` so package-lock.json stays consistent
with package.json (CI runs `npm ci`, which hard-fails on drift).
Verified in web/: npm test exit=0 (28 files, 235 tests), check:facts exit=0,
check:locales exit=0, check:docs exit=0, lint exit=0.
FINISH-0.9.4 §0A Phase 1. The homepage, nav, footer, and layout were an
EN/ZH special case with a thin foreign fallback: English and Chinese copy
lived inline in the TSX behind isZh ternaries, and the eight routed partial
locales fell through to English for anything the dictionaries did not cover.
- HomeDict/ChromeDict extended to cover every visible homepage and shared
chrome string (chrome 51->52 keys, home 60->62).
- New web/lib/i18n/dictionaries/zh/{chrome,home}.ts, extracted faithfully
from the existing inline Chinese rather than retranslated.
- Real translations to exact key parity for ja, vi, ko, ru, uk, es, pt-BR
and id. {token} placeholders preserved; no sentence is concatenated
around a variable.
- Homepage, nav, footer and layout consume getHome(locale)/getChrome(locale)
for all ten locales. Every isZh/foreign user-copy branch on those surfaces
is deleted rather than left running alongside the new path.
- Footer link sets generate from the dictionaries via the new
web/lib/i18n/links.ts instead of hardcoded per-locale arrays.
Closes a real gap found on the way: app/[locale]/layout.tsx still carried an
isZh branch governing the skip-to-content link, which renders on every page
of every locale, and the home route's metadata title and description. Eight
locales were serving an English skip link and an English <title> behind
fully translated chrome.
Honesty: zh stays `shipped` because its first-class pages (install, FAQ,
community, contribute, models, runtime, roadmap, constitution) really are
translated — chrome alone never earns it, and config.ts now records that as
the reason. The other eight stay `partial` with a localized badge;
install/faq/community/contribute still fork on isZh, which is Phase 2 scope
and is exactly what keeps those locales partial.
Contract tests strengthened, not relaxed: public-copy and
public-surface-contract now assert the rendered contract and the EN
dictionary value instead of matching raw TSX strings, and the footer's
account-copy ban is asserted across all ten locales rather than the TSX alone.
Receipts, all exit 0: npm run prebuild, check:facts, check:locales,
check:docs, test, lint, build. Ten locales fetched from a dev server and the
markup inspected: no rendered dictionary keys; masthead, 深 seal,
ocean-framed codewhale-tui.png and the partial badge intact in every locale.
Add Indonesian (id) to codewhale.net as a partial locale, aligning website localization with the shipped Indonesian TUI pack (#4789) and README.id.md.
- Scaffold web/lib/i18n/dictionaries/id/chrome.ts and home.ts for shared chrome and landing page translations.
- Register id in web/lib/i18n/dictionaries/index.ts and flip status to partial in web/lib/i18n/config.ts.
- UpdateVitest suites (config.test.ts, dictionaries.test.ts, detect.test.ts) for exact key parity and regional tag matching (id-ID -> id).
- Update website status matrix in docs/LOCALIZATION.md.
Bring the canonical and Indonesian locale inventories up to the verified 1,248-key release state, record the current partial Traditional Chinese count, and include the newly shipped Indonesian README.
Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
- docs/LOCALIZATION.md: documents the seven new packs, the digits+letters
hotkey run, and the #4749 assessment deferring Galician (gl) and Basque
(eu) — smaller addressable populations than the shipped set, workable
es-419/pt-BR fallbacks for gl, no community request for either, and
both base tags already routing cleanly through the fallback chain.
- docs/evidence/v092-devanagari-terminal-shaping.md: the #4790 spike
evidence behind the grapheme-cluster truncation rewrite.
- crates/tui/locales/AGENTS.md: pack authoring contract updated for the
new locales.
Open scope, stated plainly: #4790's physical-terminal and native-review
halves are not closed by this work, and native-speaker sign-off for the
seven packs is tracked separately as human evidence.
Harvested from the v0.9.2 localization lane (#4749, #4790).
Admit ko, vi, and zh-Hant in the typed config schema and keep schema, Serde, native choices, and persisted settings aligned with Locale::shipped().
Surface zh-Hant as an explicit partial pack in the settings chooser, including a minimum-terminal badge and localized English-fallback detail, while independently checking the shipped, complete, and partial registries.
Update locale documentation and authoring guidance, and add focused schema, persistence, selection, render, and parity regressions.
Refs #4786
Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
docs/LOCALIZATION.md is the stated single source of truth for what the
project ships, plans, or has deferred — but it only described the website
and README surfaces. The TUI locale packs are the largest translation
surface in the repo (eight packs, 1128 keys each), and they were absent
entirely. So complete ko/es-419/pt-BR packs shipped while the matrix read
as though no Latin-American work existed, and zh-Hant's deliberate
478/1128 partial (#4057) appeared nowhere at all. Every check that would
have caught the drift was listed as Planned and unbuilt.
That matters more now than it did: the v0.9.2 wave adds six locales
(#4788, #4789, #4790, #4791, #4749). Adding them to a matrix that already
misdescribes reality compounds the problem once per locale.
- Add a TUI locale packs table with measured key counts against en.json,
and represent zh-Hant as partial with a pointer to its English-fallback
behaviour rather than omitting it.
- Add scripts/check-tui-locale-parity.py, which fails when a pack that
claims completeness diverges from en.json's key set in either direction
or drops a {named} placeholder. Declared partials are exempt from
completeness but still may not define keys English lacks, since the
English fallback can never surface those. PARTIAL_PACKS mirrors
Locale::is_partial_pack(). The check is file-based on purpose: it also
covers packs whose Locale wiring has not landed yet, and it attributes
a failure to a file instead of burying it in a test binary.
- Wire that gate and the already-existing scripts/check-readme-locales.sh
into the CI Lint job, and flip both Drift-checks rows off Planned. The
three rows that remain Planned now name their tracking issue (#3091)
instead of sitting bare.
- Extend "How to add a locale" into a three-surface checklist (TUI pack,
README, website) so the v0.9.2 wave follows one procedure rather than
six improvisations.
- Record the #4749 assessment of Galician and Basque: defer both. The
argument #4788 makes for Catalan is about review capacity, not market
size, and it does not transfer — neither language has a localization
community that could review a pack, Galician already has a workable
fallback in the shipped es-419 pack, and Basque is an isolate with none.
The website-side items from #4787 (npm run check:locales, and using the
existing "partial" LocaleStatus for zh-Hant in web/lib/i18n/config.ts)
depend on the #3091 dictionary layer and stay Planned under that issue.
Closes#4787
Refs #4749
Expose Blue Stage as the public theme name while retaining stable dark/light config identifiers. Centralize authored terminal glyphs and ASCII fallbacks, and document the measured Codewhale voice, visual ownership, and localization boundary.
Signed-off-by: Hunter B <hmbown@gmail.com>
Integrate the underwater TUI, message-first Operate, Fleet and Workflow reliability, expanded model/provider catalog, exact custom-route restoration, docs-first site, localization, packaging, and release metadata for the v0.9.0 candidate.
Harden endpoint-bound credential provenance, approval and goal UX, Fleet attempt fencing and crash recovery, large-workspace mention discovery, Kimi budgeting, and release asset/version gates. Include the stopship Fleet and Workflow fixtures used by release dogfood.
Verified with workspace fmt/check/clippy/tests on Rust 1.88, release-script and npm suites, 18-crate publish dry run, production web build, Docker build check, secret scan, dependency audit, and protected-state hash validation.
A full audit of every document claiming to define 0.9.0 or the next major
found that most of the old cutover plan already shipped in v0.8.68 under a
different route, while several committed documents still presented stale
obligations as binding — including a tracker asserting unshipped Multitask
work as Done and a handoff instructing removal of todo_* aliases that #4132
deliberately kept.
Give every roadmap-era document an explicit status: the workrooms RFC is a
future RFC with Phase 1 shipped; the external-memory cutline is marked
principle-only with its aspirational layer rows called out; the harness
cutline records its shipped schema/resolver lane; the file-decomposition RFC
is re-scoped honestly (config.rs was overtaken by ProviderLake while ui.rs
and main.rs grew); the 0.8.68 playbook, tracker, and completion handoff are
stamped Historical with their live residuals (#4175/#4177/#4178/#4179) and
their false-Done rows named. TOOL_SURFACE gets its version stamp and the
alias paragraph corrected to shipped-in-0.8.68; ARCHITECTURE gains the
workflow/workflow-js/lane crates; LOCALIZATION states its website-only scope
next to the TUI packs; REBRAND's product framing is neutralized to
every-provider-first-class per stewardship policy.
The present-day description of what a next-major release would actually
mean now lives in docs/AGENT_RUNTIME.md — scope, not a version promise —
and the six-module do-not-delete guardrail is salvaged from the handoff
into AGENTS.md where agents will see it.
- docs/LOCALIZATION.md: canonical tracking document for shipped,
planned, and deferred locales across website and README surfaces.
Includes Russian as next-priority and Arabic as RTL deferred.
- web/lib/i18n/config.ts: expand locale config with ALL_LOCALES
registry (9 tracked locales, 2 shipped) and LocaleStatus types.
Active `locales` array now derived from shipped status, enabling
>2 locale support without hard-coded arrays.
- web/components/locale-switcher.tsx: rewrite from hard-coded en↔zh
toggle to support any number of shipped locales (2 = toggle,
3+ = dropdown). Reads from ALL_LOCALES.
- web/middleware.ts: Accept-Language detection now matches against all
shipped locales instead of hard-coding Chinese-only detection.
- scripts/check-readme-locales.sh: symmetry check verifying main
README links all locale READMEs and no orphaned locale files exist.
Harvested from PR #3763 by @idling11
Co-authored-by: idling11 <8055620+idling11@users.noreply.github.com>