docs(asl): Upgrade Tool 3 architecture from Fan-out to Scatter+Aggregator (v2.0)

Architecture transformation:
- Replace Fan-out (Manager->Child->Last Child Wins) with Scatter+Aggregator pattern
- API layer directly dispatches N independent jobs (no Manager)
- Worker only writes its own Result row, never touches Task table (zero row-lock)
- Aggregator polls groupBy for completion + zombie cleanup (replaces Sweeper)
- Reduce red lines from 13 to 9, eliminate distributed complexity

Documents updated (10 files):
- 08-Tool3 main architecture doc: v2.0 rewrite (schema, Task 2.3/2.4, red lines, risks)
- 08d-Code patterns: rewrite sections 4.1-4.6 (API dispatch, SingleWorker, Aggregator)
- 08a-M1 sprint: rewrite M1-3 core (Worker+Aggregator), red lines, acceptance criteria
- 08b-M2 sprint: simplify SSE (NOTIFY/LISTEN downgraded to P2 optional)
- 08c-M3 sprint: milestone table wording update
- New: Scatter+Polling Aggregator pattern guide v1.1 (Level 2 cookbook)
- New: V2.0 architecture deep review and gap-fix report
- Updated: ASL module status, system status, capability layer index

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-24 22:11:09 +08:00
parent 85fda830c2
commit 371fa53956
13 changed files with 1163 additions and 597 deletions

View File

@@ -3,7 +3,7 @@
> **所属:** 工具 3 全文智能提取工作台 V2.0
> **架构总纲:** `08-工具3-全文智能提取工作台V2.0开发计划.md`
> **代码手册:** `08d-工具3-代码模式与技术规范.md`(所有代码模式均在此手册中,开发时按需查阅)
> **前置依赖:** M1 全部完成(Fan-out 管线已验证、PKB ACL 已通、纯文本提取可跑通)
> **前置依赖:** M1 全部完成(散装管线 + Aggregator 已验证、PKB ACL 已通、纯文本提取可跑通)
> **建议时间:** Week 2-38-9 天)
> **核心目标:** 接入 MinerU 视觉大模型提升表格准确率,完成前端最复杂的 HITL 审核抽屉,交付一个"完全可用"的 V1 产品。
@@ -21,19 +21,18 @@
**做什么:**
- `PdfProcessingPipeline.ts` 升级M1 的纯文本降级 → 完整双引擎流水线
- 从 PKB `storageKey` 下载 PDF Buffer → 调用 MinerU Cloud API → 返回结构化 HTML 表格
- 从 PKB `snapshotStorageKey` 下载 PDF Buffer → 调用 MinerU Cloud API → 返回结构化 HTML 表格
- **MinerU Clean Data OSS 缓存**Cache-Aside调用前先检查 `pkb/{kbId}/{docId}_mineru_clean.html`,命中则 <1 秒返回
- 注册 `asl_mineru_extract` 子队列`teamConcurrency: 2`
- Child Worker 内部通过 `pgBoss.send('asl_mineru_extract', ...)` 派发 MinerU 子任务
- Worker 内部串行 `await mineruClient.extractTables()`(无需独立子队列`teamConcurrency: 10` 即为 MinerU 隐式并发上限
**不做什么:**
- 不改 Fan-out 架构M1 已稳定)
- 不改散装架构M1 已稳定)
- 不做动态 PromptM3继续用写死的 RCT Schema
**验收标准:**
- [ ] MinerU 返回 HTML 表格,含 `<table>` + `colspan/rowspan`
- [ ] OSS 缓存命中时跳过 MinerU 调用(日志可见 "Cache hit"
- [ ] `asl_mineru_extract` 队列 `teamConcurrency: 2` 生效3 Pod 环境下全局最多 2 个并行
- [ ] `teamConcurrency: 10` 全局并发控制生效MinerU 调用受此限制
- [ ] MinerU 超时(>3min自动降级到纯文本
> 📖 缓存代码模式见架构总纲 Task 2.2
@@ -68,30 +67,30 @@
**做什么:**
- `ExtractionController.ts` 新增 SSE 端点 `GET /tasks/:taskId/stream`
- SSE 事件类型:`sync`(首帧)、`progress``log``complete``error`
- SSE 事件类型:`sync`(首帧)、`log``error`
- **首帧 sync 降级方案**`recentLogs: []`(不依赖内存 logBuffer前端检测到空日志时打印 "--- 监控已重新连接 ---"
- `ProcessingTerminal.tsx` 组件深色终端风格来源颜色区分MinerU 蓝 / DeepSeek 紫 / System 绿)
- `useExtractionLogs.ts` Hook仅驱动日志区不影响主业务流
- SSE 使用**本 Pod 内存事件**即可Worker 和 API 在同一 Pod 时日志实时可达)
**M1 已完成的不动:**
- `useTaskStatus.ts`React Query 轮询)继续驱动进度条和步骤跳转
- `useTaskStatus.ts`React Query 轮询 + groupBy 进度)继续驱动进度条和步骤跳转
- `complete` 检测完全由 React Query 轮询到 `status === 'completed'` 触发,不依赖 SSE
**[P2 可选] SSE 跨 Pod 广播 — NOTIFY/LISTEN**
> 散装架构下进度条由 React Query 轮询驱动SSE 仅为日志增强。
> 多 Pod 部署后若日志体验不佳,可后续实施 `SseNotifyBridge.ts`(代码见 08d §7.6)。
> M2 阶段不强制实施。
**验收标准:**
- [ ] SSE 连接后立即收到 `sync` 首帧
- [ ] 日志实时打字机效果(`[MinerU]``[DeepSeek]``[System]` 分色)
- [ ] SSE 断开后进度条不受影响React Query 继续轮询)
- [ ] 多 Pod 环境下 SSE 重连到其他 Pod → 显示 "监控已重新连接" 提示
- [ ] **🆕 v1.5 NOTIFY/LISTEN 跨 Pod 实时日志:** Worker 在 Pod B 提取 → Pod A 的 SSE 客户端能实时收到日志
**🆕 v1.5 额外任务SSE 跨 Pod 广播 — NOTIFY/LISTEN含在 M2-3 工期内):**
- `SseNotifyBridge.ts`Pod 启动时创建独立 PgClient 长连接(不从连接池借),执行 `LISTEN asl_sse_channel`
- 收到 NOTIFY 后检查本机是否有该 `taskId` 的 SSE 客户端,有则推送,无则静默忽略
- `ExtractionChildWorker` 中替代 `sseEmitter.emit()`:改用 `prisma.$executeRawUnsafe('NOTIFY asl_sse_channel, ...')`
- `complete` 事件同样走 NOTIFY 广播,确保"Last Child Wins"翻转后所有 Pod 收到
- [ ] 多 Pod 环境下 SSE 重连到其他 Pod → 显示 "监控已重新连接" 提示(本 Pod 无历史日志时)
> 📖 双轨制架构见架构总纲 Task 4.1
> 📖 SSE Hydration 降级见架构总纲 Task 2.4 补丁 2
> 📖 NOTIFY/LISTEN 代码模式见 08d §7.6
> 📖 SSE 降级方案见架构总纲 Task 2.4
> 📖 [P2 可选] NOTIFY/LISTEN 代码模式见 08d §7.6
---
@@ -159,7 +158,7 @@
- Step 1 → Step 2 → Step 3 完整流程走通(含 MinerU + 审核抽屉 + Excel
- fuzzyQuoteMatch 边界测试(连字符替换、空格差异、换行吞掉)
- 断点恢复测试(关闭浏览器 → 重新打开 → 恢复正确步骤)
- Fan-out 10 篇并发提取压力测试
- 散装 10 篇并发提取压力测试
**验收标准:**
- [ ] 8 篇测试 PDF 全链路跑通PKB → MinerU + LLM → 抽屉审核 → Excel 导出
@@ -172,12 +171,13 @@
```
✅ M1 全部 +
✅ MinerU 表格引擎 + OSS 缓存
✅ MinerU 表格引擎 + OSS 缓存Worker 内部串行调用)
✅ XML 隔离 Prompt + 表格优先级
✅ fuzzyQuoteMatch 三级置信度验证
✅ SSE 终端日志双轨制React Query 主驱 + SSE 日志增强 + NOTIFY/LISTEN 跨 Pod 广播
✅ SSE 终端日志双轨制React Query 轮询主驱 + SSE Pod 日志增强
✅ 完整审核抽屉Collapse + Quote + HITL 解锁 + 签名 URL
✅ Excel 宽表导出
⏳ [P2 可选] SSE NOTIFY/LISTEN 跨 Pod 广播(多 Pod 部署后按需实施)
❌ 无自定义字段(仅系统基座模板)
❌ 无 Prompt 注入防护(无用户输入,不需要)
❌ 无 E2E 自动化测试