# tools/recover —— 误删源码的恢复工具 ## 事故 2026-10-09,执行 `tools/p2_import_legacy.py` 把老 `zteits-clouds` 的核心模块搬进 `parking-cloud/` 时,`parking-module-system` 与 `parking-module-api` 的 `src/main/java` **被整个 `shutil.rmtree` 删掉**——这两个模块既装老代码,又装 P1 手写的新代码,而当时的脚本为了「可重复执行」一律先删目标目录。 删除清单:96 个文件(`parking-module-system` 92 + `parking-module-api` 4), 全部是 `com.zteits.parking.*` 包(新工程自己的包名,老工程里根本不存在)。 为什么差点不可恢复:`parking-cloud/` **不是 git 仓库**, IntelliJ LocalHistory 里也没有这些路径。仅剩 `target/classes` 下的 `.class`。 ## 恢复配方 | 脚本 | 恢复什么 | 依据 | |---|---|---| | `scan.py` | 只是**盘点**:列出会话里有哪些文件可恢复、各有几个操作 | — | | `restore_p1.py` | 80 个文件 | Claude Code 会话 jsonl 里的 `Write`/`Edit` 按序重放 | | `regen_derived.py` | 12 个 Mapper + 4 个 apibase 文件 | 当时用的是 bash 生成器与 `sed`,规则确定性,可重算 | 合计 96 个,与 `target/classes` 里的 96 个 `.class` 一一对应(脚本会自校验)。 ```bash cd /Users/wangbiao/IdeaProjects/parking/parking-cloud # 1) 重放工具写过的文件 -> tools/recover/out/ python3 -I tools/recover/restore_p1.py \ ~/.claude/projects/-Users-wangbiao-IdeaProjects-parking-zteits-clouds/a887c773-a75a-45d4-9ea4-4406d3a1991b.jsonl # 2) 重算生成器/sed 产出的文件 -> 同一个 out/ python3 -I tools/recover/regen_derived.py # 3) 与 .class 对账(期望「缺 0 / 多 0」),确认无误后回拷源码树 # 实际执行时用的是 git 式的「目标已存在且内容不同就拒绝覆盖」,不会盖掉现有代码 ``` 产物先落 `tools/recover/out/`(镜像源码树的相对路径),核对后再拷回去, **不要**让恢复脚本直接写源码树。 ## 两个关键坑(都在脚本注释里写明了) 1. **必须剔除失败的操作。** 会话里 `Edit` 报错后助手会重试,失败的那次也留在 jsonl 里;照单全收会让重放内容和真实历史分叉。判据是 `tool_result.is_error`。 不剔除时 80 个里有 4 个重放失败(`LoginLogTypeEnum`/`LoginResultEnum`/ `DataScopeEnum`/`RoleServiceImpl`),剔除后 80/80 干净通过。 2. **有的文件不是 Write 写的。** 12 个 Mapper 出自一句 bash 函数 + heredoc, 4 个 apibase 出自 `sed` 改包名,都不在 Write 记录里。它们必须按当时的**同样规则** 重算,而不是手写一个"看起来对"的版本——`regen_derived.py` 里连生成器第 4 个参数 `extra`(三个关联表被误传成 `*`、`'*'`,随后被 `sed '/^\*$/d'` 删掉)都如实保留, 就是为了和当时的最终文件**逐字节一致**;该校验用会话里现成的一次 `cat UserRoleMapper.java` 输出做过 diff,结果无差异。 ## 别再犯 根因是「为了幂等而先删目录」。`tools/p2_import_legacy.py` 已改成 **默认只增不删**,`--prune` 也只删「老工程镜像过来的相对路径」, 并有 `PROTECTED_PREFIXES` 兜底 `com/zteits/parking/**`。 详见 `AGENTS.md` 的坑 12 与 `p2_import_legacy.py` 的模块 docstring。