feat(file-manager): suggest-name via naming engine; plan.naming source from override chain (W9-H G9)

- POST /files/suggest-name renders the effective template (entity > root >
  global) with the same variables as organize: file name segment for files,
  work/season dir segment for directories; identity_uncertain when no entity
- planImport plan.naming.templateSource/templateVersion now come from
  effectiveNaming + the registered template version (fixes the leftover
  DEFAULT_TEMPLATES reference after the naming chain landed)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 15:26:34 +08:00
1 parent 8651a35594
commit 99a3e17210
5 files changed
+129 -14

No files matched your search

+30 -5
View File
@@ -15,7 +15,7 @@ import {
} from "./harness.ts";
// W9-H 文件管理 v2 后端缺口:G1 TMDB 候选建作品 / G2 最小体积 / G3 目标已存在策略 / G4 命名方式与来源 /
// G5 整理记录提示 + 重新整理源 + 整理后刷新元数据 + 批量刮削 / G8 目录摘要 / G9 推荐名(引擎未就绪 501)。
// G5 整理记录提示 + 重新整理源 + 整理后刷新元数据 + 批量刮削 / G8 目录摘要 / G9 推荐名。
const skip = !(await pgAvailable());
@@ -315,14 +315,39 @@ describe.skipIf(skip)("files v2(W9-H)", () => {
expect(top.body.data.summary.registeredCount).toBeGreaterThanOrEqual(2);
});
it("G9:推荐名在命名引擎接入前返回 501 not_implemented", async () => {
const r = await h.api(
it("G9:推荐名按命名模板渲染(文件名 / 作品目录);识别不可信 → null + 原因", async () => {
const f = await h.api(
"POST",
"/files/suggest-name",
{ root: h.dlRoot, path: "Blue.Film.2021.2160p.BluRay.x265-GRP.mkv" },
READ_KEY,
);
expect(r.status).toBe(501);
expect(r.body.error.message).toMatch(/^not_implemented:/);
expect(f.status).toBe(200);
expect(f.body.data).toMatchObject({
mediaEntityId: film,
templateSource: "global",
reason: null,
name: "Blue Film (2021) - 2160p.mkv",
relativePath: "Blue Film (2021)/Blue Film (2021) - 2160p.mkv",
});
expect(f.body.data.segments.map((s: Loose) => s.role)).toEqual(["root", "file"]);
await mkdir(join(h.dl, "Blue.Film.2021.Pack"), { recursive: true });
const dir = await h.api(
"POST",
"/files/suggest-name",
{ root: h.dlRoot, path: "Blue.Film.2021.Pack", mediaEntityId: film },
READ_KEY,
);
expect(dir.body.data.name).toBe("Blue Film (2021)");
await writeFile(join(h.dl, "Nobody.Knows.This.2011.mkv"), big);
const unknown = await h.api(
"POST",
"/files/suggest-name",
{ root: h.dlRoot, path: "Nobody.Knows.This.2011.mkv" },
READ_KEY,
);
expect(unknown.body.data).toMatchObject({ name: null, reason: "identity_uncertain" });
});
});