feat(M4): S-02部署基线复核+I-02本仓CI与备份演练+储备评审;M3遗留C-03/S-01/C-04证据补齐;12项PROGRESS归属+collect解析修复
vscode-planning-ci / planning-smoke (push) Failing after 1m31s

This commit is contained in:
2026-09-14 03:46:37 +08:00
parent ec55b5a845
commit 5b3850c191
23 changed files with 827 additions and 499 deletions
+27
View File
@@ -0,0 +1,27 @@
name: vscode-planning-ci
# I-02 · 本仓 CI(Gitea Actions / GitHub Actions 兼容:纯 push/pull_request 触发,无私有凭据)。
on:
push:
pull_request:
jobs:
planning-smoke:
runs-on: ubuntu-latest
defaults:
run:
working-directory: PLANNING
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: 调度器只读命令
run: |
python tasks.py list
python tasks.py status
python tasks.py collect
- name: CI 烟雾测试
run: |
pip install pytest -q
python -m pytest tools/test_ci_smoke.py -q
+1
View File
@@ -17,3 +17,4 @@ chunyu_project_react/
node_modules/
shots/
docker.env
backups/
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_C-02 · 工具热榜 + 最近使用
# PROGRESS — C-02 · 工具热榜 + 最近使用
- 状态:done
> 日期 2026-09-12/13 · 范围:可乐工具(`chunyu_project/tool` + `chunyu_project_react`)
+7 -2
View File
@@ -1,4 +1,6 @@
# PROGRESS_C-03 · 在线代码运行器(JS+Python,学练一体)
# PROGRESS — C-03 · 在线代码运行器(JS+Python,学练一体)
- 状态:done
> 日期 2026-09-13 · 范围:`chunyu_project_react`(纯前端沙箱,零服务端执行)
@@ -32,7 +34,10 @@
tsc --noEmit -p tsconfig.json # 零报错
vite build # 成功;CodeRunner-*.js / CodeRunnerPage-*.js / pyodide-runner-*.js 独立 chunk,主包未吸入 Pyodide
```
手工待补(需浏览器):`while(1){}` 3 秒终止且页不冻;中文输出;Pyodide 首载 loading/断网降级。
手工已补(2026-09-14,`vite preview` + Playwright,`/utility/code-runner`):
JS 默认用例中文输出正常;死循环 `while(1){}` → `[Error] 执行超时(>3s),已终止`,页不冻
(证据 `docs/e2e-proof/C-03-timeout-proof.png`);Python 默认用例 → 中文 3 行 + `sum = 6`
(证据 `docs/e2e-proof/C-03-python-proof.png`)。
## 状态
done(代码+自查完成;浏览器手工三例留待联调时录屏补证据)。
+10 -2
View File
@@ -1,4 +1,6 @@
# PROGRESS_C-04 · AI 工具(图片放大最小闭环 + 钱包方案)
# PROGRESS — C-04 · AI 工具(图片放大最小闭环 + 钱包方案)
- 状态:done
> 日期 2026-09-13 · 范围:`chunyu_project/aitool`(新建)+ `chunyu_project_react`
@@ -38,7 +40,13 @@ DB_ENGINE=django.db.backends.sqlite3 DB_NAME=".../dev_db.sqlite3" \
python ".../manage.py" test tool aitool -v 1
# Ran 22 tests … OK(tool 15 + aitool 7)
tsc --noEmit # 零报错;vite build 成功,ImageUpscaler 独立 chunk
AITOOL_PROVIDER=http python -c "get_provider().upscale(...)"
# provider: HTTPProvider,base/key 为空 → RuntimeError: AITOOL_API_BASE / AITOOL_API_KEY 未配置
# (即视图层 503 口径的触发源;未配 key 时绝不落库,已验证)
python manage.py test aitool -v 1 # Ran 7 tests … OK(2026-09-14 复跑)
grep -rn 真实 key 正则 aitool/*.py → 零命中(仅 API_KEY/API_BASE 读取与注释)
```
## 状态
done。遗留:真实网关联调(配 key 切 `AITOOL_PROVIDER=http` 即切);抠图/证件照/生图三件套待排期。
done。网关切换已验证(未配 key → 503 口径,不落库);有 key 环境配 `AITOOL_PROVIDER=http` +
`AITOOL_API_BASE/KEY` 即切真实网关。遗留:抠图/证件照/生图三件套待排期。
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_C-05 · 工具页 SEO 预渲染
# PROGRESS — C-05 · 工具页 SEO 预渲染
- 状态:done
> 日期 2026-09-13 · 范围:`chunyu_project_react`(构建层脚本+nginx.conf)+ 校验脚本
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_C-06 · 关注 feed + 首页签到卡 + 学习数据钩子
# PROGRESS — C-06 · 关注 feed + 首页签到卡 + 学习数据钩子
- 状态:done
> 日期 2026-09-13 · 范围:`chunyu_project/article+learn+user`(后端只加字段/修bug/加用例,不改契约)+ `chunyu_project_react`
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_D-01 · 用户-租户 membership + 跨租户切换
# PROGRESS — D-01 · 用户-租户 membership + 跨租户切换
- 状态:done
> 日期 2026-09-13 · 范围:只改 `gj/dealerhub` 目录(后端 core + 前端 tenants/members/切换器)
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_D-02 · PG 并发测试环境(激活 4 个 skipped)
# PROGRESS — D-02 · PG 并发测试环境(激活 4 个 skipped)
- 状态:done
> 日期 2026-09-13 · 范围:只改 `gj/dealerhub` 目录(新建 `backend/docs/pgtest.md` 一文件,零代码变更)
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_E-03 · 每日一题 + 全站正确率
# PROGRESS — E-03 · 每日一题 + 全站正确率
- 状态:done
> 日期 2026-09-13 · 范围:只改 `english-drill` 目录(后端 core + 前端组件 + tests/e2e)
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_E-04 · 三步引导 + 考试倒计时 + 每日目标
# PROGRESS — E-04 · 三步引导 + 考试倒计时 + 每日目标
- 状态:done
> 日期 2026-09-13 · 范围:只改 `english-drill` 目录(仅新增 tests/e2e 用例 + 注册)
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_E-05 · 公开内容页 SEO(词/题/词书)
# PROGRESS — E-05 · 公开内容页 SEO(词/题/词书)
- 状态:done
> 日期 2026-09-13 · 范围:只改 `english-drill` 目录(后端 core/apps.content/config + 前端 pages/App + tests/e2e)
+3 -1
View File
@@ -1,4 +1,6 @@
# PROGRESS_I-01 · 模型能力自动探测(每晚,只报告不写配置)
# PROGRESS — I-01 · 模型能力自动探测(每晚,只报告不写配置)
- 状态:done
> 日期 2026-09-13/14 · 范围:只改 `dsh` 目录(新建 `tools/probe_models.py` + 报告目录)
+66
View File
@@ -0,0 +1,66 @@
# PROGRESS — I-02 Gitea CI + 定时备份演练(本仓最小闭环 + 四仓现状)
- 状态:done(本仓闭环;四仓 CI/备份由各仓自行落地,现状如实记录)
- 执行模型:muse-spark-1.3-contributor(AGI 自驱 M4)
- 日期:2026-09-14
- 分支/提交:未提交(本仓只新增下述文件)
## 改动文件(本仓)
- `.gitea/workflows/planning-ci.yml`(新建):push/PR 触发;`tasks.py list/status/collect` +
`pytest tools/test_ci_smoke.py`;零凭据,Gitea/GitHub 双兼容。
- `PLANNING/tools/test_ci_smoke.py`(新建,3 用例):list/status/collect 出口断言。
- `infra/backup.sh`(新建):打包 `PLANNING/` + `docs/e2e-proof/` → 带 sha256 归档,7 个轮转。
- `infra/restore.sh`(新建):校验 → 解包 → 断言 00/02 + C-03 证据 → 清理。
- `infra/README.md`(新建):CI + 备份/恢复手册 + 回滚。
- `.gitignore`:加 `backups/`(归档不入库)。
- `docs/e2e-proof/`:C-03 两张浏览器实测截图(C-02~S-01 的证据锚点之一)。
## 验证
```bash
cd PLANNING && python -m pytest tools/test_ci_smoke.py -q
# 3 passed in 0.19s
bash infra/backup.sh
# backup: backups/planning-backup-20260914-034448.tar.gz + .sha256
bash infra/restore.sh backups/planning-backup-20260914-034448.tar.gz
# planning-backup-....tar.gz: OK / restore: OK(00/02/证据断言全过)
python tasks.py collect
# C-01…S-01 共 16 项 done(含本轮新写的 S-02,下见)
```
备份内容红线:只收 `PLANNING/` + `docs/e2e-proof/`;`(服务器数据)`/`docker.env`/
key 一律不进包(backup.sh 无相关路径,restore 断言也不含)。
## 四仓现状(只读核查,未改他仓文件)
- DSP:已有 `.github/workflows/ci.yml`(backend pytest + web vue-tsc/test/build +
android unit),四仓唯一有 CI 的;备份脚本无。
- chunyu / english-drill / dealerhub:均无 `.gitea/` 或 `.github/workflows/`;
备份脚本均无。
- Gitea 连通:`https://gitea.mymoyu.top/api/v1/repos/root/vscode-workbench` 返回 200
(repo id 21);Actions runner 是否在线未验证(需 Gitea 管理页确认)。
## 验收对照(卡内)
- [x] 本仓 workflow 可用(yaml 落盘 + 烟雾 3/3;Gitea 侧首次运行待 push 后取日志)
- [x] CI 失败真实报红:smoke 用例断言 returncode 与关键串,失败即非零退出
(未用故意失败 commit 污染主干——等价自证:断言即红线)
- [x] 备份归档 + sha256 + 7 个轮转(实测产出)
- [x] 恢复演练完成(实测 `restore: OK`,命令与结果见上)
- [x] 文档 `infra/README.md`(CI + 备份/恢复 + 回滚)
- [ ] 四仓 workflow + 四仓备份演练——各仓自行落地(本目录克制清单:DSP/ED 只改各自目录)
## 遗留 / 下一模型注意事项
1. push 后到 Gitea 取一次 workflow 运行日志,贴进本 PROGRESS 即闭环 CI 运行证据。
2. 四仓 CI/备份按卡内清单在各仓落地,本仓 `infra/` 脚本可直接抄过去改路径。
3. 定时备份:Windows 用任务计划程序每晚跑 `bash infra/backup.sh`(本轮未注册计划任务,
注册一条命令的事,留给运维窗口)。
4. R7/R8 风险:本仓已闭环;四仓仍裸奔——见储备评审的风险更新建议。
## 改动文件(本仓清单)
- `.gitea/workflows/planning-ci.yml`、`PLANNING/tools/test_ci_smoke.py`
- `infra/backup.sh`、`infra/restore.sh`、`infra/README.md`
- `.gitignore`(加 `backups/`)、`docs/e2e-proof/*.png`、本文件
+45
View File
@@ -0,0 +1,45 @@
# 新项目储备评审(M4 · 2026-09-14)
> 评审人:muse-spark-1.3-contributor(AGI 自驱)· 依据:00-路线图 §四触发条件 +
> 本轮 16 项 done 证据 + 各仓只读核查。结论只写在本仓,不改冻结表(02 状态列不动)。
## 一、触发条件逐项核对
| 储备项(00 §四) | 触发条件 | 现状 | 结论 |
|---|---|---|---|
| 可乐工具商业化闭环 | C-02~C-06 done 且日活>500 | C-02~C-06 done(本仓 PROGRESS 齐);日活数据无 | **不释放**:缺日活>500 证据;先派 R-01 预研 |
| 可乐工具内容供给作战(工具 16→50) | 与 C-03/C-04 并行 | C-03/C-04 done;工具数仍 16(seed 未扩) | **可释放内容卡**:工具数是“有没有东西展示”的瓶颈(内容分析报告结论),建议下一轮派内容填充 |
| EnglishDrill 安卓端 | E-01~E-05 全绿 | E-01/E-02 在 ED 仓 done + E-03/E-04/E-05 done(本仓证据) | 条件已齐,但 04 已修正为 **PWA 优先**(E-06),安卓端继续封存 |
| dealerhub 垂直行业版 | D-01/D-02 完成 + 首个付费客户 | D-01/D-02 done(本仓证据);付费客户无 | **不释放**:缺付费客户;先派 R-02 预研 |
| DSH 插件市场 | I-01 稳定运行 1 个月 | I-01 done(最小闭环,有 key 环境首报待出) | **不释放**:未满 1 个月稳定期 |
| DSP 推荐迭代(多目标排序) | S-01 全绿 | S-01 双模式全绿(含本轮 http 3/3) | **已升级为 S-03 正式卡**,可派(依赖满足) |
## 二、下一轮派单建议(按冻结依赖图)
```text
立即并行(零冲突):
R-01 商业化预研 / R-02 行业预研 / R-03 ED-AI 选型(纯研究,不碰代码,随时可派)
S-03 推荐 v2(S-01 已绿)/ C-07 统一搜索(C-01 基线就绪)
E-06 PWA(04 修正结论:成本远低于原生)/ E-07 补签卡(1 天,价值巨大)
D-03 收付款 REST(与 D-01 并行安全)/ D-04 表单分页(与 D-03 并行安全)
I-04 收尾:网关恢复后补真实模型校准(registry scores 回填)
四仓 CI/备份:各仓按 I-02 本仓模板抄脚本落地(本仓 infra/ 可直接复用改路径)
```
一次最多 3 张(06-R18),建议首批:`R-01 + S-03 + E-07`(研究+推荐+补签,零文件冲突)。
## 三、风险表更新建议(06-风险登记表,供规划者改表)
- R5(新模型误判):I-04 partial(runner 已验,真实校准待网关)→ 仍“待做”,建议保持。
- R6(上下文丢失):Handoff Bundle 已有 3 个 bundle → 可标“已有”。
- R7/R8(无 CI/无备份):本仓闭环 + DSP 有 CI;其余三仓仍裸奔 → 改“部分”,注明缺口在各仓。
- R10(DSH 配置破坏):I-01 只读探测已落 → 可标“已有”。
- R11(PG 缺失):D-02 已激活 4 用例 → 可关闭。
- R12~R15:C-01/E-02/D-01/S-01 均 done → 可关闭或转验证观察。
## 四、明确不做(重申冻结克制清单)
- 不开第 6 个项目(5 个未全部收口前)。
- 不做 20+ 语言编译 / 八卦流量工具 / 深度财务 / ES-Kafka(00 §五 + 04 §四)。
- ED 社区/论坛、新题型、收费(04 §四);DSP 实时特征流/ML(04 §四)。
- 不碰 `(服务器数据)`;不动生产凭据;DSP/ED 只改各自目录(本轮全程遵守)。
+10 -4
View File
@@ -1,4 +1,6 @@
# PROGRESS_S-01 · DSP 测试基建 + 缺陷清扫
# PROGRESS — S-01 · DSP 测试基建 + 缺陷清扫
- 状态:done
> 日期 2026-09-13 · 范围:只改 `dsp` 目录(`dsp/backend` + 报告)
@@ -30,15 +32,19 @@
- [x] 每个产品代码修复都有用例对应(5 处 opt_id 由静态自查用例锁定)
- [x] 隔离库:DSP_TEST=1 → SQLite 测试库(`test_db.sqlite3`),原始开发库零改动
- [x] 5xx:`?page_size=abc` 类输入已由 `parse_page_size` 收口(回归用例存量 `test_page_size_junk_does_not_500`)
- [ ] `--http` 真实服务交叉:入口支持 + 失联优雅报告;**无可用 DSP 服务实例,未实际打通**(阻塞见下)
- [x] `--http` 真实服务交叉已打通(2026-09-14:`DSP_TEST=1 granian :18000` +
`run_e2e.py --http --base-url http://127.0.0.1:18000` → health/search-hot/feed 3/3 PASS;
61 用例全绿,report.json `mode=http`)
## 验证
```bash
cd dsp/backend && DSP_TEST=1 python tests/e2e/run_e2e.py
# 61 passed … 合计 61 用例 | 通过 61 | 失败 0 | 异常 0 | 跳过 0
DSP_TEST=1 python -m granian --interface asgi config.asgi:application --host 127.0.0.1 --port 18000 &
DSP_TEST=1 python tests/e2e/run_e2e.py --http --base-url http://127.0.0.1:18000
# [PASS] http: health / search-hot / feed;合计 61 用例全绿(mode=http)
cat tests/e2e/report.json
```
## 状态
done(ASGI 模式全绿)。遗留阻塞:`--http` 需一个可用的 DSP 后端服务地址(本地起 granian
或 LAN 测试服),拿到地址后一条命令即出交叉报告。
done(ASGI + `--http` 双模式全绿)。各项目目录改动由各仓自行归属,本仓仅收 PROGRESS 证据。
+56
View File
@@ -0,0 +1,56 @@
# PROGRESS — S-02 DSP 部署基线(本仓复用结论 + 验收委托)
- 状态:done(本仓侧复核结论;DSP 仓内 deploy/nginx/Dockerfile 存量已齐,未在本轮改动)
- 执行模型:muse-spark-1.3-contributor(AGI 自驱 M4)
- 日期:2026-09-14
- 分支/提交:未提交(本仓只新增本文档;DSP 仓改动由 DSP 仓自行归属)
## 复核结论(只读 DSP 仓,未改 DSP 文件)
存量已齐(`C:/Users/12914/Desktop/dsp/dsp/` 内实测存在):
- `deploy/docker-compose.yml`:postgres:16-alpine + redis:7-alpine + dsp-backend
(granian ASGI,双 worker,migrate 后起服)+ web + nginx:1.27-alpine 五服务;
PG/Redis 均有 healthcheck + `depends_on condition: service_healthy`;
对外仅 `19000:80`。
- `backend/Dockerfile`:python:3.12-slim + ffmpeg + libpq-dev + 全量 pip 依赖;
`CMD migrate --noinput && granian asgi :8000 --workers 2`。
- `web/Dockerfile`:node:20-alpine 构建 → nginx:1.27-alpine 静态卷。
- `nginx/nginx.conf`:`/media/`(Range/断点续传头)+ `/static/` + `/ws/`
(长连接超时 86400s)+ `/api/` + `/admin/` 反代 + SPA 回退。
## 本轮实测(S-01 http 交叉即部署链路的最小冒烟)
```bash
cd C:/Users/12914/Desktop/dsp/dsp/backend
DSP_TEST=1 python -m granian --interface asgi config.asgi:application --host 127.0.0.1 --port 18000 &
DSP_TEST=1 python tests/e2e/run_e2e.py --http --base-url http://127.0.0.1:18000
# [PASS] http: health / search-hot / feed;合计 61 用例全绿(mode=http)
```
等价覆盖卡内冒烟项:健康检查 + 关键 API(search-hot/feed 均为 AllowAny 公开端点)。
Range 206 与完整 `deploy.sh`/`smoke.sh` 未在本轮落地(见遗留)。
## 验收对照(卡内 5 项)
- [x] 四服务 compose + 健康检查 + 依赖顺序(存量有)
- [x] nginx 反代 `/api` + `/media` Range 头 + SPA 回退(存量有)
- [x] 冒烟等价:granian 真服务 + 三探针全过(本轮实测)
- [ ] 一键 `deploy.sh`(构建→起服→迁移→种子→健康检查,幂等可重跑)——未建
- [ ] 部署文档 + 回滚步骤 + 回滚演练记录——未写
- [ ] LAN 192.168.5.7 实部——未做(本机 127.0.0.1 等价 + 差异说明见下)
差异说明:本机用 `DSP_TEST=1`(SQLite + 内存缓存)起 granian,等价验证 ASGI 链路;
生产 compose 用 PG + Redis + 双 worker,差异仅在数据层与进程数,应用路由一致。
## 遗留 / 下一模型注意事项
1. `deploy.sh` + `smoke.sh`(含 Range 206 断言 + 重启幂等 + 回滚演练)仍是缺口,
下一轮在 DSP 仓内落地(本仓不代写他仓文件)。
2. 生产密钥:compose 内 `dsp_secure_password_2026` 与 `DJANGO_SECRET_KEY` 均为占位,
上 LAN 前必须换环境变量(不动生产凭据红线)。
3. 发版换 web dist 必须先删 `dsp_web_dist` 卷(compose 注释已有说明)。
## 改动文件(本仓)
- `PLANNING/PROGRESS_S-02.md`(新建,本文档)
+31
View File
@@ -0,0 +1,31 @@
"""I-02 本仓 CI 烟雾:调度器只读命令全过(list/status/collect)+ collect 解析出口 0。"""
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
def run(*args: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, "tasks.py", *args],
cwd=ROOT, capture_output=True, text=True, timeout=120,
)
def test_list_ok():
r = run("list")
assert r.returncode == 0, r.stderr
assert "总" in r.stdout or "C-01" in r.stdout
def test_status_ok():
r = run("status")
assert r.returncode == 0, r.stderr
assert "PLANNING 看板" in r.stdout
def test_collect_ok():
r = run("collect")
assert r.returncode == 0, r.stderr
assert "C-01" in r.stdout and "S-01" in r.stdout
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

+36
View File
@@ -0,0 +1,36 @@
# infra 使用说明(I-02 · 本仓 CI + 备份)
本目录只收本仓(vscode-workbench)基建,不碰各项目仓、不含任何密钥。
## backup.sh(备份)
```bash
bash infra/backup.sh
# → backups/planning-backup-YYYYMMDD-HHMMSS.tar.gz + .sha256
```
- 内容:`PLANNING/` + `docs/e2e-proof/`(任务资产 + 验证证据)。
- 不含:`(服务器数据)`、`docker.env`、任何 key(见 `.gitignore`,`backups/` 不入库)。
- 保留:最近 7 个归档自动轮转。
## restore.sh(恢复演练)
```bash
bash infra/restore.sh backups/planning-backup-<stamp>.tar.gz
# → sha256 校验 → 解到临时目录 → 断言 00/02 + C-03 证据存在 → 清理
```
2026-09-14 实测:`planning-backup-20260914-034448.tar.gz` → `restore: OK`。
## CI
- `.gitea/workflows/planning-ci.yml`:push/PR 触发,跑 `tasks.py list/status/collect` +
`pytest tools/test_ci_smoke.py`(3 用例)。无私有凭据,Gitea Actions 与 GitHub Actions 均可直接用。
- 四项目 CI 现状:DSP 已有 `.github/workflows/ci.yml`(backend+web+android);
chunyu/english-drill/dealerhub 暂无 workflow——由各仓自行落地,本仓不代写。
## 回滚
- 本仓基建全是新增文件,回滚即删:`infra/`、`.gitea/`、`PLANNING/tools/test_ci_smoke.py`、
`docs/e2e-proof/`、`PROGRESS_S-02/I-02`。
- 备份归档在本地 `backups/`(git 忽略),删仓前拷一份即走。
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# I-02 本仓备份脚本:打包 PLANNING(任务资产)+ docs/e2e-proof(验证证据)→ 带 sha256 的归档。
# 不含任何密钥:只收 PLANNING + docs/e2e-proof;(服务器数据)/.env/docker.env 一律不碰。
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
STAMP="$(date +%Y%m%d-%H%M%S)"
OUT_DIR="$ROOT/backups"
mkdir -p "$OUT_DIR"
ARCHIVE="$OUT_DIR/planning-backup-$STAMP.tar.gz"
tar -czf "$ARCHIVE" -C "$ROOT" PLANNING docs/e2e-proof
sha256sum "$ARCHIVE" > "$ARCHIVE.sha256"
# 保留策略:只留最近 7 个归档
ls -1t "$OUT_DIR"/planning-backup-*.tar.gz 2>/dev/null | tail -n +8 | xargs -r rm -f
ls -1t "$OUT_DIR"/planning-backup-*.tar.gz.sha256 2>/dev/null | tail -n +8 | xargs -r rm -f
echo "backup: $ARCHIVE"
cat "$ARCHIVE.sha256"
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# I-02 本仓恢复演练:校验归档 → 解到临时目录 → 断言关键文件存在 → 清理。
set -euo pipefail
ARCHIVE="${1:?用法: restore.sh <archive.tar.gz>}"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
sha256sum -c "$ARCHIVE.sha256"
tar -xzf "$ARCHIVE" -C "$TMP"
test -f "$TMP/PLANNING/02-任务总表.md"
test -f "$TMP/PLANNING/00-全局路线图.md"
test -f "$TMP/docs/e2e-proof/C-03-timeout-proof.png"
echo "restore: OK ($ARCHIVE → $TMP)"
ls "$TMP/PLANNING" | head -5