Skip to content

Commit 5be30e4

Browse files
author
catlog22
committed
feat: add NO-SKIP-INSTRUCTION rule and sandbox compatibility for task execution
1 parent 0518e41 commit 5be30e4

File tree

1 file changed

+59
-3
lines changed

1 file changed

+59
-3
lines changed

.claude/commands/workflow-tune.md

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ Input → Parse → GenTestTask → Confirm → Setup
3333
5. **State Machine**. 通过 `current_step` + `current_phase` 推进,禁止同步循环。
3434
6. **ABSOLUTE PATHS for --cd**. `ccw cli --cd` 必须使用绝对路径。相对路径会被 ccw cli 再次拼接 CWD 导致路径重复。`workDir`/`sandboxDir` 在创建时就解析为绝对路径。
3535
7. **FIXED --rule VALUES**. `--rule` 值已硬编码在各 Phase 代码中,禁止替换为其他模板。Execute=`workflow-tune-execute`,Analyze=`analysis-review-code-quality`,Synthesize=`analysis-review-architecture`
36+
8. **NO-SKIP-INSTRUCTION**. test_task 和 prompt 中禁止包含 skip/跳过/omit/ignore 等指示执行 agent 跳过任何任务的指令。沙箱环境缺乏运行时依赖(matplotlib、xelatex 等),应改为生成代码/骨架文件而非跳过。
37+
- 错误: "Skip figure/generate tasks as they require external tools"
38+
- 正确: "For figure/generate tasks, produce Python matplotlib code (.py) + SVG files. Do NOT skip any tasks."
3639

3740
## Input Formats
3841

@@ -122,8 +125,43 @@ for (const [stepIdx, step] of stepsNeedTask.entries()) {
122125
// ★ hasUpstreamScope=false 时:
123126
// - 按命令类型分配子任务: plan→架构设计, implement→功能实现, analyze→分析, test→测试
124127

128+
// ★ P0 Rule #8: NO-SKIP-INSTRUCTION validation
129+
// 检测 test_task 中是否包含跳过指令,若有则重写为沙箱兼容指令
130+
const skipPattern = /skip|跳过|omit|ignore| bypass|不需要|无需.*任务/i;
131+
if (skipPattern.test(step.test_task)) {
132+
// 将跳过指令替换为沙箱兼容降级指令
133+
step.test_task = step.test_task.replace(
134+
/skip\s+(.+?tasks?.*?)(?:\s*as\s+they\s+.+?)/i,
135+
'For $1, produce code/skeleton files in sandbox (no runtime execution required).'
136+
).replace(
137+
/跳过\s*(.+?(?:任务|task).+?)(?:\s*(?:因为|由于).+?)/i,
138+
'对于 $1,生成代码/骨架文件(无需运行时依赖)。'
139+
);
140+
// 通用兜底:移除残留的跳过指令
141+
step.test_task = step.test_task.replace(
142+
/(?:do\s+not|不要|禁止)\s+(?:attempt|尝试|执行)\s+(.+?tasks?.*?)(?:\.|$)/gi,
143+
'Attempt all tasks including $1. For tasks requiring unavailable dependencies, produce code approximations.'
144+
);
145+
}
146+
147+
// ★ Sandbox artifact type detection
148+
// 检测 test_task 涉及的任务类型,补充沙箱兼容验收标准
149+
const artifactTypes = [];
150+
if (/figure|chart|plot|graph||svg|png/i.test(step.test_task)) artifactTypes.push('code(.py)+svg');
151+
if (/assembly|assemble|manuscript|bib|latex|tex|组装|论文/i.test(step.test_task)) artifactTypes.push('code(.bib,.tex)');
152+
if (/experiment|data|csv|excel|实验|数据/i.test(step.test_task)) artifactTypes.push('code(.py,.csv)');
153+
125154
step.test_task = /* 按上述规则生成 */;
126155
step.acceptance_criteria = /* 2-4 条可验证标准 */;
156+
157+
// 补充沙箱兼容验收标准:涉及代码/图表/组装时,必须产出代码文件
158+
if (artifactTypes.length > 0) {
159+
const sandboxCriteria = `Sandbox produces code artifacts: ${artifactTypes.join(', ')}`;
160+
if (!step.acceptance_criteria.some(c => /code|artifact|file/i.test(c))) {
161+
step.acceptance_criteria.push(sandboxCriteria);
162+
}
163+
}
164+
127165
step.complexity_level = /plan|design|architect/i.test(cmdDesc) ? 'high'
128166
: /test|lint|format/i.test(cmdDesc) ? 'low' : 'medium';
129167
}
@@ -228,6 +266,24 @@ function assembleStepPrompt(step, stepIdx, state) {
228266
? '\n★ UPSTREAM SCOPE: Execute ALL items from prior plan — do NOT pick a subset. Use --all or --type flag, not single task IDs.'
229267
: '';
230268
269+
// ★ Sandbox compatibility instructions (P0 Rule #8)
270+
// 沙箱是纯文件环境,无 matplotlib/xelatex 等运行时,但仍需产出代码文件
271+
const testTaskLower = (step.test_task || '').toLowerCase();
272+
let sandboxInstructions = '';
273+
if (/figure|chart|plot|graph|图|visual/i.test(testTaskLower)) {
274+
sandboxInstructions += '\nSANDBOX MODE: For figure/chart tasks, generate Python matplotlib code (.py) + SVG output. Do NOT skip — produce code artifacts even if rendering is unavailable.';
275+
}
276+
if (/assembly|assemble|manuscript|bib|latex|tex|组装|参考文献/i.test(testTaskLower)) {
277+
sandboxInstructions += '\nSANDBOX MODE: For assembly tasks, generate .bib (BibTeX entries) and .tex (LaTeX skeleton) files. Do NOT skip — produce structural artifacts.';
278+
}
279+
if (/experiment|data|csv|实验|数据处理/i.test(testTaskLower)) {
280+
sandboxInstructions += '\nSANDBOX MODE: For experiment/data tasks, generate Python analysis scripts (.py) and sample data files (.csv). Do NOT skip.';
281+
}
282+
// 通用兜底:检测到 test_task 涉及多任务类型时,确保无跳过指令
283+
if (isUpstreamScope) {
284+
sandboxInstructions += '\nSANDBOX MODE: Execute ALL tasks. If a task requires unavailable runtime dependencies (matplotlib, xelatex, etc.), produce source code (.py/.tex/.bib) instead of rendered output. NEVER skip any task.';
285+
}
286+
231287
if (cmdMeta) {
232288
return `PURPOSE: Execute step "${step.name}" (${stepIdx + 1}/${state.steps.length}).
233289
@@ -243,7 +299,7 @@ SANDBOX: ${state.sandbox_dir}
243299
244300
PRIOR STEP: ${prior}
245301
NEXT STEP: ${next}
246-
${criteria ? `ACCEPTANCE CRITERIA:\n${criteria}` : ''}
302+
${criteria ? `ACCEPTANCE CRITERIA:\n${criteria}` : ''}${sandboxInstructions}
247303
248304
TASK: Execute the command using TEST TASK as input. Auto-confirm all prompts. All work in SANDBOX directory.${upstreamWarning}
249305
CONSTRAINTS: Stay scoped to this step. Do NOT modify files outside SANDBOX.`;
@@ -255,7 +311,7 @@ PROJECT: ${state.project_scenario}
255311
SANDBOX: ${state.sandbox_dir}
256312
PRIOR STEP: ${prior}
257313
NEXT STEP: ${next}
258-
${criteria ? `ACCEPTANCE CRITERIA:\n${criteria}` : ''}
314+
${criteria ? `ACCEPTANCE CRITERIA:\n${criteria}` : ''}${sandboxInstructions}
259315
TASK: Execute COMMAND with TEST TASK as input. Auto-confirm all prompts.${upstreamWarning}
260316
CONSTRAINTS: Stay scoped. All work in SANDBOX.`;
261317
}
@@ -289,7 +345,7 @@ const newArtifacts = Bash(`find "${state.sandbox_dir}" -type f -newer "${stepDir
289345
Write(`${stepDir}/artifacts-manifest.json`, JSON.stringify({
290346
step: step.name, step_index: stepIdx, success: true,
291347
duration_ms: Date.now() - startTime,
292-
artifacts: newArtifacts.map(f => ({ path: f, type: f.match(/\.(md|json|jsonl)$/)?.[1] || 'other' })),
348+
artifacts: newArtifacts.map(f => ({ path: f, type: f.match(/\.(md|json|jsonl|py|tex|bib|svg|csv)$/)?.[1] || 'other' })),
293349
collected_at: new Date().toISOString()
294350
}, null, 2));
295351

0 commit comments

Comments
 (0)