sillyspec 2.4.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 (59) hide show
  1. package/.claude/commands/sillyspec/archive.md +63 -0
  2. package/.claude/commands/sillyspec/brainstorm.md +463 -0
  3. package/.claude/commands/sillyspec/continue.md +44 -0
  4. package/.claude/commands/sillyspec/execute.md +255 -0
  5. package/.claude/commands/sillyspec/explore.md +88 -0
  6. package/.claude/commands/sillyspec/export.md +53 -0
  7. package/.claude/commands/sillyspec/init.md +166 -0
  8. package/.claude/commands/sillyspec/plan.md +238 -0
  9. package/.claude/commands/sillyspec/propose.md +234 -0
  10. package/.claude/commands/sillyspec/quick.md +62 -0
  11. package/.claude/commands/sillyspec/resume.md +100 -0
  12. package/.claude/commands/sillyspec/scan.md +672 -0
  13. package/.claude/commands/sillyspec/status.md +122 -0
  14. package/.claude/commands/sillyspec/verify.md +141 -0
  15. package/.claude/commands/sillyspec/workspace.md +122 -0
  16. package/README.md +158 -0
  17. package/SKILL.md +46 -0
  18. package/adapters/adapters.sh +172 -0
  19. package/bin/sillyspec.js +2 -0
  20. package/commands/sillyspec/archive.md +62 -0
  21. package/commands/sillyspec/brainstorm.md +462 -0
  22. package/commands/sillyspec/continue.md +41 -0
  23. package/commands/sillyspec/execute.md +254 -0
  24. package/commands/sillyspec/explore.md +85 -0
  25. package/commands/sillyspec/export.md +51 -0
  26. package/commands/sillyspec/init.md +163 -0
  27. package/commands/sillyspec/plan.md +237 -0
  28. package/commands/sillyspec/propose.md +233 -0
  29. package/commands/sillyspec/quick.md +59 -0
  30. package/commands/sillyspec/resume.md +99 -0
  31. package/commands/sillyspec/scan.md +671 -0
  32. package/commands/sillyspec/status.md +119 -0
  33. package/commands/sillyspec/verify.md +140 -0
  34. package/commands/sillyspec/workspace.md +120 -0
  35. package/package.json +14 -0
  36. package/scripts/init.sh +2 -0
  37. package/scripts/install.ps1 +316 -0
  38. package/scripts/scan-preprocess.sh +378 -0
  39. package/scripts/validate-all.sh +50 -0
  40. package/scripts/validate-plan.sh +44 -0
  41. package/scripts/validate-proposal.sh +87 -0
  42. package/scripts/validate-scan.sh +90 -0
  43. package/src/index.js +560 -0
  44. package/src/init.js +269 -0
  45. package/templates/archive.md +58 -0
  46. package/templates/brainstorm.md +458 -0
  47. package/templates/continue.md +39 -0
  48. package/templates/execute.md +250 -0
  49. package/templates/explore.md +83 -0
  50. package/templates/export.md +48 -0
  51. package/templates/init.md +161 -0
  52. package/templates/plan.md +233 -0
  53. package/templates/propose.md +229 -0
  54. package/templates/quick.md +57 -0
  55. package/templates/resume.md +95 -0
  56. package/templates/scan.md +667 -0
  57. package/templates/status.md +117 -0
  58. package/templates/verify.md +136 -0
  59. package/templates/workspace.md +117 -0
@@ -0,0 +1,378 @@
1
+ #!/bin/bash
2
+ # SillySpec 扫描预处理脚本
3
+ # 用途:在 AI 介入前完成机械性工作,节省 token + 防止上下文爆炸
4
+ # 输出:.sillyspec/codebase/SCAN-RAW.md
5
+ #
6
+ # 用法:
7
+ # bash scripts/scan-preprocess.sh [目录]
8
+ # bash scripts/scan-preprocess.sh api # 只扫 api 目录
9
+
10
+ set -euo pipefail
11
+
12
+ TARGET_DIR="${1:-.}"
13
+ OUTPUT_DIR=".sillyspec/codebase"
14
+ OUTPUT_FILE="$OUTPUT_DIR/SCAN-RAW.md"
15
+
16
+ # ── 排除目录 ──
17
+
18
+ EXCLUDE_DIRS=(
19
+ "node_modules" "dist" ".git" "vendor" "build"
20
+ "__pycache__" ".next" "coverage" ".nuxt" "target"
21
+ ".idea" ".vscode" ".DS_Store" "bin" "obj"
22
+ "tmp" "temp" "logs" ".cache" "out"
23
+ )
24
+
25
+ build_exclude_args() {
26
+ local args=()
27
+ for d in "${EXCLUDE_DIRS[@]}"; do
28
+ args+=(-not -path "*/$d/*" -not -path "*/$d")
29
+ done
30
+ echo "${args[@]}"
31
+ }
32
+
33
+ EXCLUDE_ARGS=$(build_exclude_args)
34
+
35
+ # ── 统计源文件 ──
36
+
37
+ echo "🔍 SillySpec 扫描预处理"
38
+ echo " 目标目录: $TARGET_DIR"
39
+ echo ""
40
+
41
+ # 文件类型分类
42
+ count_files() {
43
+ local ext="$1" label="$2"
44
+ local cmd="find \"$TARGET_DIR\" -type f -name \"*.$ext\" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' '"
45
+ local n=$(eval "$cmd")
46
+ if [ "$n" -gt 0 ]; then
47
+ echo " $label: $n 个文件"
48
+ fi
49
+ }
50
+
51
+ echo "📊 文件统计:"
52
+ FILE_COUNT=0
53
+ TOTAL_SIZE=0
54
+
55
+ # 按语言统计
56
+ JAVA_COUNT=$(find "$TARGET_DIR" -type f -name "*.java" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
57
+ PY_COUNT=$(find "$TARGET_DIR" -type f -name "*.py" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
58
+ TS_COUNT=$(find "$TARGET_DIR" -type f \( -name "*.ts" -o -name "*.tsx" \) $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
59
+ JS_COUNT=$(find "$TARGET_DIR" -type f \( -name "*.js" -o -name "*.jsx" \) $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
60
+ GO_COUNT=$(find "$TARGET_DIR" -type f -name "*.go" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
61
+ RB_COUNT=$(find "$TARGET_DIR" -type f -name "*.rb" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
62
+ PHP_COUNT=$(find "$TARGET_DIR" -type f -name "*.php" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
63
+ RS_COUNT=$(find "$TARGET_DIR" -type f -name "*.rs" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
64
+ VUE_COUNT=$(find "$TARGET_DIR" -type f -name "*.vue" $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
65
+ SQL_COUNT=$(find "$TARGET_DIR" -type f \( -name "*.sql" -o -name "*.prisma" \) $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
66
+ YAML_COUNT=$(find "$TARGET_DIR" -type f \( -name "*.yaml" -o -name "*.yml" \) $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
67
+ XML_COUNT=$(find "$TARGET_DIR" -type f \( -name "*.xml" \) $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
68
+
69
+ # 配置文件
70
+ CONFIG_COUNT=$(find "$TARGET_DIR" -maxdepth 3 -type f \( -name "package.json" -o -name "pom.xml" -o -name "build.gradle" -o -name "go.mod" -o -name "requirements.txt" -o -name "Cargo.toml" -o -name "composer.json" -o -name "Gemfile" -o -name "*.csproj" \) $EXCLUDE_ARGS 2>/dev/null | wc -l | tr -d ' ')
71
+
72
+ [ "$JAVA_COUNT" -gt 0 ] && echo " Java: $JAVA_COUNT"
73
+ [ "$PY_COUNT" -gt 0 ] && echo " Python: $PY_COUNT"
74
+ [ "$TS_COUNT" -gt 0 ] && echo " TypeScript: $TS_COUNT"
75
+ [ "$JS_COUNT" -gt 0 ] && echo " JavaScript: $JS_COUNT"
76
+ [ "$GO_COUNT" -gt 0 ] && echo " Go: $GO_COUNT"
77
+ [ "$RB_COUNT" -gt 0 ] && echo " Ruby: $RB_COUNT"
78
+ [ "$PHP_COUNT" -gt 0 ] && echo " PHP: $PHP_COUNT"
79
+ [ "$RS_COUNT" -gt 0 ] && echo " Rust: $RS_COUNT"
80
+ [ "$VUE_COUNT" -gt 0 ] && echo " Vue: $VUE_COUNT"
81
+ [ "$SQL_COUNT" -gt 0 ] && echo " SQL/Schema: $SQL_COUNT"
82
+ [ "$XML_COUNT" -gt 0 ] && echo " XML: $XML_COUNT"
83
+ [ "$YAML_COUNT" -gt 0 ] && echo " YAML: $YAML_COUNT"
84
+ [ "$CONFIG_COUNT" -gt 0 ] && echo " 配置文件: $CONFIG_COUNT"
85
+
86
+ # 总计
87
+ ALL_SOURCE=$(find "$TARGET_DIR" -type f \( -name "*.java" -o -name "*.py" -o -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" -o -name "*.go" -o -name "*.rb" -o -name "*.php" -o -name "*.rs" -o -name "*.vue" \) $EXCLUDE_ARGS 2>/dev/null)
88
+ FILE_COUNT=$(echo "$ALL_SOURCE" | wc -l | tr -d ' ')
89
+ [ -z "$FILE_COUNT" ] && FILE_COUNT=0
90
+ TOTAL_SIZE=$(echo "$ALL_SOURCE" | xargs cat 2>/dev/null | wc -c | tr -d ' ')
91
+ [ -z "$TOTAL_SIZE" ] && TOTAL_SIZE=0
92
+
93
+ TOTAL_SIZE_KB=$((TOTAL_SIZE / 1024))
94
+
95
+ echo ""
96
+ echo " ────────────────"
97
+ echo " 源文件总计: $FILE_COUNT 个"
98
+ echo " 源码总大小: ${TOTAL_SIZE_KB}KB"
99
+
100
+ # 时间估算
101
+ if [ "$FILE_COUNT" -lt 50 ]; then
102
+ EST_TIME="约 30 秒"
103
+ RISK="低"
104
+ elif [ "$FILE_COUNT" -lt 150 ]; then
105
+ EST_TIME="约 1-2 分钟"
106
+ RISK="低"
107
+ elif [ "$FILE_COUNT" -lt 300 ]; then
108
+ EST_TIME="约 3-5 分钟"
109
+ RISK="中"
110
+ elif [ "$FILE_COUNT" -lt 500 ]; then
111
+ EST_TIME="约 5-8 分钟"
112
+ RISK="中"
113
+ else
114
+ EST_TIME="约 8-15 分钟"
115
+ RISK="⚠️ 高(建议指定扫描区域)"
116
+ fi
117
+
118
+ echo " 预计耗时: $EST_TIME"
119
+ echo " 上下文风险: $RISK"
120
+
121
+ # ── 目录分布 ──
122
+
123
+ echo ""
124
+ echo "📁 目录分布(源文件最多的目录):"
125
+ find "$TARGET_DIR" -type f \( -name "*.java" -o -name "*.py" -o -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" -o -name "*.go" -o -name "*.vue" \) $EXCLUDE_ARGS 2>/dev/null \
126
+ | sed 's|/[^/]*$||' \
127
+ | sort | uniq -c | sort -rn | head -10 \
128
+ | while read count dir; do
129
+ echo " $count 个文件 $dir"
130
+ done
131
+
132
+ # ── 提取结构化信息 ──
133
+
134
+ mkdir -p "$OUTPUT_DIR"
135
+
136
+ echo ""
137
+ echo "🔧 提取结构化信息..."
138
+
139
+ {
140
+ echo "# SCAN-RAW.md — 扫描预处理结果"
141
+ echo ""
142
+ echo "> 由 scripts/scan-preprocess.sh 自动生成,AI 深度扫描时读取此文件。"
143
+ echo "> 生成时间: $(date '+%Y-%m-%d %H:%M:%S')"
144
+ echo ""
145
+ echo "## 项目概况"
146
+ echo "- 扫描目录: $TARGET_DIR"
147
+ echo "- 源文件数: $FILE_COUNT"
148
+ echo "- 源码大小: ${TOTAL_SIZE_KB}KB"
149
+ echo "- 预计耗时: $EST_TIME"
150
+ echo ""
151
+
152
+ # ── 配置文件内容 ──
153
+ echo "## 配置文件"
154
+ echo ""
155
+
156
+ for f in $(find "$TARGET_DIR" -maxdepth 3 -type f \( -name "package.json" -o -name "pom.xml" -o -name "build.gradle" -o -name "build.gradle.kts" -o -name "settings.gradle" -o -name "go.mod" -o -name "requirements.txt" -o -name "pyproject.toml" -o -name "Cargo.toml" -o -name "composer.json" -o -name "Gemfile" -o -name "*.csproj" -o -name "application.yml" -o -name "application.yaml" -o -name "application.properties" \) $EXCLUDE_ARGS 2>/dev/null | head -20); do
157
+ echo "### $f"
158
+ echo '```'
159
+ cat "$f" 2>/dev/null | head -50
160
+ echo '```'
161
+ echo ""
162
+ done
163
+
164
+ # ── 目录结构树 ──
165
+ echo "## 目录结构"
166
+ echo ""
167
+ echo '```'
168
+ find "$TARGET_DIR" -type f -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/vendor/*" -not -path "*/build/*" -not -path "*/__pycache__/*" -not -path "*/.next/*" -not -path "*/target/*" -not -path "*/.idea/*" -not -path "*/.vscode/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/tmp/*" | head -300 | sed "s|$TARGET_DIR/||" | sort
169
+ echo '```'
170
+ echo ""
171
+
172
+ # ── import/依赖关系 ──
173
+ echo "## 依赖关系(import 分析)"
174
+ echo ""
175
+
176
+ # Java imports
177
+ if [ "$JAVA_COUNT" -gt 0 ]; then
178
+ echo "### Java imports(出现频率 Top 30)"
179
+ echo '```'
180
+ find "$TARGET_DIR" -name "*.java" $EXCLUDE_ARGS 2>/dev/null | xargs grep -h "^import " 2>/dev/null | sed 's/import static //' | sort | uniq -c | sort -rn | head -30
181
+ echo '```'
182
+ echo ""
183
+ fi
184
+
185
+ # Python imports
186
+ if [ "$PY_COUNT" -gt 0 ]; then
187
+ echo "### Python imports(出现频率 Top 30)"
188
+ echo '```'
189
+ find "$TARGET_DIR" -name "*.py" $EXCLUDE_ARGS 2>/dev/null | xargs grep -h "^import \|^from " 2>/dev/null | sort | uniq -c | sort -rn | head -30
190
+ echo '```'
191
+ echo ""
192
+ fi
193
+
194
+ # TypeScript/JavaScript imports
195
+ if [ "$TS_COUNT" -gt 0 ] || [ "$JS_COUNT" -gt 0 ]; then
196
+ echo "### JS/TS imports(出现频率 Top 30)"
197
+ echo '```'
198
+ find "$TARGET_DIR" \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" -o -name "*.vue" \) $EXCLUDE_ARGS 2>/dev/null | xargs grep -hE "^\s*(import |require\(|from ['\"])" 2>/dev/null | sed "s/.*from ['\"]//;s/.*require(['\"]//;s/['\").*//" | grep -v "^\." | grep -v "^@" | sort | uniq -c | sort -rn | head -30
199
+ echo '```'
200
+ echo ""
201
+ fi
202
+
203
+ # Go imports
204
+ if [ "$GO_COUNT" -gt 0 ]; then
205
+ echo "### Go imports(出现频率 Top 30)"
206
+ echo '```'
207
+ find "$TARGET_DIR" -name "*.go" $EXCLUDE_ARGS 2>/dev/null | xargs grep -hE '^\s*"[a-zA-Z]' 2>/dev/null | sort | uniq -c | sort -rn | head -30
208
+ echo '```'
209
+ echo ""
210
+ fi
211
+
212
+ # ── 类名/函数名提取 ──
213
+ echo "## 代码结构(类名/函数名)"
214
+ echo ""
215
+
216
+ # Java classes
217
+ if [ "$JAVA_COUNT" -gt 0 ]; then
218
+ echo "### Java 类和接口"
219
+ echo '```'
220
+ find "$TARGET_DIR" -name "*.java" $EXCLUDE_ARGS 2>/dev/null | xargs grep -hE "^\s*(public|protected|private|)?" | grep -E "(class |interface |enum |@Entity|@Table|@Controller|@Service|@Repository|@RestController|@Mapper|@Component)" | head -50
221
+ echo '```'
222
+ echo ""
223
+ fi
224
+
225
+ # Python classes/functions
226
+ if [ "$PY_COUNT" -gt 0 ]; then
227
+ echo "### Python 类和函数(Top 50)"
228
+ echo '```'
229
+ find "$TARGET_DIR" -name "*.py" $EXCLUDE_ARGS 2>/dev/null | xargs grep -hE "^(class |def |async def )" 2>/dev/null | head -50
230
+ echo '```'
231
+ echo ""
232
+ fi
233
+
234
+ # Go structs
235
+ if [ "$GO_COUNT" -gt 0 ]; then
236
+ echo "### Go 结构体和接口"
237
+ echo '```'
238
+ find "$TARGET_DIR" -name "*.go" -not -path "*/vendor/*" 2>/dev/null | xargs grep -hE "^(type .+ struct|type .+ interface)" 2>/dev/null | head -30
239
+ echo '```'
240
+ echo ""
241
+ fi
242
+
243
+ # ── 数据库 Schema 文件位置 ──
244
+ echo "## 数据库 Schema 文件"
245
+ echo ""
246
+
247
+ SCHEMA_FILES=""
248
+ # Prisma
249
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "schema.prisma" $EXCLUDE_ARGS 2>/dev/null) "
250
+ # MyBatis Mapper XML
251
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "*Mapper.xml" $EXCLUDE_ARGS 2>/dev/null) "
252
+ # SQLAlchemy / Django models
253
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "models.py" $EXCLUDE_ARGS 2>/dev/null) "
254
+ # TypeORM entities
255
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "*.entity.ts" $EXCLUDE_ARGS 2>/dev/null) "
256
+ # Mongoose models
257
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "*.model.ts" $EXCLUDE_ARGS 2>/dev/null) "
258
+ # SQL migrations
259
+ SCHEMA_FILES+="$(find "$TARGET_DIR" \( -name "*.sql" -o -name "*migration*" \) $EXCLUDE_ARGS 2>/dev/null) "
260
+ # Java entities
261
+ SCHEMA_FILES+="$(find "$TARGET_DIR" \( -path "*/entity/*" -o -path "*/model/*" \) -name "*.java" $EXCLUDE_ARGS 2>/dev/null) "
262
+ # Drizzle schema
263
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "schema.ts" $EXCLUDE_ARGS 2>/dev/null) "
264
+ # Go GORM models
265
+ SCHEMA_FILES+="$(find "$TARGET_DIR" -name "models.go" -o -name "model.go" $EXCLUDE_ARGS 2>/dev/null) "
266
+
267
+ if [ -n "$SCHEMA_FILES" ]; then
268
+ echo "$SCHEMA_FILES" | tr ' ' '\n' | grep -v "^$" | while read -r f; do
269
+ if [ -n "$f" ] && [ -f "$f" ]; then
270
+ echo "- \`$f\`"
271
+ fi
272
+ done
273
+ echo ""
274
+ else
275
+ echo "未检测到数据库 schema 文件。"
276
+ echo ""
277
+ fi
278
+
279
+ # ── 框架检测 ──
280
+ echo "## 框架检测"
281
+ echo ""
282
+
283
+ # 检测 Web 框架
284
+ if find "$TARGET_DIR" -name "*.java" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "@RestController\|@Controller\|@RequestMapping\|@GetMapping\|@PostMapping" 2>/dev/null | head -1 | grep -q .; then
285
+ echo "- **Java Web**: Spring Boot (Spring MVC annotations detected)"
286
+ fi
287
+ if find "$TARGET_DIR" -name "*.java" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "mybatis\|MyBatis\|@Mapper\|@Select" 2>/dev/null | head -1 | grep -q .; then
288
+ echo "- **ORM**: MyBatis / MyBatis-Plus"
289
+ fi
290
+ if find "$TARGET_DIR" -name "*.java" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "@Entity\|@Table\|@Column\|JPA\|javax.persistence\|jakarta.persistence" 2>/dev/null | head -1 | grep -q .; then
291
+ echo "- **ORM**: JPA / Hibernate"
292
+ fi
293
+ if find "$TARGET_DIR" -name "pom.xml" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "mybatis-plus\|mybatis\|MybatisPlus" 2>/dev/null | head -1 | grep -q .; then
294
+ echo "- **增强**: MyBatis-Plus"
295
+ fi
296
+
297
+ if find "$TARGET_DIR" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "flask\|Flask" 2>/dev/null | head -1 | grep -q .; then
298
+ echo "- **Python Web**: Flask"
299
+ fi
300
+ if find "$TARGET_DIR" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "django\|Django" 2>/dev/null | head -1 | grep -q .; then
301
+ echo "- **Python Web**: Django"
302
+ fi
303
+ if find "$TARGET_DIR" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "fastapi\|FastAPI" 2>/dev/null | head -1 | grep -q .; then
304
+ echo "- **Python Web**: FastAPI"
305
+ fi
306
+ if find "$TARGET_DIR" -name "*.py" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "sqlalchemy\|SQLAlchemy" 2>/dev/null | head -1 | grep -q .; then
307
+ echo "- **ORM**: SQLAlchemy"
308
+ fi
309
+
310
+ if [ -f "$TARGET_DIR/package.json" ]; then
311
+ if grep -q "vue" "$TARGET_DIR/package.json" 2>/dev/null; then
312
+ echo "- **Frontend**: Vue.js"
313
+ fi
314
+ if grep -q "react\|next" "$TARGET_DIR/package.json" 2>/dev/null; then
315
+ echo "- **Frontend**: React / Next.js"
316
+ fi
317
+ if grep -q "express" "$TARGET_DIR/package.json" 2>/dev/null; then
318
+ echo "- **Backend**: Express.js"
319
+ fi
320
+ if grep -q "nestjs\|NestJS" "$TARGET_DIR/package.json" 2>/dev/null; then
321
+ echo "- **Backend**: NestJS"
322
+ fi
323
+ if grep -q "prisma" "$TARGET_DIR/package.json" 2>/dev/null; then
324
+ echo "- **ORM**: Prisma"
325
+ fi
326
+ if grep -q "typeorm\|TypeORM" "$TARGET_DIR/package.json" 2>/dev/null; then
327
+ echo "- **ORM**: TypeORM"
328
+ fi
329
+ fi
330
+
331
+ if [ "$GO_COUNT" -gt 0 ] && find "$TARGET_DIR" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "gorm.io\|GORM\|gorm.Model" 2>/dev/null | head -1 | grep -q .; then
332
+ echo "- **ORM**: GORM"
333
+ fi
334
+ if [ "$GO_COUNT" -gt 0 ] && find "$TARGET_DIR" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "gin\|Gin\|gin.Context" 2>/dev/null | head -1 | grep -q .; then
335
+ echo "- **Web**: Gin"
336
+ fi
337
+ if [ "$GO_COUNT" -gt 0 ] && find "$TARGET_DIR" $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "echo\|Echo\|labstack/echo" 2>/dev/null | head -1 | grep -q .; then
338
+ echo "- **Web**: Echo"
339
+ fi
340
+
341
+ echo ""
342
+
343
+ # ── 框架隐形规则相关文件 ──
344
+ echo "## 框架配置文件(隐形规则扫描参考)"
345
+ echo ""
346
+
347
+ FRAMEWORK_FILES=""
348
+ FRAMEWORK_FILES+="$(find "$TARGET_DIR" \( -name "*Interceptor*.java" -o -name "*Plugin*.java" -o -name "mybatis-config.xml" \) $EXCLUDE_ARGS 2>/dev/null) "
349
+ FRAMEWORK_FILES+="$(find "$TARGET_DIR" \( -name "*Auditor*.java" -o -name "*EventListener*.java" \) $EXCLUDE_ARGS 2>/dev/null) "
350
+ FRAMEWORK_FILES+="$(find "$TARGET_DIR" -name "settings.py" -maxdepth 3 $EXCLUDE_ARGS 2>/dev/null) "
351
+ FRAMEWORK_FILES+="$(find "$TARGET_DIR" \( -name "*event*.py" -o -name "*listener*.py" -o -name "*mixin*.py" \) $EXCLUDE_ARGS 2>/dev/null) "
352
+ FRAMEWORK_FILES+="$(find "$TARGET_DIR" \( -name "Base*.java" -o -name "Abstract*.java" \) \( -path "*/entity/*" -o -path "*/model/*" -o -path "*/po/*" \) $EXCLUDE_ARGS 2>/dev/null) "
353
+ FRAMEWORK_FILES+="$(find "$TARGET_DIR" \( -name "*.rb" \) $EXCLUDE_ARGS 2>/dev/null | xargs grep -l "acts_as_paranoid\|acts_as_tenant" 2>/dev/null) "
354
+
355
+ if [ -n "$FRAMEWORK_FILES" ]; then
356
+ echo "$FRAMEWORK_FILES" | tr ' ' '\n' | grep -v "^$" | while read -r f; do
357
+ if [ -n "$f" ] && [ -f "$f" ]; then
358
+ echo "- \`$f\`"
359
+ fi
360
+ done
361
+ echo ""
362
+ else
363
+ echo "未检测到框架配置文件。"
364
+ echo ""
365
+ fi
366
+
367
+ echo "---"
368
+ echo "预处理完成。AI 深度扫描时读取此文件,不需要再遍历原始源码。"
369
+
370
+ } > "$OUTPUT_FILE"
371
+
372
+ echo ""
373
+ echo "✅ 预处理完成"
374
+ echo " 输出文件: $OUTPUT_FILE"
375
+ echo " 文件大小: $(wc -c < "$OUTPUT_FILE" | tr -d ' ') bytes"
376
+ echo ""
377
+ echo " 下一步: /sillyspec:scan --deep"
378
+ echo " AI 会读取 SCAN-RAW.md 而不是原始源码,大幅节省上下文。"
@@ -0,0 +1,50 @@
1
+ #!/bin/bash
2
+ # SillySpec 综合校验
3
+ # 用法:validate-all.sh
4
+
5
+ echo "========================================="
6
+ echo " SillySpec 综合校验"
7
+ echo "========================================="
8
+
9
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
10
+ ERRORS=0
11
+
12
+ # 1. 检查 SillySpec 安装
13
+ echo ""
14
+ echo "📦 检查安装状态..."
15
+ if [ -d ".claude/commands/sillyspec" ]; then
16
+ cmd_count=$(ls .claude/commands/sillyspec/*.md 2>/dev/null | wc -l | tr -d ' ')
17
+ echo " ✅ 已安装 $cmd_count 个 commands"
18
+ else
19
+ echo " ❌ 未安装 SillySpec commands"
20
+ ((ERRORS++))
21
+ fi
22
+
23
+ # 2. 检查当前变更
24
+ echo ""
25
+ echo "📋 检查变更..."
26
+ LATEST=$(ls -d .sillyspec/changes/*/ 2>/dev/null | grep -v archive | tail -1)
27
+ if [ -n "$LATEST" ]; then
28
+ echo " 📁 当前变更: $LATEST"
29
+ "$SCRIPT_DIR/validate-proposal.sh" "$LATEST" || ((ERRORS++))
30
+ else
31
+ echo " ℹ️ 无活跃变更"
32
+ fi
33
+
34
+ # 3. 检查代码库文档
35
+ echo ""
36
+ echo "🗂️ 检查代码库文档..."
37
+ if [ -d ".sillyspec/codebase" ]; then
38
+ "$SCRIPT_DIR/validate-scan.sh" ".sillyspec/codebase" || ((ERRORS++))
39
+ else
40
+ echo " ℹ️ 无代码库文档(新项目或未 scan)"
41
+ fi
42
+
43
+ echo ""
44
+ echo "========================================="
45
+ if [ $ERRORS -eq 0 ]; then
46
+ echo " ✅ 全部通过"
47
+ else
48
+ echo " ❌ $ERRORS 个问题需要处理"
49
+ fi
50
+ echo "========================================="
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # SillySpec 校验:plan 阶段输出
3
+ # 用法:validate-plan.sh <change-dir>
4
+
5
+ CHANGE_DIR="${1:?用法: validate-plan.sh <change-dir>}"
6
+ ERRORS=0
7
+
8
+ echo "🔍 校验计划 $CHANGE_DIR/tasks.md ..."
9
+
10
+ if [ ! -f "$CHANGE_DIR/tasks.md" ]; then
11
+ echo "❌ tasks.md 不存在"
12
+ exit 1
13
+ fi
14
+
15
+ # 检查每个 task 是否有文件路径
16
+ task_no_path=0
17
+ while IFS= read -r line; do
18
+ task_name=$(echo "$line" | sed 's/.*Task [0-9]*: //')
19
+ # 简单检查:task 行之后 5 行内是否有路径相关关键词
20
+ echo " 📋 $line"
21
+ done < <(grep '^\- \[ \] Task' "$CHANGE_DIR/tasks.md")
22
+
23
+ # 检查是否有验证命令
24
+ if grep -q "验证" "$CHANGE_DIR/tasks.md"; then
25
+ echo " ✅ 包含验证步骤"
26
+ else
27
+ echo " ⚠️ 建议添加验证步骤"
28
+ fi
29
+
30
+ # 检查是否有 Wave 分组
31
+ if grep -qi "wave\|并行\|依赖" "$CHANGE_DIR/tasks.md"; then
32
+ echo " ✅ 包含执行顺序标注"
33
+ else
34
+ echo " ⚠️ 建议添加 Wave 分组"
35
+ fi
36
+
37
+ # 检查文件变更清单一致性
38
+ if [ -f "$CHANGE_DIR/design.md" ]; then
39
+ design_files=$(grep -c '|' "$CHANGE_DIR/design.md" 2>/dev/null)
40
+ echo " ✅ design.md 有 $design_files 行表格"
41
+ fi
42
+
43
+ echo ""
44
+ echo "✅ 计划校验完成"
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+ # SillySpec 校验:propose 阶段输出
3
+ # 用法:validate-proposal.sh <change-dir>
4
+ # 示例:validate-proposal.sh .sillyspec/changes/docsite-redesign
5
+
6
+ CHANGE_DIR="${1:?用法: validate-proposal.sh <change-dir>}"
7
+ ERRORS=0
8
+
9
+ check_section() {
10
+ local file="$1" section="$2"
11
+ if [ -f "$file" ]; then
12
+ if grep -q "## $section" "$file"; then
13
+ echo " ✅ $file: 包含 '$section'"
14
+ else
15
+ echo " ❌ $file: 缺少 '$section'"
16
+ ((ERRORS++))
17
+ fi
18
+ else
19
+ echo " ❌ 文件不存在: $file"
20
+ ((ERRORS++))
21
+ fi
22
+ }
23
+
24
+ check_file_exists() {
25
+ if [ -f "$1" ]; then
26
+ echo " ✅ $1 存在"
27
+ else
28
+ echo " ❌ $1 不存在"
29
+ ((ERRORS++))
30
+ fi
31
+ }
32
+
33
+ echo "🔍 校验 $CHANGE_DIR ..."
34
+
35
+ # proposal.md
36
+ echo ""
37
+ echo "--- proposal.md ---"
38
+ check_section "$CHANGE_DIR/proposal.md" "动机"
39
+ check_section "$CHANGE_DIR/proposal.md" "变更范围"
40
+ check_section "$CHANGE_DIR/proposal.md" "不在范围内"
41
+ check_section "$CHANGE_DIR/proposal.md" "成功标准"
42
+
43
+ # design.md
44
+ echo ""
45
+ echo "--- design.md ---"
46
+ check_file_exists "$CHANGE_DIR/design.md"
47
+ check_section "$CHANGE_DIR/design.md" "文件变更清单"
48
+ if [ -f "$CHANGE_DIR/design.md" ]; then
49
+ if grep -q "|" "$CHANGE_DIR/design.md"; then
50
+ echo " ✅ design.md: 包含变更表格"
51
+ else
52
+ echo " ❌ design.md: 缺少变更表格"
53
+ ((ERRORS++))
54
+ fi
55
+ fi
56
+
57
+ # tasks.md
58
+ echo ""
59
+ echo "--- tasks.md ---"
60
+ check_file_exists "$CHANGE_DIR/tasks.md"
61
+ if [ -f "$CHANGE_DIR/tasks.md" ]; then
62
+ task_count=$(grep -c '^\- \[ \] Task' "$CHANGE_DIR/tasks.md" 2>/dev/null)
63
+ echo " ✅ tasks.md: $task_count 个 task"
64
+ if [ "$task_count" -eq 0 ]; then
65
+ echo " ❌ tasks.md: 没有 task"
66
+ ((ERRORS++))
67
+ fi
68
+ fi
69
+
70
+ # requirements.md
71
+ echo ""
72
+ echo "--- requirements.md ---"
73
+ if [ -f "$CHANGE_DIR/specs/requirements.md" ]; then
74
+ check_section "$CHANGE_DIR/specs/requirements.md" "功能需求"
75
+ check_section "$CHANGE_DIR/specs/requirements.md" "用户场景"
76
+ else
77
+ check_file_exists "$CHANGE_DIR/specs/requirements.md"
78
+ fi
79
+
80
+ echo ""
81
+ if [ $ERRORS -eq 0 ]; then
82
+ echo "✅ 校验通过,无错误"
83
+ exit 0
84
+ else
85
+ echo "❌ 校验失败,$ERRORS 个错误"
86
+ exit 1
87
+ fi
@@ -0,0 +1,90 @@
1
+ #!/bin/bash
2
+ # SillySpec 校验:scan 阶段输出
3
+ # 用法:validate-scan.sh [codebase-dir]
4
+ # 默认检查 .sillyspec/codebase/
5
+
6
+ CODEBASE_DIR="${1:-.sillyspec/codebase}"
7
+ ERRORS=0
8
+
9
+ # ── 路径误放检查 ──
10
+
11
+ MISPLACED=0
12
+ TARGET_DOCS="ARCHITECTURE.md STACK.md STRUCTURE.md CONVENTIONS.md INTEGRATIONS.md TESTING.md CONCERNS.md PROJECT.md SCAN-RAW.md"
13
+
14
+ for name in $TARGET_DOCS; do
15
+ for f in $(find . -maxdepth 2 -name "$name" 2>/dev/null | grep -v "^\.\/$CODEBASE_DIR/"); do
16
+ if [ -f "$f" ]; then
17
+ echo " ❌ 误放: $f(应在 $CODEBASE_DIR/ 下)"
18
+ ((MISPLACED++))
19
+ ((ERRORS++))
20
+ fi
21
+ done
22
+ done
23
+
24
+ if [ $MISPLACED -gt 0 ]; then
25
+ echo " 💡 运行 /sillyspec:scan 修正路径,或手动移动到 $CODEBASE_DIR/"
26
+ fi
27
+
28
+ # ── 文件完整性检查 ──
29
+
30
+ echo "🔍 校验代码库扫描 $CODEBASE_DIR ..."
31
+
32
+ if [ ! -d "$CODEBASE_DIR" ]; then
33
+ echo " ❌ 目录 $CODEBASE_DIR 不存在"
34
+ exit 1
35
+ fi
36
+
37
+ # 深度扫描 7 份
38
+ DEEP_FILES=(
39
+ "STACK.md"
40
+ "ARCHITECTURE.md"
41
+ "STRUCTURE.md"
42
+ "CONVENTIONS.md"
43
+ "INTEGRATIONS.md"
44
+ "TESTING.md"
45
+ "CONCERNS.md"
46
+ )
47
+
48
+ # 快速扫描 2 份 + PROJECT.md
49
+ QUICK_FILES=(
50
+ "STACK.md"
51
+ "STRUCTURE.md"
52
+ )
53
+
54
+ # 检查深度扫描文件
55
+ for f in "${DEEP_FILES[@]}"; do
56
+ if [ -f "$CODEBASE_DIR/$f" ]; then
57
+ lines=$(wc -l < "$CODEBASE_DIR/$f" | tr -d ' ')
58
+ if [ "$lines" -gt 3 ]; then
59
+ echo " ✅ $f ($lines 行)"
60
+ else
61
+ echo " ⚠️ $f 只有 $lines 行,内容可能不完整"
62
+ ((ERRORS++))
63
+ fi
64
+ else
65
+ echo " ⬜ $f 不存在(深度扫描文件)"
66
+ fi
67
+ done
68
+
69
+ # 检查 PROJECT.md
70
+ if [ -f ".sillyspec/PROJECT.md" ]; then
71
+ echo " ✅ PROJECT.md 存在"
72
+ else
73
+ echo " ⚠️ PROJECT.md 不存在(建议生成)"
74
+ fi
75
+
76
+ # 检查 SCAN-RAW.md
77
+ if [ -f "$CODEBASE_DIR/SCAN-RAW.md" ]; then
78
+ echo " ✅ SCAN-RAW.md 存在(预处理数据)"
79
+ fi
80
+
81
+ # ── 结果 ──
82
+
83
+ echo ""
84
+ if [ $ERRORS -eq 0 ]; then
85
+ echo "✅ 扫描校验通过"
86
+ exit 0
87
+ else
88
+ echo "❌ 扫描校验失败,$ERRORS 个问题"
89
+ exit 1
90
+ fi