sillyspec 3.9.0 → 3.10.0
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/.claude/skills/sillyspec-archive/SKILL.md +17 -0
- package/.claude/skills/sillyspec-auto/SKILL.md +78 -0
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +17 -0
- package/{templates/commit.md → .claude/skills/sillyspec-commit/SKILL.md} +32 -47
- package/.claude/skills/sillyspec-continue/SKILL.md +45 -0
- package/.claude/skills/sillyspec-doctor/SKILL.md +27 -0
- package/.claude/skills/sillyspec-execute/SKILL.md +17 -0
- package/.claude/skills/sillyspec-explore/SKILL.md +105 -0
- package/.claude/skills/sillyspec-export/SKILL.md +53 -0
- package/.claude/skills/sillyspec-init/SKILL.md +170 -0
- package/.claude/skills/sillyspec-plan/SKILL.md +17 -0
- package/.claude/skills/sillyspec-propose/SKILL.md +17 -0
- package/.claude/skills/sillyspec-quick/SKILL.md +17 -0
- package/.claude/skills/sillyspec-resume/SKILL.md +111 -0
- package/.claude/skills/sillyspec-scan/SKILL.md +17 -0
- package/.claude/skills/sillyspec-state/SKILL.md +54 -0
- package/.claude/skills/sillyspec-status/SKILL.md +17 -0
- package/.claude/skills/sillyspec-verify/SKILL.md +17 -0
- package/.claude/skills/sillyspec-workspace/SKILL.md +149 -0
- package/README.md +19 -11
- package/SKILL.md +15 -10
- package/package.json +7 -9
- package/packages/dashboard/dist/assets/index-BcM2J-hv.css +1 -0
- package/packages/dashboard/dist/assets/index-DpLHK4jv.js +7446 -0
- package/packages/dashboard/dist/index.html +16 -16
- package/packages/dashboard/dist/prototype-dashboard.html +836 -0
- package/packages/dashboard/dist/prototype-overview.html +256 -0
- package/packages/dashboard/package-lock.json +226 -6
- package/packages/dashboard/package.json +8 -5
- package/packages/dashboard/public/logo.jpg +0 -0
- package/packages/dashboard/public/prototype-dashboard.html +836 -0
- package/packages/dashboard/public/prototype-overview.html +256 -0
- package/packages/dashboard/server/executor.js +1 -1
- package/packages/dashboard/server/index.js +341 -113
- package/packages/dashboard/server/parser.js +442 -30
- package/packages/dashboard/server/watcher.js +214 -134
- package/packages/dashboard/src/App.vue +475 -71
- package/packages/dashboard/src/components/ActionBar.vue +36 -43
- package/packages/dashboard/src/components/CommandPalette.vue +45 -66
- package/packages/dashboard/src/components/DetailPanel.vue +68 -53
- package/packages/dashboard/src/components/DocPreview.vue +257 -0
- package/packages/dashboard/src/components/DocTree.vue +114 -0
- package/packages/dashboard/src/components/HResizeHandle.vue +48 -0
- package/packages/dashboard/src/components/LogStream.vue +13 -33
- package/packages/dashboard/src/components/PipelineStage.vue +8 -8
- package/packages/dashboard/src/components/PipelineView.vue +99 -45
- package/packages/dashboard/src/components/ProjectCard.vue +187 -0
- package/packages/dashboard/src/components/ProjectList.vue +103 -45
- package/packages/dashboard/src/components/ProjectOverview.vue +152 -0
- package/packages/dashboard/src/components/StageBadge.vue +13 -13
- package/packages/dashboard/src/components/StepCard.vue +15 -15
- package/packages/dashboard/src/components/VResizeHandle.vue +61 -0
- package/packages/dashboard/src/components/detail/DocsDetail.vue +48 -0
- package/packages/dashboard/src/components/detail/GitDetail.vue +61 -0
- package/packages/dashboard/src/components/detail/TechDetail.vue +43 -0
- package/packages/dashboard/src/composables/useDashboard.js +48 -6
- package/packages/dashboard/src/composables/useKeyboard.js +6 -4
- package/packages/dashboard/src/composables/useLayout.js +131 -0
- package/packages/dashboard/src/main.js +4 -1
- package/packages/dashboard/src/style.css +17 -17
- package/src/index.js +141 -22
- package/src/init.js +93 -231
- package/src/migrate.js +117 -0
- package/src/progress.js +460 -0
- package/src/run.js +635 -0
- package/src/setup.js +2 -72
- package/src/stages/archive.js +54 -0
- package/src/stages/brainstorm.js +264 -0
- package/src/stages/doctor.js +303 -0
- package/src/stages/execute.js +287 -0
- package/src/stages/explore.js +34 -0
- package/src/stages/index.js +28 -0
- package/src/stages/plan.js +354 -0
- package/src/stages/propose.js +115 -0
- package/src/stages/quick.js +64 -0
- package/src/stages/scan.js +141 -0
- package/src/stages/status.js +65 -0
- package/src/stages/verify.js +135 -0
- package/.sillyspec/changes/dashboard/design.md +0 -219
- package/.sillyspec/plans/2026-04-05-dashboard.md +0 -737
- package/.sillyspec/specs/2026-04-05-dashboard-design.md +0 -206
- package/dist/steps/brainstorm/01-load-context.md +0 -30
- package/dist/steps/brainstorm/02-reuse-check.md +0 -6
- package/dist/steps/brainstorm/03-prototype-analysis.md +0 -11
- package/dist/steps/brainstorm/04-module-split.md +0 -23
- package/dist/steps/brainstorm/05-dialog-explore.md +0 -8
- package/dist/steps/brainstorm/06-propose-approaches.md +0 -3
- package/dist/steps/brainstorm/07-present-design.md +0 -3
- package/dist/steps/brainstorm/08-write-design.md +0 -21
- package/dist/steps/brainstorm/09-self-review.md +0 -15
- package/dist/steps/brainstorm/10-user-confirm.md +0 -3
- package/dist/steps/brainstorm/11-output-spec.md +0 -7
- package/dist/steps/brainstorm/manifest.yaml +0 -26
- package/dist/steps/execute/01-load-context.md +0 -41
- package/dist/steps/execute/02-scan-conventions.md +0 -47
- package/dist/steps/execute/03-skill-mcp.md +0 -19
- package/dist/steps/execute/04-assign-task.md +0 -22
- package/dist/steps/execute/04b-prompt-template.md +0 -54
- package/dist/steps/execute/05-write-test.md +0 -7
- package/dist/steps/execute/06-write-code.md +0 -8
- package/dist/steps/execute/07-run-test.md +0 -26
- package/dist/steps/execute/08-fix-issues.md +0 -28
- package/dist/steps/execute/09-next-task.md +0 -33
- package/dist/steps/execute/manifest.yaml +0 -28
- package/dist/steps/plan/01-load-context.md +0 -22
- package/dist/steps/plan/02-anchor-confirm.md +0 -1
- package/dist/steps/plan/03-expand-tasks.md +0 -33
- package/dist/steps/plan/04-mark-order.md +0 -15
- package/dist/steps/plan/05-e2e-planning.md +0 -17
- package/dist/steps/plan/06-self-check.md +0 -16
- package/dist/steps/plan/07-save.md +0 -1
- package/dist/steps/plan/manifest.yaml +0 -18
- package/dist/steps/scan/01-env-detect.md +0 -51
- package/dist/steps/scan/02-tech-stack.md +0 -16
- package/dist/steps/scan/03-conventions.md +0 -16
- package/dist/steps/scan/04-structure.md +0 -19
- package/dist/steps/scan/05-quality.md +0 -18
- package/dist/steps/scan/06-complete.md +0 -49
- package/dist/steps/scan/manifest.yaml +0 -16
- package/dist/steps/verify/01-load-specs.md +0 -28
- package/dist/steps/verify/02-check-tasks.md +0 -1
- package/dist/steps/verify/03-check-design.md +0 -6
- package/dist/steps/verify/04-run-tests.md +0 -7
- package/dist/steps/verify/05-e2e-tests.md +0 -27
- package/dist/steps/verify/05b-e2e-fix.md +0 -33
- package/dist/steps/verify/06-code-quality.md +0 -25
- package/dist/steps/verify/07-lint-check.md +0 -27
- package/dist/steps/verify/08-output-report.md +0 -14
- package/dist/steps/verify/manifest.yaml +0 -22
- package/docs/.vitepress/config.mts +0 -45
- package/docs/.vitepress/dist/404.html +0 -25
- package/docs/.vitepress/dist/assets/app.YytxICdd.js +0 -1
- package/docs/.vitepress/dist/assets/chunks/framework.Czhw_PXq.js +0 -19
- package/docs/.vitepress/dist/assets/chunks/theme.DusTRZQk.js +0 -1
- package/docs/.vitepress/dist/assets/index.md.C3VCvtQA.js +0 -1
- package/docs/.vitepress/dist/assets/index.md.C3VCvtQA.lean.js +0 -1
- package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/docs/.vitepress/dist/assets/sillyspec_commands.md.CXFFsj08.js +0 -15
- package/docs/.vitepress/dist/assets/sillyspec_commands.md.CXFFsj08.lean.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_dashboard.md.BuPXHqjX.js +0 -4
- package/docs/.vitepress/dist/assets/sillyspec_dashboard.md.BuPXHqjX.lean.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_file-io.md.Cz3x7llx.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_file-io.md.Cz3x7llx.lean.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_getting-started.md.ClcvV8k3.js +0 -4
- package/docs/.vitepress/dist/assets/sillyspec_getting-started.md.ClcvV8k3.lean.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_install.md.CKuR2tiT.js +0 -5
- package/docs/.vitepress/dist/assets/sillyspec_install.md.CKuR2tiT.lean.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_lifecycle.md.DY293cR1.js +0 -28
- package/docs/.vitepress/dist/assets/sillyspec_lifecycle.md.DY293cR1.lean.js +0 -1
- package/docs/.vitepress/dist/assets/sillyspec_structure.md.sVYS4zPs.js +0 -30
- package/docs/.vitepress/dist/assets/sillyspec_structure.md.sVYS4zPs.lean.js +0 -1
- package/docs/.vitepress/dist/assets/style.DFTx90Kk.css +0 -1
- package/docs/.vitepress/dist/hashmap.json +0 -1
- package/docs/.vitepress/dist/index.html +0 -28
- package/docs/.vitepress/dist/sillyspec/commands.html +0 -42
- package/docs/.vitepress/dist/sillyspec/dashboard.html +0 -31
- package/docs/.vitepress/dist/sillyspec/file-io.html +0 -28
- package/docs/.vitepress/dist/sillyspec/getting-started.html +0 -31
- package/docs/.vitepress/dist/sillyspec/install.html +0 -32
- package/docs/.vitepress/dist/sillyspec/lifecycle.html +0 -55
- package/docs/.vitepress/dist/sillyspec/structure.html +0 -57
- package/docs/.vitepress/dist/vp-icons.css +0 -1
- package/docs/index.md +0 -34
- package/docs/sillyspec/commands.md +0 -218
- package/docs/sillyspec/dashboard.md +0 -51
- package/docs/sillyspec/file-io.md +0 -34
- package/docs/sillyspec/getting-started.md +0 -61
- package/docs/sillyspec/install.md +0 -51
- package/docs/sillyspec/lifecycle.md +0 -146
- package/docs/sillyspec/structure.md +0 -62
- package/packages/dashboard/dist/assets/index-Bh-GPjKY.css +0 -1
- package/packages/dashboard/dist/assets/index-CrCn5Gg6.js +0 -17
- package/src/step.js +0 -543
- package/templates/archive.md +0 -120
- package/templates/brainstorm.md +0 -170
- package/templates/continue.md +0 -32
- package/templates/execute.md +0 -304
- package/templates/explore.md +0 -59
- package/templates/export.md +0 -21
- package/templates/init.md +0 -61
- package/templates/plan.md +0 -146
- package/templates/quick.md +0 -135
- package/templates/scan-quick.md +0 -49
- package/templates/scan.md +0 -156
- package/templates/skills/playwright-e2e/SKILL.md +0 -340
- package/templates/status.md +0 -75
- package/templates/verify.md +0 -236
- package/templates/workspace-sync.md +0 -99
- package/templates/workspace.md +0 -70
- /package/{docs/.vitepress/dist/logo.jpg → logo.jpg} +0 -0
- /package/{docs/.vitepress → packages/dashboard}/dist/favicon.jpg +0 -0
- /package/{docs/public → packages/dashboard/dist}/logo.jpg +0 -0
- /package/{docs → packages/dashboard}/public/favicon.jpg +0 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// SillySpec Doctor — 项目自检阶段
|
|
2
|
+
// 检查项通过 prompt 中的 bash 命令执行,此文件仅定义步骤结构
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const definition = {
|
|
6
|
+
name: 'doctor',
|
|
7
|
+
title: '项目自检',
|
|
8
|
+
description: '检查 SillySpec 配置、构建环境和外部依赖',
|
|
9
|
+
auxiliary: true,
|
|
10
|
+
steps: [
|
|
11
|
+
{
|
|
12
|
+
name: 'SillySpec 内部检查',
|
|
13
|
+
prompt: `运行 SillySpec 内部检查。逐项执行以下命令并汇总结果:
|
|
14
|
+
|
|
15
|
+
### 1. 目录结构完整性
|
|
16
|
+
\`\`\`bash
|
|
17
|
+
# 检查 .sillyspec/ 及子目录
|
|
18
|
+
for d in .sillyspec .sillyspec/projects .sillyspec/docs .sillyspec/changes .sillyspec/.runtime; do
|
|
19
|
+
[ -d "$d" ] && echo "✅ $d" || echo "❌ $d"
|
|
20
|
+
done
|
|
21
|
+
# 检查 progress.json
|
|
22
|
+
[ -f .sillyspec/.runtime/progress.json ] && echo "✅ progress.json 存在" || echo "❌ progress.json 不存在"
|
|
23
|
+
node -e "JSON.parse(require('fs').readFileSync('.sillyspec/.runtime/progress.json','utf8')); console.log('✅ progress.json 可解析')" 2>/dev/null || echo "⚠️ progress.json 不可解析"
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
### 2. 项目配置检查
|
|
27
|
+
\`\`\`bash
|
|
28
|
+
ls .sillyspec/projects/*.yaml 2>/dev/null
|
|
29
|
+
# 对每个 yaml 文件,检查 name 和 path 字段,验证 path 存在
|
|
30
|
+
for f in .sillyspec/projects/*.yaml; do
|
|
31
|
+
[ -f "$f" ] || continue
|
|
32
|
+
name=$(grep '^name:' "$f" | head -1 | sed 's/^name:[[:space:]]*//')
|
|
33
|
+
p=$(grep '^path:' "$f" | head -1 | sed 's/^path:[[:space:]]*//')
|
|
34
|
+
[ -z "$name" ] && echo "⚠️ $(basename $f) — 缺少 name"
|
|
35
|
+
[ -z "$p" ] && echo "⚠️ $(basename $f) — 缺少 path"
|
|
36
|
+
[ -n "$p" ] && [ ! -d "$p" ] && echo "❌ $(basename $f) — path 不存在: $p"
|
|
37
|
+
[ -n "$name" ] && [ -n "$p" ] && [ -d "$p" ] && echo "✅ $(basename $f) — $name ($p)"
|
|
38
|
+
done
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
### 3. 进度数据一致性
|
|
42
|
+
\`\`\`bash
|
|
43
|
+
# 读取 currentChange 并检查目录存在性
|
|
44
|
+
node -e "
|
|
45
|
+
const p = JSON.parse(require('fs').readFileSync('.sillyspec/.runtime/progress.json','utf8'));
|
|
46
|
+
const cc = p.currentChange;
|
|
47
|
+
if (!cc) { console.log('ℹ️ 无当前变更'); process.exit(0); }
|
|
48
|
+
const dir = '.sillyspec/changes/' + cc;
|
|
49
|
+
const exists = require('fs').existsSync(dir);
|
|
50
|
+
console.log(exists ? '✅ currentChange 目录存在: ' + cc : '❌ currentChange 目录不存在: ' + cc);
|
|
51
|
+
// 检查各阶段产出
|
|
52
|
+
const stages = p.stages || {};
|
|
53
|
+
for (const [name, sd] of Object.entries(stages)) {
|
|
54
|
+
if (sd.status === 'completed' && sd.steps.length > 0) {
|
|
55
|
+
const hasOutput = sd.steps.some(s => s.output && s.output.trim());
|
|
56
|
+
console.log(' ' + name + ': ' + (hasOutput ? '✅ 有产出' : '⚠️ 已完成但无产出记录'));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
" 2>/dev/null || echo "⚠️ 无法读取 progress.json"
|
|
60
|
+
\`\`\`
|
|
61
|
+
|
|
62
|
+
### 4. 孤儿文件检查
|
|
63
|
+
\`\`\`bash
|
|
64
|
+
node -e "
|
|
65
|
+
const fs = require('fs');
|
|
66
|
+
const dir = '.sillyspec/changes';
|
|
67
|
+
if (!fs.existsSync(dir)) { console.log('ℹ️ changes/ 目录不存在'); process.exit(0); }
|
|
68
|
+
const subs = fs.readdirSync(dir).filter(f => fs.statSync(dir+'/'+f).isDirectory());
|
|
69
|
+
if (subs.length === 0) { console.log('ℹ️ 无变更目录'); process.exit(0); }
|
|
70
|
+
let progress;
|
|
71
|
+
try { progress = JSON.parse(fs.readFileSync('.sillyspec/.runtime/progress.json','utf8')); } catch { console.log('⚠️ 无法读取 progress.json'); subs.forEach(s => console.log('❓ ' + s)); process.exit(0); }
|
|
72
|
+
const known = new Set();
|
|
73
|
+
if (progress.currentChange) known.add(progress.currentChange);
|
|
74
|
+
for (const sd of Object.values(progress.stages || {})) {
|
|
75
|
+
(sd.steps || []).forEach(s => { if (s.output) known.add(s.output); });
|
|
76
|
+
}
|
|
77
|
+
subs.forEach(s => {
|
|
78
|
+
console.log(known.has(s) ? '✅ ' + s + ' — 已关联' : '⚠️ ' + s + ' — 孤儿目录(可清理)');
|
|
79
|
+
});
|
|
80
|
+
"
|
|
81
|
+
\`\`\`
|
|
82
|
+
|
|
83
|
+
### 5. 配置文件检查
|
|
84
|
+
\`\`\`bash
|
|
85
|
+
# 检查 local.yaml 和 STACK.md
|
|
86
|
+
for f in .sillyspec/projects/*.yaml; do
|
|
87
|
+
[ -f "$f" ] || continue
|
|
88
|
+
name=$(grep '^name:' "$f" | head -1 | sed 's/^name:[[:space:]]*//')
|
|
89
|
+
p=$(grep '^path:' "$f" | head -1 | sed 's/^path:[[:space:]]*//')
|
|
90
|
+
[ -z "$p" ] && continue
|
|
91
|
+
local_yaml="$p/.sillyspec/local.yaml"
|
|
92
|
+
stack_md="$p/.sillyspec/STACK.md"
|
|
93
|
+
[ -f "$local_yaml" ] && echo "✅ local.yaml ($name)" || echo "⚠️ local.yaml ($name) — 不存在"
|
|
94
|
+
if [ -f "$local_yaml" ]; then
|
|
95
|
+
grep -q 'build:' "$local_yaml" && echo " ✅ build 命令已配置" || echo " ⚠️ 缺少 build 命令"
|
|
96
|
+
grep -q 'test:' "$local_yaml" && echo " ✅ test 命令已配置" || echo " ⚠️ 缺少 test 命令"
|
|
97
|
+
fi
|
|
98
|
+
[ -f "$stack_md" ] && echo "✅ STACK.md ($name)" || echo "⚠️ STACK.md ($name) — 不存在"
|
|
99
|
+
done
|
|
100
|
+
\`\`\`
|
|
101
|
+
|
|
102
|
+
### 输出
|
|
103
|
+
汇总所有检查结果,按以下格式:
|
|
104
|
+
\`\`\`
|
|
105
|
+
## SillySpec 内部
|
|
106
|
+
✅/⚠️/❌ 各项状态
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
### 注意
|
|
110
|
+
- 不要编造路径或结果,严格基于命令输出
|
|
111
|
+
- 如果 .sillyspec/ 不存在,直接输出 ❌ 并跳过后续检查`,
|
|
112
|
+
outputHint: 'SillySpec 内部检查结果',
|
|
113
|
+
optional: false
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: '构建环境检查',
|
|
117
|
+
prompt: `检查项目构建环境。先探测项目使用的构建工具,再逐项检查可用性。
|
|
118
|
+
|
|
119
|
+
### 1. 探测构建工具
|
|
120
|
+
\`\`\`bash
|
|
121
|
+
# 确定项目路径(使用 progress.json 中的项目或当前目录)
|
|
122
|
+
PROJECT_DIR=$(node -e "
|
|
123
|
+
const fs=require('fs');
|
|
124
|
+
try{const p=JSON.parse(fs.readFileSync('.sillyspec/.runtime/progress.json','utf8'));if(p.project){console.log(p.project);process.exit(0)}}catch{}
|
|
125
|
+
const files=fs.readdirSync('.sillyspec/projects').filter(f=>f.endsWith('.yaml'));
|
|
126
|
+
if(files.length>0){const c=fs.readFileSync('.sillyspec/projects/'+files[0],'utf8');const m=c.match(/^path:\\s*(.+)/m);console.log(m?m[1].trim():'.')}else console.log('.')
|
|
127
|
+
" 2>/dev/null)
|
|
128
|
+
echo "项目目录: $PROJECT_DIR"
|
|
129
|
+
|
|
130
|
+
# 探测构建工具
|
|
131
|
+
for f in pom.xml build.gradle package.json requirements.txt pyproject.toml go.mod Cargo.toml; do
|
|
132
|
+
[ -f "$PROJECT_DIR/$f" ] && echo "检测到: $f"
|
|
133
|
+
done
|
|
134
|
+
[ -f "$PROJECT_DIR/.sillyspec/STACK.md" ] && cat "$PROJECT_DIR/.sillyspec/STACK.md" | head -30
|
|
135
|
+
\`\`\`
|
|
136
|
+
|
|
137
|
+
### 2. 构建工具可用性
|
|
138
|
+
根据上面检测到的工具,运行对应检查(未检测到的跳过):
|
|
139
|
+
|
|
140
|
+
**Maven 项目:**
|
|
141
|
+
\`\`\`bash
|
|
142
|
+
timeout 10 mvn -v 2>/dev/null | head -1 && echo "✅ Maven 可用" || echo "❌ Maven 不可用"
|
|
143
|
+
[ -f ~/.m2/settings.xml ] && echo "✅ Maven settings.xml 存在" || echo "⚠️ Maven settings.xml 不存在"
|
|
144
|
+
timeout 10 java -version 2>&1 | head -1
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
**Gradle 项目:**
|
|
148
|
+
\`\`\`bash
|
|
149
|
+
timeout 10 gradle -v 2>/dev/null | head -1 && echo "✅ Gradle 可用" || echo "❌ Gradle 不可用"
|
|
150
|
+
\`\`\`
|
|
151
|
+
|
|
152
|
+
**Node.js 项目:**
|
|
153
|
+
\`\`\`bash
|
|
154
|
+
timeout 5 node -v 2>/dev/null && echo "✅ Node.js 可用" || echo "❌ Node.js 不可用"
|
|
155
|
+
timeout 5 npm -v 2>/dev/null && echo "✅ npm 可用" || echo "❌ npm 不可用"
|
|
156
|
+
timeout 5 pnpm -v 2>/dev/null && echo "✅ pnpm 可用" || echo "ℹ️ pnpm 未安装"
|
|
157
|
+
# 检查 registry
|
|
158
|
+
npm config get registry 2>/dev/null
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
**Python 项目:**
|
|
162
|
+
\`\`\`bash
|
|
163
|
+
timeout 5 python3 --version 2>/dev/null && echo "✅ Python3 可用" || echo "❌ Python3 不可用"
|
|
164
|
+
timeout 5 pip3 --version 2>/dev/null && echo "✅ pip3 可用" || echo "❌ pip3 不可用"
|
|
165
|
+
\`\`\`
|
|
166
|
+
|
|
167
|
+
### 3. Maven 私服检查(仅 Maven 项目)
|
|
168
|
+
\`\`\`bash
|
|
169
|
+
# 从 settings.xml 提取仓库地址
|
|
170
|
+
if [ -f ~/.m2/settings.xml ]; then
|
|
171
|
+
grep -oP 'https?://[^<"]+:[0-9]+' ~/.m2/settings.xml 2>/dev/null | sort -u | while read url; do
|
|
172
|
+
timeout 5 curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null
|
|
173
|
+
echo " — $url"
|
|
174
|
+
done
|
|
175
|
+
fi
|
|
176
|
+
# 从 pom.xml 提取
|
|
177
|
+
if [ -f "$PROJECT_DIR/pom.xml" ]; then
|
|
178
|
+
grep -oP 'https?://[^<"]+:[0-9]+' "$PROJECT_DIR/pom.xml" 2>/dev/null | sort -u | while read url; do
|
|
179
|
+
code=$(timeout 5 curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null)
|
|
180
|
+
[ "$code" = "000" ] && echo "❌ 私服不可达: $url(超时)" || echo "✅ 私服可达 ($code): $url"
|
|
181
|
+
done
|
|
182
|
+
fi
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
### 4. 运行时环境
|
|
186
|
+
\`\`\`bash
|
|
187
|
+
timeout 5 node -v 2>/dev/null && echo "Node.js: $(node -v)" || echo "❌ Node.js 未安装"
|
|
188
|
+
timeout 5 git --version 2>/dev/null && echo "Git: $(git --version)" || echo "❌ Git 未安装"
|
|
189
|
+
timeout 10 git remote -v 2>/dev/null | head -2
|
|
190
|
+
timeout 5 git ls-remote --heads origin 2>/dev/null >/dev/null && echo "✅ Git remote 可达" || echo "⚠️ Git remote 不可达"
|
|
191
|
+
timeout 5 java -version 2>&1 | head -1
|
|
192
|
+
timeout 5 python3 --version 2>/dev/null
|
|
193
|
+
\`\`\`
|
|
194
|
+
|
|
195
|
+
### 输出
|
|
196
|
+
汇总所有检查结果:
|
|
197
|
+
\`\`\`
|
|
198
|
+
## 构建环境
|
|
199
|
+
✅/⚠️/❌ 各项状态
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
### 注意
|
|
203
|
+
- 未检测到的构建工具直接跳过,不要报错
|
|
204
|
+
- timeout 超时的命令视为不可用
|
|
205
|
+
- 不编造结果`,
|
|
206
|
+
outputHint: '构建环境检查结果',
|
|
207
|
+
optional: false
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: '外部依赖检查',
|
|
211
|
+
prompt: `检查外部依赖工具是否可用。
|
|
212
|
+
|
|
213
|
+
### 1. Context7 MCP
|
|
214
|
+
\`\`\`bash
|
|
215
|
+
# 检查 MCP 配置
|
|
216
|
+
for f in ~/.config/claude/claude_desktop_config.json ~/.cursor/mcp.json ~/.openclaw/mcp.json; do
|
|
217
|
+
[ -f "$f" ] && echo "MCP 配置文件: $f" && grep -i context7 "$f" 2>/dev/null && echo "✅ Context7 已配置" || true
|
|
218
|
+
done
|
|
219
|
+
# 也检查 sillyspec 自身的 setup
|
|
220
|
+
node -e "
|
|
221
|
+
try{const m=require(require('path').join(require('os').homedir(),'.sillyspec','config.json'));console.log('✅ sillyspec config 存在')}catch{console.log('ℹ️ 无 sillyspec 全局配置')}
|
|
222
|
+
" 2>/dev/null
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
### 2. grep.app
|
|
226
|
+
\`\`\`bash
|
|
227
|
+
timeout 5 curl -s -o /dev/null -w "%{http_code}" https://grep.app 2>/dev/null | grep -q "200" && echo "✅ grep.app 可达" || echo "⚠️ grep.app 不可达"
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
### 3. 其他 AI 工具(可选)
|
|
231
|
+
\`\`\`bash
|
|
232
|
+
# 检查常用 AI/开发工具
|
|
233
|
+
timeout 5 which gh 2>/dev/null && echo "✅ GitHub CLI 可用" || echo "ℹ️ GitHub CLI 未安装"
|
|
234
|
+
timeout 5 which docker 2>/dev/null && echo "✅ Docker 可用" || echo "ℹ️ Docker 未安装"
|
|
235
|
+
\`\`\`
|
|
236
|
+
|
|
237
|
+
### 输出
|
|
238
|
+
\`\`\`
|
|
239
|
+
## 外部依赖
|
|
240
|
+
✅/⚠️/❌ 各项状态
|
|
241
|
+
\`\`\`
|
|
242
|
+
|
|
243
|
+
### 注意
|
|
244
|
+
- 不编造结果
|
|
245
|
+
- 工具未安装用 ℹ️ 标记(非错误),不可达用 ⚠️`,
|
|
246
|
+
outputHint: '外部依赖检查结果',
|
|
247
|
+
optional: false
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: '汇总报告',
|
|
251
|
+
prompt: `汇总前三步的所有检查结果,生成最终的自检报告。
|
|
252
|
+
|
|
253
|
+
### 输出格式
|
|
254
|
+
\`\`\`
|
|
255
|
+
🔍 SillySpec Doctor — 项目自检报告
|
|
256
|
+
|
|
257
|
+
## SillySpec 内部
|
|
258
|
+
✅ .sillyspec/ 目录结构 — 正常
|
|
259
|
+
✅ projects/*.yaml — N 个项目已注册
|
|
260
|
+
⚠️ local.yaml (xxx) — 缺少 test 命令
|
|
261
|
+
❌ progress.json — brainstorm 标记完成但 design.md 不存在
|
|
262
|
+
|
|
263
|
+
## 构建环境
|
|
264
|
+
✅ Node.js v23.4.0 — 可用
|
|
265
|
+
✅ npm 10.x — 可用
|
|
266
|
+
✅ Java 17.0.2 — 可用
|
|
267
|
+
❌ Maven 私服 (10.0.0.1:8081) — 不可达(超时)
|
|
268
|
+
|
|
269
|
+
## 外部依赖
|
|
270
|
+
✅ Context7 MCP — 已配置
|
|
271
|
+
⚠️ grep.app — 不可达
|
|
272
|
+
\`\`\`
|
|
273
|
+
|
|
274
|
+
### 要求
|
|
275
|
+
- 基于前 3 步的实际输出汇总,不要编造
|
|
276
|
+
- 每类问题归入对应分区
|
|
277
|
+
- 全部通过给出 🎉
|
|
278
|
+
- 如果有 ❌ 或 ⚠️,在末尾逐项给出修复建议
|
|
279
|
+
|
|
280
|
+
### 修复建议模板
|
|
281
|
+
根据问题类型给出具体可操作的修复命令:
|
|
282
|
+
|
|
283
|
+
**常见问题及修复:**
|
|
284
|
+
- CLI 未安装 → \`npm install -g sillyspec\`
|
|
285
|
+
- 缺少 local.yaml → \`sillyspec init\` 重新生成,或手动创建
|
|
286
|
+
- local.yaml 缺少 build/test → 补充对应命令
|
|
287
|
+
- 缺少 STACK.md → \`sillyspec run scan\` 重新扫描
|
|
288
|
+
- progress.json 不一致 → \`sillyspec run <阶段> --reset\` 重置对应阶段
|
|
289
|
+
- 孤儿目录 → 确认后 \`rm -rf .sillyspec/changes/<目录名>\`
|
|
290
|
+
- Maven 私服不可达 → 检查 VPN、settings.xml 配置、私服状态
|
|
291
|
+
- Git remote 不可达 → 检查网络、SSH key 或凭证
|
|
292
|
+
- 工具未安装 → 给出安装命令(如 \`brew install maven\`)
|
|
293
|
+
|
|
294
|
+
每条建议格式:
|
|
295
|
+
\`\`\`
|
|
296
|
+
💡 修复:<问题描述>
|
|
297
|
+
<具体命令或操作>
|
|
298
|
+
\`\`\``,
|
|
299
|
+
outputHint: '完整自检报告',
|
|
300
|
+
optional: false
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
export const definition = {
|
|
5
|
+
name: 'execute',
|
|
6
|
+
title: '波次执行',
|
|
7
|
+
description: '子代理并行 + 强制 TDD + 两阶段审查',
|
|
8
|
+
steps: [] // 动态构建,由 buildExecuteSteps() 生成
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 固定前缀步骤定义
|
|
12
|
+
const fixedPrefix = [
|
|
13
|
+
{
|
|
14
|
+
name: '状态检查',
|
|
15
|
+
prompt: `检查当前状态,确认可以执行 execute。
|
|
16
|
+
|
|
17
|
+
### 操作
|
|
18
|
+
1. 运行 \`sillyspec progress show\`
|
|
19
|
+
2. 确认 currentStage 为 execute
|
|
20
|
+
3. 如果不是 → 检查是否有未完成的 tasks.md
|
|
21
|
+
4. 确认执行范围($ARGUMENTS 指定 wave/task 或全部)
|
|
22
|
+
|
|
23
|
+
### 输出
|
|
24
|
+
当前状态 + 执行范围确认`,
|
|
25
|
+
outputHint: '当前状态 + 执行范围',
|
|
26
|
+
optional: false
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: '加载上下文',
|
|
30
|
+
prompt: `加载计划、设计和代码库上下文。
|
|
31
|
+
|
|
32
|
+
### 操作
|
|
33
|
+
1. 读取 tasks.md(执行计划)
|
|
34
|
+
2. 读取 design.md(技术方案)
|
|
35
|
+
3. 读取 CONVENTIONS.md、ARCHITECTURE.md
|
|
36
|
+
4. 读取 local.yaml(构建命令)
|
|
37
|
+
5. 加载 CODEBASE-OVERVIEW.md
|
|
38
|
+
|
|
39
|
+
### 输出
|
|
40
|
+
已加载的上下文摘要`,
|
|
41
|
+
outputHint: '上下文摘要',
|
|
42
|
+
optional: false
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: '确认执行范围',
|
|
46
|
+
prompt: `解析任务,确认执行范围和确认模式。
|
|
47
|
+
|
|
48
|
+
### 操作
|
|
49
|
+
1. 从 plan 中解析 Wave 分组和任务列表
|
|
50
|
+
2. 根据任务描述关键词为每个 Task 建议模型:
|
|
51
|
+
- 架构/复杂推理 → 最强模型
|
|
52
|
+
- 常规实现 → 中等模型
|
|
53
|
+
- 简单修改 → 快速模型
|
|
54
|
+
- 文档/写作 → 写作模型
|
|
55
|
+
3. 用户在 tasks.md 中的 [model:xxx] 标签优先
|
|
56
|
+
4. 询问用户执行确认频率:
|
|
57
|
+
- 每个 Wave 确认 — 每个 Wave 完成后展示结果
|
|
58
|
+
- AI 自主判断 — BLOCKED 或计划外变更时才询问
|
|
59
|
+
- 全自动 — 全部自动执行
|
|
60
|
+
5. 查询知识库:读取 \`.sillyspec/knowledge/INDEX.md\`,根据 Task 关键词匹配
|
|
61
|
+
|
|
62
|
+
### 输出
|
|
63
|
+
Wave 分组 + 模型分配 + 确认模式 + 知识库匹配结果
|
|
64
|
+
|
|
65
|
+
### 注意
|
|
66
|
+
- 默认推荐"每个 Wave 确认"`,
|
|
67
|
+
outputHint: 'Wave 分组 + 模型分配',
|
|
68
|
+
optional: false
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
// 固定后缀步骤定义
|
|
73
|
+
const fixedSuffix = [
|
|
74
|
+
{
|
|
75
|
+
name: '知识库审阅',
|
|
76
|
+
prompt: `检查本轮执行产生的新知识。
|
|
77
|
+
|
|
78
|
+
### 操作
|
|
79
|
+
1. 检查 \`.sillyspec/knowledge/uncategorized.md\` 中待确认条目
|
|
80
|
+
2. 如有 → 提示用户审阅
|
|
81
|
+
3. 用户确认后改为 [已确认],可归类到专题文件
|
|
82
|
+
|
|
83
|
+
### 输出
|
|
84
|
+
新知识条目数量 + 审阅提示(或"无新知识")`,
|
|
85
|
+
outputHint: '知识条目数量',
|
|
86
|
+
optional: true
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: '完成确认',
|
|
90
|
+
prompt: `所有任务完成后的收尾。
|
|
91
|
+
|
|
92
|
+
### 操作
|
|
93
|
+
1. 询问用户下一步:
|
|
94
|
+
- 验证 → sillyspec run verify
|
|
95
|
+
- 归档 → /sillyspec:archive
|
|
96
|
+
- 继续开发
|
|
97
|
+
2. 提示 git add 暂存变更
|
|
98
|
+
|
|
99
|
+
### 输出
|
|
100
|
+
用户选择 + 下一步命令
|
|
101
|
+
|
|
102
|
+
### 注意
|
|
103
|
+
- 完成后运行 \`sillyspec run execute --done\` 即可自动推进阶段`,
|
|
104
|
+
outputHint: '用户选择',
|
|
105
|
+
optional: false
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 从 plan 文件解析 Wave 分组
|
|
111
|
+
*/
|
|
112
|
+
function parseWavesFromPlan(planContent) {
|
|
113
|
+
const waves = []
|
|
114
|
+
const lines = planContent.split('\n')
|
|
115
|
+
let currentWave = null
|
|
116
|
+
let currentTask = null
|
|
117
|
+
|
|
118
|
+
for (const line of lines) {
|
|
119
|
+
const waveMatch = line.match(/^#+\s*Wave\s+(\d+)/i)
|
|
120
|
+
if (waveMatch) {
|
|
121
|
+
currentWave = { index: parseInt(waveMatch[1]), tasks: [] }
|
|
122
|
+
currentTask = null
|
|
123
|
+
waves.push(currentWave)
|
|
124
|
+
continue
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!currentWave) continue
|
|
128
|
+
|
|
129
|
+
const taskMatch = line.match(/^[-*]\s*\[[ x]\]\s*(.+)/)
|
|
130
|
+
if (taskMatch) {
|
|
131
|
+
const taskNoMatch = taskMatch[1].match(/\btask-(\d+)\b/i)
|
|
132
|
+
currentTask = {
|
|
133
|
+
index: taskNoMatch ? parseInt(taskNoMatch[1], 10) : null,
|
|
134
|
+
name: taskMatch[1].trim(),
|
|
135
|
+
file: '',
|
|
136
|
+
steps: '',
|
|
137
|
+
reference: ''
|
|
138
|
+
}
|
|
139
|
+
// 兼容旧格式:任务名后跟 (文件路径)
|
|
140
|
+
const fileMatch = taskMatch[1].match(/\(([^)]+)\)$/)
|
|
141
|
+
if (fileMatch) {
|
|
142
|
+
currentTask.file = fileMatch[1]
|
|
143
|
+
currentTask.name = taskMatch[1].replace(/\([^)]+\)$/, '').trim()
|
|
144
|
+
}
|
|
145
|
+
currentWave.tasks.push(currentTask)
|
|
146
|
+
continue
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 解析子行信息(修改/参考/步骤)
|
|
150
|
+
if (currentTask) {
|
|
151
|
+
const modMatch = line.match(/^\s+-\s*修改:\s*(.+)/)
|
|
152
|
+
if (modMatch) { currentTask.file = modMatch[1].trim(); continue }
|
|
153
|
+
|
|
154
|
+
const refMatch = line.match(/^\s+-\s*参考:\s*(.+)/)
|
|
155
|
+
if (refMatch) { currentTask.reference = refMatch[1].trim(); continue }
|
|
156
|
+
|
|
157
|
+
const stepMatch = line.match(/^\s+-\s*步骤:/)
|
|
158
|
+
if (stepMatch) { currentTask.steps = line.replace(/^\s+-\s*步骤:\s*/, '').trim(); continue }
|
|
159
|
+
|
|
160
|
+
// 步骤续行(数字开头的子步骤)
|
|
161
|
+
if (currentTask.steps && line.match(/^\s+\d+\./)) {
|
|
162
|
+
currentTask.steps += '\n' + line.trim()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return waves
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 为 Wave 生成 prompt(强制子代理执行)
|
|
172
|
+
*/
|
|
173
|
+
function buildWavePrompt(wave, waveIndex, changeDir) {
|
|
174
|
+
// 构建子代理 prompt 模板(每个任务的蓝图内容)
|
|
175
|
+
const subagentTemplates = wave.tasks.map((t, ti) => {
|
|
176
|
+
const taskNum = String(t.index || (ti + 1)).padStart(2, '0')
|
|
177
|
+
const taskFile = changeDir ? `${changeDir}/tasks/task-${taskNum}.md` : ''
|
|
178
|
+
const taskFileExists = taskFile && existsSync(taskFile)
|
|
179
|
+
let taskContent = ''
|
|
180
|
+
if (taskFileExists) {
|
|
181
|
+
try { taskContent = readFileSync(taskFile, 'utf8').trim() } catch { taskContent = '(无法读取任务蓝图文件)' }
|
|
182
|
+
}
|
|
183
|
+
const fileInfo = t.file ? ` (${t.file})` : ''
|
|
184
|
+
return `\`\`\`
|
|
185
|
+
任务:${t.name}${fileInfo}
|
|
186
|
+
${taskContent ? `蓝图内容:\n${taskContent}` : '(无蓝图文件,按任务描述执行)'}
|
|
187
|
+
|
|
188
|
+
操作:
|
|
189
|
+
1. 先读后写 — 读取要修改的文件,理解现有结构
|
|
190
|
+
2. 按 TDD 步骤实现
|
|
191
|
+
3. 运行对应测试确认通过
|
|
192
|
+
4. 报告改动文件和测试结果
|
|
193
|
+
|
|
194
|
+
铁律:
|
|
195
|
+
- 只做蓝图/任务描述里写的事,不增不减
|
|
196
|
+
- 蓝图有问题 → 报告问题,不要自己改
|
|
197
|
+
- 先写测试,再写代码
|
|
198
|
+
- grep 确认方法存在,不要编造
|
|
199
|
+
\`\`\``
|
|
200
|
+
}).join('\n\n')
|
|
201
|
+
|
|
202
|
+
const taskList = wave.tasks.map((t, ti) => {
|
|
203
|
+
const taskNum = String(t.index || (ti + 1)).padStart(2, '0')
|
|
204
|
+
let s = `- [ ] ${t.name}`
|
|
205
|
+
if (t.file) s += ` (${t.file})`
|
|
206
|
+
return s
|
|
207
|
+
}).join('\n')
|
|
208
|
+
|
|
209
|
+
return `## Wave ${waveIndex}: 执行以下任务
|
|
210
|
+
|
|
211
|
+
## 执行方式(必须严格遵守)
|
|
212
|
+
|
|
213
|
+
**每个任务必须由独立子代理执行,你不要自己写代码。**
|
|
214
|
+
|
|
215
|
+
你的角色是调度者 + 审查者:
|
|
216
|
+
1. 为每个任务启动一个子代理(Agent tool),同 Wave 内可并行
|
|
217
|
+
2. 子代理完成后审查结果
|
|
218
|
+
3. 勾选 plan.md 中的 checkbox
|
|
219
|
+
4. 记录改动文件和测试结果
|
|
220
|
+
|
|
221
|
+
### 子代理 prompt 模板
|
|
222
|
+
为每个任务使用以下 prompt 启动子代理:
|
|
223
|
+
|
|
224
|
+
${subagentTemplates}
|
|
225
|
+
|
|
226
|
+
### Wave 开始前
|
|
227
|
+
1. 读取 design.md 的「编码铁律」章节(如果存在),严格遵守
|
|
228
|
+
2. 读取 plan.md 了解全局任务划分和依赖关系
|
|
229
|
+
3. 确认本 Wave 的输入/输出契约(前置 Wave 产出了什么,本 Wave 需要消费什么)
|
|
230
|
+
4. 检查前置 Wave 的产出是否完整(文件是否存在、测试是否通过)
|
|
231
|
+
5. **上下文分层加载**:
|
|
232
|
+
- 🔥 热上下文:design.md 编码铁律 + 当前 Wave 任务(必须加载)
|
|
233
|
+
- 🌡️ 温上下文:CONVENTIONS.md + ARCHITECTURE.md(需要时加载)
|
|
234
|
+
- ❄️ 冷上下文:其他变更的 design.md、历史 plan.md(不要主动加载,除非明确需要)
|
|
235
|
+
|
|
236
|
+
### 本 Wave 任务
|
|
237
|
+
${taskList}
|
|
238
|
+
|
|
239
|
+
### 调度要求
|
|
240
|
+
1. 同一 Wave 内任务可并行启动子代理
|
|
241
|
+
2. **Reverse Sync**:子代理报告实现与 design.md 不一致时,先检查是代码错了还是文档有遗漏
|
|
242
|
+
3. **不要频繁编译!** 编译很慢,只在以下情况运行:
|
|
243
|
+
- 写了大量代码后需要验证语法正确性
|
|
244
|
+
- 最后一个 Wave 完成后做一次全量编译验证
|
|
245
|
+
- 用户明确要求编译时
|
|
246
|
+
4. 每个任务完成后:
|
|
247
|
+
- 勾选 plan.md / tasks.md 中对应任务的 checkbox
|
|
248
|
+
- 记录改动文件和测试结果
|
|
249
|
+
5. 遇到 BLOCKED → 记录原因,选择:重试/跳过/停止
|
|
250
|
+
|
|
251
|
+
### 完成后
|
|
252
|
+
运行 sillyspec run execute --done --input "用户原始反馈" --output "Wave ${waveIndex} 结果摘要"`
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 动态构建 execute 步骤列表
|
|
257
|
+
* @param {string|null} planFilePath - plan 文件路径,null 则用默认 3 Wave
|
|
258
|
+
* @returns {Array} 步骤列表
|
|
259
|
+
*/
|
|
260
|
+
export function buildExecuteSteps(planFilePath = null) {
|
|
261
|
+
let waves
|
|
262
|
+
let changeDir = null
|
|
263
|
+
|
|
264
|
+
if (planFilePath && existsSync(planFilePath)) {
|
|
265
|
+
const planContent = readFileSync(planFilePath, 'utf8')
|
|
266
|
+
waves = parseWavesFromPlan(planContent)
|
|
267
|
+
// 从 planFilePath 推导 changeDir: .sillyspec/changes/<name>/plan.md
|
|
268
|
+
changeDir = path.dirname(planFilePath)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 如果没解析出 Wave,生成默认 3 个
|
|
272
|
+
if (!waves || waves.length === 0) {
|
|
273
|
+
waves = []
|
|
274
|
+
for (let i = 1; i <= 3; i++) {
|
|
275
|
+
waves.push({ index: i, tasks: [{ name: `默认任务 ${i}`, file: 'TBD' }] })
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const waveSteps = waves.map((wave, i) => ({
|
|
280
|
+
name: `Wave ${i + 1} 执行`,
|
|
281
|
+
prompt: buildWavePrompt(wave, i + 1, changeDir),
|
|
282
|
+
outputHint: `Wave ${i + 1} 执行结果`,
|
|
283
|
+
optional: false
|
|
284
|
+
}))
|
|
285
|
+
|
|
286
|
+
return [...fixedPrefix, ...waveSteps, ...fixedSuffix]
|
|
287
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const definition = {
|
|
2
|
+
name: 'explore',
|
|
3
|
+
title: '自由探索',
|
|
4
|
+
description: '讨论、调研、画图,不写实现代码',
|
|
5
|
+
auxiliary: true,
|
|
6
|
+
steps: [
|
|
7
|
+
{
|
|
8
|
+
name: '自由探索',
|
|
9
|
+
prompt: `围绕用户给出的话题做技术探索,不进入实现。
|
|
10
|
+
|
|
11
|
+
### 操作
|
|
12
|
+
1. 明确探索边界:这次只讨论、调研、画图和识别风险
|
|
13
|
+
2. 如果需要代码库上下文,可以读取:
|
|
14
|
+
- \`.sillyspec/projects/*.yaml\`
|
|
15
|
+
- \`.sillyspec/docs/<project>/scan/ARCHITECTURE.md\`
|
|
16
|
+
- \`.sillyspec/docs/<project>/scan/CONVENTIONS.md\`
|
|
17
|
+
- \`.sillyspec/changes/<change-name>/design.md\`
|
|
18
|
+
3. 可以用 \`rg\` / \`ls\` / \`cat\` 调查已有结构和集成点
|
|
19
|
+
4. 输出 2-3 个有价值方向、关键风险和下一步建议
|
|
20
|
+
5. 如果用户要求保存结论,先明确保存位置,再写入对应文档
|
|
21
|
+
|
|
22
|
+
### 输出
|
|
23
|
+
探索结论、选项对比、风险清单或 ASCII 图
|
|
24
|
+
|
|
25
|
+
### 铁律
|
|
26
|
+
- 不写实现代码
|
|
27
|
+
- 不安装依赖
|
|
28
|
+
- 不修改文件,除非用户明确要求保存探索结论
|
|
29
|
+
- 不强行推进到 brainstorm/plan/execute`,
|
|
30
|
+
outputHint: '探索结论',
|
|
31
|
+
optional: false
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { definition as brainstorm } from './brainstorm.js'
|
|
2
|
+
import { definition as propose } from './propose.js'
|
|
3
|
+
import { definition as plan } from './plan.js'
|
|
4
|
+
import { definition as execute } from './execute.js'
|
|
5
|
+
import { definition as verify } from './verify.js'
|
|
6
|
+
import { definition as scan } from './scan.js'
|
|
7
|
+
import { definition as quick } from './quick.js'
|
|
8
|
+
import { definition as explore } from './explore.js'
|
|
9
|
+
import { definition as archive } from './archive.js'
|
|
10
|
+
import { definition as status } from './status.js'
|
|
11
|
+
import { definition as doctor } from './doctor.js'
|
|
12
|
+
|
|
13
|
+
export const stageRegistry = {
|
|
14
|
+
brainstorm,
|
|
15
|
+
propose,
|
|
16
|
+
plan,
|
|
17
|
+
execute,
|
|
18
|
+
verify,
|
|
19
|
+
scan,
|
|
20
|
+
quick,
|
|
21
|
+
explore,
|
|
22
|
+
archive,
|
|
23
|
+
status,
|
|
24
|
+
doctor
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 辅助命令(在没有 progress.json 时也可执行)
|
|
28
|
+
export const auxiliaryStages = ['scan', 'quick', 'explore', 'archive', 'status', 'doctor']
|