sillyspec 3.11.2 → 3.11.4

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/run.js +60 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.11.2",
3
+ "version": "3.11.4",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "icon": "logo.jpg",
6
6
  "homepage": "https://sillyspec.ppdmq.top/",
package/src/run.js CHANGED
@@ -144,7 +144,11 @@ function outputStep(stageName, stepIndex, steps, cwd, changeName) {
144
144
  console.log(`step: ${stepIndex + 1}/${total}`)
145
145
  console.log(`stepName: ${step.name}`)
146
146
  console.log(`project: ${projectName}`)
147
- if (changeName) console.log(`change: ${changeName}`)
147
+ if (changeName) {
148
+ console.log(`change: ${changeName}`)
149
+ const changeDir = join('.sillyspec', 'changes', changeName)
150
+ console.log(`changeDir: ${changeDir}`)
151
+ }
148
152
  console.log(`---\n`)
149
153
  if (personas[stageName]) {
150
154
  console.log(personas[stageName])
@@ -160,6 +164,11 @@ function outputStep(stageName, stepIndex, steps, cwd, changeName) {
160
164
  console.log('- 完成后立即执行 --done 命令,不得跳过')
161
165
  console.log('- 文档类型文件(.md/.yaml/.json 等)头部必须包含 author(git 用户名)和 created_at(精确到秒)')
162
166
  console.log('- 执行构建/测试前必须先读 local.yaml,优先使用其中配置的命令、路径和环境变量;未配置时才使用默认值')
167
+ // 路径安全规则:防止 AI 拼错变更目录
168
+ if (changeName) {
169
+ const changeDir = join('.sillyspec', 'changes', changeName)
170
+ console.log(`- **文件路径规则:所有变更文件必须写入 \`${changeDir}/\` 目录下。不要自己拼接路径,直接使用 changeDir 值。示例:\`${changeDir}/proposal.md\`**`)
171
+ }
163
172
  const changeFlag = changeName ? ` --change ${changeName}` : ''
164
173
  console.log(`\n### 完成后执行`)
165
174
  console.log(`sillyspec run ${stageName} --done${changeFlag} --input "用户原始需求/反馈" --output "你的摘要"`)
@@ -368,6 +377,53 @@ function validateMetadata(cwd, stageName) {
368
377
  }
369
378
  }
370
379
 
380
+ /**
381
+ * 验证关键文件是否存在于正确的变更目录下
382
+ * 防止 AI 将文件写到错误的路径
383
+ */
384
+ function validateFileLocations(cwd, stageName, progress, changeName) {
385
+ const effectiveChange = changeName || progress.currentChange
386
+ if (!effectiveChange) return
387
+
388
+ const changeDir = join(cwd, '.sillyspec', 'changes', effectiveChange)
389
+ if (!existsSync(changeDir)) return
390
+
391
+ // 每个阶段完成后预期存在的文件
392
+ const expectedFiles = {
393
+ propose: ['proposal.md', 'design.md', 'requirements.md', 'tasks.md'],
394
+ plan: ['plan.md'],
395
+ verify: ['verify-result.md'],
396
+ archive: ['module-impact.md'],
397
+ }
398
+
399
+ const expected = expectedFiles[stageName]
400
+ if (!expected) return
401
+
402
+ const missing = []
403
+ for (const file of expected) {
404
+ if (!existsSync(join(changeDir, file))) {
405
+ missing.push(file)
406
+ }
407
+ }
408
+
409
+ if (missing.length > 0) {
410
+ console.log(`\n⚠️ 文件位置验证:以下文件未在变更目录中找到`)
411
+ console.log(` 变更目录:${changeDir.replace(cwd + '/', '')}/`)
412
+ for (const f of missing) {
413
+ // 检查是否写到了错误的位置
414
+ const wrongPath = join(cwd, '.sillyspec', 'changes', 'change', effectiveChange, f)
415
+ if (existsSync(wrongPath)) {
416
+ console.log(` ❌ ${f} — 不存在,但发现了错误路径:${wrongPath.replace(cwd + '/', '')}`)
417
+ console.log(` 提示:应该写入 ${changeDir.replace(cwd + '/', '')}/${f}`)
418
+ } else {
419
+ console.log(` ⬜ ${f} — 未找到(该阶段可能未产出此文件)`)
420
+ }
421
+ }
422
+ } else {
423
+ console.log(`\n✅ 文件位置验证:所有 ${expected.length} 个预期文件均在变更目录中`)
424
+ }
425
+ }
426
+
371
427
  async function completeStep(pm, progress, stageName, cwd, outputText, inputText = null, options = {}) {
372
428
  const { printNext = true, confirm = false, changeName } = options
373
429
  const stageData = progress.stages[stageName]
@@ -444,6 +500,9 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
444
500
 
445
501
  validateMetadata(cwd, stageName)
446
502
 
503
+ // 验证关键文件是否在正确的变更目录下
504
+ validateFileLocations(cwd, stageName, progress, changeName)
505
+
447
506
  // archive 阶段确认归档
448
507
  if (stageName === 'archive' && steps[currentIdx]?.name === '确认归档') {
449
508
  if (confirm) {