sillyspec 3.11.11 → 3.12.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.
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +7 -5
- package/.claude/skills/sillyspec-resume/SKILL.md +21 -64
- package/.claude/skills/sillyspec-workspace/SKILL.md +10 -2
- package/CLAUDE.md +18 -0
- package/docs/sillyspec/file-lifecycle.md +1108 -0
- package/package.json +2 -1
- package/src/db.js +168 -0
- package/src/index.js +98 -2
- package/src/init.js +2 -8
- package/src/progress.js +652 -325
- package/src/run.js +129 -26
- package/src/stages/archive.js +7 -11
- package/src/stages/verify.js +6 -6
- package/src/sync.js +497 -0
package/src/run.js
CHANGED
|
@@ -11,6 +11,33 @@ import { stageRegistry, auxiliaryStages } from './stages/index.js'
|
|
|
11
11
|
import { buildExecuteSteps } from './stages/execute.js'
|
|
12
12
|
import { buildPlanSteps } from './stages/plan.js'
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* 同步触发辅助函数:_write 后 best-effort 同步到平台
|
|
16
|
+
*/
|
|
17
|
+
async function triggerSync(cwd, changeName) {
|
|
18
|
+
try {
|
|
19
|
+
const syncMod = await import('./sync.js')
|
|
20
|
+
await syncMod.sync(cwd, changeName)
|
|
21
|
+
} catch (e) {
|
|
22
|
+
// sync.js 不存在或同步失败,静默跳过
|
|
23
|
+
console.warn('⚠️ 同步失败:', e.message)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 审批检查辅助函数:execute 阶段启动前检查
|
|
29
|
+
* @returns {{ status: string, reason?: string } | null}
|
|
30
|
+
*/
|
|
31
|
+
async function checkApproval(cwd, changeName) {
|
|
32
|
+
try {
|
|
33
|
+
const syncMod = await import('./sync.js')
|
|
34
|
+
return await syncMod.checkApproval(cwd, changeName)
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// sync.js 不存在或检查失败,静默跳过
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
14
41
|
/**
|
|
15
42
|
* 统一查找变更目录(与 progress.js 的变更检测逻辑一致)
|
|
16
43
|
*/
|
|
@@ -207,6 +234,7 @@ export async function runCommand(args, cwd) {
|
|
|
207
234
|
const isStatus = flags.includes('--status')
|
|
208
235
|
const isReset = flags.includes('--reset')
|
|
209
236
|
const isConfirm = flags.includes('--confirm')
|
|
237
|
+
const isSkipApproval = flags.includes('--skip-approval')
|
|
210
238
|
|
|
211
239
|
// 解析 --output
|
|
212
240
|
let outputText = null
|
|
@@ -232,22 +260,25 @@ export async function runCommand(args, cwd) {
|
|
|
232
260
|
const isAuxiliary = auxiliaryStages.includes(stageName)
|
|
233
261
|
|
|
234
262
|
const pm = new ProgressManager()
|
|
235
|
-
pm.
|
|
236
|
-
let progress = pm.read(cwd, changeName)
|
|
263
|
+
let progress = await pm.read(cwd, changeName)
|
|
237
264
|
|
|
238
265
|
if (!progress) {
|
|
239
266
|
// 如果指定了变更名或有变更目录,自动初始化变更的 progress
|
|
240
267
|
const autoChange = changeName || resolveChangeNameAuto(cwd)
|
|
241
268
|
if (autoChange) {
|
|
242
|
-
progress = pm.initChange(cwd, autoChange)
|
|
243
|
-
} else if (
|
|
269
|
+
progress = await pm.initChange(cwd, autoChange)
|
|
270
|
+
} else if (isAuxiliary) {
|
|
271
|
+
// 辅助阶段(scan/explore/quick/doctor/status)不需要 currentChange
|
|
272
|
+
// 但仍然需要初始化一个空的 progress 对象以避免后续引用报错
|
|
273
|
+
progress = { currentStage: stageName, stages: {}, lastActive: new Date().toLocaleString('zh-CN', { hour12: false }) }
|
|
274
|
+
} else {
|
|
244
275
|
// brainstorm / propose 作为流程入口,自动生成变更名并初始化
|
|
245
276
|
if (stageName === 'brainstorm' || stageName === 'propose') {
|
|
246
277
|
const date = new Date().toISOString().slice(0, 10)
|
|
247
278
|
const autoName = `${date}-new-change`
|
|
248
279
|
console.log(`🔄 自动创建变更:${autoName}`)
|
|
249
280
|
console.log(` 提示:可以用 --change <名称> 指定自定义变更名`)
|
|
250
|
-
progress = pm.initChange(cwd, autoName)
|
|
281
|
+
progress = await pm.initChange(cwd, autoName)
|
|
251
282
|
changeName = autoName
|
|
252
283
|
} else {
|
|
253
284
|
console.error('❌ 未找到 progress.json,请先运行 sillyspec init 或指定 --change <变更名>')
|
|
@@ -267,7 +298,7 @@ export async function runCommand(args, cwd) {
|
|
|
267
298
|
// --change 只作为变更名标识,不再拦截流程
|
|
268
299
|
// 注册变更到全局活跃列表(如果尚未注册)
|
|
269
300
|
if (effectiveChange) {
|
|
270
|
-
pm.registerChange(cwd, effectiveChange)
|
|
301
|
+
await pm.registerChange(cwd, effectiveChange)
|
|
271
302
|
}
|
|
272
303
|
|
|
273
304
|
// --reset
|
|
@@ -277,9 +308,10 @@ export async function runCommand(args, cwd) {
|
|
|
277
308
|
|
|
278
309
|
// 确保步骤已初始化
|
|
279
310
|
const changed = await ensureStageSteps(progress, stageName, cwd)
|
|
280
|
-
if (changed) {
|
|
281
|
-
pm._write(cwd, progress, effectiveChange)
|
|
282
|
-
|
|
311
|
+
if (changed && effectiveChange) {
|
|
312
|
+
await pm._write(cwd, progress, effectiveChange)
|
|
313
|
+
triggerSync(cwd, effectiveChange)
|
|
314
|
+
progress = await pm.read(cwd, effectiveChange) || progress
|
|
283
315
|
}
|
|
284
316
|
|
|
285
317
|
// --status
|
|
@@ -298,7 +330,7 @@ export async function runCommand(args, cwd) {
|
|
|
298
330
|
}
|
|
299
331
|
|
|
300
332
|
// 默认:输出当前步骤
|
|
301
|
-
return await runStage(pm, progress, stageName, cwd, effectiveChange)
|
|
333
|
+
return await runStage(pm, progress, stageName, cwd, effectiveChange, isSkipApproval)
|
|
302
334
|
}
|
|
303
335
|
|
|
304
336
|
/**
|
|
@@ -313,11 +345,27 @@ function resolveChangeNameAuto(cwd) {
|
|
|
313
345
|
return null
|
|
314
346
|
}
|
|
315
347
|
|
|
316
|
-
async function runStage(pm, progress, stageName, cwd, changeName) {
|
|
348
|
+
async function runStage(pm, progress, stageName, cwd, changeName, skipApproval = false) {
|
|
349
|
+
// execute 阶段启动前检查审批
|
|
350
|
+
if (stageName === 'execute' && !skipApproval) {
|
|
351
|
+
const approval = await checkApproval(cwd, changeName)
|
|
352
|
+
if (approval) {
|
|
353
|
+
if (approval.status === 'rejected') {
|
|
354
|
+
console.error(`❌ 变更 ${changeName} 的执行已被拒绝:${approval.reason || '无原因'}`)
|
|
355
|
+
process.exit(1)
|
|
356
|
+
}
|
|
357
|
+
if (approval.status === 'pending') {
|
|
358
|
+
console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
|
|
359
|
+
console.log(' 提示:使用 --skip-approval 跳过审批检查')
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
317
364
|
// 自动探测 currentChange
|
|
318
365
|
if (autoDetectChange(progress, cwd)) {
|
|
319
366
|
progress.lastActive = new Date().toLocaleString('zh-CN', { hour12: false })
|
|
320
|
-
pm._write(cwd, progress, changeName)
|
|
367
|
+
await pm._write(cwd, progress, changeName)
|
|
368
|
+
triggerSync(cwd, changeName)
|
|
321
369
|
}
|
|
322
370
|
|
|
323
371
|
const stageData = progress.stages[stageName]
|
|
@@ -330,7 +378,8 @@ async function runStage(pm, progress, stageName, cwd, changeName) {
|
|
|
330
378
|
if (progress.currentStage !== stageName) {
|
|
331
379
|
progress.currentStage = stageName
|
|
332
380
|
progress.lastActive = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
333
|
-
pm._write(cwd, progress, changeName)
|
|
381
|
+
await pm._write(cwd, progress, changeName)
|
|
382
|
+
triggerSync(cwd, changeName)
|
|
334
383
|
}
|
|
335
384
|
|
|
336
385
|
const steps = stageData.steps
|
|
@@ -345,7 +394,8 @@ async function runStage(pm, progress, stageName, cwd, changeName) {
|
|
|
345
394
|
stageData.status = 'in-progress'
|
|
346
395
|
stageData.startedAt = new Date().toLocaleString('zh-CN', { hour12: false })
|
|
347
396
|
stageData.completedAt = null
|
|
348
|
-
pm._write(cwd, progress, changeName)
|
|
397
|
+
await pm._write(cwd, progress, changeName)
|
|
398
|
+
triggerSync(cwd, changeName)
|
|
349
399
|
currentIdx = 0
|
|
350
400
|
console.log(`🔄 ${stageName} 阶段已自动重置,重新开始。\n`)
|
|
351
401
|
}
|
|
@@ -506,7 +556,8 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
|
|
|
506
556
|
stageData.status = 'completed'
|
|
507
557
|
stageData.completedAt = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
508
558
|
progress.lastActive = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
509
|
-
pm._write(cwd, progress, changeName)
|
|
559
|
+
await pm._write(cwd, progress, changeName)
|
|
560
|
+
triggerSync(cwd, changeName)
|
|
510
561
|
|
|
511
562
|
// Append to user-inputs.md
|
|
512
563
|
if (outputText) {
|
|
@@ -552,7 +603,7 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
|
|
|
552
603
|
}
|
|
553
604
|
|
|
554
605
|
// 从全局活跃列表移除
|
|
555
|
-
pm.unregisterChange(cwd, archiveChangeName)
|
|
606
|
+
await pm.unregisterChange(cwd, archiveChangeName)
|
|
556
607
|
console.log(`📦 已归档:${archiveChangeName} → archive/${date}-${archiveChangeName}/`)
|
|
557
608
|
} else {
|
|
558
609
|
console.log('⚠️ 请添加 --confirm 确认归档,例如:sillyspec run archive --done --confirm --output "确认归档"')
|
|
@@ -571,7 +622,7 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
|
|
|
571
622
|
stageData.steps = freshSteps
|
|
572
623
|
stageData.status = 'pending'
|
|
573
624
|
stageData.completedAt = null
|
|
574
|
-
pm._write(cwd, progress, changeName)
|
|
625
|
+
await pm._write(cwd, progress, changeName)
|
|
575
626
|
}
|
|
576
627
|
|
|
577
628
|
const total = steps.length
|
|
@@ -590,7 +641,8 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
|
|
|
590
641
|
}
|
|
591
642
|
|
|
592
643
|
progress.lastActive = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
593
|
-
pm._write(cwd, progress, changeName)
|
|
644
|
+
await pm._write(cwd, progress, changeName)
|
|
645
|
+
triggerSync(cwd, changeName)
|
|
594
646
|
|
|
595
647
|
// Append to user-inputs.md
|
|
596
648
|
if (outputText) {
|
|
@@ -632,7 +684,8 @@ async function skipStep(pm, progress, stageName, cwd, changeName) {
|
|
|
632
684
|
steps[currentIdx].status = 'skipped'
|
|
633
685
|
steps[currentIdx].skippedAt = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
634
686
|
progress.lastActive = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
635
|
-
pm._write(cwd, progress, changeName)
|
|
687
|
+
await pm._write(cwd, progress, changeName)
|
|
688
|
+
triggerSync(cwd, changeName)
|
|
636
689
|
|
|
637
690
|
console.log(`⏭️ Step ${currentIdx + 1}/${steps.length} 已跳过:${steps[currentIdx].name}`)
|
|
638
691
|
|
|
@@ -694,7 +747,8 @@ async function resetStage(pm, progress, stageName, cwd, changeName) {
|
|
|
694
747
|
steps: defSteps ? defSteps.map(s => ({ name: s.name, status: 'pending' })) : []
|
|
695
748
|
}
|
|
696
749
|
progress.lastActive = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
697
|
-
pm._write(cwd, progress, changeName)
|
|
750
|
+
await pm._write(cwd, progress, changeName)
|
|
751
|
+
triggerSync(cwd, changeName)
|
|
698
752
|
console.log(`🔄 ${stageName} 阶段已重置`)
|
|
699
753
|
}
|
|
700
754
|
|
|
@@ -708,6 +762,7 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
|
|
|
708
762
|
const outputText = outputIdx !== -1 && flags[outputIdx + 1] ? flags[outputIdx + 1] : null
|
|
709
763
|
const inputIdx = flags.indexOf('--input')
|
|
710
764
|
const inputText = inputIdx !== -1 && flags[inputIdx + 1] ? flags[inputIdx + 1] : null
|
|
765
|
+
const skipApproval = flags.includes('--skip-approval')
|
|
711
766
|
const nextInFlow = (stage) => {
|
|
712
767
|
const i = flowStages.indexOf(stage)
|
|
713
768
|
return i >= 0 && i < flowStages.length - 1 ? flowStages[i + 1] : null
|
|
@@ -717,8 +772,11 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
|
|
|
717
772
|
const stageChanged = progress.currentStage !== stage
|
|
718
773
|
progress.currentStage = stage
|
|
719
774
|
const changed = await ensureStageSteps(progress, stage, cwd)
|
|
720
|
-
if (stageChanged || changed)
|
|
721
|
-
|
|
775
|
+
if (stageChanged || changed) {
|
|
776
|
+
await pm._write(cwd, progress, changeName)
|
|
777
|
+
triggerSync(cwd, changeName)
|
|
778
|
+
}
|
|
779
|
+
progress = await pm.read(cwd, changeName)
|
|
722
780
|
return progress
|
|
723
781
|
}
|
|
724
782
|
|
|
@@ -765,6 +823,20 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
|
|
|
765
823
|
else console.log('All auto flow stages are complete.')
|
|
766
824
|
return
|
|
767
825
|
}
|
|
826
|
+
// execute 阶段启动前检查审批
|
|
827
|
+
if (currentStage === 'execute' && !skipApproval) {
|
|
828
|
+
const approval = await checkApproval(cwd, changeName)
|
|
829
|
+
if (approval) {
|
|
830
|
+
if (approval.status === 'rejected') {
|
|
831
|
+
console.error(`❌ 变更 ${changeName} 的执行已被拒绝:${approval.reason || '无原因'}`)
|
|
832
|
+
process.exit(1)
|
|
833
|
+
}
|
|
834
|
+
if (approval.status === 'pending') {
|
|
835
|
+
console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
|
|
836
|
+
console.log(' 提示:使用 --skip-approval 跳过审批检查')
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
768
840
|
outputStep(currentStage, pendingIdx, defSteps, cwd, changeName)
|
|
769
841
|
return
|
|
770
842
|
}
|
|
@@ -776,11 +848,25 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
|
|
|
776
848
|
|
|
777
849
|
const result = await completeStep(pm, progress, currentStage, cwd, outputText, inputText, { printNext: false, changeName })
|
|
778
850
|
if (!result) return
|
|
779
|
-
progress = pm.read(cwd, changeName)
|
|
851
|
+
progress = await pm.read(cwd, changeName)
|
|
780
852
|
|
|
781
853
|
const nextPendingIdx = progress.stages[currentStage]?.steps?.findIndex(step => step.status === 'pending') ?? -1
|
|
782
854
|
if (nextPendingIdx !== -1) {
|
|
783
855
|
const defSteps = await getStageSteps(currentStage, cwd, progress)
|
|
856
|
+
// execute 阶段启动前检查审批
|
|
857
|
+
if (currentStage === 'execute' && !skipApproval) {
|
|
858
|
+
const approval = await checkApproval(cwd, changeName)
|
|
859
|
+
if (approval) {
|
|
860
|
+
if (approval.status === 'rejected') {
|
|
861
|
+
console.error(`❌ 变更 ${changeName} 的执行已被拒绝:${approval.reason || '无原因'}`)
|
|
862
|
+
process.exit(1)
|
|
863
|
+
}
|
|
864
|
+
if (approval.status === 'pending') {
|
|
865
|
+
console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
|
|
866
|
+
console.log(' 提示:使用 --skip-approval 跳过审批检查')
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
784
870
|
outputStep(currentStage, nextPendingIdx, defSteps, cwd, changeName)
|
|
785
871
|
return
|
|
786
872
|
}
|
|
@@ -801,11 +887,28 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
|
|
|
801
887
|
}
|
|
802
888
|
progress.lastActive = new Date().toLocaleString('zh-CN',{hour12:false})
|
|
803
889
|
await ensureStageSteps(progress, next, cwd)
|
|
804
|
-
pm._write(cwd, progress, changeName)
|
|
805
|
-
|
|
890
|
+
await pm._write(cwd, progress, changeName)
|
|
891
|
+
triggerSync(cwd, changeName)
|
|
892
|
+
progress = await pm.read(cwd, changeName)
|
|
806
893
|
|
|
807
894
|
console.log(`\n${currentStage} complete. Auto advanced to ${next}.`)
|
|
808
895
|
const nextSteps = await getStageSteps(next, cwd, progress)
|
|
809
896
|
const firstPending = progress.stages[next]?.steps?.findIndex(step => step.status === 'pending') ?? -1
|
|
810
|
-
if (firstPending !== -1)
|
|
897
|
+
if (firstPending !== -1) {
|
|
898
|
+
// execute 阶段启动前检查审批
|
|
899
|
+
if (next === 'execute' && !skipApproval) {
|
|
900
|
+
const approval = await checkApproval(cwd, changeName)
|
|
901
|
+
if (approval) {
|
|
902
|
+
if (approval.status === 'rejected') {
|
|
903
|
+
console.error(`❌ 变更 ${changeName} 的执行已被拒绝:${approval.reason || '无原因'}`)
|
|
904
|
+
process.exit(1)
|
|
905
|
+
}
|
|
906
|
+
if (approval.status === 'pending') {
|
|
907
|
+
console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
|
|
908
|
+
console.log(' 提示:使用 --skip-approval 跳过审批检查')
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
outputStep(next, firstPending, nextSteps, cwd, changeName)
|
|
913
|
+
}
|
|
811
914
|
}
|
package/src/stages/archive.js
CHANGED
|
@@ -142,22 +142,18 @@ module-impact.md 路径 + 影响模块数量 + 未匹配文件数量`,
|
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
name: '确认归档',
|
|
145
|
-
prompt:
|
|
145
|
+
prompt: `确认归档内容并执行目录移动。
|
|
146
146
|
|
|
147
147
|
### 操作
|
|
148
148
|
1. 展示:变更目录名、包含的文件列表(含 module-impact.md)、生成总结
|
|
149
|
-
2.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
确认归档后,执行以下命令自动完成目录移动:
|
|
155
|
-
\t\tsillyspec run archive --done --confirm --output "确认归档"
|
|
156
|
-
- \`--confirm\` 标志会自动执行目录移动(原子操作)
|
|
157
|
-
- 不带 \`--confirm\` 则只提示需要确认
|
|
149
|
+
2. **直接执行归档**(本步骤完成后自动移动):
|
|
150
|
+
- 创建 archive 目录:\`mkdir -p .sillyspec/changes/archive\`
|
|
151
|
+
- 移动变更目录:\`mv .sillyspec/changes/<change-name> .sillyspec/changes/archive/<change-name>\`
|
|
152
|
+
- 确认移动成功:\`ls .sillyspec/changes/archive/<change-name>/\`
|
|
153
|
+
3. 确保所有 checkbox 都已勾选
|
|
158
154
|
|
|
159
155
|
### 输出
|
|
160
|
-
|
|
156
|
+
归档完成 + archive 目录路径`,
|
|
161
157
|
outputHint: '归档确认',
|
|
162
158
|
optional: false
|
|
163
159
|
},
|
package/src/stages/verify.js
CHANGED
|
@@ -27,7 +27,7 @@ export const definition = {
|
|
|
27
27
|
### 只允许的操作
|
|
28
28
|
- git status / git diff / git show / git log / git stash list(只读)
|
|
29
29
|
- cat / head / grep / find / wc(只读检查)
|
|
30
|
-
- 写入 .sillyspec/changes/ 下的报告文件(
|
|
30
|
+
- 写入 .sillyspec/changes/ 下的报告文件(verify-result.md)
|
|
31
31
|
- 运行测试命令(不修改源码)
|
|
32
32
|
- 运行 lint 命令(不自动修复)
|
|
33
33
|
|
|
@@ -185,14 +185,14 @@ grep -rl "<关键词>" <源码目录>/ --include="*.java" --include="*.js" --inc
|
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
name: '输出验证报告',
|
|
188
|
-
prompt: `生成完整验证报告,并写入
|
|
188
|
+
prompt: `生成完整验证报告,并写入 verify-result.md。
|
|
189
189
|
|
|
190
190
|
### 操作
|
|
191
191
|
1. 汇总以上所有检查结果
|
|
192
|
-
2. 生成
|
|
192
|
+
2. 生成 verify-result.md 文件,保存到 \`.sillyspec/changes/<change-name>/verify-result.md\`
|
|
193
193
|
3. 给出结论:PASS / PASS WITH NOTES / FAIL
|
|
194
194
|
|
|
195
|
-
###
|
|
195
|
+
### verify-result.md 格式
|
|
196
196
|
\`\`\`markdown
|
|
197
197
|
# 验证报告
|
|
198
198
|
|
|
@@ -221,12 +221,12 @@ PASS / PASS WITH NOTES / FAIL
|
|
|
221
221
|
\`\`\`
|
|
222
222
|
|
|
223
223
|
### 输出
|
|
224
|
-
|
|
224
|
+
verify-result.md 路径 + 验证报告摘要 + 下一步命令
|
|
225
225
|
|
|
226
226
|
### 注意
|
|
227
227
|
- PASS → 运行 \`sillyspec run archive\` 归档
|
|
228
228
|
- FAIL → 修复后运行 \`sillyspec run verify\` 重新验证
|
|
229
|
-
-
|
|
229
|
+
- verify-result.md 是变更包的正式验收记录,归档后保留`,
|
|
230
230
|
outputHint: '验证报告',
|
|
231
231
|
optional: false
|
|
232
232
|
}
|