Spec Kit 复杂功能开发实战:用任务范围控制与子代理委派化解上下文窗口耗尽
当大型功能顺利走完 /speckit.specify、/speckit.plan、/speckit.tasks 三个阶段后,退化往往发生在 /speckit.implement 执行中途:随着上下文窗口逐渐填满,代理开始偏离计划、忽略任务甚至产生幻觉。本文基于 Handling Complex Features 展开,讲清楚这一问题的根因——上下文窗口耗尽——以及 Spec Kit 提供的四种递进式解法:按任务数量或阶段限制单次执行范围、指示代理使用子代理(sub-agent)委派任务、两者组合,以及最后的"Spec of Specs"分解策略。读完后你能够根据功能规模和所用代理的能力,选择一套无需任何工具链改动的上下文管理方案,让长实现过程稳定可续跑。
问题背景:为什么实现阶段会退化
Spec Kit 的核心流程是先由规格(spec)驱动生成计划与任务清单,再交给代理执行。前三个命令之所以稳定,是因为每次调用只处理一个相对完整的产物;而 /speckit.implement 需要在一个会话内持有整个功能的上下文。当单次执行试图把整个功能都装进上下文窗口时,模型会随着窗口填满而逐渐退化,典型症状包括:
- 在长
/speckit.implement运行中途丢失计划; - 忽略
tasks.md中尚未完成的任务; - 出现幻觉,尤其是上下文压缩(context compaction)被触发的前后。
文档给出的结论是:修复方向不是让模型更强,而是控制每次执行的范围,让每一次调用都远远低于上下文限制。所有方案都建立在同一个机制之上——/speckit.implement 命令接受自由格式的用户输入,代理在继续执行前必须考虑这些输入。这意味着不需要任何工具改造,仅靠给命令附加一句话即可改变其执行范围。
机制基础:为什么"续跑"天然可行
从命令模板源码可以印证上述两个前提。
第一,用户输入是强制项。implement 命令模板开头即声明:
## User Input
$ARGUMENTS
You **MUST** consider the user input before proceeding (if not empty).
$ARGUMENTS 占位符会被展开为你在斜杠命令后附加的任意文本,模板明确要求代理在推进前必须考虑它——这就是"限制任务数量""委派给子代理"等指示得以生效的原因。
第二,任务完成状态持久化在文件里,而非会话里。模板第 8 步要求:
IMPORTANT For completed tasks, make sure to mark the task off as [X] in the tasks file.
也就是说,每完成一个任务,代理会把它在 tasks.md 中的 - [ ] 标记为 - [X]。下次再调用 /speckit.implement 时,代理重新读取同一份 tasks.md,自然会跳过已完成项、从未完成项继续。这正是"分批执行可以无状态衔接"的底层保证。
第三,tasks.md 本身自带可切分的结构。从 任务模板 与 任务生成规则 可见,任务被组织为固定阶段:Phase 1 为 Setup(项目初始化),Phase 2 为 Foundational(阻塞性前置),Phase 3+ 为按优先级排列的用户故事(P1/P2/P3),最后为 Polish 收尾阶段;每个任务都有稳定 ID(T001、T002……),并带有 [P] 标记表示"可并行"(不同文件、无依赖)。阶段名、任务 ID 和 [P] 标记,就是后面四种方案中所有范围限定指令的操作对象。
另外,执行前的前置检查脚本也会验证 tasks.md 存在:implement 命令的 frontmatter 声明执行 check-prerequisites.sh --json --require-tasks --include-tasks,对应实现见 check_prerequisites.py,其中 --require-tasks 参数强制要求 tasks.md 已存在,--include-tasks 将其纳入 AVAILABLE_DOCS 列表供代理读取。
方案一:限制单次执行的任务数量
最简单的做法是不让 /speckit.implement 一次跑完所有任务,而是明确指示它提前停止。按任务 ID 范围限定:
/speckit.implement only execute tasks T001-T010, then stop and report progress
或者按阶段限定:
/speckit.implement only execute the Setup phase, then stop
这里的"Setup phase"直接对应 tasks-template.md 中的 "Phase 1: Setup (Shared Infrastructure)",而 T001-T010 则对应模板中示例任务的编号区间。执行结束后:
- 已完成的任务在
tasks.md中被标记为[X]; - 下一次
/speckit.implement调用读取同一份文件,从断点继续; - 每次运行的上下文占用都被压在一个可控区间内,远离压缩触发点。
按"任务 ID 范围"切分适合任务粒度均匀的功能;按"阶段"切分更符合 tasks-template.md 中描述的依赖结构——Setup 无依赖可立即开始,Foundational 阻塞所有用户故事,用户故事阶段之间可以并行或按优先级顺序推进。先跑完一个阶段再验证,正好利用模板中每个阶段的 Checkpoint 设计。
方案二:指示代理使用子代理委派
如果你的编码代理支持子代理(例如 GitHub Copilot CLI 或 VS Code 的 GitHub Copilot 扩展),可以把单个任务的执行委派出去:
/speckit.implement delegate each parallel [P] task to a sub-agent
原理是:每个子代理获得的是一个聚焦的上下文——一个任务加上相关的计划摘录,而不是完整的功能上下文。这样主会话的上下文几乎不增长,压缩(compaction)永远不会在主会话触发。[P] 恰好是 tasks-template.md 定义的并行标记(不同文件、无依赖),天然适合并行委派;而 implement 命令模板 本身也要求"parallel tasks [P] can run together",两者在语义上完全对齐。
方案三:组合范围限定与委派
对于非常大的功能,把前两个手段叠加使用:
/speckit.implement execute only the Core phase, delegate [P] tasks to sub-agents
这样主会话只处理一个阶段的骨架与串行任务,阶段内的可并行任务 [P] 再分发给子代理。范围限定压低主会话的上下文压力,委派进一步压低单个任务在会话中的驻留时间,两者互为补充。
方案四:把功能分解为更小的规格(Spec of Specs)
当单个阶段本身就已经压垮上下文时,前三招都不够用,此时应把功能拆分为若干可独立规格的子功能。每个子功能拥有自己的 spec.md、plan.md、tasks.md,各自走一遍完整的 specify/plan/tasks/implement 循环。
这就是 "spec of specs" 方法:先做一次分解路径(roadmap pass),把巨型功能拆成若干自包含的小规格;每个子规格小到足以在上下文窗口内完成整个循环。由于它引入了额外的规格维护开销,文档明确建议只保留给其他方法都处理不了的功能。
完整操作流程(如何执行 roadmap 路径、roadmap 工件的结构、子规格如何双向链接回 roadmap、以及一个计费门户的完整示例)见 Spec of Specs。其中有几个要点值得注意:
- roadmap 是刻意保持"浅"的:只命名和排序子功能,不做设计,设计留到各子功能的
/speckit.specify中进行; - roadmap 是一个普通 Markdown 文件(功能级 epic 放
specs/<epic-slug>/roadmap.md,更大的横切 epic 可放顶层ROADMAP.md),每行带稳定 ID、意图、范围边界、依赖与状态; - 子规格的
spec.md开头一行回链 roadmap 条目(如**Input**: Parent roadmap: specs/<epic>/roadmap.md → entry R3),roadmap 表格的Sub-spec列反向指向子规格目录,双向纯文本链接让追溯无需任何工具; - 若要并行构建互不依赖的子功能,可以使用独立的 git worktree,让每次运行都有隔离的 active-feature 状态;
- 若某个子功能仍然过大,可以递归地给它再做一层 roadmap——只在上下文问题实际要求时才深入。
四种方案如何选择
文档给出的选择矩阵:
| 方案 | 适用场景 |
|---|---|
| 限制为 N 个任务或一个阶段 | 任何代理;最简单;不需要子代理支持 |
| 子代理委派 | 支持子代理的代理;最大化并行度 |
| 范围限定 + 委派组合 | 支持子代理的代理上的大型功能;兼顾两者 |
| 分解为更小的规格 | 单个阶段仍然过大、无法在一次运行内处理时 |
文档的建议顺序是:大多数情况下,限制每次运行的任务范围就是最简单的修复;当你的代理支持子代理且你希望并行时,再上委派;只有当一个阶段本身大到一次运行装不下时,才做规格分解。
这套阶梯与 Spec Kit 的整体设计理念一致:规格驱动开发强调多步精炼而非一次性生成(见 What is Spec-Driven Development),而复杂功能处理的本质,就是把"一次生成"进一步细化为"多次有边界、可断点续跑的小步生成"——边界来自 tasks.md 的 ID/阶段/[P] 结构,续跑来自文件化的 [X] 标记,扩展性则来自规格本身的分解。
小结
- 长
/speckit.implement退化的根因是上下文窗口耗尽,修复手段是把每次执行范围压进上下文限制内; - 范围指示能生效,是因为 implement 命令模板 强制代理先考虑用户输入,且 check-prerequisites 脚本 保证执行前
tasks.md就绪; - 断点续跑能生效,是因为任务完成状态以
[X]形式持久化在tasks.md中,任务结构(阶段、ID、[P]标记)由 tasks 模板 标准化; - 按"限制任务数 → 子代理委派 → 组合 → Spec of Specs 分解"逐级升级,优先选最轻的方案,把规格分解留给单阶段仍然过大的极端情况。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00