refactor: create 从 SDD 阶段降级为工具命令,移除阶段配置和提示词
This commit is contained in:
@@ -36,6 +36,22 @@ export async function injectClaudeCode(
|
||||
}
|
||||
}
|
||||
|
||||
// create 是工具命令,不是 SDD 阶段,但仍需生成对应的 command 文件
|
||||
{
|
||||
const stage = "create";
|
||||
const cmd = `${command} ${stage} <变更名>`;
|
||||
const smartGuide = `\n${buildSmartGuide(command)}\n`;
|
||||
const commandDir = join(projectRoot, COMMANDS_DIR);
|
||||
await mkdir(commandDir, { recursive: true });
|
||||
const commandPath = join(commandDir, `rune-${stage}.md`);
|
||||
if (!existsSync(commandPath)) {
|
||||
await writeFile(
|
||||
commandPath,
|
||||
`执行以下命令,将输出作为当前阶段的工作指引:\n\`\`\`bash\n${cmd}\n\`\`\`${smartGuide}\n`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const introCommandPath = join(projectRoot, COMMANDS_DIR, "rune-intro.md");
|
||||
if (!existsSync(introCommandPath)) {
|
||||
await mkdir(join(projectRoot, COMMANDS_DIR), { recursive: true });
|
||||
@@ -59,6 +75,18 @@ export async function updateClaudeCode(
|
||||
await writeIfChanged(commandPath, newContent);
|
||||
}
|
||||
|
||||
// create 是工具命令,不是 SDD 阶段,但仍需生成对应的 command 文件
|
||||
{
|
||||
const stage = "create";
|
||||
const cmd = `${command} ${stage} <变更名>`;
|
||||
const smartGuide = `\n${buildSmartGuide(command)}\n`;
|
||||
const commandDir = join(projectRoot, COMMANDS_DIR);
|
||||
await mkdir(commandDir, { recursive: true });
|
||||
const commandPath = join(commandDir, `rune-${stage}.md`);
|
||||
const newContent = `执行以下命令,将输出作为当前阶段的工作指引:\n\`\`\`bash\n${cmd}\n\`\`\`${smartGuide}\n`;
|
||||
await writeIfChanged(commandPath, newContent);
|
||||
}
|
||||
|
||||
const introCommandPath = join(projectRoot, COMMANDS_DIR, "rune-intro.md");
|
||||
await writeIfChanged(introCommandPath, generateIntroCommand(command));
|
||||
}
|
||||
@@ -66,11 +94,11 @@ export async function updateClaudeCode(
|
||||
function generateIntroCommand(command: string): string {
|
||||
return `Rune 是基于规格驱动开发(SDD)的 AI 开发辅助工具。SDD 工作流程:
|
||||
|
||||
discuss → create → plan → build → archive
|
||||
discuss → plan → build → archive
|
||||
|
||||
可用命令:
|
||||
- /rune-discuss — 自由讨论需求和方案
|
||||
- /rune-create — 创建变更目录
|
||||
- /rune-create — 创建变更目录(辅助命令,plan 阶段的前置步骤)
|
||||
- /rune-plan — 生成设计文档和任务清单
|
||||
- /rune-build — 按任务清单逐步实现
|
||||
- /rune-archive — 归档已完成的变更
|
||||
|
||||
@@ -26,6 +26,24 @@ export async function injectOpenCode(projectRoot: string, command: string = "run
|
||||
}
|
||||
}
|
||||
|
||||
// create 是工具命令,不是 SDD 阶段,但仍需生成对应的 command 和 skill 文件
|
||||
{
|
||||
const stage = "create";
|
||||
const commandDir = join(projectRoot, COMMANDS_DIR);
|
||||
await mkdir(commandDir, { recursive: true });
|
||||
const commandPath = join(commandDir, `rune-${stage}.md`);
|
||||
if (!existsSync(commandPath)) {
|
||||
await writeFile(commandPath, generateCommand(stage));
|
||||
}
|
||||
|
||||
const skillStageDir = join(projectRoot, SKILLS_DIR, `rune-${stage}`);
|
||||
await mkdir(skillStageDir, { recursive: true });
|
||||
const skillPath = join(skillStageDir, "SKILL.md");
|
||||
if (!existsSync(skillPath)) {
|
||||
await writeFile(skillPath, generateSkill(stage, command));
|
||||
}
|
||||
}
|
||||
|
||||
const introSkillDir = join(projectRoot, SKILLS_DIR, "rune-intro");
|
||||
await mkdir(introSkillDir, { recursive: true });
|
||||
const introSkillPath = join(introSkillDir, "SKILL.md");
|
||||
@@ -47,6 +65,20 @@ export async function updateOpenCode(projectRoot: string, command: string = "run
|
||||
await writeIfChanged(skillPath, generateSkill(stage, command));
|
||||
}
|
||||
|
||||
// create 是工具命令,不是 SDD 阶段,但仍需生成对应的 command 和 skill 文件
|
||||
{
|
||||
const stage = "create";
|
||||
const commandDir = join(projectRoot, COMMANDS_DIR);
|
||||
await mkdir(commandDir, { recursive: true });
|
||||
const commandPath = join(commandDir, `rune-${stage}.md`);
|
||||
await writeIfChanged(commandPath, generateCommand(stage));
|
||||
|
||||
const skillStageDir = join(projectRoot, SKILLS_DIR, `rune-${stage}`);
|
||||
await mkdir(skillStageDir, { recursive: true });
|
||||
const skillPath = join(skillStageDir, "SKILL.md");
|
||||
await writeIfChanged(skillPath, generateSkill(stage, command));
|
||||
}
|
||||
|
||||
const introSkillDir = join(projectRoot, SKILLS_DIR, "rune-intro");
|
||||
await mkdir(introSkillDir, { recursive: true });
|
||||
const introSkillPath = join(introSkillDir, "SKILL.md");
|
||||
@@ -69,7 +101,7 @@ function generateSkill(stage: string, command: string): string {
|
||||
|
||||
const descriptionMap: Record<string, string> = {
|
||||
discuss: "Use when 需要进入 SDD 讨论阶段,自由讨论需求和架构方案",
|
||||
create: "Use when 需要创建变更目录,为 SDD 流程准备变更工作区",
|
||||
create: "Use when 需要创建变更目录(plan 阶段的辅助命令,prepare workspace)",
|
||||
plan: "Use when 需要进入 SDD 规划阶段,生成设计文档和任务清单",
|
||||
build: "Use when 需要进入 SDD 构建阶段,按任务清单逐步实现变更",
|
||||
archive: "Use when 需要进入 SDD 归档阶段,确认变更完成并归档",
|
||||
@@ -115,8 +147,8 @@ Rune 是基于规格驱动开发(SDD)的 AI 开发辅助工具。它通过
|
||||
## SDD 工作流程
|
||||
|
||||
\`\`\`
|
||||
discuss → create → plan → build → archive
|
||||
探索 创建 规划 构建 归档
|
||||
discuss → plan → build → archive
|
||||
探索 规划 构建 归档
|
||||
\`\`\`
|
||||
|
||||
## 可用命令
|
||||
@@ -124,7 +156,7 @@ discuss → create → plan → build → archive
|
||||
| 阶段 | 编辑器命令 | 说明 |
|
||||
|------|-----------|------|
|
||||
| discuss | /rune-discuss | 自由讨论需求和方案 |
|
||||
| create | /rune-create | 创建变更目录 |
|
||||
| create | /rune-create | 创建变更目录(辅助命令) |
|
||||
| plan | /rune-plan | 生成设计文档和任务清单 |
|
||||
| build | /rune-build | 按任务清单逐步实现 |
|
||||
| archive | /rune-archive | 归档已完成的变更 |
|
||||
@@ -138,9 +170,8 @@ ${command} status
|
||||
## 快速开始
|
||||
|
||||
1. 使用 /rune-discuss 进入讨论,自由探索需求
|
||||
2. 使用 /rune-create 创建变更目录
|
||||
3. 使用 /rune-plan 生成设计文档和任务清单
|
||||
4. 使用 /rune-build 按任务顺序实现功能
|
||||
5. 使用 /rune-archive 归档已完成的变更
|
||||
2. 使用 /rune-create 创建变更目录,然后用 /rune-plan 生成设计文档和任务清单
|
||||
3. 使用 /rune-build 按任务顺序实现功能
|
||||
4. 使用 /rune-archive 归档已完成的变更
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { runInit } from "./commands/init.ts";
|
||||
import { findProjectRoot, loadConfig, getChangeDir, getArchiveDir } from "./core/config.ts";
|
||||
import {
|
||||
assembleDiscussPrompt,
|
||||
assembleCreatePrompt,
|
||||
assemblePlanPrompt,
|
||||
assembleBuildPrompt,
|
||||
assembleArchivePrompt,
|
||||
@@ -216,8 +215,10 @@ cli.command("create <change-name>", "创建变更").action(async (changeName: st
|
||||
});
|
||||
}
|
||||
await mkdir(changeDir, { recursive: true });
|
||||
const prompt = assembleCreatePrompt(config);
|
||||
console.log(prompt);
|
||||
const prefix = getPmPrefix(config);
|
||||
console.log(`变更 "${changeName}" 已创建。
|
||||
|
||||
下一步:${prefix} plan ${changeName} <文档名>`);
|
||||
});
|
||||
|
||||
cli
|
||||
|
||||
@@ -30,10 +30,11 @@ const COMMANDS: Record<string, CommandHelpDef> = {
|
||||
create: {
|
||||
name: "create",
|
||||
alias: "create <变更>",
|
||||
description: "创建:创建变更目录",
|
||||
description: "创建变更目录(plan 阶段的辅助命令)",
|
||||
usageTemplate: "create <change-name>",
|
||||
args: [{ name: "<change-name>", desc: '变更名称,如 "add-login"' }],
|
||||
detail: "在 .rune/changes/ 下创建以变更名称命名的目录,并生成创建阶段提示词。",
|
||||
detail:
|
||||
"在 .rune/changes/ 下创建以变更名称命名的目录。这不是独立的 SDD 阶段,而是为 plan 阶段准备变更工作区的工具命令。使用 plan 前必须先 create 创建变更目录。",
|
||||
exampleArgs: ["create add-user-auth", "create fix-memory-leak"],
|
||||
},
|
||||
plan: {
|
||||
|
||||
@@ -11,11 +11,11 @@ import { parse as parseYaml } from "yaml";
|
||||
const CONFIG_TEMPLATE = `# Rune 配置文件
|
||||
#
|
||||
# 未配置的阶段将使用内置默认配置。
|
||||
# 阶段顺序:discuss -> create -> plan -> build -> archive
|
||||
# SDD 四阶段:discuss -> plan -> build -> archive
|
||||
# 辅助命令:create(创建变更目录,plan 阶段的前置步骤)
|
||||
#
|
||||
# 可配置阶段:
|
||||
# discuss - 探索阶段:深度思考、调查代码库、对比方案
|
||||
# create - 创建阶段:拟定变更名称并创建变更目录
|
||||
# plan - 规划阶段:生成设计文档和任务清单
|
||||
# build - 构建阶段:按任务清单逐步实现
|
||||
# archive - 归档阶段:确认完成并归档变更
|
||||
|
||||
@@ -16,15 +16,6 @@ export function assembleDiscussPrompt(config: RuneConfig): string {
|
||||
return applyCommandPrefix(discuss.prompt, config);
|
||||
}
|
||||
|
||||
export function assembleCreatePrompt(config: RuneConfig): string {
|
||||
const create = config.stages.create;
|
||||
if (!create)
|
||||
throw new CommandError("创建阶段未配置", {
|
||||
hint: "请在 .rune/config.yaml 中配置 stages.create",
|
||||
});
|
||||
return applyCommandPrefix(create.prompt, config);
|
||||
}
|
||||
|
||||
export async function assemblePlanPrompt(
|
||||
config: RuneConfig,
|
||||
projectRoot: string,
|
||||
|
||||
@@ -91,7 +91,7 @@ export function validateConfig(config: RuneConfig): void {
|
||||
|
||||
function mergeConfig(userConfig: Partial<RuneConfig>): RuneConfig {
|
||||
const result: RuneConfig = { stages: {} };
|
||||
const stageKeys = ["discuss", "create", "plan", "build", "archive"] as const;
|
||||
const stageKeys = ["discuss", "plan", "build", "archive"] as const;
|
||||
|
||||
for (const stage of stageKeys) {
|
||||
if (userConfig.stages?.[stage]) {
|
||||
|
||||
@@ -232,14 +232,6 @@ rune status
|
||||
|
||||
除非……有同步组件?
|
||||
\`\`\``,
|
||||
},
|
||||
create: {
|
||||
prompt: `请根据讨论内容,拟定一个简短、有意义的变更名称,然后执行 create 命令创建变更目录。
|
||||
|
||||
要求:
|
||||
- 变更名称应简洁明了,能概括变更的核心内容
|
||||
- 仅支持中文、英文和短横线(-)
|
||||
- 创建成功后,引导用户使用 /rune-plan <变更名> <文档名> 进入规划阶段`,
|
||||
},
|
||||
plan: {
|
||||
documents: [
|
||||
|
||||
@@ -15,10 +15,6 @@ export interface DiscussStage {
|
||||
prompt: string;
|
||||
}
|
||||
|
||||
export interface CreateStage {
|
||||
prompt: string;
|
||||
}
|
||||
|
||||
export interface PlanStage {
|
||||
documents: DocumentConfig[];
|
||||
}
|
||||
@@ -33,7 +29,6 @@ export interface ArchiveStage {
|
||||
|
||||
export interface StagesConfig {
|
||||
discuss?: DiscussStage;
|
||||
create?: CreateStage;
|
||||
plan?: PlanStage;
|
||||
build?: BuildStage;
|
||||
archive?: ArchiveStage;
|
||||
@@ -60,7 +55,7 @@ export interface ChangeStatus {
|
||||
taskProgress: { completed: number; total: number } | null;
|
||||
}
|
||||
|
||||
export const STAGES = ["discuss", "create", "plan", "build", "archive"] as const;
|
||||
export const STAGES = ["discuss", "plan", "build", "archive"] as const;
|
||||
export type Stage = (typeof STAGES)[number];
|
||||
|
||||
export const RUNE_DIR = ".rune";
|
||||
|
||||
Reference in New Issue
Block a user