From a0635ff2c68082e4a2f81bcad6f8b909c4f1ed4b Mon Sep 17 00:00:00 2001 From: SpecialX <47072643+wangxiner55@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:21:13 +0800 Subject: [PATCH] =?UTF-8?q?docs(content):=20=E5=90=8C=E6=AD=A5=20ARB-005?= =?UTF-8?q?=20=E8=A3=81=E5=86=B3=E8=87=B3=E5=85=A8=E9=83=A8=E6=B2=BB?= =?UTF-8?q?=E7=90=86=E6=96=87=E6=A1=A3=20-=20matrix/contract/issue/worklin?= =?UTF-8?q?e=20P4=20=E5=B0=B1=E7=BB=AA=E4=BF=A1=E5=8F=B7=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E5=8B=BE=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issues/contracts/content_contract.md | 222 +++++++++--------- docs/architecture/issues/matrix.md | 70 +++--- .../issues/objections/content_issue.md | 2 +- .../issues/worklines/content_workline.md | 56 +++-- 4 files changed, 179 insertions(+), 171 deletions(-) diff --git a/docs/architecture/issues/contracts/content_contract.md b/docs/architecture/issues/contracts/content_contract.md index 4b75ac3..6e6db5c 100644 --- a/docs/architecture/issues/contracts/content_contract.md +++ b/docs/architecture/issues/contracts/content_contract.md @@ -9,12 +9,12 @@ ## §0 契约状态总览 -| 维度 | 当前状态 | 目标状态(P4 完成) | -| ---------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------- | -| gRPC | ❌ 未实现([content.proto](../../../packages/shared-proto/proto/content.proto) 仅 5 RPC 定义) | ✅ 21 RPC(4 Service) | -| HTTP REST | ✅ 已实现 22 端点(4 Controller) | 🔁 保留作为管理面(不作为下游契约,下游统一 gRPC) | -| Kafka 发布 | ❌ 未实现 | ✅ 4 聚合 topic(待 ISSUE-002 仲裁确认策略) | -| Kafka 消费 | ❌ 未实现 | 🟢 可选(content 是上游,不主动消费 core-edu 事件,见 ISSUE-005) | +| 维度 | 当前状态 | 目标状态(P4 完成) | +| ---------- | --------------------------------------------- | ----------------------------------------------------------------- | +| gRPC | ✅ 已实现 22 RPC(4 Service,ARB-005 已裁决) | ✅ 22 RPC(4 Service) | +| HTTP REST | ✅ 已实现 22 端点(4 Controller) | 🔁 保留作为管理面(不作为下游契约,下游统一 gRPC) | +| Kafka 发布 | ✅ 已实现 4 聚合 topic(ARB-005 §5.3 裁决) | ✅ 4 聚合 topic | +| Kafka 消费 | ❌ 未实现 | 🟢 可选(content 是上游,不主动消费 core-edu 事件,见 ISSUE-005) | --- @@ -23,36 +23,36 @@ ### 1.1 gRPC 接口(目标态 · P4 完成) > 依据 [coord-final-decisions.md §3.3](../../coord-final-decisions.md) N1/N3/N5 + [02-architecture-design.md §4.2](../../../services/content/docs/02-architecture-design.md) -> 待 ISSUE-004 仲裁后定稿,当前按建议方案 21 RPC 列出 +> ARB-005 已裁决(2026-07-10),按 22 RPC 定稿(TextbookService 5 + ChapterService 5 + KnowledgeGraphService 4 + QuestionService 8) -| Service | RPC | 请求 | 响应 | 端口 | 阶段 | -| --------------------- | -------------------- | ------------------------------------------------------------ | ----------------------------------------------------------- | ----- | ---- | -| TextbookService | CreateTextbook | CreateTextbookRequest{title, subject_id, grade_id, version?} | Textbook | 50054 | P4 | -| TextbookService | GetTextbook | GetTextbookRequest{id} | Textbook | 50054 | P4 | -| TextbookService | ListTextbooks | ListTextbooksRequest{subject_id?, grade_id?, page_token, page_size} | ListTextbooksResponse{textbooks[], next_page_token} | 50054 | P4 | -| TextbookService | UpdateTextbook | UpdateTextbookRequest{id, title?, status?, metadata?} | Textbook | 50054 | P4 | -| TextbookService | DeleteTextbook | DeleteTextbookRequest{id} | Empty | 50054 | P4 | -| ChapterService | CreateChapter | CreateChapterRequest{textbook_id, title, order, parent_id?} | Chapter | 50054 | P4 | -| ChapterService | GetChapter | GetChapterRequest{id} | Chapter | 50054 | P4 | -| ChapterService | ListChapters | ListChaptersRequest{textbook_id, parent_id?} | ListChaptersResponse{chapters[]} | 50054 | P4 | -| ChapterService | UpdateChapter | UpdateChapterRequest{id, title?, order?, status?} | Chapter | 50054 | P4 | -| ChapterService | DeleteChapter | DeleteChapterRequest{id} | Empty | 50054 | P4 | -| KnowledgeGraphService | GetPrerequisites | GetPrerequisitesRequest{knowledge_point_id, depth?} | KnowledgePointsResponse{points[]} | 50054 | P4 | -| KnowledgeGraphService | GetLearningPath | GetLearningPathRequest{student_id, subject_id} | LearningPath{points[], recommended_order[]} | 50054 | P4 | -| KnowledgeGraphService | AddPrerequisite | AddPrerequisiteRequest{kp_id, prerequisite_id} | Empty | 50054 | P4 | -| KnowledgeGraphService | RemovePrerequisite | RemovePrerequisiteRequest{kp_id, prerequisite_id} | Empty | 50054 | P4 | -| QuestionService | CreateQuestion | CreateQuestionRequest{knowledge_point_id, type, content, options?, answer, explanation?, difficulty?, source?, created_by?} | Question | 50054 | P4 | -| QuestionService | BatchCreateQuestions | BatchCreateQuestionsRequest{questions[]} | BatchCreateQuestionsResponse{ids[], failed[]} | 50054 | P4 | -| QuestionService | GetQuestion | GetQuestionRequest{id} | Question | 50054 | P4 | -| QuestionService | ListQuestions | ListQuestionsRequest{knowledge_point_id?, type?, difficulty?, status?, page_token, page_size} | ListQuestionsResponse{questions[], next_page_token} | 50054 | P4 | -| QuestionService | UpdateQuestion | UpdateQuestionRequest{id, content?, answer?, status?} | Question | 50054 | P4 | -| QuestionService | DeleteQuestion | DeleteQuestionRequest{id} | Empty | 50054 | P4 | -| QuestionService | PublishQuestion | PublishQuestionRequest{id} | Empty | 50054 | P4 | -| QuestionService | SearchQuestions | SearchQuestionsRequest{q?, type?, difficulty?, knowledge_point_id?, page_token, page_size} | SearchQuestionsResponse{questions[], total, next_page_token} | 50054 | P5 | +| Service | RPC | 请求 | 响应 | 端口 | 阶段 | +| --------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ----- | ---- | +| TextbookService | CreateTextbook | CreateTextbookRequest{title, subject_id, grade_id, version?} | Textbook | 50054 | P4 | +| TextbookService | GetTextbook | GetTextbookRequest{id} | Textbook | 50054 | P4 | +| TextbookService | ListTextbooks | ListTextbooksRequest{subject_id?, grade_id?, page_token, page_size} | ListTextbooksResponse{textbooks[], next_page_token} | 50054 | P4 | +| TextbookService | UpdateTextbook | UpdateTextbookRequest{id, title?, status?, metadata?} | Textbook | 50054 | P4 | +| TextbookService | DeleteTextbook | DeleteTextbookRequest{id} | Empty | 50054 | P4 | +| ChapterService | CreateChapter | CreateChapterRequest{textbook_id, title, order, parent_id?} | Chapter | 50054 | P4 | +| ChapterService | GetChapter | GetChapterRequest{id} | Chapter | 50054 | P4 | +| ChapterService | ListChapters | ListChaptersRequest{textbook_id, parent_id?} | ListChaptersResponse{chapters[]} | 50054 | P4 | +| ChapterService | UpdateChapter | UpdateChapterRequest{id, title?, order?, status?} | Chapter | 50054 | P4 | +| ChapterService | DeleteChapter | DeleteChapterRequest{id} | Empty | 50054 | P4 | +| KnowledgeGraphService | GetPrerequisites | GetPrerequisitesRequest{knowledge_point_id, depth?} | KnowledgePointsResponse{points[]} | 50054 | P4 | +| KnowledgeGraphService | GetLearningPath | GetLearningPathRequest{student_id, subject_id} | LearningPath{points[], recommended_order[]} | 50054 | P4 | +| KnowledgeGraphService | AddPrerequisite | AddPrerequisiteRequest{kp_id, prerequisite_id} | Empty | 50054 | P4 | +| KnowledgeGraphService | RemovePrerequisite | RemovePrerequisiteRequest{kp_id, prerequisite_id} | Empty | 50054 | P4 | +| QuestionService | CreateQuestion | CreateQuestionRequest{knowledge_point_id, type, content, options?, answer, explanation?, difficulty?, source?, created_by?} | Question | 50054 | P4 | +| QuestionService | BatchCreateQuestions | BatchCreateQuestionsRequest{questions[]} | BatchCreateQuestionsResponse{ids[], failed[]} | 50054 | P4 | +| QuestionService | GetQuestion | GetQuestionRequest{id} | Question | 50054 | P4 | +| QuestionService | ListQuestions | ListQuestionsRequest{knowledge_point_id?, type?, difficulty?, status?, page_token, page_size} | ListQuestionsResponse{questions[], next_page_token} | 50054 | P4 | +| QuestionService | UpdateQuestion | UpdateQuestionRequest{id, content?, answer?, status?} | Question | 50054 | P4 | +| QuestionService | DeleteQuestion | DeleteQuestionRequest{id} | Empty | 50054 | P4 | +| QuestionService | PublishQuestion | PublishQuestionRequest{id} | Empty | 50054 | P4 | +| QuestionService | SearchQuestions | SearchQuestionsRequest{q?, type?, difficulty?, knowledge_point_id?, page_token, page_size} | SearchQuestionsResponse{questions[], total, next_page_token} | 50054 | P5 | -**RPC 总数**:21(TextbookService 5 + ChapterService 5 + KnowledgeGraphService 4 + QuestionService 7) +**RPC 总数**:22(TextbookService 5 + ChapterService 5 + KnowledgeGraphService 4 + QuestionService 8) -> ⚠️ **matrix.md §2 同步项**:当前 matrix.md §2 登记 content 为 18 RPC,待 ISSUE-004 仲裁后需更新为 21 RPC(差额:ChapterService 补 Update + Delete = +2;TextbookService 补 Update + Delete = +2;QuestionService 原 contract 已含 Publish/Search,design doc 缺,对齐后 +0;原合计 18 + 4 - 1 = 21) +> ✅ **matrix.md §2 已同步**:ARB-005 裁决后已更新为 22 RPC #### proto message 字段说明(关键字段) @@ -124,12 +124,12 @@ message Question { > 待 ISSUE-002 仲裁确认 topic 命名策略,当前按**聚合 topic + action 字段**策略列出(与 matrix.md §4 / events.proto ClassEvent 模式一致) -| Topic | Event message | action 字段值 | 消费方 | 阶段 | -| ------------------------------------ | -------------------- | ---------------------------------------------------------- | -------------------------------------------------- | ---- | -| edu.content.textbook.events | TextbookEvent | created / updated / published / archived | data-ana / msg(通知教师教材发布) | P4 | -| edu.content.chapter.events | ChapterEvent | created / updated / deleted | data-ana | P4 | -| edu.content.knowledge_point.events | KnowledgePointEvent | created / updated / prerequisite_added / prerequisite_removed | data-ana / ai / Neo4j Sync Worker / ES Sync Worker | P4 | -| edu.content.question.events | QuestionEvent | created / updated / published / deleted | data-ana / ai / ES Sync Worker | P4 | +| Topic | Event message | action 字段值 | 消费方 | 阶段 | +| ---------------------------------- | ------------------- | ------------------------------------------------------------- | -------------------------------------------------- | ---- | +| edu.content.textbook.events | TextbookEvent | created / updated / published / archived | data-ana / msg(通知教师教材发布) | P4 | +| edu.content.chapter.events | ChapterEvent | created / updated / deleted | data-ana | P4 | +| edu.content.knowledge_point.events | KnowledgePointEvent | created / updated / prerequisite_added / prerequisite_removed | data-ana / ai / Neo4j Sync Worker / ES Sync Worker | P4 | +| edu.content.question.events | QuestionEvent | created / updated / published / deleted | data-ana / ai / ES Sync Worker | P4 | > ⚠️ **ISSUE-003 待仲裁**:当前 matrix.md §4 仅登记 kp + question 两类 topic,Textbook/Chapter 事件未登记。本契约按 design doc §5.1 补全 4 类,待 coord 仲裁后同步 matrix.md。 @@ -200,24 +200,24 @@ message QuestionEvent { `CONTENT_`(详见 [02-architecture-design.md §6.2](../../../services/content/docs/02-architecture-design.md)) -| 错误码 | HTTP | gRPC status | 触发条件 | -| ------------------------- | ---- | ------------------ | ---------------------------------- | -| CONTENT_VALIDATION_ERROR | 400 | INVALID_ARGUMENT | Zod 校验失败 / 题型非法 / 难度越界 | -| CONTENT_NOT_FOUND | 404 | NOT_FOUND | 资源不存在 | -| CONTENT_PERMISSION_DENIED | 403 | PERMISSION_DENIED | 权限不足 | -| CONTENT_CONFLICT | 409 | ALREADY_EXISTS | 唯一约束冲突 / 状态机非法转换 | -| CONTENT_BUSINESS_ERROR | 422 | FAILED_PRECONDITION | 业务规则违反(如循环依赖检测) | -| CONTENT_DATABASE_ERROR | 500 | INTERNAL | Drizzle 操作异常 | -| CONTENT_INTERNAL_ERROR | 500 | INTERNAL | 未知异常 | -| CONTENT_NEO4J_UNAVAILABLE | 503 | UNAVAILABLE | Neo4j 不可用且无降级路径 | +| 错误码 | HTTP | gRPC status | 触发条件 | +| ------------------------- | ---- | ------------------- | ---------------------------------- | +| CONTENT_VALIDATION_ERROR | 400 | INVALID_ARGUMENT | Zod 校验失败 / 题型非法 / 难度越界 | +| CONTENT_NOT_FOUND | 404 | NOT_FOUND | 资源不存在 | +| CONTENT_PERMISSION_DENIED | 403 | PERMISSION_DENIED | 权限不足 | +| CONTENT_CONFLICT | 409 | ALREADY_EXISTS | 唯一约束冲突 / 状态机非法转换 | +| CONTENT_BUSINESS_ERROR | 422 | FAILED_PRECONDITION | 业务规则违反(如循环依赖检测) | +| CONTENT_DATABASE_ERROR | 500 | INTERNAL | Drizzle 操作异常 | +| CONTENT_INTERNAL_ERROR | 500 | INTERNAL | 未知异常 | +| CONTENT_NEO4J_UNAVAILABLE | 503 | UNAVAILABLE | Neo4j 不可用且无降级路径 | ### 1.6 健康检查端点 -| 端点 | 用途 | 鉴权 | 响应 | -| ----------- | ------------------------------------------------------- | ---- | ------------------------------------------------------------------------------- | -| GET /healthz | 存活探针(liveness),仅返回进程状态 | 无 | `{ "status": "ok", "service": "content", "timestamp": "..." }` | -| GET /readyz | 就绪探针(readiness),检查 DB/Neo4j/Kafka 三依赖 | 无 | `{ "status": "ok|degraded|down", "checks": { database, neo4j, kafka_producer, kafka_consumer } }` | -| GET /metrics | Prometheus 指标 | 无 | Prometheus exposition format | +| 端点 | 用途 | 鉴权 | 响应 | +| ------------ | ------------------------------------------------- | ---- | -------------------------------------------------------------- | +| GET /healthz | 存活探针(liveness),仅返回进程状态 | 无 | `{ "status": "ok", "service": "content", "timestamp": "..." }` | +| GET /readyz | 就绪探针(readiness),检查 DB/Neo4j/Kafka 三依赖 | 无 | `{ "status": "ok | degraded | down", "checks": { database, neo4j, kafka_producer, kafka_consumer } }` | +| GET /metrics | Prometheus 指标 | 无 | Prometheus exposition format | --- @@ -241,14 +241,14 @@ message QuestionEvent { ### 2.4 基础设施依赖 -| 依赖 | 用途 | 配置项(env.ts) | 必需性 | -| --------------- | ----------------------------- | ----------------------------- | ---------------------- | -| MySQL 8 | 写模型主库(4 张业务表 + outbox) | DATABASE_URL | 🔴 必需 | -| Neo4j 5 | 知识图谱(PREREQUISITE_OF) | NEO4J_URL / NEO4J_PASSWORD | 🔴 必需(图谱查询核心) | -| Kafka | Outbox 事件发布 | KAFKA_BROKERS(待补 env.ts) | 🔴 必需(Outbox 强制) | -| Redis | 缓存(教材树/章节树,P5+) | REDIS_URL(已预留) | 🟢 P5+ 可选 | -| Elasticsearch 8 | 题库全文检索(P5+) | ES_URL(已预留) | 🟢 P5+ 必需 | -| OTLP Collector | 链路追踪 | OTEL_EXPORTER_OTLP_ENDPOINT | 🟢 可选(未配置时降级) | +| 依赖 | 用途 | 配置项(env.ts) | 必需性 | +| --------------- | --------------------------------- | ---------------------------- | ----------------------- | +| MySQL 8 | 写模型主库(4 张业务表 + outbox) | DATABASE_URL | 🔴 必需 | +| Neo4j 5 | 知识图谱(PREREQUISITE_OF) | NEO4J_URL / NEO4J_PASSWORD | 🔴 必需(图谱查询核心) | +| Kafka | Outbox 事件发布 | KAFKA_BROKERS(待补 env.ts) | 🔴 必需(Outbox 强制) | +| Redis | 缓存(教材树/章节树,P5+) | REDIS_URL(已预留) | 🟢 P5+ 可选 | +| Elasticsearch 8 | 题库全文检索(P5+) | ES_URL(已预留) | 🟢 P5+ 必需 | +| OTLP Collector | 链路追踪 | OTEL_EXPORTER_OTLP_ENDPOINT | 🟢 可选(未配置时降级) | --- @@ -256,28 +256,28 @@ message QuestionEvent { ### 3.1 我依赖的上游就绪标志 -| 上游 | 就绪标志 | 必需性 | mock 策略 | -| -------------- | ----------------------------------------- | ---------------------- | ----------------------------------------------- | -| infra | MySQL 8 可用 | 🔴 必需 | 本地 docker-compose | -| infra | Neo4j 5 可用 | 🔴 必需 | 本地 docker-compose;未配置时图谱查询返回 503 | -| infra | Kafka 集群可用 | 🔴 必需 | 本地 docker-compose | -| shared-proto | content.proto / events.proto 补全 | 🔴 必需(P4.6 自身完成) | ai09 自行修改 proto | -| core-edu (ai08) | gRPC 50053 启用 | 🟢 可选(content 独立) | 不依赖 core-edu 实时数据 | -| ai (ai12) | gRPC 50058 启用 | 🟢 P5 联调时必需 | grpc-mock 拦截 | +| 上游 | 就绪标志 | 必需性 | mock 策略 | +| --------------- | --------------------------------- | ------------------------ | --------------------------------------------- | +| infra | MySQL 8 可用 | 🔴 必需 | 本地 docker-compose | +| infra | Neo4j 5 可用 | 🔴 必需 | 本地 docker-compose;未配置时图谱查询返回 503 | +| infra | Kafka 集群可用 | 🔴 必需 | 本地 docker-compose | +| shared-proto | content.proto / events.proto 补全 | 🔴 必需(P4.6 自身完成) | ai09 自行修改 proto | +| core-edu (ai08) | gRPC 50053 启用 | 🟢 可选(content 独立) | 不依赖 core-edu 实时数据 | +| ai (ai12) | gRPC 50058 启用 | 🟢 P5 联调时必需 | grpc-mock 拦截 | ### 3.2 我的就绪标志(供下游消费) #### P4 就绪(核心交付) -- [ ] content gRPC 50054 启用(HealthService.Check 返回 SERVING) -- [ ] TextbookService 5 RPC 可调用(Create/Get/List/Update/Delete) -- [ ] ChapterService 5 RPC 可调用(Create/Get/List/Update/Delete) -- [ ] KnowledgeGraphService 4 RPC 可调用(GetPrerequisites/GetLearningPath/AddPrerequisite/RemovePrerequisite) -- [ ] QuestionService 7 RPC 可调用(Create/BatchCreate/Get/List/Update/Delete/Publish/Search) -- [ ] edu.content.textbook.events / chapter.events / knowledge_point.events / question.events 4 topic 可发布 -- [ ] /readyz 返回 DB/Neo4j/Kafka 三依赖状态 -- [ ] Outbox Publisher worker 运行中(content_outbox_events 表 PENDING 事件 < 100) -- [ ] Neo4j Sync Worker 运行中(知识点节点最终一致延迟 < 2s) +- [x] content gRPC 50054 启用(HealthService.Check 返回 SERVING) +- [x] TextbookService 5 RPC 可调用(Create/Get/List/Update/Delete) +- [x] ChapterService 5 RPC 可调用(Create/Get/List/Update/Delete) +- [x] KnowledgeGraphService 4 RPC 可调用(GetPrerequisites/GetLearningPath/AddPrerequisite/RemovePrerequisite) +- [x] QuestionService 8 RPC 可调用(Create/BatchCreate/Get/List/Update/Delete/Publish/Search) +- [x] edu.content.textbook.events / chapter.events / knowledge_point.events / question.events 4 topic 可发布 +- [x] /readyz 返回 DB/Neo4j/Kafka 三依赖状态 +- [x] Outbox Publisher worker 运行中(content_outbox_events 表 PENDING 事件 < 100) +- [x] Neo4j Sync Worker 运行中(知识点节点最终一致延迟 < 2s) #### P5 就绪(检索 + AI 集成) @@ -303,17 +303,17 @@ message QuestionEvent { #### gRPC mock(grpc-mock 拦截 50054 端口) -| Service | RPC | Mock 返回 | -| --------------------- | --------------------- | ---------------------------------------------------------- | -| TextbookService | ListTextbooks | 固定 5 个 Textbook(语数英理化,subject_id=math/chn/eng/phy/chem) | -| TextbookService | GetTextbook | 返回第一个 Textbook | -| ChapterService | ListChapters | 固定章节树(每教材 10 章,含 parent_id 树形结构) | -| KnowledgeGraphService | GetLearningPath | 固定 8 个 KnowledgePoint 推荐顺序(按 difficulty 升序) | -| KnowledgeGraphService | GetPrerequisites | 固定 3 个前置知识点 | -| QuestionService | ListQuestions | 固定 20 个 Question(含 4 种题型各 5 个) | -| QuestionService | SearchQuestions | 固定 20 个 Question(含 options) | -| QuestionService | BatchCreateQuestions | 返回成功 + 生成 20 个 cuid2 ID | -| QuestionService | CreateQuestion | 返回成功 + 生成 1 个 cuid2 ID | +| Service | RPC | Mock 返回 | +| --------------------- | -------------------- | ------------------------------------------------------------------ | +| TextbookService | ListTextbooks | 固定 5 个 Textbook(语数英理化,subject_id=math/chn/eng/phy/chem) | +| TextbookService | GetTextbook | 返回第一个 Textbook | +| ChapterService | ListChapters | 固定章节树(每教材 10 章,含 parent_id 树形结构) | +| KnowledgeGraphService | GetLearningPath | 固定 8 个 KnowledgePoint 推荐顺序(按 difficulty 升序) | +| KnowledgeGraphService | GetPrerequisites | 固定 3 个前置知识点 | +| QuestionService | ListQuestions | 固定 20 个 Question(含 4 种题型各 5 个) | +| QuestionService | SearchQuestions | 固定 20 个 Question(含 options) | +| QuestionService | BatchCreateQuestions | 返回成功 + 生成 20 个 cuid2 ID | +| QuestionService | CreateQuestion | 返回成功 + 生成 1 个 cuid2 ID | #### Kafka mock @@ -324,6 +324,7 @@ content 就绪前不发布真实事件,下游使用本地 stub(data-ana / ai content P4 不消费任何上游事件,无需 mock 上游。 P5 联调阶段消费 ai (ai12) 的 gRPC,使用 grpc-mock 拦截 50058 端口: + - AiService.GenerateQuestion 返回固定 1 个 Question(source=ai_generated) - AiService.Chat 返回固定文本响应 @@ -335,34 +336,35 @@ P5 联调阶段消费 ai (ai12) 的 gRPC,使用 grpc-mock 拦截 50058 端口 ### 5.1 与 02-architecture-design.md 对齐 -| 维度 | design doc | contract.md(本文件) | 一致性 | 备注 | -| ------------- | -------------------------------- | ------------------------------ | ------ | ------------------------------------------ | -| gRPC RPC 数 | §4.2 列 18 RPC | §1.1 列 21 RPC | ⚠️ | 待 ISSUE-004 仲裁;建议以 21 RPC 为准 | -| 事件 topic | §5.1 列 12 独立 topic | §1.4 列 4 聚合 topic | ⚠️ | 待 ISSUE-002 仲裁;建议以 4 聚合 topic 为准 | -| 错误码 | §6.2 列 8 个 | §1.5 列 8 个 | ✅ | 一致 | -| 健康检查 | §6.6 /readyz 多依赖 | §1.6 三依赖 | ✅ | 一致 | +| 维度 | design doc | contract.md(本文件) | 一致性 | 备注 | +| ----------- | --------------------- | --------------------- | ------ | ---------------------------------------------------------- | +| gRPC RPC 数 | §4.2 列 18 RPC | §1.1 列 22 RPC | ✅ | ARB-005 已裁决:22 RPC 为准;design doc 待 ai09 同步 | +| 事件 topic | §5.1 列 12 独立 topic | §1.4 列 4 聚合 topic | ✅ | ARB-005 已裁决:4 聚合 topic 为准;design doc 待 ai09 同步 | +| 错误码 | §6.2 列 8 个 | §1.5 列 8 个 | ✅ | 一致 | +| 健康检查 | §6.6 /readyz 多依赖 | §1.6 三依赖 | ✅ | 一致 | ### 5.2 与 matrix.md 对齐 -| 维度 | matrix.md | contract.md(本文件) | 一致性 | 备注 | -| ------------- | -------------------------------- | ------------------------------ | ------ | ------------------------------------------ | -| gRPC RPC 总数 | §2 列 18 RPC | §1.1 列 21 RPC | ⚠️ | 待 ISSUE-004 仲裁后同步 matrix.md | -| Kafka topic | §4 列 2 topic(kp + question) | §1.4 列 4 topic | ⚠️ | 待 ISSUE-003 仲裁后同步 matrix.md | -| 错误码前缀 | §6 列 CONTENT_ | §1.5 列 CONTENT_ | ✅ | 一致 | -| 端口 | §2 列 50054 | §1.1 列 50054 | ✅ | 一致 | +| 维度 | matrix.md | contract.md(本文件) | 一致性 | 备注 | +| ------------- | --------------------------------------------- | --------------------- | ------ | -------------------- | +| gRPC RPC 总数 | §2 列 22 RPC | §1.1 列 22 RPC | ✅ | ARB-005 裁决后已同步 | +| Kafka topic | §4 列 4 topic(textbook/chapter/kp/question) | §1.4 列 4 topic | ✅ | ARB-005 裁决后已同步 | +| 错误码前缀 | §6 列 CONTENT_ | §1.5 列 CONTENT_ | ✅ | 一致 | +| 端口 | §2 列 50054 | §1.1 列 50054 | ✅ | 一致 | ### 5.3 与 proto 文件对齐 -| 文件 | 当前状态 | 目标状态(P4 完成) | -| ------------- | ---------------------------------------------------------------- | ------------------------------------------------ | -| content.proto | 5 RPC(TextbookService 3 + KnowledgeGraphService 2),无 Chapter/Question | 21 RPC(4 Service 完整) | -| events.proto | 4 message(ClassEvent/ExamEvent/HomeworkEvent/GradeEvent) | 8 message(+ TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEvent) | +| 文件 | 当前状态 | 目标状态(P4 完成) | +| ------------- | ------------------------------------------------------------------ | --------------------------- | +| content.proto | ✅ 22 RPC(4 Service 完整,ARB-005 已裁决) | ✅ 22 RPC(4 Service 完整) | +| events.proto | ✅ 含 TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEvent | ✅ 4 content message 已补全 | --- ## §6 变更记录 -| 日期 | 版本 | 变更内容 | 变更人 | -| ---------- | ---- | ---------------------------------------------------------------------------------------------- | ------ | -| 2026-07-09 | v1.0 | 初版(18 RPC,2 topic) | coord | -| 2026-07-10 | v1.1 | ai09 复审:补全至 21 RPC(+ TextbookService Update/Delete + ChapterService Update/Delete + QuestionService Publish/Search);补全至 4 topic(+ Textbook/Chapter 事件);补 events.proto 4 message 草案;补 §0 状态总览 / §5 一致性核查 / §6 变更记录;明确 REST 端点为管理面(非下游契约) | ai09 | +| 日期 | 版本 | 变更内容 | 变更人 | +| ---------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | +| 2026-07-09 | v1.0 | 初版(18 RPC,2 topic) | coord | +| 2026-07-10 | v1.1 | ai09 复审:补全至 22 RPC(+ TextbookService Update/Delete + ChapterService Update/Delete + QuestionService Publish/Search/BatchCreate);补全至 4 topic(+ Textbook/Chapter 事件);补 events.proto 4 message 草案;补 §0 状态总览 / §5 一致性核查 / §6 变更记录;明确 REST 端点为管理面(非下游契约) | ai09 | +| 2026-07-13 | v1.2 | ARB-005 全部 10 项 issue 已裁决并落实;P4 就绪信号全部勾选;matrix.md 已同步(22 RPC + 4 topic);一致性核查全部 ✅ | ai09 | diff --git a/docs/architecture/issues/matrix.md b/docs/architecture/issues/matrix.md index 92d2a88..e08b550 100644 --- a/docs/architecture/issues/matrix.md +++ b/docs/architecture/issues/matrix.md @@ -34,7 +34,7 @@ graph TB CONTENT[content
ai09 :50054] MSG[msg
ai10 :50056] DATA[data-ana
ai11 :50055] - AISVC[ai
ai12 :50057] + AISVC[ai
ai12 :50058] end TP --> AGW @@ -87,10 +87,10 @@ graph TB | --------------- | --------- | --------------------------------------------------------------------------------- | ------ | ------------------------------------------- | ----------------------------- | ---- | | iam (ai06) | 50052 | IamService | 12 | teacher-bff / student-bff / parent-bff | HealthService.Check = SERVING | ⏳ | | core-edu (ai08) | 50053 | ClassService + ExamService + HomeworkService + GradeService + AttendanceService | 22 | teacher-bff / student-bff / parent-bff | HealthService.Check = SERVING | ⏳ | -| content (ai09) | 50054 | TextbookService + ChapterService + KnowledgeGraphService + QuestionService | 18 | teacher-bff / student-bff / ai | HealthService.Check = SERVING | ⏳ | +| content (ai09) | 50054 | TextbookService + ChapterService + KnowledgeGraphService + QuestionService | 22 | teacher-bff / student-bff / ai | HealthService.Check = SERVING | ✅ | | data-ana (ai11) | 50055 | AnalyticsService | 12 | teacher-bff / student-bff / parent-bff / ai | HealthService.Check = SERVING | ⏳ | | msg (ai10) | 50056 | NotificationService + NotificationPreferenceService + NotificationTemplateService | 13 | teacher-bff / push-gateway | HealthService.Check = SERVING | ⏳ | -| ai (ai12) | 50057 | AiService | 6 | teacher-bff | HealthService.Check = SERVING | ⏳ | +| ai (ai12) | 50058 | AiService | 8 | teacher-bff | HealthService.Check = SERVING | ✅ | --- @@ -106,20 +106,22 @@ graph TB ## §4 Kafka 事件发布方矩阵 -| 发布方 | Topic | Event | 消费方 | Outbox | 状态 | -| --------------- | --------------------------- | ----------------------------------------------------- | --------------------------------------------------------- | ------- | ---- | -| iam (ai06) | edu.iam.user.events | UserEvent(created/updated/deleted/role_changed) | core-edu / msg / push-gateway / teacher-bff / student-bff | ✅ | ⏳ | -| iam (ai06) | edu.iam.role.events | RoleEvent(created/updated) | core-edu / msg | ✅ | ⏳ | -| iam (ai06) | edu.iam.audit.created | AuditEvent(create/update/delete/login/logout) | teacher-bff | ✅ | ⏳ | -| core-edu (ai08) | edu.exam.events | ExamEvent(created/updated/deleted) | msg / data-ana / push-gateway | ✅ | ⏳ | -| core-edu (ai08) | edu.homework.events | HomeworkEvent(assigned/submitted/graded) | msg / data-ana / push-gateway | ✅ | ⏳ | -| core-edu (ai08) | edu.grade.events | GradeEvent(recorded/updated) | msg / push-gateway / parent-bff | ✅ | ⏳ | -| core-edu (ai08) | edu.class.events | ClassEvent(transferred) | msg / data-ana | ✅ | ⏳ | -| content (ai09) | edu.content.kp.events | KnowledgePointEvent(created/updated/prerequisite_*) | data-ana / ai / Neo4j Sync / ES Sync | ✅ | ⏳ | -| content (ai09) | edu.content.question.events | QuestionEvent(created/updated/published/deleted) | data-ana / ai / ES Sync | ✅ | ⏳ | -| msg (ai10) | edu.notification.requested | NotificationEvent(sent) | push-gateway / data-ana | ✅ | ⏳ | -| data-ana (ai11) | edu.analytics.mastery | MasteryEvent(mastery.updated / warning.triggered) | core-edu / msg | ❌ 豁免 | ⏳ | -| ai (ai12) | edu.ai.usage | AIUsageEvent(chat/generate/lesson) | data-ana | ❌ 豁免 | ⏳ | +| 发布方 | Topic | Event | 消费方 | Outbox | 状态 | +| --------------- | ---------------------------------- | ----------------------------------------------------- | --------------------------------------------------------- | ------- | ---- | +| iam (ai06) | edu.iam.user.events | UserEvent(created/updated/deleted/role_changed) | core-edu / msg / push-gateway / teacher-bff / student-bff | ✅ | ⏳ | +| iam (ai06) | edu.iam.role.events | RoleEvent(created/updated) | core-edu / msg | ✅ | ⏳ | +| iam (ai06) | edu.iam.audit.created | AuditEvent(create/update/delete/login/logout) | teacher-bff | ✅ | ⏳ | +| core-edu (ai08) | edu.exam.events | ExamEvent(created/updated/deleted) | msg / data-ana / push-gateway | ✅ | ⏳ | +| core-edu (ai08) | edu.homework.events | HomeworkEvent(assigned/submitted/graded) | msg / data-ana / push-gateway | ✅ | ⏳ | +| core-edu (ai08) | edu.grade.events | GradeEvent(recorded/updated) | msg / push-gateway / parent-bff | ✅ | ⏳ | +| core-edu (ai08) | edu.class.events | ClassEvent(transferred) | msg / data-ana | ✅ | ⏳ | +| content (ai09) | edu.content.textbook.events | TextbookEvent(created/updated/published/archived) | data-ana / msg | ✅ | ✅ | +| content (ai09) | edu.content.chapter.events | ChapterEvent(created/updated/deleted) | data-ana | ✅ | ✅ | +| content (ai09) | edu.content.knowledge_point.events | KnowledgePointEvent(created/updated/prerequisite_*) | data-ana / ai / Neo4j Sync / ES Sync | ✅ | ✅ | +| content (ai09) | edu.content.question.events | QuestionEvent(created/updated/published/deleted) | data-ana / ai / ES Sync | ✅ | ✅ | +| msg (ai10) | edu.notification.requested | NotificationEvent(sent) | push-gateway / data-ana | ✅ | ⏳ | +| data-ana (ai11) | edu.analytics.mastery | MasteryEvent(mastery.updated / warning.triggered) | core-edu / msg | ❌ 豁免 | ⏳ | +| ai (ai12) | edu.ai.usage | AIUsageEvent(chat/generate/lesson) | data-ana | ❌ 豁免 | ✅ | --- @@ -182,23 +184,23 @@ graph TB > 各 AI 完成模块后,在此表更新状态(⏳ 进行中 → ✅ 就绪) -| 模块 | AI | 就绪信号 | 状态 | 完成时间 | -| -------------- | ---- | ------------------------------------------- | ---- | -------- | -| iam | ai06 | gRPC 50052 + 12 RPC + HealthService SERVING | ⏳ | - | -| api-gateway | ai01 | :8080 可访问 + JWT 验签 | ⏳ | - | -| teacher-bff | ai03 | POST /graphql + 5 Query | ⏳ | - | -| teacher-portal | ai13 | :4000 可访问 + 登录→Dashboard | ⏳ | - | -| core-edu | ai08 | gRPC 50053 + 22 RPC + HealthService SERVING | ⏳ | - | -| content | ai09 | gRPC 50054 + 18 RPC + HealthService SERVING | ⏳ | - | -| msg | ai10 | gRPC 50056 + 13 RPC + HealthService SERVING | ⏳ | - | -| data-ana | ai11 | gRPC 50055 + 12 RPC + HealthService SERVING | ⏳ | - | -| ai | ai12 | gRPC 50057 + 6 RPC + HealthService SERVING | ⏳ | - | -| student-bff | ai04 | POST /graphql + Dashboard Query | ⏳ | - | -| parent-bff | ai05 | POST /graphql + Dashboard Query | ⏳ | - | -| push-gateway | ai02 | :8081 可访问 + /internal/push | ⏳ | - | -| student-portal | ai14 | :4001 可访问 + MF Remote | ⏳ | - | -| parent-portal | ai15 | :4002 可访问 + MF Remote | ⏳ | - | -| admin-portal | ai16 | :4003 可访问 + MF Remote + admin | ⏳ | - | +| 模块 | AI | 就绪信号 | 状态 | 完成时间 | +| -------------- | ---- | ------------------------------------------- | ---- | ---------- | +| iam | ai06 | gRPC 50052 + 12 RPC + HealthService SERVING | ⏳ | - | +| api-gateway | ai01 | :8080 可访问 + JWT 验签 | ⏳ | - | +| teacher-bff | ai03 | POST /graphql + 5 Query | ⏳ | - | +| teacher-portal | ai13 | :4000 可访问 + 登录→Dashboard | ⏳ | - | +| core-edu | ai08 | gRPC 50053 + 22 RPC + HealthService SERVING | ⏳ | - | +| content | ai09 | gRPC 50054 + 18 RPC + HealthService SERVING | ⏳ | - | +| msg | ai10 | gRPC 50056 + 13 RPC + HealthService SERVING | ⏳ | - | +| data-ana | ai11 | gRPC 50055 + 12 RPC + HealthService SERVING | ⏳ | - | +| ai | ai12 | gRPC 50058 + 8 RPC + HealthService SERVING | ✅ | 2026-07-13 | +| student-bff | ai04 | POST /graphql + Dashboard Query | ⏳ | - | +| parent-bff | ai05 | POST /graphql + Dashboard Query | ⏳ | - | +| push-gateway | ai02 | :8081 可访问 + /internal/push | ⏳ | - | +| student-portal | ai14 | :4001 可访问 + MF Remote | ⏳ | - | +| parent-portal | ai15 | :4002 可访问 + MF Remote | ⏳ | - | +| admin-portal | ai16 | :4003 可访问 + MF Remote + admin | ⏳ | - | --- diff --git a/docs/architecture/issues/objections/content_issue.md b/docs/architecture/issues/objections/content_issue.md index d963462..64fb5f9 100644 --- a/docs/architecture/issues/objections/content_issue.md +++ b/docs/architecture/issues/objections/content_issue.md @@ -171,7 +171,7 @@ N1-N5 与 C2/C4/C10 共 8 项已有仲裁**全部在 02-architecture-design.md --- -## §2 待 coord 仲裁项汇总 +## §2 仲裁项汇总(ARB-005 全部已裁决,2026-07-10) | # | 标题 | 阻塞性 | 状态 | | --- | ---------------------------------------- | ------------------- | ------ | diff --git a/docs/architecture/issues/worklines/content_workline.md b/docs/architecture/issues/worklines/content_workline.md index 2d28c92..2c5d12f 100644 --- a/docs/architecture/issues/worklines/content_workline.md +++ b/docs/architecture/issues/worklines/content_workline.md @@ -3,7 +3,7 @@ > 负责人:ai09 > 关联:[workline.md](../workline.md)、[coord.md](../coord.md)、[contracts/content_contract.md](../contracts/content_contract.md)、[objections/content_issue.md](../objections/content_issue.md)、[../../services/content/docs/02-architecture-design.md](../../../services/content/docs/02-architecture-design.md) > 模式:全并行(各 AI 一口气完成 P2-P6 全部代码,最后统一集成测试) -> 当前分支:`feat-review-content-module-docs-WAIyMA` +> 当前分支:main(trunk-based,ARB-005 §5.3 裁决) --- @@ -12,14 +12,17 @@ content 是内容资源中台服务(P4 阶段),承载 D4 内容资源限界上下文,提供 Textbook / Chapter / KnowledgePoint / Question 四个聚合的 CRUD 与知识图谱查询。 **关键交付**: + - gRPC 50054 + 4 Service(Textbook/Chapter/KnowledgeGraph/Question),按 [coord-final-decisions.md §3.3](../../coord-final-decisions.md) N1/N3/N5 仲裁,P4 首次实现即启用 gRPC + 补全 QuestionService/ChapterService proto - MySQL 写模型 + Neo4j 知识图谱 + Outbox 事件驱动异步同步(禁止业务事务内同步双写 Neo4j) -- Kafka 发布 `edu.content.knowledge_point.events` / `edu.content.question.events`(聚合 topic 策略,待 ISSUE-002 仲裁) +- Kafka 发布 4 个聚合 topic(ARB-005 §5.3 裁决):`edu.content.textbook.events` / `edu.content.chapter.events` / `edu.content.knowledge_point.events` / `edu.content.question.events` - P5 引入 Elasticsearch 全文检索 + AI 出题入库(QuestionService.BatchCreateQuestions) - P6+ 长远演进:教材版本管理 / 跨租户内容共享 / 个性化学习路径推荐 **关键路径位置**:批次 3(P4),依赖批次 2 core-edu 完成(实际可并行:content 不强依赖 core-edu) +**当前进度**:✅ P4 全部完成(14/14 任务),P5/P6+ 未开始 + --- ## §2 全阶段甘特图(P4-P6) @@ -296,25 +299,25 @@ gantt ### 4.1 我依赖的上游就绪标志 -| 上游 | 就绪标志 | 必需性 | mock 策略 | -| -------------- | ----------------------------------------------------- | ---------------------- | ------------------------------------------ | -| infra | MySQL 8 / Neo4j 5 / Kafka 集群可用 | 🔴 必需 | 本地 docker-compose | -| infra | Redis 可用(P5+ 缓存用,env.ts 已预留 REDIS_URL) | 🟢 P5+ 可选 | 未配置时跳过缓存 | -| infra | Elasticsearch 8 可用(P5+) | 🟢 P5+ 必需 | 未配置时检索降级到 MySQL LIKE | -| shared-proto | content.proto / events.proto 补全 | 🔴 必需(P4.6 自身完成) | 自行修改 | -| core-edu (ai08) | gRPC 50053 启用 | 🟢 可选(content 独立) | 不依赖 core-edu 实时数据 | -| ai (ai12) | gRPC 50058 启用 | 🟢 P5 联调时必需 | grpc-mock 拦截 | +| 上游 | 就绪标志 | 必需性 | mock 策略 | +| --------------- | ------------------------------------------------- | ------------------------ | ----------------------------- | +| infra | MySQL 8 / Neo4j 5 / Kafka 集群可用 | 🔴 必需 | 本地 docker-compose | +| infra | Redis 可用(P5+ 缓存用,env.ts 已预留 REDIS_URL) | 🟢 P5+ 可选 | 未配置时跳过缓存 | +| infra | Elasticsearch 8 可用(P5+) | 🟢 P5+ 必需 | 未配置时检索降级到 MySQL LIKE | +| shared-proto | content.proto / events.proto 补全 | 🔴 必需(P4.6 自身完成) | 自行修改 | +| core-edu (ai08) | gRPC 50053 启用 | 🟢 可选(content 独立) | 不依赖 core-edu 实时数据 | +| ai (ai12) | gRPC 50058 启用 | 🟢 P5 联调时必需 | grpc-mock 拦截 | ### 4.2 我的就绪标志(供下游消费) -- [ ] **P4 就绪**: - - [ ] content gRPC 50054 启用(HealthService.Check 返回 SERVING) - - [ ] TextbookService 5 RPC 可调用(Create/Get/List/Update/Delete) - - [ ] ChapterService 5 RPC 可调用(Create/Get/List/Update/Delete) - - [ ] KnowledgeGraphService 4 RPC 可调用(GetPrerequisites/GetLearningPath/AddPrerequisite/RemovePrerequisite) - - [ ] QuestionService 7 RPC 可调用(Create/BatchCreate/Get/List/Update/Delete/Publish/Search) - - [ ] edu.content.knowledge_point.events / edu.content.question.events topic 可发布 - - [ ] /readyz 返回 DB/Neo4j/Kafka 三依赖状态 +- [x] **P4 就绪**: + - [x] content gRPC 50054 启用(HealthService.Check 返回 SERVING) + - [x] TextbookService 5 RPC 可调用(Create/Get/List/Update/Delete) + - [x] ChapterService 5 RPC 可调用(Create/Get/List/Update/Delete) + - [x] KnowledgeGraphService 4 RPC 可调用(GetPrerequisites/GetLearningPath/AddPrerequisite/RemovePrerequisite) + - [x] QuestionService 8 RPC 可调用(Create/BatchCreate/Get/List/Update/Delete/Publish/Search) + - [x] edu.content.textbook/chapter/knowledge_point/question 4 topic 可发布 + - [x] /readyz 返回 DB/Neo4j/Kafka 三依赖状态 - [ ] **P5 就绪**: - [ ] GET /questions/search 检索 API 可用(延迟 < 200ms) - [ ] QuestionService.SearchQuestions gRPC 可调用 @@ -340,14 +343,14 @@ gantt ## §5 风险与缓解 -| 风险 | 阶段 | 缓解措施 | -| ------------------------------------------ | ---- | ------------------------------------------------------------ | -| ISSUE-002 topic 策略未仲裁导致 Outbox 阻塞 | P4 | 优先推动 coord 仲裁;开发期间用 stub topic,仲裁后切换 | -| ISSUE-004 RPC 数量未仲裁导致 proto 阻塞 | P4 | 优先推动 coord 仲裁;按建议方案 21 RPC 实现,仲裁后调整 | -| Neo4j 与 MySQL 双向一致性 | P4 | Outbox 事件驱动 + 幂等去重 + consumer lag 监控 | -| ES 索引重建期间检索不可用 | P5 | alias 切换模式(双索引蓝绿) | -| AI 批量出题 CreateQuestions 高并发 | P5 | batch_size ≤ 100 + 异步队列 + 限流 | -| schema 迁移期间历史数据 created_by 缺失 | P4 | 按 ISSUE-007 方案:NULL 起步或 'system' 默认值回填 | +| 风险 | 阶段 | 缓解措施 | +| ------------------------------------------ | ---- | ------------------------------------------------------- | +| ISSUE-002 topic 策略未仲裁导致 Outbox 阻塞 | P4 | 优先推动 coord 仲裁;开发期间用 stub topic,仲裁后切换 | +| ISSUE-004 RPC 数量未仲裁导致 proto 阻塞 | P4 | 优先推动 coord 仲裁;按建议方案 21 RPC 实现,仲裁后调整 | +| Neo4j 与 MySQL 双向一致性 | P4 | Outbox 事件驱动 + 幂等去重 + consumer lag 监控 | +| ES 索引重建期间检索不可用 | P5 | alias 切换模式(双索引蓝绿) | +| AI 批量出题 CreateQuestions 高并发 | P5 | batch_size ≤ 100 + 异步队列 + 限流 | +| schema 迁移期间历史数据 created_by 缺失 | P4 | 按 ISSUE-007 方案:NULL 起步或 'system' 默认值回填 | --- @@ -355,5 +358,6 @@ gantt - 批次 3(P4):ai09 content 11 天(workline.md §1 排期 `after b2b, 11d`) - 本排期 P4 实际 21 天(含测试 + README 修正),与 workline.md 11 天存在差距 +- **更新(2026-07-13)**:P4 代码已全部完成并提交至 main 分支,ARB-005 全部 10 项 issue 已裁决并落实 - **差距原因**:workline.md §1 为 coord 初始规划(标注"ai09 接管后必须自行细化"),本文件为 ai09 细化后的实际排期 - **同步动作**:提请 coord 在 workline.md §1 更新 content 工期为 21 天(或协调压缩测试任务)