#!/usr/bin/env node /** * plan-next.js - 规划下一步功能 * * 1. 分析当前项目状态(待办任务、已完成任务) * 2. 根据优先级推荐下一个要完成的任务 * 3. 生成对应的prompt文件或下一步文档 */ const fs = require('fs'); const path = require('path'); const TODO_FILE = path.join(__dirname, '../meta/todo.md'); const PROMPTS_DIR = path.join(__dirname, '../prompts'); const OUTPUT_DIR = path.join(__dirname, '../docs/next-steps'); // 任务优先级映射 const PRIORITY_MAP = { '核心功能开发': 'high', '基础设施': 'medium', '文档': 'medium', '测试与质量': 'medium', '未来功能': 'low' }; // 解析待办任务文件 function parseTodo(content) { const lines = content.split('\n'); const tasks = []; let currentCategory = ''; for (const line of lines) { const categoryMatch = line.match(/^##\s+(.+)/); if (categoryMatch) { currentCategory = categoryMatch[1].trim(); continue; } const taskMatch = line.match(/^- \[( |x)\]\s+(.+)/); if (taskMatch) { const checked = taskMatch[1] === 'x'; const description = taskMatch[2].trim(); tasks.push({ category: currentCategory, description, checked, priority: PRIORITY_MAP[currentCategory] || 'medium', raw: line }); } } return tasks; } // 分析项目状态并推荐下一个任务 function recommendNextTask(tasks) { // 只考虑未完成的任务 const pendingTasks = tasks.filter(t => !t.checked); if (pendingTasks.length === 0) { return { recommended: null, message: '🎉 所有任务已完成!没有待推荐的任务。' }; } // 按优先级排序:high > medium > low const priorityOrder = { high: 1, medium: 2, low: 3 }; pendingTasks.sort((a, b) => { if (priorityOrder[a.priority] !== priorityOrder[b.priority]) { return priorityOrder[a.priority] - priorityOrder[b.priority]; } // 同优先级按类别排序 const categoryOrder = ['核心功能开发', '基础设施', '文档', '测试与质量', '未来功能']; return categoryOrder.indexOf(a.category) - categoryOrder.indexOf(b.category); }); const recommendedTask = pendingTasks[0]; // 计算统计数据 const totalTasks = tasks.length; const completedTasks = tasks.filter(t => t.checked).length; const pendingByCategory = {}; pendingTasks.forEach(task => { pendingByCategory[task.category] = (pendingByCategory[task.category] || 0) + 1; }); return { recommended: recommendedTask, stats: { totalTasks, completedTasks, pendingTasks: pendingTasks.length, completionRate: totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0, pendingByCategory }, message: `🎯 推荐下一个任务:${recommendedTask.description} (优先级: ${recommendedTask.priority}, 类别: ${recommendedTask.category})` }; } // 为推荐的任务生成prompt文件 function generatePromptForTask(task) { if (!task) return null; // 生成文件名:将任务描述转换为kebab-case // 保留中文字符、英文字母、数字,将其他字符替换为空格,然后转换为连字符 const fileName = task.description .toLowerCase() // 保留中文字符 (\u4e00-\u9fff)、英文字母、数字、空格 .replace(/[^\u4e00-\u9fffa-z0-9\s]/g, ' ') // 将连续的多个空格替换为单个空格 .replace(/\s+/g, ' ') .trim() // 将空格替换为连字符 .replace(/\s/g, '-') .replace(/^implement-/, '') // 如果以implement-开头,去掉它 + '.md'; const filePath = path.join(PROMPTS_DIR, fileName); // 生成prompt内容 const promptContent = `# ${task.description} ## 描述 详细描述${task.description}的功能需求和实现目标。 ## 要求 1. 明确的功能边界和交付物 2. 与现有系统集成的考虑 3. 代码质量标准和最佳实践 4. 必要的测试覆盖 ## 上下文 当前项目状态: - 项目:MetaCraft (AI驱动的元开发工具) - 阶段:早期开发 - 已完成任务:${task.checked ? '是' : '否'} - 优先级:${task.priority} 相关依赖和前置条件: (根据任务分析添加具体依赖) ## 输出 请提供: 1. 完整的设计方案 2. 具体的实现代码 3. 必要的测试用例 4. 文档更新建议 ## 约束 - 保持与现有代码风格一致 - 考虑可扩展性和维护性 - 遵循项目架构设计原则`; // 确保prompts目录存在 if (!fs.existsSync(PROMPTS_DIR)) { fs.mkdirSync(PROMPTS_DIR, { recursive: true }); } // 写入文件 fs.writeFileSync(filePath, promptContent, 'utf-8'); return { filePath, fileName, promptContent }; } // 生成下一步文档 function generateNextStepDocument(task, stats) { if (!task) return null; // 确保输出目录存在 if (!fs.existsSync(OUTPUT_DIR)) { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } const timestamp = new Date().toISOString().split('T')[0]; const docFileName = `next-step-${timestamp}.md`; const docFilePath = path.join(OUTPUT_DIR, docFileName); const docContent = `# 下一步规划:${task.description} 生成时间:${new Date().toLocaleString()} ## 项目状态概览 - 总任务数:${stats.totalTasks} - 已完成:${stats.completedTasks} - 待完成:${stats.pendingTasks} - 完成率:${stats.completionRate}% ### 按类别待完成任务: ${Object.entries(stats.pendingByCategory).map(([cat, count]) => `- ${cat}: ${count}个`).join('\n')} ## 推荐的下一个任务 **任务描述**:${task.description} **优先级**:${task.priority} **类别**:${task.category} ## 任务分析 ### 为什么选择这个任务? 1. **优先级最高**:属于"${task.category}"类别,在当前开发阶段最为关键 2. **依赖关系**:可能是其他任务的前置条件 3. **价值最大**:完成此任务将为后续开发奠定基础 ### 预期影响 - ✅ 推动核心功能开发进度 - ✅ 为后续任务扫清障碍 - ✅ 验证工具链的有效性 ## 详细需求 ### 功能要求 1. 明确的功能定义和边界 2. 与现有系统的集成点 3. 输入/输出接口规范 4. 错误处理和边界情况 ### 技术实现考虑 1. 代码结构和模块设计 2. 性能和安全要求 3. 测试策略和覆盖目标 4. 文档和示例代码 ## 验收标准 - [ ] 功能实现完整且符合需求 - [ ] 代码质量符合项目标准 - [ ] 测试用例覆盖主要场景 - [ ] 文档更新及时准确 ## 时间规划建议 **阶段1:设计与规划** (1-2天) - 详细需求分析 - 技术方案设计 - 接口定义和原型验证 **阶段2:实现与测试** (2-3天) - 核心功能实现 - 单元测试和集成测试 - 代码审查和优化 **阶段3:集成与文档** (1天) - 系统集成和验证 - 文档编写和示例 - 部署和发布准备 ## 风险与缓解 ### 技术风险 - 与现有系统兼容性问题 - 性能瓶颈或扩展性限制 ### 缓解措施 - 提前进行技术验证和原型测试 - 分阶段实现,及时反馈和调整 ## 后续任务建议 完成此任务后,建议考虑: 1. **${task.category}**中的其他高优先级任务 2. 依赖此任务的下游功能开发 3. 相关文档和测试完善 --- *本文档由MetaCraft的"规划下一步"功能自动生成*`; fs.writeFileSync(docFilePath, docContent, 'utf-8'); return { docFilePath, docFileName, docContent }; } async function main() { console.log('🚀 MetaCraft 规划下一步功能启动\n'); // 读取待办任务文件 if (!fs.existsSync(TODO_FILE)) { console.error('❌ 待办任务文件不存在:', TODO_FILE); process.exit(1); } const todoContent = fs.readFileSync(TODO_FILE, 'utf-8'); const tasks = parseTodo(todoContent); // 推荐下一个任务 const recommendation = recommendNextTask(tasks); console.log(recommendation.message); if (recommendation.recommended) { // 显示统计信息 console.log('\n📊 项目状态统计:'); console.log(` 总任务数:${recommendation.stats.totalTasks}`); console.log(` 已完成:${recommendation.stats.completedTasks}`); console.log(` 待完成:${recommendation.stats.pendingTasks}`); console.log(` 完成率:${recommendation.stats.completionRate}%`); console.log('\n📈 按类别待完成任务:'); Object.entries(recommendation.stats.pendingByCategory).forEach(([cat, count]) => { console.log(` ${cat}: ${count}个`); }); // 询问用户要做什么 const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); function askQuestion(query) { return new Promise(resolve => { rl.question(query, answer => { resolve(answer.trim()); }); }); } console.log('\n📝 请选择操作:'); console.log(' 1. 为推荐任务生成prompt文件'); console.log(' 2. 生成下一步规划文档'); console.log(' 3. 两者都生成'); console.log(' 4. 只显示推荐,不生成文件'); const choice = await askQuestion('\n请输入选择 (1-4,默认3): ') || '3'; let promptResult = null; let docResult = null; switch(choice) { case '1': promptResult = generatePromptForTask(recommendation.recommended); break; case '2': docResult = generateNextStepDocument(recommendation.recommended, recommendation.stats); break; case '3': promptResult = generatePromptForTask(recommendation.recommended); docResult = generateNextStepDocument(recommendation.recommended, recommendation.stats); break; case '4': console.log('\n👌 已跳过文件生成。'); break; default: console.log(`\n❌ 无效的选择:"${choice}",跳过文件生成。`); } // 输出生成结果 if (promptResult) { console.log(`\n✅ 已生成prompt文件:${promptResult.filePath}`); } if (docResult) { console.log(`\n📄 已生成下一步规划文档:${docResult.docFilePath}`); } rl.close(); // 给出后续建议 if (promptResult || docResult) { console.log('\n💡 后续建议:'); console.log(' 1. 查看生成的文件,根据需要调整内容'); console.log(' 2. 运行 bootstrap.js 执行该任务'); console.log(' 3. 或直接运行 prompt:node scripts/run-prompt.js prompts/...'); } } else { console.log(recommendation.message); } } if (require.main === module) { main().catch(err => { console.error('规划下一步功能错误:', err); process.exit(1); }); } module.exports = { parseTodo, recommendNextTask, generatePromptForTask, generateNextStepDocument };