sdd-apply
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesesdd-apply
sdd-apply
Implements the plan tasks following specs and design, marking progress as it goes.
Triggers: , implement change, write code, apply changes, sdd apply
/sdd-apply <change-name>按照规格说明与设计实现计划任务,同步标记进度。
触发方式:、implement change、write code、apply changes、sdd apply
/sdd-apply <变更名称>Purpose
目的
The implementation phase converts the task plan into real code. The implementer follows the specs (WHAT to do) and the design (HOW to do it), marking tasks as completed in real time.
实现阶段将任务计划转化为实际代码。实现人员需遵循规格说明(要做什么)和设计方案(怎么做),并实时标记任务完成状态。
Process
流程
Skill Resolution
技能路径解析(Skill Resolution)
When the orchestrator launches this sub-agent, it resolves the skill path using:
1. .claude/skills/sdd-apply/SKILL.md (project-local — highest priority)
2. ~/.claude/skills/sdd-apply/SKILL.md (global catalog — fallback)Project-local skills override the global catalog. See for the full algorithm.
docs/SKILL-RESOLUTION.md当编排器(orchestrator)启动此子代理(sub-agent)时,将通过以下优先级解析技能路径:
1. .claude/skills/sdd-apply/SKILL.md (项目本地 — 最高优先级)
2. ~/.claude/skills/sdd-apply/SKILL.md (全局目录 — 备用)项目本地技能会覆盖全局目录技能。完整算法请参考。
docs/SKILL-RESOLUTION.mdStep 0 — Technology Skill Preload
步骤0 — 技术技能预加载
Step 0a — Load project context
步骤0a — 加载项目上下文
Follow Section F (Project Context Load). Non-blocking.
skills/_shared/sdd-phase-common.md遵循 Section F(项目上下文加载)。非阻塞操作。
skills/_shared/sdd-phase-common.mdStep 0 sub-step — Spec context preload
步骤0子步骤 — 规格上下文预加载
Follow Section G (Spec Context Preload). Non-blocking.
skills/_shared/sdd-phase-common.mdBefore reading the change context, I load technology-specific skills to ensure their patterns and conventions are available throughout implementation.
遵循 Section G(规格上下文预加载)。非阻塞操作。
skills/_shared/sdd-phase-common.md在读取变更上下文之前,我会加载特定技术的技能,确保其模式和约定在整个实现过程中可用。
Scope guard
范围校验
I first check whether this is a documentation-only change by inspecting the File Change Matrix in the design artifact:
- →
mem_search(query: "sdd/{change-name}/design").mem_get_observation(id) - If not found and Engram not reachable: design content passed inline from orchestrator.
I scan every file listed in the matrix:
scope_guard_triggered = true
for each file in design.md file change matrix:
if file extension not in [".md", ".yaml", ".yml"]:
scope_guard_triggered = false
break
if scope_guard_triggered:
→ report: "Tech skill preload: skipped (documentation-only change)"
→ skip remainder of Step 0我首先通过检查设计工件中的文件变更矩阵,判断这是否为仅文档变更:
- →
mem_search(query: "sdd/{change-name}/design")。mem_get_observation(id) - 若未找到且无法访问Engram:设计内容由编排器直接传入。
我会扫描矩阵中列出的每个文件:
scope_guard_triggered = true
for each file in design.md file change matrix:
if file extension not in [".md", ".yaml", ".yml"]:
scope_guard_triggered = false
break
if scope_guard_triggered:
→ 报告:"技术技能预加载:已跳过(仅文档变更)"
→ 跳过步骤0剩余部分Stack detection
技术栈检测
I detect the project technology stack using two sources in priority order:
Primary — :
I read the file and extract all technology keywords (case-insensitive, free text).
ai-context/stack.mdSecondary — project config file :
If is absent and a exists at project root with a key, I read it and extract keywords from its values.
config.yamlai-context/stack.mdconfig.yamlproject.stackIf neither source is available:
→ report:
→ skip remainder of Step 0
"Tech skill preload: skipped (no stack source found — ai-context/stack.md absent)"我通过以下两个优先级来源检测项目技术栈:
主要来源 — :
读取文件并提取所有技术关键词(不区分大小写,自由文本)。
ai-context/stack.md次要来源 — 项目配置文件:
若不存在,且项目根目录下的包含键,则读取该键并从其值中提取关键词。
config.yamlai-context/stack.mdconfig.yamlproject.stack若两个来源均不可用:
→ 报告:
→ 跳过步骤0剩余部分
"技术技能预加载:已跳过(未找到技术栈来源 — ai-context/stack.md不存在)"Stack-to-Skill Mapping Table
技术栈-技能映射表
I match detected keywords (case-insensitive substring match) against the following table:
| Keyword(s) | Skill path |
|---|---|
| always (non-doc changes) | |
| react native, expo | |
| react | |
| next, nextjs, next.js | |
| typescript, ts | |
| zustand | |
| tailwind | |
| go, golang | |
Note:andreact nativeare matched beforeexpoto avoid the shorter keyword absorbing the longer one. Match order is top-to-bottom.react
Note: Therow is evaluated after the scope guard. Ifalways (non-doc changes)isscope_guard_triggered(documentation-only change), this row is also skipped.true
Note: This table only lists skills that exist in the global catalog. If a skill path does not exist on disk, it is silently skipped.
我将检测到的关键词(不区分大小写的子串匹配)与下表进行匹配:
| 关键词 | 技能路径 |
|---|---|
| always (non-doc changes) | |
| react native, expo | |
| react | |
| next, nextjs, next.js | |
| typescript, ts | |
| zustand | |
| tailwind | |
| go, golang | |
注意:和react native会在expo之前匹配,避免短关键词覆盖长关键词。匹配顺序为从上到下。react
注意:行在范围校验后评估。若always (non-doc changes)为scope_guard_triggered(仅文档变更),此行也会被跳过。true
注意:此表仅列出全局目录中存在的技能。若技能路径在磁盘上不存在,则会被静默跳过。
Step 0b — Initialize retry counter
步骤0b — 初始化重试计数器
This step initializes the in-memory retry counter that the task execution loop uses to enforce the circuit breaker. It MUST run after the scope guard (regardless of whether the scope guard triggered) and before Step 1.
Read from project config (optional):
apply_max_retriesif config.yaml exists at project root and has key apply_max_retries:
max_attempts = config.yaml.apply_max_retries
→ log: "Retry limit: max_attempts = [value] (source: config.yaml)"
else:
max_attempts = 3 # default
→ log: "Retry limit: max_attempts = 3 (default)"Initialize attempt counter:
attempt_counter = {} # task_id → attempt count; starts empty; per-invocation onlyThe counter is in-memory and per-invocation. Each invocation starts with a fresh counter. If a task was previously blocked and the user resumes by changing back to , the counter resets to 0 for that task.
/sdd-apply[BLOCKED][TODO]Circuit breaker behavior:
When before a new attempt, the task is immediately marked and the phase halts. The user must resolve the block and re-run to resume.
attempt_counter[task_id] >= max_attempts[BLOCKED]/sdd-apply <change-name>此步骤初始化内存重试计数器,任务执行循环将使用该计数器强制执行熔断机制。此步骤必须在范围校验之后(无论范围校验是否触发)、步骤1之前运行。
从项目配置中读取(可选):
apply_max_retriesif config.yaml exists at project root and has key apply_max_retries:
max_attempts = config.yaml.apply_max_retries
→ 日志:"重试限制:max_attempts = [值](来源:config.yaml)"
else:
max_attempts = 3 # 默认值
→ 日志:"重试限制:max_attempts = 3(默认值)"初始化尝试计数器:
attempt_counter = {} # task_id → 尝试次数;初始为空;仅针对当前调用计数器是内存级且仅针对当前调用的。每次调用都会启动一个新的计数器。若某个任务之前被阻塞,用户通过将改回恢复任务,则该任务的计数器会重置为0。
/sdd-apply[BLOCKED][TODO]熔断机制行为:
当新尝试开始前时,该任务会立即被标记为,且当前阶段会暂停。用户必须解决阻塞问题并重新运行才能恢复。
attempt_counter[task_id] >= max_attempts[BLOCKED]/sdd-apply <change-name>Skill loading
技能加载
For each matched skill path:
- If the file exists on disk → read its contents and load its patterns into context
- If the file does not exist on disk → skip silently; note:
"<skill-name>: skipped (file not found at <path>)"
This step MUST NOT produce or under any circumstance. All failure modes degrade to INFO or skip.
status: blockedstatus: failed对于每个匹配的技能路径:
- 若文件存在于磁盘上 → 读取其内容并将其模式加载到上下文中
- 若文件不存在于磁盘上 → 静默跳过;记录:
"<技能名称>:已跳过(在<路径>未找到文件)"
此步骤在任何情况下都不得产生或。所有失败模式都降级为INFO或跳过。
status: blockedstatus: failedDetection report
检测报告
Tech skill preload:
- <skill-name> loaded (source: ai-context/stack.md)
- <skill-name> loaded (source: config.yaml)
- <skill-name>: skipped (file not found at ~/.claude/skills/<skill-name>/SKILL.md)
[or, if entire step skipped:]
Tech skill preload: skipped (documentation-only change)
Tech skill preload: skipped (no stack source found — ai-context/stack.md absent)The list of loaded skills is carried forward and included in the Step 2 detection output line:
(or if preload was skipped or no matches).
"Technology skills loaded: [typescript, react-19, tailwind-4]""none"技术技能预加载:
- <技能名称>已加载(来源:ai-context/stack.md)
- <技能名称>已加载(来源:config.yaml)
- <技能名称>:已跳过(在~/.claude/skills/<技能名称>/SKILL.md未找到文件)
[或者,若整个步骤被跳过:]
技术技能预加载:已跳过(仅文档变更)
技术技能预加载:已跳过(未找到技术栈来源 — ai-context/stack.md不存在)已加载的技能列表会被带入后续流程,并包含在步骤2的检测输出行中:(若预加载被跳过或无匹配项则显示)。
"已加载的技术技能:[typescript, react-19, tailwind-4]""none"Step 1 — Read full context
步骤1 — 读取完整上下文
I read in this order:
- The tasks artifact — which tasks are assigned:
- →
mem_search(query: "sdd/{change-name}/tasks").mem_get_observation(id) - If not found and Engram not reachable: tasks content passed inline from orchestrator.
- The spec artifact — the success criteria (WHAT it must do):
- →
mem_search(query: "sdd/{change-name}/spec").mem_get_observation(id) - If not found and Engram not reachable: spec content passed inline from orchestrator.
- The design artifact — how to implement it (technical decisions, interfaces):
- →
mem_search(query: "sdd/{change-name}/design").mem_get_observation(id) - If not found and Engram not reachable: design content passed inline from orchestrator.
- Project config file (at project root) — if it exists, read optional keys:
config.yaml,diagnosis_commandsrules - — code conventions
ai-context/conventions.md - Existing code files that I will modify or that serve as pattern references
我按以下顺序读取:
- 任务工件 — 分配的任务:
- →
mem_search(query: "sdd/{change-name}/tasks")。mem_get_observation(id) - 若未找到且无法访问Engram:任务内容由编排器直接传入。
- 规格工件 — 成功标准(必须做什么):
- →
mem_search(query: "sdd/{change-name}/spec")。mem_get_observation(id) - 若未找到且无法访问Engram:规格内容由编排器直接传入。
- 设计工件 — 实现方式(技术决策、接口):
- →
mem_search(query: "sdd/{change-name}/design")。mem_get_observation(id) - 若未找到且无法访问Engram:设计内容由编排器直接传入。
- 项目配置文件(项目根目录下的) — 若存在,读取可选键:
config.yaml、diagnosis_commandsrules - — 代码约定
ai-context/conventions.md - 我将修改的现有代码文件或作为模式参考的现有代码文件
Step 2 — Detect Implementation Mode
步骤2 — 检测实现模式
Before implementing, I determine whether to use TDD (test-driven development) mode. I check three sources in priority order:
Source 1 — Explicit config (highest priority):
I read the project config file ( at project root, if it exists) and look for a key:
config.yamltdd- or
tdd: true→ TDD mode is ON. Report:tdd.enabled: true"TDD mode: ON (source: config)" - or
tdd: false→ TDD mode is OFF. Report:tdd.enabled: false. Skip Sources 2 and 3."TDD mode: OFF (explicitly disabled in config)" - Key not present → continue to heuristic detection (Sources 2 and 3).
Source 2 — Testing skills in project CLAUDE.md:
I scan the project's CLAUDE.md skills registry for testing-related skills (e.g. , , , , or any skill whose name or description indicates testing). If found → .
playwrightpytestvitestjestsignal_count++Source 3 — Test file patterns in the codebase:
I search for existing test files matching common patterns: , , , . If at least one match is found → .
*.test.**.spec.*test_**_test.*signal_count++Decision (when no explicit config):
- → TDD mode is ON. Report:
signal_count >= 2"TDD mode: ON (source: testing skill + test files)" - → TDD mode is OFF. Report:
signal_count == 1"TDD mode: OFF ([signal found] but insufficient signals)" - → TDD mode is OFF. Report:
signal_count == 0"TDD mode: OFF"
The detection step MUST NOT install test frameworks, create test files, or modify any configuration. Its only observable effect is the detection report line, which also includes the technology skills summary from Step 0.
在实现之前,我会确定是否使用TDD(测试驱动开发)模式。我按优先级检查三个来源:
来源1 — 显式配置(最高优先级):
读取项目配置文件(若存在,项目根目录下的),查找键:
config.yamltdd- 或
tdd: true→ TDD模式开启。报告:tdd.enabled: true"TDD模式:开启(来源:配置)" - 或
tdd: false→ TDD模式关闭。报告:tdd.enabled: false。跳过来源2和3。"TDD模式:关闭(配置中显式禁用)" - 键不存在 → 继续启发式检测(来源2和3)。
来源2 — 项目CLAUDE.md中的测试技能:
扫描项目的CLAUDE.md技能注册表,查找与测试相关的技能(例如、、、,或名称/描述表明测试的任何技能)。若找到 → 。
playwrightpytestvitestjestsignal_count++来源3 — 代码库中的测试文件模式:
搜索符合常见模式的现有测试文件:、、、。若至少找到一个匹配项 → 。
*.test.**.spec.*test_**_test.*signal_count++决策(无显式配置时):
- → TDD模式开启。报告:
signal_count >= 2"TDD模式:开启(来源:测试技能 + 测试文件)" - → TDD模式关闭。报告:
signal_count == 1"TDD模式:关闭(找到[信号]但信号不足)" - → TDD模式关闭。报告:
signal_count == 0"TDD模式:关闭"
检测步骤不得安装测试框架、创建测试文件或修改任何配置。其唯一可观察的效果是检测报告行,该行还包含步骤0的技术技能摘要。
Step 3 — Verify work scope
步骤3 — 验证工作范围
The orchestrator tells me which tasks to implement (e.g. "Phase 1, tasks 1.1-1.3").
I implement ONLY those tasks. I do not advance to the next ones without confirmation.
编排器会告诉我要实现哪些任务(例如“阶段1,任务1.1-1.3”)。
我仅实现这些任务。未经确认,我不会推进到下一批任务。
Step 4 — Diagnosis
步骤4 — 诊断
Before making any file change for each assigned task, I MUST execute a Diagnosis Step. No file write or edit operation is permitted until the block for that task has been written.
DIAGNOSIS在为每个分配的任务进行任何文件变更之前,我必须执行诊断步骤。在该任务的块编写完成之前,不得进行任何文件写入或编辑操作。
DIAGNOSIS4.1 — Read files to be modified
4.1 — 读取待修改文件
I read every file I intend to modify in its current state. For tasks that create new files, I read related files that serve as pattern references.
我读取每个我打算修改的文件的当前状态。对于创建新文件的任务,我读取作为模式参考的相关文件。
4.2 — Run diagnostic commands
4.2 — 运行诊断命令
I check the project config file ( at project root) for a key:
config.yamldiagnosis_commands- Present: I run each listed command (expected to be read-only). I capture the output (or a summary) for inclusion in the block. A command that exits non-zero is recorded as a failure; it MUST NOT block the Diagnosis Step — I note the failure in the Risk field and continue.
DIAGNOSIS - Absent: I use only auto-detected read-only commands relevant to the task (or none). I note in the block.
"diagnosis_commands: not configured"
我检查项目配置文件(项目根目录下的)是否存在键:
config.yamldiagnosis_commands- 存在:我运行每个列出的命令(应为只读命令)。我捕获输出(或摘要)以包含在块中。退出码非零的命令会被记录为失败;不得阻塞诊断步骤 — 我会在风险字段中记录失败并继续。
DIAGNOSIS - 不存在:我仅使用与任务相关的自动检测到的只读命令(或不使用)。在块中记录。
"diagnosis_commands: 未配置"
4.3 — Write DIAGNOSIS block
4.3 — 编写DIAGNOSIS块
I write the following structured block in my task output before proceeding to implementation:
DIAGNOSIS — Task X.Y:
1. Files to be modified: [list of paths]
2. Diagnostic command outputs:
- [command]: [output summary]
(or "none applicable" / "diagnosis_commands: not configured")
3. Current behavior observation: [what the code actually does now]
4. Relevant data/state: [key data values, config, environment state]
5. Hypothesis: "The bug/issue is [X] because [Y].
Changing [Z] will achieve [expected behavior] because [rationale]."
6. Risk: [what could go wrong with this change]For file-creation tasks: field 3 describes the gap (what is absent), field 5 describes what the new file is intended to do and why.
在开始实现之前,我会在任务输出中编写以下结构化块:
DIAGNOSIS — 任务X.Y:
1. 待修改文件:[路径列表]
2. 诊断命令输出:
- [命令]:[输出摘要]
(或“无适用命令” / “diagnosis_commands: 未配置”)
3. 当前行为观察:[代码当前实际执行的操作]
4. 相关数据/状态:[关键数据值、配置、环境状态]
5. 假设:“缺陷/问题是[X],因为[Y]。
修改[Z]将实现[预期行为],因为[理由]。”
6. 风险:[此变更可能出现的问题]对于创建文件的任务:字段3描述缺失的内容(即缺少什么),字段5描述新文件的预期用途及原因。
4.4 — Check for contradictions
4.4 — 检查矛盾
If the Diagnosis Step reveals that the current system state contradicts the assumptions underlying the task description, I MUST produce a warning and pause for user confirmation before proceeding:
MUST_RESOLVE⚠️ MUST_RESOLVE — Diagnosis finding:
Task X.Y assumes [A], but current state shows [B].
This may indicate the task description is based on incorrect assumptions.
Confirm how to proceed:
Option 1: [proceed with updated understanding]
Option 2: [revise task description]If there are multiple contradictions, I MUST list each one as a separate item within the single block and wait for one combined user confirmation before proceeding.
MUST_RESOLVEIf diagnosis confirms the expected state, I proceed immediately to Step 5.
若诊断步骤发现当前系统状态与任务描述所基于的假设相矛盾,我必须生成警告并暂停,等待用户确认后再继续:
MUST_RESOLVE⚠️ MUST_RESOLVE — 诊断发现:
任务X.Y假设[A],但当前状态显示[B]。
这可能表明任务描述基于错误的假设。
请确认如何继续:
选项1:[基于更新后的理解继续]
选项2:[修订任务描述]若存在多个矛盾,我必须在单个块中将每个矛盾列为单独项,并等待用户的统一确认后再继续。
MUST_RESOLVE若诊断确认预期状态,我会立即进入步骤5。
Step 5 — Implement task by task
步骤5 — 逐任务实现
Step 5a — Check for warnings before executing each task
步骤5a — 执行每个任务前检查警告
Before executing any task, I inspect the task entry in for a or marker.
tasks.md[WARNING: MUST_RESOLVE][WARNING: ADVISORY]If is present and no has been recorded yet:
[WARNING: MUST_RESOLVE]Answer:I MUST stop and present the following blocking gate to the user:
⛔ BLOCKED — Task X.Y has an unresolved MUST_RESOLVE warning:
[warning text from tasks.md]
You must answer before implementation can proceed:
→ [Question from tasks.md or derived from warning]
Type your answer to continue.I MUST NOT continue to the next step until an answer is received. I MUST NOT offer "Ready to continue?" or any other prompt that allows bypassing the answer.
Answer recording: Once the user provides an answer, I MUST append the following block to the task entry in , immediately after the line:
tasks.mdQuestion:markdown
Answer: [exact text of the user's answer]
Answered: [ISO 8601 timestamp, e.g., 2026-03-10T14:35:00Z]After recording the answer, I proceed with task execution.
If is present AND an is already recorded:
[WARNING: MUST_RESOLVE]Answer:The warning has already been resolved. I proceed with task execution without presenting the blocking gate again.
If is present:
[WARNING: ADVISORY]I log the advisory warning to the progress output in the format:
ℹ️ ADVISORY — Task X.Y: [warning text]I MUST NOT request user input. I continue execution of the task immediately after logging.
在执行任何任务之前,我会检查中的任务条目是否存在或标记。
tasks.md[WARNING: MUST_RESOLVE][WARNING: ADVISORY]若存在且尚未记录:
[WARNING: MUST_RESOLVE]Answer:我必须停止并向用户呈现以下阻塞提示:
⛔ BLOCKED — 任务X.Y存在未解决的MUST_RESOLVE警告:
[tasks.md中的警告文本]
您必须先回答才能继续实现:
→ [tasks.md中的问题或从警告中衍生的问题]
输入您的答案以继续。在收到答案之前,我不得继续下一步。我不得提供“准备继续?”或任何其他允许绕过答案的提示。
答案记录: 用户提供答案后,我必须将以下块追加到中的任务条目,紧跟在行之后:
tasks.mdQuestion:markdown
Answer: [用户答案的准确文本]
Answered: [ISO 8601时间戳,例如2026-03-10T14:35:00Z]记录答案后,我会继续执行任务。
若存在且已记录:
[WARNING: MUST_RESOLVE]Answer:警告已解决。我会继续执行任务,不再呈现阻塞提示。
若存在:
[WARNING: ADVISORY]我会将警告记录到进度输出中,格式如下:
ℹ️ ADVISORY — 任务X.Y:[警告文本]我不得请求用户输入。记录后立即继续执行任务。
If TDD mode is NOT active (standard flow):
若TDD模式未激活(标准流程):
For each assigned task:
- I check for warnings per Step 5a (MUST_RESOLVE blocks; ADVISORY is logged and continues)
- I read the task in tasks.md — extract (e.g.,
task_id,1.1)2.3 - Check attempt counter BEFORE attempting the task:
- If is undefined → set
attempt_counter[task_id]attempt_counter[task_id] = 0 - If :
attempt_counter[task_id] >= max_attempts- → Mark task in tasks.md (see BLOCKED State section below)
[BLOCKED] - → Halt the current phase immediately
- → Report BLOCKED state to user (see BLOCKED Reporting section below)
- → STOP — do NOT continue to the next task
- → Mark task
- If
- Increment attempt counter: — record the current strategy snapshot:
attempt_counter[task_id]++file_snapshot = list of all files this attempt will modify - I consult the specs for the affected domain (success criteria)
- I consult the design (interfaces, decisions, patterns)
- I read existing code in related files (to follow the pattern)
- I implement the task following specs and design
- Check success:
- Success (all file operations complete, output as expected, no tool errors):
- Mark task in tasks.md
[x] - Optionally reset (clean state)
attempt_counter[task_id] = 0 - Proceed to next task
- Mark task
- Failure (tool error, validation error, unexpected output):
- Capture current and the error output
file_snapshot_after - Same-strategy detection: compare with the snapshot from the previous attempt (if any):
file_snapshot_after- If both attempts modified the same files in the same way (see Same-Strategy Detection below):
- → Mark task with message
[BLOCKED]"Identical strategy attempted twice — manual intervention required" - → Halt the current phase
- → Report BLOCKED state to user
- → STOP — do NOT continue to the next task
- → Mark task
- Otherwise (different strategy):
- Increment again
attempt_counter[task_id] - If :
attempt_counter[task_id] >= max_attempts- → Mark task (see BLOCKED State section below)
[BLOCKED] - → Halt phase, report to user
- → STOP — do NOT continue to the next task
- → Mark task
- Otherwise: re-attempt the task with a different approach (loop back to step 8)
- Increment
- If both attempts modified the same files in the same way (see Same-Strategy Detection below):
- Capture current
- Success (all file operations complete, output as expected, no tool errors):
对于每个分配的任务:
- 检查警告,遵循步骤5a(MUST_RESOLVE会阻塞;ADVISORY会被记录并继续)
- 读取任务,从tasks.md中提取(例如
task_id、1.1)2.3 - 尝试任务前检查计数器:
- 若未定义 → 设置
attempt_counter[task_id]attempt_counter[task_id] = 0 - 若:
attempt_counter[task_id] >= max_attempts- → 在tasks.md中将任务标记为(参见下方BLOCKED状态部分)
[BLOCKED] - → 立即暂停当前阶段
- → 向用户报告BLOCKED状态(参见下方BLOCKED报告部分)
- → 停止 — 不得继续下一个任务
- → 在tasks.md中将任务标记为
- 若
- 递增计数器: — 记录当前策略快照:
attempt_counter[task_id]++file_snapshot = 此尝试将修改的所有文件列表 - 查阅规格说明,了解受影响领域的成功标准
- 查阅设计方案(接口、决策、模式)
- 读取现有代码,参考相关文件中的模式
- 实现任务,遵循规格说明与设计方案
- 检查成功状态:
- 成功(所有文件操作完成,输出符合预期,无工具错误):
- 在tasks.md中将任务标记为
[x] - 可选重置(清除状态)
attempt_counter[task_id] = 0 - 继续下一个任务
- 在tasks.md中将任务标记为
- 失败(工具错误、验证错误、意外输出):
- 捕获当前和错误输出
file_snapshot_after - 相同策略检测: 将与上一次尝试的快照(若有)进行比较:
file_snapshot_after- 若两次尝试以相同方式修改了相同文件(参见下方相同策略检测):
- → 将任务标记为,消息为
[BLOCKED]"已尝试两次相同策略 — 需要人工干预" - → 暂停当前阶段
- → 向用户报告BLOCKED状态
- → 停止 — 不得继续下一个任务
- → 将任务标记为
- 否则(策略不同):
- 再次递增
attempt_counter[task_id] - 若:
attempt_counter[task_id] >= max_attempts- → 将任务标记为(参见下方BLOCKED状态部分)
[BLOCKED] - → 暂停阶段,向用户报告
- → 停止 — 不得继续下一个任务
- → 将任务标记为
- 否则:采用不同方法重新尝试任务(回到步骤8循环)
- 再次递增
- 若两次尝试以相同方式修改了相同文件(参见下方相同策略检测):
- 捕获当前
- 成功(所有文件操作完成,输出符合预期,无工具错误):
Same-Strategy Detection
相同策略检测
Two consecutive attempts are the same strategy if they modified exactly the same set of files AND the content changes to each file were identical:
def is_same_strategy(previous_attempt, current_attempt):
files_prev = set(previous_attempt.files_modified.keys())
files_curr = set(current_attempt.files_modified.keys())
# Different files touched → different strategy
if files_prev != files_curr:
return False
# Same files → compare content changes
for file_path in files_prev:
if previous_attempt.files_modified[file_path] != current_attempt.files_modified[file_path]:
return False
return True # Same files, same content changes → same strategyIf unsure whether strategies match, count them as different (conservative default).
若连续两次尝试修改了完全相同的文件集,且每个文件的内容变更完全相同,则视为相同策略:
def is_same_strategy(previous_attempt, current_attempt):
files_prev = set(previous_attempt.files_modified.keys())
files_curr = set(current_attempt.files_modified.keys())
# 修改的文件不同 → 策略不同
if files_prev != files_curr:
return False
# 文件相同 → 比较内容变更
for file_path in files_prev:
if previous_attempt.files_modified[file_path] != current_attempt.files_modified[file_path]:
return False
return True # 文件相同,内容变更相同 → 策略相同若不确定策略是否匹配,视为不同(保守默认)。
BLOCKED State — Marking tasks.md
BLOCKED状态 — 标记tasks.md
When a task must be marked BLOCKED, I update BEFORE halting or reporting. The task line is changed from to , and a block is appended immediately below:
tasks.md- [ ] X.Y description- [BLOCKED] X.Y descriptionmarkdown
- [BLOCKED] Task X.Y — description
- Attempts: N/max_attempts
- Tried:
1. [summary of first attempt: what files were modified, what error occurred]
2. [summary of second attempt]
3. [summary of third attempt]
- Last error: [the error message or output from the final attempt]
- Resolution required: [specific, actionable instruction for the user — not vague]The attempt summary MUST include:
- What files were modified in that attempt
- What error or failure was observed
- For same-strategy detection blocks: note "Identical strategy detected"
当任务必须标记为BLOCKED时,我会在暂停或报告之前更新。任务行从改为,并在其下方立即追加一个块:
tasks.md- [ ] X.Y description- [BLOCKED] X.Y descriptionmarkdown
- [BLOCKED] 任务X.Y — 描述
- 尝试次数:N/max_attempts
- 已尝试:
1. [第一次尝试摘要:修改了哪些文件,发生了什么错误]
2. [第二次尝试摘要]
3. [第三次尝试摘要]
- 最后错误:[最后一次尝试的错误消息或输出]
- 需要解决:[给用户的具体、可操作的指令 — 不得模糊]尝试摘要必须包含:
- 该尝试中修改了哪些文件
- 观察到的错误或失败
- 对于相同策略检测阻塞:记录“检测到相同策略”
BLOCKED Reporting — Output to user
BLOCKED报告 — 向用户输出
After updating , I report the BLOCKED state to the user:
tasks.md⛔ Task X.Y BLOCKED after N attempts.
What was tried:
1. [attempt 1 summary]
2. [attempt 2 summary]
3. [attempt 3 summary]
Last error: [error from final attempt]
tasks.md updated. Manual intervention required.
Resume after resolving: /sdd-apply <change-name>I MUST NOT continue to the next task or the next phase after this report.
更新后,我会向用户报告BLOCKED状态:
tasks.md⛔ 任务X.Y在N次尝试后被阻塞。
已尝试的操作:
1. [尝试1摘要]
2. [尝试2摘要]
3. [尝试3摘要]
最后错误:[最后一次尝试的错误]
tasks.md已更新。需要人工干预。
解决后恢复:/sdd-apply <change-name>报告后,我不得继续下一个任务或下一阶段。
If TDD mode is active (RED-GREEN-REFACTOR flow):
若TDD模式激活(RED-GREEN-REFACTOR流程):
For each assigned task:
- I check for warnings per Step 5a (MUST_RESOLVE blocks; ADVISORY is logged and continues)
- I read the task in tasks.md — extract
task_id - Check attempt counter BEFORE attempting the task (same logic as standard flow step 3): if , mark
attempt_counter[task_id] >= max_attempts, halt phase, report to user, STOP.[BLOCKED] - Increment attempt counter:
attempt_counter[task_id]++ - I consult the specs for the affected domain — identify the Given/When/Then scenarios this task covers
- I consult the design (interfaces, decisions, patterns)
- I read existing code in related files (to follow the pattern)
- RED — Write a failing test:
- I write a test that captures the expected behavior from the spec scenario(s)
- The test name or description SHOULD reference the spec scenario name
- I run the test to confirm it fails. If it passes unexpectedly, I report a DEVIATION noting the behavior was already implemented
- GREEN — Write minimum code to pass:
- I write only the minimum code necessary to make the test pass
- I do NOT add extra features, optimizations, or abstractions in this phase
- I run the test to confirm it passes
- REFACTOR — Clean up while tests stay green:
- I clean up the code (remove duplication, improve naming, etc.)
- I run the tests after refactoring to confirm they still pass
- If a test breaks during refactoring, I fix the code (not the test) to restore the green state
- I mark the task as complete in tasks.md: — only after REFACTOR is done
- [x]
对于每个分配的任务:
- 检查警告,遵循步骤5a(MUST_RESOLVE会阻塞;ADVISORY会被记录并继续)
- 读取任务,从tasks.md中提取
task_id - 尝试任务前检查计数器(与标准流程步骤3逻辑相同):若,标记为
attempt_counter[task_id] >= max_attempts,暂停阶段,向用户报告,停止。[BLOCKED] - 递增计数器:
attempt_counter[task_id]++ - 查阅规格说明,了解受影响领域 — 确定此任务覆盖的Given/When/Then场景
- 查阅设计方案(接口、决策、模式)
- 读取现有代码,参考相关文件中的模式
- RED — 编写失败的测试:
- 编写一个测试,捕获规格说明场景中的预期行为
- 测试名称或描述应引用规格说明场景名称
- 运行测试以确认失败。若意外通过,我会报告一个DEVIATION,说明该行为已被实现
- GREEN — 编写最少代码使测试通过:
- 仅编写使测试通过所需的最少代码
- 此阶段不得添加额外功能、优化或抽象
- 运行测试以确认通过
- REFACTOR — 保持测试通过的同时清理代码:
- 清理代码(移除重复、改进命名等)
- 重构后运行测试以确认仍通过
- 若重构期间测试失败,修复代码(而非测试)以恢复通过状态
- 在tasks.md中标记任务完成:— 仅在REFACTOR完成后标记
- [x]
Step 6 — Respect the design
步骤6 — 遵循设计方案
If during implementation I find that the design has a problem:
- I do NOT fix it silently
- I note it in my report as "DEVIATION: [what and why]"
- If it is a blocker, I stop and report
status: blocked
若在实现过程中发现设计方案存在问题:
- 不得静默修复
- 在报告中记录为“DEVIATION:[问题及原因]”
- 若为阻塞问题,停止并报告
status: blocked
Step 7 — Update progress in tasks.md
步骤7 — 在tasks.md中更新进度
I update the progress counter in tasks.md:
markdown
undefined我会更新tasks.md中的进度计数器:
markdown
undefinedProgress: [completed]/[total] tasks
进度:[已完成]/[总任务数] 任务
And I mark each completed task:
```markdown
- [x] 1.1 Create `src/types/auth.types.ts` ✓
- [x] 1.2 Create `src/schemas/auth.schema.ts` ✓
- [ ] 1.3 Modify `src/config/jwt.config.ts`
并标记每个已完成的任务:
```markdown
- [x] 1.1 创建`src/types/auth.types.ts` ✓
- [x] 1.2 创建`src/schemas/auth.schema.ts` ✓
- [ ] 1.3 修改`src/config/jwt.config.ts`Quality Gate
质量门
I always follow project conventions
始终遵循项目约定
If exists, I apply it strictly.
If not, I observe the existing code and follow its patterns.
ai-context/conventions.md若存在,我会严格遵循。
若不存在,我会观察现有代码并遵循其模式。
ai-context/conventions.mdI load technology skills if applicable
加载适用的技术技能
Technology skills and are loaded automatically in Step 0 — Technology Skill Preload. No manual judgment is required here.
solid-ddd技术技能和会在步骤0 — 技术技能预加载中自动加载。无需人工判断。
solid-dddQuality Gate checklist
质量门检查清单
Before marking any code task , I evaluate each criterion below. For each item I mark one of: ✅ (satisfied) | ❌ VIOLATION | N/A — [reason].
[x]- Single Responsibility (SRP): Does each new or modified class, function, or module have exactly one reason to change? Signal: can it be described in one sentence without using "and"? If not → .
QUALITY_VIOLATION: SRP — <description> - Abstraction appropriateness (OCP): Is new behavior added via extension (new file/class/interface) rather than modification of existing stable code? Are abstractions justified by actual reuse or testability need today — not speculatively? Premature abstractions with no current consumer → .
QUALITY_VIOLATION: OCP — <description> - Dependency direction (DIP): Do high-level modules depend on abstractions (interfaces/ports), not on concrete implementations? Dependencies pointing inward toward stable abstractions → PASS. Outward dependencies on volatile implementations → .
QUALITY_VIOLATION: DIP — <description> - Domain model integrity: Is business logic inside domain objects (entities, aggregates, value objects), not leaked into services or controllers? An anemic domain model (domain objects with only getters/setters and no behavior) → . Mark N/A if the task does not touch domain model code.
QUALITY_VIOLATION: Domain model — <description> - Layer separation: Does the code respect the architectural layers defined in the design (e.g., domain → application → infrastructure)? Cross-layer leakage (e.g., infrastructure detail in a domain entity) → .
QUALITY_VIOLATION: Layer separation — <description> - No scope creep: Does the implementation stay strictly within the task's defined scope (tasks.md + design.md)? Files or features outside the scope → , escalated to
QUALITY_VIOLATION: Scope creep — <description>if it contradicts an observable behavior in the spec.DEVIATION - Naming clarity: Do names (classes, functions, variables) reveal intent without requiring a comment to explain them? If a name needs a comment to be understood, rename it first → .
QUALITY_VIOLATION: Naming — <description>
Reporting rules:
- : the criterion does not apply to this task (e.g., "task adds a CLI flag — no domain model touched").
N/A — [one-line reason] - : criterion fails. Fix the code BEFORE marking
QUALITY_VIOLATION: <principle> — <description>. If fixing requires scope outside this task, report as[x]and setDEVIATION: <principle> — <description>.status: warning - Non-contradicting violations do NOT block the apply phase. The orchestrator MUST surface all notes in the phase summary.
QUALITY_VIOLATION - A violation that contradicts a scenario in the spec MUST be escalated to and MUST set
DEVIATION.status: warning
在将任何代码任务标记为之前,我会评估以下每个标准。对于每个项目,我会标记:✅(满足)| ❌ 违规 | N/A — [原因]。
[x]- 单一职责原则(SRP):每个新增或修改的类、函数或模块是否只有一个变更理由?判断信号:能否用一句话描述且不使用“和”?若不能 → 。
QUALITY_VIOLATION: SRP — <描述> - 抽象适当性(OCP):是否通过扩展(新文件/类/接口)添加新行为,而非修改现有稳定代码?抽象是否基于当前实际复用或可测试性需求,而非推测性的?无当前使用者的过早抽象 → 。
QUALITY_VIOLATION: OCP — <描述> - 依赖方向(DIP):高层模块是否依赖抽象(接口/端口),而非具体实现?依赖是否指向内部稳定抽象 → 通过。依赖外部易变实现 → 。
QUALITY_VIOLATION: DIP — <描述> - 领域模型完整性:业务逻辑是否在领域对象(实体、聚合根、值对象)内部,而非泄露到服务或控制器中?贫血领域模型(领域对象仅包含getter/setter且无行为) → 。若任务未涉及领域模型代码,标记为N/A。
QUALITY_VIOLATION: Domain model — <描述> - 分层分离:代码是否遵循设计中定义的架构层(例如领域 → 应用 → 基础设施)?跨层泄露(例如领域实体中包含基础设施细节) → 。
QUALITY_VIOLATION: Layer separation — <描述> - 无范围蔓延:实现是否严格遵循任务定义的范围(tasks.md + design.md)?超出范围的文件或功能 → ,若与规格说明中的可观察行为矛盾,则升级为
QUALITY_VIOLATION: Scope creep — <描述>。DEVIATION - 命名清晰性:名称(类、函数、变量)是否无需注释即可表明意图?若名称需要注释才能理解,先重命名 → 。
QUALITY_VIOLATION: Naming — <描述>
报告规则:
- :该标准不适用于此任务(例如“任务添加CLI标志 — 未涉及领域模型”)。
N/A — [一行理由] - :标准未满足。在标记
QUALITY_VIOLATION: <原则> — <描述>之前修复代码。若修复需要超出此任务的范围,报告为[x]并设置DEVIATION: <原则> — <描述>。status: warning - 非矛盾违规不得阻塞应用阶段。编排器必须在阶段摘要中显示所有记录。
QUALITY_VIOLATION - 与规格说明场景矛盾的违规必须升级为并设置
DEVIATION。status: warning
No over-engineering
避免过度设计
- I implement the minimum necessary to pass the spec's scenarios
- I do not add features that are not in the proposal
- I do not refactor code that is not part of the change
- 仅实现满足规格说明场景所需的最少代码
- 不添加提案中未包含的功能
- 不重构不属于变更范围的代码
Output to Orchestrator
向编排器输出
json
{
"status": "ok|warning|blocked|failed",
"summary": "Implemented [N] tasks of [total]. Phase [X] complete. [TDD mode: active — RED/GREEN/REFACTOR cycle used per task.]",
"tdd_mode": true,
"artifacts": [
"src/services/auth.service.ts — created",
"src/types/auth.types.ts — created",
"engram:sdd/{change-name}/tasks — updated"
],
"deviations": ["DEVIATION in task 2.1: [description and reason]"],
"next_recommended": ["sdd-apply (Phase 2) — if more phases remain", "/sdd-verify <change-name> — verify against specs before committing (run after all phases are complete)"],
"risks": []
}Thefield istdd_modewhen TDD mode was active,trueotherwise. Whenfalse, thetruefield mentions that TDD mode was used.summary
Implementation complete — next step: When all phases are done, the only permitted next-step suggestion is:Continue with verification? Reply **yes** to proceed or **no** to pause. _(Manual: `/sdd-verify <change-name>`)_The summary MUST NOT suggestor/commitat any phase.git commit
json
{
"status": "ok|warning|blocked|failed",
"summary": "已实现[总任务数]中的[N]个任务。阶段[X]完成。[TDD模式:激活 — 每个任务使用RED/GREEN/REFACTOR循环。]",
"tdd_mode": true,
"artifacts": [
"src/services/auth.service.ts — 已创建",
"src/types/auth.types.ts — 已创建",
"engram:sdd/{change-name}/tasks — 已更新"
],
"deviations": ["任务2.1中的DEVIATION:[描述及原因]"],
"next_recommended": ["sdd-apply(阶段2) — 若存在更多阶段", "/sdd-verify <change-name> — 提交前对照规格说明验证(所有阶段完成后运行)"],
"risks": []
}当TDD模式激活时,字段为tdd_mode,否则为true。当为false时,true字段会提及使用了TDD模式。summary
实现完成 — 下一步: 所有阶段完成后,唯一允许的下一步建议是:是否继续验证?回复**yes**继续或**no**暂停。 _(手动:`/sdd-verify <change-name>`)_摘要不得在任何阶段建议或/commit。git commit
Rules
规则
- I read specs BEFORE writing code — they are my acceptance criteria
- I follow design decisions — I do not ignore or silently improve them
- I follow existing project patterns — I do not introduce new ones without justification
- I mark tasks as completed AT THE MOMENT I finish them
- If a task is blocked, I stop and report — I do not skip it
- I do not implement tasks outside my assigned scope
- I do not modify specs or design during implementation
- If something in the spec is ambiguous, I ask before assuming
- warnings MUST block execution until the user provides an explicit answer — there is no skip option
MUST_RESOLVE - warnings MUST be logged to output but MUST NOT interrupt the execution flow or request user input
ADVISORY
- 编写代码前先阅读规格说明 — 它们是我的验收标准
- 遵循设计决策 — 不得忽略或静默改进
- 遵循现有项目模式 — 无正当理由不得引入新模式
- 完成任务后立即标记为已完成
- 若任务被阻塞,停止并报告 — 不得跳过
- 不得实现超出分配范围的任务
- 实现期间不得修改规格说明或设计方案
- 若规格说明存在歧义,先询问再假设
- 警告必须阻塞执行,直到用户提供明确答案 — 无跳过选项
MUST_RESOLVE - 警告必须记录到输出,但不得中断执行流程或请求用户输入
ADVISORY