diff --git a/CLAUDE.md b/CLAUDE.md index e21e543d..272a0883 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,6 +16,8 @@ deno task ci # 提交前完整检查(含 web 构建与编译产物自 deno task release # 测试环境发布,见下 ``` +REST 端点定义按领域分在 `packages/contracts/src/api/*.ts`,`api.ts` 按顺序合并成 `Api`(顺序即路由注册顺序)。整理服务按阶段分在 `organize-plan / -exec / -finalize / -records / -types.ts`,外部仍从 `organize.ts` 引用。 + 只改一个包时可在包目录跑 `deno run -A npm:vitest run <文件>`;web 包用 `../../node_modules/.bin/vitest run`(Node)。改迁移后跑 `deno task gen:types` 重新生成 `packages/db/src/types.ts`,contracts 枚举顺序与数据库保持一致(`packages/contracts/test/db-sync.test.ts` 会查)。 ## 约定 @@ -31,7 +33,8 @@ deno task release # 测试环境发布,见下 - 位置:server 的测试统一放 `apps/server/test/<模块>/`(不再用 `src/**/__tests__`);web 与 adapters 测试和源码放同目录 `*.test.ts`;其它包放 `test/`。 - 命名按测的行为(`crash-recovery.test.ts`、`two-stage-search.test.ts`),不要用任务编号(`e4-`、`w5a2`、`-md1`)。 -- server 分三组(`apps/server/vitest.config.ts`):`unit` 不碰 PG;`pg` 真实 PG + 假引擎,文件并行;`serial` 起真实引擎 / worker / 子进程的集成与 e2e,串行。新文件缺省进 `pg`,起真实 worker 的必须加进 `SERIAL`。 +- server 分三组(`apps/server/vitest.config.ts`):`unit` 不碰 PG;`pg` 真实 PG + 假引擎,文件并行;`serial` 起真实引擎 / worker / 子进程的集成与 e2e,串行。新文件缺省进 `pg`,起真实 worker / 引擎 / 子进程的必须加进 `SERIAL`。 +- server 测试的建库、schema 锁、假引擎统一用 `apps/server/test/support/`(`pg.ts`、`engine.ts`),各模块 harness 只写自己的装配。 - 每个 PG 测试文件用自己的 schema;等待异步结果用轮询到条件,不写固定 sleep。 - 真机测试用 `*.real.test.ts`,靠环境变量开启,缺省跳过。 diff --git a/docs/plan/README.md b/docs/plan/README.md index 9393377d..43b08f7b 100644 --- a/docs/plan/README.md +++ b/docs/plan/README.md @@ -26,14 +26,15 @@ ### 工程 -- 任务恢复的三处边界:升级前未结束任务的版本处置(发布前查在途任务版本,没有在途旧任务就不保留旧处理器);业务结果提交、run 关联、事件派发三个时点分别注入失败确认最终状态;引擎查询异常时只记录并跳过本轮,仅在明确查无 run 或终态时补投。 -- 生产模块装配的处理器来源断言(防止漏注册的任务静默回显 todo),下次改任务注册时补。 -- 测试装配去重:server 6 份 harness(约 1800 行)各自实现建 schema、迁移、假引擎、临时目录,抽公共部分到 `@umt/testkit`,各模块只留自己的装配;下次改到相关 harness 时做。 -- 大文件拆分候选,改到相关功能时顺手拆,不单独重构:`packages/contracts/src/api.ts`(~2700 行)、`acquisition-organize/services/organize.ts`(~2600)、`browser/service.ts`(~2400)、`web/app/components/organize-wizard/organize-wizard.tsx`。 +- `BrowserService`(`apps/server/src/modules/browser/service.ts`,约 2300 行)仍是单个类。纯函数已移到 `session-view.ts`;Cloudflare 挑战流程(`beginChallenge`~`fetchSiteHtml`,约 400 行)要拆成独立协作对象,需要先把它用到的私有方法改成公开接口,下次改挑战流程时做。 +- 超长函数:`planImport`(`organize-plan.ts`,约 830 行)、`finalizeRecord`(`organize-finalize.ts`,约 460 行)、`OrganizeWizard` 组件(约 800 行)。文件已按阶段拆开,函数内部等改到相关逻辑时再拆,不单独重构。 -### 业务 +### 业务(需要真实环境或决定) -- 疑似竞争:同一 Slot 两个版本几乎同时评估时,`evaluateForSlot`(`acquisition.ts`)读在途计划与写计划 / 延后之间没有锁,可能都不被延后。现象:`test/e2e/continuous-series.test.ts`「另一版本延后」在全量跑时偶发等待超时(2026-10-02 并行化后 3 次全量中 1 次,单跑 4 次均过)。先复现确认,再考虑按 Slot 加行锁。 +- R06 通用 HTTP 失败转浏览器:要先定"哪些失败转浏览器、每站每小时上限、失败后怎么提示",再实现;真实 Cloudflare 挑战需要一个会触发挑战的站点账号验收。 +- R21 缓存阈值里未纳管占用的专项验收:需要在真实下载盘上放一批不归本工具管理的文件,观察暂停 / 恢复水位。 +- 四站与真实下载、媒体服务器的完整验收:需要真实站点账号、qB 与 Emby / Jellyfin 实例。 -- 与 MP 对照里仍未定的项,见 [对照 §6.4/6.5](../porting/moviepilot-v3-comparison.md#64-用户反馈与后续讨论2026-10-02)。 -- 需求里仍是"部分实现"的:R06 通用 HTTP 失败转浏览器、真实 Cloudflare 挑战验收;R21 缓存阈值里未纳管占用的专项验收;四站与真实下载、媒体服务器的完整验收。 +### 观察项 + +- `test/e2e/continuous-series.test.ts`「另一版本延后」2026-10-02 全量跑时偶发等待超时 1 次。已核实不是业务竞争(`reserve()` 在 Slot 行锁内复核单元重叠,冲突即延后);单跑 4 次、3 份 / 8 份并发均未复现,疑为负载下评估任务重试退避超过 60s 等待。再出现时保留 `.local/test-logs/` 日志再查。 diff --git a/docs/plan/lessons.md b/docs/plan/lessons.md index d6776996..c336030b 100644 --- a/docs/plan/lessons.md +++ b/docs/plan/lessons.md @@ -38,3 +38,4 @@ ## 发布与检查(2026-10-02 补充) 25. v0.3.8~v0.3.13 六个版本都由未提交工作区构建部署,发布记录写"检查通过",实际 agent / db / contracts 测试与类型检查一直是红的:`deno task test` 在第一个失败的包就停、后面的包根本没跑;连不上库时数据库用例静默跳过也算通过;开发库落后 9 个迁移没人发现 → **规则**:发布只走 `deno task release`(工作区不干净直接拒绝,tag 即镜像版本);检查只认 `deno task test:all` 的汇总(逐包跑完、连不上库即失败);拉代码后 `deno task dev:up`。 +26. 用 `deno task lint | tail -1 && git commit` 做提交前检查:管道的退出码是 `tail` 的,lint 失败照样提交,`b61335e` 因此带进了一批格式问题 → **规则**:检查命令不接管道,输出重定向到文件再看退出码(`cmd > log 2>&1; echo $?`)。