Egbe Companions · Features

Accessibility & Localization

A focused page within the Egbe Companions Features documentation. The full map and every sibling page live in the Features hub.

4sections10 minread1diagram

On this page

V6 — Egbe, the agentic-companion universe — makes two design choices that collide head-on with accessibility and localization, and the collision is the whole reason this page exists. First, the game's primary command channel is voice: a steward speaks an objective and Vac parses it. Second, its primary content is not authored — it is a continuous stream of generated agent dialogue, Chronicle narration, and the Book of the Ori. A player who cannot hear or speak must lose nothing, and a player in Madrid or Lagos must hear their companion speak their language and be no less governed for it. Neither of those is a string table you can hand to a translation vendor. The first is an input-parity problem the size of the entire control scheme; the second is a generation-time problem that reaches into the cognition kernel itself.

This page describes how V6 meets both — and it draws the same hard line V2–V5 draw between code that runs, gates that machine-check declared facts, and intent recorded honestly in a manifest. Some of this surface is real, tested code (the Tier-2 fallback client's accessibility surfaces in TypeScript; the VR comfort options in Unreal C++; the per-locale dialogue seam in the cognition stack). Some is machine-checked policy over JSON (the axe-core gate artifacts, the region-rating/residency matrix, the readiness gate). And one load-bearing thing — natively generated localized speech — is a real, tested seam that needs a wired hosted model to actually produce native text at runtime, which the repository deliberately does not pretend to have. The section hub is ../V6_features.md.

What ships, honestly#

The boundary between "implemented and tested" and "declared intent" runs cleanly through this cluster, and stating it up front keeps nothing below oversold.

  • The Tier-2 accessibility surfaces are real TypeScript. The web-fallback client (apps/v6/egbe-web-fallback/src/app.ts, ~4,900 lines) builds the no-microphone capability routes, the speaker-tagged readable transcript with live text-scale/contrast/history controls, the cognitive-load reductions, and the reduced-motion/reduced-stimulus/plain-language modes as actual rendered DOM with computed reductions — not stubs. Its e2e/egbe-web-fallback.spec.ts (~600 lines) drives those surfaces under Playwright.
  • VR comfort is real, tested Unreal C++. V6/ue/Source/V6UI/Private/V6VRComfortOptions.cpp (387 lines) and its header build the vignette / snap-turn / seated-play / comfort-intensity panel, persist it across V1 identity, and restore it before the first VR frame; the V6.XR.VRComfort.OptionsPersistenceReview automation test (151 lines) was built and run on the on-box UnrealEngine 5.5.4 with Result={Success} (V6/ue/Saved/CI/v6-vr-comfort-automation-ueagent.log).
  • The per-locale dialogue seam is real and unit-tested — but template-backed in-repo. libs/v6/cognition-stack/src/index.ts carries a genuine native generation path through the Iris CognitionGateway with a §9.5 quality judge/refine (generateLocalizedAgentDialogueViaGateway), exercised by localized-dialogue-gateway.spec.ts. With no model wired — the repo's state — it falls back to a deterministic per-locale template and reports that honestly (generatedNatively: false, source: 'template-fallback'). It never claims native generation over a static string.
  • The a11y/loc/region gates are machine-checked JSON. The seven artifacts under V6/accessibility/ and V6/localization/, plus the readiness manifest V6/release/accessibility-localization-security-cert-readiness.v6release.json, are validated by scripts/v6/verify-v6-accessibility-localization-security-cert-readiness.mjs (699 lines). A green gate certifies the declared posture; an axe-core "pass" in a manifest is a declaration the verifier enforces, distinct from the live Playwright run that produces it.
  • The shared @oshun/i18n registry is not wired into V6. It exists (libs/oshun/i18n/src/index.ts, with OSHUN_LAUNCH_LOCALES spanning eight RTL-aware platform locales), but V6's generated-text localization defines its own three-locale profile set in the cognition stack and does not import it. Authored-string reuse of the V1 pipeline is doctrine described below, not an in-repo V6 dependency edge.

Accessibility#

The named conformance standard is WCAG 2.2 Level AA for every web-rendered and app surface — the Tier-2 fallback client, the Egbe Steward App, Egbe Studio, and the Chronicle reader — evaluated by axe-core in CI alongside the per-platform console/mobile/VR accessibility checklists for the Unreal client. The governing V6-specific concern is that voice and generated dialogue must both be fully operable and fully legible without hearing or speaking.

Non-voice parity — the load-bearing guarantee#

Because Vac is voice-first, the single most important accessibility claim is that every Vac capability has a complete non-voice equivalent. The intent grammar is authorable through a structured UI — a verb picker, target picker, and constraint / priority / deadline / forbidden-line fields — that emits the identical structured intent the voice parser produces; conversation is text chat; squad comms run fully by text. V6/accessibility/vac-no-microphone-a11y.v6a11y.json enumerates the four capability routes (intent-grammar, text-dialogue, squad-comms, negotiation-routing), each completeWithoutMicrophone: true, keyboardOperable: true, and axeVerified: true, with microphoneRequired: false and passedCapabilityCount: 4. The verifier asserts exactly those four pass on desktop- and mobile-chromium. Voice is a convenience, never a requirement.

Readable transcripts and cognitive-load controls#

All squad comms, dialogue, and negotiation render as speaker-tagged, timestamped, scrollable transcript lines, with live controls for text size, contrast mode, and history depth. In app.ts these are real types (VacTranscriptAccessibilitySettings, VacAccessibleTranscriptLine) with setters wired to the UI; comms-transcripts-a11y.v6a11y.json checks nine boolean guarantees (speakerTagged, timestamped, resizable, highContrast, historyDepthAdjustable, …) and ships a large / high / full default.

Cognitive load is controlled by measured reduction, not assertion. The Chronicle's brief mode drops visible beats from 5 → 3; emergent-arc prompts go 3 → 1 (reduced) → 0 (muted); the homestead-rest pace cuts return milestones 8 → 2 and cognition spend 11,520 ms → 720 ms. The verifier does not trust the booleans alone — it arithmetically requires chronicleBriefBeatCount < chronicleFullBeatCount, emergentMutedPromptCount < emergentStandardPromptCount, and homesteadRestCognitionMs < homesteadNormalCognitionMs. A control that claimed to reduce load without reducing the number fails the gate.

Reduced-stimulus, plain language, and screen-reader support#

reduced-stimulus-screen-reader-a11y.v6a11y.json records that reduced-motion dampens 3D scene animation (motion multiplier 1 → 0) and reduced-stimulus lowers the ambient rendered-agent count 18 → 6, and that the roster, Chronicle, dossier, intent builder, and Steward App are screen-reader ready. Crucially, no game-critical information is color-only or numbers-only: bond is a plain-language relationship summary, not a raw meter, and arc state is described in words — the AccessibilityRelationshipMode of 'plain-language' in app.ts is the concrete expression of that doctrine. This artifact is verifiedBy three runners — @axe-core/playwright, react-native-accessibility-props (the Steward App), and ue-platform-a11y (the console/VR client).

VR comfort — real Unreal C++#

The intimate VR stewardship surface carries comfort options as genuine engine code. FV6VRComfortOptionsSettings exposes vignette (off/light/strong), snap-turn (smooth → snap-45), standing/seated play, a seated eye height, and a 0–1 comfort intensity; FV6VRComfortOptionsPresenter builds the panel, a comfort-first preset, and a launch comfort-review report. The settings persist across V1 identity, encrypted at rest, and restore before the first VR frame — so a motion-sensitive player never sees a single uncomforted frame. The on-box automation passed, and the V6/ue/Build/XR/VRComfortOptions.json contract records a QA-signed-off comfort review (48 evaluated users, sickness-report rate 0.0417 under the 0.05 threshold). The review numbers are declared QA data; the widget, persistence, and validation logic are running C++.

Localization#

V6's localization load is different in kind from a normal title's. The authored surfaces — UI chrome, district names, store copy, the Steward App — follow the V1 string-translation pipeline as doctrine. But the bulk of V6's text is generated, so its localization is a generation-time concern. V6 launches with exactly three locales — en-US, es-ES, yo-NG — pinned in region-rating-residency.v6loc.json (checkedLocales). Adding a locale means adding it to that artifact and passing every per-locale gate.

Three locales, governed per locale#

The cognition stack defines CognitionLocaleCode = 'en-US' | 'es-ES' | 'yo-NG' and a COGNITION_LOCALE_PROFILES table giving each locale its language name, native name (English / Español / Yorùbá), text direction, a native-language generationInstruction, and — the governance hook — an isisPolicyLocaleRef and sophiaGroundingLocaleRef. The type carries a CognitionTextDirection of 'ltr' | 'rtl', so RTL is representable; all three launch locales ship 'ltr'. Per-locale governance is not decorative: every localized line is run through the same Isis behavior-policy and Sophia grounding as an English one, keyed to that locale's refs, so a localized agent is no less governed and no less grounded.

Localizing agent speech — generate, don't translate#

This is the heart of the page. V6 does not generate English and machine-translate it. The cognition stack's LocalizedDialogueSource type is precisely 'model' | 'template-fallback' — there is no 'translation' source, and a code comment states the rule outright: V6 never machine-translates; localized dialogue is either natively model-generated per locale or a governed per-locale template.

The real path is generateLocalizedAgentDialogueViaGateway. It hands the steward utterance, objective, persona tags, and locale to the Iris CognitionGateway, which generates in the target language, runs the §9.5 dialogue-quality judge/refine, and returns a verdict. A 'blocked' verdict withholds the line (approved: false) even when Sophia grounding and Isis policy would clear it; a gateway error fails loud with no template fallback. The honesty seam is strict: generatedNatively is true only when a real model produced the text. In the repository — no model wired — generateLocalizedAgentDialogue serves a deterministic per-locale template (e.g. "I can answer in English and keep the market bridge inside consent and the Ori record." / "Puedo responder en español…" / "Mo lè dáhùn ní Yorùbá…") and reports generatedNatively: false, source: 'template-fallback', translationFallbackUsed: true. The committed generation-time-localization.v6loc.json declares the intended shipped state (nativeGenerationLocaleCount: 3, translationFallbackUsed: false) — the target a wired model satisfies. The gateway spec proves the native path works against an injected provider; producing genuinely native text in CI is what the wired model, absent here, would add.

flowchart TD S[Steward utterance + objective + locale] --> P[cognitionLocaleProfile<br/>en-US / es-ES / yo-NG] P --> Q{Hosted model wired?} Q -- yes --> G[CognitionGateway.generate<br/>native language] G --> J{§9.5 quality judge/refine} J -- blocked --> W[Withhold line<br/>approved = false] J -- cleared --> A[assembleLocalizedDialogue<br/>generatedNatively = true] Q -- no --> T[Deterministic per-locale TEMPLATE<br/>generatedNatively = false] T --> A A --> SG[Sophia grounding<br/>per-locale ref] A --> IP[Isis behavior policy<br/>per-locale ref] SG --> D{grounded AND approved AND not blocked?} IP --> D D -- yes --> SHIP[Ship native line] D -- no --> W

Cultural grounding, region ratings, and residency#

A grounded backstory references real cultural, historical, and geographic fact — which reads differently across cultures — so each locale gets an independent cultural-accuracy and -sensitivity review. locale-cultural-backstory-grounding.v6loc.json requires three review roles per locale (source-grounding, local-cultural-adapter, community-advisor); a backstory that fails review is blocked for that locale, not shipped softened. These roles are declared human responsibilities, gated by role coverage, not something the repo can perform on its own.

Region rating and residency are handled independently of locale. region-rating-residency.v6loc.json carries a profile per launch locale: en-US is ESRB Mature 17+ (US zone, full emergent drama, Aye age-gated-17); es-ES is PEGI 16 (EU residency + compute zone, softened drama); yo-NG is IARC 12+ (brief drama, Aye deferred-pending-local-review, with residency pinned to the us zone). The artifact's invariant localeIndependentFromResidency: true encodes the principle that choosing Yorùbá is a content choice, not a data-placement choice — the V1 account-home-zone residency posture governs where Ori data lives regardless of language.

Where the shared i18n stack fits#

The platform's @oshun/i18n is the authored-string registry — a real, RTL-aware locale set (en-US, es-US, fr-FR, de-DE, ar, he, ja-JP, pt-BR) used by the broader Oshun web apps. V6 does not consume it: its three launch locales are a generated-text concern owned by the cognition stack, and its authored-string side is described as following the V1 workflow rather than wiring that package. Keeping the two separate is deliberate — a generation-time locale and an authored-string locale are different artifacts with different review paths, and conflating them is exactly the kind of shortcut the honesty convention forbids.

Verification and the launch bar#

Everything above rolls into one launch-blocking gate. verify-v6-accessibility-localization-security-cert-readiness.mjs confirms every a11y and loc artifact exists and is internally consistent (the cognitive-load reductions actually reduce, the three locales are native-declared with no translation fallback, the region profiles meet their ratings, the VR comfort review is QA-signed), that V6_TODOS sections 39/40/44/45 carry no unchecked boxes, and that the readiness gate is chained into the CI workflow after the governance/safety gate. The corresponding launch-readiness line in V6_TODOS is honestly marked [~] — partial — because final certification needs a cooked, signed, vendor-approved build that a stand-in repo cannot produce, the same caveat the architecture companion states in full.

This page is one of three under Trust, Safety, and the Launch Bar. Its safety and commerce sibling — persona governance, welfare, operator audit, and the storefront — is ./governance-safety-and-commerce.md. The rollout sibling — region staging, cross-platform certification, and cross-progression continuity, which consume the region-rating/residency matrix above — is ./cross-platform-rollout-and-launch.md. The architecture companion, which holds the unforgeable view of the readiness gate and the eval/cost/welfare contract gates, is ../architecture/performance-build-security-testing-and-launch.md.