# Rust bat 工作流命令 Rust `bat` 的工作流入口按三个一级命令组织: - `res`:官方资源拉取、校验、修复和拉取计划。 - `parse`:当前官方 release 的解析和 UnityFS 重打包。 - `i18n`:离线翻译工作台、人工文本修改和汉化 release 发布。 `resource`、`resources`、`translation` 和 `translate` 仍作为长别名接受,但文档示例统一使用 `res` 和 `i18n`;例如 `resource status`、`resource schedule`、`translation tasks`、`translation handoff` 和 `translation status` 都会落到同一组已实现命令。 ## 资源拉取 单次拉取: ```bash bat res pull --auto-discover --output /tmp/bat-resources ``` 同一进程内限定次数执行。第二轮及以后必须显式给出间隔: ```bash bat res pull --auto-discover \ --run-count 3 \ --interval 1h \ --output /tmp/bat-resources ``` 无限周期执行使用 `--watch`: ```bash 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: ```bash # 查看 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.status` 的 `patch_manifest_contract_status` 与 `artifact_integrity_status` 分开表示 schema 和产物健康度,产物损坏时为 `localized.degraded`,检查不会自动修复。 清理必须先 dry-run,再使用同一 `plan_id` 执行: ```bash 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":""}}\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: ```bash bat parse run --output /tmp/bat-resources ``` 也可以显式指定隔离的已发布 release 根目录: ```bash bat parse run \ --resource-root /tmp/bat-resources/versions/ \ --force ``` 解析结果会刷新 `official-parse-cache.json`、`official-textunit-index.json` 和翻译队列。`--force` 忽略已有解析缓存,但仍要求输入 release 已通过官方下载 manifest 校验。 清理当前 release 的可再生解析缓存和离线翻译队列: ```bash bat parse clear-cache \ --resource-root /tmp/bat-resources/versions/ \ --force ``` 该命令不会删除 `translation-tasks.sqlite`;worker 状态必须通过任务接口单独维护。 批量 UnityFS 重打包使用 JSON spec。spec 的 `schema_version` 当前为 `1`,支持 `text_asset`、`string_field` 和受支持的语义 `field` 操作: ```bash bat parse repack --repack-spec /tmp/bat-repack.json ``` 重打包写入独立的 `target_bundle`,逐个操作后由底层 UnityFS patch 实现重建并校验,不允许 source 和 target 相同。重建会保留已识别的 block 压缩、alignment、目录和未修改对象内容;未知压缩模式或无法证明保真的结构会失败。 ## 翻译工作台与发布 导出可人工编辑的工作台: ```bash bat i18n export \ --output /tmp/bat-resources \ --translation-file /tmp/bat-workbench.json ``` 修改一个条目: ```bash bat i18n set \ --translation-file /tmp/bat-workbench.json \ --translation-id \ --translated-text '中文文本' ``` 也可以使用 `--translated-file` 读取 UTF-8 文本。 如果译文触发 blocking Glossary QA,需先从 diagnose/任务结果取得当前 `qa_identity`,并与 reviewer、reason、provenance 一起提交;系统不会根据 workbench 中旧的 QA 自动补填: ```bash bat i18n set \ --translation-file /tmp/bat-workbench.json \ --translation-id \ --translated-text '人工确认的译文' \ --glossary-qa-identity \ --glossary-reviewer operator \ --glossary-reason '人工确认术语偏离' \ --glossary-provenance workbench ``` 需要复核单条内容时: ```bash bat i18n get \ --translation-file /tmp/bat-workbench.json \ --translation-id \ --json ``` 需要把某条译文恢复为未审核状态时: ```bash bat i18n unset \ --translation-file /tmp/bat-workbench.json \ --translation-id ``` 这些工作台操作也可以写成 `bat i18n workbench set|get|unset|validate ...`, `--translation-file` 也可简写为 `--workbench`。 工作台会保存 source text、release ID、TextUnit 目标和人工译文;发布前会重新读取当前 TextUnit 索引,拒绝过期 release、source text 或 patch 目标。 发布前可只做工作台审计: ```bash bat i18n validate \ --resource-root /tmp/bat-resources/versions/ \ --translation-file /tmp/bat-workbench.json ``` 报告会区分未审核、原文未变化、可直接 `i18n publish` 的受支持 TextAsset/ TypeTree string field 条目,以及需要先经过独立 repack 流程的 ZIP 内或其他不支持条目。 发布汉化 release: ```bash 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` 不覆盖已有目录,而是生成独立的 `-manual-` 汉化 release ID;也可以用 `--localized-release-id` 显式指定新 ID。因此强制发布仍保留旧 release 和 rollback 信息。 当前 `i18n run` 是离线工作流:刷新 TextUnit 队列,并可用 `--translation-file` 导出工作台;真实 provider 由单独的 worker 命令消费 `translation-tasks.sqlite`。 运行一次 mock provider worker: ```bash bat i18n worker run \ --output /tmp/bat-resources \ --provider mock \ --worker-concurrency 8 ``` `--provider` 支持 `mock` 和 `crowdin`。`mock` 可通过 `--translation-fixture` 读取本地 JSON fixture;`crowdin` 从环境变量 `CROWDIN_PROJECT_ID`、 `CROWDIN_LANGUAGE_ID`、`CROWDIN_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 domain/feature contract V1 由 Rust `bat` 持有,并由 SQLite persistence schema V2 承载,默认位于 `/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 返回 和人工工作台/任务回写时执行相同的确定性 QA。冲突或不符合推荐/允许译法的结果会 阻止自动完成;必须提交带当前 `qa_identity`、reviewer、reason 和 provenance 的显式 override。 常用 Glossary 操作: ```bash 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 的任务状态: ```bash 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 中的 `queued`、`running`、`failed`、 `completed` 和 `skipped`;命令只更新当前 release 的 `translation-tasks.sqlite`,不会创建任意翻译任务。 任务查询和交接查询可以用 `bat i18n tasks` / `bat i18n handoff`; 汉化发布状态可以用 `bat i18n status`。这些只读入口也可以写成 `bat translation tasks|handoff|status`,其中 `translation` / `translate` 是一级命令长别名。 需要把当前汉化 workflow 切到人工校对中时,可用: ```bash bat i18n proofread \ --output /tmp/bat-resources \ --localized-output /tmp/bat-localized ``` 该命令只改写 `localized-version-state.json` 中的工作流标记,不会改动已发布的 汉化 release 指针;如果自动汉化已经发布,后续仍可继续正常发布汉化资源。 ## 持久化调度 每个一级工作流都可以管理自己的 schedule。调度计划保存在 `--state-dir/bat-schedules.json`,计划记录包含动作、参数、下一次执行时间、周期、剩余次数、启用状态和最近错误。 `parse schedule` 与 `res schedule` / `i18n schedule` 共用同一份计划库, `--id` / `--action` 分别是 `--schedule-id` / `--schedule-action` 的简写。 新增一个每天执行的资源拉取计划: ```bash 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 ``` 计划操作: ```bash 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` 默认动作是 `run`,`i18n 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/schedules` 和 `POST /admin/control/schedule-add|schedule-update|schedule-remove|schedule-run`, 均要求配置 `BAT_API_AUTH_TOKEN` 并携带管理 token。列表接口支持 `id`、`group`、 `enabled` query 过滤;请求字段沿用 Rust contract:`id`、`group`、`action`、`args`、`next_run_unix_seconds`、 `delay_seconds`、`every_seconds`、`count`、`clear_args`、`clear_every`、 `enabled`;`schedule.list` 额外接受 `id`、`group`、`enabled` 过滤, `schedule.run` 额外接受 `group`、`force` 和 `max_runs`。 任务和诊断接口同样要求管理 token:`GET /admin/diagnostics` 转发 `daemon.doctor`,`GET /admin/logs?tail=200` 转发 `daemon.logs`, `GET /admin/tasks`、`GET /admin/tasks/status?task_id=...` 和 `GET /admin/tasks/logs?task_id=...` 转发 `task.*` 查询。取消任务使用 `POST /admin/control/task-cancel`,请求字段为 `task_id`。 解析查询接口为 `GET /admin/parse/status`、 `GET /admin/parse/text-units` 和 `GET /admin/parse/errors`,均只读转发当前 Rust release 的 `parse.*` 数据。`text-units` 与 `errors` 支持 `offset`、 `limit`、`destination`、`path_pattern`、`archive_entry`、`path_id`、`class_id`、 `field_path` 和 `format` query,`limit` 范围为 `1..=1000`。 翻译任务状态可由已鉴权的 dashboard 通过 `GET /admin/translation/tasks` 查询,query 过滤项包括 `offset`、`limit`、`task_id`、`release_id`、 `destination`、`path_pattern`、`archive_entry`、`status`、`worker_status`、 `parse_status`、`format`、`has_reason` 和 `has_failure_reason`。完整 provider run 交接视图通过 `GET /admin/translation/handoff` 查询。两个查询接口都只转发 Rust `translation.tasks` / `translation.handoff`,不在 Go 侧维护状态。 翻译任务状态也可由已鉴权的 dashboard 通过 `POST /admin/control/translation-task-update` 回写,请求字段为 `task_id`、`status`,以及可选的 `failure_reason`、`provider`、 `provider_run_id` 和 `translation_results`;该接口只转发 `translation.task.update`。人工校对流程提交译文时必须使用 `status=completed`, 并为每个 `translation_results[]` 提供 `unit_id`、`source_text` 和 `translated_text`,Rust 会用当前 `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`,请求字段为 `provider`、`fixture_path`、 `concurrency`、`max_attempts`、`lease_seconds`、`retry_backoff_seconds`、 `max_tasks` 和 `worker_id`。bat-api 只做鉴权、JSON 解码和基础范围校验; 任务状态、lease、重试和 provider 结果仍由 Rust 持久化。 `POST /admin/control/translation-proofread` 会把当前汉化 workflow 标记为人工校对中; 该接口只转发 `translation.proofread`,不会改动已发布汉化 release 指针。 ## localized patch 发布与回滚 `i18n publish` 会在独立的 `.staging/` 中复制当前官方 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 `、`--zip ` 或对应的 `BAT_UNZIP`、`BAT_ZIP` 配置工具路径。 使用人工编辑的工作台发布: ```bash bat i18n publish \ --translation-file /tmp/bat-workbench.json \ --localized-release-id release-manual-1 ``` 使用已完成 provider worker 的译文结果发布: ```bash bat i18n publish \ --from-worker \ --localized-release-id release-worker-1 ``` 已有 generic manifest 时直接发布: ```bash 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/Text,UnityFS 操作 必须保留 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`: ```bash bat i18n rollback --localized-release-id release-worker-1 ``` Rust RPC 方法为 `localized.publish` 和 `localized.rollback`;bat-api 对应为 `POST /admin/control/localized-publish`、`POST /admin/control/localized-rollback` 以及鉴权的 `GET /admin/translation/status`。发布请求必须且只能包含 `translation_file`、`from_worker=true` 或 `patch_manifest`;rollback 可省略 release ID 以操作当前 release。Go 只做鉴权、参数校验和转发,状态与产物仍由 Rust 持有。 ## 边界 解析器新增类型覆盖和新的解析格式当前按路线图推进;新增覆盖仍需通过真实 fixture、回归测试和文档同步验收,不要只靠合成样本宣称能力。