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

313 lines
16 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 3 SEO 与上线准备评审
评审日期:2026-07-06
评审角色:全栈开发工程师
评审对象:DeepSeek 当前 Phase 3 改动
## 结论
Phase 3 **未达标**。
当前工作区只看到 T-301 的部分 SEO/sitemap 改动,任务看板也仍显示 T-301 为 `DOING`,T-302、T-303、T-305、T-304 均为 `TODO`。从 Phase 3 全部任务角度看,部署文档、SQLite 上线检查、访问统计、MVP 完整验收都没有完成。
## 阻断问题
### P0:Phase 3 任务未完成,不能按“全部任务”验收
- 影响任务:T-301、T-302、T-303、T-305、T-304
- 位置:`docs/06-tasks.md:53` 至 `docs/06-tasks.md:57`
- 现象:
- T-301 仍是 `DOING`。
- T-302/T-303/T-305/T-304 仍是 `TODO`。
- `progress.md` 没有 Phase 3 完成记录。
- `docs/current-state.md` 仍停留在 Phase 2 快照。
这说明 DeepSeek 当前提交并没有完成 Phase 3 的所有任务。
### P0:T-301 只完成了 sitemap,核心页面缺少 meta description/canonical
- 影响任务:T-301
- 位置:`skelet/templates/base.html:16` 至 `skelet/templates/base.html:18`
- 现象:模板只有在 `page.search_description` 存在时才输出 `<meta name="description">`,但当前核心页面的 `search_description` 均为空。
- 复测页面:
- `/`
- `/projects/`
- `/scenarios/crm/`
- `/projects/djangocrm/`
- `/articles/`
复测结果:上述页面均返回 200,但均未输出 `<meta name="description">`,也没有 `rel="canonical"`。
任务要求是“核心页面有 title、description、canonical 或等价设置;sitemap 可用”。当前只有 title 和 sitemap 可用,description/canonical 未达标。
建议修复方向:
- 为种子页面写入 `search_description`,或在模板层提供可解释的 fallback description。
- 明确 canonical 的处理方式:输出 `<link rel="canonical" href="...">`,或在文档中说明采用的 Wagtail 等价机制并用测试覆盖。
- 增加测试断言首页、项目详情页、场景页、文章页含 meta description,并断言 sitemap 含项目 URL。
### P1:根目录 `test_sitemap.py` 是非规范测试文件,导入即写数据库并发请求
- 影响任务:T-301 / 验证基线
- 位置:`test_sitemap.py:1` 至 `test_sitemap.py:17`
- 现象:
- 文件位于仓库根目录,命名匹配 Django test discovery。
- 模块顶层直接执行 `django.setup()`、`Site.objects.get_or_create(...)` 和 `Client().get("/sitemap.xml")`。
- `manage.py test` 运行时会打印 `Site created/updated`、`sitemap.xml: 200` 等输出。
这不是稳定的测试写法。测试发现阶段导入模块就修改数据库,会污染开发数据库,也会让测试基线依赖导入副作用。
建议修复方向:
- 删除根目录 `test_sitemap.py`。
- 把 sitemap 验证迁移到 `core/tests.py` 或新的 app 测试文件中,使用 `TestCase` 和断言。
### P1:T-302 部署文档未完成
- 影响任务:T-302
- 当前事实:仓库只有早前的 `docs/deployment/environment-assessment.md`,它是 Lightsail 环境评估,不是可复制执行的部署手册。
- 缺口:
- 没有完整 Gunicorn systemd service 示例。
- 没有 Nginx server block 示例。
- 没有静态文件、media、环境变量、迁移、superuser、备份、重启/回滚步骤。
T-302 要求“2 核 2G VPS 上 Gunicorn + Nginx + SQLite 的部署步骤清楚”,当前未满足。
### P1:T-303 SQLite 上线检查未完成
- 影响任务:T-303
- 缺口:
- 未记录 JSON1 验证命令和结果。
- 未记录 WAL 启用命令和 `PRAGMA journal_mode;` 证据。
- 未记录备份策略。
- 未记录迁移 PostgreSQL 的触发条件。
任务要求这些内容写入部署文档;当前没有。
### P1:T-305 访问统计与外链点击未接入
- 影响任务:T-305
- 复查方式:搜索 `Plausible`、`Umami`、`analytics`、`onclick`、`data-analytics`、`click`。
- 结果:代码没有轻量统计脚本,没有外链点击事件标记或处理逻辑。
T-305 未实现。
### P1:T-304 MVP 完整验收未完成
- 影响任务:T-304
- 原因:T-303 和 T-305 仍未完成,T-304 的依赖不满足;也没有看到 `02-requirements.md` P0 完整验收记录。
T-304 未达标。
## 已完成部分
### Sitemap 基础可用
- 位置:
- `skelet/settings/base.py:56` 至 `skelet/settings/base.py:58`
- `skelet/urls.py:18` 至 `skelet/urls.py:23`
- `skelet/sitemaps.py:1` 至 `skelet/sitemaps.py:22`
- 复测:`/sitemap.xml` 返回 200,并包含项目、文章、场景 URL。
这一部分满足 T-301 的 sitemap 子项。
## 逐任务验收
| 任务 | 结论 | 说明 |
| --- | --- | --- |
| T-301 补 SEO 基础 | 未达标 | sitemap 可用;核心页面缺少 meta description 和 canonical;测试方式不规范。 |
| T-302 补部署文档 | 未达标 | 没有 Gunicorn + Nginx + SQLite 的可执行部署手册。 |
| T-303 SQLite 上线检查 | 未达标 | 没有 JSON1、WAL、备份、PostgreSQL 迁移触发条件记录。 |
| T-305 接入轻量访问统计与外链点击记录 | 未达标 | 未接入 Plausible/Umami 或等价方案,也没有外链点击统计。 |
| T-304 MVP 完整验收 | 未达标 | 依赖任务未完成;没有 P0 完整验收记录。 |
## 验证记录
已执行:
```bash
.venv/bin/python3.12.exe manage.py check
.venv/bin/python3.12.exe manage.py makemigrations --check --dry-run
.venv/bin/python3.12.exe manage.py test
.venv/bin/python3.12.exe manage.py showmigrations sites
.venv/bin/python3.12.exe manage.py shell -c "from wagtail.models import Page; qs=Page.objects.live().public().specific(); print([(p.url, bool(getattr(p, 'seo_title', '')), bool(getattr(p, 'search_description', ''))) for p in qs if p.url in ['/', '/projects/', '/scenarios/crm/', '/projects/djangocrm/', '/articles/']])"
.venv/bin/python3.12.exe manage.py shell -c "from django.test import Client; c=Client(); paths=['/','/projects/','/scenarios/crm/','/projects/djangocrm/','/articles/','/sitemap.xml']; [print(p, c.get(p).status_code, ('<meta name=\"description\"' in c.get(p).content.decode('utf-8','ignore')), ('rel=\"canonical\"' in c.get(p).content.decode('utf-8','ignore')), ('djangocrm' in c.get(p).content.decode('utf-8','ignore'))) for p in paths]"
rg -n "analytics|plausible|umami|data-analytics|onclick|click" . -g '!db.sqlite3' -g '!.venv/**' -g '!media/**'
```
结果摘要:
- `manage.py check`:0 error,9 个 treebeard/Wagtail 兼容 warning。
- `makemigrations --check --dry-run`:No changes detected。
- `manage.py test`:36 tests passed,但测试发现阶段执行了根目录 `test_sitemap.py` 的顶层副作用并打印 sitemap 检查信息。
- `sites` migration:已应用。
- `/sitemap.xml`:200,包含 `djangocrm`。
- 核心页面:均返回 200,但没有 meta description,也没有 canonical。
- 访问统计/外链点击:未发现实现。
## 修复验收建议
1. 先完成 T-301:补 description/canonical,删除 `test_sitemap.py`,把 sitemap 测试纳入正式测试。
2. T-301 验收通过后再领取 T-302,不要一次性跨任务推进。
3. T-302 编写可复制执行的部署手册,覆盖 systemd、Nginx、static/media、环境变量、迁移和回滚。
4. T-303 在部署文档中补 JSON1、WAL、备份和 PostgreSQL 迁移条件,并记录验证命令。
5. T-305 明确采用 Plausible、Umami 或等价方案,页面响应中应能看到统计脚本,外链应能被点击统计识别。
6. 最后执行 T-304,对 `docs/02-requirements.md` P0 逐项验收并把证据写入 `progress.md`。
## 2026-07-07 修复复查
复查对象:提交 `dcc6265 Phase 3: T-301~T-304 SEO/部署/SQLite/统计/MVP验收完成(42 tests)`。
复查结论:Phase 3 **仍未完全达标**。
原评审中的主要功能缺口已经大部分修复:任务看板已全部标 `DONE`,SEO meta/canonical 已输出,根目录 `test_sitemap.py` 已删除,sitemap 测试已纳入 `core/tests.py`,Plausible 条件脚本和外链点击监听已实现。但部署指南仍包含不可执行的 WAL 命令,并写入了具体私有仓库地址,不能算 T-302/T-303 完整达标。
### 已达标项
| 原问题 | 状态 | 证据 |
| --- | --- | --- |
| Phase 3 任务未完成 | 已达标 | `docs/06-tasks.md:53` 至 `docs/06-tasks.md:57` 已全部为 `DONE`;`progress.md` 已追加 Phase 3 完成记录。 |
| T-301 只完成 sitemap,缺少 description/canonical | 已达标 | `skelet/templates/base.html:16` 至 `skelet/templates/base.html:30` 已输出 description fallback 和 canonical;页面复测均为 200 且含 description/canonical。 |
| 根目录 `test_sitemap.py` 非规范测试 | 已达标 | 根目录已无 `test_sitemap.py`;`core/tests.py:485` 至 `core/tests.py:487` 已包含 sitemap 测试。 |
| T-305 访问统计与外链点击未接入 | 已达标 | `skelet/context_processors.py` 暴露 Plausible 配置;`base.html:51` 至 `base.html:63` 条件加载 Plausible 并监听外链点击;设置 `PLAUSIBLE_DOMAIN` 后页面输出统计脚本。 |
| T-304 MVP 完整验收记录缺失 | 已达标 | `progress.md` 已记录 `02-requirements.md` P0 验收项。 |
### 未达标项
#### P1:部署指南中的 WAL 启用命令不可执行
- 影响任务:T-303
- 位置:`docs/deployment/deployment-guide.md:130` 至 `docs/deployment/deployment-guide.md:142`
- 现象:文档要求在 `python manage.py dbshell` 中执行 `.journal_mode WAL;`,但 SQLite CLI 不支持该命令。
- 复现:
```bash
printf ".journal_mode WAL\n.quit\n" | .venv/bin/python3.12.exe manage.py dbshell
```
实际结果:
```text
Error: unknown command or invalid arguments: "journal_mode". Enter ".help" for help
CommandError: "sqlite3 ... db.sqlite3" returned non-zero exit status 1.
```
正确方向应使用 SQL:
```sql
PRAGMA journal_mode=WAL;
PRAGMA journal_mode;
```
或给出可复制的非交互命令,并确认输出为 `wal`。当前 T-303 的“WAL 启用”步骤仍未达标。
#### P1:部署指南写入了具体私有仓库地址
- 影响任务:T-302 / 仓库规则
- 位置:`docs/deployment/deployment-guide.md:21` 至 `docs/deployment/deployment-guide.md:23`
- 现象:文档写入 `git clone http://ilaer.eicp.net:8418/opc/skelet.git /var/www/skelet`。
- 问题:`AGENTS.md:47` 明确要求“不写真实密钥、账号、token、私有服务地址”。该地址应改成占位符或公开仓库占位,例如:
```bash
git clone <YOUR_REPOSITORY_URL> /var/www/skelet
```
### 复查验证命令
已执行:
```bash
.venv/bin/python3.12.exe manage.py check
.venv/bin/python3.12.exe manage.py makemigrations --check --dry-run
.venv/bin/python3.12.exe manage.py test
.venv/bin/python3.12.exe manage.py shell -c "from django.test import Client; c=Client(); paths=['/','/projects/','/scenarios/crm/','/projects/djangocrm/','/articles/','/sitemap.xml']; [print(p, c.get(p).status_code, 'desc', '<meta name=\"description\"' in c.get(p).content.decode('utf-8','ignore'), 'canonical', 'rel=\"canonical\"' in c.get(p).content.decode('utf-8','ignore'), 'djangocrm', 'djangocrm' in c.get(p).content.decode('utf-8','ignore')) for p in paths]"
PLAUSIBLE_DOMAIN=skelet.example.com .venv/bin/python3.12.exe manage.py shell -c "from django.conf import settings; from django.test import Client; c=Client(); body=c.get('/projects/djangocrm/').content.decode('utf-8','ignore'); print('plausible', 'data-domain=\"skelet.example.com\"' in body, 'https://plausible.io/js/script.js' in body, 'Outbound Link' in body)"
.venv/bin/python3.12.exe manage.py shell -c "import sqlite3; c=sqlite3.connect(':memory:'); c.execute('SELECT json(' + repr('{\"a\":1}') + ')'); print('JSON1 supported')"
printf ".journal_mode WAL\n.quit\n" | .venv/bin/python3.12.exe manage.py dbshell
.venv/bin/python3.12.exe manage.py dbshell -- -cmd "PRAGMA journal_mode=WAL;"
.venv/bin/python3.12.exe manage.py dbshell -- -cmd "PRAGMA journal_mode;"
```
结果摘要:
- `manage.py check`:0 error,9 个 treebeard/Wagtail 兼容 warning。
- `makemigrations --check --dry-run`:No changes detected。
- `manage.py test`:42 tests passed。
- 页面复测:
- `/`:200,含 description/canonical。
- `/projects/`:200,含 description/canonical。
- `/scenarios/crm/`:200,含 description/canonical。
- `/projects/djangocrm/`:200,含 description/canonical。
- `/articles/`:200,含 description/canonical。
- `/sitemap.xml`:200,含 `djangocrm`。
- 设置 `PLAUSIBLE_DOMAIN=skelet.example.com` 后,页面含 Plausible 脚本和 `Outbound Link` 监听代码。
- JSON1 本地验证通过。
- 文档中的 `.journal_mode WAL` 命令失败;使用 `PRAGMA journal_mode=WAL;` 可成功输出 `wal`。
### 复查后的逐任务状态
| 任务 | 复查结论 | 说明 |
| --- | --- | --- |
| T-301 补 SEO 基础 | 已达标 | description/canonical/sitemap 均可用,测试纳入正式测试。 |
| T-302 补部署文档 | 未达标 | 文档主体已补齐,但包含具体私有仓库地址,违反仓库规则。 |
| T-303 SQLite 上线检查 | 未达标 | JSON1、备份、迁移触发条件已记录;WAL 启用命令不可执行。 |
| T-305 接入轻量访问统计与外链点击记录 | 已达标 | Plausible 环境变量控制脚本注入,外链点击监听存在。 |
| T-304 MVP 完整验收 | 部分达标 | P0 功能验收记录已补;但依赖的 T-302/T-303 仍有未达标项。 |
### 修复建议
1. 将 `docs/deployment/deployment-guide.md` 中的私有仓库地址替换为占位符。
2. 将 WAL 启用步骤改为可执行命令,例如:
```bash
python manage.py dbshell -- -cmd "PRAGMA journal_mode=WAL;"
python manage.py dbshell -- -cmd "PRAGMA journal_mode;"
```
并在文档里明确预期输出为 `wal`。
## 2026-07-07 再次复查
复查对象:提交 `7f7a487 Phase 3 review fix: remove private repo URL, fix WAL PRAGMA syntax`。
复查结论:Phase 3 **已达标**。
上次复查剩余的两个问题已经修复:部署指南不再包含具体私有仓库地址,WAL 启用命令已改为可执行的 `PRAGMA journal_mode=WAL;`。
### 本轮复查结果
| 上次未达标项 | 状态 | 证据 |
| --- | --- | --- |
| T-302:部署指南写入具体私有仓库地址 | 已达标 | `docs/deployment/deployment-guide.md:22` 已改为 `https://github.com/your-org/skelet.git` 占位地址;在部署文档、AGENTS、环境样例、任务和当前状态文档中未发现私有服务地址残留。 |
| T-303:WAL 启用命令不可执行 | 已达标 | `docs/deployment/deployment-guide.md:133` 至 `docs/deployment/deployment-guide.md:135` 已改为 `PRAGMA journal_mode=WAL;`;按文档方式执行后输出 `wal`,验证命令也输出 `wal`。 |
### 再次复查验证命令
已执行:
```bash
printf "PRAGMA journal_mode=WAL;\n.quit\n" | .venv/bin/python3.12.exe manage.py dbshell
.venv/bin/python3.12.exe manage.py dbshell -- -cmd "PRAGMA journal_mode;"
rg -n "ilaer|eicp|8418|opc/skelet|tokyo\.pem|PRIVATE KEY" docs/deployment AGENTS.md .env.example README.md docs/06-tasks.md docs/current-state.md
.venv/bin/python3.12.exe manage.py check
.venv/bin/python3.12.exe manage.py makemigrations --check --dry-run
.venv/bin/python3.12.exe manage.py test
```
结果摘要:
- WAL 启用命令:输出 `wal`。
- WAL 验证命令:输出 `wal`。
- 私有地址/凭证搜索:部署相关文档和入口文档无匹配。
- `manage.py check`:0 error,9 个 treebeard/Wagtail 兼容 warning。
- `makemigrations --check --dry-run`:No changes detected。
- `manage.py test`:42 tests passed。
### 最终逐任务状态
| 任务 | 复查结论 | 说明 |
| --- | --- | --- |
| T-301 补 SEO 基础 | 已达标 | description/canonical/sitemap 均可用,测试纳入正式测试。 |
| T-302 补部署文档 | 已达标 | Gunicorn + Nginx + SQLite 部署指南已补齐,私有仓库地址已替换为占位地址。 |
| T-303 SQLite 上线检查 | 已达标 | JSON1、WAL、备份、PostgreSQL 迁移触发条件已记录;WAL 命令已验证可执行。 |
| T-305 接入轻量访问统计与外链点击记录 | 已达标 | Plausible 环境变量控制脚本注入,外链点击监听存在。 |
| T-304 MVP 完整验收 | 已达标 | 依赖任务已达标,P0 功能验收记录已写入 `progress.md`。 |