Skip to content

feat: add Russian-language support to the corrections signal (#6)#28

Merged
HumanBean17 merged 1 commit into
mainfrom
feat/ru-correction-support
Jul 18, 2026
Merged

feat: add Russian-language support to the corrections signal (#6)#28
HumanBean17 merged 1 commit into
mainfrom
feat/ru-correction-support

Conversation

@HumanBean17

Copy link
Copy Markdown
Owner

Closes #6.

Why

The corrections signal's keyword catalog (src/adapter/correction.ts) was English-only, so Russian course-corrections (нет, не туда, стоп, отмена, …) went undetected — they never set the correction flag, under-counting friction on any EN/RU bilingual session. DESIGN.md §4.2 already listed «не туда» as a correction example.

What changed

  • Additive per-language catalog. Replaced the hardcoded English token arrays with LANG_CATALOGS: { en, ru }, mapped to the same four shape values. Per-shape token lists are merged + normalized + deduped once at module load; the matching loop is language-agnostic. Adding a language is now a catalog-only change — no matching-logic edits. Latin/Cyrillic are disjoint scripts, so the merge cannot introduce cross-language bleed.
  • Cyrillic normalization at the input boundary, applied symmetrically to both input text and tokens: lowercase, ёе, curly/smart quotes → straight apostrophe, every other non-letter/digit/apostrophe → space, whitespace collapse. So «нет,»нет, ещёеще, and hyphenated по-другому unifies with its two-word form.
  • Unicode word boundary. startsWithToken now uses \p{L} for continuation, so нет no longer matches нетворк / неточный — and the prior English semantics (apostrophe + digit = boundary) are preserved exactly.
  • Privacy contract intact. Still emits only {matched, shape}; raw text is consumed and discarded.

Tests

  • test/correction.test.ts: RU coverage across all four shapes; affirmations (да/отлично/точно) do not match; normalization («нет,», стоп!, ёе cross-form); word-boundary anti-false-positives (нетворк/неточный); cross-language bleed; shape-precedence lock (по-другому → redirect).
  • test/privacy.test.ts §(f): pipeline-level Russian prose-leak assertion across human/json/calibrate + warnings, with a load-bearing corrections >= 1 check proving the text was actually ingested/detected (so non-leak isn't vacuously true).
  • No English regression — all 11 prior correction.test.ts cases stay green.

Docs

EN+RU note added to CONSUMER_GUIDE.md (FAQ), DESIGN.md §4.2, and the ARCHITECTURE.md module-table row.

Verification

npm run build ✓ · tsc --noEmit ✓ · 423 tests pass.

Review

Reviewed via requesting-code-review (3 parallel reviewers: detector core / tests+privacy / docs). No Critical. Applied: неверно one-word synonym gap, vacuous ёе test fix, privacy §(f) load-bearing assertion, misleading да test rationale, dead по-другому duplicate removal, precedence-comment correction, positive-precedence + cross-bleed test strengthening, "stripped"→"ignored" wording. Accepted as-is: bare no, length-floor edge, short-token substring FP risk (consistent with pre-existing English), micro-allocation.

🤖 Generated with Claude Code

The corrections keyword catalog was English-only, so Russian
course-corrections (нет, не туда, стоп, отмена, …) went undetected.

Refactor src/adapter/correction.ts from hardcoded English token arrays into
an additive per-language LANG_CATALOGS {en, ru} table; adding a language is
now a catalog-only change (matching logic is language-agnostic). A shared
normalize() — lowercase, ё→е, curly→straight apostrophe, punctuation→space,
whitespace collapse — is applied to both input and tokens, so «нет,» and нет
match identically. Word-boundary check upgraded to Unicode \p{L} so нет no
longer matches нетворк; English behavior is preserved exactly. Emits only
{matched, shape} — privacy contract intact.

Tests: RU coverage across all four shapes, affirmations (да/отлично/точно),
normalization (guillemets, ё→е cross-form), word-boundary anti-false-positives,
cross-language bleed, shape precedence; plus a pipeline-level Russian
prose-leak assertion in test/privacy.test.ts with a load-bearing
corrections>=1 check that the text was actually processed.

Docs: EN+RU note in CONSUMER_GUIDE FAQ, DESIGN §4.2, ARCHITECTURE module row.

Co-Authored-By: Claude <noreply@anthropic.com>
@HumanBean17
HumanBean17 merged commit 58e1606 into main Jul 18, 2026
2 checks passed
@HumanBean17
HumanBean17 deleted the feat/ru-correction-support branch July 18, 2026 16:02
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.

Add Russian-language support to the corrections signal

1 participant