sillyspec 3.33.9 → 3.34.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.33.9",
3
+ "version": "3.34.0",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "icon": "logo.jpg",
6
6
  "homepage": "https://sillyspec.ppdmq.top/",
@@ -641,6 +641,44 @@ export function distillIntoKnowledge(changeDir, knowledgeRoot, headHash, moduleI
641
641
  if (keep && !taken.has(e.number)) { taken.add(e.number); keep.change = changeName; batch.push(keep) }
642
642
  }
643
643
 
644
+ // 文件字段自动填充(2026-11-03-decision-files-autofill):变更交付面 → 无关联条目的「文件:」字段。
645
+ // 策略:① 条目已有文件字段或有有效锚点 → 不动;② 单决策变更 → 全部交付文件填入(语义成立:
646
+ // 该变更只做了一个决策,交付面即影响面);③ 多决策变更 → 仅填条目正文(答案/理由)中实际
647
+ // 提到的交付文件(信号匹配,防过度关联——方法论决策不对应单一代码位置)。
648
+ // 数据源:change-patch.json 的 files 列表(归档时生成,蒸馏在归档后跑——时序正确)。
649
+ const deliverableFiles = (() => {
650
+ try {
651
+ const patchPath = join(changeDir, 'change-patch.json')
652
+ if (!existsSync(patchPath)) return []
653
+ const patch = JSON.parse(readFileSync(patchPath, 'utf8'))
654
+ return (Array.isArray(patch.files) ? patch.files : []).map(f => String(f).replace(/\\/g, '/')).filter(Boolean)
655
+ } catch { return [] }
656
+ })()
657
+ const noAssociation = batch.filter(e =>
658
+ !(e.files && e.files.length > 0) &&
659
+ !(e.anchor && e.anchor.trim() && e.anchor.trim() !== NOT_RECORDED)
660
+ )
661
+ if (deliverableFiles.length > 0 && noAssociation.length > 0) {
662
+ if (batch.length === 1) {
663
+ // 单决策:全部交付文件
664
+ noAssociation[0].files = deliverableFiles.slice(0, 20)
665
+ console.log(` 📎 文件字段自动填充:单决策变更 ← 交付面 ${deliverableFiles.length} 个文件`)
666
+ } else {
667
+ // 多决策:仅填正文实际提到的
668
+ for (const e of noAssociation) {
669
+ const text = [e.answer, e.reason, e.normalizedRequirement, e.question].join('\n')
670
+ const matched = deliverableFiles.filter(f => text.includes(f))
671
+ if (matched.length > 0) e.files = matched.slice(0, 10)
672
+ }
673
+ const filled = noAssociation.filter(e => e.files && e.files.length > 0).length
674
+ if (filled > 0) console.log(` 📎 文件字段自动填充:${filled}/${noAssociation.length} 条从交付面信号匹配`)
675
+ }
676
+ const still = noAssociation.filter(e => !(e.files && e.files.length > 0))
677
+ if (still.length > 0) {
678
+ console.log(` ⚠️ ${still.length} 条决策无代码关联(无锚点无文件,多决策但正文未提及交付文件)——decisions add 时带 --files 可显式指定`)
679
+ }
680
+ }
681
+
644
682
  const decisionsDir = join(knowledgeRoot, 'decisions')
645
683
  mkdirSync(decisionsDir, { recursive: true })
646
684
  const idx = moduleIndex || discoverModuleIndex(knowledgeRoot)
package/src/index.js CHANGED
@@ -4724,7 +4724,7 @@ SillySpec platform — SillyHub 平台同步
4724
4724
  const decChangeIdx = args.indexOf('--change');
4725
4725
  const decChange = decChangeIdx >= 0 && args[decChangeIdx + 1] && !String(args[decChangeIdx + 1]).startsWith("--") ? args[decChangeIdx + 1] : null;
4726
4726
  if (!decChange || !['add', 'list'].includes(decSub)) {
4727
- console.error('用法: sillyspec decisions add --change <名> --id D-001 --title "…" [--version N] [--status confirmed] [--type architecture] [--domain x(可重复)] [--question/--answer/--anchor/--reject-reason/--revisit-when/--supersedes/--impacts/--note]\n sillyspec decisions list --change <名>');
4727
+ console.error('用法: sillyspec decisions add --change <名> --id D-001 --title "…" [--version N] [--status confirmed] [--type architecture] [--domain x(可重复)] [--question/--answer/--anchor/--files <逗号分隔路径>/--reject-reason/--revisit-when/--supersedes/--impacts/--note]\n sillyspec decisions list --change <名>');
4728
4728
  process.exit(2);
4729
4729
  }
4730
4730
  assertSafeChangeName(decChange, '--change 变更名');
@@ -4765,6 +4765,8 @@ SillySpec platform — SillyHub 平台同步
4765
4765
  question: decFlag('--question') || undefined,
4766
4766
  answer: decFlag('--answer') || undefined,
4767
4767
  anchor: decFlag('--anchor') || undefined,
4768
+ // 文件字段(2026-11-03-decision-files-autofill):逗号分隔路径 → 数组 + POSIX 归一
4769
+ files: decFlag('--files') ? decFlag('--files').split(/[,,、]/).map(s => s.trim().replace(/\\/g, '/')).filter(Boolean) : undefined,
4768
4770
  rejectReason: decFlag('--reject-reason') || undefined,
4769
4771
  revisitWhen: decFlag('--revisit-when') || undefined,
4770
4772
  supersedes: decFlag('--supersedes') || undefined,