feat: build 阶段根据 tracked 分支处理

This commit is contained in:
2026-06-10 09:03:38 +08:00
parent 8e00e2cdf1
commit 0c89b3ebb2
2 changed files with 50 additions and 2 deletions

View File

@@ -4,7 +4,7 @@ import { join } from "node:path";
import type { RuneConfig } from "../types.ts";
import { CommandError } from "../cli/errors.ts";
import { getChangeDir } from "./config.ts";
import { parseTasks } from "./task-parser.ts";
import { parseTasks, validateTaskFormat } from "./task-parser.ts";
import { applyCommandPrefix, getPmPrefix } from "./pm.ts";
export function assembleDiscussPrompt(config: RuneConfig): string {
@@ -85,6 +85,10 @@ export async function assembleBuildPrompt(
});
}
if (!config.metadata?.tracked) {
return applyCommandPrefix(build.prompt, config);
}
const changeDir = getChangeDir(projectRoot, changeName);
const taskPath = join(changeDir, "task.md");
@@ -98,6 +102,8 @@ export async function assembleBuildPrompt(
});
}
validateTaskFormat(taskContent);
const tasks = parseTasks(taskContent);
const pendingTasks = tasks.filter((t) => !t.checked);

View File

@@ -152,6 +152,48 @@ describe("assembleBuildPrompt", () => {
expect(e.hint).toContain("plan nonexistent");
}
});
it("tracked=false 时只输出通用提示词", async () => {
const config: RuneConfig = {
stages: { build: { prompt: "按规划文档逐步实现功能" } },
metadata: { tracked: false },
};
const prompt = await assembleBuildPrompt(config, TMP_DIR, "user-auth");
expect(prompt).toBe("按规划文档逐步实现功能");
});
it("tracked=true 且 task.md 格式不合法时抛错", async () => {
const changeDir = join(TMP_DIR, ".rune", "changes", "user-auth");
await mkdir(changeDir, { recursive: true });
await writeFile(join(changeDir, "task.md"), "# 标题\n无 checkbox");
const config: RuneConfig = {
stages: { build: { prompt: "构建阶段" } },
metadata: { tracked: true },
};
try {
await assembleBuildPrompt(config, TMP_DIR, "user-auth");
expect.unreachable();
} catch (e: any) {
expect(e.message).toContain("task.md");
expect(e.message).toContain("checkbox");
}
});
it("tracked=true 且 task.md 有空 checkbox 文本时抛错", async () => {
const changeDir = join(TMP_DIR, ".rune", "changes", "user-auth");
await mkdir(changeDir, { recursive: true });
await writeFile(join(changeDir, "task.md"), "- [ ] \n- [x] 有内容");
const config: RuneConfig = {
stages: { build: { prompt: "构建阶段" } },
metadata: { tracked: true },
};
try {
await assembleBuildPrompt(config, TMP_DIR, "user-auth");
expect.unreachable();
} catch (e: any) {
expect(e.message).toContain("checkbox");
}
});
});
describe("assembleArchivePrompt", () => {
@@ -187,7 +229,7 @@ describe("命令前缀替换", () => {
it("assembleBuildPrompt 错误提示使用动态前缀", async () => {
const config: RuneConfig = {
stages: { build: { prompt: "构建阶段" } },
metadata: { command: "pnpx @lanyuanxiaoyao/rune" },
metadata: { command: "pnpx @lanyuanxiaoyao/rune", tracked: true },
};
try {
await assembleBuildPrompt(config, TMP_DIR, "nonexistent-build");