feat: add official full pull smoke

Emit runtime download progress and validation summaries for official sync.

Add repeatable real-network full pull smoke runbook and script.

Fixes #4

Fixes #6
This commit is contained in:
2026-07-14 00:48:59 +08:00
parent 2ff99ae9e3
commit 25c2c4d40f
15 changed files with 435 additions and 57 deletions
@@ -233,12 +233,12 @@ Linux 生产路径:
- pull plan 会同时包含 discovery URLs 和 content URLs
- 全量样本下是 `2` 个 discovery URL + `5` 个内容 URL = `7` 个 URL
- `OfficialUpdateService` 能持久化 v2 snapshot,并在远端 marker 内容变化时触发下载决策
- `bat` 默认向 stderr 输出 `BlueArchiveToolkit` ASCII banner 和 progress logstdout 默认输出人类可读摘要;支持 `--json` 输出稳定 JSON,支持 `--no-progress` 关闭进度日志,支持 `--no-banner` 只关闭横幅,支持 `--watch --interval 1h --error-retry 60s` 常驻运行,支持 `--daemon` Unix socket JSON-RPC 控制、`status``stop``restart``reload``logs``refresh --force``verify``repair``doctor``clean-stable`,非 dry-run 使用 `.official-sync.lock` 防止并发写资源目录,控制命令使用 `bat-control.lock` 防止并发状态修改,资源发布使用 `.staging``versions``current` 原子切换,daemon 写 `bat-events.jsonl` 结构化日志并在 `status` 中暴露下载进度和调度状态
- `bat` 默认向 stderr 输出 `BlueArchiveToolkit` ASCII banner 和 progress logstdout 默认输出人类可读摘要;progress log 覆盖总体下载进度、单文件开始/完成状态和校验结果摘要;支持 `--json` 输出稳定 JSON,支持 `--no-progress` 关闭进度日志,支持 `--no-banner` 只关闭横幅,支持 `--watch --interval 1h --error-retry 60s` 常驻运行,支持 `--daemon` Unix socket JSON-RPC 控制、`status``stop``restart``reload``logs``refresh --force``verify``repair``doctor``clean-stable`,非 dry-run 使用 `.official-sync.lock` 防止并发写资源目录,控制命令使用 `bat-control.lock` 防止并发状态修改,资源发布使用 `.staging``versions``current` 原子切换,daemon 写 `bat-events.jsonl` 结构化日志并在 `status` 中暴露下载进度和调度状态
- `OfficialUpdateService` 能读写 `official-bootstrap-cache.json`,并支持默认开启的 `audit_local` / `repair` CLI 行为
- 下载层能在本地文件 size/BLAKE3/path、ZIP 结构或 manifest 不匹配时重新下载
- 官方 seed `.hash` mismatch 会导致下载失败,而不是降级为本地 BLAKE3 猜测
- 非官方 URL 会在 fetch/download 入口被拒绝
- 尚未在仓库中记录真实官方网络全量下载 smoke test
- 真实官方网络全量下载 smoke 已固化为 `scripts/official-full-pull-smoke.sh``make official-smoke``docs/guides/official-full-pull-smoke.md`;大型资源文件和运行报告默认保留在 `/tmp` 隔离目录,不纳入 Git
相关验证主要来自:
+5 -4
View File
@@ -89,7 +89,7 @@ git check-ignore -v Cargo.lock CLAUDE.md
CAS V1 和 Rust 官方同步闭环完成后,下一阶段优先推进:
1. Go CLI 的 `doctor` 和基础命令框架。
2. 真实官方网络全量下载 smoke 记录
2. `docs/guides/official-full-pull-smoke.md` 执行真实官方网络全量下载 smoke,并保留隔离目录报告
3. 官方同步结果接入 CAS + ResourceRepository。
4. AssetBundle UnityFS 解析。
@@ -99,6 +99,7 @@ CAS V1 和 Rust 官方同步闭环完成后,下一阶段优先推进:
2. `CURRENT_STATUS.md`
3. `docs/reports/CURRENT_GAPS.md`
4. `docs/guides/official-resource-test-pull.md`
5. `docs/architecture/official-resource-backend.md`
6. `docs/architecture/adr/0001-engine-and-application-boundaries.md`
7. `docs/architecture/adr/0002-cas-v1-design-boundary.md`
5. `docs/guides/official-full-pull-smoke.md`
6. `docs/architecture/official-resource-backend.md`
7. `docs/architecture/adr/0001-engine-and-application-boundaries.md`
8. `docs/architecture/adr/0002-cas-v1-design-boundary.md`
+99
View File
@@ -0,0 +1,99 @@
# 官方全量拉取 Smoke Runbook
本文档固定真实官方网络全量拉取 smoke 的可重复命令。该流程会访问官方日服 HTTP 资源并下载完整 Windows + Android 资源集合,输出目录必须是隔离目录。
## 目标
验证当前 `bat` 能在真实官方网络环境下完成:
1. `--auto-discover --dry-run --plan`
2. 首次全量拉取并发布到 `current`
3. 第二次运行返回 `up_to_date`
4. 人工破坏 active release 中一个资源文件
5. `repair` 检出并重新下载损坏文件
6. `verify` 在 repair 后通过
## 一条命令
默认写入 `/tmp/bat-official-smoke-<UTC timestamp>/`
```bash
scripts/official-full-pull-smoke.sh
```
也可以通过 Makefile 执行:
```bash
make official-smoke
```
脚本默认会先构建 release binary
```bash
cargo build --release -p bat-infrastructure --bin bat
```
## 输出
默认目录结构:
```text
/tmp/bat-official-smoke-<timestamp>/
resources/
current -> versions/<id>
versions/<id>/
.staging/
state/
report/
01-dry-run-plan.command.txt
01-dry-run-plan.stdout.json
01-dry-run-plan.stderr.log
02-first-full-pull.command.txt
02-first-full-pull.stdout.json
02-first-full-pull.stderr.log
03-second-up-to-date.command.txt
03-second-up-to-date.stdout.json
03-second-up-to-date.stderr.log
04-repair-after-damage.command.txt
04-repair-after-damage.stdout.json
04-repair-after-damage.stderr.log
05-verify-after-repair.command.txt
05-verify-after-repair.stdout.json
05-verify-after-repair.stderr.log
damaged-file.txt
damaged-file.before.txt
SMOKE_REPORT.md
```
`damaged-file.before.txt` 只记录被破坏文件的路径、大小和 sha256,不复制原始资源文件。`SMOKE_REPORT.md` 记录本次 smoke 的实际输出目录、active release、文件数量、release 大小和被破坏的文件。大型资源文件不进入 Git。
脚本会在关键步骤后自动检查:
- 首次全量拉取 stderr log 包含总体下载进度、单文件进度和校验结果。
- 二次运行 stdout JSON 包含 `update_status=up_to_date`
- repair stdout JSON 包含 `command=repair``status=completed`
- repair stderr log 包含总体下载进度、单文件进度和校验结果。
- repair 后 verify stdout JSON 包含 `healthy=true`
## 环境变量
- `BAT_SMOKE_ROOT`:覆盖默认根目录。
- `BAT_SMOKE_OUTPUT`:覆盖资源发布根目录。
- `BAT_SMOKE_STATE_DIR`:覆盖 daemon/status 目录。
- `BAT_SMOKE_REPORT_DIR`:覆盖报告目录。
- `BAT_BIN`:使用已有 `bat` binary。
- `BAT_SMOKE_SKIP_BUILD=1`:跳过 release 构建。
- `BAT_SMOKE_ALLOW_NON_TMP=1`:允许 `BAT_SMOKE_OUTPUT` 指向非 `/tmp` 路径。只可用于确认隔离的测试目录。
## 安全边界
脚本默认拒绝非 `/tmp` 输出目录,且拒绝复用非空输出目录。不要把输出目录指向已有客户端、官方启动器安装目录、生产资源目录或开发机人工维护资源目录。
## 成功判定
脚本全部步骤退出码为 0 即表示 smoke 通过。重点检查:
- `03-second-up-to-date.stdout.json``update_status``up_to_date`
- `04-repair-after-damage.stdout.json` 中 repair 完成,且有重新下载或修复行为。
- `05-verify-after-repair.stdout.json``healthy``true`
- `02-first-full-pull.stderr.log``04-repair-after-damage.stderr.log` 中包含下载总体进度、单文件进度和校验结果日志。
+16 -3
View File
@@ -258,13 +258,26 @@ cargo run -p bat-infrastructure --bin bat -- \
--error-retry 60s
```
默认平台是 `Windows,Android`,无需显式传 `--platforms`;只有要覆盖默认平台时才传。`--interval` 是正常检查周期,默认 `1h`watch/daemon 模式还会在每天北京时间(UTC+8)`03:00``16:00``18:00` 强制执行一次自动刷新,该轮会注入 `force=true`,并且会中断普通 interval 的 sleep。`--error-retry` 是下载、发现或校验失败后的重试周期,默认 `60s`,也可以用 `--error-retry-seconds 60`。CLI 默认启动时向 stderr 打印 `BlueArchiveToolkit` ASCII banner,并把阶段进度日志写到 stderr,包括自动发现、server-info、marker、catalog、audit、download、snapshot 和 publish 阶段;daemon 还会写 `bat-events.jsonl` 结构化日志并按大小轮转。命令结果默认以人类可读摘要写到 stdout。需要纯机器输出时加 `--json --no-progress`,需要显式开启进度日志则用 `--progress`;只想关闭横幅但保留日志时可加 `--no-banner`。错误时 stderr 输出 JSON errorwatch 模式下错误 JSON 的 `next_retry_seconds` 使用失败重试周期;如果未关闭 progress,错误 JSON 前可能已有 banner 和进度日志。普通错误 exit `1`,资源目录锁冲突 exit `75``verify``doctor` 发现问题也返回非 0。
默认平台是 `Windows,Android`,无需显式传 `--platforms`;只有要覆盖默认平台时才传。`--interval` 是正常检查周期,默认 `1h`watch/daemon 模式还会在每天北京时间(UTC+8)`03:00``16:00``18:00` 强制执行一次自动刷新,该轮会注入 `force=true`,并且会中断普通 interval 的 sleep。`--error-retry` 是下载、发现或校验失败后的重试周期,默认 `60s`,也可以用 `--error-retry-seconds 60`。CLI 默认启动时向 stderr 打印 `BlueArchiveToolkit` ASCII banner,并把阶段进度日志写到 stderr,包括自动发现、server-info、marker、catalog、audit、download、snapshot 和 publish 阶段;download 阶段会输出总体下载进度和单文件开始/完成状态,audit 阶段会输出官方 `.hash`、本地 BLAKE3、需修复项和 ZIP 结构校验结果摘要。daemon 还会写 `bat-events.jsonl` 结构化日志并按大小轮转。命令结果默认以人类可读摘要写到 stdout。需要纯机器输出时加 `--json --no-progress`,需要显式开启进度日志则用 `--progress`;只想关闭横幅但保留日志时可加 `--no-banner`。错误时 stderr 输出 JSON errorwatch 模式下错误 JSON 的 `next_retry_seconds` 使用失败重试周期;如果未关闭 progress,错误 JSON 前可能已有 banner 和进度日志。普通错误 exit `1`,资源目录锁冲突 exit `75``verify``doctor` 发现问题也返回非 0。
生产可以直接运行 `--watch`,也可以用 `--daemon` 后台运行,或者用 systemd service、容器或 Go 进程守护它。cron/systemd timer 仍可调用单次模式,但不再是 Rust 自动更新的唯一方式。项目是否热更新、热重载或重启进程,由上层业务集成决定。生产资源目录应使用独立输出目录,不要指向现有客户端或人工维护的资源目录;上层读取资源时应读取 `--output/current`,不要读取 `.staging``versions` 中未切换的目录。非 dry-run 每轮会创建 `--output/.official-sync.lock`,防止并发写同一资源目录;live daemon 还会阻止前台写命令直接修改它正在管理的同一目录。
需要只做探测时可以加 `--dry-run`。需要关闭本地 audit 或 repair 时可以显式使用 `--no-audit-local``--no-repair`,但生产同步默认应保持开启。
## 6. 例外输入
## 6. 真实全量 smoke
真实官方网络全量拉取 smoke 已固化为 runbook 和脚本:
```bash
scripts/official-full-pull-smoke.sh
# 或
make official-smoke
```
默认输出在 `/tmp/bat-official-smoke-<UTC timestamp>/`,脚本会执行 dry-run plan、首次全量拉取、二次 `up_to_date`、本地文件破坏后的 `repair`、repair 后 `verify`,并检查 stderr progress log 中存在总体下载进度、单文件进度和校验结果摘要。完整说明见 `docs/guides/official-full-pull-smoke.md`
## 7. 例外输入
可接受的 `server-info` 输入是:
@@ -275,7 +288,7 @@ cargo run -p bat-infrastructure --bin bat -- \
如果没有显式 `server-info` 输入,必须手动加 `--auto-discover` 才会走官方 metadata / `GameMainConfig` 辅助发现链路。不要在 Linux 生产任务里依赖已安装启动器或本地客户端目录。
## 7. 代码入口
## 8. 代码入口
当前可用的用户入口:
+15 -11
View File
@@ -319,26 +319,30 @@
- GitHub Actions 或等价 CI 执行 format、lint、test、build。
### G-018:真实官方网络全量下载 smoke test 未记录
### G-018:真实官方网络全量下载 smoke test 已固化为可重复命令
状态:**关闭**
状态:**关闭(已固化可重复 smoke 命令;真实下载产物不纳入 Git)**
现象:
历史现象:
- 本地测试覆盖 mock、fixture、synthetic import 和 CLI 参数。
- 尚未在隔离输出目录记录一次真实官方网络全量下载
- 曾缺少真实官方网络全量下载的固定 runbook 和可重复命令
影响
处理结果
- 无法用文档证明当前 `bat` 在真实官方网络环境下完成首次下载、二次静默 up-to-date 和本地损坏 repair
- 新增 `scripts/official-full-pull-smoke.sh`,默认在 `/tmp/bat-official-smoke-<UTC timestamp>/` 下创建隔离资源目录、状态目录和报告目录
- 新增 `make official-smoke` 统一入口。
- 新增 `docs/guides/official-full-pull-smoke.md`,记录目标、命令、输出结构、环境变量、安全边界和成功判定。
- smoke 流程覆盖 dry-run plan、首次全量拉取、二次 `up_to_date`、人工破坏 active release 文件后的 `repair`、repair 后 `verify`
- 脚本会检查二次 `up_to_date`、repair 完成、verify `healthy=true`,并检查首次拉取和 repair 的 stderr log 中存在总体下载进度、单文件进度和校验结果日志。
- 运行报告 `SMOKE_REPORT.md` 记录实际输出目录、active release、文件数量、release 大小和被破坏文件;大型官方资源文件保留在隔离输出目录,不纳入 Git。
验收:
- 使用独立目录执行 dry-run
- 执行真实首次下载,不指向任何现有客户端或人工维护资源目录
- 二次运行返回 `up_to_date`watch 模式在 up-to-date 时静默
- 人工破坏一个本地文件后,audit 检出并 repair
- 记录命令、摘要、输出目录和未纳入 Git 的大文件位置。
- 使用 `scripts/official-full-pull-smoke.sh``make official-smoke`
- 默认输出目录必须是独立 `/tmp` 目录;非 `/tmp` 路径需要显式设置 `BAT_SMOKE_ALLOW_NON_TMP=1`,且输出目录必须为空
- 脚本退出码为 0 即表示 runbook 验收通过
- 真实网络执行需要外部网络和足够磁盘空间;本仓库只保存 runbook、脚本和测试,不保存官方大文件
---
+6 -5
View File
@@ -1,8 +1,8 @@
# 当前阶段说明
- **更新时间**2026-07-06
- **更新时间**2026-07-14
- **状态分支**`experiment`
- **最新功能提交**`789402c feat: add official resource sync pipeline`
- **最新功能提交**以当前 `git log --oneline -1` 为准
- **用途**:当前阶段交付说明、推送前核查和下一步依据。
## 1. 当前目标
@@ -28,6 +28,8 @@
- `OfficialResourcePullService` 的官方 URL 拒绝、`.part` 续传、重试、本地 manifest、官方 seed `.hash` 校验。
- `OfficialUpdateService` 的 auto-discover、bootstrap cache、v2 snapshot、remote marker diff、本地 audit/repair。
- `bat` one-shot 和 `--watch`
- `bat` 运行时 progress log 覆盖总体下载进度、单文件进度和校验结果摘要。
- 真实官方网络全量下载 smoke 已固化为 `scripts/official-full-pull-smoke.sh``make official-smoke``docs/guides/official-full-pull-smoke.md`
- `bat-ffi` 的 Manifest inspect 和 sync plan JSON API。
- `SqliteResourceRepository`
@@ -35,7 +37,6 @@
- Go CLI 最小可用入口。
- 官方同步下载结果自动导入 CAS + ResourceRepository 的用户级流程。
- 真实官方网络全量下载 smoke 记录。
- 完整 AssetBundle 解析。
- Patch、翻译系统、API Server、Web。
@@ -62,11 +63,11 @@ git status --short
## 4. 当前结论
当前 Rust 官方资源同步链路已经具备可运行闭环,但仓库还不是完整产品。下一步不应继续只扩展 example,而应补齐 Go CLI 最小入口、真实网络 smoke、CAS/ResourceRepository 编排和 AssetBundle 解析。
当前 Rust 官方资源同步链路已经具备可运行闭环,并已固化真实网络 smoke 的可重复命令,但仓库还不是完整产品。下一步不应继续只扩展 example,而应补齐 Go CLI 最小入口、CAS/ResourceRepository 编排和 AssetBundle 解析。
## 5. 下一步
1. 实现 Go CLI`bat doctor``bat sync --help``bat official sync --help`
2. `bat`真实官方网络 smoke,输出目录必须隔离。
2. `docs/guides/official-full-pull-smoke.md` 在具备网络和磁盘窗口的环境中执行真实官方网络 smoke,输出目录必须隔离。
3. 将官方同步下载结果接入 CAS + `SqliteResourceRepository`
4. 开始 AssetBundle UnityFS header/block/directory 解析。
+7 -4
View File
@@ -1,13 +1,13 @@
# 当前进度交接
- **更新时间**2026-07-06
- **更新时间**2026-07-14
- **状态分支**`experiment`
- **最新功能提交**`789402c feat: add official resource sync pipeline`
- **最新功能提交**以当前 `git log --oneline -1` 为准
- **用途**:给下一次对话快速恢复上下文,优先以当前工作区和已验证结果为准。
## 1. 现在处在什么阶段
项目已经完成基础整理、CAS V1Rust 官方资源同步闭环。下一阶段重点是 Go CLI 最小可用、真实官方网络 smoke、同步结果进入 CAS/ResourceRepository,以及 AssetBundle 解析起步。
项目已经完成基础整理、CAS V1Rust 官方资源同步闭环,以及真实官方网络 smoke 的可重复命令固化。下一阶段重点是 Go CLI 最小可用、同步结果进入 CAS/ResourceRepository,以及 AssetBundle 解析起步。
已确认的事实:
@@ -19,6 +19,8 @@
- 默认平台是 `Windows + Android`
- 真实下载会维护 `official-download-manifest.json`,并使用 size + BLAKE3、本地 audit/repair 和官方 seed `.hash` 校验。
- `--watch` 是 Rust 内部常驻检查模式,正常检查默认 1 小时,失败重试默认 60 秒;外部 systemd/container 只负责守护进程。
- `bat` progress log 会输出总体下载进度、单文件进度和校验结果摘要。
- 真实官方网络 smoke 已固化为 `scripts/official-full-pull-smoke.sh``make official-smoke``docs/guides/official-full-pull-smoke.md`,默认写入 `/tmp` 隔离目录。
## 2. 现在不要误解的点
@@ -34,7 +36,7 @@
仍待实现的主线工作:
1. Go CLI 最小入口:`bat doctor``bat sync --help``bat official sync --help`
2. 真实官方网络 smoke:dry-run、首次下载、二次 up-to-date、本地损坏 repair
2. 按 smoke runbook 在具备网络和磁盘窗口的环境中执行真实官方网络 smoke,并保留隔离目录报告
3. 官方同步下载结果进入 CAS + `SqliteResourceRepository` 的用户级流程。
4. Addressables parser 覆盖更多真实 catalog 结构。
5. AssetBundle UnityFS header/block/directory 解析。
@@ -57,4 +59,5 @@
- `DOCS_INDEX.md`
- `docs/reports/CURRENT_GAPS.md`
- `docs/guides/official-resource-test-pull.md`
- `docs/guides/official-full-pull-smoke.md`
- `docs/architecture/official-resource-backend.md`