Task Master update-task 命令统一迁移指南:策略模式重构任务与子任务更新架构
2026/9/12 3:36:58 网站建设 项目流程

Task Master update-task 命令统一迁移指南:策略模式重构任务与子任务更新架构

【免费下载链接】claude-task-masterAn AI-powered task-management system you can drop into Cursor, Lovable, Windsurf, Roo, and others.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-task-master

本指南围绕 claude-task-master 仓库中的update-task-migration-plan.md迁移计划展开,系统讲解如何将遗留的update-tasks.js(批量更新)与update-subtask-by-id.js(单条子任务更新)合并为统一的update-task命令,并迁移到packages/tm-core+apps/cli的新架构。读者读完将掌握:智能行为检测规则、策略模式 + 模板方法模式 + 工厂模式的具体落地方式、上下文采集与提示词构建的调用链,以及分 11 个阶段的渐进式迁移与回滚策略。

迁移背景:为什么需要统一 update 命令

在 claude-task-master 的旧架构中,任务更新逻辑分散在两个独立文件中,职责重叠且维护成本高:

旧模块职责输入格式AI 服务
update-tasks.js从指定 ID 起批量更新多个任务--from=<id> --prompt="context"generateObjectService(结构化 schema 输出)
update-subtask-by-id.js向特定子任务追加带时间戳的信息--id=<parentId.subtaskId> --prompt="notes"generateTextService(自由文本输出)

两者共享大量相同逻辑(任务加载、上下文采集、提示词构建、CLI 展示、错误处理),却各自维护一份拷贝。迁移计划的核心目标是把它们合并为单一update-task命令,并按照tm-coreapps/cli的既有模式完成面向对象重构——这一点可以从 packages/tm-core/src/modules/commands/index.ts 的占位注释得到印证,该文件明确写着 "Placeholder for future migration",任务命令的执行编排正是计划中的待迁移内容。

统一命令设计与智能行为检测

迁移后的新命令语法如下:

# 更新单个任务(替代 update-task) task-master update-task --id=3 --prompt="changes" # 更新单个子任务(替代 update-subtask) task-master update-task --id=3.2 --prompt="implementation notes" # 从 ID 起批量更新多个任务(替代 update --from) task-master update-task --from=3 --prompt="changes"

命令不需要显式声明模式,而是通过智能行为检测自动判定,判定顺序如下:

  1. ID 包含.→ 子任务模式(subtask mode),例如--id=3.2
  2. 存在--from标志→ 批量更新模式(bulk mode)
  3. 默认→ 单任务更新模式(single task mode)

这一检测逻辑在计划中由UpdateStrategyFactory.detectMode()实现,代码骨架清晰地体现了判定优先级(先判--from,再判带点号的--id,最后是普通--id,三者均缺失则抛出TaskMasterError)。结合旧实现可以验证该设计的一致性:update-tasks.js 中批量筛选条件为task.id >= fromId && task.status !== 'done',而 update-subtask-by-id.js 通过parentId.subtaskId拆分字符串并校验两段均为正整数——这些规则全部被吸收进新设计的TaskIdValidator与各策略的validate()中。

功能清单:从输入校验到持久化的完整链路

迁移计划给出了一个覆盖全流程的功能清单,它实际上是对旧实现行为的逐条核对。以下结合源码逐层展开。

输入校验与解析

  • 校验tasksPath文件存在(旧实现中update-subtask-by-id.js通过fs.existsSync(tasksPath)显式检查);
  • 校验id参数:任务必须为整数,子任务必须为"parent.child"格式;
  • 校验fromId:正整数;
  • 校验prompt:非空字符串(子任务模式例外——见下文的 metadata-only 快速路径);
  • 解析子任务 ID:拆分parentId.subtaskId并分别校验;
  • 项目根目录:优先取上下文传入的projectRoot,否则调用findProjectRoot(),两者都拿不到则抛出Could not determine project root directory
  • 双模式支持:通过mcpLog是否存在判定 MCP 模式(isMCP = !!mcpLog),并据此选择mcpLogconsoleLog作为日志函数;
  • 输出格式:'text''json',MCP 模式下自动为'json'update-subtask-by-id.js中默认值即为context.mcpLog ? 'json' : 'text')。

任务加载与过滤

统一通过readJSON(tasksPath, projectRoot, tag)加载tasks.json,三种模式过滤逻辑不同:

  • 批量模式id >= fromId 且 status !== 'done';若筛选结果为空,则优雅地提示 "No tasks to update" 并直接返回;
  • 单任务模式:按 ID 精确查找;
  • 子任务模式:先按父 ID 找到父任务,校验其subtasks数组存在,再在数组中定位具体子任务。

上下文采集:ContextGatherer 与 FuzzyTaskSearch 的协作

两种旧实现都使用同一套上下文采集流程,迁移计划将其收敛到ContextBuilderService

  1. projectRoottag初始化ContextGatherer——该类的构造器会从.taskmaster/tasks/tasks.json预加载全部任务(见 contextGatherer.js);
  2. flattenTasksWithSubtasks()拍平所有任务与子任务;
  3. 初始化FuzzyTaskSearch,按命令类型选择搜索配置:批量/单任务模式用'update',子任务模式用'update-subtask'
  4. 批量/单任务模式:直接用 prompt 搜索,最多 5 条结果并包含自身;
  5. 子任务模式:用${parentTask.title} ${subtask.title} ${prompt}组合查询串搜索(见 update-subtask-by-id.js);
  6. 将"待更新任务 ID 集合"与"相关上下文任务 ID 集合"合并去重;
  7. 'research'格式调用gatherer.gather({ tasks, format: 'research' })
  8. 采集失败仅告警并继续(Could not gather additional context)。

值得说明的是FuzzyTaskSearch的搜索算法(见 fuzzyTaskSearch.js):底层基于 Fuse.js,按 title(权重 2.0)、description(权重 1.5)、details(权重 1.0)、dependencyTitles(权重 0.5)加权模糊匹配,并按 relevance 阈值(high < 0.25、medium < 0.4、low < 0.6)分层,最后补充最多 5 条最近任务与类别匹配任务。计划中的ContextBuilderService.buildContext()骨架正是这套流程的封装,且在 catch 中返回{ context: '', taskIds: options.targetTaskIds }兜底。

提示词构建:PromptManager 双模板

通过getPromptManager()获取PromptManager后加载模板,两种模式参数不同:

批量/单任务模式'update-tasks'模板):

{ tasks: tasksToUpdate, // 待更新任务数组 updatePrompt: prompt, // 用户提示词 useResearch, // 是否使用 research AI 角色 projectContext: gatheredContext, // 采集到的上下文 hasCodebaseAnalysis: hasCodebaseAnalysis(useResearch, projectRoot, session), projectRoot }

(对应 update-tasks.js 的实际调用。)

子任务模式'update-subtask'模板):额外传入parentTask(id、title)、prevSubtask(若存在,含 id/title/status)、nextSubtask(若存在)、currentDetails(现有 details 或兜底文案),并支持'research'/'default'变体键——旧实现通过const variantKey = useResearch ? 'research' : 'default'传入loadPrompt第三参。

AI 服务集成:结构化对象 vs 自由文本

计划要求根据useResearch决定服务角色('research' | 'main'),再按模式调用不同的统一 AI 服务:

  • 批量/单任务模式generateObjectService({ role, session, projectRoot, systemPrompt, prompt, schema: COMMAND_SCHEMAS['update-tasks'], objectName: 'tasks', commandName: 'update-tasks', outputType: isMCP ? 'mcp' : 'cli' })。旧实现随后对返回的mainResult.tasks做字段归一化(为 dependencies、priority、details、testStrategy、subtasks 等字段填充默认值,见 update-tasks.js);
  • 子任务模式generateTextService({ prompt, systemPrompt, role, session, projectRoot, maxRetries: 2, commandName: 'update-subtask', outputType }),并处理空/非法响应。

两条服务都要求捕获telemetryDatatagInfo用于用量展示。

数据更新与持久化

批量/单任务模式的合并策略(对应旧实现 update-tasks.js,计划中移植到DataMergerService.mergeTasks()):

  • 解析aiServiceResponse.mainResult.tasks数组并校验结构;
  • Map按任务 ID 建立索引实现高效查找;
  • 遍历原数据,命中则{ ...task, ...updatedTask, subtasks: updatedTask.subtasks !== undefined ? updatedTask.subtasks : task.subtasks }——保留 AI 未返回的 subtasks 字段是关键防数据丢失点;
  • 统计真实更新条数actualUpdateCount

子任务模式的追加策略(对应 update-subtask-by-id.js,移植到DataMergerService.mergeSubtask()):

  • 提取mainResult文本;生成 ISO 时间戳;
  • 格式化为<info added on ${timestamp}>\n${content}\n</info added on ${timestamp}>块;
  • 追加到subtask.details(不存在则创建),并单独保存新增片段用于展示;
  • 若 prompt 长度 < 100 字符,向subtask.description追加[Updated: ${date}]日期标记。

最后统一writeJSON(tasksPath, data, projectRoot, tag)写回,并保留(当前被注释的)generateTaskFiles()调用点。此外旧实现还包含一个metadata-only 快速路径(update-subtask-by-id.js):当只传metadata而不传 prompt 时,跳过 AI 直接合并 metadata 字段并写盘,这一行为也应在新架构中保留。

CLI 展示、日志与错误处理

  • 更新前展示(仅 CLI text 模式):用cli-table3生成 ID/Title/Status 三列表格(任务标题截断 57 字符、子任务 52 字符),状态通过getStatusWithColor()着色,用boxen输出带边框的标题;批量模式额外输出"已完成子任务如何处理"的信息框;
  • 加载指示器:AI 调用前startLoadingIndicator('Updating tasks with AI...')'Updating subtask...',完成或出错时stopLoadingIndicator(),research 变体有独立文案;
  • 更新后展示:批量模式输出成功条数;子任务模式用绿色边框 boxen 展示子任务 ID、标题与 "Newly Added Snippet"(时间戳内容);最后通过displayAiUsageSummary(telemetryData, 'cli')展示 AI 用量;
  • 日志与调试:按mcpLog/consoleLog分流;getDebugFlag(session)为真时输出子任务更新前后 details、writeJSON 调用、完整错误堆栈;
  • 错误处理分级:上下文采集失败(告警继续)、AI 服务失败(停止并上报)、一般错误(CLI 打印红色错误并process.exit(1),MCP 直接 re-throw)。CLI 模式下对常见错误(API key 缺失、模型过载、任务/子任务不存在、ID 格式非法、空 prompt、空 AI 响应)提供针对性排查提示——例如子任务未找到时建议运行task-master list --with-subtasks查看可用 ID;
  • 返回值契约:成功时批量/单任务返回{ success: true, updatedTasks, telemetryData, tagInfo },子任务返回{ updatedSubtask, telemetryData, tagInfo };失败时 CLI 退出码 1、MCP 抛错、子任务模式返回null

新架构设计:tm-core 中的策略模式实现

迁移计划为update-taskpackages/tm-core下设计了完整的目录结构,遵循 tm-core 的既有约定:领域隔离、依赖注入、抽象基类、接口契约、服务层编排、工厂模式与单一职责原则。

包结构总览

packages/tm-core/ src/commands/update-task/ types.ts # 共享类型、枚举、接口 interfaces/ update-strategy.interface.ts # IUpdateStrategy 契约 update-context.interface.ts # IUpdateContext 契约 display.interface.ts # IDisplayManager 契约 update-task.service.ts # 主编排服务 context-builder.service.ts # 构建 AI 上下文 prompt-builder.service.ts # 构建提示词 >async execute(context: IUpdateContext): Promise<UpdateStrategyResult> { await this.validate(context); const tasks = await this.loadTasks(context); const prompts = await this.buildPrompts(context, tasks); const aiResult = await this.callAIService(context, prompts); const merged = await this.mergeResults(context, aiResult, tasks); return merged; }

子类只需实现validate()loadTasks()getMode()与受保护的getPromptParams(),共享逻辑(提示词构建、AI 调用、数据合并)由基类与三个辅助服务完成。三种具体策略的分工:

  • BulkUpdateStrategy:校验--from存在;加载id >= fromId && status !== 'done'的任务;调用generateObjectService
  • SingleTaskUpdateStrategy:通过TaskIdValidator.validateTaskId()校验整数 ID;加载单个任务;AI 调用与批量相同;
  • SubtaskUpdateStrategy:通过TaskIdValidator.parseSubtaskId()校验点号格式;定位父任务与子任务并携带前后子任务上下文;调用generateTextServicemergeResults()中生成<info added on ${timestamp}>时间戳块追加到subtask.details

ContextBuilderService / PromptBuilderService / DataMergerService三个辅助服务分别封装上下文采集、模板加载与结果合并,各自只依赖已有工具类(ContextGathererFuzzyTaskSearchPromptManager),保证可独立单测。

UpdateStrategyFactorydetectMode()实现了本文第二节的行为检测规则;createStrategy(mode)按枚举创建对应策略并注入依赖,未知模式抛出TaskMasterError

IDisplayManager接口定义showPreUpdate / startLoading / stopLoading / showPostUpdate / showTelemetry / showError六个方法,CLIDisplayManager用 chalk、boxen、cli-table3 实现终端渲染,JSONDisplayManager面向 MCP 输出结构化结果,UpdateDisplayFactory按运行环境选择实现。

依赖注入与初始化

计划在packages/tm-core/src/commands/update-task/index.ts提供工厂函数createUpdateTaskService(configManager, storage),依次创建 logger、ContextBuilderServicePromptManager(复用现有getPromptManager())、PromptBuilderServiceDataMergerServiceAIService(对generateObjectService/generateTextService的包装),组装UpdateStrategyFactoryUpdateDisplayFactory,最后注入UpdateTaskService。CLI 侧apps/cli/src/commands/update-task.command.ts只需调用该工厂并执行——这与现有 CLI 命令的模式一致,例如 next.command.ts 继承Commander.Command作为薄展示层、内部委托TmCore的做法。

分阶段实施路线:11 个 Phase

迁移计划将实施拆分为 11 个阶段,每阶段都有明确的新增文件、测试与复用对象,可按序增量交付:

Phase内容关键产出
1基础与核心类型types.ts、三个接口文件;研究BaseExecutorTaskServiceIStorage的模式
2校验器与工具UpdateInputValidatorTaskIdValidator(移植两个旧文件的校验逻辑)+ 对应 spec
3服务层ContextBuilderService(复用 ContextGatherer/FuzzyTaskSearch)、PromptBuilderService(复用 PromptManager)、DataMergerService(移植 update-tasks.js L250-273 与 update-subtask-by-id.js L291-332 的合并逻辑)+ spec
4策略模式实现抽象基类 + 三种策略;Bulk/Single 用generateObjectService+COMMAND_SCHEMAS['update-tasks'],Subtask 用generateTextService+ spec
5展示层CLIDisplayManager(复用 chalk/boxen/cli-table3/getStatusWithColor)、JSONDisplayManagerUpdateDisplayFactory+ spec
6工厂模式UpdateStrategyFactorycreateStrategy()detectMode()+ spec
7主服务编排UpdateTaskServiceindex.ts导出(类型 + 工厂 + 服务类);集成 spec
8CLI 集成update-task.command.ts(commander 定义);在 CLI 入口注册命令,可选兼容别名
9集成与测试三模式端到端、MCP vs CLI、全清单边界用例、性能对比
10文档与弃用更新命令参考文档、JSDoc、为旧命令加弃用警告、changeset
11清理(未来版本)删除旧文件与兼容垫片,更新全部引用

计划中提到的COMMAND_SCHEMAS来自 src/schemas/registry.js,统一 AI 服务来自 scripts/modules/ai-services-unified.js,这两处是策略层移植时的既有依赖。

测试策略与边界用例

单元测试覆盖:模式检测逻辑、ID 解析与校验、上下文采集集成、各模式提示词构建、数据合并逻辑。集成测试覆盖:批量/单任务/单子任务三条工作流、MCP 与 CLI 双模式运行。边界用例清单包括:

  • tasks.json
  • 非法 ID 格式(如负数、非数字、5..2
  • 不存在的 ID
  • 无子任务的任务
  • 空 AI 响应
  • 上下文采集失败(应告警继续而非中断)

计划中的update-task.service.spec.ts集成测试与data-merger.service.spec.ts单元测试可直接对照旧实现的合并逻辑逐条断言。

向后兼容、风险缓解与成功标准

向后兼容采用渐进式弃用:旧命令保持可用 → 添加弃用警告 → 更新文档 → 下个大版本移除。可选方案是保留旧命令名作为别名内部转发:

task-master update --from=3 --prompt="..." # 仍可用,实际调用 update-task task-master update-subtask --id=3.2 --prompt="..." # 仍可用,实际调用 update-task

高风险区域与对策:

  1. 数据完整性——确保writeJSON不损坏既有数据(保留 subtasks 字段、Map 合并、原子写);
  2. AI 服务兼容性——generateObjectServicegenerateTextService必须同时工作;
  3. 子任务 details 格式——维持时间戳块格式一致性(<info added on ${timestamp}>标签必须成对闭合);
  4. 上下文采集——各模式行为保持一致。

回滚计划:旧文件保留至新版本充分测试;通过版本号升级支持回退;发布前完成全量测试覆盖。

成功标准:清单全部核验通过、各模式测试通过、MCP 集成可用、CLI 展示与既有行为一致、文档更新、无功能回归、性能不劣于现有实现。

结语

这份迁移计划的价值在于:它不是一次简单"搬文件",而是把两个行为相似、实现重复的遗留模块,按照策略模式、模板方法模式、工厂模式和服务层模式重构成单一命令的完整工程蓝图。packages/tm-core的目录骨架、接口契约(如 storage.interface.ts)与apps/cli的 Commander 命令模式均已就绪,迁移者只需按 11 个 Phase 顺序实施,即可在保持 CLI 与 MCP 双模式行为一致的前提下,把任务更新逻辑收敛到可单测、可扩展、可替换策略的新架构中。

【免费下载链接】claude-task-masterAn AI-powered task-management system you can drop into Cursor, Lovable, Windsurf, Roo, and others.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-task-master

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询