R14-TQ1-R4-R3: align generator and validator lexical contract

#54
Files changed (1) hide show
  1. core/pipeline_agent.py +30 -5
core/pipeline_agent.py CHANGED
@@ -3751,6 +3751,23 @@ Output only the repaired section."""
3751
  'contamination_policy': 'Treat sustained untranslated English prose as a repair signal; normal acronyms, model names and protected terms are allowed.',
3752
  }
3753
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3754
  @classmethod
3755
  def _translation_language_rule(cls, target_lang):
3756
  profile = cls._translation_language_profile(target_lang)
@@ -3760,7 +3777,11 @@ Output only the repaired section."""
3760
  core = 'Use idiomatic academic Kazakh with correct case and possessive suffixes, person/plural endings, vowel harmony, consonant assimilation, natural word order, and correct Kazakh-specific letters. Translate directly from English and avoid Russian syntactic calques.'
3761
  else:
3762
  core = 'Use formal academic Simplified Chinese with explicit concepts, natural Chinese syntax, clear hierarchy, and logically connected claims. Avoid carrying English nominalization and clause order into Chinese mechanically.'
3763
- return core + ' ' + profile['term_policy'] + ' ' + profile['contamination_policy']
 
 
 
 
3764
 
3765
  @classmethod
3766
  def _russian_contamination_evidence(cls, source, target, glossary=None):
@@ -5062,10 +5083,11 @@ SECTION: {section_name}
5062
  'items': [{'id': row['id'], 'english': row['english'], 'target': row['target']} for row in rows],
5063
  }
5064
  profile = self._translation_language_profile(target_lang)
 
5065
  system_prompt = f"""You are a bilingual academic translation QA classifier for {target_lang}.
5066
  Review EACH claim independently. Do not rewrite and do not provide free-form explanations. Check semantic equivalence and language quality: omissions/additions, negation, uncertainty, association-versus-causation strength, terminology, grammar, language contamination, citation attachment, and acronym attachment.
5067
- LANGUAGE ADAPTER: {profile['adapter_id']}; morphology={profile['morphology']}. {profile['term_policy']} {profile['contamination_policy']}
5068
- For Russian, do not flag a terminology error merely because a translated term is inflected for grammatical case/number/gender. Russian LANGUAGE_CONTAMINATION includes sustained unprotected English prose and ordinary untranslated English lexemes; never use it for protected acronyms, AI/LLM/SEM, model or tool names, variable names, citations, canonical glossary terms, or source-matched proper names/titles. For Chinese, ordinary untranslated English lexical words are contamination while protected technical objects remain legal. For Kazakh, do not flag a terminology error merely because productive suffixes attach to the correct term stem. Kazakh LANGUAGE_CONTAMINATION includes ordinary untranslated English lexemes and clearly Russian lexical/syntactic intrusions not justified by shared international terminology; Cyrillic script or absence of Kazakh-specific letters alone is never sufficient evidence.
5069
  Return valid JSON only in this exact form: {{"items":[{{"id":"SP-P000001-C000001","ok":true,"codes":[],"evidence_codes":[]}}]}}.
5070
  If ok=false, codes MUST contain only values from allowed_issue_codes. For SEMANTIC_DRIFT, NEGATION_DRIFT, CAUSALITY_STRENGTH_DRIFT, UNCERTAINTY_DRIFT, OMITTED_CLAIM, or ADDED_CLAIM, evidence_codes should identify the affected semantic dimension using only: {sorted(allowed_semantic_evidence)}. For GRAMMAR, evidence_codes should identify the narrow grammatical defect using only: {sorted(allowed_grammar_evidence)}. Use the narrowest supported evidence; use MEANING_CHANGED or GRAMMAR_UNSPECIFIED only when the narrower dimension cannot be identified from the pair. Do not invent an error dimension. Never return numbered prose, examples, quotes, or corrective wording. Never return replacement text. Return every supplied id exactly once."""
5071
  response = self.call_deepseek(
@@ -5604,12 +5626,13 @@ Each code must be one of: {sorted(allowed)}. Return one or more specific dimensi
5604
  ]
5605
  if grammar_evidence_codes:
5606
  evidence_payload['grammar_evidence_codes'] = grammar_evidence_codes[:4]
 
5607
  retry_mode = (
5608
  '\nCLAIM SOURCE REGENERATION. The previous target wording has failed bounded repair and MUST NOT be used as drafting context. Generate a fresh translation of only this one claim directly from the frozen marked English source. '
5609
  if strategy == 'SOURCE_REGENERATE' else
5610
  '\nCLAIM QUALITY RETRY. Repair only this one claim. '
5611
  )
5612
- effective_prompt = system_prompt + retry_mode + (
5613
  'The only permitted repair signals are the following bounded issue codes: '
5614
  + json.dumps(codes[:5], ensure_ascii=False)
5615
  + '. Use the bounded detector evidence below only to repair the supplied claim; do not invent additional defects. '
@@ -5859,9 +5882,11 @@ Each code must be one of: {sorted(allowed)}. Return one or more specific dimensi
5859
  for row in model_rows
5860
  ],
5861
  }
 
5862
  system_prompt = f"""You are an independent bilingual translation QA adjudicator for {target_lang}.
5863
  This is verification-only: do not rewrite, suggest wording, or emit free-form explanations. Each supplied issue already survived two bounded claim-local repair rounds. Confirm a BLOCKING defect only when the English/target pair itself provides clear evidence. Do not treat stylistic preference or a legitimate grammatical/morphological variant as blocking.
5864
- For Russian, allow required case/number/gender inflection. For Kazakh, allow productive case, possessive, person/plural and vowel-harmony suffixes on the correct term stem, but treat clearly Russian lexical/syntactic substitution as blocking only when the pair itself supports that conclusion. For Chinese, allow natural reordering and sentence reshaping inside the same claim while preserving meaning. For all three languages, an ordinary untranslated English lexical word is blocking; protected acronyms, model/tool names, variables, citations, canonical glossary terms, and source-matched proper names are not.
 
5865
  Return valid JSON only: {{"items":[{{"id":"SP-P000001-C000001","issue_code":"GRAMMAR","decision":"CONFIRMED_BLOCKING","evidence_code":"GRAMMATICAL_VIOLATION"}}]}}.
5866
  Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one of: {sorted(allowed_evidence)}. Return every supplied id+issue_code pair exactly once."""
5867
  try:
 
3751
  'contamination_policy': 'Treat sustained untranslated English prose as a repair signal; normal acronyms, model names and protected terms are allowed.',
3752
  }
3753
 
3754
+ @staticmethod
3755
+ def _translation_lexical_retention_contract(target_lang):
3756
+ """Single prompt-side authority for legal Latin retention in ZH/RU/KK.
3757
+
3758
+ The deterministic lexical-purity validator remains the enforcement
3759
+ authority. This contract mirrors that policy so generation, QA, repair,
3760
+ source regeneration, and adjudication are instructed by the same rule.
3761
+ """
3762
+ return (
3763
+ 'LEXICAL RETENTION CONTRACT: In Chinese, Russian, or Kazakh target-language prose, '
3764
+ 'every ordinary English lexical item must be translated. Latin script may remain only '
3765
+ 'for protected immutable research objects, approved acronyms, model/tool/variable identifiers, '
3766
+ 'citations, DOI/URL strings, source-matched proper names or bounded titles/institutions, and '
3767
+ 'legitimate Latin glossary targets recognized by the deterministic lexical-purity policy. '
3768
+ 'Do not retain ordinary English words or phrases merely because they appear technical or familiar.'
3769
+ )
3770
+
3771
  @classmethod
3772
  def _translation_language_rule(cls, target_lang):
3773
  profile = cls._translation_language_profile(target_lang)
 
3777
  core = 'Use idiomatic academic Kazakh with correct case and possessive suffixes, person/plural endings, vowel harmony, consonant assimilation, natural word order, and correct Kazakh-specific letters. Translate directly from English and avoid Russian syntactic calques.'
3778
  else:
3779
  core = 'Use formal academic Simplified Chinese with explicit concepts, natural Chinese syntax, clear hierarchy, and logically connected claims. Avoid carrying English nominalization and clause order into Chinese mechanically.'
3780
+ return (
3781
+ core + ' ' + profile['term_policy'] + ' '
3782
+ + cls._translation_lexical_retention_contract(target_lang) + ' '
3783
+ + profile['contamination_policy']
3784
+ )
3785
 
3786
  @classmethod
3787
  def _russian_contamination_evidence(cls, source, target, glossary=None):
 
5083
  'items': [{'id': row['id'], 'english': row['english'], 'target': row['target']} for row in rows],
5084
  }
5085
  profile = self._translation_language_profile(target_lang)
5086
+ lexical_contract = self._translation_lexical_retention_contract(target_lang)
5087
  system_prompt = f"""You are a bilingual academic translation QA classifier for {target_lang}.
5088
  Review EACH claim independently. Do not rewrite and do not provide free-form explanations. Check semantic equivalence and language quality: omissions/additions, negation, uncertainty, association-versus-causation strength, terminology, grammar, language contamination, citation attachment, and acronym attachment.
5089
+ LANGUAGE ADAPTER: {profile['adapter_id']}; morphology={profile['morphology']}. {profile['term_policy']} {lexical_contract} {profile['contamination_policy']}
5090
+ For Russian, do not flag a terminology error merely because a translated term is inflected for grammatical case/number/gender; sustained non-Russian prose remains an additional contamination signal. For Kazakh, do not flag a terminology error merely because productive suffixes attach to the correct term stem; clearly Russian lexical/syntactic intrusion remains an additional language-specific signal when the pair supports that conclusion. Cyrillic script or absence of Kazakh-specific letters alone is never sufficient evidence.
5091
  Return valid JSON only in this exact form: {{"items":[{{"id":"SP-P000001-C000001","ok":true,"codes":[],"evidence_codes":[]}}]}}.
5092
  If ok=false, codes MUST contain only values from allowed_issue_codes. For SEMANTIC_DRIFT, NEGATION_DRIFT, CAUSALITY_STRENGTH_DRIFT, UNCERTAINTY_DRIFT, OMITTED_CLAIM, or ADDED_CLAIM, evidence_codes should identify the affected semantic dimension using only: {sorted(allowed_semantic_evidence)}. For GRAMMAR, evidence_codes should identify the narrow grammatical defect using only: {sorted(allowed_grammar_evidence)}. Use the narrowest supported evidence; use MEANING_CHANGED or GRAMMAR_UNSPECIFIED only when the narrower dimension cannot be identified from the pair. Do not invent an error dimension. Never return numbered prose, examples, quotes, or corrective wording. Never return replacement text. Return every supplied id exactly once."""
5093
  response = self.call_deepseek(
 
5626
  ]
5627
  if grammar_evidence_codes:
5628
  evidence_payload['grammar_evidence_codes'] = grammar_evidence_codes[:4]
5629
+ lexical_contract = self._translation_lexical_retention_contract(target_lang)
5630
  retry_mode = (
5631
  '\nCLAIM SOURCE REGENERATION. The previous target wording has failed bounded repair and MUST NOT be used as drafting context. Generate a fresh translation of only this one claim directly from the frozen marked English source. '
5632
  if strategy == 'SOURCE_REGENERATE' else
5633
  '\nCLAIM QUALITY RETRY. Repair only this one claim. '
5634
  )
5635
+ effective_prompt = system_prompt + '\n' + lexical_contract + retry_mode + (
5636
  'The only permitted repair signals are the following bounded issue codes: '
5637
  + json.dumps(codes[:5], ensure_ascii=False)
5638
  + '. Use the bounded detector evidence below only to repair the supplied claim; do not invent additional defects. '
 
5882
  for row in model_rows
5883
  ],
5884
  }
5885
+ lexical_contract = self._translation_lexical_retention_contract(target_lang)
5886
  system_prompt = f"""You are an independent bilingual translation QA adjudicator for {target_lang}.
5887
  This is verification-only: do not rewrite, suggest wording, or emit free-form explanations. Each supplied issue already survived two bounded claim-local repair rounds. Confirm a BLOCKING defect only when the English/target pair itself provides clear evidence. Do not treat stylistic preference or a legitimate grammatical/morphological variant as blocking.
5888
+ {lexical_contract}
5889
+ For Russian, allow required case/number/gender inflection and retain sustained non-Russian prose as an additional contamination signal. For Kazakh, allow productive case, possessive, person/plural and vowel-harmony suffixes on the correct term stem, but treat clearly Russian lexical/syntactic substitution as blocking only when the pair itself supports that conclusion. For Chinese, allow natural reordering and sentence reshaping inside the same claim while preserving meaning.
5890
  Return valid JSON only: {{"items":[{{"id":"SP-P000001-C000001","issue_code":"GRAMMAR","decision":"CONFIRMED_BLOCKING","evidence_code":"GRAMMATICAL_VIOLATION"}}]}}.
5891
  Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one of: {sorted(allowed_evidence)}. Return every supplied id+issue_code pair exactly once."""
5892
  try: