Files
nyaKazuha e486f1aaaa
bat-rust / Build and test Rust (push) Waiting to run
bat-rust / Build and test Go API (push) Waiting to run
fix(glossary): 修复历史 V1 漂移并建立 V2 迁移
2026-09-17 21:25:29 +08:00

18 KiB
Raw Permalink Blame History

Rust bat 工作流命令

Rust bat 的工作流入口按三个一级命令组织:

  • res:官方资源拉取、校验、修复和拉取计划。
  • parse:当前官方 release 的解析和 UnityFS 重打包。
  • i18n:离线翻译工作台、人工文本修改和汉化 release 发布。

resourceresourcestranslationtranslate 仍作为长别名接受,但文档示例统一使用 resi18n;例如 resource statusresource scheduletranslation taskstranslation handofftranslation status 都会落到同一组已实现命令。

资源拉取

单次拉取:

bat res pull --auto-discover --output /tmp/bat-resources

同一进程内限定次数执行。第二轮及以后必须显式给出间隔:

bat res pull --auto-discover \
  --run-count 3 \
  --interval 1h \
  --output /tmp/bat-resources

无限周期执行使用 --watch

bat res pull --auto-discover --watch --interval 1h \
  --output /tmp/bat-resources

资源下载默认使用 8 个独立 worker,允许范围为 1..=256。worker 完成当前 URL 后立即领取共享队列中的下一个任务,进度按完成顺序统计,最终报告仍按计划顺序输出。

Release 查询与清理

双 release 运维由 Rust bat 通过 bat.sock 提供,不新增平行顶层 CLI

# 查看 official/localized 当前、历史、source relation 和完整性
printf '{"jsonrpc":"2.0","id":1,"method":"release.status"}\n' \
  | socat - UNIX-CONNECT:/tmp/bat-state/bat.sock
printf '{"jsonrpc":"2.0","id":2,"method":"release.list","params":{"channel":"localized"}}\n' \
  | socat - UNIX-CONNECT:/tmp/bat-state/bat.sock

# 选择已验证的 localized 当前 release,默认 channel 仍是 official
printf '{"jsonrpc":"2.0","id":3,"method":"release.distribution","params":{"channel":"localized"}}\n' \
  | socat - UNIX-CONNECT:/tmp/bat-state/bat.sock

release.distribution 只返回 Rust 已验证的当前或显式历史 release。localized 必须 同时满足 source official、current、manifest identity、source/target hash/size 和 UnityFS/ZIP 最终语义校验;staging、损坏、缺失或路径不安全的 release 不会跨 channel fallback。localized.statuspatch_manifest_contract_statusartifact_integrity_status 分开表示 schema 和产物健康度,产物损坏时为 localized.degraded,检查不会自动修复。

清理必须先 dry-run,再使用同一 plan_id 执行:

printf '{"jsonrpc":"2.0","id":4,"method":"release.cleanup","params":{"execute":false}}\n' \
  | socat - UNIX-CONNECT:/tmp/bat-state/bat.sock
printf '{"jsonrpc":"2.0","id":5,"method":"release.cleanup","params":{"execute":true,"plan_id":"<plan-id>"}}\n' \
  | socat - UNIX-CONNECT:/tmp/bat-state/bat.sock

Rust 会在执行前重算计划,保护 current、rollback previous、active/in-progress、 localized source official、state/manifest/CAS/reference 和未知归属对象。cleanup 不改变 current、不执行 rollback,也不删除 staging;回滚仍使用独立的 localized.rollback

解析与重打包

解析当前已发布 release

bat parse run --output /tmp/bat-resources

也可以显式指定隔离的已发布 release 根目录:

bat parse run \
  --resource-root /tmp/bat-resources/versions/<release-id> \
  --force

解析结果会刷新 official-parse-cache.jsonofficial-textunit-index.json 和翻译队列。--force 忽略已有解析缓存,但仍要求输入 release 已通过官方下载 manifest 校验。

清理当前 release 的可再生解析缓存和离线翻译队列:

bat parse clear-cache \
  --resource-root /tmp/bat-resources/versions/<release-id> \
  --force

该命令不会删除 translation-tasks.sqlite;worker 状态必须通过任务接口单独维护。

批量 UnityFS 重打包使用 JSON spec。spec 的 schema_version 当前为 1,支持 text_assetstring_field 和受支持的语义 field 操作:

bat parse repack --repack-spec /tmp/bat-repack.json

重打包写入独立的 target_bundle,逐个操作后由底层 UnityFS patch 实现重建并校验,不允许 source 和 target 相同。重建会保留已识别的 block 压缩、alignment、目录和未修改对象内容;未知压缩模式或无法证明保真的结构会失败。

翻译工作台与发布

导出可人工编辑的工作台:

bat i18n export \
  --output /tmp/bat-resources \
  --translation-file /tmp/bat-workbench.json

修改一个条目:

bat i18n set \
  --translation-file /tmp/bat-workbench.json \
  --translation-id <text-unit-id> \
  --translated-text '中文文本'

也可以使用 --translated-file 读取 UTF-8 文本。 如果译文触发 blocking Glossary QA,需先从 diagnose/任务结果取得当前 qa_identity,并与 reviewer、reason、provenance 一起提交;系统不会根据 workbench 中旧的 QA 自动补填:

bat i18n set \
  --translation-file /tmp/bat-workbench.json \
  --translation-id <text-unit-id> \
  --translated-text '人工确认的译文' \
  --glossary-qa-identity <qa-identity> \
  --glossary-reviewer operator \
  --glossary-reason '人工确认术语偏离' \
  --glossary-provenance workbench

需要复核单条内容时:

bat i18n get \
  --translation-file /tmp/bat-workbench.json \
  --translation-id <text-unit-id> \
  --json

需要把某条译文恢复为未审核状态时:

bat i18n unset \
  --translation-file /tmp/bat-workbench.json \
  --translation-id <text-unit-id>

这些工作台操作也可以写成 bat i18n workbench set|get|unset|validate ... --translation-file 也可简写为 --workbench。 工作台会保存 source text、release ID、TextUnit 目标和人工译文;发布前会重新读取当前 TextUnit 索引,拒绝过期 release、source text 或 patch 目标。

发布前可只做工作台审计:

bat i18n validate \
  --resource-root /tmp/bat-resources/versions/<release-id> \
  --translation-file /tmp/bat-workbench.json

报告会区分未审核、原文未变化、可直接 i18n publish 的受支持 TextAsset/ TypeTree string field 条目,以及需要先经过独立 repack 流程的 ZIP 内或其他不支持条目。

发布汉化 release

bat i18n publish \
  --output /tmp/bat-resources \
  --localized-output /tmp/bat-localized \
  --translation-file /tmp/bat-workbench.json

发布接受当前实现支持的直接 TextAsset、TypeTree string field 和 managed-reference string field 条目;zip 内 bundle 和其他不支持条目使用 parse repack 的 spec 单独处理。--force 不覆盖已有目录,而是生成独立的 <official-release>-manual-<unix-seconds> 汉化 release ID;也可以用 --localized-release-id 显式指定新 ID。因此强制发布仍保留旧 release 和 rollback 信息。

当前 i18n run 是离线工作流:刷新 TextUnit 队列,并可用 --translation-file 导出工作台;真实 provider 由单独的 worker 命令消费 translation-tasks.sqlite

运行一次 mock provider worker

bat i18n worker run \
  --output /tmp/bat-resources \
  --provider mock \
  --worker-concurrency 8

--provider 支持 mockcrowdinmock 可通过 --translation-fixture 读取本地 JSON fixturecrowdin 从环境变量 CROWDIN_PROJECT_IDCROWDIN_LANGUAGE_IDCROWDIN_API_TOKEN 读取配置。worker 默认并发为 8, 范围 1..=256;每个 worker 完成当前任务后立即从 SQLite 队列领取下一项, 不会等待当前一批 worker 全部结束后再重新分配。

可用参数包括 --worker-max-attempts--worker-lease-seconds--worker-retry-backoff / --worker-retry-backoff-seconds--worker-max-tasks--worker-id。worker 支持 --run-count--watch,因此可以单次、限定次数或周期执行;--run-count > 1 时仍必须 显式指定 --interval

Glossary V2 是 Rust bat 持有的独立项目级 SQLite 资产,默认位于 <output>/glossary.sqliteV2 正式吸收历史上的 glossary_term_deletions schema drift;也可以用 --glossary-pathBAT_GLOSSARY_PATH[translation.worker].glossary_path 指定。worker 只把 approved term 转成 provider-neutral constraints,并在 TM 复用、provider 返回 和人工工作台/任务回写时执行相同的确定性 QA。冲突或不符合推荐/允许译法的结果会 阻止自动完成;必须提交带当前 qa_identity、reviewer、reason 和 provenance 的显式 override。

常用 Glossary 操作:

bat i18n glossary summary --output /tmp/bat-resources
bat i18n glossary query --glossary-source-text 'Sensei' --glossary-review-status approved
bat i18n glossary diagnose --glossary-source-text 'Sensei' \
  --glossary-context-json '{"destination":"Table.bytes"}'

外部 provider 或人工流程也可以用 i18n task update 回写当前 release 的任务状态:

bat i18n task update \
  --state-dir /tmp/bat-state \
  --task-id textunit/v-current/TextAssets/Scenario.json \
  --task-status failed \
  --failure-reason "provider rejected payload" \
  --provider-run-id provider-run-1 \
  --json

--task-status 支持 Rust contract 中的 queuedrunningfailedcompletedskipped;命令只更新当前 release 的 translation-tasks.sqlite,不会创建任意翻译任务。 任务查询和交接查询可以用 bat i18n tasks / bat i18n handoff 汉化发布状态可以用 bat i18n status。这些只读入口也可以写成 bat translation tasks|handoff|status,其中 translation / translate 是一级命令长别名。

需要把当前汉化 workflow 切到人工校对中时,可用:

bat i18n proofread \
  --output /tmp/bat-resources \
  --localized-output /tmp/bat-localized

该命令只改写 localized-version-state.json 中的工作流标记,不会改动已发布的 汉化 release 指针;如果自动汉化已经发布,后续仍可继续正常发布汉化资源。

持久化调度

每个一级工作流都可以管理自己的 schedule。调度计划保存在 --state-dir/bat-schedules.json,计划记录包含动作、参数、下一次执行时间、周期、剩余次数、启用状态和最近错误。 parse scheduleres schedule / i18n schedule 共用同一份计划库, --id / --action 分别是 --schedule-id / --schedule-action 的简写。

新增一个每天执行的资源拉取计划:

bat res schedule add \
  --state-dir /tmp/bat-schedule \
  --schedule-id daily-pull \
  --schedule-action pull \
  --schedule-delay 1s \
  --schedule-every 24h \
  --schedule-arg --auto-discover \
  --schedule-arg --output \
  --schedule-arg /tmp/bat-resources

计划操作:

bat res schedule list --state-dir /tmp/bat-schedule
bat res schedule update --state-dir /tmp/bat-schedule --schedule-id daily-pull --schedule-every 12h
bat res schedule remove --state-dir /tmp/bat-schedule --schedule-id daily-pull
bat res schedule run --state-dir /tmp/bat-schedule
bat parse schedule list --state-dir /tmp/bat-schedule

parse schedule add 默认动作是 runi18n schedule add 默认动作也是 run;可以用 --schedule-action repack--schedule-action publish 选择对应动作。--schedule-count 限定执行次数,省略表示周期无限执行;没有 --schedule-every 的计划执行一次后自动停用。

res/parse/i18n schedule list 默认只显示对应一级命令的计划;也可以用 --schedule-id--schedule-enabled--schedule-disabled 过滤。计划删除和执行 会校验一级命令作用域,避免误操作其他工作流。schedule update 可以用 --schedule-clear-every 将周期计划改为单次计划;schedule remove 会删除计划。 schedule run --force 会忽略到期时间立即执行指定计划,--schedule-max-runs N 限制本轮最多执行 N 个到期计划。

bat-api 调度与 dashboard 接口

内嵌 dashboard 由 bat-api 直接服务于 GET /admin/dashboard/。页面静态资产免 token 读取,但资源、调度、任务、日志、解析和翻译控制都通过 bat-api 转发到 Rust bat.sock,不维护第二份计划状态或翻译状态。Rust RPC 方法为:

  • schedule.list
  • schedule.add
  • schedule.update
  • schedule.remove
  • schedule.run
  • task.list
  • task.status
  • task.logs
  • task.cancel
  • daemon.logs
  • daemon.doctor
  • parse.status
  • parse.text_units
  • parse.errors

bat-api 对应接口为 GET /admin/schedulesPOST /admin/control/schedule-add|schedule-update|schedule-remove|schedule-run 均要求配置 BAT_API_AUTH_TOKEN 并携带管理 token。列表接口支持 idgroupenabled query 过滤;请求字段沿用 Rust contractidgroupactionargsnext_run_unix_secondsdelay_secondsevery_secondscountclear_argsclear_everyenabledschedule.list 额外接受 idgroupenabled 过滤, schedule.run 额外接受 groupforcemax_runs

任务和诊断接口同样要求管理 token:GET /admin/diagnostics 转发 daemon.doctorGET /admin/logs?tail=200 转发 daemon.logs GET /admin/tasksGET /admin/tasks/status?task_id=...GET /admin/tasks/logs?task_id=... 转发 task.* 查询。取消任务使用 POST /admin/control/task-cancel,请求字段为 task_id

解析查询接口为 GET /admin/parse/statusGET /admin/parse/text-unitsGET /admin/parse/errors,均只读转发当前 Rust release 的 parse.* 数据。text-unitserrors 支持 offsetlimitdestinationpath_patternarchive_entrypath_idclass_idfield_pathformat querylimit 范围为 1..=1000

翻译任务状态可由已鉴权的 dashboard 通过 GET /admin/translation/tasks 查询,query 过滤项包括 offsetlimittask_idrelease_iddestinationpath_patternarchive_entrystatusworker_statusparse_statusformathas_reasonhas_failure_reason。完整 provider run 交接视图通过 GET /admin/translation/handoff 查询。两个查询接口都只转发 Rust translation.tasks / translation.handoff,不在 Go 侧维护状态。

翻译任务状态也可由已鉴权的 dashboard 通过 POST /admin/control/translation-task-update 回写,请求字段为 task_idstatus,以及可选的 failure_reasonproviderprovider_run_idtranslation_results;该接口只转发 translation.task.update。人工校对流程提交译文时必须使用 status=completed 并为每个 translation_results[] 提供 unit_idsource_texttranslated_textRust 会用当前 official-textunit-index.json 校验 unit、 source text、destination 和 archive entry 后再落库。blocking Glossary QA 还必须提交 与当前 QA 完全相等的 glossary_override.qa_identity;旧或缺少 identity 的 override 不会授权。

POST /admin/control/translation-worker-run 会触发 Rust 侧 translation.worker.run,请求字段为 providerfixture_pathconcurrencymax_attemptslease_secondsretry_backoff_secondsmax_tasksworker_id。bat-api 只做鉴权、JSON 解码和基础范围校验; 任务状态、lease、重试和 provider 结果仍由 Rust 持久化。

POST /admin/control/translation-proofread 会把当前汉化 workflow 标记为人工校对中; 该接口只转发 translation.proofread,不会改动已发布汉化 release 指针。

localized patch 发布与回滚

i18n publish 会在独立的 .staging/<localized-release-id> 中复制当前官方 release,校验工作台或 generic patch manifest 与当前官方 release 的 source identity 一致后,按确定的 operation sequence 写入 Binary、JSON、UTF-8 Text,以及已有支持 范围内的 TextAsset、TypeTree string field 和 managed-reference string field patch。校验通过后才原子切换 localized/current,并在 release manifest 中记录 源/目标 BLAKE3、字节数、patch kind、TextUnit、provider、review、发布时重新计算的 Glossary QA/override 和 rollback 信息。若 TextUnit 带有 archive_entry,发布会在 staging 内验证 ZIP 条目路径,修改并重解析内层 UnityFS 后重写外层 ZIP;路径不安全、内层结构无效或重打包工具失败时不会发布不完整结果。可通过 --unzip <PATH>--zip <PATH> 或对应的 BAT_UNZIPBAT_ZIP 配置工具路径。

使用人工编辑的工作台发布:

bat i18n publish \
  --translation-file /tmp/bat-workbench.json \
  --localized-release-id release-manual-1

使用已完成 provider worker 的译文结果发布:

bat i18n publish \
  --from-worker \
  --localized-release-id release-worker-1

已有 generic manifest 时直接发布:

bat i18n publish \
  --patch-manifest /tmp/bat-patch-manifest.json \
  --localized-release-id localized-v1

manifest 必须声明当前官方 source_version 和目标 localized target_version 文件 hash/size、操作顺序和算法载荷;直接文件支持 Binary/JSON/TextUnityFS 操作 必须保留 serialized file、path ID、field path 或 TextAsset 定位,ZIP 内 UnityFS 还必须保留 archive_entry。Rust 会在 staging 中逐操作验证 source precondition、 最终 hash/size,并在 ZIP 外层重写后重新读取条目、重解析 UnityFS 和校验实际替换值。 其他未支持的 UnityFS 结构仍明确拒绝。

发布失败会清理 staging,不切换 current。当前 release 的 rollback 目标由 manifest 记录,执行后删除本次版本目录并恢复上一版本;没有上一版本时移除 current

bat i18n rollback --localized-release-id release-worker-1

Rust RPC 方法为 localized.publishlocalized.rollbackbat-api 对应为 POST /admin/control/localized-publishPOST /admin/control/localized-rollback 以及鉴权的 GET /admin/translation/status。发布请求必须且只能包含 translation_filefrom_worker=truepatch_manifestrollback 可省略 release ID 以操作当前 release。Go 只做鉴权、参数校验和转发,状态与产物仍由 Rust 持有。

边界

解析器新增类型覆盖和新的解析格式当前按路线图推进;新增覆盖仍需通过真实 fixture、回归测试和文档同步验收,不要只靠合成样本宣称能力。