sillyspec 3.26.10 → 3.26.13
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 +115 -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/README.md +203 -201
- package/SKILL.md +91 -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 +95 -86
- package/packages/dashboard/server/index.js +663 -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 +313 -310
- package/src/contract-matrix.js +388 -379
- package/src/db.js +370 -350
- package/src/dispatch/backends/local-agent.js +155 -155
- package/src/dispatch/backends/sillyhub-mcp.js +245 -245
- package/src/dispatch/probe.js +246 -210
- package/src/dispatch/strategy.js +121 -121
- package/src/docs-check.js +188 -16
- package/src/docs-debt.js +6 -2
- package/src/docs-gate.js +1 -0
- package/src/doctor-diagnostics.js +898 -711
- package/src/endpoint-extractor.js +401 -401
- package/src/fs-atomic.js +71 -69
- package/src/git-helper.js +82 -79
- package/src/hooks/claude-pre-tool-use.cjs +125 -125
- package/src/hooks/worktree-guard.js +854 -848
- package/src/index.js +251 -20
- package/src/init.js +624 -623
- package/src/knowledge-match.js +130 -130
- package/src/local-detect.js +128 -120
- package/src/machine-interface.js +543 -543
- package/src/migrate.js +127 -127
- package/src/modules.js +7 -5
- 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 +589 -550
- package/src/progress/step-store.js +261 -261
- package/src/progress.js +1285 -1127
- package/src/quicklog.js +724 -693
- package/src/review-tier.js +77 -77
- package/src/run/command.js +1408 -1364
- package/src/run/complete-handlers.js +1450 -1399
- package/src/run/complete.js +1181 -920
- package/src/run/gates.js +878 -755
- package/src/run/prompt.js +765 -761
- package/src/run/quick-audit.js +155 -146
- package/src/run/shared.js +1348 -1215
- package/src/run/stage.js +527 -479
- package/src/scan-postcheck.js +371 -371
- package/src/setup.js +414 -416
- package/src/sillyhub-mcp/client.js +597 -529
- package/src/spec-dir-typo.js +3 -24
- package/src/spec-sync.js +358 -319
- package/src/stage-contract.js +871 -897
- package/src/stage-review.js +549 -549
- package/src/stages/archive.js +156 -155
- package/src/stages/brainstorm-auto.js +236 -236
- package/src/stages/brainstorm.js +597 -597
- package/src/stages/cmd-existence.js +145 -145
- package/src/stages/doctor.js +386 -371
- package/src/stages/execute.js +1014 -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 +1323 -1302
- package/src/stages/plan.js +642 -623
- package/src/stages/quick.js +153 -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 +1325 -1135
- package/src/task-review.js +1204 -1019
- package/src/taskcard.js +178 -0
- package/src/verify-postcheck.js +1199 -1186
- package/src/workflow.js +600 -600
- package/src/worktree-apply.js +1237 -1136
- package/src/worktree-deps.js +453 -353
- package/src/worktree.js +1527 -1481
- package/templates/workflows/archive-impact.yaml +79 -79
- package/templates/workflows/scan-docs.yaml +132 -132
package/src/config-schema.js
CHANGED
|
@@ -1,310 +1,313 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* config-schema.js — local.yaml 配置键的单一数据源。
|
|
3
|
-
*
|
|
4
|
-
* 定位:`.sillyspec/local.yaml` 是 gitignored 的机器+人混写配置,键散落在 ~10 个 reader
|
|
5
|
-
* 里(detect / verify-postcheck / sync / dispatch / worktree-guard / classify-change …),
|
|
6
|
-
* 外部项目的 agent 无从得知有哪些键、哪些生效。本模块把「全部已知键 + 生效状态 + 读取点」
|
|
7
|
-
* 集中成一张表,供:
|
|
8
|
-
* - `sillyspec config schema`(人类可读树 / --json 机读)打印;
|
|
9
|
-
* - `sillyspec init` 调 renderExample() 落盘脱敏 local.yaml.example 给人/外部 agent 看。
|
|
10
|
-
*
|
|
11
|
-
* 单一真相 = LOCAL_YAML_SCHEMA。renderExample() 是策展模板(YAML 形态各异:嵌套 / inline
|
|
12
|
-
* flow / 顶层标量,自动生成不如策展可读),由测试「每个 live 键路径必出现于 example 文本」
|
|
13
|
-
* 耦合保证不漂移——加键忘 example 则测试红。
|
|
14
|
-
*
|
|
15
|
-
* reader 引用一律用符号名(readMcpConfig / extractModules),**不用行号**——行号随重构漂移,
|
|
16
|
-
* 符号名稳定可 grep。
|
|
17
|
-
*
|
|
18
|
-
* status 语义:
|
|
19
|
-
* - live 真有 reader 从 local.yaml 读并起效(配了即生效)。
|
|
20
|
-
* - declared 代码/JSDoc/prompt 声明过,但无 reader 真读 local.yaml(或调用方未传),配了不生效。
|
|
21
|
-
* 诚实标出,避免 agent 白配 + 暴露待接线债。
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @typedef {Object} SchemaKey
|
|
26
|
-
* @property {string} path 点分路径(mcp.url / worktree-hook.readonlyCommands)
|
|
27
|
-
* @property {string} type string|enum|integer|object|array|scalar
|
|
28
|
-
* @property {string[]} [values] enum 取值
|
|
29
|
-
* @property {boolean} [required] 凭据类必填(两键齐全才视为有效源)
|
|
30
|
-
* @property {boolean} [secret] 敏感凭据,example 用占位符
|
|
31
|
-
* @property {boolean} [optional] 可选键
|
|
32
|
-
* @property {string} status live|declared
|
|
33
|
-
* @property {string[]} readers 读取点符号名(稳定可 grep),declared 键留空数组
|
|
34
|
-
* @property {string} desc 一句话说明
|
|
35
|
-
* @property {string} example 脱敏示例值(secret 键用占位符)
|
|
36
|
-
*
|
|
37
|
-
* @typedef {Object} SchemaSection
|
|
38
|
-
* @property {string} id
|
|
39
|
-
* @property {string} title
|
|
40
|
-
* @property {string} note 段说明(写入来源 / 注意事项)
|
|
41
|
-
* @property {SchemaKey[]} keys
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/** @type {{ file: string, note: string, sections: SchemaSection[] }} */
|
|
45
|
-
export const LOCAL_YAML_SCHEMA = {
|
|
46
|
-
file: '.sillyspec/local.yaml',
|
|
47
|
-
note: 'gitignored(含敏感凭据勿提交);脱敏示例 local.yaml.example 由 sillyspec init 生成(可提交)。',
|
|
48
|
-
sections: [
|
|
49
|
-
{
|
|
50
|
-
id: 'project',
|
|
51
|
-
title: '项目类型',
|
|
52
|
-
note: '由 sillyspec local detect 纯 fs 嗅探写入,一般无需手填。',
|
|
53
|
-
keys: [
|
|
54
|
-
{
|
|
55
|
-
path: 'project.type',
|
|
56
|
-
type: 'enum',
|
|
57
|
-
values: ['nodejs', 'maven', 'gradle', 'make', 'generic'],
|
|
58
|
-
status: 'live',
|
|
59
|
-
readers: ['detectLocalYaml (src/local-detect.js)', 'extractProjectType (src/worktree-deps.js)'],
|
|
60
|
-
desc: '项目类型,决定默认 commands 嗅探与 worktree 依赖策略。',
|
|
61
|
-
example: 'nodejs',
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: 'commands',
|
|
67
|
-
title: '构建/测试/lint 命令',
|
|
68
|
-
note: 'detect 核验 package.json(或对应构建文件) scripts 存在性后才写对应键;缺失则不写。agent 可改。',
|
|
69
|
-
keys: [
|
|
70
|
-
{ path: 'commands.build', type: 'string', optional: true, status: 'live', readers: ['detectLocalYaml (src/local-detect.js)', 'validateCommands (src/scan-postcheck.js)'], desc: '构建命令。', example: 'npm run build' },
|
|
71
|
-
{ path: 'commands.test', type: 'string', optional: true, status: 'live', readers: ['extractTestCommand (src/verify-postcheck.js)', 'validateCommands (src/scan-postcheck.js)'], desc: '测试命令——verify 阶段 CLI 亲自执行此命令与 verify-result.md 对账,实测失败即阻断。', example: 'npm test' },
|
|
72
|
-
{ path: 'commands.lint', type: 'string', optional: true, status: 'live', readers: ['detectLocalYaml (src/local-detect.js)', 'validateCommands (src/scan-postcheck.js)'], desc: 'lint 命令。', example: 'npm run lint' },
|
|
73
|
-
{ path: 'commands.install', type: 'string', optional: true, status: 'live', readers: ['extractInstallCommand (src/worktree-deps.js)'], desc: '依赖安装命令(worktree 依赖 provisioning 用)。', example: 'npm install' },
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: 'mcp',
|
|
78
|
-
title: 'SillyHub MCP 客户端凭据(派发用)',
|
|
79
|
-
note: 'agent 手填,或 sillyspec platform connect 在 mcp 段缺失时同源自动填(§7.4)。两键齐全才生效,否则回退 env SILLYHUB_MCP_URL/TOKEN。',
|
|
80
|
-
keys: [
|
|
81
|
-
{ path: 'mcp.url', type: 'string', required: true, secret: true, status: 'live', readers: ['readMcpConfig (src/sillyhub-mcp/config.js)'], desc: 'SillyHub MCP 服务地址(尾斜杠自动归一)。', example: 'https://your-sillyhub.example.com' },
|
|
82
|
-
{ path: 'mcp.token', type: 'string', required: true, secret: true, status: 'live', readers: ['readMcpConfig (src/sillyhub-mcp/config.js)'], desc: 'SillyHub MCP 认证 token。', example: '<your-mcp-token>' },
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: 'platform',
|
|
87
|
-
title: 'SillyHub 平台同步',
|
|
88
|
-
note: 'sillyspec platform connect 写入(含 ping 验活);手填亦可。user/last_connected 可空或自动写。',
|
|
89
|
-
keys: [
|
|
90
|
-
{ path: 'platform.url', type: 'string', required: true, secret: true, status: 'live', readers: ['SyncManager._getPlatform (src/sync.js)'], desc: 'SillyHub 平台地址。', example: 'https://your-sillyhub.example.com' },
|
|
91
|
-
{ path: 'platform.token', type: 'string', required: true, secret: true, status: 'live', readers: ['SyncManager._getPlatform (src/sync.js)'], desc: '平台认证 token(Bearer)。', example: '<your-platform-token>' },
|
|
92
|
-
{ path: 'platform.user', type: 'string', optional: true, status: 'live', readers: ['resolvePlatformUser / SyncManager.connect (src/sync.js)'], desc: '推送者身份;缺则回退 git user.name / env。推送时进 X-SillySpec-User header。', example: 'alice' },
|
|
93
|
-
{ path: 'platform.last_connected', type: 'string', optional: true, status: 'live', readers: ['SyncManager.connect (src/sync.js)'], desc: 'connect 成功时间戳(ISO),自动写,勿手填。', example: '2026-08-11T00:00:00.000Z' },
|
|
94
|
-
],
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
id: 'dispatch',
|
|
98
|
-
title: '派发调参',
|
|
99
|
-
note: '仅在确知调优值时填,否则留默认。',
|
|
100
|
-
keys: [
|
|
101
|
-
{ path: 'dispatch.probe_ttl_ms', type: 'integer', optional: true, status: 'live', readers: ['readProbeTtlFromLocalYaml (src/dispatch/probe.js)'], desc: '派发探测负面缓存 TTL(毫秒,默认 60000)。daemon 抖动期避免反复探测。', example: '60000' },
|
|
102
|
-
{ path: 'dispatch.poll_interval_ms', type: 'integer', optional: true, status: 'declared', readers: [], desc: '【路径A 预留·未落地】renderSillyHubInstruction 注入的轮询文本提及,但 isPathASupported()=false 该指令当前不注入;路径A 落地后接线,配了暂不生效。', example: '15000' },
|
|
103
|
-
{ path: 'dispatch.worker_timeout_ms', type: 'integer', optional: true, status: 'declared', readers: [], desc: '【路径A 预留·未落地】同 poll_interval_ms,路径A 落地后接线,配了暂不生效。', example: '60000' },
|
|
104
|
-
],
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: 'modules',
|
|
108
|
-
title: 'monorepo 子模块映射',
|
|
109
|
-
note: 'test_strategy: module 时,按 git diff 命中的模块子集收窄测试。只支持 inline flow 形态(extractModules 不解析嵌套展开式)。',
|
|
110
|
-
keys: [
|
|
111
|
-
{ path: 'modules.<name>.path', type: 'string', optional: true, status: 'live', readers: ['extractModules (src/verify-postcheck.js)', 'parseLocalYamlModules (src/plan-postcheck.js)', 'extractModulePaths (src/worktree-deps.js)'], desc: '子模块目录路径(相对仓库根)。', example: 'frontend/' },
|
|
112
|
-
{ path: 'modules.<name>.test', type: 'string', optional: true, status: 'live', readers: ['extractModules (src/verify-postcheck.js)'], desc: '该子模块的测试命令。', example: 'cd frontend && pnpm test' },
|
|
113
|
-
],
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
id: 'test_strategy',
|
|
117
|
-
title: '测试策略',
|
|
118
|
-
note: 'verify 阶段 CLI 对账的收窄策略。',
|
|
119
|
-
keys: [
|
|
120
|
-
{ path: 'test_strategy', type: 'enum', values: ['full', 'module'], optional: true, status: 'live', readers: ['extractTestStrategy (src/verify-postcheck.js)'], desc: 'full=全量 commands.test;module=按 git diff 命中 modules 子集收窄(需配 modules)。缺省=全量。', example: 'full' },
|
|
121
|
-
],
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
id: 'known_failures',
|
|
125
|
-
title: '预存失败豁免清单',
|
|
126
|
-
note: '变更前就失败的测试行,豁免后不计入 verify 阻断。支持块列表或 inline 数组。务必定期复核,避免误豁免本变更引入的真实失败。',
|
|
127
|
-
keys: [
|
|
128
|
-
{ path: 'known_failures', type: 'array', optional: true, status: 'live', readers: ['extractKnownFailures (src/verify-postcheck.js)'], desc: '失败行模式列表(匹配测试输出失败行)。', example: 'tests/some-old-test' },
|
|
129
|
-
],
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
id: 'worktree-hook',
|
|
133
|
-
title: 'worktree-guard 扩展',
|
|
134
|
-
note: 'execute worktree 隔离期内放行的额外只读命令。键名用 camelCase(parseSimpleYaml 原样保留)。',
|
|
135
|
-
keys: [
|
|
136
|
-
{ path: 'worktree-hook.readonlyCommands', type: 'array', optional: true, status: 'live', readers: ['loadLocalConfig (src/hooks/worktree-guard.js)'], desc: '额外放行的只读命令名列表(如 rg/fd),绕过 worktree-guard 写操作拦截。', example: 'rg' },
|
|
137
|
-
],
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
id: 'auto_mode',
|
|
141
|
-
title: '变更规模自动分类',
|
|
142
|
-
note: 'sillyspec run auto 时,readAutoModeFromLocalYaml 读本段传 classifyChange 的 localConfig,force_*_patterns 匹配需求描述则强制对应模式。',
|
|
143
|
-
keys: [
|
|
144
|
-
{ path: 'auto_mode.force_full_patterns', type: 'array', optional: true, status: 'live', readers: ['readAutoModeFromLocalYaml + classifyChange (src/classify-change.js)', 'runCommand (src/run/command.js)'], desc: '需求描述匹配任一正则(i 大小写无关)→ 强制 full 流程。非法正则跳过不崩。', example: '数据库|migration' },
|
|
145
|
-
{ path: 'auto_mode.force_quick_patterns', type: 'array', optional: true, status: 'live', readers: ['readAutoModeFromLocalYaml + classifyChange (src/classify-change.js)', 'runCommand (src/run/command.js)'], desc: '需求描述匹配任一正则 → 强制 quick。非法正则跳过不崩。', example: 'fix typo' },
|
|
146
|
-
],
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
id: 'docs-check',
|
|
150
|
-
title: '文档引用校验',
|
|
151
|
-
note: 'sillyspec docs check 的扫描与断言配置(2026-08-15 docs-check-productize)。glob 相对源码仓根展开,仅支持 目录/**/*.扩展、目录/*.扩展、字面路径 三形态。',
|
|
152
|
-
keys: [
|
|
153
|
-
{ path: 'docs-check.paths', type: 'array', optional: true, status: 'live', readers: ['docs check (src/index.js case docs) + runDocsCheck (src/docs-check.js)'], desc: '扫描的文档 glob 列表,缺省 docs/**/*.md 与 .sillyspec/docs/**/*.md(scan/modules 产物同纳入)。', example: 'docs/**/*.md' },
|
|
154
|
-
{ path: 'docs-check.skip', type: 'array', optional: true, status: 'live', readers: ['walkGlob (src/docs-check.js)'], desc: '排除的路径/glob 列表,缺省空。', example: 'docs/sillyspec/archive' },
|
|
155
|
-
{ path: 'docs-check.keywordAssert', type: 'boolean', optional: true, status: 'live', readers: ['runDocsCheck (src/docs-check.js)'], desc: '层2 关键词断言开关,缺省 true(关闭时 warning 提示仅做存在性校验)。', example: 'true' },
|
|
156
|
-
{ path: 'docs-check.living-docs', type: 'array', optional: true, status: 'live', readers: ['resolveLivingDocs (src/run/shared.js) — 经 readLocalYamlRaw 直读'], desc: '活文档监控点追加列表(docs check 之外,quick 审计的 livingDocDrift
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
L
|
|
171
|
-
L.push(
|
|
172
|
-
L.push(
|
|
173
|
-
L.push('');
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
L.push(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
L.push(`
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
L.push(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
L.push(`
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (k.
|
|
212
|
-
if (k.
|
|
213
|
-
if (k.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
#
|
|
254
|
-
#
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
platform
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
#
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
#
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
#
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
worktree-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
#
|
|
300
|
-
docs
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
-
|
|
304
|
-
|
|
305
|
-
#
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
#
|
|
309
|
-
|
|
310
|
-
|
|
1
|
+
/**
|
|
2
|
+
* config-schema.js — local.yaml 配置键的单一数据源。
|
|
3
|
+
*
|
|
4
|
+
* 定位:`.sillyspec/local.yaml` 是 gitignored 的机器+人混写配置,键散落在 ~10 个 reader
|
|
5
|
+
* 里(detect / verify-postcheck / sync / dispatch / worktree-guard / classify-change …),
|
|
6
|
+
* 外部项目的 agent 无从得知有哪些键、哪些生效。本模块把「全部已知键 + 生效状态 + 读取点」
|
|
7
|
+
* 集中成一张表,供:
|
|
8
|
+
* - `sillyspec config schema`(人类可读树 / --json 机读)打印;
|
|
9
|
+
* - `sillyspec init` 调 renderExample() 落盘脱敏 local.yaml.example 给人/外部 agent 看。
|
|
10
|
+
*
|
|
11
|
+
* 单一真相 = LOCAL_YAML_SCHEMA。renderExample() 是策展模板(YAML 形态各异:嵌套 / inline
|
|
12
|
+
* flow / 顶层标量,自动生成不如策展可读),由测试「每个 live 键路径必出现于 example 文本」
|
|
13
|
+
* 耦合保证不漂移——加键忘 example 则测试红。
|
|
14
|
+
*
|
|
15
|
+
* reader 引用一律用符号名(readMcpConfig / extractModules),**不用行号**——行号随重构漂移,
|
|
16
|
+
* 符号名稳定可 grep。
|
|
17
|
+
*
|
|
18
|
+
* status 语义:
|
|
19
|
+
* - live 真有 reader 从 local.yaml 读并起效(配了即生效)。
|
|
20
|
+
* - declared 代码/JSDoc/prompt 声明过,但无 reader 真读 local.yaml(或调用方未传),配了不生效。
|
|
21
|
+
* 诚实标出,避免 agent 白配 + 暴露待接线债。
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Object} SchemaKey
|
|
26
|
+
* @property {string} path 点分路径(mcp.url / worktree-hook.readonlyCommands)
|
|
27
|
+
* @property {string} type string|enum|integer|object|array|scalar
|
|
28
|
+
* @property {string[]} [values] enum 取值
|
|
29
|
+
* @property {boolean} [required] 凭据类必填(两键齐全才视为有效源)
|
|
30
|
+
* @property {boolean} [secret] 敏感凭据,example 用占位符
|
|
31
|
+
* @property {boolean} [optional] 可选键
|
|
32
|
+
* @property {string} status live|declared
|
|
33
|
+
* @property {string[]} readers 读取点符号名(稳定可 grep),declared 键留空数组
|
|
34
|
+
* @property {string} desc 一句话说明
|
|
35
|
+
* @property {string} example 脱敏示例值(secret 键用占位符)
|
|
36
|
+
*
|
|
37
|
+
* @typedef {Object} SchemaSection
|
|
38
|
+
* @property {string} id
|
|
39
|
+
* @property {string} title
|
|
40
|
+
* @property {string} note 段说明(写入来源 / 注意事项)
|
|
41
|
+
* @property {SchemaKey[]} keys
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/** @type {{ file: string, note: string, sections: SchemaSection[] }} */
|
|
45
|
+
export const LOCAL_YAML_SCHEMA = {
|
|
46
|
+
file: '.sillyspec/local.yaml',
|
|
47
|
+
note: 'gitignored(含敏感凭据勿提交);脱敏示例 local.yaml.example 由 sillyspec init 生成(可提交)。',
|
|
48
|
+
sections: [
|
|
49
|
+
{
|
|
50
|
+
id: 'project',
|
|
51
|
+
title: '项目类型',
|
|
52
|
+
note: '由 sillyspec local detect 纯 fs 嗅探写入,一般无需手填。',
|
|
53
|
+
keys: [
|
|
54
|
+
{
|
|
55
|
+
path: 'project.type',
|
|
56
|
+
type: 'enum',
|
|
57
|
+
values: ['nodejs', 'maven', 'gradle', 'make', 'generic'],
|
|
58
|
+
status: 'live',
|
|
59
|
+
readers: ['detectLocalYaml (src/local-detect.js)', 'extractProjectType (src/worktree-deps.js)'],
|
|
60
|
+
desc: '项目类型,决定默认 commands 嗅探与 worktree 依赖策略。',
|
|
61
|
+
example: 'nodejs',
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 'commands',
|
|
67
|
+
title: '构建/测试/lint 命令',
|
|
68
|
+
note: 'detect 核验 package.json(或对应构建文件) scripts 存在性后才写对应键;缺失则不写。agent 可改。',
|
|
69
|
+
keys: [
|
|
70
|
+
{ path: 'commands.build', type: 'string', optional: true, status: 'live', readers: ['detectLocalYaml (src/local-detect.js)', 'validateCommands (src/scan-postcheck.js)'], desc: '构建命令。', example: 'npm run build' },
|
|
71
|
+
{ path: 'commands.test', type: 'string', optional: true, status: 'live', readers: ['extractTestCommand (src/verify-postcheck.js)', 'validateCommands (src/scan-postcheck.js)'], desc: '测试命令——verify 阶段 CLI 亲自执行此命令与 verify-result.md 对账,实测失败即阻断。', example: 'npm test' },
|
|
72
|
+
{ path: 'commands.lint', type: 'string', optional: true, status: 'live', readers: ['detectLocalYaml (src/local-detect.js)', 'validateCommands (src/scan-postcheck.js)'], desc: 'lint 命令。', example: 'npm run lint' },
|
|
73
|
+
{ path: 'commands.install', type: 'string', optional: true, status: 'live', readers: ['extractInstallCommand (src/worktree-deps.js)'], desc: '依赖安装命令(worktree 依赖 provisioning 用)。', example: 'npm install' },
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'mcp',
|
|
78
|
+
title: 'SillyHub MCP 客户端凭据(派发用)',
|
|
79
|
+
note: 'agent 手填,或 sillyspec platform connect 在 mcp 段缺失时同源自动填(§7.4)。两键齐全才生效,否则回退 env SILLYHUB_MCP_URL/TOKEN。',
|
|
80
|
+
keys: [
|
|
81
|
+
{ path: 'mcp.url', type: 'string', required: true, secret: true, status: 'live', readers: ['readMcpConfig (src/sillyhub-mcp/config.js)'], desc: 'SillyHub MCP 服务地址(尾斜杠自动归一)。', example: 'https://your-sillyhub.example.com' },
|
|
82
|
+
{ path: 'mcp.token', type: 'string', required: true, secret: true, status: 'live', readers: ['readMcpConfig (src/sillyhub-mcp/config.js)'], desc: 'SillyHub MCP 认证 token。', example: '<your-mcp-token>' },
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: 'platform',
|
|
87
|
+
title: 'SillyHub 平台同步',
|
|
88
|
+
note: 'sillyspec platform connect 写入(含 ping 验活);手填亦可。user/last_connected 可空或自动写。',
|
|
89
|
+
keys: [
|
|
90
|
+
{ path: 'platform.url', type: 'string', required: true, secret: true, status: 'live', readers: ['SyncManager._getPlatform (src/sync.js)'], desc: 'SillyHub 平台地址。', example: 'https://your-sillyhub.example.com' },
|
|
91
|
+
{ path: 'platform.token', type: 'string', required: true, secret: true, status: 'live', readers: ['SyncManager._getPlatform (src/sync.js)'], desc: '平台认证 token(Bearer)。', example: '<your-platform-token>' },
|
|
92
|
+
{ path: 'platform.user', type: 'string', optional: true, status: 'live', readers: ['resolvePlatformUser / SyncManager.connect (src/sync.js)'], desc: '推送者身份;缺则回退 git user.name / env。推送时进 X-SillySpec-User header。', example: 'alice' },
|
|
93
|
+
{ path: 'platform.last_connected', type: 'string', optional: true, status: 'live', readers: ['SyncManager.connect (src/sync.js)'], desc: 'connect 成功时间戳(ISO),自动写,勿手填。', example: '2026-08-11T00:00:00.000Z' },
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 'dispatch',
|
|
98
|
+
title: '派发调参',
|
|
99
|
+
note: '仅在确知调优值时填,否则留默认。',
|
|
100
|
+
keys: [
|
|
101
|
+
{ path: 'dispatch.probe_ttl_ms', type: 'integer', optional: true, status: 'live', readers: ['readProbeTtlFromLocalYaml (src/dispatch/probe.js)'], desc: '派发探测负面缓存 TTL(毫秒,默认 60000)。daemon 抖动期避免反复探测。', example: '60000' },
|
|
102
|
+
{ path: 'dispatch.poll_interval_ms', type: 'integer', optional: true, status: 'declared', readers: [], desc: '【路径A 预留·未落地】renderSillyHubInstruction 注入的轮询文本提及,但 isPathASupported()=false 该指令当前不注入;路径A 落地后接线,配了暂不生效。', example: '15000' },
|
|
103
|
+
{ path: 'dispatch.worker_timeout_ms', type: 'integer', optional: true, status: 'declared', readers: [], desc: '【路径A 预留·未落地】同 poll_interval_ms,路径A 落地后接线,配了暂不生效。', example: '60000' },
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'modules',
|
|
108
|
+
title: 'monorepo 子模块映射',
|
|
109
|
+
note: 'test_strategy: module 时,按 git diff 命中的模块子集收窄测试。只支持 inline flow 形态(extractModules 不解析嵌套展开式)。',
|
|
110
|
+
keys: [
|
|
111
|
+
{ path: 'modules.<name>.path', type: 'string', optional: true, status: 'live', readers: ['extractModules (src/verify-postcheck.js)', 'parseLocalYamlModules (src/plan-postcheck.js)', 'extractModulePaths (src/worktree-deps.js)'], desc: '子模块目录路径(相对仓库根)。', example: 'frontend/' },
|
|
112
|
+
{ path: 'modules.<name>.test', type: 'string', optional: true, status: 'live', readers: ['extractModules (src/verify-postcheck.js)'], desc: '该子模块的测试命令。', example: 'cd frontend && pnpm test' },
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'test_strategy',
|
|
117
|
+
title: '测试策略',
|
|
118
|
+
note: 'verify 阶段 CLI 对账的收窄策略。',
|
|
119
|
+
keys: [
|
|
120
|
+
{ path: 'test_strategy', type: 'enum', values: ['full', 'module'], optional: true, status: 'live', readers: ['extractTestStrategy (src/verify-postcheck.js)'], desc: 'full=全量 commands.test;module=按 git diff 命中 modules 子集收窄(需配 modules)。缺省=全量。', example: 'full' },
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: 'known_failures',
|
|
125
|
+
title: '预存失败豁免清单',
|
|
126
|
+
note: '变更前就失败的测试行,豁免后不计入 verify 阻断。支持块列表或 inline 数组。务必定期复核,避免误豁免本变更引入的真实失败。',
|
|
127
|
+
keys: [
|
|
128
|
+
{ path: 'known_failures', type: 'array', optional: true, status: 'live', readers: ['extractKnownFailures (src/verify-postcheck.js)'], desc: '失败行模式列表(匹配测试输出失败行)。', example: 'tests/some-old-test' },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'worktree-hook',
|
|
133
|
+
title: 'worktree-guard 扩展',
|
|
134
|
+
note: 'execute worktree 隔离期内放行的额外只读命令。键名用 camelCase(parseSimpleYaml 原样保留)。',
|
|
135
|
+
keys: [
|
|
136
|
+
{ path: 'worktree-hook.readonlyCommands', type: 'array', optional: true, status: 'live', readers: ['loadLocalConfig (src/hooks/worktree-guard.js)'], desc: '额外放行的只读命令名列表(如 rg/fd),绕过 worktree-guard 写操作拦截。', example: 'rg' },
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: 'auto_mode',
|
|
141
|
+
title: '变更规模自动分类',
|
|
142
|
+
note: 'sillyspec run auto 时,readAutoModeFromLocalYaml 读本段传 classifyChange 的 localConfig,force_*_patterns 匹配需求描述则强制对应模式。',
|
|
143
|
+
keys: [
|
|
144
|
+
{ path: 'auto_mode.force_full_patterns', type: 'array', optional: true, status: 'live', readers: ['readAutoModeFromLocalYaml + classifyChange (src/classify-change.js)', 'runCommand (src/run/command.js)'], desc: '需求描述匹配任一正则(i 大小写无关)→ 强制 full 流程。非法正则跳过不崩。', example: '数据库|migration' },
|
|
145
|
+
{ path: 'auto_mode.force_quick_patterns', type: 'array', optional: true, status: 'live', readers: ['readAutoModeFromLocalYaml + classifyChange (src/classify-change.js)', 'runCommand (src/run/command.js)'], desc: '需求描述匹配任一正则 → 强制 quick。非法正则跳过不崩。', example: 'fix typo' },
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 'docs-check',
|
|
150
|
+
title: '文档引用校验',
|
|
151
|
+
note: 'sillyspec docs check 的扫描与断言配置(2026-08-15 docs-check-productize)。glob 相对源码仓根展开,仅支持 目录/**/*.扩展、目录/*.扩展、字面路径 三形态。',
|
|
152
|
+
keys: [
|
|
153
|
+
{ path: 'docs-check.paths', type: 'array', optional: true, status: 'live', readers: ['docs check (src/index.js case docs) + runDocsCheck (src/docs-check.js)'], desc: '扫描的文档 glob 列表,缺省 docs/**/*.md 与 .sillyspec/docs/**/*.md(scan/modules 产物同纳入)。', example: 'docs/**/*.md' },
|
|
154
|
+
{ path: 'docs-check.skip', type: 'array', optional: true, status: 'live', readers: ['walkGlob (src/docs-check.js)'], desc: '排除的路径/glob 列表,缺省空。', example: 'docs/sillyspec/archive' },
|
|
155
|
+
{ path: 'docs-check.keywordAssert', type: 'boolean', optional: true, status: 'live', readers: ['runDocsCheck (src/docs-check.js)'], desc: '层2 关键词断言开关,缺省 true(关闭时 warning 提示仅做存在性校验)。', example: 'true' },
|
|
156
|
+
{ path: 'docs-check.living-docs', type: 'array', optional: true, status: 'live', readers: ['resolveLivingDocs (src/run/shared.js) — 经 readLocalYamlRaw 直读'], desc: '活文档监控点追加列表(docs check 之外,quick 审计的 livingDocDrift 真失效提示也监控——只报校验真失败的引用,全过零输出)。只追加不覆盖缺省集合(缺省:docs/sillyspec/platform-interface-map.md)。配了是加哨兵,不该把缺省监控点挤掉。', example: 'docs/sillyspec/architecture.md' },
|
|
157
|
+
{ path: 'docs-check.cross_repo_roots', type: 'object', optional: true, status: 'live', readers: ['readDocsCheckConfig (src/docs-check.js)'], desc: 'repo://<仓库名> 跨仓引用 → 本机仓库根目录映射。文档里 repo://name/src/x.js:12 形态的引用:未配映射默认跳过(不同设备仓库位置不同,防跨设备误报);配了映射走与本地引用相同的行号+关键词校验。local.yaml 是 gitignored,绝对路径不入库,每台设备各自配。', example: 'sillyspec: /c/Users/you/IdeaProjects/sillyspec' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/** 全部键(拍平),便于 JSON 输出与 example 耦合测试。 */
|
|
164
|
+
export function flatKeys() {
|
|
165
|
+
return LOCAL_YAML_SCHEMA.sections.flatMap((s) => s.keys.map((k) => ({ section: s.id, ...k })));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** 人类可读树形 schema 文本。live 在前、declared 在后,段内逐键列 path/type/约束/读取点/说明。 */
|
|
169
|
+
export function renderSchemaHuman() {
|
|
170
|
+
const L = [];
|
|
171
|
+
L.push('SillySpec local.yaml 配置清单');
|
|
172
|
+
L.push(`文件:${LOCAL_YAML_SCHEMA.file} — ${LOCAL_YAML_SCHEMA.note}`);
|
|
173
|
+
L.push('数据源:src/config-schema.js(本表唯一真相;reader 见各键「读取点」,符号名可 grep)');
|
|
174
|
+
L.push('');
|
|
175
|
+
|
|
176
|
+
const all = flatKeys();
|
|
177
|
+
const live = all.filter((k) => k.status === 'live');
|
|
178
|
+
const declared = all.filter((k) => k.status === 'declared');
|
|
179
|
+
|
|
180
|
+
L.push(`━━━ 生效(${live.length} 键,配了即生效) ━━━`);
|
|
181
|
+
L.push('');
|
|
182
|
+
for (const s of LOCAL_YAML_SCHEMA.sections) {
|
|
183
|
+
const keys = s.keys.filter((k) => k.status === 'live');
|
|
184
|
+
if (keys.length === 0) continue;
|
|
185
|
+
L.push(`[${s.id}] ${s.title}`);
|
|
186
|
+
L.push(` ${s.note}`);
|
|
187
|
+
for (const k of keys) {
|
|
188
|
+
L.push(` ${k.path}${formatConstraint(k)} ${k.desc}`);
|
|
189
|
+
if (k.readers.length) L.push(` 读取点:${k.readers.join(';')}`);
|
|
190
|
+
}
|
|
191
|
+
L.push('');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
L.push(`━━━ 声明但未接线(${declared.length} 键,配了不生效 / 待接线债) ━━━`);
|
|
195
|
+
L.push('');
|
|
196
|
+
for (const s of LOCAL_YAML_SCHEMA.sections) {
|
|
197
|
+
const keys = s.keys.filter((k) => k.status === 'declared');
|
|
198
|
+
if (keys.length === 0) continue;
|
|
199
|
+
L.push(`[${s.id}] ${s.title}`);
|
|
200
|
+
L.push(` ${s.note}`);
|
|
201
|
+
for (const k of keys) {
|
|
202
|
+
L.push(` ${k.path}${formatConstraint(k)} ${k.desc}`);
|
|
203
|
+
}
|
|
204
|
+
L.push('');
|
|
205
|
+
}
|
|
206
|
+
return L.join('\n');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function formatConstraint(k) {
|
|
210
|
+
const tags = [];
|
|
211
|
+
if (k.required) tags.push('必填');
|
|
212
|
+
if (k.optional) tags.push('可选');
|
|
213
|
+
if (k.secret) tags.push('凭据');
|
|
214
|
+
if (k.type === 'enum' && k.values) tags.push(k.values.join('|'));
|
|
215
|
+
else tags.push(k.type);
|
|
216
|
+
return tags.length ? ` [${tags.join(' · ')}]` : '';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** 机读 JSON(程序化消费)。结构 = LOCAL_YAML_SCHEMA 本体 + flatKeys 视图。 */
|
|
220
|
+
export function renderSchemaJson() {
|
|
221
|
+
return JSON.stringify({
|
|
222
|
+
file: LOCAL_YAML_SCHEMA.file,
|
|
223
|
+
note: LOCAL_YAML_SCHEMA.note,
|
|
224
|
+
sections: LOCAL_YAML_SCHEMA.sections,
|
|
225
|
+
keys: flatKeys().map(({ section, path, type, values, required, optional, secret, status, readers, desc }) => ({
|
|
226
|
+
section, path, type, values, required, optional, secret, status, readers, desc,
|
|
227
|
+
})),
|
|
228
|
+
}, null, 2);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 脱敏 local.yaml 示例文本(sillyspec init 落盘用)。
|
|
233
|
+
* 策展模板(非自动生成):YAML 形态各异(嵌套/inline flow/顶层标量),策展可读性远胜自动拼。
|
|
234
|
+
* 与 SCHEMA 的耦合由测试保证:每个 live 键路径必出现于本文本。
|
|
235
|
+
*/
|
|
236
|
+
export function renderExample() {
|
|
237
|
+
return `# SillySpec local.yaml — 脱敏示例(由 sillyspec init 生成,可提交)
|
|
238
|
+
# 真实配置文件 .sillyspec/local.yaml 是 gitignored(含敏感凭据)。
|
|
239
|
+
# 用法:复制本文件为 .sillyspec/local.yaml,填真实值;或直接 sillyspec platform connect 自动写凭据段。
|
|
240
|
+
# 全部键与生效状态:sillyspec config schema
|
|
241
|
+
|
|
242
|
+
# ── 项目类型(sillyspec local detect 自动写入,一般无需手填)──
|
|
243
|
+
project:
|
|
244
|
+
type: nodejs # nodejs | maven | gradle | make | generic
|
|
245
|
+
|
|
246
|
+
# ── 构建/测试/lint 命令(detect 核验 scripts 存在性后才写;缺失键省略)──
|
|
247
|
+
commands:
|
|
248
|
+
build: npm run build
|
|
249
|
+
test: npm test
|
|
250
|
+
lint: npm run lint
|
|
251
|
+
# install: npm install # worktree 依赖安装命令
|
|
252
|
+
|
|
253
|
+
# ── SillyHub MCP 客户端凭据(派发到 worker 用)──
|
|
254
|
+
# agent 手填,或 sillyspec platform connect 在 mcp 段缺失时同源自动填。
|
|
255
|
+
# 两键齐全才生效;缺则回退环境变量 SILLYHUB_MCP_URL / SILLYHUB_MCP_TOKEN。
|
|
256
|
+
mcp:
|
|
257
|
+
url: https://your-sillyhub.example.com
|
|
258
|
+
token: <your-mcp-token>
|
|
259
|
+
|
|
260
|
+
# ── SillyHub 平台同步(sillyspec platform connect 写入,含 ping 验活)──
|
|
261
|
+
platform:
|
|
262
|
+
url: https://your-sillyhub.example.com
|
|
263
|
+
token: <your-platform-token>
|
|
264
|
+
user: alice # 推送者身份(可空,回退 git user.name / env)
|
|
265
|
+
# last_connected: 2026-08-11T00:00:00.000Z # connect 自动写,勿手填
|
|
266
|
+
|
|
267
|
+
# ── 派发调参(仅确知调优值时填,否则留默认)──
|
|
268
|
+
dispatch:
|
|
269
|
+
probe_ttl_ms: 60000 # 派发探测负面缓存 TTL(默认 60000)
|
|
270
|
+
# poll_interval_ms: 15000 # ⚠ 路径A 预留·未落地,配了暂不生效
|
|
271
|
+
# worker_timeout_ms: 60000 # ⚠ 路径A 预留·未落地,配了暂不生效
|
|
272
|
+
|
|
273
|
+
# ── monorepo 子模块映射(test_strategy: module 时按 git diff 命中模块收窄测试)──
|
|
274
|
+
# 只支持 inline flow 形态(嵌套展开式解析不出):
|
|
275
|
+
modules:
|
|
276
|
+
frontend: { path: "frontend/", test: "cd frontend && pnpm test" }
|
|
277
|
+
backend: { path: "backend/", test: "cd backend && npm test" }
|
|
278
|
+
|
|
279
|
+
# ── 测试策略:full=全量 commands.test | module=按命中模块收窄(需配 modules)──
|
|
280
|
+
test_strategy: full
|
|
281
|
+
|
|
282
|
+
# ── 预存失败豁免清单(变更前就失败的测试行;务必定期复核,防误豁免真实失败)──
|
|
283
|
+
known_failures:
|
|
284
|
+
- tests/some-old-stable-failure
|
|
285
|
+
|
|
286
|
+
# ── worktree-guard 只读命令扩展(execute worktree 隔离期内放行额外只读命令)──
|
|
287
|
+
worktree-hook:
|
|
288
|
+
readonlyCommands:
|
|
289
|
+
- rg
|
|
290
|
+
- fd
|
|
291
|
+
|
|
292
|
+
# ── 变更规模自动分类(sillyspec run auto 时按需求描述强制 quick/full;正则数组,i 大小写无关)──
|
|
293
|
+
auto_mode:
|
|
294
|
+
force_full_patterns:
|
|
295
|
+
- 数据库|migration
|
|
296
|
+
force_quick_patterns:
|
|
297
|
+
- fix typo
|
|
298
|
+
|
|
299
|
+
# ── 文档引用校验(sillyspec docs check;glob 相对源码仓根,三形态:递归/单层/字面路径)──
|
|
300
|
+
# 缺省已扫 docs/**/*.md 与 .sillyspec/docs/**/*.md;本段仅在需要收窄/排除时配置
|
|
301
|
+
docs-check:
|
|
302
|
+
paths:
|
|
303
|
+
- docs/**/*.md
|
|
304
|
+
- .sillyspec/docs/**/*.md
|
|
305
|
+
# skip:
|
|
306
|
+
# - docs/sillyspec/archive
|
|
307
|
+
keywordAssert: true
|
|
308
|
+
# living-docs: # 活文档监控点追加(缺省已含 docs/sillyspec/platform-interface-map.md,只加哨兵不覆盖)
|
|
309
|
+
# - docs/sillyspec/architecture.md
|
|
310
|
+
# cross_repo_roots: # repo://<仓库名> 跨仓引用 → 本机仓库根(每台设备各自配,绝对路径勿提交)
|
|
311
|
+
# sillyspec: /c/Users/you/IdeaProjects/sillyspec
|
|
312
|
+
`;
|
|
313
|
+
}
|