Files
skelet/docs/review/phase1-review.md
T

239 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 1 评审
> 评审日期:2026-07-06
> 评审视角:全栈开发工程师
> 评审范围:T-101 至 T-104 的内容模型、迁移、测试、任务状态和当前文档同步。
## 结论
Phase 1 尚未完全达标。
T-101、T-103 基本达标;T-102 主体模型已建立,但 `SkeletonProjectPage` 的必填多对多约束没有被实际校验;T-104 标为 `BLOCKED` 是合理的,因为当前仓库没有人工确认的首批种子内容清单。
当前不能把 Phase 1 视为完整完成。最低需要先修复:
1. `SkeletonProjectPage.scenarios` / `languages` 至少 1 个的校验。
2. 相关单元测试,覆盖缺少场景 / 缺少语言时抛 `ValidationError`。
3. `AGENTS.md` 当前阶段和下一步任务,与 `docs/06-tasks.md`、`docs/current-state.md` 同步。
## Findings
### 1. High:`scenarios` / `languages` 必填约束未真正生效
架构文档明确要求:
- `docs/04-architecture.md` §3.3:`scenarios` 至少 1 个,`languages` 至少 1 个。
- `docs/06-tasks.md` T-102:`SkeletonProjectPage` 必须严格按 `04-architecture.md` §3.3 表和必填 / 默认附注实现。
当前模型只写了:
```python
scenarios = ParentalManyToManyField("core.ScenarioPage", blank=False)
languages = ParentalManyToManyField("core.Language", blank=False)
```
位置:`core/models.py`。
但实测 `blank=False` 不会让 `SkeletonProjectPage.full_clean()` 拦截空多对多。临时创建正确页面树后分别验证:
```text
no_m2m PASS_NO_ERROR
language_only PASS_NO_ERROR
scenario_only PASS_NO_ERROR
```
这意味着项目可以没有场景、没有语言,仍通过模型校验。后续筛选、场景页列表和内容质量都会受影响。
建议修复:
- 在 `SkeletonProjectPage.clean()` 中检查:
- 已保存对象:`self.scenarios.exists()` / `self.languages.exists()`。
- Wagtail 编辑流程中如果使用 unsaved cluster relation,需要确认 `ParentalManyToManyField` 的表单数据能被正确校验。
- 或实现 Wagtail admin form / panel 层校验,确保后台编辑保存时无法为空。
- 增加单元测试:
- 缺 `scenarios` 时抛 `ValidationError`。
- 缺 `languages` 时抛 `ValidationError`。
- 两者都有时 `full_clean()` 通过。
### 2. Medium:T-102 的测试没有覆盖正确页面树和必填场景
`core/tests.py` 中 `test_valid_project_full_clean` 把 `SkeletonProjectPage` 直接加到 root 下:
```python
root = Page.get_first_root_node()
root.add_child(instance=project)
```
但模型声明和架构要求是:
```text
HomePage
└── ProjectIndexPage
└── SkeletonProjectPage
```
`SkeletonProjectPage.parent_page_types = ["core.ProjectIndexPage"]`,直接挂 root 在真实 Wagtail 页面创建流程里是不允许的。
实测:
```text
can_create_project_under_root False
can_create_article_under_root False
can_create_scenario_under_root False
```
当前测试绕过了真实父子页面约束,也没有给项目添加 `scenario`,因此无法证明 T-102 的核心编辑路径可用。
建议修复:
- 测试中创建 `HomePage -> ProjectIndexPage -> SkeletonProjectPage`。
- 为合法项目同时添加 `scenario` 和 `language`。
- 文章测试中创建 `HomePage -> ArticleIndexPage -> ArticlePage`。
### 3. Medium:`AGENTS.md` 当前阶段已过期
`docs/06-tasks.md` 显示:
```text
T-101 DONE
T-102 DONE
T-103 DONE
T-104 BLOCKED
```
`docs/current-state.md` 也写:
```text
下一个可领取任务:T-104(BLOCKED,等待人工确认种子内容)
```
但 `AGENTS.md` 仍写:
```text
下一步 ... T-101:建立场景、语言、框架、数据库、功能标签模型。
```
这会误导下一轮 agent 重复领取已完成任务,违反任务状态变化同步 `current-state.md` 和入口文档的工作规则。
建议修复:
- `AGENTS.md` 改为 Phase 1 局部完成:T-101/T-102/T-103 已完成,T-104 BLOCKED。
- 下一步写清楚:等待人工确认种子内容;未解除阻塞前不要进入 Phase 2。
## 逐任务评审
### T-101 建立场景、语言、框架、数据库、功能标签模型
状态:基本达标。
已确认:
- `ScenarioIndexPage` / `ScenarioPage` 是 Page,不是 Snippet。
- `Language`、`Framework`、`DatabaseOption`、`SkeletonFeature` 是 Snippet,并使用 `@register_snippet` 注册。
- 4 个 Snippet 都有 `name` unique + `slug` unique。
- 没有实现 `AiCodingScore` 模型,符合 MVP 决策。
- 迁移 `core/migrations/0001_initial.py` 存在并已应用。
- 测试覆盖创建对象和 slug 唯一性。
遗留风险:
- 测试只验证数据库唯一约束抛 `IntegrityError`,没有验证 Wagtail 后台表单体验;但对 T-101 当前验收不是阻断。
### T-102 建立骨架项目详情模型
状态:未完全达标。
已确认:
- `ProjectIndexPage` 和 `SkeletonProjectPage` 已建立。
- `SkeletonProjectPage` 字段基本覆盖 `04-architecture.md` §3.3。
- `scenarios`、`languages`、`frameworks`、`databases`、`features` 使用 `ParentalManyToManyField`。
- 6 个评分字段有 `MinValueValidator(0)` / `MaxValueValidator(5)`。
- `total_score` 是 property,计算 6 项总分。
- 后台面板分为 5 组。
- 迁移 `0002_projectindexpage_skeletonprojectpage.py` 存在并已应用。
未达标点:
- `scenarios` / `languages` 至少 1 个没有实际校验。
- 合法对象测试没有创建正确页面树,也没有添加 `scenario`。
- 缺少针对空 `scenarios` / 空 `languages` 的失败测试。
### T-103 建立文章模型
状态:基本达标。
已确认:
- `ArticleIndexPage` 和 `ArticlePage` 已建立。
- `ArticlePage.body` 使用 `RichTextField`。
- `related_projects` 是可空多对多,指向 `SkeletonProjectPage`。
- 迁移 `0003_articleindexpage_articlepage.py` 存在并已应用。
- 测试覆盖文章关联项目。
遗留风险:
- 当前测试把 `ArticlePage` 直接挂 root,没有按 `ArticleIndexPage -> ArticlePage` 的真实页面树创建。建议随 T-102 测试一起修正。
### T-104 准备首批种子内容
状态:BLOCKED 合理。
已确认:
- 当前数据库中 `ScenarioPage` / `SkeletonProjectPage` / `ArticlePage` count 均为 0。
- 当前没有人工确认的首批项目清单、评分和评语。
- `docs/06-tasks.md` 明确要求无清单时标 `BLOCKED`,禁止模型编造。
- `progress.md` 已记录 T-104 因缺少人工确认清单而 BLOCKED。
因此 T-104 不能标 DONE,但当前 BLOCKED 状态符合规则。
## 验证命令
本次评审运行:
```bash
bash -lc '.venv/bin/python3.12.exe manage.py check'
bash -lc '.venv/bin/python3.12.exe manage.py test'
bash -lc '.venv/bin/python3.12.exe manage.py makemigrations --check --dry-run'
bash -lc '.venv/bin/python3.12.exe manage.py showmigrations core'
```
结果:
- `manage.py check`:0 errors,9 个 treebeard 兼容 warning。
- `manage.py test`:17 tests passed。
- `makemigrations --check --dry-run`:No changes detected。
- `showmigrations core`:`0001_initial`、`0002_projectindexpage_skeletonprojectpage`、`0003_articleindexpage_articlepage` 已应用。
补充行为检查:
```text
snippets ['DatabaseOption', 'Framework', 'Language', 'SkeletonFeature']
project parents ['core.ProjectIndexPage']
article parents ['core.ArticleIndexPage']
can_create_project_under_root False
can_create_article_under_root False
can_create_scenario_under_root False
no_m2m PASS_NO_ERROR
language_only PASS_NO_ERROR
scenario_only PASS_NO_ERROR
```
## 是否允许进入 Phase 2
不允许。
原因:
- T-104 仍处于 BLOCKED,依赖未满足。
- T-102 仍有必填多对多校验缺口。
建议下一步:
1. 修复 `SkeletonProjectPage` 的 `scenarios` / `languages` 至少 1 个校验。
2. 修正 T-102 / T-103 测试的页面树创建方式。
3. 更新 `AGENTS.md` 当前阶段和下一步任务。
4. 等待用户提供人工确认的种子内容后,再继续 T-104。