From 45467558ab0ea12dc904b913edfa75d97096aca9 Mon Sep 17 00:00:00 2001 From: Stev_Wang <304865932@qq.com> Date: Thu, 5 Nov 2026 11:41:26 +0800 Subject: [PATCH] =?UTF-8?q?docs(plan):=20A6=20=E5=AE=9E=E6=96=BD=E6=8A=A5?= =?UTF-8?q?=E5=91=8A=E4=B8=8E=E8=AE=A1=E5=88=92=E5=9B=9E=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 背景:A6 全部 WBS 与门禁完成,按文档规范同批更新实现记录与计划状态。 改动: - 新增 docs/开发计划/灵犀_A6任务中心与队列骨架_实施报告_V0.1.md:范围与完成度、交付物、门禁结果、关键口径(202 / 幂等 / 取消重试 / SSE / 状态机 / 队列物理名 / Outbox 退避 / 前端预估 / 角标)、与计划差异、已知遗留与下一步。 - 开发计划:状态行与 A6 批次置为已完成、§6.7 增加执行状态与完成情况、§7.6 增加状态行、M0 清单勾选任务中心。 - README:索引新增 A6 报告,当前进度推进到 A7。 影响面:仅文档与索引;无代码行为变化。 回滚:撤销提交恢复文档。 验证:pnpm format:check 通过;报告中的门禁数据来自本批实际执行结果。 --- README.md | 3 +- ...灵犀_A6任务中心与队列骨架_实施报告_V0.1.md | 157 ++++++++++++++++++ .../灵犀_信息流素材生产平台_开发计划_V0.1.md | 11 +- 3 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 docs/开发计划/灵犀_A6任务中心与队列骨架_实施报告_V0.1.md diff --git a/README.md b/README.md index b739985..5978870 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ | **A3 报告** | [灵犀_A3客户与行业目录_实施报告_V0.1.md](docs/开发计划/灵犀_A3客户与行业目录_实施报告_V0.1.md) | V0.1 | A3 完成范围、两级行业决策、混搭 UI、测试与遗留 | | **A4 报告** | [灵犀_A4数据字典与系统配置_实施报告_V0.1.md](docs/开发计划/灵犀_A4数据字典与系统配置_实施报告_V0.1.md) | V0.1 | A4 完成范围、三层合并/配置版本、方案 A UI、测试与遗留 | | **A5 报告** | [灵犀_A5审计与日志_实施报告_V0.1.md](docs/开发计划/灵犀_A5审计与日志_实施报告_V0.1.md) | V0.1 | A5 完成范围、append-only / 检索导出 / 运行日志、A+A+C UI、测试与遗留 | +| **A6 报告** | [灵犀_A6任务中心与队列骨架_实施报告_V0.1.md](docs/开发计划/灵犀_A6任务中心与队列骨架_实施报告_V0.1.md) | V0.1 | A6 完成范围、任务协议 / 九队列 / SSE / Outbox、方案 A UI、e2e 与遗留 | | **ADR** | [docs/adr/](docs/adr/README.md) | — | 架构决策记录(ADR-001 权限;ADR-002 两级行业目录) | | 历史 PRD | `docs/PRD/灵犀_信息流素材生产平台_PRD_V0.1~V0.3.md` | 归档 | 仅作沿革参考,**不具约束力** | @@ -68,7 +69,7 @@ infra/ compose、Nginx、监控、备份 docs/ PRD / 技术架构 / 开发计划 / 立项建议 / 工程规范 ``` -当前已完成 **A0 工程骨架与契约基线**、A1 身份认证、A2 角色权限、A3 客户与行业目录、A4 数据字典与系统配置、A5 审计与日志;下一步 A6 任务中心与队列骨架。目录与依赖方向见 [AGENTS.md §5](AGENTS.md)。 +当前已完成 **A0 工程骨架与契约基线**、A1 身份认证、A2 角色权限、A3 客户与行业目录、A4 数据字典与系统配置、A5 审计与日志、A6 任务中心与队列骨架;下一步 A7 AI 配置与调用底座。目录与依赖方向见 [AGENTS.md §5](AGENTS.md)。 --- diff --git a/docs/开发计划/灵犀_A6任务中心与队列骨架_实施报告_V0.1.md b/docs/开发计划/灵犀_A6任务中心与队列骨架_实施报告_V0.1.md new file mode 100644 index 0000000..7241d9e --- /dev/null +++ b/docs/开发计划/灵犀_A6任务中心与队列骨架_实施报告_V0.1.md @@ -0,0 +1,157 @@ +# 灵犀 A6 任务中心与队列骨架 · 实施报告 V0.1 + +| 项 | 内容 | +| --- | --- | +| 批次 | A6 任务中心与队列骨架(开发计划 §6.7 / §7.6,架构 §3.6 / §3.7 / §6.4) | +| 完成日期 | 2026-11-05 | +| 状态 | ✅ 已完成(A6-BE-01~05、A6-INF-01、A6-FE-01~02、A6-QA-01 全部交付) | +| 用户选定方案 | 前端采用 **方案 A · 经典管理台**(design/a6-ui-v1/a) | +| 代码提交 | `4a29cf8`(shared 契约与数据模型)、`633765f`(API / SSE / 队列 / worker)、A6 前端提交见仓库 `feat(web)` | +| 本地依赖 | PostgreSQL 18 / Redis 7.4;`pnpm check:dev` 通过 | + +--- + +## 1 范围与完成度 + +| 编号 | 交付 | 状态 | +| --- | --- | --- | +| A6-BE-01 | 任务协议与九态状态机、`media_tasks` / `media_items` / `task_events`、提交预估、`Idempotency-Key` 24h | ✅ | +| A6-BE-02 | BullMQ 5 九队列(5 组)、worker 按 `QUEUE` 启停、重试 / 退避 / 死信 / 并发上限、Redis 锁 | ✅ | +| A6-BE-03 | SSE `/media-tasks/{id}/events`:心跳、`Last-Event-ID` 续推、进度落库、轮询兜底 | ✅ | +| A6-BE-04 | 跨类型任务列表 / 详情(客户 / 状态 / 类型 / 时间 / 我提交的 / 关键字)、取消、仅重试失败项、失败行号 | ✅ | +| A6-BE-05 | `outbox_events` 事务写入 + dispatcher 至少一次投递 + jobId 幂等 + 死信 + 本地结果事件审计 | ✅ | +| A6-INF-01 | `/api/v1/health/queues`、`/api/v1/metrics`(Prometheus 0.0.4)、4 条告警规则文件、worker 心跳 | ✅(未接真实 Grafana,见 §5) | +| A6-FE-01 | `/material/tasks`、`/material/tasks/:id`:列表 / 详情 / 提交演练任务 / 取消 / 仅重试失败项 / 三态 / 权限三态 | ✅ | +| A6-FE-02 | 可复用任务组件(类型 / 状态 / 进度条 / 进度环 / SSE 状态)、顶栏全局角标、待处理失败信号、完成 / 失败通知 | ✅ | +| A6-QA-01 | 幂等 / 取消 / 重试 / 断线续推 / 进程重启恢复 / 权限三态 / 浏览器 e2e | ✅ | + +**本批门禁对照**:提交 → SSE → 完成 / 失败闭环 ✅;幂等与取消生效 ✅;五个队列组独立启停 ✅;进度落库、刷新 / 重连 / 进程重启不丢 ✅。 + +--- + +## 2 交付物 + +### 2.1 共享契约(`packages/shared`) + +- `src/tasks/task-protocol.ts`(+ spec):任务类型、架构 §3.6 九态与允许迁移、5 组 9 队列定义(并发 / 重试 / 退避)、Outbox 事件、SSE 事件、进度与收敛纯函数。 +- `src/schemas/tasks.ts`(+ spec):提交 / 响应 / 摘要 / 详情 / 列表 query+response / 取消 / 重试 / SSE 事件载荷;body camelCase、query snake_case、列表 `{ items, next_cursor }`。 +- `src/config/system-configs.ts`:新增 `task` 分组 3 项(`task.demo.max_items=20` / `task.estimate.demo_cost_per_item=0.02` / `task.estimate.demo_seconds_per_item=3`);后两项置为 `public` 供前端提交前展示预估(PRD R-06),数值非敏感且演练任务不产生真实计费。 + +### 2.2 数据库(`prisma/`) + +- 迁移 `20261104125003_a6_media_tasks`(expand-only,未改历史迁移与旧表): + - `media_tasks`:任务头(类型 / 状态 / 客户快照 / 计数 / 预估 / 实际 / 取消与失败信息 / 时间); + - `media_items`:任务项(seq / 状态 / 失败原因码与文案 / 尝试次数 / 时间;`(task_id, seq)` 唯一); + - `task_events`:append-only 事件流(`seq BIGSERIAL` 作为 SSE id;`(task_id, seq)` 索引)。 +- 关系:任务项 / 事件 `onDelete: Cascade`(无删除任务对外入口,级联仅用于测试夹具清理;审计留痕由 append-only `audit_logs` 承担)。 + +### 2.3 后端 API(`apps/api`) + +- `modules/media/`:controller / service / repository / mapper / estimator / cursor / idempotency / SSE / 结果审计消费者,共 9 个单测 + 1 个集成测试。 +- `infra/queue/`:9 队列注册与生命周期、Outbox dispatcher(Redis 锁 + `FOR UPDATE SKIP LOCKED` + jobId 幂等 + 退避 / 死信)、`/health/queues`、`/metrics`。 +- 通用改动:`AuditInterceptor` 支持幂等重放 `skipAudit`(默认行为不变);`AppModule` 接线 `MediaModule` / `QueueModule`。 + +### 2.4 Worker(`apps/worker`) + +- `config.ts`(`QUEUE=all|分组|队列名`、并发 / workerId)、`queues.ts`、`heartbeat.ts`(30s TTL,10s 续写)、`redis-options.ts`。 +- `processors/demo.processor.ts`:事务 + 任务行锁、任务项条件认领、取消语义、非末次失败回 queued 交给 BullMQ 重试、末次失败落 failed、原子计数、`item` / `progress` / `done` 事件、收敛后写 `media.task.finished|failed` outbox;纯函数单测。 +- `main.ts`:按 `QUEUE` 建 Worker、心跳、SIGINT/SIGTERM 优雅退出并清理心跳。 + +### 2.5 前端(`apps/web`,方案 A) + +- 路由:`/material/tasks`、`/material/tasks/:id`(`material:read`;写操作按钮按 `material:render` 渲染),侧栏「生产任务」更名「任务中心」,详情面包屑补齐。 +- 页面:`pages/material/tasks/`(TasksPage / TaskDetailPage / TaskFilters / TaskTable / TaskSubmitModal / TaskConfirmModal / task-filter-utils + spec)。 +- 可复用组件:`components/tasks/`(TaskTypeTag / TaskStatusTag / TaskItemStatusTag / TaskProgressBar / TaskMiniProgress / TaskProgressRing / TaskSseIndicator / TaskBadge / useTaskStream / task-display / task-sse + spec)。 +- API / hooks:`api/media.ts`(+ spec)、`hooks/queries/use-media-tasks.ts`、`api/{endpoints,query-keys,client,query-client}.ts` 增量。 +- 样式:`styles/tasks.css`(基础组件 + 列表)、`styles/task-detail.css`(详情);全部使用 `--lx-*` token。 +- 交互:筛选 URL 双向同步(关键字 260ms 防抖)、游标「加载更多」、行点击进详情、提交演练任务(实时预估 + 复用幂等键 + 提交中禁用)、取消 / 重试二次确认、顶栏角标 + 待处理失败直达、完成 / 失败通知。 + +### 2.6 测试与监控 + +- 单元测试:shared 197、api 257、web 238、worker 27。 +- 集成测试:api 92(含 media 12、outbox / 队列端点)。 +- 浏览器 e2e:`e2e/a6-tasks.spec.ts` 6 条(真实 API + worker + PG/Redis + 浏览器,40s 左右)。 +- 监控:`infra/monitoring/queue-alerts.yml`(积压 > 10min、失败率 > 5%、心跳缺失、outbox 死信)+ `README.md`(抓取地址 / promtool 校验 / 接入步骤)。 + +--- + +## 3 验证结果 + +| 门禁 | 命令 | 结果 | +| --- | --- | --- | +| 格式 | `pnpm format:check` | ✅ | +| Lint | `pnpm lint` | ✅ 0 error / 0 warning | +| 类型 | `pnpm typecheck` | ✅ 10/10 tasks | +| 单测(shared) | `pnpm --filter @lingxi/shared test` | ✅ 18 files / 197 tests | +| 单测(api) | `pnpm --filter @lingxi/api test` | ✅ 37 files / 257 tests(lines 71%+) | +| 单测(web) | `pnpm --filter @lingxi/web test` | ✅ 37 files / 238 tests(lines 91.7%) | +| 单测(worker) | `pnpm --filter @lingxi/worker test` | ✅ 7 files / 27 tests | +| 集成(api) | `pnpm --filter @lingxi/api test:int`(停 dev 服务后) | ✅ 11 files / 92 tests | +| 构建 | `pnpm build` | ✅ 8/8 tasks | +| OpenAPI | `pnpm openapi:diff` | ✅ 无破坏性变更(新增 6 端点) | +| 浏览器 e2e | `A6_E2E=1 pnpm exec playwright test e2e/a6-tasks.spec.ts` | ✅ 6/6(约 39s,连跑多次稳定) | + +**e2e 覆盖**: +① 提交混合模式 → 列表出现 → 顶栏角标面板 → 详情 SSE 推进到「部分失败」→ 仅重试失败项; +② 提交 20 项后立即取消 → 已取消、未开始项跳过; +③ 同 `Idempotency-Key` 同 body 返回同一任务、不同 body 40902(API 断言); +④ SSE `Last-Event-ID` 续推首帧 seq 更大、不重发历史; +⑤ 仅 `material:read`:不渲染提交 / 取消 / 重试,保留查看与只读提示; +⑥ 无 `material:read`:访问 `/material/tasks` → `/403`。 + +**真实画面证据**(真实 API + worker,1440×900 / 1024×900):`design/a6-ui-v1/shots/impl/real/`(列表、1024、提交弹层、角标面板、详情进行中 / 部分失败 / 待预览、重试确认、只读列表 / 详情)。独立视觉评审 7/10,按评审意见完成两轮修正:失败数进入角标与 1024 首屏、部分失败首屏头条改为「失败 N / M 项已处理」、去除工程化文案与禁用入口、状态色 / 图标统一、行高与表格撑满、重复入口与计数去重。 + +--- + +## 4 关键口径与实现说明 + +1. **提交 = 202**:按工程规范 04 §1/§6,异步任务提交返回 `202`;幂等重放同为 202 且返回同一 `taskId`。取消 / 重试是同步状态迁移,返回 201。 +2. **幂等**:`Idempotency-Key` 8–128 可见 ASCII;指纹 `sha256(actorId + 规范化 body)`;24h;同 key 同 body 返回首次响应且**不重复写审计 / outbox / 任务行**(`skipAudit`),不同 body 40902;并发由 `(scope,key)` 唯一约束兜底。 +3. **取消**:仅排队 / 生成中;条件 UPDATE 认领;排队项 → 已跳过,执行中的项完成;无运行项时立即收敛为已取消,有运行项时交 worker 收敛。已成功项不受影响。 +4. **仅重试失败项**:仅「部分失败」;失败项重置为排队、attempts 保留、失败原因清空;任务回到排队,成功项不重复执行。 +5. **SSE**:`Authorization` 头鉴权(前端 fetch 流,不用 EventSource);`id` = `task_events.seq`;800ms 落库轮询事件、15s 心跳、单轮 200 条;`Last-Event-ID` 优先于 `last_event_id`;终态补发 `done` 后关闭;前端重连 2 次失败后降级 5s 轮询(状态提示可见)。 +6. **状态机**:完整九态与迁移表;M0 演练任务点亮排队 / 生成中 / 部分失败 / 待预览 / 失败 / 已取消;成功终态为「待预览」(B3 接入产物后点亮勾选 / 导出 / 入库)。 +7. **任务标题**:后端生成 `{类型} · {客户} · N 项` 快照;前端列表 / 角标去掉类型前缀(类型已有独立标签),详情标题同理。 +8. **队列物理名**:BullMQ 5 禁止队列名 / jobId 含 `:`,逻辑队列名(`media:verify` 等,用于指标 / 心跳 / `QUEUE` env)与物理名(`media-verify`)一对一映射,协议与监控口径不变。 +9. **Outbox 退避**:`outbox_events` 无 `next_attempt_at`,失败时把 `occurred_at` 重置为失败时刻作为退避起点;`canceled` 事件直接置已投递(worker 以 DB 状态感知),`finished|failed` 永不认领(media 本地消费者写审计)。 +10. **前端预估**:读 `/system/configs/effective` 的 `task.*`(已置 public);缺失时回退 shared 定义默认值做展示兜底,后端仍最终校验与计算。 +11. **全局角标**:数字 = 排队 + 生成中;有待处理失败时显示红点与「待处理失败 N 项,去处理」(直达失败筛选);1024 页头保留「待处理失败」一条关键统计。 +12. **完整任务号**:后端无独立任务编号字段,UI 展示 `T-` + ULID 末 6 位,详情可复制完整 ID。 + +--- + +## 5 与计划的差异与待确认 + +| 编号 | 项 | 现状 / 决策 | +| --- | --- | --- | +| A6-D-01 | A5 审计导出迁移 | 本轮**未迁移**(用户确认):A5 `AuditExportJob` 保持 `setImmediate`,B3 导出统一接入任务协议时迁移;A5 报告中的下一步顺延到 B3。 | +| A6-D-02 | 队列物理名 | BullMQ 5 禁止冒号 → 物理名连字符、逻辑名保留冒号;已写入代码注释、infra README 与本报告。 | +| A6-D-03 | Outbox 退避 | 复用 `occurred_at` 作为退避起点,无 schema 变更;代价是首次投递最多 ~1.5s 固有延迟。 | +| A6-D-04 | 状态迁移补充 | 增加 `partial_failed → queued`(重试)与 `running → failed`(全部失败直接收敛)两条工程补充,单测覆盖,不改变 §3.6 九态枚举。 | +| A6-D-05 | 重试与历史失败原因 | 任务项重试后清空 failureCode / failureMessage(详情展示最新状态);历史由 append-only `task_events` / `audit_logs` 保留。 | +| A6-D-06 | 9 队列范围 | 采用 `script:generate / image:matting / image:render / video:keyframe / video:shot / video:compose / delivery:zip / export:package / media:verify`;架构中 `media:post` / `embed:index` 不在本批 9 队列内(M1/M3 再启用)。 | +| A6-D-07 | 监控基建 | 本机无 Prometheus / Grafana:交付指标端点、健康检查、告警规则文件与接入说明,未接真实 Grafana。 | +| A6-D-08 | 任务中心路由 | 采用工程规范 11 的 `/material/tasks`(计划 §7.6 `/tasks` 视为简写);权限复用 `material:read` / `material:render`(DP-01,不新增 `task:*`)。 | +| A6-D-09 | 单任务项重试 | 本批只提供「仅重试失败项」批量入口,不提供单项重试(计划未要求;B3 快筛 / M1 重试可按需追加)。 | +| A6-D-10 | 任务提交演练入口 | M0 真实任务未建设,按用户确认提供「提交演练任务」(`material:render`);B3 / M1 接入真实任务后下线演练入口。 | + +--- + +## 6 已知遗留 + +1. **真实任务类型**:图片 / 视频 / 脚本 / 导出 / 校验任务与产物、勾选、导出、入库由 B3 / M1 / M2 接入;当前九态中「已勾选 / 已导出 / 已入库」仅契约保留。 +2. **审计导出迁移**:A5 审计导出仍走 `setImmediate`,B3 统一迁移到 A6 任务协议(含对象存储与并发限流)。 +3. **可观测**:OTel SDK(新增依赖待评审)未接入;Grafana 告警规则文件未在本机加载验证;任务成功率 / 成本看板在 M2 / M4。 +4. **SSE 扩展性**:当前每连接 800ms DB 轮询 + 15s 心跳,100 人规模足够;若任务事件量增大应改为 Redis pub/sub 或 Postgres LISTEN/NOTIFY。 +5. **任务数据清理**:`task_events` / `media_tasks` 无归档与保留期策略(后续与 A5 保留策略一并定)。 +6. **单项重试 / 批量取消**:本批未提供(见 A6-D-09)。 +7. **演练任务成功终态**:M0 演练任务成功收敛到「待预览」,不含产物与快筛;接口与 UI 已注明快筛后续开放。 + +--- + +## 7 下一步 + +- 按计划进入 **A7 AI 配置与调用底座**(A6 的 Outbox / 任务协议 / 审计可直接复用)。 +- B3 导出接入时:迁移 A5 审计导出、接通对象存储签名 URL、补充导出任务类型与进度。 +- M1 接入图片 / 视频真实任务:产物表、快筛勾选、单镜替换、断点续跑在既有任务协议上扩展。 +- 运维:Prometheus / Grafana 接入 `infra/monitoring/queue-alerts.yml`,补齐队列积压与失败率看板。 diff --git a/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md b/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md index 1e0472b..23f355e 100644 --- a/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md +++ b/docs/开发计划/灵犀_信息流素材生产平台_开发计划_V0.1.md @@ -10,7 +10,7 @@ | 文档名称 | 灵犀 · 信息流素材生产平台 项目开发计划 | | 版本 | V0.1(初稿,待评审) | | 日期 | 2026-11-02 | -| 状态 | **执行中**:A0 工程骨架与契约基线已完成(2026-11-02);A1 身份认证与用户管理已完成(2026-11-03);A2 角色权限与数据范围已完成(2026-11-03);A3 客户与行业目录已完成(2026-11-04 最终验收);A4 数据字典与系统配置已完成(2026-11-04);A5 审计与日志已完成(2026-11-04);下一步 A6 | +| 状态 | **执行中**:A0 工程骨架与契约基线已完成(2026-11-02);A1 身份认证与用户管理已完成(2026-11-03);A2 角色权限与数据范围已完成(2026-11-03);A3 客户与行业目录已完成(2026-11-04 最终验收);A4 数据字典与系统配置已完成(2026-11-04);A5 审计与日志已完成(2026-11-04);A6 任务中心与队列骨架已完成(2026-11-05);下一步 A7 | | 需求基线 | PRD V1.6([灵犀-信息流广告素材一站式生产平台PRD.md](../PRD/灵犀-信息流广告素材一站式生产平台PRD.md)) | | 技术基线 | 技术架构 V0.4([灵犀_信息流素材生产平台_技术架构_V0.1.md](../技术架构/灵犀_信息流素材生产平台_技术架构_V0.1.md))+ `AGENTS.md` V1.0 + `docs/工程规范/` V1.0 | | 覆盖范围 | **M0 任务级;M1–M4 迭代级 + 任务组级;M5 预研边界(不排期)** | @@ -385,7 +385,7 @@ flowchart LR | **A3** | ✅ 已完成 | 客户与行业目录 | A1 / A2 | 7 | 4–5 日 | W2 | 行业 / 客户 / 客户组可用;唯一性;状态只读;字段审批 | | **A4** | ✅ 已完成 | 数据字典与系统配置 | A3 | 4 | 3–4 日 | W3 | 三层合并;编码不可改;阈值同源;配置版本 + 审计 | | **A5** | ✅ 已完成 | 审计与日志 | A1 / A4 | 4 | 3–4 日 | W2–W3 | 关键操作全留痕;不可篡改;导出自身审计 | -| **A6** | 未开始 | 任务中心与队列骨架 | A0 / A1 | 6 | 4–5 日 | W2–W3 | 提交 → SSE → 完成 / 失败;幂等;取消 / 重试 | +| **A6** | ✅ 已完成 | 任务中心与队列骨架 | A0 / A1 | 6 | 4–5 日 | W2–W3 | 提交 → SSE → 完成 / 失败;幂等;取消 / 重试 | | **A7** | 未开始 | AI 配置与调用底座 | A0 / A1 / A5 | 6 | 4–5 日 | W3 | 四层配置;Mock 调用;密钥不泄露;账本可查 | | **B0** | 未开始 | 行业包与表单设计器 | A3 / A4 | 8 | 6–7 日 | W4 | 电商行业包 v1;七项校验;双人发布;快照 | | **B1** | 未开始 | 资产与模板最小集 | A3 / A5 | 6.5 | 5–6 日 | W4 | 15 类资产;引用保护;PSD 图层校验 | @@ -641,6 +641,8 @@ PRD §7 把 **M-27(素材元素级拆解)** 与「自动字幕 → TTS 配 **目标**:所有耗时操作走统一任务协议,前端有统一进度体验。**对应**:架构 §6.4 / §3.3;M-05;`D-02` / `D-08`。 +> **执行状态:✅ 已完成(2026-11-05)**。以下 9 项 WBS 全部交付并实测;前端按用户选定 **方案 A · 经典管理台** 落地;实现记录、验收证据与遗留见 [A6 实施报告](./灵犀_A6任务中心与队列骨架_实施报告_V0.1.md)。 + | 编号 | 任务 | 端 | 内容与产出 | 依赖 | 验收要点 | EPD | | --- | --- | --- | --- | --- | --- | --- | | A6-BE-01 | 任务协议与状态机 | BE | `media_tasks` / `media_items` 基表;状态机**对齐架构 §3.6 九态**(排队 / 生成中 / 部分失败 / 待预览 / 已勾选 / 已导出 / 已入库 / 失败 / 已取消),M0 先点亮排队 / 生成中 / 部分失败 / 失败 / 已取消,其余状态由 B3 / M1 点亮;提交返回 `{taskId, estimatedItems, estimatedCost, estimatedSeconds}`;`Idempotency-Key` 24 小时去重 | A0-BE-02、A0-SH-01 | 重复提交返回同一任务;缺预估字段拒绝提交;状态枚举与架构 §3.6 一致;流转有单测 | 1.0 | @@ -655,6 +657,8 @@ PRD §7 把 **M-27(素材元素级拆解)** 与「自动字幕 → TTS 配 **本批门禁**:提交 → SSE → 完成 / 失败闭环;幂等与取消生效;队列隔离;进度落库可恢复。 +> **A6 完成情况(2026-11-05)**:9/9 项 WBS 全部 ✅。统一任务协议(架构 §3.6 九态 / 5 组 9 队列 / SSE 事件 / Outbox)、`media_tasks` / `media_items` / `task_events` 三表、提交(202 + Idempotency-Key 24h 去重 + 预估)、跨类型列表 / 详情(筛选 + 游标分页)、SSE(Last-Event-ID 续推 + 心跳 + 落库轮询)、取消(只影响未开始项)、仅重试失败项、BullMQ 九队列 / Outbox dispatcher / 演练 worker / 队列健康与 Prometheus 指标全部落地;前端按用户选定 **方案 A** 实现 `/material/tasks`、`/material/tasks/:id`,含可复用进度组件、顶栏全局角标与待处理失败信号、提交 / 取消 / 重试确认。门禁:`format:check / lint / typecheck` 全绿,单测 shared 197 / api 257 / web 238 / worker 27,`test:int` 92(含 media 12),`build` 8/8,`openapi:diff` 无破坏性变更,A6 浏览器 e2e 6/6(约 39s)。已知遗留:A5 审计导出仍待 B3 迁移、真实任务类型与产物待 B3 / M1、Prometheus/Grafana 未接真实告警、OTel 未接。实现记录与偏差见 [A6 实施报告](./灵犀_A6任务中心与队列骨架_实施报告_V0.1.md)。 + ### 6.8 A7 AI 配置与调用底座 **目标**:四层配置可管、密钥安全、Mock 可跑通、调用有账本。**对应**:P-08、PRD §5.4.4;`R-23`;架构 §2.6 / §7.7;`D-10` 前置。 @@ -986,6 +990,7 @@ PRD §7 把 **M-27(素材元素级拆解)** 与「自动字幕 → TTS 配 | 项 | 内容 | | --- | --- | +| 状态 | ✅ 已完成(2026-11-05);实现记录见 [A6 实施报告](./灵犀_A6任务中心与队列骨架_实施报告_V0.1.md) | | 页面 | `/tasks`(跨类型任务中心)、`/tasks/:id`(进度 / 逐项 / 失败明细 / 重试 / 取消) | | 接口 | `POST /media-tasks`、`GET /media-tasks`、`/media-tasks/{id}`、`GET /media-tasks/{id}/events`(SSE)、`POST /media-tasks/{id}/cancel`、`POST /media-tasks/{id}/retry` | | 关键规则 | 提交必带 `Idempotency-Key`;必须返回预估条数 / 成本 / 时长,缺一不可提交;状态机统一;进度落库、进程重启不丢;取消只影响未开始项;重试只重失败项;队列分组隔离,视频积压不拖垮脚本 | @@ -1253,7 +1258,7 @@ infra/:compose、Nginx、监控、备份脚本占位 - [x] 系统配置单一来源、阈值 / 上限同源、配置版本与变更记录可用; - [ ] 审计七类关键动作留痕、只读、导出留痕; - [ ] AI 四层配置 + Mock 全链路 + 密钥不回显; -- [ ] 任务中心可查 / 可取消 / 可重试,幂等生效; +- [x] 任务中心可查 / 可取消 / 可重试,幂等生效; - [ ] 行业包 v1(电商)草稿 → 校验 → 审核 → 发布; - [ ] 资产包上传 / 版本 / 停用 / 引用保护; - [ ] 要素卡与脚本模板可用,表单设计器 14 类字段可用;