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.
Files changed (206) hide show
  1. package/.claude/skills/sillyspec-archive/SKILL.md +17 -0
  2. package/.claude/skills/sillyspec-auto/SKILL.md +78 -0
  3. package/.claude/skills/sillyspec-brainstorm/SKILL.md +17 -0
  4. package/{templates/commit.md → .claude/skills/sillyspec-commit/SKILL.md} +32 -47
  5. package/.claude/skills/sillyspec-continue/SKILL.md +45 -0
  6. package/.claude/skills/sillyspec-doctor/SKILL.md +27 -0
  7. package/.claude/skills/sillyspec-execute/SKILL.md +17 -0
  8. package/.claude/skills/sillyspec-explore/SKILL.md +105 -0
  9. package/.claude/skills/sillyspec-export/SKILL.md +53 -0
  10. package/.claude/skills/sillyspec-init/SKILL.md +170 -0
  11. package/.claude/skills/sillyspec-plan/SKILL.md +17 -0
  12. package/.claude/skills/sillyspec-propose/SKILL.md +17 -0
  13. package/.claude/skills/sillyspec-quick/SKILL.md +17 -0
  14. package/.claude/skills/sillyspec-resume/SKILL.md +111 -0
  15. package/.claude/skills/sillyspec-scan/SKILL.md +17 -0
  16. package/.claude/skills/sillyspec-state/SKILL.md +54 -0
  17. package/.claude/skills/sillyspec-status/SKILL.md +17 -0
  18. package/.claude/skills/sillyspec-verify/SKILL.md +17 -0
  19. package/.claude/skills/sillyspec-workspace/SKILL.md +149 -0
  20. package/README.md +19 -11
  21. package/SKILL.md +15 -10
  22. package/package.json +7 -9
  23. package/packages/dashboard/dist/assets/index-BcM2J-hv.css +1 -0
  24. package/packages/dashboard/dist/assets/index-DpLHK4jv.js +7446 -0
  25. package/packages/dashboard/dist/index.html +16 -16
  26. package/packages/dashboard/dist/prototype-dashboard.html +836 -0
  27. package/packages/dashboard/dist/prototype-overview.html +256 -0
  28. package/packages/dashboard/package-lock.json +226 -6
  29. package/packages/dashboard/package.json +8 -5
  30. package/packages/dashboard/public/logo.jpg +0 -0
  31. package/packages/dashboard/public/prototype-dashboard.html +836 -0
  32. package/packages/dashboard/public/prototype-overview.html +256 -0
  33. package/packages/dashboard/server/executor.js +1 -1
  34. package/packages/dashboard/server/index.js +341 -113
  35. package/packages/dashboard/server/parser.js +442 -30
  36. package/packages/dashboard/server/watcher.js +214 -134
  37. package/packages/dashboard/src/App.vue +475 -71
  38. package/packages/dashboard/src/components/ActionBar.vue +36 -43
  39. package/packages/dashboard/src/components/CommandPalette.vue +45 -66
  40. package/packages/dashboard/src/components/DetailPanel.vue +68 -53
  41. package/packages/dashboard/src/components/DocPreview.vue +257 -0
  42. package/packages/dashboard/src/components/DocTree.vue +114 -0
  43. package/packages/dashboard/src/components/HResizeHandle.vue +48 -0
  44. package/packages/dashboard/src/components/LogStream.vue +13 -33
  45. package/packages/dashboard/src/components/PipelineStage.vue +8 -8
  46. package/packages/dashboard/src/components/PipelineView.vue +99 -45
  47. package/packages/dashboard/src/components/ProjectCard.vue +187 -0
  48. package/packages/dashboard/src/components/ProjectList.vue +103 -45
  49. package/packages/dashboard/src/components/ProjectOverview.vue +152 -0
  50. package/packages/dashboard/src/components/StageBadge.vue +13 -13
  51. package/packages/dashboard/src/components/StepCard.vue +15 -15
  52. package/packages/dashboard/src/components/VResizeHandle.vue +61 -0
  53. package/packages/dashboard/src/components/detail/DocsDetail.vue +48 -0
  54. package/packages/dashboard/src/components/detail/GitDetail.vue +61 -0
  55. package/packages/dashboard/src/components/detail/TechDetail.vue +43 -0
  56. package/packages/dashboard/src/composables/useDashboard.js +48 -6
  57. package/packages/dashboard/src/composables/useKeyboard.js +6 -4
  58. package/packages/dashboard/src/composables/useLayout.js +131 -0
  59. package/packages/dashboard/src/main.js +4 -1
  60. package/packages/dashboard/src/style.css +17 -17
  61. package/src/index.js +141 -22
  62. package/src/init.js +93 -231
  63. package/src/migrate.js +117 -0
  64. package/src/progress.js +460 -0
  65. package/src/run.js +635 -0
  66. package/src/setup.js +2 -72
  67. package/src/stages/archive.js +54 -0
  68. package/src/stages/brainstorm.js +264 -0
  69. package/src/stages/doctor.js +303 -0
  70. package/src/stages/execute.js +287 -0
  71. package/src/stages/explore.js +34 -0
  72. package/src/stages/index.js +28 -0
  73. package/src/stages/plan.js +354 -0
  74. package/src/stages/propose.js +115 -0
  75. package/src/stages/quick.js +64 -0
  76. package/src/stages/scan.js +141 -0
  77. package/src/stages/status.js +65 -0
  78. package/src/stages/verify.js +135 -0
  79. package/.sillyspec/changes/dashboard/design.md +0 -219
  80. package/.sillyspec/plans/2026-04-05-dashboard.md +0 -737
  81. package/.sillyspec/specs/2026-04-05-dashboard-design.md +0 -206
  82. package/dist/steps/brainstorm/01-load-context.md +0 -30
  83. package/dist/steps/brainstorm/02-reuse-check.md +0 -6
  84. package/dist/steps/brainstorm/03-prototype-analysis.md +0 -11
  85. package/dist/steps/brainstorm/04-module-split.md +0 -23
  86. package/dist/steps/brainstorm/05-dialog-explore.md +0 -8
  87. package/dist/steps/brainstorm/06-propose-approaches.md +0 -3
  88. package/dist/steps/brainstorm/07-present-design.md +0 -3
  89. package/dist/steps/brainstorm/08-write-design.md +0 -21
  90. package/dist/steps/brainstorm/09-self-review.md +0 -15
  91. package/dist/steps/brainstorm/10-user-confirm.md +0 -3
  92. package/dist/steps/brainstorm/11-output-spec.md +0 -7
  93. package/dist/steps/brainstorm/manifest.yaml +0 -26
  94. package/dist/steps/execute/01-load-context.md +0 -41
  95. package/dist/steps/execute/02-scan-conventions.md +0 -47
  96. package/dist/steps/execute/03-skill-mcp.md +0 -19
  97. package/dist/steps/execute/04-assign-task.md +0 -22
  98. package/dist/steps/execute/04b-prompt-template.md +0 -54
  99. package/dist/steps/execute/05-write-test.md +0 -7
  100. package/dist/steps/execute/06-write-code.md +0 -8
  101. package/dist/steps/execute/07-run-test.md +0 -26
  102. package/dist/steps/execute/08-fix-issues.md +0 -28
  103. package/dist/steps/execute/09-next-task.md +0 -33
  104. package/dist/steps/execute/manifest.yaml +0 -28
  105. package/dist/steps/plan/01-load-context.md +0 -22
  106. package/dist/steps/plan/02-anchor-confirm.md +0 -1
  107. package/dist/steps/plan/03-expand-tasks.md +0 -33
  108. package/dist/steps/plan/04-mark-order.md +0 -15
  109. package/dist/steps/plan/05-e2e-planning.md +0 -17
  110. package/dist/steps/plan/06-self-check.md +0 -16
  111. package/dist/steps/plan/07-save.md +0 -1
  112. package/dist/steps/plan/manifest.yaml +0 -18
  113. package/dist/steps/scan/01-env-detect.md +0 -51
  114. package/dist/steps/scan/02-tech-stack.md +0 -16
  115. package/dist/steps/scan/03-conventions.md +0 -16
  116. package/dist/steps/scan/04-structure.md +0 -19
  117. package/dist/steps/scan/05-quality.md +0 -18
  118. package/dist/steps/scan/06-complete.md +0 -49
  119. package/dist/steps/scan/manifest.yaml +0 -16
  120. package/dist/steps/verify/01-load-specs.md +0 -28
  121. package/dist/steps/verify/02-check-tasks.md +0 -1
  122. package/dist/steps/verify/03-check-design.md +0 -6
  123. package/dist/steps/verify/04-run-tests.md +0 -7
  124. package/dist/steps/verify/05-e2e-tests.md +0 -27
  125. package/dist/steps/verify/05b-e2e-fix.md +0 -33
  126. package/dist/steps/verify/06-code-quality.md +0 -25
  127. package/dist/steps/verify/07-lint-check.md +0 -27
  128. package/dist/steps/verify/08-output-report.md +0 -14
  129. package/dist/steps/verify/manifest.yaml +0 -22
  130. package/docs/.vitepress/config.mts +0 -45
  131. package/docs/.vitepress/dist/404.html +0 -25
  132. package/docs/.vitepress/dist/assets/app.YytxICdd.js +0 -1
  133. package/docs/.vitepress/dist/assets/chunks/framework.Czhw_PXq.js +0 -19
  134. package/docs/.vitepress/dist/assets/chunks/theme.DusTRZQk.js +0 -1
  135. package/docs/.vitepress/dist/assets/index.md.C3VCvtQA.js +0 -1
  136. package/docs/.vitepress/dist/assets/index.md.C3VCvtQA.lean.js +0 -1
  137. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  138. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  139. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  140. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  141. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  142. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  143. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  144. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  145. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  146. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  147. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  148. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  149. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  150. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  151. package/docs/.vitepress/dist/assets/sillyspec_commands.md.CXFFsj08.js +0 -15
  152. package/docs/.vitepress/dist/assets/sillyspec_commands.md.CXFFsj08.lean.js +0 -1
  153. package/docs/.vitepress/dist/assets/sillyspec_dashboard.md.BuPXHqjX.js +0 -4
  154. package/docs/.vitepress/dist/assets/sillyspec_dashboard.md.BuPXHqjX.lean.js +0 -1
  155. package/docs/.vitepress/dist/assets/sillyspec_file-io.md.Cz3x7llx.js +0 -1
  156. package/docs/.vitepress/dist/assets/sillyspec_file-io.md.Cz3x7llx.lean.js +0 -1
  157. package/docs/.vitepress/dist/assets/sillyspec_getting-started.md.ClcvV8k3.js +0 -4
  158. package/docs/.vitepress/dist/assets/sillyspec_getting-started.md.ClcvV8k3.lean.js +0 -1
  159. package/docs/.vitepress/dist/assets/sillyspec_install.md.CKuR2tiT.js +0 -5
  160. package/docs/.vitepress/dist/assets/sillyspec_install.md.CKuR2tiT.lean.js +0 -1
  161. package/docs/.vitepress/dist/assets/sillyspec_lifecycle.md.DY293cR1.js +0 -28
  162. package/docs/.vitepress/dist/assets/sillyspec_lifecycle.md.DY293cR1.lean.js +0 -1
  163. package/docs/.vitepress/dist/assets/sillyspec_structure.md.sVYS4zPs.js +0 -30
  164. package/docs/.vitepress/dist/assets/sillyspec_structure.md.sVYS4zPs.lean.js +0 -1
  165. package/docs/.vitepress/dist/assets/style.DFTx90Kk.css +0 -1
  166. package/docs/.vitepress/dist/hashmap.json +0 -1
  167. package/docs/.vitepress/dist/index.html +0 -28
  168. package/docs/.vitepress/dist/sillyspec/commands.html +0 -42
  169. package/docs/.vitepress/dist/sillyspec/dashboard.html +0 -31
  170. package/docs/.vitepress/dist/sillyspec/file-io.html +0 -28
  171. package/docs/.vitepress/dist/sillyspec/getting-started.html +0 -31
  172. package/docs/.vitepress/dist/sillyspec/install.html +0 -32
  173. package/docs/.vitepress/dist/sillyspec/lifecycle.html +0 -55
  174. package/docs/.vitepress/dist/sillyspec/structure.html +0 -57
  175. package/docs/.vitepress/dist/vp-icons.css +0 -1
  176. package/docs/index.md +0 -34
  177. package/docs/sillyspec/commands.md +0 -218
  178. package/docs/sillyspec/dashboard.md +0 -51
  179. package/docs/sillyspec/file-io.md +0 -34
  180. package/docs/sillyspec/getting-started.md +0 -61
  181. package/docs/sillyspec/install.md +0 -51
  182. package/docs/sillyspec/lifecycle.md +0 -146
  183. package/docs/sillyspec/structure.md +0 -62
  184. package/packages/dashboard/dist/assets/index-Bh-GPjKY.css +0 -1
  185. package/packages/dashboard/dist/assets/index-CrCn5Gg6.js +0 -17
  186. package/src/step.js +0 -543
  187. package/templates/archive.md +0 -120
  188. package/templates/brainstorm.md +0 -170
  189. package/templates/continue.md +0 -32
  190. package/templates/execute.md +0 -304
  191. package/templates/explore.md +0 -59
  192. package/templates/export.md +0 -21
  193. package/templates/init.md +0 -61
  194. package/templates/plan.md +0 -146
  195. package/templates/quick.md +0 -135
  196. package/templates/scan-quick.md +0 -49
  197. package/templates/scan.md +0 -156
  198. package/templates/skills/playwright-e2e/SKILL.md +0 -340
  199. package/templates/status.md +0 -75
  200. package/templates/verify.md +0 -236
  201. package/templates/workspace-sync.md +0 -99
  202. package/templates/workspace.md +0 -70
  203. /package/{docs/.vitepress/dist/logo.jpg → logo.jpg} +0 -0
  204. /package/{docs/.vitepress → packages/dashboard}/dist/favicon.jpg +0 -0
  205. /package/{docs/public → packages/dashboard/dist}/logo.jpg +0 -0
  206. /package/{docs → packages/dashboard}/public/favicon.jpg +0 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * 布局管理 Composable
3
+ * 管理双层布局的概览/详情比例和三栏宽度
4
+ */
5
+ import { reactive, ref, onMounted } from 'vue'
6
+
7
+ const STORAGE_KEY = 'dashboard-layout-v2'
8
+
9
+ // 默认值
10
+ const DEFAULT_OVERVIEW_HEIGHT = 30 // 概览区域百分比
11
+ const DEFAULT_COLUMN_WIDTHS = [33.33, 33.33, 33.33] // 三栏宽度百分比
12
+
13
+ // 最小值限制
14
+ const MIN_OVERVIEW_HEIGHT = 15
15
+ const MAX_OVERVIEW_HEIGHT = 75
16
+ const MIN_COLUMN_WIDTH = 10
17
+
18
+ /**
19
+ * 布局管理 Hook
20
+ */
21
+ export function useLayout() {
22
+ // 布局状态
23
+ const layout = reactive({
24
+ overviewHeight: DEFAULT_OVERVIEW_HEIGHT,
25
+ columnWidths: [...DEFAULT_COLUMN_WIDTHS]
26
+ })
27
+
28
+ // 拖动状态
29
+ const isDragging = ref(false)
30
+ const dragType = ref(null) // 'vertical' | 'horizontal'
31
+
32
+ /**
33
+ * 加载保存的布局
34
+ */
35
+ function loadLayout() {
36
+ try {
37
+ const saved = localStorage.getItem(STORAGE_KEY)
38
+ if (saved) {
39
+ const parsed = JSON.parse(saved)
40
+ if (parsed.overviewHeight !== undefined) {
41
+ layout.overviewHeight = Math.max(MIN_OVERVIEW_HEIGHT, Math.min(MAX_OVERVIEW_HEIGHT, parsed.overviewHeight))
42
+ }
43
+ if (Array.isArray(parsed.columnWidths) && parsed.columnWidths.length === 3) {
44
+ layout.columnWidths = parsed.columnWidths
45
+ }
46
+ }
47
+ } catch (e) {
48
+ console.error('Failed to load layout:', e)
49
+ // 使用默认值
50
+ resetLayout()
51
+ }
52
+ }
53
+
54
+ /**
55
+ * 保存布局到 localStorage
56
+ */
57
+ function saveLayout() {
58
+ try {
59
+ localStorage.setItem(STORAGE_KEY, JSON.stringify({
60
+ overviewHeight: layout.overviewHeight,
61
+ columnWidths: layout.columnWidths
62
+ }))
63
+ } catch (e) {
64
+ console.error('Failed to save layout:', e)
65
+ }
66
+ }
67
+
68
+ /**
69
+ * 重置布局为默认值
70
+ */
71
+ function resetLayout() {
72
+ layout.overviewHeight = DEFAULT_OVERVIEW_HEIGHT
73
+ layout.columnWidths = [...DEFAULT_COLUMN_WIDTHS]
74
+ saveLayout()
75
+ }
76
+
77
+ /**
78
+ * 设置概览区域高度(百分比)
79
+ */
80
+ function setOverviewHeight(percent) {
81
+ layout.overviewHeight = Math.max(MIN_OVERVIEW_HEIGHT, Math.min(MAX_OVERVIEW_HEIGHT, percent))
82
+ saveLayout()
83
+ }
84
+
85
+ /**
86
+ * 设置列宽度(索引,百分比)
87
+ */
88
+ function setColumnWidth(index, percent) {
89
+ if (index >= 0 && index < 3) {
90
+ layout.columnWidths[index] = Math.max(MIN_COLUMN_WIDTH, percent)
91
+ saveLayout()
92
+ }
93
+ }
94
+
95
+ /**
96
+ * 开始拖动
97
+ */
98
+ function startDrag(type) {
99
+ isDragging.value = true
100
+ dragType.value = type
101
+ document.body.classList.add('resizing')
102
+ }
103
+
104
+ /**
105
+ * 结束拖动
106
+ */
107
+ function endDrag() {
108
+ isDragging.value = false
109
+ dragType.value = null
110
+ document.body.classList.remove('resizing')
111
+ saveLayout()
112
+ }
113
+
114
+ // 组件挂载时加载布局
115
+ onMounted(() => {
116
+ loadLayout()
117
+ })
118
+
119
+ return {
120
+ layout,
121
+ isDragging,
122
+ dragType,
123
+ loadLayout,
124
+ saveLayout,
125
+ resetLayout,
126
+ setOverviewHeight,
127
+ setColumnWidth,
128
+ startDrag,
129
+ endDrag
130
+ }
131
+ }
@@ -1,5 +1,8 @@
1
1
  import { createApp } from 'vue'
2
+ import naive from 'naive-ui'
2
3
  import App from './App.vue'
3
4
  import './style.css'
4
5
 
5
- createApp(App).mount('#app')
6
+ const app = createApp(App)
7
+ app.use(naive)
8
+ app.mount('#app')
@@ -1,20 +1,20 @@
1
1
  @import "tailwindcss";
2
2
 
3
3
  @theme {
4
- --color-bg: #0A0A0B;
5
- --color-primary: #FBBF24;
6
- --color-primary-dim: #B45309;
7
- --color-warning: #FB923C;
8
- --color-danger: #EF4444;
9
- --color-muted: #525252;
10
- --color-surface: #141416;
11
- --color-surface-2: #1C1C1F;
12
- --color-border: #2A2A2D;
13
- --color-border-light: #3A3A3D;
14
- --color-text: #E4E4E7;
15
- --color-text-secondary: #8B8B8E;
16
- --color-info: #38BDF8;
17
- --color-success: #34D399;
4
+ --color-bg: #F5F5F7;
5
+ --color-primary: #D97706;
6
+ --color-primary-dim: #92400E;
7
+ --color-warning: #EA580C;
8
+ --color-danger: #DC2626;
9
+ --color-muted: #6B7280;
10
+ --color-surface: #FFFFFF;
11
+ --color-surface-2: #F0F0F3;
12
+ --color-border: #E5E5EA;
13
+ --color-border-light: #D1D1D6;
14
+ --color-text: #1C1C1E;
15
+ --color-text-secondary: #636366;
16
+ --color-info: #2563EB;
17
+ --color-success: #16A34A;
18
18
 
19
19
  --font-display: 'JetBrains Mono', monospace;
20
20
  --font-body: 'DM Sans', sans-serif;
@@ -96,7 +96,7 @@
96
96
 
97
97
  /* Skeleton shimmer */
98
98
  .skeleton-shimmer {
99
- background: linear-gradient(90deg, #1C1C1F 25%, #2A2A2D 50%, #1C1C1F 75%);
99
+ background: linear-gradient(90deg, #1A1E28 25%, #2A3040 50%, #1A1E28 75%);
100
100
  background-size: 200% 100%;
101
101
  animation: shimmer 1.5s ease-in-out infinite;
102
102
  }
@@ -112,12 +112,12 @@
112
112
  }
113
113
 
114
114
  ::-webkit-scrollbar-thumb {
115
- background: #2A2A2D;
115
+ background: #2A3040;
116
116
  border-radius: 10px;
117
117
  }
118
118
 
119
119
  ::-webkit-scrollbar-thumb:hover {
120
- background: #3A3A3D;
120
+ background: #3A4555;
121
121
  }
122
122
 
123
123
  * {
package/src/index.js CHANGED
@@ -4,11 +4,12 @@
4
4
  * SillySpec CLI — 安装工具
5
5
  *
6
6
  * 只负责两件事:init(安装命令模板)和 setup(安装 MCP 工具)。
7
- * 状态管理由 AI 直接读文件(STATE.md)完成,不需要 CLI。
7
+ * 状态管理通过 progress.json 完成,使用 `sillyspec progress` 命令。
8
8
  */
9
- import { existsSync } from 'fs';
10
- import { resolve } from 'path';
9
+ import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
10
+ import { join, resolve } from 'path';
11
11
  import { cmdInit, getVersion } from './init.js';
12
+ import { ProgressManager } from './progress.js';
12
13
 
13
14
  // ── CLI 入口 ──
14
15
 
@@ -19,15 +20,36 @@ SillySpec CLI — 规范驱动开发工具包
19
20
  用法:
20
21
  sillyspec init 初始化(零交互,自动检测工具)
21
22
  [--tool <name>] 只安装指定工具
22
- [--workspace] 工作区模式
23
23
  [--interactive] 交互式引导
24
24
  [--dir <path>] 指定目录
25
+
25
26
  sillyspec setup [--list] 安装推荐 MCP 工具
26
27
  [--list] 查看已安装状态
27
- sillyspec step <phase> 步骤调度器
28
- [--next] [--status] [--list] [--jump <n>]
29
- [--sessions] [--clean]
30
- [--session <id>] [--json]
28
+
29
+ sillyspec run <stage> 执行阶段步骤(核心命令)
30
+ --done --output "..." 完成当前步骤
31
+ --skip 跳过可选步骤
32
+ --status 查看阶段进度
33
+ --reset 重置阶段
34
+ --change <name> 设置当前变更名
35
+ auto 连续推进 brainstorm→plan→execute→verify
36
+
37
+ 可选阶段:
38
+ scan, brainstorm, plan, execute, verify, archive
39
+ quick, explore, status, doctor
40
+
41
+ sillyspec progress <cmd> 进度记录(轻量,不强制顺序)
42
+ init 初始化 progress.json
43
+ show 查看当前进度
44
+ set-stage <stage> 设置当前阶段
45
+ add-step <stage> <name> 添加步骤
46
+ update-step <s> <n> --status <st> [--output <t>]
47
+ complete-stage <stage> 标记阶段完成
48
+ validate 校验并修复
49
+ reset [--stage X] 重置进度
50
+
51
+ sillyspec docs migrate 迁移旧文档到统一结构
52
+
31
53
  sillyspec dashboard 启动 Dashboard Web UI
32
54
  [--port <number>] 指定端口(默认 3456)
33
55
  [--no-open] 不自动打开浏览器
@@ -38,11 +60,12 @@ SillySpec CLI — 规范驱动开发工具包
38
60
 
39
61
  示例:
40
62
  sillyspec init
41
- sillyspec init --tool claude
42
- sillyspec init --workspace
43
- sillyspec setup
63
+ sillyspec run scan
64
+ sillyspec run brainstorm
65
+ sillyspec run quick
66
+ sillyspec run explore
67
+ sillyspec run brainstorm --done --output "需求已澄清"
44
68
  sillyspec setup --list
45
- sillyspec dashboard
46
69
  sillyspec dashboard --port 8080 --no-open
47
70
  `);
48
71
  }
@@ -64,7 +87,6 @@ async function main() {
64
87
  let json = false;
65
88
  let targetDir = process.cwd();
66
89
  let tool = null;
67
- let workspace = false;
68
90
  let interactive = false;
69
91
  const filteredArgs = [];
70
92
 
@@ -77,8 +99,6 @@ async function main() {
77
99
  } else if (args[i] === '--tool' && args[i + 1]) {
78
100
  tool = args[i + 1];
79
101
  i++;
80
- } else if (args[i] === '--workspace' || args[i] === '-w') {
81
- workspace = true;
82
102
  } else if (args[i] === '--interactive' || args[i] === '-i') {
83
103
  interactive = true;
84
104
  } else if (args[i] === '--list' || args[i] === '-l') {
@@ -89,8 +109,18 @@ async function main() {
89
109
  }
90
110
 
91
111
  const command = filteredArgs[0];
112
+ // 支持 sillyspec init /path/to/project 语法:如果第二个参数看起来像路径,当作 targetDir
113
+ if (command === 'init' && filteredArgs[1] && !filteredArgs[1].startsWith('-')) {
114
+ targetDir = resolve(filteredArgs[1]);
115
+ filteredArgs.splice(1, 1);
116
+ }
92
117
  const dir = targetDir;
93
118
 
119
+ if (command === 'init' && !existsSync(dir)) {
120
+ const { mkdirSync } = await import('fs');
121
+ mkdirSync(dir, { recursive: true });
122
+ }
123
+
94
124
  if (!existsSync(dir)) {
95
125
  console.error(`❌ 目录不存在: ${dir}`);
96
126
  process.exit(1);
@@ -98,21 +128,110 @@ async function main() {
98
128
 
99
129
  switch (command) {
100
130
  case 'init':
101
- await cmdInit(dir, { tool, workspace, interactive });
131
+ await cmdInit(dir, { tool, interactive });
102
132
  break;
103
133
  case 'setup':
104
134
  const setupList = filteredArgs.includes('--list') || filteredArgs.includes('-l');
105
135
  await (await import('./setup.js')).cmdSetup(dir, { json, list: setupList });
106
136
  break;
107
- case 'step': {
108
- const stepArgs = filteredArgs.slice(1);
109
- if (json) stepArgs.push('--json');
110
- await (await import('./step.js')).cmdStep(dir, stepArgs);
137
+ case 'progress': {
138
+ const pm = new ProgressManager();
139
+ const subCommand = filteredArgs[1];
140
+ const stageIdx = filteredArgs.indexOf('--stage');
141
+ const stage = stageIdx >= 0 && filteredArgs[stageIdx + 1] ? filteredArgs[stageIdx + 1] : null;
142
+
143
+ switch (subCommand) {
144
+ case 'init':
145
+ pm.init(dir);
146
+ break;
147
+ case 'status':
148
+ case 'show':
149
+ pm.show(dir);
150
+ break;
151
+ case 'validate':
152
+ await pm.validate(dir);
153
+ break;
154
+ case 'reset':
155
+ pm.reset(dir, stage);
156
+ break;
157
+ case 'set-stage': {
158
+ const setStageName = filteredArgs[2];
159
+ if (!setStageName) { console.log('❌ 用法: sillyspec progress set-stage <stage>'); break; }
160
+ pm.setStage(dir, setStageName);
161
+ break;
162
+ }
163
+ case 'add-step': {
164
+ const addStepStage = filteredArgs[2];
165
+ const addStepName = filteredArgs[3];
166
+ if (!addStepStage || !addStepName) { console.log('❌ 用法: sillyspec progress add-step <stage> <step-name>'); break; }
167
+ pm.addStep(dir, addStepStage, addStepName);
168
+ break;
169
+ }
170
+ case 'update-step': {
171
+ const updStepStage = filteredArgs[2];
172
+ const updStepName = filteredArgs[3];
173
+ if (!updStepStage || !updStepName) { console.log('❌ 用法: sillyspec progress update-step <stage> <step-name> --status <status> [--output <text>]'); break; }
174
+ // Parse --status and --output from args
175
+ let updStatus = null, updOutput = undefined;
176
+ for (let ai = 0; ai < args.length; ai++) {
177
+ if (args[ai] === '--status' && args[ai + 1]) { updStatus = args[ai + 1]; ai++; }
178
+ if (args[ai] === '--output' && args[ai + 1]) { updOutput = args[ai + 1]; ai++; }
179
+ }
180
+ pm.updateStep(dir, updStepStage, updStepName, { status: updStatus, output: updOutput });
181
+ break;
182
+ }
183
+ case 'complete-stage': {
184
+ const compStageName = filteredArgs[2];
185
+ if (!compStageName) { console.log('❌ 用法: sillyspec progress complete-stage <stage>'); break; }
186
+ pm.completeStage(dir, compStageName);
187
+ break;
188
+ }
189
+ case 'batch': {
190
+ if (filteredArgs.includes('--status')) {
191
+ const bp = pm.readBatchProgress(dir);
192
+ if (!bp) { console.log('📭 无批量进度数据'); break; }
193
+ const line = pm._renderBatchProgress(bp);
194
+ console.log(line || '📭 无批量进度数据');
195
+ console.log(JSON.stringify(bp, null, 2));
196
+ } else {
197
+ let batchData = {};
198
+ const a = args;
199
+ for (let i = 0; i < a.length; i++) {
200
+ if (a[i] === '--total' && a[i + 1]) { batchData.total = parseInt(a[i + 1]); i++; }
201
+ if (a[i] === '--completed' && a[i + 1]) { batchData.completed = parseInt(a[i + 1]); i++; }
202
+ if (a[i] === '--failed' && a[i + 1]) { batchData.failed = parseInt(a[i + 1]); i++; }
203
+ if (a[i] === '--skipped' && a[i + 1]) { batchData.skipped = parseInt(a[i + 1]); i++; }
204
+ }
205
+ if (Object.keys(batchData).length === 0) {
206
+ console.log('用法: sillyspec progress batch --total 100 --completed 73');
207
+ console.log(' sillyspec progress batch --status');
208
+ break;
209
+ }
210
+ pm.updateBatchProgress(dir, batchData);
211
+ console.log('✅ 批量进度已更新');
212
+ }
213
+ break;
214
+ }
215
+ default:
216
+ console.log('用法: sillyspec progress <init|show|validate|reset|set-stage|add-step|update-step|complete-stage>');
217
+ }
111
218
  break;
112
219
  }
113
- case 'progress':
114
- console.log('⚠️ 阶段控制功能已移除,各阶段独立运行。');
220
+ case 'docs': {
221
+ const docsSubCmd = filteredArgs[1];
222
+ if (docsSubCmd === 'migrate') {
223
+ const { migrateDocs } = await import('./migrate.js');
224
+ migrateDocs(dir);
225
+ } else {
226
+ console.log('用法: sillyspec docs migrate');
227
+ }
115
228
  break;
229
+ }
230
+ case 'run': {
231
+ const { runCommand } = await import('./run.js')
232
+ await runCommand(filteredArgs.slice(1), dir)
233
+ break
234
+ }
116
235
  case 'dashboard': {
117
236
  // Parse dashboard options
118
237
  let port = 3456;