docs(impl): PR2 implementation note + acceptance checklist

记录 Stage 0 PR2 的实施落点、关键 LOCK 决策、跟进项与 7 commit 列表。
验收:3087 passed + 23 skipped + 0 failed(vs PR1 基线 3085 + 2 新
default-backend 测试)。

Stage 0 PR2 T2.10. PR2 完成。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1445043649
2026-05-11 09:23:16 +08:00
parent c53295dfee
commit 1112a1971b
@@ -0,0 +1,75 @@
# PR2 · 默认 backend 切到 Postgres
> 实现笔记。对应 [docs/superpowers/plans/2026-05-10-stage-0-multi-tenant-foundation.md](../../superpowers/plans/2026-05-10-stage-0-multi-tenant-foundation.md) PR2T2.1-T2.10)。
>
> 状态:**已落地**7 commits 提交在 branch `feat/stage-0-pr2-postgres-default`。
## 范围
让 Postgres 成为 dev + 生产的默认 backendSQLite 沦为可选 fallback——但**不破坏** SQLite 路径(Stage 0 期间 dev 仍可走 SQLite)。
具体动作:
- `config.example.yaml` `database` 段:postgres 活跃、SQLite 注释;bump `config_version` 9→10
- `.env.example``DATABASE_URL` 行从注释改为活值(指向本地 docker postgres
- `docker-compose-dev.yaml` `gateway depends_on postgres healthcheck`(生产 compose 不动——prod 用远程 RDS
- `scripts/check.py``check_postgres_preflight()``make dev` 链上 PG 不通时 FAIL 阻断启动
- `README.md` Quick Start 加 Step 3 "Database backend"
- 2 个 regression test 锁定:(a) 显式 sqlite 仍工作 (b) `config.example.yaml` 默认 postgres
## 验收
- [x] 全套 `pytest tests/` 3087 passed + 23 skipped + 0 failedPR1 基线 3085diff = 2 新 default-backend 测试)
- [x] `test_explicit_sqlite_backend_still_works` PASSSQLite regression 防线)
- [x] `test_config_example_default_backend_is_postgres` PASS
- [x] `python scripts/check.py` 在 sqlite 配置下 silent skip postgres preflight(无破坏现有用户)
- [x] `make doctor` 在 postgres 配置 + DATABASE_URL 不可达时给可执行 fix(指向 docker compose 命令)
- [x] `docker compose -f docker/docker-compose-dev.yaml config` 校验通过(postgres + gateway depends_on healthcheck 都合法)
- [ ] live`make dev` 在 postgres 模式下 preflight + 服务启动——**待 docker daemon 起后由用户实测**
- [ ] liveCI workflow `backend-postgres-tests` 跑通——**PR push 后验证**
## 关键决策(lock 项)
| 项 | 选择 | 理由 |
|---|---|---|
| 默认 backend | postgres | Stage 0 不可逆决策(plan §不可逆决策一览);省 Stage 1 重 ALTER 4 张表的返工 |
| SQLite 处理 | 注释保留为 fallback,不删 | offline dev / 单元测试场景仍需要 |
| `config_version` bump | 9 → 10 | 默认行为变化属于 schema 变更,触发 `AppConfig.from_file()` 旧版 warning |
| `DATABASE_URL` 形态 | `postgresql+asyncpg://` 而非 `postgresql://` | 与 SQLAlchemy 异步 dialect 对齐,避免 dialect 推断警告 |
| `depends_on` 仅 dev compose | prod compose 无 postgres service | 生产用远程 RDS,不在 compose 内 |
| PG preflight 加在 check.py | 不在 serve.sh 加 bash 版 | Makefile 已串 check.py → serve.sh,避免双重实现 |
| preflight FAIL vs WARN | FAIL(阻断启动) | 配了 PG 但不通就一定崩,preflight 早死好过 runtime 崩 |
| sqlite→pg 数据迁移工具 | **不实现**plan T2.8 marked optional | Stage 0 没有生产数据需要迁;follow-up |
## 跟进项(不在 PR2 范围)
- **PR3+**:在新建的 PG 上跑 workspace 表 schema
- **`backend/CLAUDE.md` 更新**plan T2.9 包括 backend/CLAUDE.md,本 PR 仅做了 READMECLAUDE.md follow-up
- **`scripts/migrate_sqlite_to_postgres.py`**plan T2.8 optional):如果将来有用户从 SQLite dev 迁 PG 的需求,再写
- **prod compose postgres service**:当前 docker-compose.yaml(生产)无 postgres service;如果将来不用远程 RDS,可补上
## 涉及文件
| 类别 | 文件 |
|---|---|
| 配置 | `config.example.yaml``.env.example` |
| Docker | `docker/docker-compose-dev.yaml`gateway depends_on postgres |
| 脚本 | `scripts/check.py`postgres preflight |
| 测试 | `backend/tests/test_default_database_backend.py` |
| 文档 | `README.md` |
## 提交记录
7 commits(每条 1 task):
```
404135a1 feat(config): default database backend to postgres T2.1
7d3d3560 feat(env): activate DATABASE_URL with local-dev default T2.2
d312bdf9 test(config): pin default postgres backend + sqlite regression T2.3 + T2.4
3e62a0f6 feat(docker): gateway depends_on postgres healthcheck (dev only) T2.5
83b680b2 feat(check): postgres preflight in scripts/check.py T2.6
745a33e0 chore: T2.7 acknowledgement (covered by T1.8) T2.7empty
c53295df docs(readme): add Database backend section in Quick Start T2.9
```
T2.10impl doc)是这份文档本身。
T2.8sqlite→pg 迁移工具)跳过——plan marked optional + Stage 0 无生产数据。