speccrew 0.7.24 → 0.7.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.speccrew/agents/speccrew-task-worker.md +7 -0
- package/.speccrew/skills/speccrew-pm-requirement-clarify/SKILL.md +31 -4
- package/.speccrew/skills/speccrew-pm-requirement-clarify/workflow.agentflow.xml +69 -11
- package/.speccrew/skills/speccrew-task-worker-execution/workflow.agentflow.xml +22 -5
- package/lib/commands/update.js +10 -8
- package/package.json +1 -1
|
@@ -100,6 +100,13 @@ Receive from the calling Agent:
|
|
|
100
100
|
|
|
101
101
|
If the skill file is not found, report an error with the attempted paths.
|
|
102
102
|
|
|
103
|
+
### Skill Path Resolution
|
|
104
|
+
|
|
105
|
+
When Worker loads a skill (via `skill_name` or `skill_path` parameter):
|
|
106
|
+
1. Resolve the skill directory path (e.g., `.qoder/skills/speccrew-pm-requirement-clarify/`)
|
|
107
|
+
2. Set `skill_path` variable to the resolved directory path (NOT the SKILL.md file path)
|
|
108
|
+
3. This `skill_path` is passed to the skill's workflow execution context, enabling the skill to reference templates, scripts, and other resources within the skill directory using `${skill_path}/templates/...` syntax
|
|
109
|
+
|
|
103
110
|
### 3. Execute Task
|
|
104
111
|
|
|
105
112
|
**If `skill_path` or `skill_name` is provided:**
|
|
@@ -35,10 +35,37 @@ Applies ISA-95 Stage 1 (Domain Description) for clarification:
|
|
|
35
35
|
|
|
36
36
|
## Templates Used
|
|
37
37
|
|
|
38
|
-
| Template | Path | Purpose |
|
|
39
|
-
|
|
40
|
-
| Clarification Questions | `templates/CLARIFICATION-QUESTIONS-TEMPLATE.md` | Round-based questionnaire for user clarification |
|
|
41
|
-
| Clarification Summary | `templates/CLARIFICATION-SUMMARY-TEMPLATE.md` | Final summary document with all Q&A and decisions |
|
|
38
|
+
| Template | Path | When to Load | Purpose |
|
|
39
|
+
|----------|------|-------------|----------|
|
|
40
|
+
| Clarification Questions | `templates/CLARIFICATION-QUESTIONS-TEMPLATE.md` | **Inside Loop L1** (each round) | Round-based questionnaire for user clarification |
|
|
41
|
+
| Clarification Summary | `templates/CLARIFICATION-SUMMARY-TEMPLATE.md` | **After G3 guard passes** (sufficiency_checks_passed == true) | Final summary document with all Q&A and decisions |
|
|
42
|
+
|
|
43
|
+
> **CRITICAL**: These two templates are used in **separate phases**. NEVER load both templates at the same time.
|
|
44
|
+
> - During the clarification loop: ONLY load `CLARIFICATION-QUESTIONS-TEMPLATE.md`
|
|
45
|
+
> - After ALL sufficiency checks pass: ONLY then load `CLARIFICATION-SUMMARY-TEMPLATE.md`
|
|
46
|
+
|
|
47
|
+
## Execution Flow (MANDATORY sequence)
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Step 1: Read requirement document
|
|
51
|
+
Step 2: Read system knowledge (if exists)
|
|
52
|
+
Step 3: Determine complexity mode (simple/complex/auto-detect)
|
|
53
|
+
Step 4: Initialize loop variables
|
|
54
|
+
Step 5: Clarification Loop (both simple and complex modes):
|
|
55
|
+
5a. Load CLARIFICATION-QUESTIONS-TEMPLATE.md (ONLY this template)
|
|
56
|
+
5b. Generate .clarification-questions-round-{N}.md from template
|
|
57
|
+
5c. *** HARD STOP *** Wait for user to answer questions (user-confirm event)
|
|
58
|
+
5d. Read user's answered questions file
|
|
59
|
+
5e. Perform sufficiency checks (MUST have real user answers)
|
|
60
|
+
5f. If checks fail and rounds remain → back to 5a
|
|
61
|
+
5g. If checks pass → exit loop
|
|
62
|
+
Step 6: Guard Gateway G3 (sufficiency_checks_passed == true required)
|
|
63
|
+
6a. Load CLARIFICATION-SUMMARY-TEMPLATE.md (ONLY now)
|
|
64
|
+
6b. Generate .clarification-summary.md from template
|
|
65
|
+
6c. Checkpoint: clarification complete
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> **FORBIDDEN**: Skipping Step 5c (user-confirm), loading summary template during Step 5, or generating summary without user answers.
|
|
42
69
|
|
|
43
70
|
---
|
|
44
71
|
|
|
@@ -86,19 +86,58 @@
|
|
|
86
86
|
<!-- Step 5: Execute Clarification -->
|
|
87
87
|
<block type="gateway" id="G2" mode="exclusive" desc="Execute clarification based on mode">
|
|
88
88
|
<branch test="${complexity} == 'simple'" name="Simple Mode Clarification">
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
<!-- Simple mode: 1 round of key clarification questions -->
|
|
90
|
+
<block type="rule" id="R-SIMPLE-TEMPLATE" level="mandatory" desc="Simple mode also uses template">
|
|
91
|
+
<field name="text">MANDATORY: Even in simple mode, clarification questions MUST be generated from CLARIFICATION-QUESTIONS-TEMPLATE.md template.</field>
|
|
92
|
+
<field name="text">Simple mode generates 1-3 key questions focusing on: scope, acceptance criteria, and business reason.</field>
|
|
93
|
+
</block>
|
|
94
|
+
|
|
95
|
+
<block type="task" id="B6-load-template" action="read-file" desc="Load clarification questions template for simple mode">
|
|
96
|
+
<field name="path" value="${skill_path}/templates/CLARIFICATION-QUESTIONS-TEMPLATE.md"/>
|
|
97
|
+
<field name="output" var="questions_template"/>
|
|
98
|
+
</block>
|
|
99
|
+
|
|
100
|
+
<block type="task" id="B6" action="generate" desc="Simple mode: generate 1-3 key clarification questions from template">
|
|
101
|
+
<field name="template" value="${questions_template}"/>
|
|
102
|
+
<field name="output_path" value="${iteration_path}/01.product-requirement/.clarification-questions-round-1.md"/>
|
|
103
|
+
<field name="vars">
|
|
104
|
+
- round_number: 1
|
|
105
|
+
- iteration_name: ${iteration_name}
|
|
106
|
+
- date: ${current_date}
|
|
107
|
+
- complexity_level: simple
|
|
108
|
+
- requirement_summary: ${requirement_summary}
|
|
95
109
|
</field>
|
|
96
|
-
<field name="
|
|
110
|
+
<field name="guidance">Simple mode: generate only 1-3 key questions focusing on scope boundaries, acceptance criteria, and business reason. Remove unused category sections from template.</field>
|
|
111
|
+
<field name="output" var="questions_file"/>
|
|
112
|
+
</block>
|
|
113
|
+
|
|
114
|
+
<block type="rule" id="R-SIMPLE-CONFIRM" level="mandatory" desc="User must answer even in simple mode">
|
|
115
|
+
<field name="text">MANDATORY: User-confirm event below is a HARD STOP. Worker MUST pause and wait for user response.</field>
|
|
116
|
+
</block>
|
|
117
|
+
|
|
118
|
+
<block type="event" id="E-SIMPLE-CONFIRM" action="user-confirm" desc="Wait for user to answer simple clarification questions">
|
|
119
|
+
<field name="prompt">📋 澄清问题已生成 (简单模式): ${questions_file}
|
|
120
|
+
|
|
121
|
+
请:
|
|
122
|
+
1. 查看澄清问题文件
|
|
123
|
+
2. 在文件中填写您的答案
|
|
124
|
+
3. 填写完成后确认继续</field>
|
|
125
|
+
<field name="skippable" value="false"/>
|
|
126
|
+
</block>
|
|
127
|
+
|
|
128
|
+
<block type="task" id="B6-read-answers" action="read-file" desc="Read user answers for simple mode">
|
|
129
|
+
<field name="path" value="${questions_file}"/>
|
|
130
|
+
<field name="output" var="answered_questions"/>
|
|
131
|
+
</block>
|
|
132
|
+
|
|
133
|
+
<block type="task" id="B6-mark-complete" action="set-var" desc="Mark simple mode clarification as complete">
|
|
134
|
+
<field name="sufficiency_checks_passed" value="true"/>
|
|
97
135
|
</block>
|
|
98
136
|
</branch>
|
|
99
137
|
<branch test="${complexity} == 'complex'" name="Complex Mode Clarification">
|
|
100
138
|
<!-- Clarification Loop -->
|
|
101
139
|
<block type="loop" id="L1" condition="sufficiency_checks_passed == false AND round_number <= max_rounds" desc="Clarification rounds until sufficiency">
|
|
140
|
+
<!-- ========== PHASE A: Generate Questions (ONLY questions template loaded here) ========== -->
|
|
102
141
|
<!-- MANDATORY: Template-based generation rule -->
|
|
103
142
|
<block type="rule" id="R-TEMPLATE-GENERATION" level="mandatory" desc="Template-based generation is MANDATORY">
|
|
104
143
|
<field name="text">MANDATORY: Clarification questions MUST be generated by loading the template file and performing variable substitution.</field>
|
|
@@ -125,6 +164,7 @@
|
|
|
125
164
|
<field name="output" var="questions_file"/>
|
|
126
165
|
</block>
|
|
127
166
|
|
|
167
|
+
<!-- ========== PHASE B: HARD STOP - Wait for User Answers ========== -->
|
|
128
168
|
<!-- MANDATORY: User confirmation cannot be bypassed -->
|
|
129
169
|
<block type="rule" id="R-USER-CONFIRM-MANDATORY" level="mandatory" desc="User-confirm events MUST pause Worker execution">
|
|
130
170
|
<field name="text">MANDATORY: The following user-confirm event is a HARD STOP. Worker MUST pause and present the prompt to user.</field>
|
|
@@ -143,6 +183,7 @@
|
|
|
143
183
|
<field name="skippable" value="false"/>
|
|
144
184
|
</block>
|
|
145
185
|
|
|
186
|
+
<!-- ========== PHASE C: Read Answers and Check Sufficiency ========== -->
|
|
146
187
|
<block type="task" id="B8" action="read-file" desc="Read answered questions">
|
|
147
188
|
<field name="path" value="${questions_file}"/>
|
|
148
189
|
<field name="output" var="answered_questions"/>
|
|
@@ -178,6 +219,16 @@
|
|
|
178
219
|
<block type="task" id="B9-increment" action="set-var" desc="Increment round counter">
|
|
179
220
|
<field name="round_number" value="${round_number + 1}"/>
|
|
180
221
|
</block>
|
|
222
|
+
<!-- ========== END OF LOOP ITERATION - Summary template is NOT loaded here ========== -->
|
|
223
|
+
</block>
|
|
224
|
+
</branch>
|
|
225
|
+
<branch default="true" name="ERROR: Unknown Complexity">
|
|
226
|
+
<block type="task" id="B-COMPLEXITY-ERROR" action="set-variable" desc="Handle unknown complexity value">
|
|
227
|
+
<field name="error_type">UNKNOWN_COMPLEXITY</field>
|
|
228
|
+
<field name="error_message">Complexity mode could not be determined. Value: ${complexity}. Expected 'simple' or 'complex'.</field>
|
|
229
|
+
</block>
|
|
230
|
+
<block type="event" id="E-COMPLEXITY-ABORT" action="abort" desc="Abort: unknown complexity">
|
|
231
|
+
<field name="message">Cannot proceed: complexity mode is '${complexity}', expected 'simple' or 'complex'.</field>
|
|
181
232
|
</block>
|
|
182
233
|
</branch>
|
|
183
234
|
</block>
|
|
@@ -194,6 +245,8 @@
|
|
|
194
245
|
<!-- Step 6: Generate .clarification-summary.md (Guarded by G3) -->
|
|
195
246
|
<block type="gateway" id="G3" mode="exclusive" desc="Guard: Only generate summary if sufficiency checks passed">
|
|
196
247
|
<branch test="${sufficiency_checks_passed} == true" name="Sufficiency Passed - Generate Summary">
|
|
248
|
+
<!-- ========== SUMMARY GENERATION (Only reached when ALL sufficiency checks passed) ========== -->
|
|
249
|
+
<!-- NOTE: Summary template is loaded HERE, not in the loop above. This is intentional. -->
|
|
197
250
|
<block type="task" id="B10-load-template" action="read-file" desc="Load summary template">
|
|
198
251
|
<field name="path" value="${skill_path}/templates/CLARIFICATION-SUMMARY-TEMPLATE.md"/>
|
|
199
252
|
<field name="output" var="summary_template"/>
|
|
@@ -223,10 +276,15 @@
|
|
|
223
276
|
<field name="verify" value="file_exists(${summary_path})"/>
|
|
224
277
|
</block>
|
|
225
278
|
</branch>
|
|
226
|
-
<branch default="true" name="Sufficiency Failed -
|
|
227
|
-
<block type="
|
|
228
|
-
<field name="
|
|
229
|
-
<field name="
|
|
279
|
+
<branch default="true" name="Sufficiency Failed - Abort Workflow">
|
|
280
|
+
<block type="rule" id="R-ABORT-RULE" level="mandatory" desc="Abort when sufficiency failed">
|
|
281
|
+
<field name="text">MANDATORY: sufficiency_checks_passed is false. Worker MUST abort workflow immediately.</field>
|
|
282
|
+
<field name="text">DO NOT attempt to generate .clarification-summary.md.</field>
|
|
283
|
+
<field name="text">Return control to PM Agent with error status.</field>
|
|
284
|
+
</block>
|
|
285
|
+
<block type="event" id="E-INSUFFICIENCY-ABORT" action="abort" desc="Abort: sufficiency checks failed after all rounds">
|
|
286
|
+
<field name="message">Requirement clarification did not achieve sufficient clarity after ${round_number - 1} round(s). Returning control to PM Agent for user intervention.</field>
|
|
287
|
+
<field name="error_code">CLARIFICATION_INSUFFICIENT</field>
|
|
230
288
|
</block>
|
|
231
289
|
</branch>
|
|
232
290
|
</block>
|
|
@@ -82,8 +82,24 @@
|
|
|
82
82
|
</branch>
|
|
83
83
|
</block>
|
|
84
84
|
|
|
85
|
-
<!-- === Phase 3:
|
|
86
|
-
<block type="event" id="E5" action="log" desc="
|
|
85
|
+
<!-- === Phase 3: 设置 skill_path 变量 === -->
|
|
86
|
+
<block type="event" id="E5" action="log" desc="设置 skill_path 变量">📋 Phase 3: Set skill_path Variable</block>
|
|
87
|
+
|
|
88
|
+
<block type="gateway" id="G5b" mode="exclusive" desc="设置 skill_path 目录路径">
|
|
89
|
+
<branch test="${resolved_skill_path} != null" name="从 resolved_skill_path 推导">
|
|
90
|
+
<block type="task" id="T5b" action="run-script" desc="提取 skill 目录路径">
|
|
91
|
+
<field name="command">node -e "const path = require('path'); const skillFilePath = process.env.SKILL_FILE_PATH || '${resolved_skill_path}'; const skillDir = path.dirname(skillFilePath); console.log(skillDir);"</field>
|
|
92
|
+
<field name="output" var="skill_path"/>
|
|
93
|
+
</block>
|
|
94
|
+
<block type="event" id="E5b" action="log" desc="skill_path 已设置">📁 skill_path set to: ${skill_path}</block>
|
|
95
|
+
</branch>
|
|
96
|
+
<branch test="true" name="无 skill 路径">
|
|
97
|
+
<block type="event" id="E5c" action="log" desc="无 skill_path">ℹ️ No skill_path to set</block>
|
|
98
|
+
</branch>
|
|
99
|
+
</block>
|
|
100
|
+
|
|
101
|
+
<!-- === Phase 4: 执行任务 === -->
|
|
102
|
+
<block type="event" id="E6" action="log" desc="开始执行任务">📋 Phase 4: Execute Task</block>
|
|
87
103
|
|
|
88
104
|
<block type="rule" id="R1" level="mandatory" desc="技能执行强制约束">
|
|
89
105
|
如果技能指定通过 run_in_terminal 或 Bash 执行脚本 → 必须通过终端执行
|
|
@@ -130,13 +146,14 @@
|
|
|
130
146
|
<block type="task" id="T8" action="run-skill" desc="执行技能工作流">
|
|
131
147
|
<field name="skill">${resolved_skill_path}</field>
|
|
132
148
|
<field name="context">${context}</field>
|
|
149
|
+
<field name="skill_path">${skill_path}</field>
|
|
133
150
|
</block>
|
|
134
151
|
<field name="execution_status" value="success"/>
|
|
135
152
|
</branch>
|
|
136
153
|
</block>
|
|
137
154
|
|
|
138
|
-
<!-- === Phase
|
|
139
|
-
<block type="event" id="E10" action="log" desc="开始报告结果">📋 Phase
|
|
155
|
+
<!-- === Phase 5: 报告结果 === -->
|
|
156
|
+
<block type="event" id="E10" action="log" desc="开始报告结果">📋 Phase 5: Report Results</block>
|
|
140
157
|
|
|
141
158
|
<block type="gateway" id="G7" mode="exclusive" desc="选择报告格式">
|
|
142
159
|
<branch test="${execution_status} == success" name="成功报告">
|
|
@@ -163,7 +180,7 @@
|
|
|
163
180
|
</branch>
|
|
164
181
|
</block>
|
|
165
182
|
|
|
166
|
-
<!-- === Phase
|
|
183
|
+
<!-- === Phase 6: 完成报告输出 === -->
|
|
167
184
|
<block type="event" id="E11" action="log" desc="输出结构化完成报告">
|
|
168
185
|
## Task Completion Report
|
|
169
186
|
- **Status**: ${status}
|
package/lib/commands/update.js
CHANGED
|
@@ -211,16 +211,18 @@ function updateSkillsRecursive(srcDir, destDir, stats, currentRelPath = '', ideC
|
|
|
211
211
|
const relPath = currentRelPath ? path.join(currentRelPath, entry.name) : entry.name;
|
|
212
212
|
|
|
213
213
|
if (entry.isDirectory()) {
|
|
214
|
-
// Only
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
// Only check speccrew-* prefix at skills directory level (when currentRelPath is empty)
|
|
215
|
+
// Once inside a skill directory, all subdirectories should be processed unconditionally
|
|
216
|
+
if (!currentRelPath && !isSpeccrewFile(entry.name)) continue;
|
|
217
|
+
|
|
218
218
|
updateSkillsRecursive(srcPath, destPath, stats, relPath, ideConfig);
|
|
219
219
|
} else {
|
|
220
|
-
// Files
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
220
|
+
// Files - only check speccrew-* prefix at skills directory level
|
|
221
|
+
// Once inside a skill directory, all files should be processed unconditionally
|
|
222
|
+
if (!currentRelPath) {
|
|
223
|
+
const parentDir = path.basename(srcDir);
|
|
224
|
+
if (!isSpeccrewFile(parentDir)) continue;
|
|
225
|
+
}
|
|
224
226
|
|
|
225
227
|
// Apply frontmatter transformation to SKILL.md files (if needed)
|
|
226
228
|
const isSkillMd = entry.name === 'SKILL.md';
|