fix(i18n): harden prompt v4 contract

This commit is contained in:
Tianyi Cui
2026-07-23 21:44:41 +08:00
parent a66ed5474c
commit 6046a13a29
6 changed files with 141 additions and 22 deletions

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-07-23-translation-prompt-v4-contract.md: be7a1c5c78ff770d554dd694b1e4760d2b5c0415
2026-07-23-translation-prompt-v4-contract.zh.md: a637361cc853ba652fe25adcba8ef15dde0df75d

View File

@@ -0,0 +1,33 @@
# Agent Note: Calibrated translation prompt v4 contract
Status: implemented
English | [中文](2026-07-23-translation-prompt-v4-contract.zh.md)
## Problem
Automated counterpart generation needs a stable prompt that reproduces the register and corrections established by human-reviewed translations. Injecting a general-purpose instruction document changes that calibrated model input whenever human or agent guidance changes, while an unframed response cannot carry a draft, its self-review, and the corrected document separately. Plain XML-like section tags also collide with valid Markdown that documents those same tags.
## Decision
The committed [translation prompt](../../../../docs/i18n/translation-prompt.md) is the calibrated pipeline asset. Its renderer injects only the source language, target language, and current [terminology table](../../../../docs/i18n/terminology.md); whole reviewed document pairs supply the few-shot examples. The template may carry model-specific calibration rules, but those rules remain subordinate to the repository's binding pairing, terminology, structure, and emphasis contracts.
The response has three ordered top-level sections: `translation`, `review`, and `final`. The pipeline consumes `final` after parsing, then mechanically inserts or corrects the language switcher for the target path. The parser requires each section exactly once, rejects content outside the envelope, and tolerates one outer `xml` Markdown fence because models sometimes echo the prompt's example fence.
## Response framing
Section delimiter lines are reserved by the wire format. When a Markdown body line consists of a delimiter tag, possibly preceded by backslashes, the serializer and model add one leading backslash; the parser removes exactly one. This count-preserving escape round-trips both a literal delimiter and an already escaped delimiter without changing inline tag mentions.
The executable contract lives in [the renderer and parser](../../../../scripts/translation-prompt.ts). Its tests cover both render directions, strict section order and cardinality, fenced responses, inline tag mentions, and delimiter lines inside Markdown bodies.
## Alternatives considered
**Inject `translation-rules.md` into every request.** That document governs humans and agents as well as the automated pipeline. Injecting it couples each editorial clarification to model behavior and displaces the manually calibrated prompt constraints; the pipeline instead injects the binding terminology table and verifies its own asset directly.
**Use a strict CDATA XML document.** CDATA provides general XML framing but adds a nested protocol, an additional `]]>` escape, and XML-parser behavior that the three-section contract does not otherwise need. Reserving and escaping six delimiter lines keeps the calibrated response shape while preserving arbitrary Markdown.
**Return only the final translation.** A single body is simpler to parse but discards the explicit correction pass used to catch tone, structure, terminology, and punctuation defects before publication.
## Consequences
Prompt wording is executable behavior and receives code review plus the translation-prompt verifier. The calibrated asset and the general translation rules can evolve for their different audiences, but review must reject contradictions with binding repository contracts. The line escape is visible only when source documentation contains a wrapper tag on its own line, and parser tests pin its lossless behavior.

View File

@@ -0,0 +1,33 @@
# Agent Note: 经校准的翻译提示词 v4 契约
Status: implemented
[English](2026-07-23-translation-prompt-v4-contract.md) | 中文
## 问题
自动生成对侧文件需要一份稳定的提示词,能够复现经人工评审的译文所确立的语体和修正方式。注入通用说明文档,会让这份经校准的模型输入随着面向人类或 agent(智能体)的指导发生变化,而未经封装的响应无法分别承载草稿、自检内容和修正后的文档。普通的类 XML 分段标签还会与用于说明这些标签的合法 Markdown 内容发生冲突。
## 决策
提交入库的[翻译提示词](../../../../docs/i18n/translation-prompt.md)是经过校准的流水线资源。其渲染器仅注入源语言、目标语言和当前[术语表](../../../../docs/i18n/terminology.md);few-shot 示例由经过评审的整篇文档对提供。模板可以包含针对特定模型的校准规则,但这些规则必须服从仓库中具约束力的配对、术语、结构与强调格式契约。
响应包含三个有序的顶层分段:`translation`、`review` 和 `final`。流水线在解析后读取 `final`,随后依据目标路径以机械方式插入或校正语言切换行。解析器要求每个分段恰好出现一次,拒绝封套之外的内容,并允许响应最外层有一层 `xml` Markdown 围栏,因为模型有时会照抄提示词中的示例围栏。
## 响应封装格式
分段定界行由协议格式(wire format)保留。当 Markdown 正文中的某一行仅包含定界标签(前面可以带反斜杠)时,序列化器和模型会在行首再添加一个反斜杠;解析器则只移除一个。这种保留计数的转义方式让字面量定界标签与已转义的定界标签都能无损往返,同时不会改动行内提及的标签。
可执行契约由[渲染器和解析器](../../../../scripts/translation-prompt.ts)实现。其测试覆盖双向渲染、严格的分段顺序与数量约束、带围栏的响应、行内提及标签,以及 Markdown 正文中的定界行。
## 考虑过的替代方案
**在每个请求中注入 `translation-rules.md`。** 该文档既约束人类与 agent,也约束自动翻译流水线。注入它会让编辑规范的每次澄清都与模型行为耦合,并挤占经过人工校准的提示词约束;因此流水线仅注入具约束力的术语表,并直接校验自身资源。
**使用严格的 CDATA XML 文档。** CDATA 提供通用的 XML 封装,但会引入一层嵌套协议、额外的 `]]>` 转义规则,以及三段式契约原本不需要的 XML 解析器行为。预留并转义六种定界行,既能维持经校准的响应形态,也能保留任意 Markdown 内容不变。
**只返回最终译文。** 单一正文更易解析,却会丢弃显式修正步骤;这个步骤用于在发布前发现语气、结构、术语和标点缺陷。
## 影响
提示词措辞属于可执行行为,因此既接受代码评审,也由翻译提示词校验器校验。经校准的资源与通用翻译规则可以针对各自的受众分别演进,但评审必须拒绝任何与仓库约束性契约冲突的改动。只有当源文档中的封装标签独占一行时,行转义才会显现;解析器测试锁定这一无损行为。