diff --git a/.gitignore b/.gitignore index e358d34..019aa6b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ storage/ .data/ .env .env.* +!.env.example *.local # 日志与临时文件 diff --git a/docs/superpowers/plans/2026-10-20-slice-foundation-phase0-1.md b/docs/superpowers/plans/2026-10-20-slice-foundation-phase0-1.md index 76cea62..db3958d 100644 --- a/docs/superpowers/plans/2026-10-20-slice-foundation-phase0-1.md +++ b/docs/superpowers/plans/2026-10-20-slice-foundation-phase0-1.md @@ -18,7 +18,7 @@ 1. **不改动 `D:\project\cms`**:只读。备份是"读出来写到别处",也不算改动。 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 为准。 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` 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 # docs/evidence/env-baseline.md @@ -59,7 +69,7 @@ git commit -m "chore(evidence): 记录阶段0环境版本基线" **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 容器在运行,先停止(文件级拷贝一致性)** @@ -601,7 +611,7 @@ describe('数据库连接', () => { - [ ] **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 // 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 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` -- [ ] **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 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_` → 对其运行全部迁移 → 把连接串写入注入的 `process.env.DATABASE_URL_TEST` 供测试读取;`globalTeardown` drop 库。Task 6–12 的内联建库逻辑统一收敛为调用此 helper)。 - [ ] **Step 3: 运行**:`pnpm db:up && pnpm test` 全绿。 - [ ] **Step 4: Commit** `test(db): 空库一键迁移 + 21 表断言(阶段1验收)` @@ -843,7 +853,7 @@ git push origin main ## 验收(对照 spec §15 阶段 0/1) -- [ ] 原项目未被修改(`git -C D:/project/cms status` 干净) +- [ ] 原项目未被修改(cms 的 `git status --porcelain` 输出与 Task 0.1 记录的基线**逐字节一致**——无新增改动即可;cms 工作树可能存在既有未提交改动,那是基线的一部分。**发现差异只报告用户,绝不 restore/checkout cms**) - [ ] 备份有哈希与位置记录;`git status` 不出现真实试点数据 - [ ] 空环境一条命令启动数据库并迁移(Task 13) - [ ] 所有核心约束有自动测试(不可变×4、唯一键×7+、枚举 CHECK)