From c612afd217407c6cae945181d977898d3e8bca80 Mon Sep 17 00:00:00 2001 From: meijiali <你的邮箱@xxx.com> Date: Fri, 3 Jul 2026 11:12:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=90=8C=E6=AD=A5=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/CodexPrompts.md | 861 +++++++++++++++++++++++++++++++++++++++++ docs/TaskDependency.md | 371 ++++++++++++++++++ docs/Tasks.md | 74 ++-- 3 files changed, 1269 insertions(+), 37 deletions(-) create mode 100644 docs/CodexPrompts.md create mode 100644 docs/TaskDependency.md diff --git a/docs/CodexPrompts.md b/docs/CodexPrompts.md new file mode 100644 index 0000000..fcb3dd2 --- /dev/null +++ b/docs/CodexPrompts.md @@ -0,0 +1,861 @@ +# CodexPrompts.md:T01-T23 最小发送单元 + +## 使用说明 + +本文为每个 P0 Task 提供可复制发送给 Codex 的最小任务指令。 + +依据文件: + +- `AGENTS.md`(当前仓库未发现 `docs/AGENTS.md`,规则文件位于仓库根目录) +- `docs/Tasks.md` +- `docs/TaskDependency.md` +- `docs/TDD.md` + +全局执行口径: + +- 严格 TDD:先写失败测试,再写最小实现,再重构。 +- 不使用真实 TikHub / AI API;所有外部依赖必须 mock。 +- 后台任务使用 `ThreadPoolExecutor(max_workers=1)` 和同步 `httpx.Client`。 +- T13 固定 `AI_BATCH_SIZE=20`,不实现 batch size 减半。 +- 报告总结失败默认文案统一为:`总结生成失败,请查看上方统计数据。` +- 当前处于初始单人开发和流程练习阶段,默认一次只发送一个 Task,不启用并行。 +- 每个 Task 使用一个 `feat/tXX-short-description` 分支;完成验证后优先创建一个 focused commit。 +- 不创建 PR,除非用户明确要求。 +- 若未来启用并行,涉及 `docs/Tasks.md` 勾选项时由主协调者统一勾选,避免文档冲突。 + +## 当前推荐执行顺序 + +```text +T01 -> 审查/验证/commit +T02 -> 审查/验证/commit +T03 -> 审查/验证/commit +... +T23 -> 最终验收 +``` + +当前阶段不要提前并行发送 T05/T06、T08/T09、T18/T19。等串行流程跑顺后,再由用户明确切换到并行模式。 + +## 未来并行发送参考 + +| 分组 | 任务 | 发送方式 | +|---|---|---| +| Group 1 | T01 -> T02 -> T03 -> T04 | 串行 | +| Group 2 | T05 + T06 | 可小心并行,需合并 `app/main.py` | +| Group 3 | T07 -> (T08 + T09) -> T10 -> T11 | T08/T09 可并行 | +| Group 4 | T12 -> T13 -> T14 -> T15 -> T16 | 基本串行 | +| Group 5 | T17 -> (T18 + T19 + T20 service 部分) -> T21 | T18/T19 可并行,T20 service 可并行 | +| Group 6 | T22 -> T23 | 串行;T22 可与页面收尾低冲突并行 | + +--- + +### T01 任务指令 + +## 任务 +完成 T01:初始化项目结构与依赖。 + +## 前置 +前置任务:无。 + +并行发送:不可并行。T01-T04 是基础骨架,必须串行。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T01 部分 +- `docs/TDD.md` §2、§3、§5.1 +- `docs/DevelopmentPlan.md` §2、§4 + +## 分支 +在分支 `feat/t01-project-skeleton` 上开发。 + +## 输出要求 +- 创建 FastAPI 单体项目基础目录:`app/`、`app/services/`、`app/platforms/`、`app/templates/`、`app/static/`、`tests/`。 +- 创建基础文件:`app/main.py`、`app/config.py`、`app/db.py`、`app/models.py`、`app/schemas.py`、依赖文件、`.env.example`。 +- 实现 `/health`,返回 `{ "status": "ok" }`。 +- 先写 `tests/unit/test_config.py` 和 `/health` 集成测试,再实现代码。 +- 运行并通过:`pytest tests/unit tests/integration -q`。 + +## 边界 +- 只做 T01,不实现任务 API、数据库模型细节或页面。 +- 不提交真实 key、token、cookie。 +- 若 `pyproject.toml` 与 `requirements.txt` 二选一,按现有仓库风格;若没有风格,优先 `pyproject.toml`。 + +--- + +### T02 任务指令 + +## 任务 +完成 T02:配置管理与环境变量。 + +## 前置 +前置任务:T01。 + +并行发送:不可并行。需等待 T01 项目骨架完成。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T02 部分 +- `docs/TDD.md` §3.2、§5.1 +- `docs/DevelopmentPlan.md` §2.1、§12.1 + +## 分支 +在分支 `feat/t02-config-env` 上开发。 + +## 输出要求 +- 修改 `app/config.py`,集中管理 TikHub、AI、数据库、HTTP 超时和任务配置。 +- 修改 `.env.example`,只保留变量名和示例空值,不包含真实 key。 +- 先写配置默认值和环境变量覆盖测试。 +- 覆盖 `AI_CONCURRENCY=2`,硬上限不超过 3;`AI_MAX_RETRIES=3`;`CRAWL_PAGE_INTERVAL_SECONDS` 默认 1.5 且可从环境变量读取。 +- 运行并通过:`pytest tests/unit/test_config.py -q`。 + +## 边界 +- 只做配置,不实现数据库模型、任务 API、外部 HTTP client。 +- 不引入超出计划的配置系统或服务发现。 + +--- + +### T03 任务指令 + +## 任务 +完成 T03:数据库初始化与模型。 + +## 前置 +前置任务:T01、T02。 + +并行发送:不可并行。模型是后续所有任务的共享基础。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T03 部分 +- `docs/TDD.md` §3.2、§5.2、§5.3 +- `docs/DevelopmentPlan.md` §5 + +## 分支 +在分支 `feat/t03-database-models` 上开发。 + +## 输出要求 +- 修改 `app/db.py` 和 `app/models.py`。 +- 建立 SQLite + SQLAlchemy Base、engine、session。 +- 启用 `check_same_thread=False`、`timeout=10`、WAL。 +- 定义 `tasks`、`hotspots`、`content_items`、`comments`、`reports` 表。 +- 实现任务状态、AI 分析状态、进度字段、报告字段和建议索引。 +- 先写 `tests/unit/test_models.py`,断言所有表可创建、状态规则正确、`analysis_status=insufficient` 不改变 `Task.status`。 +- 运行并通过:`pytest tests/unit/test_models.py -q`。 + +## 边界 +- 只做模型和数据库初始化,不实现任务创建 API 或抓取流程。 +- 不引入 Alembic。 + +--- + +### T04 任务指令 + +## 任务 +完成 T04:任务创建 API 与单任务执行器。 + +## 前置 +前置任务:T03。 + +并行发送:不可并行。该任务会修改核心 API、schema 和 task service。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T04 部分 +- `docs/TDD.md` §6.1、§6.2 +- `docs/DevelopmentPlan.md` §2.1、§9.3 + +## 分支 +在分支 `feat/t04-task-api-executor` 上开发。 + +## 输出要求 +- 修改 `app/schemas.py`、`app/main.py`。 +- 创建 `app/services/task_service.py`。 +- 实现 `POST /api/tasks`、`GET /api/tasks`、`GET /api/tasks/{task_id}`。 +- 实现 `ThreadPoolExecutor(max_workers=1)`。 +- 当已有 `status=running` 任务时,`POST /api/tasks` 返回 HTTP 400,响应体为 `{"detail": "当前有正在运行的任务,请稍后再试"}`,且不创建新任务。 +- 先写 `tests/integration/test_task_creation.py` 和 `tests/unit/test_task_executor.py`。 +- 运行并通过:`pytest tests/integration/test_task_creation.py tests/unit/test_task_executor.py -q`。 + +## 边界 +- 只做任务创建、查询和执行器框架,不实现真实抓取、AI、报告。 +- 不新增任务状态,任务主状态仅 `running` / `success` / `failed`。 + +--- + +### T05 任务指令 + +## 任务 +完成 T05:僵尸任务恢复。 + +## 前置 +前置任务:T04。 + +当前发送方式:串行发送。未来可与 T06 小心并行,但会共同修改 `app/main.py`,需主协调者合并。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T05 部分 +- `docs/TDD.md` §6.3 +- `docs/DevelopmentPlan.md` §4.3 + +## 分支 +在分支 `feat/t05-task-recovery` 上开发。 + +## 输出要求 +- 修改 `app/services/task_service.py` 和 `app/main.py`。 +- 应用 lifespan 启动时,将遗留 `status=running` 的任务标记为 `failed`。 +- 写入 `error_stage=system`、`error_type=unexpected_restart`、`error_message=系统重启,任务被中断`。 +- 先写 `tests/integration/test_task_recovery.py`。 +- 运行并通过:`pytest tests/integration/test_task_recovery.py -q`。 + +## 边界 +- 只做启动恢复,不实现任务取消、补跑或复杂恢复。 +- 若与 T06 并行,不要重构无关 route 结构。 + +--- + +### T06 任务指令 + +## 任务 +完成 T06:首页 / 任务列表基础页面。 + +## 前置 +前置任务:T04。 + +当前发送方式:串行发送。未来可与 T05 小心并行,但会共同修改 `app/main.py`,需主协调者合并。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T06 部分 +- `docs/TDD.md` §12.1、§12.2、§12.4 +- `docs/UIDesign.md` + +## 分支 +在分支 `feat/t06-index-task-list` 上开发。 + +## 输出要求 +- 创建 `app/templates/base.html`、`app/templates/index.html`、`app/templates/partials/task_rows.html`。 +- 创建 `app/static/app.css`、`app/static/app.js`。 +- 修改 `app/main.py`,提供首页页面 route。 +- 首页包含任务表单、任务列表、手动刷新、默认规模预估 1250。 +- 任务创建成功后前端跳转至 `/tasks/{new_task_id}`。 +- 实现基础面包屑 block。 +- 先写 `tests/integration/test_routes.py` 和 `tests/unit/test_template_filters.py` 中相关测试。 +- 运行并通过:`pytest tests/integration/test_routes.py tests/unit/test_template_filters.py -q`。 + +## 边界 +- 只做首页和任务列表基础,不做任务详情、报告页、导出服务。 +- 状态文案不要散落硬编码,优先集中映射或 macro。 + +--- + +### T07 任务指令 + +## 任务 +完成 T07:外部 API 基础客户端与重试。 + +## 前置 +前置任务:T02。 + +并行发送:不可并行。T08/T09 依赖本任务完成。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T07 部分 +- `docs/TDD.md` §4.4、§6.2、§8.2、§13.3 +- `docs/DevelopmentPlan.md` §6.1 + +## 分支 +在分支 `feat/t07-api-client-retry` 上开发。 + +## 输出要求 +- 创建 `app/platforms/base.py` 和 `app/services/crawl_service.py`。 +- 封装同步 `httpx.Client` 调用、20s 超时、429 指数退避 1s -> 2s -> 4s、非 429 网络错误重试。 +- 超过重试次数后返回或抛出可被上层捕获的结构化错误,不泄露 API key。 +- 新增 `tests/fixtures/http_429_response.json` 或等价 fixture。 +- 在 `tests/conftest.py` 补充 429/httpx mock fixture。 +- 先写 `tests/unit/test_comment_pagination.py` 和 `tests/integration/test_failure_tolerance.py` 中相关测试。 +- 运行并通过:`pytest tests/unit/test_comment_pagination.py tests/integration/test_failure_tolerance.py -q`。 + +## 边界 +- 只做通用客户端和重试基础,不实现小红书/抖音字段映射。 +- 禁止使用 `httpx.AsyncClient`。 + +--- + +### T08 任务指令 + +## 任务 +完成 T08:小红书热点、笔记、评论字段映射。 + +## 前置 +前置任务:T07。 + +当前发送方式:串行发送。未来可与 T09 并行发送;若并行,绝对不要修改 `app/platforms/douyin.py`。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T08 部分 +- `docs/TDD.md` §4.1、§4.5、§7.1、§7.2 +- `docs/API-Spike-Xiaohongshu.md` +- `docs/DevelopmentPlan.md` §6.2 + +## 分支 +在分支 `feat/t08-xiaohongshu-mapping` 上开发。 + +## 输出要求 +- 创建 `app/platforms/xiaohongshu.py`。 +- 创建或补齐 fixtures:`xhs_hot_list.json`、`xhs_search_notes.json`、`xhs_comments_page_1.json`、`xhs_comments_page_2_empty.json`、`xhs_comments_missing_fields.json`。 +- 实现 `fetch_hotspots()`、`search_items_by_hotspot()`、`fetch_comments()` 的最小字段映射。 +- 热点读取 `data.data.items[]`,不误用外层 `data.data.title`。 +- 笔记优先选择 `comments_count > 0`,不足时补充 `comments_count = 0`。 +- 评论 ID 优先 `comment_id`,回退 `id`;保存 raw_data。 +- 字段缺失不导致整批任务崩溃。 +- 先写并通过:`pytest tests/unit/test_xiaohongshu_mapping.py -q`。 + +## 边界 +- 只做小红书字段映射和最小抓取链路,不做分页通用停止条件和去重。 +- 不发起真实 TikHub 请求。 + +--- + +### T09 任务指令 + +## 任务 +完成 T09:抖音热点、视频、评论字段映射。 + +## 前置 +前置任务:T07。 + +当前发送方式:串行发送。未来可与 T08 并行发送;若并行,绝对不要修改 `app/platforms/xiaohongshu.py`。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T09 部分 +- `docs/TDD.md` §4.2、§4.5、§7.4、§7.5 +- `docs/API-Spike-Douyin.md` +- `docs/DevelopmentPlan.md` §6.3 + +## 分支 +在分支 `feat/t09-douyin-mapping` 上开发。 + +## 输出要求 +- 创建 `app/platforms/douyin.py`。 +- 创建或补齐 fixtures:`douyin_hot_list.json`、`douyin_search_videos.json`、`douyin_comments_page_1.json`、`douyin_comments_missing_fields.json`。 +- 实现 `fetch_hotspots()`、`search_items_by_hotspot()`、`fetch_comments()` 的最小字段映射。 +- 热点映射 `query_id`、`title`、`rank`、`hot_score`。 +- 视频映射 `aweme_info.aweme_id`、`desc`、`author`、`statistics`。 +- 评论 ID 优先 `comment_id`,回退 `cid`;保存 raw_data。 +- 字段缺失不导致整批任务崩溃。 +- 先写并通过:`pytest tests/unit/test_douyin_mapping.py -q`。 + +## 边界 +- 只做抖音字段映射和最小抓取链路,不做分页通用停止条件和去重。 +- 不发起真实 TikHub 请求。 + +--- + +### T10 任务指令 + +## 任务 +完成 T10:评论分页、间隔与去重。 + +## 前置 +前置任务:T08、T09、T02。 + +并行发送:不可并行。T10 会同时修改两个平台 adapter 和 `crawl_service.py`。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T10 部分 +- `docs/TDD.md` §8.1、§8.2、§8.3 +- `docs/DevelopmentPlan.md` §6.4 + +## 分支 +在分支 `feat/t10-comment-pagination` 上开发。 + +## 输出要求 +- 修改 `app/platforms/xiaohongshu.py`、`app/platforms/douyin.py`、`app/services/crawl_service.py`。 +- 实现分页停止条件:达到评论数上限、空列表、最大 5 页、无下一页游标、连续失败超过重试次数。 +- 实现小红书 cursor / index 推进;抖音 cursor 推进。 +- 每次分页请求之间使用 1-2 秒基础间隔,默认读取 `CRAWL_PAGE_INTERVAL_SECONDS=1.5`。 +- 实现同一任务同一内容条目同一评论 ID 去重。 +- 先写并通过:`pytest tests/unit/test_comment_pagination.py -q`。 + +## 边界 +- 只做评论分页、间隔、去重,不做任务主流程集成。 +- 不改变 T08/T09 已验证的字段映射语义。 + +--- + +### T11 任务指令 + +## 任务 +完成 T11:抓取任务主流程集成。 + +## 前置 +前置任务:T04、T07、T08、T09、T10。 + +并行发送:不可并行。该任务集中修改任务主流程。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T11 部分 +- `docs/TDD.md` §13.1、§13.2、§13.3、§13.4、§13.5 +- `docs/DevelopmentPlan.md` §4.3、§13 + +## 分支 +在分支 `feat/t11-crawl-task-flow` 上开发。 + +## 输出要求 +- 修改 `app/services/task_service.py` 和 `app/services/crawl_service.py`。 +- 串起热点、内容条目、评论抓取并入库。 +- 更新 `processed_items_count`、`successful_items_count`、`failed_items_count`。 +- 每处理完一个内容条目立即 `session.commit()`。 +- 单个内容条目失败不阻断整批;热点接口失败导致任务 failed。 +- 无任何内容条目成功时任务 failed;至少一个内容条目成功时任务 success。 +- 覆盖跨热点重复 `source_item_id` 保留、同一热点重复去重。 +- 先写并通过:`pytest tests/integration/test_task_flow_xiaohongshu.py tests/integration/test_task_flow_douyin.py tests/integration/test_failure_tolerance.py -q`。 + +## 边界 +- 只做抓取主流程,不接入 AI 分析和报告生成。 +- 不引入多 worker 或异步任务系统。 + +--- + +### T12 任务指令 + +## 任务 +完成 T12:AI Prompt 与结构化输出校验。 + +## 前置 +前置任务:T03、T02。 + +当前发送方式:串行发送。不建议与 T13 并行;未来最多仅并行准备 T14 报告统计测试数据,但不要实现 T14。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T12 部分 +- `docs/TDD.md` §4.3、§4.6、§9.1、§9.2 +- `docs/DevelopmentPlan.md` §7.1、§7.2 + +## 分支 +在分支 `feat/t12-ai-schema` 上开发。 + +## 输出要求 +- 创建 `app/services/ai_service.py`。 +- 创建 `app/prompts/comment_analysis.txt`。 +- 创建或补齐 fixtures:`ai_comments_success.json`、`ai_comments_invalid_json.txt`、`ai_comments_all_sentiments.json`。 +- 实现 prompt 构造,输入包含 `comment_id` 和截断至 150 字的 `content`。 +- AI 输出必须是 JSON Array,并用 Pydantic/schema 校验。 +- 校验 sentiment 枚举、labels 最多 3 个、comment_id 必须匹配输入。 +- 单条失败标记 `ai_analysis_status=failed`。 +- 先写并通过:`pytest tests/unit/test_ai_schema.py -q`。 + +## 边界 +- 只做 prompt 和 schema 校验,不做 AI 重试并发和任务流程接入。 +- 不调用真实 AI 服务。 + +--- + +### T13 任务指令 + +## 任务 +完成 T13:AI 重试、成功率统计。 + +## 前置 +前置任务:T12、T04。 + +并行发送:不可并行。不要与 T16 同时修改 `task_service.py`。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T13 部分 +- `docs/TDD.md` §9.3、§9.4、§9.5 +- `docs/TaskDependency.md` §2.1 +- `docs/DevelopmentPlan.md` §7.3、§7.4(若与 Tasks 冲突,以本指令和 Tasks 为准) + +## 分支 +在分支 `feat/t13-ai-retry-quality` 上开发。 + +## 输出要求 +- 修改 `app/services/ai_service.py` 和必要的 `app/services/task_service.py` 质量状态逻辑。 +- 固定 batch size 为 20,不做动态缩减,不实现 batch size 减半。 +- 整批 JSON 解析失败时整批重试,最多 3 次。 +- 第 3 次仍失败时,该批次全部评论标记 `ai_analysis_status=failed`,不阻断其他批次。 +- 重试间隔符合 1s -> 2s -> 4s。 +- 同一任务最多 2 个 AI 批量请求并发;同一内容条目多批评论串行。 +- 实现 `analysis_success_rate` 和 `analysis_status`:>= 0.8 为 `normal`,< 0.8 为 `insufficient`,不改变任务主状态。 +- 先写并通过:`pytest tests/unit/test_ai_schema.py -q`。 + +## 边界 +- 不接入完整任务流程;T16 负责集成。 +- 不使用 `httpx.AsyncClient`。 + +--- + +### T14 任务指令 + +## 任务 +完成 T14:内容条目级报告生成。 + +## 前置 +前置任务:T12、T13、T03。 + +并行发送:不建议与 T15 并行。T14/T15 都修改 `report_service.py`。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T14 部分 +- `docs/TDD.md` §10.1、§10.2、§10.3、§10.5 +- `docs/TaskDependency.md` §2.2 +- `docs/DevelopmentPlan.md` §8.1、§8.3 + +## 分支 +在分支 `feat/t14-item-report` 上开发。 + +## 输出要求 +- 创建 `app/services/report_service.py`。 +- 创建 `app/prompts/report_summary.txt`。 +- 实现内容条目级报告生成,保存 `metrics_json`、`typical_comments_json`、`summary`、`markdown_content`。 +- 统计情绪、Top 5 标签、典型评论;典型评论优先点赞数,缺失时按抓取顺序。 +- 总结 AI 输入包含统计摘要和典型评论文本,每条评论截断至 150 字。 +- 总结 AI 使用纯文本输出,不使用 JSON Schema。 +- 内容条目总结超过 200 字时截断。 +- 总结 AI 超时或失败时使用默认文案:`总结生成失败,请查看上方统计数据。` +- 先写并通过:`pytest tests/unit/test_report_stats.py -q`。 + +## 边界 +- 只做内容条目级报告,不做热点级报告和任务流程接入。 +- 不在页面 route 中临时计算统计。 + +--- + +### T15 任务指令 + +## 任务 +完成 T15:热点级报告生成。 + +## 前置 +前置任务:T14。 + +并行发送:不建议并行。T15 扩展 T14 的同一 `report_service.py`。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T15 部分 +- `docs/TDD.md` §10.1、§10.2、§10.4、§10.5 +- `docs/TaskDependency.md` §2.2 +- `docs/DevelopmentPlan.md` §8.2、§8.3 + +## 分支 +在分支 `feat/t15-hotspot-report` 上开发。 + +## 输出要求 +- 修改 `app/services/report_service.py`。 +- 实现热点级报告生成,聚合热点下所有内容条目。 +- 统计内容条目数量、评论样本数、情绪分布、Top 5 标签、典型评论。 +- 生成热点级 Markdown,并保存到 `reports`。 +- 任务完成后报告生成顺序为:先内容条目报告,再热点报告。 +- 热点总结超过 300 字时截断。 +- 总结 AI 超时或失败时使用默认文案:`总结生成失败,请查看上方统计数据。` +- 先写并通过:`pytest tests/unit/test_report_stats.py -q`。 + +## 边界 +- 只做热点级报告,不接入任务主流程。 +- 页面展示和导出必须后续读取预生成报告,不在 route 中即时计算。 + +--- + +### T16 任务指令 + +## 任务 +完成 T16:AI + 报告集成到任务流程。 + +## 前置 +前置任务:T11、T13、T14、T15。 + +并行发送:不可并行。该任务是抓取、AI、报告的主集成点。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T16 部分 +- `docs/TDD.md` §13.1、§13.2、§13.3、§9.5、§10 +- `docs/DevelopmentPlan.md` §4.3、§7、§8、§13 + +## 分支 +在分支 `feat/t16-ai-report-flow` 上开发。 + +## 输出要求 +- 修改 `app/services/task_service.py`、`app/services/ai_service.py`、`app/services/report_service.py`。 +- 在任务流程中调用 AI 分析和报告生成。 +- 任务完成后评论有 sentiment、labels,reports 已入库。 +- 写入 `analysis_success_rate` 和 `analysis_status`。 +- 每完成一批 AI 分析(20 条评论)后立即 `session.commit()`。 +- AI 单批失败不阻断其他批次。 +- 扩展并通过:`pytest tests/integration/test_task_flow_xiaohongshu.py tests/integration/test_task_flow_douyin.py tests/integration/test_failure_tolerance.py -q`。 + +## 边界 +- 不做页面、导出、Docker。 +- 不改变 T13 固定 batch size 策略。 + +--- + +### T17 任务指令 + +## 任务 +完成 T17:任务详情页。 + +## 前置 +前置任务:T06、T11;建议 T16 完成后再做以展示 AI/报告状态。 + +并行发送:T17 是 T18/T19 的前置,不建议并行。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T17 部分 +- `docs/TDD.md` §12.1、§12.4 +- `docs/UIDesign.md` + +## 分支 +在分支 `feat/t17-task-detail-page` 上开发。 + +## 输出要求 +- 创建 `app/templates/tasks/detail.html`。 +- 修改 `app/main.py` 增加任务详情页 route。 +- 展示任务概览:任务 ID、平台、创建时间、耗时、状态、AI 分析状态、进度、错误信息。 +- 实现热点手风琴列表,默认展开 rank=1。 +- 内容条目失败时展示失败原因。 +- 任务 running 且热点为空时展示 Spinner。 +- 面包屑:首页 -> 任务 `#{task_id}`,首页链接指向 `/`。 +- 热点报告入口在 T18 前仅需 href 非空。 +- 先写并通过:`pytest tests/integration/test_routes.py tests/unit/test_template_filters.py -q`。 + +## 边界 +- 只做任务详情页,不实现热点报告页和内容条目详情页。 +- 不在模板中做业务统计计算。 + +--- + +### T18 任务指令 + +## 任务 +完成 T18:热点级报告页。 + +## 前置 +前置任务:T15、T17。 + +当前发送方式:串行发送。未来可与 T19 并行,但二者都会修改 `app/main.py` 和 `tests/integration/test_routes.py`,需主协调者合并。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T18 部分 +- `docs/TDD.md` §12.1、§12.4、§11.3、§11.4 +- `docs/UIDesign.md` + +## 分支 +在分支 `feat/t18-hotspot-report-page` 上开发。 + +## 输出要求 +- 创建 `app/templates/hotspots/report.html`。 +- 修改 `app/main.py` 增加热点报告页 route。 +- 页面读取预生成热点报告。 +- 展示热点基础信息、内容条目数量、评论样本数、情绪分布、Top 5 标签、典型评论、AI 总结和分析不足 Alert。 +- 添加 Markdown 导出按钮和热点下全部评论 CSV 导出按钮。 +- 报告缺失时显示友好状态,不返回 HTTP 500。 +- 实现面包屑:首页 -> 任务 -> 热点 -> 汇总报告。 +- 先写并通过:`pytest tests/integration/test_routes.py -q`。 + +## 边界 +- 只做热点报告页,不实现内容条目详情页。 +- 页面不得即时计算报告统计,必须读取 reports 预生成数据。 + +--- + +### T19 任务指令 + +## 任务 +完成 T19:内容条目详情页与评论明细。 + +## 前置 +前置任务:T14、T17。 + +当前发送方式:串行发送。未来可与 T18 并行,但二者都会修改 `app/main.py` 和 `tests/integration/test_routes.py`,需主协调者合并。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T19 部分 +- `docs/TDD.md` §12.3、§12.4、§12.5 +- `docs/UIDesign.md` + +## 分支 +在分支 `feat/t19-item-detail-page` 上开发。 + +## 输出要求 +- 创建 `app/templates/items/detail.html`。 +- 修改 `app/main.py` 增加内容条目详情页 route。 +- 展示内容条目基础信息、原始内容链接、内容条目级报告。 +- 评论明细最多展示 100 条。 +- 评论排序:点赞数降序;点赞数相同或缺失时评论时间降序。 +- labels JSON Array 渲染为多个标签块。 +- 评论为空时展示空状态。 +- 实现面包屑:首页 -> 任务 -> 热点 -> 内容条目。 +- 先写并通过:`pytest tests/integration/test_routes.py tests/unit/test_template_filters.py -q`。 + +## 边界 +- P1 原始 JSON `
` 调试入口不是 P0,除非用户明确要求,不要实现。 +- 不实现热点报告页或导出服务。 + +--- + +### T20 任务指令 + +## 任务 +完成 T20:导出服务。 + +## 前置 +前置任务:T14、T15、T18、T19。服务层可在 T14/T15 后先做,但 route 和按钮状态需等页面完成。 + +当前发送方式:串行发送。未来 T20 service/unit-test 部分可与 T18/T19 页面并行;完整 T20 不建议与 T21 并行。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T20 部分 +- `docs/TDD.md` §11、§12.5 +- `docs/DevelopmentPlan.md` §11 + +## 分支 +在分支 `feat/t20-export-service` 上开发。 + +## 输出要求 +- 创建 `app/services/export_service.py`。 +- 修改 `app/main.py` 增加导出 routes: + - `GET /api/export/items/{item_id}/comments.csv` + - `GET /api/export/hotspots/{hotspot_id}/comments.csv` + - `GET /api/export/items/{item_id}.md` + - `GET /api/export/hotspots/{hotspot_id}.md` +- CSV 使用 `UTF-8-SIG`,字段符合 TDD §11.1。 +- labels JSON Array 导出为中文逗号拼接。 +- 防 CSV 公式注入:`=`、`+`、`-`、`@` 开头加单引号。 +- 评论内容中的换行符替换为空格。 +- 文件名安全处理符合 TDD §11.2。 +- Markdown 直接读取 `reports.markdown_content`。 +- 补充导出按钮 disabled 条件测试。 +- 先写并通过:`pytest tests/unit/test_export.py tests/integration/test_routes.py -q`。 + +## 边界 +- 不做 Excel 导出或 JSON 正式导出。 +- 不重新计算报告 Markdown。 + +--- + +### T21 任务指令 + +## 任务 +完成 T21:模板宏、过滤器与静态交互。 + +## 前置 +前置任务:T06、T17、T18、T19、T20。 + +并行发送:不建议并行。T21 是页面共享层收敛任务。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T21 部分 +- `docs/TDD.md` §12 +- `docs/UIDesign.md` + +## 分支 +在分支 `feat/t21-template-macros-js` 上开发。 + +## 输出要求 +- 创建 macro:`status_badge.html`、`sentiment_badge.html`、`label_tags.html`。 +- 注册 `from_json` Jinja2 filter。 +- 修改 `app/static/app.js` 和 `app/static/app.css`,实现表单范围校验、规模预估实时计算、导出 Blob 下载。 +- 严禁对外部平台内容使用 `|safe`。 +- 在 `base.html` 中定义 title block。 +- 各页面 title 符合 Tasks T21 规范。 +- 状态文案集中管理。 +- 先写并通过:`pytest tests/unit/test_template_filters.py tests/integration/test_routes.py -q`。 + +## 边界 +- 只做共享模板、filter、静态交互收敛,不新增页面功能。 +- 不实现 P1 自动轮询或进度条,除非用户明确要求。 + +--- + +### T22 任务指令 + +## 任务 +完成 T22:Docker Compose 与部署。 + +## 前置 +前置任务:T01、T02、T03;建议 T16/T21 后执行以便完整验收。 + +当前发送方式:串行发送。未来可与页面 polish 收尾低冲突并行,但会修改 `.env.example`,需避开 T02/T21 的同文件修改。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T22 部分 +- `docs/TDD.md` §15.1、§16.2 +- `docs/DevelopmentPlan.md` §12.2 + +## 分支 +在分支 `feat/t22-docker-compose` 上开发。 + +## 输出要求 +- 创建 `Dockerfile`。 +- 创建 `docker-compose.yml`,包含 app 服务和 `./data:/app/data` 数据卷。 +- 暴露 8000 端口。 +- 容器启动后可初始化数据库。 +- SQLite 写入 `./data/app.db`。 +- Dockerfile 使用非 root 用户 `appuser`。 +- 确认挂载卷目录对 `appuser` 可写。 +- 写测试或验证:容器内进程 `whoami` 不返回 root。 +- 运行并通过: + - `docker compose up --build` + - `curl -f http://localhost:8000/health` + +## 边界 +- 只做 Docker Compose 单服务部署。 +- 不引入 PostgreSQL、Redis、Celery、Nginx 或登录系统。 + +--- + +### T23 任务指令 + +## 任务 +完成 T23:最终测试与手工验收。 + +## 前置 +前置任务:T01-T22。 + +并行发送:不可并行。T23 是最终验收和文档收口任务。 + +请先读取: +- `AGENTS.md` +- `docs/Tasks.md` 中 T23 部分 +- `docs/TDD.md` §15.2、§16.1、§16.2 +- `docs/TaskDependency.md` +- `README.md`(如存在) + +## 分支 +在分支 `feat/t23-final-acceptance` 上开发。 + +## 输出要求 +- 运行并通过: + - `pytest tests/unit -q` + - `pytest tests/integration -q` + - `pytest tests/unit tests/integration --cov=app --cov-branch --cov-report=term-missing` +- 若覆盖率低于目标,补测试后再继续。 +- 运行 Docker 验收: + - `docker compose up --build` + - `curl -f http://localhost:8000/health` +- 按 T23 手工验收清单验证小红书和抖音默认任务流程。 +- 如项目已有 `README.md`,补充启动和验收说明。 +- 只有在对应任务真实完成且验证通过后,才更新 `docs/Tasks.md` 勾选项。 +- 输出最终验收报告:通过项、失败项、已知限制、已运行命令。 + +## 边界 +- 不新增 P1/P2 功能。 +- 不为了通过验收而删除关键测试或降低断言。 +- 不提交真实 API key 或用户私密数据。 diff --git a/docs/TaskDependency.md b/docs/TaskDependency.md new file mode 100644 index 0000000..5c38e3b --- /dev/null +++ b/docs/TaskDependency.md @@ -0,0 +1,371 @@ +# TaskDependency.md:任务依赖关系与执行方案 + +## 1. 文档依据 + +本分析依据: + +- `docs/Tasks.md` +- `docs/DevelopmentPlan.md` + +未发现 `docs/review-*.md` 文件。 + +保存位置确认:本文保存为 `docs/TaskDependency.md`。原因是它属于开发任务执行计划的补充文档,文件名能直接表达用途,且不覆盖现有 source-of-truth 文档。 + +## 2. 重要冲突与执行口径 + +### 2.0 当前执行模式:初始阶段先串行 + +当前项目处于初始单人开发和流程练习阶段。默认执行策略为: + +```text +一个 Task -> 一个分支 -> 完成并验证 -> 一个 focused commit -> 审查通过后再进入下一个 Task +``` + +暂不启用并行开发,暂不创建 PR,除非用户明确要求切换到并行或 PR 工作流。 + +分支命名沿用 `docs/CodexPrompts.md` 中的 `feat/tXX-short-description`。每个 Task +完成后,优先创建一个能用一句话说明的 commit;若 Task 很大,允许拆成多个有意义、 +可测试、可回滚的小 commit,但当前练习阶段优先保持“一 Task 一 commit”。 + +本文后续并行方案保留为未来提速参考,不是当前默认执行方式。 + +### 2.1 T13 AI batch 降级策略存在文档冲突 + +- `docs/Tasks.md` T13 明确要求:`batch size 固定为 20,不做动态缩减`,并写明 `不实现 batch size 减半逻辑`。 +- `docs/DevelopmentPlan.md` §7.3 与 §16 仍写有:第 3 次重试时 `batch_size` 减半。 + +执行建议:后续实现前必须由用户确认以哪个文档为准。若按 `AGENTS.md` 的 source-of-truth 顺序,`docs/Tasks.md` 在执行 sequencing 上更具体,且其变更日志明确说明 T13 已移除减半逻辑,因此本文的依赖和并行计划按 T13「固定 batch size、最多 3 次整批重试」建模,但不替代用户确认。 + +### 2.2 报告总结失败默认文案存在轻微差异 + +- `docs/Tasks.md` T14 要求默认文案为:`总结生成失败,请查看上方统计数据。` +- `docs/DevelopmentPlan.md` §8.1/§8.2 要求默认文案为:`总结生成失败,请查看详细数据` + +执行建议:实现 T14/T15 前需确认统一文案,避免测试和页面展示不一致。 + +## 3. 依赖关系图(文字版) + +### 3.1 主链路依赖 + +```text +T01 初始化项目结构与依赖 + -> T02 配置管理与环境变量 + -> T03 数据库初始化与模型 + -> T04 任务创建 API 与单任务执行器 + -> T05 僵尸任务恢复 + -> T06 首页 / 任务列表基础页面 + -> T07 外部 API 基础客户端与重试 + -> (T08 小红书字段映射 || T09 抖音字段映射) + -> T10 评论分页、间隔与去重 + -> T11 抓取任务主流程集成 + -> T12 AI Prompt 与结构化输出校验 + -> T13 AI 重试、成功率统计 + -> T14 内容条目级报告生成 + -> T15 热点级报告生成 + -> T16 AI + 报告集成到任务流程 + -> T17 任务详情页 + -> T18 热点级报告页 + -> T19 内容条目详情页与评论明细 + -> T20 导出服务 + -> T21 模板宏、过滤器与静态交互 + -> T22 Docker Compose 与部署 + -> T23 最终测试与手工验收 +``` + +### 3.2 平台抓取并行依赖 + +```text +T07 API 客户端与重试 + -> T08 小红书字段映射 --\ + -> T10 评论分页、间隔与去重 -> T11 抓取任务主流程集成 + -> T09 抖音字段映射 ----/ +``` + +### 3.3 页面与导出依赖 + +```text +T06 首页基础页面 + -> T17 任务详情页 + +T14 内容条目级报告生成 -> T19 内容条目详情页 +T15 热点级报告生成 -> T18 热点级报告页 +T15 热点级报告生成 -> T20 Markdown 导出 +T11 抓取任务集成 -> T20 CSV 导出 + +T17/T18/T19/T20 + -> T21 模板宏、过滤器与静态交互 +``` + +说明:T21 可在 T17-T20 之前先做 macro/filter 的底座,但它会修改多个页面共享文件。为了降低多人文件冲突,建议放到页面任务之后做统一收敛,或指定一个模板负责人先完成共享 macro,再串行接入页面。 + +### 3.4 P1 可选任务依赖 + +```text +P1-01 任务列表自动轮询 + depends on: T06, T21 的 app.js / partials 基础 + +P1-02 原始 JSON 调试入口 + depends on: T19 + +P1-03 基础进度条 + depends on: T04/T11 进度字段, T06/T17 页面 +``` + +## 4. 任务级前置依赖清单 + +| 任务 | 必须前置 | 主要原因 | +|---|---|---| +| T01 初始化项目结构与依赖 | 无 | 建立项目、依赖、测试和健康检查基础 | +| T02 配置管理与环境变量 | T01 | 修改 `app/config.py`、`.env.example` 和配置测试 | +| T03 数据库初始化与模型 | T01, T02 | 数据库 URL 与 SQLAlchemy 初始化依赖配置基础 | +| T04 任务创建 API 与单任务执行器 | T03 | 需要 `tasks` 表、schema、session 和 FastAPI 应用 | +| T05 僵尸任务恢复 | T04 | 依赖任务状态模型、task_service 和应用 lifespan | +| T06 首页 / 任务列表基础页面 | T04 | 页面创建任务和列表展示依赖任务 API | +| T07 外部 API 基础客户端与重试 | T02 | 依赖 TikHub base URL、API key、HTTP timeout/retry 配置 | +| T08 小红书字段映射 | T07 | 依赖通用同步 HTTP client 与错误抽象 | +| T09 抖音字段映射 | T07 | 依赖通用同步 HTTP client 与错误抽象 | +| T10 评论分页、间隔与去重 | T08, T09, T02 | 同时修改两平台分页推进,依赖分页间隔配置 | +| T11 抓取任务主流程集成 | T04, T07, T08, T09, T10 | 串起任务生命周期、平台抓取、入库和容错 | +| T12 AI Prompt 与结构化输出校验 | T03, T02 | 依赖 comments 模型字段、AI 配置和 prompt 目录 | +| T13 AI 重试、成功率统计 | T12, T04 | 依赖 AI schema 校验与 tasks 分析状态字段 | +| T14 内容条目级报告生成 | T12, T13, T03 | 依赖已分析评论、reports 表和报告 prompt | +| T15 热点级报告生成 | T14 | 聚合内容条目级统计,并扩展同一 report_service | +| T16 AI + 报告集成到任务流程 | T11, T13, T14, T15 | 将抓取、AI、报告接入完整任务流程 | +| T17 任务详情页 | T06, T11 | 需要任务进度、热点、内容条目和失败信息 | +| T18 热点级报告页 | T15, T17 | 需要预生成热点报告和任务详情入口 | +| T19 内容条目详情页与评论明细 | T14, T17 | 需要预生成 item 报告、评论 AI 字段和任务详情入口 | +| T20 导出服务 | T14, T15, T18, T19 | Markdown 读取 reports;CSV 读取评论;按钮状态依赖页面模板 | +| T21 模板宏、过滤器与静态交互 | T06, T17, T18, T19, T20 | 收敛各页面状态、情绪、标签、标题、导出交互 | +| T22 Docker Compose 与部署 | T01, T02, T03;建议 T16/T21 后 | 依赖应用可启动、配置齐全、数据库初始化可用;完整验收依赖主功能基本完成 | +| T23 最终测试与手工验收 | T01-T22 | MVP 闭环验收 | + +## 5. 可并行执行的任务 + +并行判断原则: + +1. 前置依赖已满足。 +2. 任务之间不修改同一核心文件。 +3. 若测试文件共享,如 `tests/integration/test_routes.py` 或 `tests/unit/test_report_stats.py`,并行时必须提前拆分测试文件或指定一个人负责合并。 + +### 5.1 强推荐并行 + +| 并行任务 | 前置条件 | 不冲突理由 | +|---|---|---| +| T08 小红书字段映射 + T09 抖音字段映射 | T07 完成 | 分别修改 `app/platforms/xiaohongshu.py` 与 `app/platforms/douyin.py`,测试和 fixtures 独立 | +| T20 导出服务的纯 service/unit-test 部分 + T18/T19 页面模板草稿 | T14, T15 完成 | `export_service.py` 和导出单元测试不触碰页面模板;路由与按钮接入需后续串行 | +| T22 Docker Compose + 页面 polish 收尾 | T01-T03 基础稳定,应用可启动 | Docker 文件与页面模板/CSS/JS 基本独立;`.env.example` 修改需避开 T02 | + +### 5.2 可并行但需要合并纪律 + +| 并行任务 | 前置条件 | 合并纪律 | +|---|---|---| +| T05 僵尸任务恢复 + T06 首页基础页面 | T04 完成 | 都会修改 `app/main.py`;T05 聚焦 lifespan/task_service,T06 聚焦模板路由,需一个人最终合并 main.py | +| T12 AI schema + T14 报告统计测试设计 | T03 完成 | T14 实现依赖 T12/T13,但报告统计测试数据和期望可先写;注意不提前假定 T13 冲突策略 | +| T17 任务详情页 + T20 导出服务测试设计 | T14/T15 基础模型稳定 | T20 的按钮 disabled 测试依赖页面模板,服务层 CSV/Markdown 测试可先行 | +| T18 热点报告页 + T19 内容条目详情页 | T17, T14, T15 完成 | 模板文件不同,但都改 `app/main.py` 和 `tests/integration/test_routes.py`,需路由合并约定 | +| T20 导出服务完整任务 + T21 macro/filter 预研 | T14, T15 完成 | T20 route/按钮和 T21 filter/static 会共享 `app/main.py`、模板和静态文件,需拆分边界 | +| P1-01 自动轮询 + P1-03 进度条 | P0 页面完成 | 都会修改 `index.html`、`task_rows.html`、`app.js`、`app.css`,建议同一前端负责人处理 | + +### 5.3 不建议并行 + +| 任务组合 | 原因 | +|---|---| +| T01/T02/T03/T04 | 都修改核心骨架、配置、模型、main.py,依赖强且文件重叠多 | +| T10 与 T08/T09 | T10 会修改两平台分页实现,容易覆盖字段映射阶段改动 | +| T11 与 T04/T10 | T11 集成任务流程依赖任务创建和分页完成,且会集中修改 `task_service.py`、`crawl_service.py` | +| T13 与 T16 | 都修改 AI 调用接入和 `task_service.py`,应先完成 T13 单元能力,再接入 T16 | +| T14 与 T15 | 都集中修改 `report_service.py` 和 `test_report_stats.py`,建议串行;多人时可先约定接口后由同一人合并 | +| T17/T18/T19/T21 同时落地 | 共享 `main.py`、`test_routes.py`、`test_template_filters.py`、`base.html` 和 CSS/JS,冲突概率高 | + +## 6. 推荐并行分组方案 + +### Group 0:文档冲突确认与执行口径冻结 + +| 内容 | 任务 | +|---|---| +| 目标 | 确认 T13 是否固定 batch size;确认报告总结失败默认文案 | +| 前置 | 无 | +| 输出 | 明确实现口径,可写入 `docs/Tasks.md` 或新 review 文档 | +| 文件冲突风险 | 低;若修改 docs,则只改相关文档 | + +### Group 1:项目基础串行启动 + +| 顺序 | 任务 | 说明 | +|---|---|---| +| 1 | T01 | 项目结构、依赖、`/health` | +| 2 | T02 | 配置和 `.env.example` | +| 3 | T03 | 数据库和模型 | +| 4 | T04 | 任务 API 和单 worker 执行器 | + +文件冲突风险: + +- 高度串行,不建议多人同时做。 +- 主要冲突文件:`app/main.py`、`app/config.py`、`app/db.py`、`app/models.py`、`app/schemas.py`、`tests/conftest.py`。 + +### Group 2:任务恢复与首页基础 + +| 可并行子组 | 任务 | 负责人边界 | +|---|---|---| +| 2A | T05 僵尸任务恢复 | `task_service.py` 恢复函数、lifespan 测试 | +| 2B | T06 首页 / 任务列表基础页面 | templates/static、首页 route、任务列表测试 | + +组内顺序: + +```text +T04 -> (T05 || T06) -> 合并 app/main.py 与路由测试 +``` + +文件冲突风险: + +- `app/main.py`:T05 注册 lifespan,T06 注册页面路由。 +- `tests/integration/test_routes.py` 与 `tests/integration/test_task_recovery.py` 应分文件,降低冲突。 +- `tests/unit/test_template_filters.py` 后续 T21 还会继续修改。 + +### Group 3:平台抓取并行 + +| 可并行子组 | 任务 | 负责人边界 | +|---|---|---| +| 3A | T07 外部 API 基础客户端与重试 | 先串行完成,作为平台公共依赖 | +| 3B | T08 小红书字段映射 | `xiaohongshu.py`、xhs fixtures、xhs mapping tests | +| 3C | T09 抖音字段映射 | `douyin.py`、douyin fixtures、douyin mapping tests | +| 3D | T10 评论分页、间隔与去重 | T08/T09 合并后串行完成 | +| 3E | T11 抓取任务主流程集成 | T10 后串行完成 | + +组内顺序: + +```text +T07 -> (T08 || T09) -> T10 -> T11 +``` + +文件冲突风险: + +- T08/T09 冲突低。 +- T10 会同时修改 `app/platforms/xiaohongshu.py`、`app/platforms/douyin.py`、`app/services/crawl_service.py`,必须等 T08/T09 合并。 +- T11 修改 `app/services/task_service.py` 与 `app/services/crawl_service.py`,不要和 T10 并行改同一文件。 + +### Group 4:AI 与报告 + +| 可并行子组 | 任务 | 负责人边界 | +|---|---|---| +| 4A | T12 AI Prompt 与结构化输出校验 | `ai_service.py` 初版、comment prompt、AI fixtures | +| 4B | T13 AI 重试、成功率统计 | T12 后串行扩展 `ai_service.py` 和 task analysis 字段 | +| 4C | T14 内容条目级报告生成 | T13 后实现 `report_service.py` 初版 | +| 4D | T15 热点级报告生成 | T14 后扩展同一 `report_service.py` | +| 4E | T16 AI + 报告集成到任务流程 | T11/T13/T14/T15 后串行接入 | + +组内顺序: + +```text +T12 -> T13 -> T14 -> T15 +T11 ----------------------\ + -> T16 +``` + +文件冲突风险: + +- T12/T13 都改 `app/services/ai_service.py` 和 `tests/unit/test_ai_schema.py`,不建议并行。 +- T14/T15 都改 `app/services/report_service.py` 和 `tests/unit/test_report_stats.py`,不建议并行。 +- T16 同时改 `task_service.py`、`ai_service.py`、`report_service.py` 和两平台集成测试,必须在前面服务稳定后做。 + +### Group 5:页面与导出 + +| 可并行子组 | 任务 | 负责人边界 | +|---|---|---| +| 5A | T17 任务详情页 | `tasks/detail.html`、任务详情 route | +| 5B | T18 热点级报告页 | `hotspots/report.html`、热点报告 route | +| 5C | T19 内容条目详情页 | `items/detail.html`、评论明细 route | +| 5D | T20 导出服务 | `export_service.py`、export routes、导出测试 | +| 5E | T21 模板宏、过滤器与静态交互 | 共享 macro/static/title/filter 收敛 | + +推荐顺序: + +```text +T16 -> T17 +T17 + T15 -> T18 +T17 + T14 -> T19 +T14 + T15 -> T20 +(T17/T18/T19/T20) -> T21 +``` + +可并行执行: + +- T18 与 T19 可并行,但需避免同时大改 `app/main.py`。 +- T20 服务层可与 T18/T19 页面并行;模板按钮状态接入建议等页面模板稳定后统一做。 +- T21 建议作为页面组最后的收敛任务,统一抽 macro、filter、title 和 JS 行为。 + +文件冲突风险: + +- `app/main.py`:T17/T18/T19/T20 都会添加路由。 +- `tests/integration/test_routes.py`:T17/T18/T19/T20 都会扩展。 +- `tests/unit/test_template_filters.py`:T17/T19/T20/T21 都可能修改。 +- `app/templates/base.html`、`app/static/app.js`、`app/static/app.css`:T06/T20/T21 共享。 + +### Group 6:部署与最终验收 + +| 顺序 | 任务 | 说明 | +|---|---|---| +| 1 | T22 Docker Compose 与部署 | 应用主体完成后做部署闭环 | +| 2 | T23 最终测试与手工验收 | 覆盖单元、集成、coverage、Docker、双平台手工流程 | + +文件冲突风险: + +- T22 主要改 `Dockerfile`、`docker-compose.yml`、`.env.example`,与业务代码冲突低。 +- `.env.example` 已由 T02 修改,T22 修改前需读取最新文件。 +- T23 会修改 `README.md` 和 `docs/Tasks.md` 勾选完成项,只能在真实完成并验证后执行。 + +## 7. 总体执行顺序建议 + +```text +Group 0 冲突确认 + -> Group 1 基础串行启动 + -> Group 2 恢复与首页 + -> Group 3 平台抓取 + -> Group 4 AI 与报告 + -> Group 5 页面与导出 + -> Group 6 部署与验收 +``` + +若多人协作,最有价值的并行窗口是: + +1. T08 与 T09。 +2. T18 与 T19。 +3. T20 服务层与 T18/T19 页面层。 +4. T22 与页面 polish 收尾。 + +最应避免的并行窗口是: + +1. T01-T04 基础骨架。 +2. T10/T11 抓取集成。 +3. T13/T16 AI 接入。 +4. T14/T15 报告服务。 +5. T21 共享模板收敛。 + +## 8. 每组文件冲突风险汇总 + +| 分组 | 冲突等级 | 高风险文件 | 风险说明 | 建议 | +|---|---|---|---|---| +| Group 1 基础 | 高 | `app/main.py`, `app/config.py`, `app/models.py`, `app/schemas.py`, `tests/conftest.py` | 基础文件会被连续扩展,接口和模型尚未稳定 | 串行执行 | +| Group 2 恢复与首页 | 中 | `app/main.py`, `tests/integration/test_routes.py`, `tests/unit/test_template_filters.py` | lifespan、页面 route、模板测试可能同时变动 | 分清 route/lifespan 修改边界,最终统一合并 | +| Group 3 平台抓取 | 中 | `app/services/crawl_service.py`, `app/platforms/xiaohongshu.py`, `app/platforms/douyin.py`, `tests/unit/test_comment_pagination.py` | T08/T09 低冲突;T10/T11 高耦合 | 只并行 T08/T09,T10/T11 串行 | +| Group 4 AI 与报告 | 高 | `app/services/ai_service.py`, `app/services/report_service.py`, `app/services/task_service.py`, `tests/unit/test_ai_schema.py`, `tests/unit/test_report_stats.py` | 服务能力和集成接入依赖强 | T12-T16 基本串行 | +| Group 5 页面与导出 | 高 | `app/main.py`, `tests/integration/test_routes.py`, `tests/unit/test_template_filters.py`, `app/templates/base.html`, `app/static/app.js`, `app/static/app.css` | 多页面和导出按钮都触碰共享模板与路由 | 服务层和模板层拆人,route 合并由一人负责 | +| Group 6 部署验收 | 低到中 | `.env.example`, `docs/Tasks.md`, `README.md` | T22 与 T02 共享 env 示例;T23 会勾选任务 | T22 读取最新 env;T23 只在验证后勾选 | + +## 9. 多代理分工建议 + +如使用多代理并行,建议每个代理使用独立分支,且不要让两个代理同时编辑同一文件。 + +推荐分支示例: + +- `agent/codex-1/T08-xiaohongshu` +- `agent/codex-2/T09-douyin` +- `agent/codex-3/T18-hotspot-report-page` +- `agent/codex-4/T19-item-detail-page` +- `agent/codex-5/T20-export-service` + +主代理保留职责: + +1. 冻结文档冲突口径。 +2. 合并共享文件:`app/main.py`、`task_service.py`、`report_service.py`、共享测试文件。 +3. 运行完整验证。 +4. 更新 `docs/Tasks.md` 复选框。 diff --git a/docs/Tasks.md b/docs/Tasks.md index 84f6965..074c7c9 100644 --- a/docs/Tasks.md +++ b/docs/Tasks.md @@ -101,13 +101,13 @@ pyproject.toml **步骤**: -- [ ] 创建 `app/`、`app/services/`、`app/platforms/`、`app/templates/`、`app/static/`、`tests/` 目录。 -- [ ] 添加 FastAPI、SQLAlchemy、Pydantic、httpx、Jinja2、pytest、respx、beautifulsoup4 等依赖。 -- [ ] 在 `app/main.py` 中创建 FastAPI 应用。 -- [ ] 实现 `/health`,返回 `{ "status": "ok" }`。 -- [ ] 编写 `tests/unit/test_config.py`,覆盖默认配置和环境变量读取。 -- [ ] 编写 `/health` 集成测试。 -- [ ] 运行 `pytest tests/unit tests/integration -q`。 +- [x] 创建 `app/`、`app/services/`、`app/platforms/`、`app/templates/`、`app/static/`、`tests/` 目录。 +- [x] 添加 FastAPI、SQLAlchemy、Pydantic、httpx、Jinja2、pytest、respx、beautifulsoup4 等依赖。 +- [x] 在 `app/main.py` 中创建 FastAPI 应用。 +- [x] 实现 `/health`,返回 `{ "status": "ok" }`。 +- [x] 编写 `tests/unit/test_config.py`,覆盖默认配置和环境变量读取。 +- [x] 编写 `/health` 集成测试。 +- [x] 运行 `pytest tests/unit tests/integration -q`。 **验收**: @@ -145,13 +145,13 @@ pyproject.toml **步骤**: -- [ ] 先写配置默认值测试。 -- [ ] 实现 Pydantic Settings 或等价配置类。 -- [ ] 校验 `AI_CONCURRENCY` 默认值为 2,硬上限不超过 3。 -- [ ] 校验 `AI_MAX_RETRIES` 默认值为 3。 -- [ ] 补充 `.env.example`。 -- [ ] 写测试:`CRAWL_PAGE_INTERVAL_SECONDS` 可从环境变量读取,默认值为 1.5。 -- [ ] 在 `.env.example` 中补充该配置项及注释说明。 +- [x] 先写配置默认值测试。 +- [x] 实现 Pydantic Settings 或等价配置类。 +- [x] 校验 `AI_CONCURRENCY` 默认值为 2,硬上限不超过 3。 +- [x] 校验 `AI_MAX_RETRIES` 默认值为 3。 +- [x] 补充 `.env.example`。 +- [x] 写测试:`CRAWL_PAGE_INTERVAL_SECONDS` 可从环境变量读取,默认值为 1.5。 +- [x] 在 `.env.example` 中补充该配置项及注释说明。 **验收**: @@ -178,15 +178,15 @@ pyproject.toml **步骤**: -- [ ] 写 `tests/unit/test_models.py`,断言所有表可创建。 -- [ ] 实现 SQLAlchemy Base、engine、session。 -- [ ] SQLite 启用 `check_same_thread=False`、`timeout=10`、WAL。 -- [ ] 实现 `Base.metadata.create_all(engine)` 启动初始化。 -- [ ] 实现 `tasks.analysis_status`、`analysis_success_rate`、进度字段。 -- [ ] 实现 reports 表业务约束在应用层校验所需字段。 -- [ ] 【性能预留索引,不影响功能验收】在 comments 表上添加 `(task_id, content_item_id)` 联合索引。 -- [ ] 【性能预留索引,不影响功能验收】在 content_items 表上添加 `(task_id, hotspot_id)` 联合索引。 -- [ ] 【性能预留索引,不影响功能验收】在 reports 表上添加 `(task_id, report_type)` 联合索引。 +- [x] 写 `tests/unit/test_models.py`,断言所有表可创建。 +- [x] 实现 SQLAlchemy Base、engine、session。 +- [x] SQLite 启用 `check_same_thread=False`、`timeout=10`、WAL。 +- [x] 实现 `Base.metadata.create_all(engine)` 启动初始化。 +- [x] 实现 `tasks.analysis_status`、`analysis_success_rate`、进度字段。 +- [x] 实现 reports 表业务约束在应用层校验所需字段。 +- [x] 【性能预留索引,不影响功能验收】在 comments 表上添加 `(task_id, content_item_id)` 联合索引。 +- [x] 【性能预留索引,不影响功能验收】在 content_items 表上添加 `(task_id, hotspot_id)` 联合索引。 +- [x] 【性能预留索引,不影响功能验收】在 reports 表上添加 `(task_id, report_type)` 联合索引。 **验收**: @@ -214,16 +214,16 @@ pyproject.toml **步骤**: -- [ ] 写创建任务 API 测试,合法参数返回 `task_id` 和 `status`。 -- [ ] 写非法参数测试:平台非法、热点数量越界、内容条目数越界、评论数越界。 -- [ ] 实现 `CreateTaskRequest` schema。 -- [ ] 实现 `ThreadPoolExecutor(max_workers=1)`。 -- [ ] 在 `CreateTaskRequest` 处理逻辑中,查询当前是否存在 `status=running` 的任务;若存在,直接返回 HTTP 400,响应体为 `{"detail": "当前有正在运行的任务,请稍后再试"}`,不创建新任务。 -- [ ] 写测试:当已有 `status=running` 任务时,`POST /api/tasks` 返回 400。 -- [ ] 写测试:当无 running 任务时,`POST /api/tasks` 正常创建并返回 200/201。 -- [ ] 创建任务时保存平台、配置规模、创建时间、状态和进度字段。 -- [ ] 同一平台重复创建任务时生成独立任务。 -- [ ] 实现任务列表查询。 +- [x] 写创建任务 API 测试,合法参数返回 `task_id` 和 `status`。 +- [x] 写非法参数测试:平台非法、热点数量越界、内容条目数越界、评论数越界。 +- [x] 实现 `CreateTaskRequest` schema。 +- [x] 实现 `ThreadPoolExecutor(max_workers=1)`。 +- [x] 在 `CreateTaskRequest` 处理逻辑中,查询当前是否存在 `status=running` 的任务;若存在,直接返回 HTTP 400,响应体为 `{"detail": "当前有正在运行的任务,请稍后再试"}`,不创建新任务。 +- [x] 写测试:当已有 `status=running` 任务时,`POST /api/tasks` 返回 400。 +- [x] 写测试:当无 running 任务时,`POST /api/tasks` 正常创建并返回 200/201。 +- [x] 创建任务时保存平台、配置规模、创建时间、状态和进度字段。 +- [x] 同一平台重复创建任务时生成独立任务。 +- [x] 实现任务列表查询。 **验收**: @@ -243,10 +243,10 @@ pyproject.toml **步骤**: -- [ ] 写测试:数据库中存在 `status=running` 的任务。 -- [ ] 应用 lifespan 启动时执行恢复逻辑。 -- [ ] 将 running 任务更新为 failed。 -- [ ] 写入 `error_stage=system`、`error_type=unexpected_restart`、`error_message=系统重启,任务被中断`。 +- [x] 写测试:数据库中存在 `status=running` 的任务。 +- [x] 应用 lifespan 启动时执行恢复逻辑。 +- [x] 将 running 任务更新为 failed。 +- [x] 写入 `error_stage=system`、`error_type=unexpected_restart`、`error_message=系统重启,任务被中断`。 **验收**: