ADR-v2-142 — Localize command grammars, not command semantics¶
Status: Proposed (2026-09-20)
Context: Chinese voice commands; commands/grammar.py; CommandIntent; application profiles.
Context¶
YazSes command recognition is currently English-specific. Tier 1 contains English regexes and English number-word normalization, while dispatch consumes language-neutral semantic actions such as:
undosavecopygo_to_lineselect_all
Chinese dictation without Chinese command recognition would type phrases such as “撤销” or “保存文件” instead of performing the corresponding action.
A naive implementation could duplicate the whole command/dispatch subsystem for Chinese. That would create separate behavior, safety fixes and editor mappings per language.
There is also an existing CommandsConfig.profile, but it represents application/editor behavior. Reusing it for spoken language would conflate two dimensions.
Decision¶
Keep semantic command IDs and dispatch language-neutral. Add language-specific Tier-1 grammars that map spoken phrases into the existing CommandIntent model.
Add a dedicated command-language setting:
Semantics:
autofollows the configured STT speech language when a grammar exists;enforces English spoken commands;zhforces Chinese spoken commands.
CommandsConfig.profile retains its current application/editor meaning.
The classifier tier order remains:
P1 Chinese support does not require a Chinese SLM.
Grammar organization¶
grammar.classify() remains the stable public API.
Internally, move/encapsulate English rules behind a grammar registry and add Chinese rules. The exact file layout may vary, but dispatch and action names must not be copied.
Locale-specific normalization¶
Chinese command parsing may normalize:
- terminal Chinese punctuation;
- ASR spacing around digits/Latin text;
- common Chinese numerals needed by commands;
- explicitly reviewed Simplified/Traditional phrase variants.
Normalization applies only to the command candidate. It must not rewrite ordinary dictation.
Consequences¶
Positive¶
- English and Chinese commands execute identical semantic actions.
- Safety fixes in dispatch apply once.
- More spoken languages can be added without duplicating action logic.
- Users can dictate in Chinese while deliberately keeping English commands, or vice versa.
- Application profile and spoken language remain orthogonal.
Costs¶
- The current monolithic English rule table must be refactored carefully.
- Phrase sets need native-speaker review.
- Chinese numeral parsing adds locale-specific logic.
- Contract vectors need a language dimension.
Alternatives considered¶
Translate text to English before the current grammar¶
Rejected. It adds an ML/translation dependency to a deterministic <5 ms path, creates privacy/latency complexity, and makes exact command safety harder to reason about.
Put Chinese alternatives into every existing English regex¶
Rejected. Mixed-language regexes become unreadable, untestable and difficult for contributors to own.
Duplicate grammar + dispatch for Chinese¶
Rejected. Semantic behavior would drift and every platform/safety fix would need duplication.
Reuse CommandsConfig.profile¶
Rejected. “VS Code” and “Chinese” are different axes. Overloading the field would make combinations impossible.
Acceptance constraints¶
- Existing English contract vectors remain valid.
- Chinese equivalent phrases emit the same action IDs/arguments.
- Unknown Chinese utterances remain dictation, never fuzzy commands.
- No Chinese rule invokes shell actions more broadly than its English semantic equivalent.
- Traditional/Simplified aliases are explicitly tested.
- Command parser changes do not globally normalize injected prose.
Implementation reconciliation (2026-10-29)¶
The grammar registry and a conservative Mandarin Tier-1 recognizer are implemented under src/yazses/commands/grammars/{registry,zh}.py. The classifier remains the existing language-neutral CommandIntent dispatch and preserves historical English call signatures. It selects a grammar through [commands] language = "auto" (following speech), honors an explicit pin with a warning, and fails closed to dictation if an unknown grammar is requested. The Mandarin branch does not consult the English Tier-2 SLM. Positive, negative, safety and bounded-numeral tests exist.
Linguistic release blocker: every phrase family in zh.py::PHRASE_REVIEW and the numeral policy in NUMERAL_REVIEW are marked provisional, not native-reviewed. Do not mark Mandarin commands as fully supported merely because regex tests pass. Separate Simplified and Traditional native reviews, negative colloquial prose, and action-by-action dispositions are required; high-impact terminal/open-ended actions stay excluded unless separately approved. See community task catalog and release gates.
The existing parser caps counts at 0–99 and line numbers at 0–999. Proposed expansions of abbreviated Han numbers must retain unambiguous bounds and all English parity/safety tests; this paragraph is not permission to change ranges.