- pnpm workspace: apps/{web,server}, packages/{contracts,db,domain,adapters,tasks,agent,testkit}
- server: Hono + zod-openapi, API Key auth with scopes, redacting pino logger, SSE event bus with replay, worker heartbeat
- db: Kysely + pg, file migrator, 0001_init (settings/api_key/audit_event/outbox_event)
- web: React Router 7 SPA console shell with 12 workspace placeholders, uhd_web tokens/ui/guard scripts
- docs: ADR-001 (Node over Deno), dev runbook, design system rules
Co-Authored-By: Claude Fable 5.1 <[email protected]>
76 lines
9.9 KiB
Markdown
76 lines
9.9 KiB
Markdown
# 首个可用版本(v0.1)工程规划
|
|
|
|
编制:2026-09-27。需求基线:`../../media_automation_requirements_architecture_v0.7.md`(下称 REQ)。本文件是所有开发子任务的统一任务书;与 REQ 冲突时以 REQ 的产品要求为准,技术选型以本文件为准。
|
|
|
|
## 1. 技术决策(ADR 摘要,详见 docs/adr/)
|
|
|
|
| 项 | 决定 | 说明 |
|
|
| --- | --- | --- |
|
|
| 运行时 | **Node.js 24 LTS + pnpm workspace**,TypeScript 5.9 strict | 用户指定沿用 /opt/uhd_web 技术栈;开发机无 Deno。REQ §9 允许"有明确依赖障碍时评估替代并记录代价"。ADR-001 记录此偏离。 |
|
|
| 前端 | React 19 + React Router 7(SPA, `ssr:false`)+ Vite 7 + Tailwind v4 + shadcn(new-york, radix-ui 统一包)+ TanStack Query 5 + zod 4 + sonner + lucide | 直接拷贝 uhd_web 的 `app/app.css` 设计 token、`app/components/ui/*`、`app/lib/api.ts`、`app/lib/utils.ts`、`scripts/gen-design-tokens.mjs`、`scripts/check-design-tokens.sh`、`docs/features/{design-tokens,interface-materials,ui-controls}.md`。**不引入 uhd_web 的播放器/WASM 相关内容。** |
|
|
| 后端 HTTP | Hono 4(`@hono/node-server`),REST + SSE | OpenAPI 由 zod schema 生成(`@hono/zod-openapi`)。 |
|
|
| 数据库 | PostgreSQL 16;Kysely + pg;SQL 迁移文件 + Kysely Migrator;`kysely-codegen` 或手写 DB 类型 | 开发用 docker-compose 起 `postgres:16-alpine`,端口 55433。 |
|
|
| 持久任务引擎 | 优先 `[email protected]`(peer: postgres.js);**须先通过 spike 验证**(重启恢复/等待信号/取消/重试)。未通过则用 `packages/tasks` 内的 PG 租约式任务表(lease + attempts + dead-letter)。 | 结论写 ADR-002。 |
|
|
| Agent 内核 | `@earendil-works/[email protected]` + `@earendil-works/[email protected]`,锁版本;通过自有 `AgentRuntimePort` 封装,显式工具白名单,不开放 bash/文件系统/任意网络 | 测试用脚本化 fake 模型 provider;真实上游由设置页配置。 |
|
|
| 校验/测试 | vitest(server/packages 单元 + 集成);web 沿用 token 守卫脚本;biome 做 lint/format | `pnpm ci` = typecheck + lint + test + check:tokens + build |
|
|
| 端口 | web dev 5180,API 4380,PG 55433 | 本机 3000/5175/5176/55432 已被占用,不要用 |
|
|
| 参考源码 | MoviePilot: `/opt/moviepilot-plus/upstream/MoviePilot`(GPLv3,只做行为对照与 TS 重写,不复制文件);MovieClaw 若本机不存在则按 REQ 附录链接对照 | 迁移对照记录写 `docs/porting/` |
|
|
|
|
## 2. 仓库结构(pnpm monorepo)
|
|
|
|
```
|
|
apps/web React Router 7 SPA 控制台(复用 uhd_web 设计系统)
|
|
apps/server Node 服务:HTTP API + SSE + worker 入口(单进程可跑,也可 `--role api|worker` 分开)
|
|
packages/contracts zod schema + 类型:所有 API/事件/能力(capability)输入输出的唯一定义,web 与 server 共用
|
|
packages/db Kysely 类型、迁移、仓储辅助
|
|
packages/domain 纯业务逻辑(无 IO):标题解析/身份匹配/Slot 满足度/路径绑定/整理计划/策略评估
|
|
packages/adapters 外部系统适配:qBittorrent、RSS、站点(观众 NexusPHP / 馒头 API)、TMDB、Emby 兼容、文件系统
|
|
packages/tasks 持久任务定义与执行器(OpenWorkflow 或自研租约表),outbox
|
|
packages/agent Pi 接入:AgentRuntimePort、能力注册中心桥接、agent_run 持久化、fake provider
|
|
packages/testkit mock 服务:mock qB WebUI、mock NexusPHP 站点、mock M-Team API、mock RSS、mock TMDB、临时目录夹具
|
|
docs/adr 架构决策记录
|
|
docs/plan 本规划与里程碑验收清单
|
|
docs/porting MoviePilot/MovieClaw 迁移对照账本(REQ §14.1.2 格式)
|
|
docs/spikes 兼容性验证记录
|
|
docs/runbook 启动/备份/恢复/配置说明
|
|
scripts dev/ci 辅助脚本
|
|
```
|
|
|
|
约定:
|
|
- 所有共享类型只在 `packages/contracts` 定义;web 不得手写与 server 重复的 DTO。
|
|
- `packages/domain` 不 import 任何 IO 库,100% 可单元测试。
|
|
- 每个包有 `src/index.ts` 作为唯一公开入口;跨包只通过入口引用。
|
|
- 命名:表名 snake_case 与 REQ §12 实体名一致;TS 类型 PascalCase;能力 ID 用 `域.动作`(如 `download.submit`)。
|
|
- 提交:conventional commits(`feat(server): ...`),每个子任务结束前 `pnpm ci` 必须绿再提交。
|
|
- 凭证一律 secret reference(`secret_ref` 列 + 加密存储),日志/错误/模型上下文脱敏;含 passkey 的 URL 不得进入日志。
|
|
|
|
## 3. v0.1 范围(= REQ M0 + M1 纵切,可在无真实 PT 账号下用 mock 全链路验证)
|
|
|
|
### 3.1 必做
|
|
1. **底座**:monorepo、配置(env + settings 表)、迁移、API Key 鉴权(scope:read/organize.read/organize.execute/admin)、审计日志 `audit_event`、SSE 事件流(带序号可补读)、全局"自动化总开关"。
|
|
2. **数据模型**(REQ §12 子集,表名照抄):media_entity、content_unit、external_identity、identity_revision、title_alias、media_asset、asset_location、path_binding、library_root、site_account、feed_source、observation、source_release、subscription、policy_revision、acquisition_slot、preference_tag、preference_suppression、acquisition_plan、download_task、asset_operation、decision、approval、automation_grant、agent_run、artifact、audit_event、outbox_event、reconcile_run、server_mapping、api_key、organization_record、organization_file_result、downloader_instance、media_server_instance、settings。
|
|
3. **来源**:多 RSS 抓取(ETag/Last-Modified、重叠窗口、GUID+摘要去重、退避/熔断、passkey 脱敏)、观众(NexusPHP 列表/详情/下载,参考 MovieClaw audiences.yaml 结构)与馒头(API Key)两类站点适配器、站点快照缓存 + 实时补查 + 站点启停 + 站点级限流。
|
|
4. **身份与元数据**:发布标题解析(对照 MP MetaInfo 行为:标题/年份/季集/分辨率/来源/编码/发布组/版本)、TMDB 查询与缓存、本地实体优先 + external_identity 映射(provider+type+id 唯一)、title_alias 模糊召回(pg_trgm)、临时 content_unit、待识别池。
|
|
5. **规则与选片**:subscription(单次/持续追踪)、acquisition_slot(硬条件/软偏好/升级阈值/完成条件,状态机 empty→reserved→downloading→verifying→satisfied/upgrade_pending/attention)、确定性 evaluateAcquisition(不含 Agent 主观选片,只留接口)、每日预算与并发限制、优先级(即时>追更>新作品>升级)。
|
|
6. **下载**:qB WebUI 适配(多实例、管理标签、提交/接管/查询/暂停恢复)、缓存卷硬阈值与恢复水位(暂停范围仅限纳管任务)、download_task 状态机、无进展只记录不换源。
|
|
7. **入库**:verifyAndImport → Copy/Move(临时文件+校验+提交;跨卷 Copy→核验→删源;EXDEV 不静默降级)、路径绑定固定(已绑定目录不因译名变化改变)、organization_record + 文件级结果、**公开整理记录 API**(API Key、游标增量)。
|
|
8. **持久任务**:ingestFeed、resolveObservation、evaluateAcquisition、submitDownload、verifyAndImport、refreshMetadata、reconcileLibrary(资产存在性)、cleanupDownloadCache、resolveDecision;outbox;重启恢复;幂等键;取消传播。
|
|
9. **Agent**:Pi AgentSession 封装;能力注册中心(ID/版本/schema/权限/风险/幂等/预览/处理器),首批能力:catalog.lookup、release.search、release.inspect、identity.resolve、download.plan、download.submit、organize.plan、organize.execute、task.inspect、task.retry、task.cancel、policy.preview、policy.apply、inventory.query;授权校验在服务端;agent_run 持久化 + SSE 增量;后台事件触发有界 Agent 任务(识别歧义、下载失败诊断);设置页可配上游/模型/思考档位/上下文预算/压缩/子代理开关。
|
|
10. **控制台页面**(REQ §13):首页六区块(自动化概览/当前工作/需要我处理/缓存与保留/来源健康/最近产出)、媒体库(列表+详情:路径/身份映射/元数据来源/Slot/候选拒绝理由/下载历史)、订阅与收录规则、偏好标签(基础 CRUD+抑制记录)、PT 站点工作台(整理视图:列表/搜索/详情/库存叠加/统一下载入口;原站视图首版只留占位与说明)、来源/Feed/快照、下载与任务(含业务时间线)、整理记录、待处理中心、身份与元数据、系统设置(实例/路径映射/API Key/Pi 上游与预算/自动化开关)、Agent 会话页 + 侧栏。
|
|
11. **可选 Emby 兼容查询**:多实例,查有无/季集/版本,未知≠缺失。
|
|
12. **运维**:`scripts/backup.sh`(pg_dump + 映射导出)、恢复后只读对账模式开关、docker-compose(生产:server + web(nginx) + pg)、runbook。
|
|
13. **测试**:domain 单元测试;adapters 对 mock 服务的集成测试;端到端:mock RSS → 观察 → 识别 → 计划 → mock qB 下载完成 → Copy 入库 → 整理记录 API 可读;Agent e2e:fake 模型按脚本调用能力完成"把 X 电影 1080p 收进来"闭环;崩溃恢复注入(worker 中断后续跑)。
|
|
|
|
### 3.2 v0.1 明确不做(留接口/占位)
|
|
国产综艺分段建模与正片覆盖(M2)、双版本 require_distinct_asset 组合校验(M2,但 Slot 多目标数据结构先建好)、浏览器/camofox 接入与原站视图(M2,BrowserProvider 接口定义先落)、HHClub/CHD 适配(M2)、旧库分范围接管预览(M2)、Agent 主观选片与规则学习回放(M2)、媒体级主动整理 UI(M2,organize.plan 能力可用)、多用户。
|
|
|
|
## 4. 里程碑与派工波次
|
|
|
|
- **W0 底座**(并行):A 脚手架与设计系统迁入;B OpenWorkflow+Pi 兼容性 spike(结论进 ADR-002);C MoviePilot 迁移对照账本(识别/刮削 + 转移入库)。
|
|
- **W1 领域与适配**(并行):domain(解析/身份/Slot/路径/整理计划)、adapters(qB/RSS/站点/TMDB/Emby)+ testkit mocks、db schema 全量迁移 + contracts 全量 schema、tasks 引擎接入。
|
|
- **W2 服务编排**:server API 全量路由 + 任务处理器串起纵切 + Agent 能力注册与 Pi 封装。
|
|
- **W3 控制台**(按页面分组并行)+ e2e。
|
|
- **W4 集成验收与修复**:跑 §3.1 第 13 条全部;补 runbook;打 tag v0.1.0。
|
|
|
|
每波结束的验收由独立审查子代理执行:`pnpm ci` 绿 + 对照本文件逐条勾选 + 抽查 REQ §2.1 五原则未被破坏。
|