sillyspec 3.1.0 → 3.2.1

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.
@@ -56,6 +56,8 @@ $ARGUMENTS
56
56
  - **STATE.md:** 清除当前变更信息,历史记录追加归档完成
57
57
  - **Git 提交:** `git add .sillyspec/ && git commit -m "docs: archive sillyspec change <change-name>"`
58
58
 
59
+ **工作区模式下:** 如果变更属于某个子项目,cd 到子项目目录执行 git commit。工作区根目录无 git 则跳过。
60
+
59
61
  ### 最后说:
60
62
 
61
63
  > ✅ 变更 `<change-name>` 已归档到 `archive/YYYY-MM-DD-<change-name>/`。继续:`/sillyspec:brainstorm "新想法"`
@@ -53,7 +53,7 @@ $ARGUMENTS
53
53
  cat .sillyspec/config.yaml 2>/dev/null
54
54
  ```
55
55
 
56
- **工作区模式:** AskUserQuestion 选子项目,加载子项目上下文 + 共享规范 + 工作区概览,设计文档保存到子项目 `.sillyspec/changes/`。
56
+ **工作区模式:** AskUserQuestion 选子项目,**cd 到子项目目录执行**,加载子项目上下文 + 共享规范 + 工作区概览,设计文档保存到子项目 `.sillyspec/changes/`。git commit 在子项目目录执行。
57
57
 
58
58
  **单项目模式:**
59
59
  ```bash
@@ -29,7 +29,7 @@ $ARGUMENTS
29
29
  cat .sillyspec/config.yaml 2>/dev/null
30
30
  ```
31
31
 
32
- **工作区模式:** 根据计划 Task 标注确定子项目,额外加载共享规范 + CODEBASE-OVERVIEW.md,执行前 cd 到对应子项目目录。
32
+ **工作区模式:** 根据计划 Task 标注确定子项目,额外加载共享规范 + CODEBASE-OVERVIEW.md,**执行前必须 cd 到对应子项目目录**。所有代码修改、测试运行、git commit 都在子项目目录中执行。一个 Task 属于哪个子项目,就 cd 到哪个子项目。
33
33
 
34
34
  **单项目模式:**
35
35
  ```bash
@@ -84,17 +84,62 @@ grep -rn "public.*getById" --include="*.java" src/main/java/**/service/
84
84
  ```
85
85
  grep 不到 → 不许调用,先查清楚或报告给用户。
86
86
 
87
- ### 2. TDD
87
+ ### 2. TDD(强制执行,不可跳过)
88
88
 
89
+ #### 🔴 RED — 写失败测试
90
+
91
+ 先写测试文件,再写实现代码。写代码前测试必须先存在。
92
+
93
+ **写完测试后,立即运行确认失败:**
94
+
95
+ 先检查 local.yaml 是否有构建命令配置:
96
+ ```bash
97
+ cat .sillyspec/local.yaml 2>/dev/null 2>/dev/null
98
+ ```
99
+
100
+ 如果有,使用 local.yaml 中的命令(含 `-s` 等参数);否则使用默认命令:
101
+
102
+ ```bash
103
+ mvn test -pl <模块> -Dtest=<测试类> 2>/dev/null || ./gradlew test --tests <测试类> 2>/dev/null || npm test -- --testPathPattern=<测试文件> 2>/dev/null || pytest <测试文件> 2>/dev/null
104
+ ```
105
+
106
+ 确认:
107
+ - 测试失败(不是编译错误)
108
+ - 失败原因是功能未实现(不是语法错误)
109
+
110
+ **测试直接通过?** 你在测试已有行为,重写测试。**测试编译报错?** 先修测试语法。
111
+
112
+ #### 🟢 GREEN — 写最少代码
113
+
114
+ 写刚好让测试通过的最少代码。不加额外功能。
115
+
116
+ **写完后立即运行确认通过:**
117
+
118
+ 先检查 local.yaml 是否有构建命令配置:
119
+ ```bash
120
+ cat .sillyspec/local.yaml 2>/dev/null 2>/dev/null
89
121
  ```
90
- 🔴 RED → 写测试,运行确认失败
91
- 🟢 GREEN → 写最少代码让测试通过
92
- 🔵 REFACTOR → 清理,保持测试通过
122
+
123
+ 如果有,使用 local.yaml 中的命令;否则使用默认命令:
124
+
125
+ ```bash
126
+ mvn test -pl <模块> -Dtest=<测试类> 2>/dev/null || ./gradlew test --tests <测试类> 2>/dev/null || npm test -- --testPathPattern=<测试文件> 2>/dev/null || pytest <测试文件> 2>/dev/null
93
127
  ```
94
128
 
95
- TDD 中间步骤(RED→GREEN→REFACTOR)连续执行,不需要每步等用户确认。
129
+ 确认:
130
+ - 测试通过
131
+ - 其他已有测试没有因此失败
132
+ - 无编译错误、无 warnings
133
+
134
+ **编译不通过或测试失败?** 修代码,不是改测试。**其他测试被破坏?** 立即修复。
135
+
136
+ #### 🔵 REFACTOR — 清理
96
137
 
97
- **测试文件必须保留**,随代码一起 commit。违反 TDD → 删代码重来。
138
+ 在测试全绿的前提下清理:提取重复、改善命名、简化逻辑。重构后重新运行测试确认仍然通过。
139
+
140
+ **TDD 中间步骤(RED→GREEN→REFACTOR)连续执行,不需要每步等用户确认。但每一步都必须运行测试命令并确认结果,不可省略。**
141
+
142
+ **测试文件必须保留**,随代码一起 commit。违反 TDD(先写代码后补测试)→ 删代码重来。
98
143
 
99
144
  **可跳过 TDD(不需要确认):** 纯配置(YAML/properties)、纯数据(SQL seed)、纯文档(README/注释)。
100
145
 
@@ -104,8 +149,17 @@ TDD 中间步骤(RED→GREEN→REFACTOR)连续执行,不需要每步等用
104
149
 
105
150
  ### 4. Git commit
106
151
 
152
+ **先确认当前在 git 仓库中:**
153
+ ```bash
154
+ git rev-parse --is-inside-work-tree 2>/dev/null
155
+ ```
156
+
157
+ 如果不在 git 仓库中,提示用户当前目录没有 git 管理,跳过 commit 或让用户指定仓库路径。
158
+
107
159
  `git add -A` → 生成 commit message → **根据用户选择的确认频率决定是否立即确认或批量确认**。
108
160
 
161
+ **工作区模式下,每个子项目的 commit 独立执行,不要跨子项目 commit。**
162
+
109
163
  ---
110
164
 
111
165
  ## 偏差处理
@@ -33,7 +33,7 @@ $ARGUMENTS
33
33
  - 纯配置/数据/文档可跳过 TDD
34
34
  - 其他情况一律走 TDD
35
35
  6. **运行相关测试:** `pnpm test 2>/dev/null || npm test 2>/dev/null || pytest 2>/dev/null`
36
- 7. **Git commit:** 展示 commit message 给用户确认后提交
36
+ 7. **Git commit:** 展示 commit message 给用户确认后提交。**工作区模式下,确认当前在正确的子项目目录中执行 commit。**
37
37
  8. **记录:**
38
38
  - **有 `--change`:** 在 `.sillyspec/changes/<变更名>/tasks.md` 追加 task 并勾选 `[x]`
39
39
  - **无 `--change`:** 记录到 `.sillyspec/quicklog/QUICKLOG.md`(见下方规则)
@@ -55,6 +55,24 @@ AskUserQuestion 依次确认:快速⚡/深度🔍、扫描范围(留空全
55
55
 
56
56
  汇总选择,用户确认后执行。
57
57
 
58
+ ### 🚨 工作区扫描铁律(防止上下文爆炸)
59
+
60
+ **工作区模式下,必须逐个子项目扫描并写入,禁止跨子项目累积上下文:**
61
+
62
+ ```
63
+ 子项目 A → 读取 → 写入文档 → 清理上下文
64
+ 子项目 B → 读取 → 写入文档 → 清理上下文
65
+ ...
66
+ 最后 → 生成 CODEBASE-OVERVIEW.md
67
+ ```
68
+
69
+ - ✅ 每个子项目扫描完成后**立即写入** `.sillyspec/codebase/` 文件
70
+ - ✅ 写入后**不再回头读**该子项目的源码
71
+ - ❌ 禁止同时读取多个子项目的源码再一次性全部写入
72
+ - ❌ 禁止在一个子项目扫描过程中去读另一个子项目的文件
73
+
74
+ **CODEBASE-OVERVIEW.md** 只读各子项目已生成的 ARCHITECTURE.md + CONVENTIONS.md(不读源码),生成汇总。
75
+
58
76
  ---
59
77
 
60
78
  ## 快速扫描
@@ -76,9 +94,73 @@ find . -type f -not -path "*/node_modules/*" -not -path "*/{dist,.git,vendor,bui
76
94
  git log --oneline -20
77
95
  ```
78
96
 
79
- ## 🚨 三项强制扫描(快速和深度都必须执行)
97
+ ## 🚨 四项强制扫描(快速和深度都必须执行)
98
+
99
+ ### A. 构建环境探测(IDE vs 终端差异修复)
100
+
101
+ **目的:** 解决 IDEA 有私服配置但终端跑不了 `mvn test` / `npm test` 的问题。
102
+
103
+ **探测步骤:**
104
+
105
+ ```bash
106
+ # 检测项目使用的构建工具
107
+ ls pom.xml build.gradle package.json requirements.txt go.mod Cargo.toml pyproject.toml 2>/dev/null
108
+ # 检测是否有 wrapper
109
+ ls mvnw gradlew package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null
110
+ # 检测是否有 IDEA 特殊配置
111
+ grep -r "mavenHome\|settings\.xml\|gradleHome\|nodeInterpreter" .idea/workspace.xml 2>/dev/null | head -5
112
+ # 检测是否有本地配置文件
113
+ cat .mvn/maven.config 2>/dev/null
114
+ cat .mvn/jvm.config 2>/dev/null
115
+ cat .npmrc 2>/dev/null
116
+ cat pip.conf .pip/pip.conf ~/.pip/pip.conf 2>/dev/null
117
+ cat ~/.gradle/gradle.properties 2>/dev/null
118
+ ```
119
+
120
+ **AskUserQuestion 询问用户:**
121
+
122
+ > "检测到本项目使用 [Maven/Gradle/npm/pip/Go],终端执行构建命令时是否需要特殊配置?"
123
+ > 选项:
124
+ > - 不需要,默认配置就能跑
125
+ > - 需要指定配置文件(如 Maven 的 settings.xml)→ 让用户输入路径
126
+ > - 需要额外参数(如私服地址、代理等)→ 让用户输入
127
+ > - 不确定,先试试默认命令
128
+
129
+ **如果用户选择了需要配置,测试默认命令是否能跑通:**
130
+
131
+ ```bash
132
+ # Maven
133
+ mvn test -s <用户提供的路径> --fail-at-end 2>&1 | tail -5
134
+ # Gradle
135
+ ./gradlew test 2>&1 | tail -5 || gradle test 2>&1 | tail -5
136
+ # npm
137
+ npm test 2>&1 | tail -5 || pnpm test 2>&1 | tail -5
138
+ # pip
139
+ pip install -e . 2>&1 | tail -5 && pytest --collect-only 2>&1 | tail -5
140
+ # Go
141
+ go test ./... 2>&1 | tail -5
142
+ ```
143
+
144
+ **写入 `.sillyspec/local.yaml`(本地记忆文件,不提交到 git):**
145
+
146
+ 此文件存储每个开发者独立的本地配置。如果文件已存在则追加,已有字段则跳过:
80
147
 
81
- ### A. 数据库 Schema 扫描
148
+ ```yaml
149
+ # .sillyspec/local.yaml — 本地记忆文件(已在 .gitignore 中,不提交)
150
+ # 每个开发者独立配置,clone 后重新 scan 即可生成
151
+
152
+ build:
153
+ tool: maven
154
+ test_cmd: 'mvn test -s "D:/software/maven/conf/settings.xml"'
155
+ compile_cmd: 'mvn compile -s "D:/software/maven/conf/settings.xml"'
156
+ single_test_cmd: 'mvn test -s "D:/software/maven/conf/settings.xml" -pl {module} -Dtest={test_class}'
157
+ ```
158
+
159
+ **铁律:后续 execute / verify 阶段执行构建或测试命令时,必须先读取 `.sillyspec/local.yaml` 中的 build 配置,使用记录的命令执行。如果 local.yaml 不存在或无 build 配置,使用默认命令。**
160
+
161
+ 无构建工具 → 跳过此步骤。
162
+
163
+ ### B. 数据库 Schema 扫描
82
164
 
83
165
  **目的:** 防止后续阶段编造表名和字段名。
84
166
 
@@ -101,7 +183,7 @@ find . \( -name "schema.prisma" -o -name "*.model.ts" -o -name "*.entity.ts" -o
101
183
 
102
184
  无数据库 → 写"本项目无数据库"。**铁律:所有阶段引用的表名必须来自此摘要,或 design.md 中声明的新增表。**
103
185
 
104
- ### B. 框架隐形规则扫描
186
+ ### C. 框架隐形规则扫描
105
187
 
106
188
  **目的:** 防止 AI 生成的 SQL/代码违反框架自动处理机制(如自动注入字段、逻辑删除拦截器)。
107
189
 
@@ -138,7 +220,7 @@ find . \( -name "*.java" -o -name "*.py" -o -name "*.go" -o -name "*.ts" -o -nam
138
220
 
139
221
  无发现 → 写"未发现框架级别的自动处理配置"。**铁律:后续阶段生成 SQL/数据操作代码必须遵守这些规则。**
140
222
 
141
- ### C. 实体继承规范扫描
223
+ ### D. 实体继承规范扫描
142
224
 
143
225
  **目的:** 防止新建表时漏掉基类通用字段,导致 ORM 查询报 Unknown column。
144
226
 
@@ -163,7 +245,7 @@ find . -name "*.java" -not -path "*/{node_modules,.git}/*" | xargs grep -l "@Map
163
245
 
164
246
  无基类 → 写"本项目没有实体基类"。
165
247
 
166
- ### D. 代码风格深度提取
248
+ ### E. 代码风格深度提取
167
249
 
168
250
  读取 2-3 个典型的 Controller、Service、ServiceImpl、Entity 源文件,提取具体风格(从源码提取,禁止编造):
169
251
 
@@ -228,9 +310,16 @@ sillyspec next
228
310
 
229
311
  ### Git 提交
230
312
 
313
+ **单项目模式:**
231
314
  ```bash
232
- git add .sillyspec/
233
- git commit -m "chore: sillyspec scan - codebase mapped"
315
+ git add .sillyspec/ && git commit -m "chore: sillyspec scan - codebase mapped"
316
+ ```
317
+
318
+ **工作区模式:** 在每个子项目目录分别 commit(主工作区无 git 则跳过):
319
+ ```bash
320
+ for proj in $(cat .sillyspec/config.yaml | grep -oP 'path:\s*\K.*'); do
321
+ cd "$proj" && git add .sillyspec/ 2>/dev/null && git commit -m "chore: sillyspec scan - codebase mapped" && cd - > /dev/null
322
+ done
234
323
  ```
235
324
 
236
325
  ### 路径校验 + 自检门控
@@ -1,8 +1,3 @@
1
- ---
2
- description: 查看项目进度和状态
3
- argument-hint: ""
4
- ---
5
-
6
1
  ## 交互规范
7
2
  **当需要用户从多个选项中做出选择时,必须使用 Claude Code 内置的 AskUserQuestion 工具,将选项以参数传入。**
8
3
 
@@ -19,7 +14,37 @@ argument-hint: ""
19
14
  cat .sillyspec/config.yaml 2>/dev/null
20
15
  ```
21
16
 
22
- **工作区模式:** 读取 config.yaml 子项目列表,对每个子项目检查 PROJECT.md、codebase 文档数、进行中变更、归档数。检查共享规范和工作区概览。输出汇总后结束,不执行单项目流程。
17
+ **工作区模式:** 读取 config.yaml 子项目列表,对每个子项目检查 PROJECT.md、codebase 文档数、进行中变更、归档数。**同时检查工作区根目录 `.sillyspec/changes/` 下的未归档变更。** 检查共享规范和工作区概览。输出汇总后结束,不执行单项目流程。
18
+
19
+ 工作区变更检查命令:
20
+ ```bash
21
+ # 工作区根目录的变更
22
+ ls .sillyspec/changes/ 2>/dev/null | grep -v archive
23
+ ls .sillyspec/changes/archive/ 2>/dev/null | wc -l
24
+
25
+ # 每个子项目的变更
26
+ for proj in $(cat .sillyspec/config.yaml | grep -oP 'path:\s*\K.*'); do
27
+ echo "=== $(basename $proj) changes ==="
28
+ ls "$proj/.sillyspec/changes/" 2>/dev/null | grep -v archive
29
+ ls "$proj/.sillyspec/changes/archive/" 2>/dev/null | wc -l
30
+ done
31
+ ```
32
+
33
+ **汇总输出格式:**
34
+ ```
35
+ 📊 SillySpec 状态
36
+ 📋 工作区模式 — N 个子项目
37
+
38
+ 工作区变更:
39
+ 🔄 进行中:sec-bonus-penalty(tasks: 3/5)
40
+ ✅ 已归档:1 个
41
+
42
+ ┌───────────────────┬────────────┬────────────┬────────┬────────┐
43
+ │ 子项目 │ PROJECT.md │ 代码库文档 │ 进行中 │ 已归档 │
44
+ ├───────────────────┼────────────┼────────────┼────────┼────────┤
45
+ │ back-service │ ✗ │ 7 份 │ 1 │ 0 │
46
+ └───────────────────┴────────────┴────────────┴────────┴────────┘
47
+ ```
23
48
 
24
49
  **单项目模式:** 继续 Step 2。
25
50
 
@@ -11,11 +11,27 @@
11
11
  ## 状态检查(必须先执行)
12
12
 
13
13
  ```bash
14
- sillyspec status --json
14
+ cat .sillyspec/STATE.md 2>/dev/null
15
15
  ```
16
16
 
17
- - `phase: "verify"` → ✅ 继续
18
- - 其他 phase → 提示 `sillyspec next`
17
+ 检查当前阶段。如果没有 STATE.md,检查是否有未归档变更:
18
+
19
+ ```bash
20
+ ls .sillyspec/changes/ 2>/dev/null | grep -v archive
21
+ ```
22
+
23
+ 无 STATE.md 且无未归档变更 → 提示用户先完成 execute 或用 `/sillyspec:status` 查看状态。
24
+
25
+ ---
26
+
27
+ ## 工作区模式处理
28
+
29
+ 如果 `.sillyspec/config.yaml` 包含 `projects` 字段:
30
+
31
+ 1. 检查工作区根目录 `.sillyspec/changes/` 下的未归档变更
32
+ 2. 检查每个子项目 `<子项目路径>/.sillyspec/changes/` 下的未归档变更
33
+ 3. 列出所有未归档变更,让用户选择要验证哪个
34
+ 4. 根据 $ARGUMENTS 或用户选择,cd 到对应目录执行验证
19
35
 
20
36
  ---
21
37
 
@@ -24,8 +40,13 @@ sillyspec status --json
24
40
  ### 1. 加载规范
25
41
 
26
42
  ```bash
27
- LATEST=$(ls -d .sillyspec/changes/*/ | grep -v archive | tail -1)
28
- cat "$LATEST"/{design,tasks}.md 2>/dev/null
43
+ # 确定变更目录
44
+ if [ -n "$ARGUMENTS" ]; then
45
+ CHANGE_DIR=".sillyspec/changes/$ARGUMENTS"
46
+ else
47
+ CHANGE_DIR=$(ls -d .sillyspec/changes/*/ 2>/dev/null | grep -v archive | tail -1)
48
+ fi
49
+ cat "$CHANGE_DIR"/{design,tasks}.md 2>/dev/null
29
50
  ```
30
51
 
31
52
  锚定确认实际存在的文件。
@@ -61,14 +82,6 @@ grep -r "TODO\|FIXME\|HACK\|XXX" src/ lib/ app/ --include="*.ts" --include="*.ts
61
82
  ## 结论:✅ PASS / ⚠️ PASS WITH NOTES / ❌ FAIL
62
83
  ```
63
84
 
64
- ```bash
65
- bash scripts/validate-all.sh 2>/dev/null
66
- ```
67
-
68
85
  ### 7. 完成
69
86
 
70
- ```bash
71
- sillyspec status --json && sillyspec next
72
- ```
73
-
74
- 更新 `.sillyspec/STATE.md`:阶段改为 `verify ✅` 或 `verify ⚠️`。
87
+ 更新 `.sillyspec/STATE.md`(如存在):阶段改为 `verify ✅` 或 `verify ⚠️`。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "type": "module",
6
6
  "bin": {
package/src/init.js CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs';
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, copyFileSync } from 'fs';
2
2
  import { join, resolve, dirname } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { homedir } from 'os';
@@ -50,17 +50,45 @@ const ARG_HINTS = {
50
50
  export: '<change-name> [--to <path>]',
51
51
  };
52
52
 
53
- const VALID_TOOLS = ['claude', 'claude_skills', 'cursor', 'codex', 'opencode', 'openclaw'];
53
+ const VALID_TOOLS = ['claude', 'claude_skills', 'cursor', 'openclaw', 'codex', 'gemini', 'opencode'];
54
54
 
55
55
  const TOOL_LABELS = {
56
56
  claude: 'Claude Code',
57
57
  claude_skills: 'Claude Skills',
58
58
  cursor: 'Cursor',
59
- codex: 'Codex CLI',
60
- opencode: 'OpenCode',
61
59
  openclaw: 'OpenClaw',
60
+ codex: 'OpenAI Codex (通过 AGENTS.md)',
61
+ gemini: 'Gemini CLI (通过 GEMINI.md)',
62
+ opencode: 'OpenCode (通过 INSTRUCTIONS.md)',
62
63
  };
63
64
 
65
+ // Slash commands 工具:安装 markdown 模板命令
66
+ const SLASH_COMMAND_TOOLS = ['claude', 'claude_skills', 'cursor', 'openclaw'];
67
+
68
+ // 指令文件工具:注入规范引用到指令文件
69
+ const INSTRUCTION_TOOLS = ['codex', 'gemini', 'opencode'];
70
+
71
+ const INSTRUCTION_FILE_MAP = {
72
+ codex: 'AGENTS.md',
73
+ gemini: 'GEMINI.md',
74
+ opencode: 'INSTRUCTIONS.md',
75
+ };
76
+
77
+ const INJECTION_CONTENT = `## SillySpec — 规范驱动开发
78
+
79
+ 在执行开发任务时,遵循以下规范:
80
+
81
+ ### 代码规范
82
+ - 写代码前先读取 \`.sillyspec/codebase/CONVENTIONS.md\`(代码风格)和 \`.sillyspec/codebase/ARCHITECTURE.md\`(架构)
83
+ - 调用已有方法前,用 grep 确认方法存在,不许编造
84
+ - 遵循 \`.sillyspec/codebase/CONVENTIONS.md\` 中的代码风格
85
+
86
+ ### 工作流程
87
+ - 读取 \`.sillyspec/STATE.md\` 确认当前阶段
88
+ - 各阶段产出文件位于 \`.sillyspec/changes/<变更名>/\` 下
89
+ - 详细流程参考模板文件:\`.sillyspec/.templates/\`(brainstorm.md, plan.md, execute.md 等)
90
+ `;
91
+
64
92
  // ── 适配器 ──
65
93
 
66
94
  function generateClaude(projectDir, name, desc, body, argHint) {
@@ -103,32 +131,6 @@ ${body}`
103
131
  );
104
132
  }
105
133
 
106
- function generateCodex(projectDir, name, desc, body, argHint) {
107
- const outDir = join(homedir(), '.agents', 'skills', `sillyspec-${name}`);
108
- mkdirSync(outDir, { recursive: true });
109
- writeFileSync(join(outDir, 'SKILL.md'),
110
- `---
111
- name: sillyspec:${name}
112
- description: ${desc}
113
- ---
114
-
115
- ${body}`
116
- );
117
- }
118
-
119
- function generateOpencode(projectDir, name, desc, body, argHint) {
120
- const outDir = join(projectDir, '.opencode', 'skills', `sillyspec-${name}`);
121
- mkdirSync(outDir, { recursive: true });
122
- writeFileSync(join(outDir, 'SKILL.md'),
123
- `---
124
- name: sillyspec:${name}
125
- description: ${desc}
126
- ---
127
-
128
- ${body}`
129
- );
130
- }
131
-
132
134
  function generateOpenclaw(projectDir, name, desc, body, argHint) {
133
135
  const outDir = join(projectDir, '.openclaw', 'skills', `sillyspec-${name}`);
134
136
  mkdirSync(outDir, { recursive: true });
@@ -146,11 +148,30 @@ const GENERATORS = {
146
148
  claude: generateClaude,
147
149
  claude_skills: generateClaudeSkills,
148
150
  cursor: generateCursor,
149
- codex: generateCodex,
150
- opencode: generateOpencode,
151
151
  openclaw: generateOpenclaw,
152
152
  };
153
153
 
154
+ // ── 指令文件注入 ──
155
+
156
+ function injectInstructions(tool, projectDir) {
157
+ const fileName = INSTRUCTION_FILE_MAP[tool];
158
+ if (!fileName) return;
159
+ const filePath = join(projectDir, fileName);
160
+
161
+ // 文件不存在则创建
162
+ if (!existsSync(filePath)) {
163
+ writeFileSync(filePath, INJECTION_CONTENT);
164
+ return;
165
+ }
166
+
167
+ // 已存在 SillySpec 标记则跳过
168
+ const content = readFileSync(filePath, 'utf8');
169
+ if (content.includes('## SillySpec')) return;
170
+
171
+ // 追加到末尾
172
+ writeFileSync(filePath, content.trimEnd() + '\n\n' + INJECTION_CONTENT);
173
+ }
174
+
154
175
  // ── 检测工具 ──
155
176
 
156
177
  function detectTools(projectDir) {
@@ -158,9 +179,10 @@ function detectTools(projectDir) {
158
179
  if (existsSync(join(projectDir, '.claude'))) found.push('claude');
159
180
  if (existsSync(join(projectDir, '.claude', 'skills'))) found.push('claude_skills');
160
181
  if (existsSync(join(projectDir, '.cursor'))) found.push('cursor');
161
- if (existsSync(join(projectDir, '.opencode'))) found.push('opencode');
162
182
  if (existsSync(join(projectDir, '.openclaw'))) found.push('openclaw');
163
- if (existsSync(join(homedir(), '.agents', 'skills'))) found.push('codex');
183
+ if (existsSync(join(projectDir, 'AGENTS.md'))) found.push('codex');
184
+ if (existsSync(join(projectDir, 'GEMINI.md'))) found.push('gemini');
185
+ if (existsSync(join(projectDir, 'INSTRUCTIONS.md'))) found.push('opencode');
164
186
  if (found.length === 0) found.push('claude');
165
187
  return found;
166
188
  }
@@ -188,7 +210,7 @@ async function doInstall(projectDir, tools, isWorkspace, subprojects = []) {
188
210
  }
189
211
 
190
212
  const gitignorePath = join(projectDir, '.gitignore');
191
- const ignoreRules = ['.sillyspec/STATE.md', '.sillyspec/codebase/SCAN-RAW.md'];
213
+ const ignoreRules = ['.sillyspec/STATE.md', '.sillyspec/codebase/SCAN-RAW.md', '.sillyspec/local.yaml'];
192
214
  if (existsSync(gitignorePath)) {
193
215
  const content = readFileSync(gitignorePath, 'utf8');
194
216
  let updated = content.trimEnd();
@@ -202,13 +224,38 @@ async function doInstall(projectDir, tools, isWorkspace, subprojects = []) {
202
224
  writeFileSync(gitignorePath, ignoreRules.join('\n') + '\n');
203
225
  }
204
226
 
205
- // 生成文件
227
+ // 生成 slash command 文件
206
228
  const templateFiles = readdirSync(TEMPLATE_DIR).filter(f => f.endsWith('.md'));
207
229
  let count = 0;
208
230
 
209
231
  for (let i = 0; i < tools.length; i++) {
210
232
  const toolName = tools[i];
211
233
  const label = TOOL_LABELS[toolName] || toolName;
234
+
235
+ if (INSTRUCTION_TOOLS.includes(toolName)) {
236
+ const spinner = ora(`安装 ${label}... (${i + 1}/${tools.length})`).start();
237
+ try {
238
+ injectInstructions(toolName, projectDir);
239
+ // 复制模板文件到 .sillyspec/.templates/
240
+ const templatesSourceDir = join(TEMPLATE_DIR);
241
+ const templatesDir = join(projectDir, '.sillyspec', '.templates');
242
+ if (!existsSync(templatesDir)) {
243
+ mkdirSync(templatesDir, { recursive: true });
244
+ for (const file of readdirSync(templatesSourceDir)) {
245
+ if (file.endsWith('.md')) {
246
+ copyFileSync(join(templatesSourceDir, file), join(templatesDir, file));
247
+ }
248
+ }
249
+ }
250
+ spinner.succeed(`${label} 完成`);
251
+ count++;
252
+ } catch (err) {
253
+ spinner.fail(`${label} 失败: ${err.message}`);
254
+ throw err;
255
+ }
256
+ continue;
257
+ }
258
+
212
259
  const spinner = ora(`安装 ${label}... (${i + 1}/${tools.length})`).start();
213
260
  try {
214
261
  const gen = GENERATORS[toolName];
@@ -345,7 +392,7 @@ export async function cmdInit(projectDir, options = {}) {
345
392
  const detected = detectTools(projectDir);
346
393
 
347
394
  const toolChoices = VALID_TOOLS.map(v => ({
348
- name: `${TOOL_LABELS[v]}${v === 'claude' ? ' (slash commands)' : v === 'claude_skills' ? ' (skills 目录)' : ''}`,
395
+ name: `${TOOL_LABELS[v]}${v === 'claude' ? ' (推荐)' : ''}`,
349
396
  value: v,
350
397
  checked: detected.includes(v),
351
398
  }));
@@ -56,6 +56,8 @@ $ARGUMENTS
56
56
  - **STATE.md:** 清除当前变更信息,历史记录追加归档完成
57
57
  - **Git 提交:** `git add .sillyspec/ && git commit -m "docs: archive sillyspec change <change-name>"`
58
58
 
59
+ **工作区模式下:** 如果变更属于某个子项目,cd 到子项目目录执行 git commit。工作区根目录无 git 则跳过。
60
+
59
61
  ### 最后说:
60
62
 
61
63
  > ✅ 变更 `<change-name>` 已归档到 `archive/YYYY-MM-DD-<change-name>/`。继续:`/sillyspec:brainstorm "新想法"`
@@ -53,7 +53,7 @@ $ARGUMENTS
53
53
  cat .sillyspec/config.yaml 2>/dev/null
54
54
  ```
55
55
 
56
- **工作区模式:** AskUserQuestion 选子项目,加载子项目上下文 + 共享规范 + 工作区概览,设计文档保存到子项目 `.sillyspec/changes/`。
56
+ **工作区模式:** AskUserQuestion 选子项目,**cd 到子项目目录执行**,加载子项目上下文 + 共享规范 + 工作区概览,设计文档保存到子项目 `.sillyspec/changes/`。git commit 在子项目目录执行。
57
57
 
58
58
  **单项目模式:**
59
59
  ```bash
@@ -29,7 +29,7 @@ $ARGUMENTS
29
29
  cat .sillyspec/config.yaml 2>/dev/null
30
30
  ```
31
31
 
32
- **工作区模式:** 根据计划 Task 标注确定子项目,额外加载共享规范 + CODEBASE-OVERVIEW.md,执行前 cd 到对应子项目目录。
32
+ **工作区模式:** 根据计划 Task 标注确定子项目,额外加载共享规范 + CODEBASE-OVERVIEW.md,**执行前必须 cd 到对应子项目目录**。所有代码修改、测试运行、git commit 都在子项目目录中执行。一个 Task 属于哪个子项目,就 cd 到哪个子项目。
33
33
 
34
34
  **单项目模式:**
35
35
  ```bash
@@ -84,17 +84,62 @@ grep -rn "public.*getById" --include="*.java" src/main/java/**/service/
84
84
  ```
85
85
  grep 不到 → 不许调用,先查清楚或报告给用户。
86
86
 
87
- ### 2. TDD
87
+ ### 2. TDD(强制执行,不可跳过)
88
88
 
89
+ #### 🔴 RED — 写失败测试
90
+
91
+ 先写测试文件,再写实现代码。写代码前测试必须先存在。
92
+
93
+ **写完测试后,立即运行确认失败:**
94
+
95
+ 先检查 local.yaml 是否有构建命令配置:
96
+ ```bash
97
+ cat .sillyspec/local.yaml 2>/dev/null 2>/dev/null
98
+ ```
99
+
100
+ 如果有,使用 local.yaml 中的命令(含 `-s` 等参数);否则使用默认命令:
101
+
102
+ ```bash
103
+ mvn test -pl <模块> -Dtest=<测试类> 2>/dev/null || ./gradlew test --tests <测试类> 2>/dev/null || npm test -- --testPathPattern=<测试文件> 2>/dev/null || pytest <测试文件> 2>/dev/null
104
+ ```
105
+
106
+ 确认:
107
+ - 测试失败(不是编译错误)
108
+ - 失败原因是功能未实现(不是语法错误)
109
+
110
+ **测试直接通过?** 你在测试已有行为,重写测试。**测试编译报错?** 先修测试语法。
111
+
112
+ #### 🟢 GREEN — 写最少代码
113
+
114
+ 写刚好让测试通过的最少代码。不加额外功能。
115
+
116
+ **写完后立即运行确认通过:**
117
+
118
+ 先检查 local.yaml 是否有构建命令配置:
119
+ ```bash
120
+ cat .sillyspec/local.yaml 2>/dev/null 2>/dev/null
89
121
  ```
90
- 🔴 RED → 写测试,运行确认失败
91
- 🟢 GREEN → 写最少代码让测试通过
92
- 🔵 REFACTOR → 清理,保持测试通过
122
+
123
+ 如果有,使用 local.yaml 中的命令;否则使用默认命令:
124
+
125
+ ```bash
126
+ mvn test -pl <模块> -Dtest=<测试类> 2>/dev/null || ./gradlew test --tests <测试类> 2>/dev/null || npm test -- --testPathPattern=<测试文件> 2>/dev/null || pytest <测试文件> 2>/dev/null
93
127
  ```
94
128
 
95
- TDD 中间步骤(RED→GREEN→REFACTOR)连续执行,不需要每步等用户确认。
129
+ 确认:
130
+ - 测试通过
131
+ - 其他已有测试没有因此失败
132
+ - 无编译错误、无 warnings
133
+
134
+ **编译不通过或测试失败?** 修代码,不是改测试。**其他测试被破坏?** 立即修复。
135
+
136
+ #### 🔵 REFACTOR — 清理
96
137
 
97
- **测试文件必须保留**,随代码一起 commit。违反 TDD → 删代码重来。
138
+ 在测试全绿的前提下清理:提取重复、改善命名、简化逻辑。重构后重新运行测试确认仍然通过。
139
+
140
+ **TDD 中间步骤(RED→GREEN→REFACTOR)连续执行,不需要每步等用户确认。但每一步都必须运行测试命令并确认结果,不可省略。**
141
+
142
+ **测试文件必须保留**,随代码一起 commit。违反 TDD(先写代码后补测试)→ 删代码重来。
98
143
 
99
144
  **可跳过 TDD(不需要确认):** 纯配置(YAML/properties)、纯数据(SQL seed)、纯文档(README/注释)。
100
145
 
@@ -104,8 +149,17 @@ TDD 中间步骤(RED→GREEN→REFACTOR)连续执行,不需要每步等用
104
149
 
105
150
  ### 4. Git commit
106
151
 
152
+ **先确认当前在 git 仓库中:**
153
+ ```bash
154
+ git rev-parse --is-inside-work-tree 2>/dev/null
155
+ ```
156
+
157
+ 如果不在 git 仓库中,提示用户当前目录没有 git 管理,跳过 commit 或让用户指定仓库路径。
158
+
107
159
  `git add -A` → 生成 commit message → **根据用户选择的确认频率决定是否立即确认或批量确认**。
108
160
 
161
+ **工作区模式下,每个子项目的 commit 独立执行,不要跨子项目 commit。**
162
+
109
163
  ---
110
164
 
111
165
  ## 偏差处理
@@ -33,7 +33,7 @@ $ARGUMENTS
33
33
  - 纯配置/数据/文档可跳过 TDD
34
34
  - 其他情况一律走 TDD
35
35
  6. **运行相关测试:** `pnpm test 2>/dev/null || npm test 2>/dev/null || pytest 2>/dev/null`
36
- 7. **Git commit:** 展示 commit message 给用户确认后提交
36
+ 7. **Git commit:** 展示 commit message 给用户确认后提交。**工作区模式下,确认当前在正确的子项目目录中执行 commit。**
37
37
  8. **记录:**
38
38
  - **有 `--change`:** 在 `.sillyspec/changes/<变更名>/tasks.md` 追加 task 并勾选 `[x]`
39
39
  - **无 `--change`:** 记录到 `.sillyspec/quicklog/QUICKLOG.md`(见下方规则)
package/templates/scan.md CHANGED
@@ -55,6 +55,24 @@ AskUserQuestion 依次确认:快速⚡/深度🔍、扫描范围(留空全
55
55
 
56
56
  汇总选择,用户确认后执行。
57
57
 
58
+ ### 🚨 工作区扫描铁律(防止上下文爆炸)
59
+
60
+ **工作区模式下,必须逐个子项目扫描并写入,禁止跨子项目累积上下文:**
61
+
62
+ ```
63
+ 子项目 A → 读取 → 写入文档 → 清理上下文
64
+ 子项目 B → 读取 → 写入文档 → 清理上下文
65
+ ...
66
+ 最后 → 生成 CODEBASE-OVERVIEW.md
67
+ ```
68
+
69
+ - ✅ 每个子项目扫描完成后**立即写入** `.sillyspec/codebase/` 文件
70
+ - ✅ 写入后**不再回头读**该子项目的源码
71
+ - ❌ 禁止同时读取多个子项目的源码再一次性全部写入
72
+ - ❌ 禁止在一个子项目扫描过程中去读另一个子项目的文件
73
+
74
+ **CODEBASE-OVERVIEW.md** 只读各子项目已生成的 ARCHITECTURE.md + CONVENTIONS.md(不读源码),生成汇总。
75
+
58
76
  ---
59
77
 
60
78
  ## 快速扫描
@@ -76,9 +94,73 @@ find . -type f -not -path "*/node_modules/*" -not -path "*/{dist,.git,vendor,bui
76
94
  git log --oneline -20
77
95
  ```
78
96
 
79
- ## 🚨 三项强制扫描(快速和深度都必须执行)
97
+ ## 🚨 四项强制扫描(快速和深度都必须执行)
98
+
99
+ ### A. 构建环境探测(IDE vs 终端差异修复)
100
+
101
+ **目的:** 解决 IDEA 有私服配置但终端跑不了 `mvn test` / `npm test` 的问题。
102
+
103
+ **探测步骤:**
104
+
105
+ ```bash
106
+ # 检测项目使用的构建工具
107
+ ls pom.xml build.gradle package.json requirements.txt go.mod Cargo.toml pyproject.toml 2>/dev/null
108
+ # 检测是否有 wrapper
109
+ ls mvnw gradlew package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null
110
+ # 检测是否有 IDEA 特殊配置
111
+ grep -r "mavenHome\|settings\.xml\|gradleHome\|nodeInterpreter" .idea/workspace.xml 2>/dev/null | head -5
112
+ # 检测是否有本地配置文件
113
+ cat .mvn/maven.config 2>/dev/null
114
+ cat .mvn/jvm.config 2>/dev/null
115
+ cat .npmrc 2>/dev/null
116
+ cat pip.conf .pip/pip.conf ~/.pip/pip.conf 2>/dev/null
117
+ cat ~/.gradle/gradle.properties 2>/dev/null
118
+ ```
119
+
120
+ **AskUserQuestion 询问用户:**
121
+
122
+ > "检测到本项目使用 [Maven/Gradle/npm/pip/Go],终端执行构建命令时是否需要特殊配置?"
123
+ > 选项:
124
+ > - 不需要,默认配置就能跑
125
+ > - 需要指定配置文件(如 Maven 的 settings.xml)→ 让用户输入路径
126
+ > - 需要额外参数(如私服地址、代理等)→ 让用户输入
127
+ > - 不确定,先试试默认命令
128
+
129
+ **如果用户选择了需要配置,测试默认命令是否能跑通:**
130
+
131
+ ```bash
132
+ # Maven
133
+ mvn test -s <用户提供的路径> --fail-at-end 2>&1 | tail -5
134
+ # Gradle
135
+ ./gradlew test 2>&1 | tail -5 || gradle test 2>&1 | tail -5
136
+ # npm
137
+ npm test 2>&1 | tail -5 || pnpm test 2>&1 | tail -5
138
+ # pip
139
+ pip install -e . 2>&1 | tail -5 && pytest --collect-only 2>&1 | tail -5
140
+ # Go
141
+ go test ./... 2>&1 | tail -5
142
+ ```
143
+
144
+ **写入 `.sillyspec/local.yaml`(本地记忆文件,不提交到 git):**
145
+
146
+ 此文件存储每个开发者独立的本地配置。如果文件已存在则追加,已有字段则跳过:
80
147
 
81
- ### A. 数据库 Schema 扫描
148
+ ```yaml
149
+ # .sillyspec/local.yaml — 本地记忆文件(已在 .gitignore 中,不提交)
150
+ # 每个开发者独立配置,clone 后重新 scan 即可生成
151
+
152
+ build:
153
+ tool: maven
154
+ test_cmd: 'mvn test -s "D:/software/maven/conf/settings.xml"'
155
+ compile_cmd: 'mvn compile -s "D:/software/maven/conf/settings.xml"'
156
+ single_test_cmd: 'mvn test -s "D:/software/maven/conf/settings.xml" -pl {module} -Dtest={test_class}'
157
+ ```
158
+
159
+ **铁律:后续 execute / verify 阶段执行构建或测试命令时,必须先读取 `.sillyspec/local.yaml` 中的 build 配置,使用记录的命令执行。如果 local.yaml 不存在或无 build 配置,使用默认命令。**
160
+
161
+ 无构建工具 → 跳过此步骤。
162
+
163
+ ### B. 数据库 Schema 扫描
82
164
 
83
165
  **目的:** 防止后续阶段编造表名和字段名。
84
166
 
@@ -101,7 +183,7 @@ find . \( -name "schema.prisma" -o -name "*.model.ts" -o -name "*.entity.ts" -o
101
183
 
102
184
  无数据库 → 写"本项目无数据库"。**铁律:所有阶段引用的表名必须来自此摘要,或 design.md 中声明的新增表。**
103
185
 
104
- ### B. 框架隐形规则扫描
186
+ ### C. 框架隐形规则扫描
105
187
 
106
188
  **目的:** 防止 AI 生成的 SQL/代码违反框架自动处理机制(如自动注入字段、逻辑删除拦截器)。
107
189
 
@@ -138,7 +220,7 @@ find . \( -name "*.java" -o -name "*.py" -o -name "*.go" -o -name "*.ts" -o -nam
138
220
 
139
221
  无发现 → 写"未发现框架级别的自动处理配置"。**铁律:后续阶段生成 SQL/数据操作代码必须遵守这些规则。**
140
222
 
141
- ### C. 实体继承规范扫描
223
+ ### D. 实体继承规范扫描
142
224
 
143
225
  **目的:** 防止新建表时漏掉基类通用字段,导致 ORM 查询报 Unknown column。
144
226
 
@@ -163,7 +245,7 @@ find . -name "*.java" -not -path "*/{node_modules,.git}/*" | xargs grep -l "@Map
163
245
 
164
246
  无基类 → 写"本项目没有实体基类"。
165
247
 
166
- ### D. 代码风格深度提取
248
+ ### E. 代码风格深度提取
167
249
 
168
250
  读取 2-3 个典型的 Controller、Service、ServiceImpl、Entity 源文件,提取具体风格(从源码提取,禁止编造):
169
251
 
@@ -228,9 +310,16 @@ sillyspec next
228
310
 
229
311
  ### Git 提交
230
312
 
313
+ **单项目模式:**
231
314
  ```bash
232
- git add .sillyspec/
233
- git commit -m "chore: sillyspec scan - codebase mapped"
315
+ git add .sillyspec/ && git commit -m "chore: sillyspec scan - codebase mapped"
316
+ ```
317
+
318
+ **工作区模式:** 在每个子项目目录分别 commit(主工作区无 git 则跳过):
319
+ ```bash
320
+ for proj in $(cat .sillyspec/config.yaml | grep -oP 'path:\s*\K.*'); do
321
+ cd "$proj" && git add .sillyspec/ 2>/dev/null && git commit -m "chore: sillyspec scan - codebase mapped" && cd - > /dev/null
322
+ done
234
323
  ```
235
324
 
236
325
  ### 路径校验 + 自检门控
@@ -14,7 +14,37 @@
14
14
  cat .sillyspec/config.yaml 2>/dev/null
15
15
  ```
16
16
 
17
- **工作区模式:** 读取 config.yaml 子项目列表,对每个子项目检查 PROJECT.md、codebase 文档数、进行中变更、归档数。检查共享规范和工作区概览。输出汇总后结束,不执行单项目流程。
17
+ **工作区模式:** 读取 config.yaml 子项目列表,对每个子项目检查 PROJECT.md、codebase 文档数、进行中变更、归档数。**同时检查工作区根目录 `.sillyspec/changes/` 下的未归档变更。** 检查共享规范和工作区概览。输出汇总后结束,不执行单项目流程。
18
+
19
+ 工作区变更检查命令:
20
+ ```bash
21
+ # 工作区根目录的变更
22
+ ls .sillyspec/changes/ 2>/dev/null | grep -v archive
23
+ ls .sillyspec/changes/archive/ 2>/dev/null | wc -l
24
+
25
+ # 每个子项目的变更
26
+ for proj in $(cat .sillyspec/config.yaml | grep -oP 'path:\s*\K.*'); do
27
+ echo "=== $(basename $proj) changes ==="
28
+ ls "$proj/.sillyspec/changes/" 2>/dev/null | grep -v archive
29
+ ls "$proj/.sillyspec/changes/archive/" 2>/dev/null | wc -l
30
+ done
31
+ ```
32
+
33
+ **汇总输出格式:**
34
+ ```
35
+ 📊 SillySpec 状态
36
+ 📋 工作区模式 — N 个子项目
37
+
38
+ 工作区变更:
39
+ 🔄 进行中:sec-bonus-penalty(tasks: 3/5)
40
+ ✅ 已归档:1 个
41
+
42
+ ┌───────────────────┬────────────┬────────────┬────────┬────────┐
43
+ │ 子项目 │ PROJECT.md │ 代码库文档 │ 进行中 │ 已归档 │
44
+ ├───────────────────┼────────────┼────────────┼────────┼────────┤
45
+ │ back-service │ ✗ │ 7 份 │ 1 │ 0 │
46
+ └───────────────────┴────────────┴────────────┴────────┴────────┘
47
+ ```
18
48
 
19
49
  **单项目模式:** 继续 Step 2。
20
50
 
@@ -11,11 +11,27 @@
11
11
  ## 状态检查(必须先执行)
12
12
 
13
13
  ```bash
14
- sillyspec status --json
14
+ cat .sillyspec/STATE.md 2>/dev/null
15
15
  ```
16
16
 
17
- - `phase: "verify"` → ✅ 继续
18
- - 其他 phase → 提示 `sillyspec next`
17
+ 检查当前阶段。如果没有 STATE.md,检查是否有未归档变更:
18
+
19
+ ```bash
20
+ ls .sillyspec/changes/ 2>/dev/null | grep -v archive
21
+ ```
22
+
23
+ 无 STATE.md 且无未归档变更 → 提示用户先完成 execute 或用 `/sillyspec:status` 查看状态。
24
+
25
+ ---
26
+
27
+ ## 工作区模式处理
28
+
29
+ 如果 `.sillyspec/config.yaml` 包含 `projects` 字段:
30
+
31
+ 1. 检查工作区根目录 `.sillyspec/changes/` 下的未归档变更
32
+ 2. 检查每个子项目 `<子项目路径>/.sillyspec/changes/` 下的未归档变更
33
+ 3. 列出所有未归档变更,让用户选择要验证哪个
34
+ 4. 根据 $ARGUMENTS 或用户选择,cd 到对应目录执行验证
19
35
 
20
36
  ---
21
37
 
@@ -24,8 +40,13 @@ sillyspec status --json
24
40
  ### 1. 加载规范
25
41
 
26
42
  ```bash
27
- LATEST=$(ls -d .sillyspec/changes/*/ | grep -v archive | tail -1)
28
- cat "$LATEST"/{design,tasks}.md 2>/dev/null
43
+ # 确定变更目录
44
+ if [ -n "$ARGUMENTS" ]; then
45
+ CHANGE_DIR=".sillyspec/changes/$ARGUMENTS"
46
+ else
47
+ CHANGE_DIR=$(ls -d .sillyspec/changes/*/ 2>/dev/null | grep -v archive | tail -1)
48
+ fi
49
+ cat "$CHANGE_DIR"/{design,tasks}.md 2>/dev/null
29
50
  ```
30
51
 
31
52
  锚定确认实际存在的文件。
@@ -61,14 +82,6 @@ grep -r "TODO\|FIXME\|HACK\|XXX" src/ lib/ app/ --include="*.ts" --include="*.ts
61
82
  ## 结论:✅ PASS / ⚠️ PASS WITH NOTES / ❌ FAIL
62
83
  ```
63
84
 
64
- ```bash
65
- bash scripts/validate-all.sh 2>/dev/null
66
- ```
67
-
68
85
  ### 7. 完成
69
86
 
70
- ```bash
71
- sillyspec status --json && sillyspec next
72
- ```
73
-
74
- 更新 `.sillyspec/STATE.md`:阶段改为 `verify ✅` 或 `verify ⚠️`。
87
+ 更新 `.sillyspec/STATE.md`(如存在):阶段改为 `verify ✅` 或 `verify ⚠️`。