feat: 新增 assembleCreatePrompt,plan/build/archive 不再内嵌文件内容

This commit is contained in:
2026-06-10 13:02:16 +08:00
parent b9ea668383
commit daec0612c4
3 changed files with 76 additions and 38 deletions

View File

@@ -3,12 +3,14 @@ import { mkdir, writeFile, rm } from "node:fs/promises";
import { join } from "node:path";
import {
assembleDiscussPrompt,
assembleCreatePrompt,
assemblePlanPrompt,
assembleBuildPrompt,
assembleArchivePrompt,
} from "../../src/core/assembler.ts";
import type { RuneConfig } from "../../src/types.ts";
import { defaultConfig } from "../../src/defaults/config.ts";
import { CommandError } from "../../src/cli/errors.ts";
const TMP_DIR = join(import.meta.dir, "__tmp_assembler_test__");
@@ -38,6 +40,35 @@ describe("assembleDiscussPrompt", () => {
});
});
describe("assembleCreatePrompt", () => {
it("返回默认 create 提示词", () => {
const prompt = assembleCreatePrompt(defaultConfig);
expect(prompt).toBeTruthy();
expect(prompt).toContain("变更名称");
expect(prompt).toContain("/rune-plan");
});
it("返回自定义 create 提示词", () => {
const config: RuneConfig = {
stages: { create: { prompt: "自定义创建" } },
};
const prompt = assembleCreatePrompt(config);
expect(prompt).toBe("自定义创建");
});
it("create 阶段未配置时抛出 CommandError", () => {
const config: RuneConfig = {
stages: { build: { prompt: "构建" } },
};
try {
assembleCreatePrompt(config);
expect.unreachable();
} catch (e) {
expect(e).toBeInstanceOf(CommandError);
}
});
});
describe("assemblePlanPrompt", () => {
it("包含指定文档名称和提示词", async () => {
const prompt = await assemblePlanPrompt(defaultConfig, TMP_DIR, "user-auth", "design");
@@ -46,13 +77,14 @@ describe("assemblePlanPrompt", () => {
expect(prompt).not.toContain("task");
});
it("包含已有文档内容(重复 plan 场景)", async () => {
it("已有文档时引导 AI 读取而非内嵌内容", async () => {
const changeDir = join(TMP_DIR, ".rune", "changes", "user-auth");
await mkdir(changeDir, { recursive: true });
await writeFile(join(changeDir, "design.md"), "# 已有设计");
const prompt = await assemblePlanPrompt(defaultConfig, TMP_DIR, "user-auth", "design");
expect(prompt).toContain("已有设计");
expect(prompt).toContain("在此基础上修订");
expect(prompt).toContain("已有内容");
expect(prompt).toContain("design.md");
expect(prompt).not.toContain("# 已有设计");
});
it("替换模板中的 {{change-name}}", async () => {
@@ -123,14 +155,15 @@ describe("assemblePlanPrompt", () => {
});
describe("assembleBuildPrompt", () => {
it("包含待执行任务列表", async () => {
it("引导 AI 读取 task.md 而非内嵌任务内容", async () => {
const changeDir = join(TMP_DIR, ".rune", "changes", "user-auth");
await mkdir(changeDir, { recursive: true });
await writeFile(join(changeDir, "task.md"), `- [x] 任务一\n- [ ] 任务二\n- [ ] 任务三`);
const prompt = await assembleBuildPrompt(defaultConfig, TMP_DIR, "user-auth");
expect(prompt).toContain("任务二");
expect(prompt).toContain("待执行任务");
expect(prompt).toContain("共 2 项");
expect(prompt).toContain("task.md");
expect(prompt).toContain("2");
expect(prompt).not.toContain("任务二");
expect(prompt).not.toContain("任务三");
});
it("所有任务完成时提示可归档", async () => {
@@ -218,7 +251,7 @@ describe("assembleArchivePrompt", () => {
expect(prompt).not.toContain("未完成");
});
it("tracked=true 时读取 task.md 并注入未完成任务警告", async () => {
it("tracked=true 时引导 AI 检查 task.md 而非内嵌任务内容", async () => {
const changeDir = join(TMP_DIR, ".rune", "changes", "user-auth");
await mkdir(changeDir, { recursive: true });
await writeFile(join(changeDir, "task.md"), "- [ ] 未完成任务");
@@ -227,8 +260,9 @@ describe("assembleArchivePrompt", () => {
metadata: { tracked: true },
};
const prompt = await assembleArchivePrompt(config, TMP_DIR, "user-auth");
expect(prompt).toContain("task.md");
expect(prompt).toContain("未完成");
expect(prompt).toContain("未完成任务");
expect(prompt).not.toContain("- [ ] 未完成任务");
});
it("tracked=true 且所有任务完成时不注入警告", async () => {