fix(tm):建立 Trusted 唯一性与 Supersede 治理

This commit is contained in:
2026-09-18 06:44:14 +08:00
parent e486f1aaaa
commit ff1adb91ee
37 changed files with 2679 additions and 530 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ Go `cmd/bat-api` 是资源 bootstrap、已发布资源分发和鉴权控制服
- `/admin/` 与白名单 `/admin/control/{action}`;其中翻译管理面包含
`/admin/translation/tasks``/admin/translation/handoff`
`/admin/translation/memory/summary``/admin/translation/memory/query`
`translation-memory-confirm` 转发
`translation-memory-confirm``translation-memory-resolve-conflict` 转发
- `/openapi.yaml`
HTTP 路由的 OpenAPI 文本由 `internal/api/openapi.go` 提供,运行中的服务也可
+7 -4
View File
@@ -196,8 +196,10 @@ pub struct ParserRegistry {
### 4. 翻译系统(目标扩展,Go;当前 worker 由 Rust `bat` 承担)
当前已实现的是 Rust `bat` 的离线 TextUnit 队列、mock/Crowdin provider worker、
lease/retry、结果落库、项目级 Translation Memory V1 和独立 Glossary V2。TM 位于独立
SQLite,按 raw source + 完整 context 做 trusted exact reusecandidate 必须显式 confirm
lease/retry、结果落库、项目级 Translation Memory persistence schema V2 和独立 Glossary
domain/feature contract V1SQLite persistence schema V2)。TM 位于独立 SQLite,按 raw
source + 完整 context 做 current Trusted exact reusecandidate 必须显式 confirm
同一 identity 的不同译文必须显式 supersede,历史 Trusted 冲突必须显式 resolve
Glossary 只有 approved term 进入 provider/TM 自动流程,并在结果上执行确定性 QA;模糊
匹配和完整 Provider 体系仍属后续缺口。
@@ -229,7 +231,7 @@ type TranslationProvider interface {
- Azure Translator Provider
**翻译记忆库**
- 当前 V1raw source 完全相同、完整 context 完全相同且记录为 trusted 时自动复用。
- 当前规则raw source 完全相同、完整 context 完全相同且只有一条 current Trusted 时自动复用。
- provider 输出写入先是 candidatemanual task result 不会自动建立 TM 或 trusted。`bat i18n memory confirm` 显式确认单条记录后才可自动复用。
- source、context、release、TextUnit、provider 和 run provenance 保存在 Rust TM SQLite 中。
- 模糊匹配、术语优先级和 PostgreSQL 服务化仍不是当前实现。
@@ -296,7 +298,8 @@ HTTP Request → Middleware (Auth, CORS, Logger) → Handler → Service → Rep
### 7. Web 后台 (Vue 3,目标设计)
当前只有 `bat-api` 内嵌 dashboard MVPRust `bat` 的 Glossary V2 已实现,登录、角色、Web 术语管理和完整协作审核仍未实现。
当前只有 `bat-api` 内嵌 dashboard MVPRust `bat` 的 Glossary domain/feature contract V1
及 SQLite persistence schema V2 已实现,登录、角色、Web 术语管理和完整协作审核仍未实现。
**技术栈**
- Vue 3 + Composition API
@@ -36,8 +36,10 @@
- 新的跨语言控制和查询能力优先增加 Rust RPC contract,再由
`internal/backendrpc` 消费。
4. **完整游戏业务 API、完整 Web 协作后台和 Provider 扩展体系仍是后续目标;Rust `bat` 已持有 Glossary V2Web 术语协作视图仍待建设**
Translation Memory V1 已由 Rust `bat` 持有,不能从目标架构图推断 Go 侧拥有第二份状态。
4. **完整游戏业务 API、完整 Web 协作后台和 Provider 扩展体系仍是后续目标;Rust `bat` 已持有
Glossary domain/feature contract V1SQLite persistence schema V2),Web 术语协作视图仍待建设**;
Translation Memory persistence schema V2 已由 Rust `bat` 持有,不能从目标架构图推断 Go
侧拥有第二份状态。
---
@@ -180,9 +180,9 @@
`available=false`,不会因为查询创建空库。发布后的 TextUnit 队列还会在当前
release 根目录写入 `translation-tasks.sqlite`,由版本化 `schema_migrations`
管理 V2 queued/running/failed/completed/skipped、provider run、lease、失败分类、
重试计划和 TextUnit 级译文结果。跨 release 的 Translation Memory V1 独立存储在
`<output>/translation-memory.sqlite`,记录 raw source/hash、完整 context、candidate/
trusted 和 release/TextUnit/provider/run provenance`translation.tasks` 优先查询这份状态库,
重试计划和 TextUnit 级译文结果。跨 release 的 Translation Memory persistence schema V2
独立存储在 `<output>/translation-memory.sqlite`,记录 raw source/hash、完整 context、
candidate/trusted 和 release/TextUnit/provider/run provenance`translation.tasks` 优先查询这份状态库,
`translation.worker.run` 由 Rust worker 回写状态;`translation.task.update` 仍供外部 provider 流程回写状态;
没有状态库的旧 release 才回退到 immutable JSON 队列。`bat doctor cas`
已提供只读 CAS 根目录、对象目录、元数据库文件和对象统计诊断;`resource.index`
+2 -2
View File
@@ -213,8 +213,8 @@ bat i18n worker run \
`--watch`,因此可以单次、限定次数或周期执行;`--run-count > 1` 时仍必须
显式指定 `--interval`
Glossary V2 是 Rust `bat` 持有的独立项目级 SQLite 资产,默认位于
`<output>/glossary.sqlite`V2 正式吸收历史上的 `glossary_term_deletions`
Glossary domain/feature contract V1 由 Rust `bat` 持有,并由 SQLite persistence schema V2
承载,默认位于 `<output>/glossary.sqlite`V2 正式吸收历史上的 `glossary_term_deletions`
schema drift;也可以用 `--glossary-path`
`BAT_GLOSSARY_PATH``[translation.worker].glossary_path` 指定。worker 只把
`approved` term 转成 provider-neutral constraints,并在 TM 复用、provider 返回
+2 -2
View File
@@ -9,8 +9,8 @@ BlueArchive Toolkit 的部署文档分为当前可用模式和目标模式:
2. **官方资源同步生产任务**:当前可用,运行 Rust `bat --watch` 或 RPC/daemon 模式。
3. **bat-api 资源 bootstrap / 分发服务**:当前可用,和 Rust `bat` 在同一服务器/容器环境运行,经 `bat.sock` RPC 获取当前 `resource_root`
4. **可选数据库开发环境**PostgreSQL/Redis 只服务于未来的 Go 服务层、完整 Web 协作后台和
Provider 扩展,不是当前 `bat` / `bat-api` 的生产运行依赖;当前 Translation Memory V1
使用 `<output>/translation-memory.sqlite`
Provider 扩展,不是当前 `bat` / `bat-api` 的生产运行依赖;当前 Translation Memory
persistence schema V2 使用 `<output>/translation-memory.sqlite`
5. **完整单机/分布式部署**:尚未提供。完整游戏业务 API、数据库迁移和 Web 未实现前,不把它作为可执行部署方案。
---
+6 -6
View File
@@ -23,9 +23,11 @@ rustc --version # 验证安装
cargo --version
```
#### 自托管 Gitea runner
#### 本地完整质量门禁
`.gitea/workflows/bat.yml` 使用 `runs-on: linux`,并且不依赖 `actions/checkout``dtolnay/rust-toolchain` 等外部 GitHub Action。runner 需要在执行环境中预装以下命令:
项目以本地 `make ci-check` 作为唯一完整 required quality gate。开发过程中可运行 focused
checks 以快速反馈,但提交前完整 gate 不得省略;仓库不依赖 Gitea、GitHub Actions 或其它
远端 CI runner。执行环境需要预装以下命令:
```bash
git --version
@@ -38,11 +40,9 @@ golangci-lint --version # 必须为 2.12.2
```
缺少上述命令、版本不匹配或 `golangci-lint` 不是 2.12.2 都会使 required gate 失败;
`golangci-lint 2.12.2` 是 required gate,不是可选检查。该 workflow 会用
`GITHUB_SERVER_URL``GITHUB_REPOSITORY``GITHUB_REF``GITHUB_SHA` 手动 `git fetch`
当前提交,再执行 Rust workspace 的只读格式检查、检查、构建、clippy 和测试,以及通过
`golangci-lint 2.12.2` 是 required gate,不是可选检查。`make ci-check` 会执行 Rust
workspace 的只读格式检查、检查、release build、clippy 和测试,以及通过
`make check-go-format` 执行的 Go 格式、测试、vet、构建、2.12.2 lint 和文档状态门禁。
这样可以避免自托管 runner 在准备阶段通过代理克隆第三方 action 仓库。
#### Docker
```bash
+10 -6
View File
@@ -261,9 +261,11 @@ rollback 或 repair。
| `translation.task.update` | 已实现 | `{ "task_id": "...", "status": "failed", "failure_reason": "...", "provider_run_id": "..." }` | 写入当前 release 的 provider worker 状态,返回可回查任务记录。 |
| `translation.worker.run` | 已实现 | provider worker 参数 | 异步触发 Rust provider worker,返回 `{ "task_id": "...", "kind": "translation.worker.run", "worker": {...} }`。 |
| `translation.proofread` | 已实现 | `null` | 将当前汉化 workflow 标记为人工校对中,返回工作流状态报告。 |
| `translation.memory.summary` | 已实现 | 可选 `{ "translation_memory_path": "..." }` | 返回 TM schema 版本、总记录数candidate/trusted/rejected/superseded 状态计数。 |
| `translation.memory.query` | 已实现 | `{ "source_text": "...", "source_context": {...}, "limit": 100 }` | 按 raw source 查询记录,返回 match kind、trust、translation 和 provenance。 |
| `translation.memory.confirm` | 已实现 | `{ "record_id": "...", "reviewer": "...", "reason": "..." }` | 显式确认一条 candidate 为 trustedworker 之后才可自动复用。 |
| `translation.memory.summary` | 已实现 | 可选 `{ "translation_memory_path": "..." }` | 返回 TM persistence schema 版本、总记录数candidate/trusted/rejected/superseded 状态计数和 trusted 冲突组计数。 |
| `translation.memory.query` | 已实现 | `{ "source_text": "...", "source_context": {...}, "limit": 100 }` | 按 raw source 查询记录,返回 match kind、trust、translation 和 provenanceconflict 结果不可自动复用。 |
| `translation.memory.confirm` | 已实现 | `{ "record_id": "...", "reviewer": "...", "reason": "...", "supersede_record_id": "..." }` | 显式确认 candidate 为 trusted已有不同 current Trusted 时必须显式 supersedeworker 之后才可自动复用。 |
| `translation.memory.conflicts` | 已实现 | 可选 `{ "translation_memory_path": "...", "limit": 100 }` | 只读列出 exact source/context 下存在多个 current Trusted 的冲突组。 |
| `translation.memory.resolve_conflict` | 已实现 | `{ "winner_record_id": "...", "expected_trusted_record_ids": ["..."], "reviewer": "...", "reason": "..." }` | 使用稳定 record ID 原子解决历史 Trusted 冲突,保留 supersede 历史并写入 audit event。 |
| `translation.glossary.summary` | 已实现 | 可选 `{ "glossary_path": "..." }` | 返回 Glossary schema 版本和 draft/approved/deprecated/rejected 计数;缺库只返回 `available=false`,不会创建空库。 |
| `translation.glossary.query` | 已实现 | `{ "source_text": "...", "category": "...", "review_status": "approved", "limit": 100 }` | 查询 term、alias、scope、source provenance 和完整 source/review history。 |
| `translation.glossary.diagnose` | 已实现 | `{ "source_text": "...", "context": {...} }` | 只对 approved term 生成 provider-neutral constraints,并返回冲突/覆盖诊断和 blocked 决策。 |
@@ -535,7 +537,8 @@ CLI 对应关系:
| `bat i18n worker run` | `translation.worker.run` |
| `bat i18n proofread` | `translation.proofread` |
| `bat i18n memory summary` / `bat i18n memory query` | `translation.memory.summary` / `translation.memory.query` |
| `bat i18n memory confirm` | `translation.memory.confirm` |
| `bat i18n memory confirm` / `bat i18n memory conflicts` | `translation.memory.confirm` / `translation.memory.conflicts` |
| `bat i18n memory resolve-conflict` | `translation.memory.resolve_conflict` |
| `bat i18n glossary summary` / `bat i18n glossary query` | `translation.glossary.summary` / `translation.glossary.query` |
| `bat i18n glossary diagnose` | `translation.glossary.diagnose` |
| `bat i18n glossary add/update` | `translation.glossary.add` / `translation.glossary.update` |
@@ -573,7 +576,8 @@ CLI 对应关系:
`localized.status``localized.publish``localized.rollback`
`translation.tasks``translation.handoff``translation.task.update`
`translation.worker.run``translation.proofread``translation.memory.summary`
`translation.memory.query``translation.memory.confirm``translation.glossary.summary`
`translation.memory.query``translation.memory.confirm``translation.memory.conflicts`
`translation.memory.resolve_conflict``translation.glossary.summary`
`translation.glossary.query``translation.glossary.diagnose``translation.glossary.add`
`translation.glossary.update``translation.glossary.approve``translation.glossary.deprecate`
`translation.glossary.delete`
@@ -594,7 +598,7 @@ CLI 对应关系:
| `TaskBackend` | `task.list``task.status``task.logs``task.cancel` | 鉴权后的 daemon 任务查询和取消 |
| `ParseBackend` | `parse.status``parse.text_units``parse.errors` | 鉴权后的当前 release 解析状态、TextUnit 和解析错误只读查询 |
| `TranslationBackend` | `translation.tasks``translation.handoff``translation.task.update``translation.worker.run``translation.proofread` | 鉴权后的 dashboard 翻译任务查询、交接视图、状态回写、provider worker 触发与人工校对标记 |
| `TranslationMemoryBackend` | `translation.memory.summary``translation.memory.query``translation.memory.confirm` | 鉴权后的 TM 摘要、source/context 查询和显式 candidate 确认;Go 只转发,不持有 TM 状态 |
| `TranslationMemoryBackend` | `translation.memory.summary``translation.memory.query``translation.memory.confirm``translation.memory.conflicts``translation.memory.resolve_conflict` | 鉴权后的 TM 摘要、source/context 查询和 Trusted 冲突治理;Go 只转发,不持有 TM 状态 |
| `GlossaryBackend` | `translation.glossary.summary/query/diagnose/add/update/approve/deprecate/delete` | 鉴权后的 Glossary 摘要、term/history 查询、确定性诊断和审核/删除 mutationGo 只转发,不持有 Glossary 状态 |
| `LocalizedBackend` | `localized.status``localized.publish``localized.rollback` | 鉴权后的汉化 release 状态、发布与显式回滚 |
| `ReleaseBackend` | `release.status``release.list``release.distribution``release.cleanup` | 鉴权后的双 release 查询、验证分发选择和 dry-run/execute cleanupGo 不持有 release 状态 |
@@ -74,7 +74,8 @@ Rust 窗口请基于当前真实代码生成或导出以下 JSON:
2. `catalog.status` available=false 响应。
3. `resource.manifest` 第一页响应,至少包含 1 到 2 个 entries。
4. 对应 release 的 `official-sync-snapshot.json`
5. Rust Glossary V2 的 `translation.glossary.query` 响应,至少包含 alias、approved
5. Rust Glossary domain/feature contract V1、SQLite persistence schema V2 的
`translation.glossary.query` 响应,至少包含 alias、approved
review、source provenance 和 created/approved history。
输出应来自 Rust 代码路径,而不是手写 JSON。允许使用 fixture resource root 或临时目录,但不能依赖开发机真实资源目录。
+8 -7
View File
@@ -152,17 +152,18 @@ official/localized distribution 均被阻断,普通查询不会自动重建。
更完整的查询/权限/损坏恢复、模糊 TM、bat.sock peer credential/perms、FFI 生命周期、
资源大小/限额与更强的持久化 fsync 语义仍按后续专项推进。
### G-012Translation Memory V1 已实现,扩展能力仍缺失
### G-012Translation Memory persistence schema V2 已实现,扩展能力仍缺失
Rust `bat` 已提供独立项目级 SQLite TM,当前 schema version 为 V1schema 打开遵守
Rust `bat` 已提供独立项目级 SQLite TM,当前 persistence schema version 为 V2schema 打开遵守
只读 preflight、fingerprint、transaction rollback 和 future/unknown fail-closed
契约。它记录 raw source/hash、完整 context、release/TextUnit/provider/run provenance
区分 candidate/trusted,只有显式 confirm 才能建立 trusted 记录;worker 只自动复用
trusted raw source + 完整 context exact match,并在复用前执行已批准 Glossary 的
确定性 QA。Go `bat-api` 已提供鉴权的 summary/query 只读接口和 confirm 转发,但 Go
不持有 TM 状态。仍缺少模糊匹配和更丰富的导入导出历史能力
区分 candidate/trusted,只有显式 confirm 或 conflict resolve 才能建立唯一 current
trusted 记录;worker 只自动复用 raw source + 完整 context exact match 的 current
trusted,并在复用前执行已批准 Glossary 的确定性 QA。Go `bat-api` 已提供鉴权的
summary/query/conflicts 只读接口和 confirm/resolve_conflict 转发,但 Go 不持有 TM 状态。
仍缺少模糊匹配和更丰富的导入导出历史能力。
### G-013Glossary V2 已实现,协作视图仍缺失
### G-013Glossary domain/feature contract V1、persistence schema V2 已实现,协作视图仍缺失
Rust `bat` 已提供独立项目级 `glossary.sqlite`,当前 schema version 为 V2V2 正式
吸收历史上未升版本的 `glossary_term_deletions` drift,并将历史 V1-A(无 deletion
+1 -1
View File
@@ -95,7 +95,7 @@
| 组件 | 路径 | 状态 | 说明 |
|---|---|---|---|
| Module | `go.mod``bat-api` | 已用 | 服务层模块名 |
| RPC client | `internal/backendrpc` | **完成** | Unix socket JSON-RPC transport + typed helpertyped helper 覆盖 daemon 已实现控制/查询、`resource.state/sync/verify/repair/manifest/list``release.attestation/status/list/distribution/cleanup``catalog.*``parse.*``localized.status/publish/rollback``task.*``translation.tasks``translation.handoff``translation.task.update``translation.worker.run``translation.proofread``translation.memory.summary/query/confirm``translation.glossary.summary/query/diagnose/add/update/approve/deprecate/delete` 和文件级 UnityFS patch 调用;`resource.manifest` typed params 固定 release/publication/manifest identity 和 verification generation`localized.publish` 的 typed params 支持 `translation_file``from_worker``patch_manifest` 三选一;`resource.index``patch.apply` 仍通过通用 `Call` 走同一 contractfake transport 单测和 `internal/api/testdata/contract/` mirror test 固化 Rust 输出字段 |
| RPC client | `internal/backendrpc` | **完成** | Unix socket JSON-RPC transport + typed helpertyped helper 覆盖 daemon 已实现控制/查询、`resource.state/sync/verify/repair/manifest/list``release.attestation/status/list/distribution/cleanup``catalog.*``parse.*``localized.status/publish/rollback``task.*``translation.tasks``translation.handoff``translation.task.update``translation.worker.run``translation.proofread``translation.memory.summary/query/confirm/conflicts/resolve_conflict``translation.glossary.summary/query/diagnose/add/update/approve/deprecate/delete` 和文件级 UnityFS patch 调用;`resource.manifest` typed params 固定 release/publication/manifest identity 和 verification generation`localized.publish` 的 typed params 支持 `translation_file``from_worker``patch_manifest` 三选一;`resource.index``patch.apply` 仍通过通用 `Call` 走同一 contractfake transport 单测和 `internal/api/testdata/contract/` mirror test 固化 Rust 输出字段 |
| 资源 bootstrap/分发 | `cmd/bat-api` + `internal/api` | **MVP+生产控制面** | RPC 发现 + 周期刷新/诊断 + `/v1/bootstrap` + `/v1/launcher/bootstrap` + `/v1/releases` + `/v1/distribution` + launcher 资源 metadata 兼容 + `/readyz` + CDN Range/缓存头 + 鉴权/限流/访问日志/反代适配 + OpenAPI + 管理控制白名单 + release/localized/TM/Glossary admin forwarding + 内嵌 dashboard + `.env` |
| 试验 CLI | `cmd/bat` | **试验** | doctor 固定 okmanifest/sync 走 FFI |
| FFI | `internal/ffi` | **可选** | 需 `build-ffi` |