# WS5 defect-class checker DATA for zh→ru (checkers.go). Pair-14 data-out: the DETECTION PATTERNS (regexes +
# literal probes) are DATA too, not engine code — a new pair ships its own. `category<TAB>key[<TAB>value]`.
# pattern values are VERBATIM (a regex or a literal probe); the checker ALGORITHM (compare counts, ×2 hours,
# suppress-if-ok) stays generic Go. The `*_re` keys are compiled; the others are literal strings.Contains probes.
#
# DC1 时辰 (double-hour): small CJK count → value (1 时辰 = 2 modern hours).
cjk_numeral	一	1
cjk_numeral	二	2
cjk_numeral	两	2
cjk_numeral	兩	2
# NB traditional-Chinese boundary (D39.79): the NUMERAL classes carry BOTH forms (两/兩=2 here, and in
# shichen_re and cheng_re) so a traditional-script count reads correctly. The pattern LITERALS (时辰, 千万,
# 数十万) stay simplified until the first traditional-Chinese book ships its own pack — this corpus has none.
cjk_numeral	三	3
cjk_numeral	四	4
cjk_numeral	五	5
cjk_numeral	六	6
cjk_numeral	七	7
cjk_numeral	八	8
cjk_numeral	九	9
cjk_numeral	十	10
# DC1: Russian hours-count word → value (the alternatives ru_hours_re captures).
ru_hour	один	1
ru_hour	два	2
ru_hour	двух	2
ru_hour	три	3
ru_hour	трёх	3
ru_hour	трех	3
ru_hour	четыре	4
ru_hour	пять	5
ru_hour	шесть	6
# DC6 register blocklist is NOT here (D39.79 Q4): the out-of-register lexis is a genre/BOOK property, so it
# lives in book.yaml `register_blocklist`, not this pair pack. register_neg stays an OPTIONAL pair category
# (a pair MAY ship target-register facts independent of any book), but zh-ru ships none.
# --- DETECTION patterns (pair-14 data-out). `pattern<TAB>key<TAB>value`; value VERBATIM. ---
# DC1: count before 时辰 (src); Russian «<count> час…» rendering (final).
# ru_hours_re carries an explicit RIGHT boundary: Go RE2 has no lookahead and its \b is ASCII-only, so the
# hour word is spelled out as its own paradigm and must be followed by a non-Cyrillic char or end-of-text.
# Without it the bare stem «час» matched INSIDE other words — «три части» read as «три час…» (a live false
# flag on ordinary prose, and a false ACTUATOR trigger once a repair loop acts on this class).
pattern	shichen_re	([0-9一二两兩三四五六七八九十])\s*个?\s*时辰
pattern	ru_hours_re	(\d+|один|два|двух|три|трёх|трех|четыре|пять|шесть)\s+час(?:ами|ах|ам|ов|ом|а|у|е|ы)?(?:[^а-яёА-ЯЁ]|$)
# DC1-half: 半个时辰 ≈ 1 час. The count group of shichen_re only accepts a NUMERAL, so 半 («half») — the single
# most frequent 时辰 form in the corpus — is invisible to it. This is a separate src probe + a target fire word:
# rendering 半个时辰 as «полчаса» halves the duration. Both keys are required for the probe to run (empty-probe
# guard); a pair that ships neither runs this sub-check inert.
pattern	halfshichen_re	半\s*个?\s*时辰
pattern	halfshichen_fire_word	полчаса
# hour_word_re: the BARE hour word of this target, used as the POSITIVE post-condition of a fractional-unit
# repair — the replacement must still STATE a duration, otherwise deleting the time expression would satisfy
# a detector that only asks whether the wrong form is gone. BOTH boundaries are explicit: Go RE2 has no
# lookaround and its \b is ASCII-only, so without a LEFT boundary the stem matches inside «полчаса»,
# «тотчас», «сейчас» — i.e. a reply that drops the duration and leaves any «-час» filler would pass.
pattern	hour_word_re	(?:^|[^а-яёА-ЯЁ])час(?:ами|ах|ам|ов|ом|а|у|е|ы)?(?:[^а-яёА-ЯЁ]|$)
# DC2 千万=10^7: src probe, ok-suppressor (case-insensitive), fire/veto words (case-sensitive Contains).
pattern	qianwan_src	千万
pattern	qianwan_ok_re	(?i)десят\p{L}* миллион|10\s*000\s*000|10000000
pattern	qianwan_fire_word	тысяч
pattern	qianwan_veto_word	миллион
# DC2 数十万: src probe, ok-suppressor, under-render fire (case-sensitive, per reference).
pattern	shushiwan_src	数十万
pattern	shushiwan_ok_re	(?i)сотн\p{L}* тысяч|нескольк\p{L}* сот\p{L}* тысяч|[1-9]00\s*000
pattern	shushiwan_fire_re	десятк\p{L}* тысяч
# percent 成=tenths: src expression; error-cue fraction; percent-form suppressor word.
pattern	cheng_re	([0-9一二两兩三四五六七八九十])成([0-9一二两兩三四五六七八九]?)
pattern	decimal_fraction_re	десят(?:ая|ых|ой|ые)|сот(?:ая|ых|ой|ые)|\d+[.,]\d
pattern	percent_word	процент
# --- UNIT RELATIONS (`dc_ratio<TAB>key<TAB>int`). The checker ALGORITHM compares counts; how many target
# hours one source time-unit is worth is a fact about THIS pair (1 时辰 = 2 h). It used to be a literal
# `n * 2` in generic Go, which would silently lie to a pair whose unit is not a double-hour.
dc_ratio	dc1_unit_in_hours	2
# --- DETAIL templates (`msg<TAB>key<TAB>template`, value VERBATIM; `{name}` placeholders are substituted by
# the checker). The counts are the engine's, but a line that says «时辰»/«千万»/«成» is pair SUBSTANCE: a
# second pair shipping its own patterns must not inherit a message about Chinese double-hours. Every key
# here is REQUIRED whenever this file exists (a detector that fires with nothing to say is a silent detector).
msg	dc1_fractional	DC1 时辰 (fractional): 半个时辰 ≈ 1 h rendered as «{fire_word}» (half of it)
msg	dc1_counted	DC1 时辰: {n}个时辰 rendered as «{rendered} час…» (counted as hours) instead of ~{expected} h (1 时辰 = {ratio} h)
msg	dc2_qianwan	DC2 千万=10^7 rendered as «тысячи» (≈10000× under) — a possible magnitude error (hyperbole risk, §5-A4)
msg	dc2_shushiwan	DC2 数十万≈several×10^5 rendered as «десятки тысяч» (≈10× under)
msg	percent_scale	成-percent: {tens}成{ones} = {pct}% rendered as a decimal fraction instead of a percentage (~{pct}%)
