sillyspec 3.26.10 → 3.26.11
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 +85 -85
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -114
- package/.claude/skills/sillyspec-commit/SKILL.md +109 -109
- package/.claude/skills/sillyspec-continue/SKILL.md +45 -45
- package/.claude/skills/sillyspec-doctor/SKILL.md +76 -76
- package/.claude/skills/sillyspec-execute/SKILL.md +200 -200
- package/.claude/skills/sillyspec-explore/SKILL.md +95 -95
- package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
- package/.claude/skills/sillyspec-plan/SKILL.md +148 -148
- package/.claude/skills/sillyspec-quick/SKILL.md +111 -111
- package/.claude/skills/sillyspec-resume/SKILL.md +68 -68
- package/.claude/skills/sillyspec-scan/SKILL.md +79 -79
- package/.claude/skills/sillyspec-state/SKILL.md +64 -64
- package/.claude/skills/sillyspec-status/SKILL.md +54 -54
- package/.claude/skills/sillyspec-verify/SKILL.md +83 -83
- package/.claude/skills/sillyspec-workspace/SKILL.md +169 -169
- package/.gitattributes +2 -0
- package/.husky/pre-push +20 -20
- package/.npmrc-publish +2 -0
- package/README.md +201 -201
- package/SKILL.md +90 -90
- package/package.json +39 -39
- package/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -7446
- package/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -1
- package/packages/dashboard/dist/index.html +16 -16
- package/packages/dashboard/package.json +25 -25
- package/packages/dashboard/server/executor.js +86 -86
- package/packages/dashboard/server/index.js +601 -601
- package/packages/dashboard/server/parser.js +526 -526
- package/src/change-risk-profile.js +254 -254
- package/src/classify-change.js +109 -109
- package/src/config-schema.js +310 -310
- package/src/contract-matrix.js +379 -379
- package/src/db.js +350 -350
- package/src/dispatch/backends/local-agent.js +155 -155
- package/src/dispatch/backends/sillyhub-mcp.js +245 -245
- package/src/dispatch/probe.js +210 -210
- package/src/dispatch/strategy.js +121 -121
- package/src/docs-check.js +131 -4
- package/src/doctor-diagnostics.js +711 -711
- package/src/endpoint-extractor.js +401 -401
- package/src/fs-atomic.js +69 -69
- package/src/git-helper.js +79 -79
- package/src/hooks/claude-pre-tool-use.cjs +125 -125
- package/src/hooks/worktree-guard.js +848 -848
- package/src/index.js +90 -8
- package/src/init.js +623 -623
- package/src/knowledge-match.js +130 -130
- package/src/local-detect.js +120 -120
- package/src/machine-interface.js +543 -543
- package/src/migrate.js +127 -127
- package/src/progress/change-registry.js +297 -260
- package/src/progress/consistency-doctor.js +355 -355
- package/src/progress/shared.js +36 -36
- package/src/progress/stage-machine.js +29 -1
- package/src/progress/step-store.js +261 -261
- package/src/progress.js +1131 -1127
- package/src/quicklog.js +693 -693
- package/src/review-tier.js +77 -77
- package/src/run/command.js +1385 -1364
- package/src/run/complete-handlers.js +1443 -1399
- package/src/run/complete.js +225 -24
- package/src/run/gates.js +755 -755
- package/src/run/prompt.js +761 -761
- package/src/run/quick-audit.js +155 -146
- package/src/run/shared.js +1268 -1215
- package/src/run/stage.js +487 -479
- package/src/scan-postcheck.js +371 -371
- package/src/setup.js +416 -416
- package/src/sillyhub-mcp/client.js +529 -529
- package/src/spec-sync.js +323 -319
- package/src/stage-contract.js +897 -897
- package/src/stage-review.js +549 -549
- package/src/stages/archive.js +155 -155
- package/src/stages/brainstorm-auto.js +236 -236
- package/src/stages/brainstorm.js +596 -597
- package/src/stages/cmd-existence.js +145 -145
- package/src/stages/doctor.js +371 -371
- package/src/stages/execute.js +1003 -1003
- package/src/stages/explore.js +34 -34
- package/src/stages/index.js +29 -29
- package/src/stages/knowledge.js +498 -498
- package/src/stages/plan-postcheck.js +1302 -1302
- package/src/stages/plan.js +625 -623
- package/src/stages/quick.js +151 -151
- package/src/stages/scan.js +607 -607
- package/src/stages/status.js +64 -64
- package/src/stages/verify.js +264 -264
- package/src/sync.js +1223 -1135
- package/src/task-review.js +1019 -1019
- package/src/verify-postcheck.js +1186 -1186
- package/src/workflow.js +600 -600
- package/src/worktree-apply.js +1213 -1136
- package/src/worktree-deps.js +353 -353
- package/src/worktree.js +1481 -1481
- package/templates/workflows/archive-impact.yaml +79 -79
- package/templates/workflows/scan-docs.yaml +132 -132
package/src/classify-change.js
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* classify-change.js — 变更规模分类器
|
|
3
|
-
*
|
|
4
|
-
* 将用户需求描述分类为 quick / auto / full,
|
|
5
|
-
* 供 auto 模式决定内部流程深度。
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { existsSync, readFileSync } from 'fs'
|
|
9
|
-
import { join } from 'path'
|
|
10
|
-
import jsYaml from 'js-yaml'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* 用户显式指定的关键词 → 强制模式
|
|
14
|
-
*/
|
|
15
|
-
const FORCE_FULL_PATTERNS = [
|
|
16
|
-
/数据库|database|schema/i,
|
|
17
|
-
/迁移|migration|migrate/i,
|
|
18
|
-
/鉴权|权限|auth|permission|rbac/i,
|
|
19
|
-
/支付|payment|billing/i,
|
|
20
|
-
/重构|refactor.*architectur/i,
|
|
21
|
-
/微服务|microserv/i,
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
const FORCE_QUICK_PATTERNS = [
|
|
25
|
-
/fix typo/i,
|
|
26
|
-
/更新文案|改文案|文案修改/i,
|
|
27
|
-
/样式调整|style.*tweak/i,
|
|
28
|
-
/修复.*\s*\bbug\b.*\bfix\b/i,
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* 读 local.yaml 的 auto_mode 段(best-effort,绝不抛)。
|
|
33
|
-
* 供 runCommand 接线:传给 classifyChange 的 localConfig,让 force_*_patterns 真生效。
|
|
34
|
-
* @param {string} cwd - 主仓库根(local.yaml 在 <cwd>/.sillyspec/local.yaml)
|
|
35
|
-
* @returns {{ force_full_patterns?: string[], force_quick_patterns?: string[] } | null}
|
|
36
|
-
* auto_mode 段含至少一个 string pattern → 归一化数组;文件缺/解析失败/无段/空 → null(降级默认关键词)
|
|
37
|
-
*/
|
|
38
|
-
export function readAutoModeFromLocalYaml(cwd) {
|
|
39
|
-
try {
|
|
40
|
-
const p = join(cwd, '.sillyspec', 'local.yaml')
|
|
41
|
-
if (!existsSync(p)) return null
|
|
42
|
-
const doc = jsYaml.load(readFileSync(p, 'utf8'))
|
|
43
|
-
if (!doc || typeof doc !== 'object') return null
|
|
44
|
-
const am = doc.auto_mode
|
|
45
|
-
if (!am || typeof am !== 'object') return null
|
|
46
|
-
const ffp = Array.isArray(am.force_full_patterns) ? am.force_full_patterns.filter(s => typeof s === 'string') : []
|
|
47
|
-
const fqp = Array.isArray(am.force_quick_patterns) ? am.force_quick_patterns.filter(s => typeof s === 'string') : []
|
|
48
|
-
if (ffp.length === 0 && fqp.length === 0) return null
|
|
49
|
-
return { force_full_patterns: ffp, force_quick_patterns: fqp }
|
|
50
|
-
} catch {
|
|
51
|
-
return null
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 分类变更规模
|
|
57
|
-
* @param {object} opts
|
|
58
|
-
* @param {string} opts.description - 用户需求描述
|
|
59
|
-
* @param {string} [opts.explicitMode] - 用户显式指定的模式(auto/quick/full)
|
|
60
|
-
* @param {object} [opts.localConfig] - local.yaml auto_mode 段(由 readAutoModeFromLocalYaml 读出)
|
|
61
|
-
* @returns {{ mode: 'quick'|'auto'|'full', reason: string }}
|
|
62
|
-
*/
|
|
63
|
-
export function classifyChange({ description = '', explicitMode, localConfig } = {}) {
|
|
64
|
-
// 1. 用户显式指定优先级最高
|
|
65
|
-
if (explicitMode && ['quick', 'auto', 'full'].includes(explicitMode)) {
|
|
66
|
-
return { mode: explicitMode, reason: '用户显式指定' }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 2. local.yaml force patterns
|
|
70
|
-
if (localConfig) {
|
|
71
|
-
const forceFullPatterns = localConfig.force_full_patterns || []
|
|
72
|
-
const forceQuickPatterns = localConfig.force_quick_patterns || []
|
|
73
|
-
|
|
74
|
-
for (const pattern of forceFullPatterns) {
|
|
75
|
-
try {
|
|
76
|
-
if (new RegExp(pattern, 'i').test(description)) {
|
|
77
|
-
return { mode: 'full', reason: `local.yaml force_full_pattern 匹配: ${pattern}` }
|
|
78
|
-
}
|
|
79
|
-
} catch {
|
|
80
|
-
// 非法正则跳过,不崩 auto 分类(review-2026-08-09 #30)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
for (const pattern of forceQuickPatterns) {
|
|
84
|
-
try {
|
|
85
|
-
if (new RegExp(pattern, 'i').test(description)) {
|
|
86
|
-
return { mode: 'quick', reason: `local.yaml force_quick_pattern 匹配: ${pattern}` }
|
|
87
|
-
}
|
|
88
|
-
} catch {
|
|
89
|
-
// 非法正则跳过
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// 3. 默认关键词匹配
|
|
95
|
-
for (const pattern of FORCE_QUICK_PATTERNS) {
|
|
96
|
-
if (pattern.test(description)) {
|
|
97
|
-
return { mode: 'quick', reason: `命中 quick 关键词: ${pattern.source}` }
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
for (const pattern of FORCE_FULL_PATTERNS) {
|
|
102
|
-
if (pattern.test(description)) {
|
|
103
|
-
return { mode: 'full', reason: `命中 full 关键词: ${pattern.source}` }
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 4. 默认 auto
|
|
108
|
-
return { mode: 'auto', reason: '默认模式' }
|
|
109
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* classify-change.js — 变更规模分类器
|
|
3
|
+
*
|
|
4
|
+
* 将用户需求描述分类为 quick / auto / full,
|
|
5
|
+
* 供 auto 模式决定内部流程深度。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readFileSync } from 'fs'
|
|
9
|
+
import { join } from 'path'
|
|
10
|
+
import jsYaml from 'js-yaml'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 用户显式指定的关键词 → 强制模式
|
|
14
|
+
*/
|
|
15
|
+
const FORCE_FULL_PATTERNS = [
|
|
16
|
+
/数据库|database|schema/i,
|
|
17
|
+
/迁移|migration|migrate/i,
|
|
18
|
+
/鉴权|权限|auth|permission|rbac/i,
|
|
19
|
+
/支付|payment|billing/i,
|
|
20
|
+
/重构|refactor.*architectur/i,
|
|
21
|
+
/微服务|microserv/i,
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const FORCE_QUICK_PATTERNS = [
|
|
25
|
+
/fix typo/i,
|
|
26
|
+
/更新文案|改文案|文案修改/i,
|
|
27
|
+
/样式调整|style.*tweak/i,
|
|
28
|
+
/修复.*\s*\bbug\b.*\bfix\b/i,
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 读 local.yaml 的 auto_mode 段(best-effort,绝不抛)。
|
|
33
|
+
* 供 runCommand 接线:传给 classifyChange 的 localConfig,让 force_*_patterns 真生效。
|
|
34
|
+
* @param {string} cwd - 主仓库根(local.yaml 在 <cwd>/.sillyspec/local.yaml)
|
|
35
|
+
* @returns {{ force_full_patterns?: string[], force_quick_patterns?: string[] } | null}
|
|
36
|
+
* auto_mode 段含至少一个 string pattern → 归一化数组;文件缺/解析失败/无段/空 → null(降级默认关键词)
|
|
37
|
+
*/
|
|
38
|
+
export function readAutoModeFromLocalYaml(cwd) {
|
|
39
|
+
try {
|
|
40
|
+
const p = join(cwd, '.sillyspec', 'local.yaml')
|
|
41
|
+
if (!existsSync(p)) return null
|
|
42
|
+
const doc = jsYaml.load(readFileSync(p, 'utf8'))
|
|
43
|
+
if (!doc || typeof doc !== 'object') return null
|
|
44
|
+
const am = doc.auto_mode
|
|
45
|
+
if (!am || typeof am !== 'object') return null
|
|
46
|
+
const ffp = Array.isArray(am.force_full_patterns) ? am.force_full_patterns.filter(s => typeof s === 'string') : []
|
|
47
|
+
const fqp = Array.isArray(am.force_quick_patterns) ? am.force_quick_patterns.filter(s => typeof s === 'string') : []
|
|
48
|
+
if (ffp.length === 0 && fqp.length === 0) return null
|
|
49
|
+
return { force_full_patterns: ffp, force_quick_patterns: fqp }
|
|
50
|
+
} catch {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 分类变更规模
|
|
57
|
+
* @param {object} opts
|
|
58
|
+
* @param {string} opts.description - 用户需求描述
|
|
59
|
+
* @param {string} [opts.explicitMode] - 用户显式指定的模式(auto/quick/full)
|
|
60
|
+
* @param {object} [opts.localConfig] - local.yaml auto_mode 段(由 readAutoModeFromLocalYaml 读出)
|
|
61
|
+
* @returns {{ mode: 'quick'|'auto'|'full', reason: string }}
|
|
62
|
+
*/
|
|
63
|
+
export function classifyChange({ description = '', explicitMode, localConfig } = {}) {
|
|
64
|
+
// 1. 用户显式指定优先级最高
|
|
65
|
+
if (explicitMode && ['quick', 'auto', 'full'].includes(explicitMode)) {
|
|
66
|
+
return { mode: explicitMode, reason: '用户显式指定' }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 2. local.yaml force patterns
|
|
70
|
+
if (localConfig) {
|
|
71
|
+
const forceFullPatterns = localConfig.force_full_patterns || []
|
|
72
|
+
const forceQuickPatterns = localConfig.force_quick_patterns || []
|
|
73
|
+
|
|
74
|
+
for (const pattern of forceFullPatterns) {
|
|
75
|
+
try {
|
|
76
|
+
if (new RegExp(pattern, 'i').test(description)) {
|
|
77
|
+
return { mode: 'full', reason: `local.yaml force_full_pattern 匹配: ${pattern}` }
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
// 非法正则跳过,不崩 auto 分类(review-2026-08-09 #30)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const pattern of forceQuickPatterns) {
|
|
84
|
+
try {
|
|
85
|
+
if (new RegExp(pattern, 'i').test(description)) {
|
|
86
|
+
return { mode: 'quick', reason: `local.yaml force_quick_pattern 匹配: ${pattern}` }
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
// 非法正则跳过
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 3. 默认关键词匹配
|
|
95
|
+
for (const pattern of FORCE_QUICK_PATTERNS) {
|
|
96
|
+
if (pattern.test(description)) {
|
|
97
|
+
return { mode: 'quick', reason: `命中 quick 关键词: ${pattern.source}` }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (const pattern of FORCE_FULL_PATTERNS) {
|
|
102
|
+
if (pattern.test(description)) {
|
|
103
|
+
return { mode: 'full', reason: `命中 full 关键词: ${pattern.source}` }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 4. 默认 auto
|
|
108
|
+
return { mode: 'auto', reason: '默认模式' }
|
|
109
|
+
}
|