docs(plan): 修复计划评审两卡点+六建议

- cms 验收改为与只读基线逐字节一致(防 agent 误 restore cms)
- .gitignore 反排除 .env.example(否则 git add 失败)
- Task0.1 补 cms 基线记录与 gitignore 验证步骤
- Task0.2 补数据授权确认;Task5 补 test 脚本
- Task12 七值改八值;Task10 复选框笔误;Task13 helpers 机制具体化

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-20 16:50:01 +08:00
parent e6c771151d
commit 8da5fa5a23
2 changed files with 19 additions and 8 deletions
+1
View File
@@ -11,6 +11,7 @@ storage/
.data/ .data/
.env .env
.env.* .env.*
!.env.example
*.local *.local
# 日志与临时文件 # 日志与临时文件
@@ -18,7 +18,7 @@
1. **不改动 `D:\project\cms`**:只读。备份是"读出来写到别处",也不算改动。 1. **不改动 `D:\project\cms`**:只读。备份是"读出来写到别处",也不算改动。
2. **PG 端口**:cms 项目 compose 占用宿主 5433;本项目用 **5434**。 2. **PG 端口**:cms 项目 compose 占用宿主 5433;本项目用 **5434**。
3. **真实数据不入 git**:`.gitignore` 已忽略 `storage/`、`artifacts/`、`.env*`。夹具必须脱敏手写,不从真实 WXR 复制内容。 3. **真实数据不入 git**:`.gitignore` 已忽略 `storage/`、`artifacts/`、`.env*`(已加 `!.env.example` 反排除,示例文件可提交)。夹具必须脱敏手写,不从真实 WXR 复制内容。
4. **Windows 环境**:路径分隔符、长路径(媒体全角文件名)注意;命令以 Git Bash 为准。 4. **Windows 环境**:路径分隔符、长路径(媒体全角文件名)注意;命令以 Git Bash 为准。
5. 上位规格字段定义见 spec §5(表结构原文)、§7.3(UniversalRow)、§12.1(Route Manifest)、§9.1(Theme Manifest)——本计划代码与之一致,冲突时以 spec 为准并回报。 5. 上位规格字段定义见 spec §5(表结构原文)、§7.3(UniversalRow)、§12.1(Route Manifest)、§9.1(Theme Manifest)——本计划代码与之一致,冲突时以 spec 为准并回报。
@@ -34,7 +34,17 @@
Run: `node -v && pnpm -v && docker --version && docker compose version` Run: `node -v && pnpm -v && docker --version && docker compose version`
Expected: node ≥ v22.x;pnpm ≥ 9.x;docker 与 compose 可用。**若 node < 22 停止并报告用户。** Expected: node ≥ v22.x;pnpm ≥ 9.x;docker 与 compose 可用。**若 node < 22 停止并报告用户。**
- [ ] **Step 2: 写基线文档** - [ ] **Step 2: 记录 cms 只读基线(验收对照用)**
Run: `git -C D:/project/cms rev-parse HEAD && git -C D:/project/cms status --porcelain`
把两段输出**原样**存入 `docs/evidence/env-baseline.md`(注:cms 工作树可能存在既有未提交改动,如 `about.astro`——这不是我们造成的,照记不误。后续验收以"与本基线一致"为准;**发现任何差异只报告用户,绝不执行 restore/checkout**)。
- [ ] **Step 3: 验证 gitignore 覆盖**
Run: `git check-ignore -v storage artifacts .env; git add --dry-run .env.example`
Expected: 前三者各命中一条忽略规则;`.env.example` 反排除生效、dry-run add 成功。输出记入 env-baseline.md。
- [ ] **Step 4: 写基线文档**
```markdown ```markdown
# docs/evidence/env-baseline.md # docs/evidence/env-baseline.md
@@ -59,7 +69,7 @@ git commit -m "chore(evidence): 记录阶段0环境版本基线"
**Files:** 无代码;产出备份与 `docs/evidence/backup-record.md` **Files:** 无代码;产出备份与 `docs/evidence/backup-record.md`
- [ ] **Step 1: 向用户确认备份目标路径 BACKUP_DIR**(如 `E:\backups\cms-2026-10-20`)。未确认前跳过本任务后续步骤。 - [ ] **Step 1: 向用户确认备份目标路径 BACKUP_DIR**(如 `E:\backups\cms-2026-10-20`),**并同时确认试点数据的使用授权与敏感信息范围**(授权结论记入 backup-record.md)。未确认前跳过本任务后续步骤。
- [ ] **Step 2: 若 cms 的 PG 容器在运行,先停止(文件级拷贝一致性)** - [ ] **Step 2: 若 cms 的 PG 容器在运行,先停止(文件级拷贝一致性)**
@@ -601,7 +611,7 @@ describe('数据库连接', () => {
- [ ] **Step 2: 依赖与实现** - [ ] **Step 2: 依赖与实现**
`apps/api/package.json`:dependencies `@nestjs/core@^10`、`@nestjs/common@^10`、`reflect-metadata`、`rxjs`、`drizzle-orm`、`postgres`(postgres.js);devDeps `drizzle-kit`、`dotenv`;scripts:`db:generate: drizzle-kit generate`、`db:migrate: drizzle-kit migrate`、`db:test-setup`(见 Task 13)。 `apps/api/package.json`:dependencies `@nestjs/core@^10`、`@nestjs/common@^10`、`reflect-metadata`、`rxjs`、`drizzle-orm`、`postgres`(postgres.js);devDeps `drizzle-kit`、`dotenv`;scripts:`test: vitest run`、`db:generate: drizzle-kit generate`、`db:migrate: drizzle-kit migrate`、`db:test-setup`(见 Task 13)。
```ts ```ts
// apps/api/src/db/client.ts // apps/api/src/db/client.ts
@@ -751,7 +761,7 @@ CREATE TRIGGER source_snapshots_immutable BEFORE UPDATE OR DELETE ON source_snap
- [ ] **Step 1: 失败测试要点**:`UNIQUE(site_id, source_url)` 与 `UNIQUE(site_id, public_path)`(media_assets);`media_usages` 主键 (media_asset_id, content_revision_id, field_path);status enum 含 ready/missing/quarantined/unsupported。 - [ ] **Step 1: 失败测试要点**:`UNIQUE(site_id, source_url)` 与 `UNIQUE(site_id, public_path)`(media_assets);`media_usages` 主键 (media_asset_id, content_revision_id, field_path);status enum 含 ready/missing/quarantined/unsupported。
- [ ] **Step 2: schema**:照 spec §5.5。 - [ ] **Step 2: schema**:照 spec §5.5。
- ] **Step 3: generate + migrate + 测试** → **Step 4: Commit** `feat(db): 0005 媒体域——assets/usages 双唯一` - [ ] **Step 3: generate + migrate + 测试** → **Step 4: Commit** `feat(db): 0005 媒体域——assets/usages 双唯一`
--- ---
@@ -778,7 +788,7 @@ CREATE UNIQUE INDEX route_exact_uq ON route_registry (site_id, host, exact_route
**Files:** Modify `schema.ts`;Test `tests/integration/db.jobs.test.ts` **Files:** Modify `schema.ts`;Test `tests/integration/db.jobs.test.ts`
- [ ] **Step 1: 失败测试要点**:`build_jobs.idempotency_key` 唯一、状态 enum 七值(queued/snapshotting/building/validating/succeeded/failed/cancelled/stale);`build_input_snapshots` 不可变触发器 + `build_job_id` UNIQUE;`audit_logs` UPDATE/DELETE 抛错(追加式);`validation_runs/validation_issues` 表存在且 issues 有 severity 列。 - [ ] **Step 1: 失败测试要点**:`build_jobs.idempotency_key` 唯一、状态 enum 八值(queued/snapshotting/building/validating/succeeded/failed/cancelled/stale);`build_input_snapshots` 不可变触发器 + `build_job_id` UNIQUE;`audit_logs` UPDATE/DELETE 抛错(追加式);`validation_runs/validation_issues` 表存在且 issues 有 severity 列。
- [ ] **Step 2: schema**:照 spec §5.7/§5.8;`audit_logs_immutable` 触发器。 - [ ] **Step 2: schema**:照 spec §5.7/§5.8;`audit_logs_immutable` 触发器。
- [ ] **Step 3: generate + migrate + 测试** → **Step 4: Commit** `feat(db): 0007 构建/验收/审计域 + 追加式审计` - [ ] **Step 3: generate + migrate + 测试** → **Step 4: Commit** `feat(db): 0007 构建/验收/审计域 + 追加式审计`
@@ -815,7 +825,7 @@ describe('空库全量迁移', () => {
}) })
``` ```
- [ ] **Step 2: helpers 收敛**(Task 6–12 的内联建库逻辑统一为:每个集成测试文件 beforeAll 用 helper 建干净库;此处抽出公共函数)。 - [ ] **Step 2: helpers 收敛**(机制:vitest `globalSetup` 创建临时库 `sf_test_<timestamp>` → 对其运行全部迁移 → 把连接串写入注入的 `process.env.DATABASE_URL_TEST` 供测试读取;`globalTeardown` drop 库。Task 6–12 的内联建库逻辑统一收敛为调用此 helper)。
- [ ] **Step 3: 运行**:`pnpm db:up && pnpm test` 全绿。 - [ ] **Step 3: 运行**:`pnpm db:up && pnpm test` 全绿。
- [ ] **Step 4: Commit** `test(db): 空库一键迁移 + 21 表断言(阶段1验收)` - [ ] **Step 4: Commit** `test(db): 空库一键迁移 + 21 表断言(阶段1验收)`
@@ -843,7 +853,7 @@ git push origin main
## 验收(对照 spec §15 阶段 0/1) ## 验收(对照 spec §15 阶段 0/1)
- [ ] 原项目未被修改(`git -C D:/project/cms status` 干净) - [ ] 原项目未被修改(cms 的 `git status --porcelain` 输出与 Task 0.1 记录的基线**逐字节一致**——无新增改动即可;cms 工作树可能存在既有未提交改动,那是基线的一部分。**发现差异只报告用户,绝不 restore/checkout cms**)
- [ ] 备份有哈希与位置记录;`git status` 不出现真实试点数据 - [ ] 备份有哈希与位置记录;`git status` 不出现真实试点数据
- [ ] 空环境一条命令启动数据库并迁移(Task 13) - [ ] 空环境一条命令启动数据库并迁移(Task 13)
- [ ] 所有核心约束有自动测试(不可变×4、唯一键×7+、枚举 CHECK) - [ ] 所有核心约束有自动测试(不可变×4、唯一键×7+、枚举 CHECK)