soloforge 1.3.0 → 1.3.2

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 (165) hide show
  1. package/README.md +15 -2
  2. package/dist/adapters/claude_code/claude_md.d.ts.map +1 -1
  3. package/dist/adapters/claude_code/claude_md.js +4 -0
  4. package/dist/adapters/claude_code/claude_md.js.map +1 -1
  5. package/dist/adapters/claude_code/tools.d.ts +36 -9
  6. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  7. package/dist/adapters/claude_code/tools.js +828 -19
  8. package/dist/adapters/claude_code/tools.js.map +1 -1
  9. package/dist/adapters/shared/workflow_template.d.ts +26 -0
  10. package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
  11. package/dist/adapters/shared/workflow_template.js +139 -40
  12. package/dist/adapters/shared/workflow_template.js.map +1 -1
  13. package/dist/bin/soloforge.d.ts.map +1 -1
  14. package/dist/bin/soloforge.js +220 -45
  15. package/dist/bin/soloforge.js.map +1 -1
  16. package/dist/engine/architecture_decision_workshop.d.ts +58 -0
  17. package/dist/engine/architecture_decision_workshop.d.ts.map +1 -0
  18. package/dist/engine/architecture_decision_workshop.js +118 -0
  19. package/dist/engine/architecture_decision_workshop.js.map +1 -0
  20. package/dist/engine/asset_manifest.d.ts +7 -1
  21. package/dist/engine/asset_manifest.d.ts.map +1 -1
  22. package/dist/engine/asset_manifest.js +36 -15
  23. package/dist/engine/asset_manifest.js.map +1 -1
  24. package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
  25. package/dist/engine/consumable_asset_registry.js +90 -1
  26. package/dist/engine/consumable_asset_registry.js.map +1 -1
  27. package/dist/engine/consumption_trace_store.d.ts +8 -8
  28. package/dist/engine/consumption_trace_store.d.ts.map +1 -1
  29. package/dist/engine/consumption_trace_store.js +11 -7
  30. package/dist/engine/consumption_trace_store.js.map +1 -1
  31. package/dist/engine/decision_workshop.d.ts +160 -0
  32. package/dist/engine/decision_workshop.d.ts.map +1 -0
  33. package/dist/engine/decision_workshop.js +279 -0
  34. package/dist/engine/decision_workshop.js.map +1 -0
  35. package/dist/engine/design_artifact_pack.d.ts +44 -0
  36. package/dist/engine/design_artifact_pack.d.ts.map +1 -0
  37. package/dist/engine/design_artifact_pack.js +167 -0
  38. package/dist/engine/design_artifact_pack.js.map +1 -0
  39. package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -1
  40. package/dist/engine/dual_layer_mechanism_registry.js +294 -0
  41. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  42. package/dist/engine/evidence_grounding_contract.d.ts +137 -0
  43. package/dist/engine/evidence_grounding_contract.d.ts.map +1 -0
  44. package/dist/engine/evidence_grounding_contract.js +410 -0
  45. package/dist/engine/evidence_grounding_contract.js.map +1 -0
  46. package/dist/engine/explicit_asset_registry.d.ts +30 -0
  47. package/dist/engine/explicit_asset_registry.d.ts.map +1 -0
  48. package/dist/engine/explicit_asset_registry.js +3508 -0
  49. package/dist/engine/explicit_asset_registry.js.map +1 -0
  50. package/dist/engine/implementation_roadmap_registry.d.ts +2 -2
  51. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  52. package/dist/engine/implementation_roadmap_registry.js +163 -6
  53. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  54. package/dist/engine/instruction_contract.d.ts +8 -1
  55. package/dist/engine/instruction_contract.d.ts.map +1 -1
  56. package/dist/engine/instruction_contract.js +63 -1
  57. package/dist/engine/instruction_contract.js.map +1 -1
  58. package/dist/engine/intent_expander.d.ts.map +1 -1
  59. package/dist/engine/intent_expander.js +60 -2
  60. package/dist/engine/intent_expander.js.map +1 -1
  61. package/dist/engine/intent_router.d.ts +1 -1
  62. package/dist/engine/intent_router.d.ts.map +1 -1
  63. package/dist/engine/intent_router.js +2 -1
  64. package/dist/engine/intent_router.js.map +1 -1
  65. package/dist/engine/knowledge_injection_boundary.d.ts +3 -0
  66. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
  67. package/dist/engine/knowledge_injection_boundary.js +48 -5
  68. package/dist/engine/knowledge_injection_boundary.js.map +1 -1
  69. package/dist/engine/mechanism_contract_registry.d.ts +1 -1
  70. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  71. package/dist/engine/mechanism_contract_registry.js +138 -0
  72. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  73. package/dist/engine/observed_consumption.d.ts +54 -0
  74. package/dist/engine/observed_consumption.d.ts.map +1 -0
  75. package/dist/engine/observed_consumption.js +377 -0
  76. package/dist/engine/observed_consumption.js.map +1 -0
  77. package/dist/engine/platform_context.d.ts.map +1 -1
  78. package/dist/engine/platform_context.js +6 -2
  79. package/dist/engine/platform_context.js.map +1 -1
  80. package/dist/engine/release_gate_scenario_registry.d.ts +16 -1
  81. package/dist/engine/release_gate_scenario_registry.d.ts.map +1 -1
  82. package/dist/engine/release_gate_scenario_registry.js +205 -2
  83. package/dist/engine/release_gate_scenario_registry.js.map +1 -1
  84. package/dist/engine/release_issue_scenario_registry.d.ts +64 -0
  85. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -0
  86. package/dist/engine/release_issue_scenario_registry.js +1349 -0
  87. package/dist/engine/release_issue_scenario_registry.js.map +1 -0
  88. package/dist/engine/release_readiness_gate.d.ts +8 -0
  89. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  90. package/dist/engine/release_readiness_gate.js +1144 -6
  91. package/dist/engine/release_readiness_gate.js.map +1 -1
  92. package/dist/engine/release_tool_harness.d.ts +71 -0
  93. package/dist/engine/release_tool_harness.d.ts.map +1 -0
  94. package/dist/engine/release_tool_harness.js +161 -0
  95. package/dist/engine/release_tool_harness.js.map +1 -0
  96. package/dist/engine/scaffolder.d.ts.map +1 -1
  97. package/dist/engine/scaffolder.js +144 -7
  98. package/dist/engine/scaffolder.js.map +1 -1
  99. package/dist/engine/standard_asset_contract.d.ts +75 -0
  100. package/dist/engine/standard_asset_contract.d.ts.map +1 -0
  101. package/dist/engine/standard_asset_contract.js +388 -0
  102. package/dist/engine/standard_asset_contract.js.map +1 -0
  103. package/dist/engine/standard_asset_coverage.d.ts +45 -0
  104. package/dist/engine/standard_asset_coverage.d.ts.map +1 -0
  105. package/dist/engine/standard_asset_coverage.js +220 -0
  106. package/dist/engine/standard_asset_coverage.js.map +1 -0
  107. package/dist/engine/task_context.d.ts +9 -2
  108. package/dist/engine/task_context.d.ts.map +1 -1
  109. package/dist/engine/task_context.js +49 -12
  110. package/dist/engine/task_context.js.map +1 -1
  111. package/dist/engine/template_asset_contract_registry.d.ts +162 -0
  112. package/dist/engine/template_asset_contract_registry.d.ts.map +1 -0
  113. package/dist/engine/template_asset_contract_registry.js +598 -0
  114. package/dist/engine/template_asset_contract_registry.js.map +1 -0
  115. package/dist/engine/template_asset_visibility.d.ts +109 -0
  116. package/dist/engine/template_asset_visibility.d.ts.map +1 -0
  117. package/dist/engine/template_asset_visibility.js +321 -0
  118. package/dist/engine/template_asset_visibility.js.map +1 -0
  119. package/dist/engine/template_init_sync.d.ts +68 -0
  120. package/dist/engine/template_init_sync.d.ts.map +1 -0
  121. package/dist/engine/template_init_sync.js +218 -0
  122. package/dist/engine/template_init_sync.js.map +1 -0
  123. package/dist/engine/template_manifest_io.d.ts +10 -0
  124. package/dist/engine/template_manifest_io.d.ts.map +1 -1
  125. package/dist/engine/template_manifest_io.js +63 -30
  126. package/dist/engine/template_manifest_io.js.map +1 -1
  127. package/dist/engine/template_mechanism_auditor.d.ts +3 -1
  128. package/dist/engine/template_mechanism_auditor.d.ts.map +1 -1
  129. package/dist/engine/template_mechanism_auditor.js +27 -24
  130. package/dist/engine/template_mechanism_auditor.js.map +1 -1
  131. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
  132. package/dist/engine/tool_invocation_contract_registry.js +11 -1
  133. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  134. package/dist/engine/verifier.d.ts.map +1 -1
  135. package/dist/engine/verifier.js +3 -40
  136. package/dist/engine/verifier.js.map +1 -1
  137. package/dist/engine/workflow_contract_registry.d.ts.map +1 -1
  138. package/dist/engine/workflow_contract_registry.js +4 -3
  139. package/dist/engine/workflow_contract_registry.js.map +1 -1
  140. package/dist/knowledge/index_manager.d.ts +20 -0
  141. package/dist/knowledge/index_manager.d.ts.map +1 -1
  142. package/dist/knowledge/index_manager.js +234 -3
  143. package/dist/knowledge/index_manager.js.map +1 -1
  144. package/dist/types.d.ts +47 -0
  145. package/dist/types.d.ts.map +1 -1
  146. package/package.json +5 -4
  147. package/templates/knowledge/acceptance_templates/API/346/216/245/345/217/243/350/247/204/346/240/274/346/226/207/346/241/243/346/250/241/347/211/210.md +74 -0
  148. package/templates/knowledge/acceptance_templates//346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/346/226/207/346/241/243/346/250/241/347/211/210.md +59 -0
  149. package/templates/knowledge/acceptance_templates//346/236/266/346/236/204/350/256/276/350/256/241/346/250/241/347/211/210.md +27 -7
  150. package/templates/knowledge/acceptance_templates//350/256/276/350/256/241/344/270/200/350/207/264/346/200/247/351/252/214/346/224/266/346/212/245/345/221/212/346/250/241/347/211/210.md +47 -0
  151. package/templates/knowledge/procedures//346/236/266/346/236/204/345/206/263/347/255/226/347/240/224/350/256/250/345/267/245/344/275/234/346/265/201.md +51 -0
  152. package/templates/knowledge/procedures//346/236/266/346/236/204/350/256/276/350/256/241/345/267/245/344/275/234/346/265/201.md +16 -7
  153. package/templates/knowledge/procedures//350/256/276/350/256/241/344/272/247/347/211/251/347/224/237/346/210/220/344/270/216/345/244/215/351/252/214/345/267/245/344/275/234/346/265/201.md +45 -0
  154. package/templates/knowledge/rules//345/267/245/344/275/234/346/265/201/346/250/241/346/235/277/345/214/205/350/247/204/345/210/231.md +10 -0
  155. package/templates/knowledge/rules//346/211/251/345/261/225/347/224/237/345/221/275/345/221/250/346/234/237/350/247/204/345/210/231.md +10 -0
  156. package/templates/knowledge/rules//346/226/275/345/267/245/346/214/207/344/273/244/345/245/221/347/272/246/350/247/204/345/210/231.md +33 -4
  157. package/templates/knowledge/rules//346/236/266/346/236/204/345/206/263/347/255/226/347/240/224/350/256/250/350/247/204/345/210/231.md +49 -0
  158. package/templates/knowledge/rules//346/240/207/345/207/206/350/265/204/344/272/247/350/246/206/347/233/226/350/247/204/345/210/231.md +29 -0
  159. package/templates/knowledge/rules//346/250/241/346/235/277/350/265/204/344/272/247/345/217/257/350/247/201/346/200/247/350/247/204/345/210/231.md +27 -0
  160. package/templates/knowledge/rules//347/224/250/346/210/267/345/217/215/351/246/210/345/245/221/347/272/246/350/247/204/345/210/231.md +62 -1
  161. package/templates/knowledge/rules//350/256/276/350/256/241/344/272/247/347/211/251/345/214/205/350/247/204/345/210/231.md +55 -0
  162. package/templates/knowledge/rules//350/257/201/346/215/256/351/251/261/345/212/250/344/270/216/345/217/215/345/271/273/350/247/211/350/247/204/345/210/231.md +75 -0
  163. package/templates/knowledge/rules//350/267/250/345/271/263/345/217/260/350/267/257/345/276/204/345/256/211/345/205/250/350/247/204/345/210/231.md +10 -0
  164. package/templates/knowledge/rules//351/200/232/347/224/250/345/206/263/347/255/226/347/240/224/350/256/250/350/247/204/345/210/231.md +30 -0
  165. package/templates/knowledge/rules//351/252/214/346/224/266/346/250/241/346/235/277/350/276/223/345/207/272/345/245/221/347/272/246/350/247/204/345/210/231.md +50 -0
@@ -1,55 +1,154 @@
1
1
  import { debug } from "../../engine/logger.js";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import crypto from "node:crypto";
5
+ import { findLayerMapByMechanismId } from "../../engine/dual_layer_mechanism_registry.js";
6
+ import { WORKFLOW_TEMPLATE_HARD_RULES } from "../../engine/asset_manifest.js";
7
+ const SF_HARD_RULE_RE = /@sf-hard-rule[^>]*mechanism=(\S+)/g;
8
+ /** 从结构化清单生成 @sf-hard-rule 标记 */
9
+ function hardRuleTag(ruleId) {
10
+ const rule = WORKFLOW_TEMPLATE_HARD_RULES.find(r => r.rule_id === ruleId);
11
+ if (!rule)
12
+ return `<!-- @sf-hard-rule id=${ruleId} MISSING_IN_MANIFEST -->`;
13
+ return `<!-- @sf-hard-rule id=${rule.rule_id} mechanism=${rule.mechanism_id} enforcement=${rule.enforcement_status} summary="${rule.rule_summary}" -->`;
14
+ }
15
+ /** 渲染一条规则的 marker + user_instruction */
16
+ function renderRule(ruleId) {
17
+ const rule = WORKFLOW_TEMPLATE_HARD_RULES.find(r => r.rule_id === ruleId);
18
+ const tag = hardRuleTag(ruleId);
19
+ const text = rule?.user_instruction ?? "";
20
+ if (text)
21
+ return `${tag}\n${text}`;
22
+ return tag;
23
+ }
24
+ /** 渲染一组规则(marker + user_instruction) */
25
+ function renderRules(ruleIds) {
26
+ return ruleIds.map(id => renderRule(id)).join("\n");
27
+ }
28
+ /** 工作流步骤定义: 每步包含标题和有序规则 ID */
29
+ const WORKFLOW_STEPS = [
30
+ { title: "", rule_ids: ["wf-privacy-before-expand", "wf-knowledge-injection", "wf-core-principles"] },
31
+ { title: "### 步骤 1: 分类", rule_ids: ["wf-classify-first"] },
32
+ { title: "### 步骤 1.5: 入口裁决", rule_ids: ["wf-routing-gate", "wf-strategy-no-route"] },
33
+ { title: "### 步骤 1.6: 多阶段拆解", rule_ids: ["wf-multi-stage-loop"] },
34
+ { title: "### 步骤 2: 执行", rule_ids: ["wf-dispatch-by-route", "wf-command-contract", "wf-tool-contract", "wf-architecture-workshop-first", "wf-design-artifact-pack", "wf-standard-asset-contract", "wf-template-asset-visibility"] },
35
+ { title: "### 步骤 3: 验证", rule_ids: ["wf-verify-after-change", "wf-evidence-grounding"] },
36
+ { title: "### 步骤 4: 学习", rule_ids: ["wf-learn-after-verify"] },
37
+ { title: "### 步骤 5: 汇报", rule_ids: ["wf-no-auto-capability-change"] },
38
+ ];
39
+ /**
40
+ * 计算所有权威规则资产的第一行非注释内容组合的 SHA256 校验和。
41
+ * 权威规则内容变化时校验和必然变化。
42
+ */
43
+ export function computeAuthoritativeRulesChecksum(rootDir) {
44
+ const mechanismIds = getWorkflowRuleMechanismIds();
45
+ const parts = [];
46
+ for (const mid of mechanismIds) {
47
+ const map = findLayerMapByMechanismId(mid);
48
+ if (!map?.template_assets)
49
+ continue;
50
+ for (const asset of map.template_assets) {
51
+ const fullPath = path.join(rootDir, asset.path);
52
+ if (!fs.existsSync(fullPath))
53
+ continue;
54
+ const content = fs.readFileSync(fullPath, "utf-8");
55
+ // 取前 200 字符(去掉 frontmatter 后的首段)作为校验依据
56
+ const bodyStart = content.indexOf("---", content.indexOf("---") + 3);
57
+ const body = bodyStart >= 0 ? content.substring(bodyStart + 3).trimStart() : content;
58
+ parts.push(`${asset.path}:${body.substring(0, 500)}`);
59
+ }
60
+ }
61
+ return crypto.createHash("sha256").update(parts.join("\n")).digest("hex").substring(0, 16);
62
+ }
63
+ /**
64
+ * 提取 generateWorkflowRules 输出中所有 @sf-hard-rule 引用的机制 ID(去重)。
65
+ */
66
+ export function getWorkflowRuleMechanismIds() {
67
+ const text = generateWorkflowRules({});
68
+ const ids = new Set();
69
+ let m;
70
+ while ((m = SF_HARD_RULE_RE.exec(text)) !== null) {
71
+ ids.add(m[1]);
72
+ }
73
+ return [...ids];
74
+ }
75
+ /**
76
+ * 校验工作流模板中每条 @sf-hard-rule 都能找到权威机制注册条目,
77
+ * 且其 template_layer 资产文件存在,且内容校验和与嵌入值一致。
78
+ */
79
+ export function validateWorkflowRuleSources(rootDir) {
80
+ const mechanismIds = getWorkflowRuleMechanismIds();
81
+ const missing_mechanisms = [];
82
+ const missing_assets = [];
83
+ for (const mid of mechanismIds) {
84
+ const map = findLayerMapByMechanismId(mid);
85
+ if (!map) {
86
+ missing_mechanisms.push(mid);
87
+ continue;
88
+ }
89
+ if (map.template_assets) {
90
+ for (const asset of map.template_assets) {
91
+ if (!fs.existsSync(path.join(rootDir, asset.path))) {
92
+ missing_assets.push(asset.path);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ // 内容校验和验证
98
+ const computedChecksum = computeAuthoritativeRulesChecksum(rootDir);
99
+ const embeddedChecksum = getEmbeddedChecksum();
100
+ const checksumMismatch = computedChecksum !== embeddedChecksum;
101
+ return {
102
+ valid: missing_mechanisms.length === 0 && missing_assets.length === 0 && !checksumMismatch,
103
+ missing_mechanisms,
104
+ missing_assets,
105
+ checksum_mismatch: checksumMismatch,
106
+ embedded_checksum: embeddedChecksum,
107
+ computed_checksum: computedChecksum,
108
+ };
109
+ }
110
+ /** 当前嵌入的权威规则校验和 — 由 `npm run update-workflow-checksum` 更新。 */
111
+ const EMBEDDED_CHECKSUM = "a875189c510913ff";
112
+ function getEmbeddedChecksum() {
113
+ return EMBEDDED_CHECKSUM;
114
+ }
115
+ /**
116
+ * 更新嵌入校验和到源文件。由 CI 或开发者在确认权威规则变化后调用。
117
+ */
118
+ export function updateEmbeddedChecksum(rootDir) {
119
+ const newChecksum = computeAuthoritativeRulesChecksum(rootDir);
120
+ const selfPath = path.join(rootDir, "src", "adapters", "shared", "workflow_template.ts");
121
+ if (fs.existsSync(selfPath)) {
122
+ let content = fs.readFileSync(selfPath, "utf-8");
123
+ content = content.replace(/const EMBEDDED_CHECKSUM = "[^"]*";/, `const EMBEDDED_CHECKSUM = "${newChecksum}";`);
124
+ fs.writeFileSync(selfPath, content, "utf-8");
125
+ }
126
+ return newChecksum;
127
+ }
2
128
  /**
3
129
  * 生成工作流规则模板内容。
130
+ * 从 WORKFLOW_TEMPLATE_HARD_RULES 结构化清单循环渲染每条规则的 marker + user_instruction。
4
131
  * @param config - 项目配置
5
132
  * @returns 工作流规则文本
6
133
  */
7
134
  export function generateWorkflowRules(config) {
8
135
  debug("工作流模板", "生成工作流规则");
9
- return `# SoloForge 集成规则
136
+ const header = `# SoloForge 集成规则
10
137
 
11
138
  ## 强制工作流
12
139
 
13
- 当收到开发指令时(非纯对话/提问),必须按以下顺序执行:
14
-
15
- <!-- @sf-hard-rule id=wf-privacy-before-expand mechanism=mc-privacy-boundary enforcement=enforced -->
16
- <!-- @sf-hard-rule id=wf-knowledge-injection mechanism=mc-knowledge-injection-boundary enforcement=enforced -->
17
- <!-- @sf-hard-rule id=wf-core-principles mechanism=mc-core-engineering-principles enforcement=enforced -->
18
- ### 步骤 1: 分类
19
- <!-- @sf-hard-rule id=wf-classify-first mechanism=mc-workflow-contract enforcement=enforced -->
20
- 调用 \`sf_classify\` 分类。
21
-
22
- <!-- @sf-hard-rule id=wf-routing-gate mechanism=mc-workflow-contract enforcement=enforced -->
23
- ### 步骤 1.5: 入口裁决
24
- 按分类结果 \`route_decision\` 字段分发。详见知识库路由规则。
25
-
26
- <!-- @sf-hard-rule id=wf-strategy-no-route mechanism=mc-workflow-contract enforcement=enforced -->
27
- \`strategy\` 仅兼容展示,不作为入口裁决。
28
-
29
- <!-- @sf-hard-rule id=wf-multi-stage-loop mechanism=mc-workflow-contract enforcement=enforced -->
30
- ### 步骤 1.6: 多阶段拆解
31
- \`execution_shape=multi_stage_plan\` 时: \`sf_plan\` → \`sf_expand\` → 执行 → \`sf_plan_advance\` → 循环。
32
-
33
- <!-- @sf-hard-rule id=wf-dispatch-by-route mechanism=mc-workflow-contract enforcement=enforced -->
34
- <!-- @sf-hard-rule id=wf-command-contract mechanism=mc-command-execution enforcement=enforced -->
35
- <!-- @sf-hard-rule id=wf-tool-contract mechanism=mc-tool-invocation-contract enforcement=enforced -->
36
- ### 步骤 2: 执行
37
- 按分类结果调用对应工具。详见知识库流程。
38
-
39
- <!-- @sf-hard-rule id=wf-verify-after-change mechanism=mc-verifier enforcement=enforced -->
40
- ### 步骤 3: 验证
41
- 代码修改后调用 \`sf_verify\` 并执行返回的验证命令。
42
-
43
- <!-- @sf-hard-rule id=wf-learn-after-verify mechanism=mc-task-context-lifecycle enforcement=enforced -->
44
- ### 步骤 4: 学习
45
- 验证后调用 \`sf_learn\`。若有 \`retry_hint\` 回到步骤 3。
46
-
47
- <!-- @sf-hard-rule id=wf-no-auto-capability-change mechanism=mc-guard-evaluation enforcement=enforced -->
48
- ### 步骤 5: 汇报
49
- 展示验证摘要和验收结果。
140
+ 当收到开发指令时(非纯对话/提问),必须按以下顺序执行:`;
141
+ const sections = WORKFLOW_STEPS.map(step => {
142
+ const rulesText = renderRules(step.rule_ids);
143
+ if (step.title)
144
+ return `${step.title}\n${rulesText}`;
145
+ return rulesText;
146
+ }).join("\n\n");
147
+ const footer = `## 项目信息
50
148
 
51
- ## 项目信息
149
+ 项目事实以 config 配置及 tool 输出为准,不在模板中硬编码。
52
150
 
53
- 项目事实以 config 配置及 tool 输出为准,不在模板中硬编码。`;
151
+ <!-- @sf-checksum: ${EMBEDDED_CHECKSUM} -->`;
152
+ return `${header}\n\n${sections}\n\n${footer}`;
54
153
  }
55
154
  //# sourceMappingURL=workflow_template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow_template.js","sourceRoot":"","sources":["../../../src/adapters/shared/workflow_template.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IACzD,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC1B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA4C4B,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"workflow_template.js","sourceRoot":"","sources":["../../../src/adapters/shared/workflow_template.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"soloforge.d.ts","sourceRoot":"","sources":["../../src/bin/soloforge.ts"],"names":[],"mappings":";AAgxBA,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAC"}
1
+ {"version":3,"file":"soloforge.d.ts","sourceRoot":"","sources":["../../src/bin/soloforge.ts"],"names":[],"mappings":";AA6yBA,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAC"}
@@ -60,6 +60,12 @@ async function main() {
60
60
  case "audit-template-mechanisms":
61
61
  await cmdAuditTemplateMechanisms();
62
62
  break;
63
+ case "audit-design-artifacts":
64
+ await cmdAuditDesignArtifacts();
65
+ break;
66
+ case "upgrade-design-artifacts":
67
+ await cmdUpgradeDesignArtifacts();
68
+ break;
63
69
  case "validate-batch1":
64
70
  userWarn("⚠️ validate-batch1 是历史施工命令,不代表正式发布通过。请使用 validate-release。");
65
71
  await cmdValidateFoundation();
@@ -75,6 +81,9 @@ async function main() {
75
81
  case "validate-release":
76
82
  await cmdValidateReleaseGate();
77
83
  break;
84
+ case "audit-template-visibility":
85
+ await cmdAuditTemplateVisibility();
86
+ break;
78
87
  case "sync-templates":
79
88
  await cmdSyncTemplates();
80
89
  break;
@@ -149,6 +158,8 @@ async function main() {
149
158
  validate 验证项目配置和知识文件(config.yaml 可选,缺失时自动推断)
150
159
  validate-mechanisms 验证双层机制承载模型完整性(模板层 + 机制层)
151
160
  audit-template-mechanisms 扫描模板与机制注册表交叉校验(--json 输出完整报告,--changed-only 仅检查变更文件)
161
+ audit-design-artifacts 审计架构/数据库/API 设计产物包(只读,--json 输出报告)
162
+ upgrade-design-artifacts 生成存量设计资产升级计划(默认 dry-run,--apply --confirm 仅建立已归档迁移基线)
152
163
  validate-release 验证发布门禁(契约、场景矩阵、消费 trace、双层机制、回归基线)
153
164
  validate-batch1 [历史] 仅基础契约验证,不代表正式发布通过
154
165
  validate-batch3 [历史] 仅知识模板验证,不代表正式发布通过
@@ -452,45 +463,32 @@ async function cmdInit() {
452
463
  "请打开 Claude Code 开始使用。"}`);
453
464
  }
454
465
  async function copyGlobalPatterns(projectPath) {
466
+ const { copyPatternsToGlobal } = await import("../engine/template_init_sync.js");
455
467
  const globalDir = getGlobalPatternsDir();
456
- fss.mkdirSync(globalDir, { recursive: true });
457
- const templatesDir = path.resolve(import.meta.dirname, "..", "..", "templates", "patterns");
458
- if (fss.existsSync(templatesDir)) {
459
- const files = fss.readdirSync(templatesDir).filter((f) => f.endsWith(".md"));
460
- for (const f of files) {
461
- const src = path.join(templatesDir, f);
462
- const dest = path.join(globalDir, f);
463
- if (!fss.existsSync(dest)) {
464
- fss.copyFileSync(src, dest);
465
- }
466
- }
467
- userInfo(`✅ ${files.length} 个默认模板已复制到 ~/.soloforge/patterns/`);
468
+ const templatesRoot = path.resolve(import.meta.dirname, "..", "..");
469
+ const result = await copyPatternsToGlobal(templatesRoot, globalDir);
470
+ const parts = [];
471
+ if (result.copied > 0)
472
+ parts.push(`新增 ${result.copied} 个`);
473
+ if (result.skipped > 0)
474
+ parts.push(`跳过 ${result.skipped} 个(已存在)`);
475
+ if (parts.length > 0) {
476
+ userInfo(`✅ 全局模板 ~/.soloforge/patterns/: ${parts.join(",")}`);
468
477
  }
469
478
  }
470
479
  async function copyKnowledgeTemplates(projectPath) {
471
- const knowledgeTemplatesDir = path.resolve(import.meta.dirname, "..", "..", "templates", "knowledge");
472
- if (fss.existsSync(knowledgeTemplatesDir)) {
473
- const subDirs = ["procedures", "domain", "product_profiles", "acceptance_templates", "review_rules", "patterns/core", "checklists", "templates"];
474
- let copiedCount = 0;
475
- for (const subDir of subDirs) {
476
- const srcDir = path.join(knowledgeTemplatesDir, subDir);
477
- if (!fss.existsSync(srcDir))
478
- continue;
479
- const destDir = path.join(projectPath, ".soloforge", "knowledge", subDir);
480
- fss.mkdirSync(destDir, { recursive: true });
481
- const files = fss.readdirSync(srcDir).filter((f) => f.endsWith(".md") || f.endsWith(".yaml") || f.endsWith(".yml"));
482
- for (const f of files) {
483
- const src = path.join(srcDir, f);
484
- const dest = path.join(destDir, f);
485
- if (!fss.existsSync(dest)) {
486
- fss.copyFileSync(src, dest);
487
- copiedCount++;
488
- }
489
- }
490
- }
491
- if (copiedCount > 0) {
492
- userInfo(`✅ ${copiedCount} 个知识模板已复制到 .soloforge/knowledge/`);
493
- }
480
+ const { copyKnowledgeToProject } = await import("../engine/template_init_sync.js");
481
+ const templatesRoot = path.resolve(import.meta.dirname, "..", "..");
482
+ const result = await copyKnowledgeToProject(templatesRoot, projectPath);
483
+ const parts = [];
484
+ if (result.copied > 0)
485
+ parts.push(`${result.copied} 个已复制`);
486
+ if (result.skipped_internal > 0)
487
+ parts.push(`${result.skipped_internal} 个内部资产已跳过`);
488
+ if (result.skipped_no_contract > 0)
489
+ parts.push(`${result.skipped_no_contract} 个无合同已跳过`);
490
+ if (parts.length > 0) {
491
+ userInfo(`✅ 知识模板: ${parts.join(",")}`);
494
492
  }
495
493
  }
496
494
  async function generateAdapterConfigs(projectPath, adapter) {
@@ -627,16 +625,24 @@ async function cmdCheckWrite() {
627
625
  }
628
626
  // 加载配置
629
627
  const projectPath = resolveProjectPath();
630
- const { config } = await resolveProjectConfig(projectPath);
628
+ const { config, source } = await resolveProjectConfig(projectPath);
631
629
  // 从配置中收集所有允许路径
632
- const allowedPaths = [
630
+ let allowedPaths = [
633
631
  ...(config.scope.backend || []),
634
632
  ...(config.scope.frontend || []),
635
633
  ...config.repos.flatMap((r) => r.scope || []),
636
634
  ].map((p) => path.resolve(projectPath, p));
635
+ if (source === "inferred" || allowedPaths.length === 0) {
636
+ allowedPaths = [...new Set([...allowedPaths, projectPath])];
637
+ }
637
638
  // 使用 scope_controller 统一检查
638
639
  const { checkScope } = await import("../engine/scope_controller.js");
639
- const result = checkScope(filePath, allowedPaths, content || undefined);
640
+ const rawTargetFilePath = path.isAbsolute(filePath) ? filePath : path.resolve(projectPath, filePath);
641
+ const projectRealPath = fss.realpathSync(projectPath);
642
+ const targetFilePath = rawTargetFilePath === projectPath || rawTargetFilePath.startsWith(projectPath + path.sep)
643
+ ? path.join(projectRealPath, path.relative(projectPath, rawTargetFilePath))
644
+ : rawTargetFilePath;
645
+ const result = checkScope(targetFilePath, allowedPaths, content || undefined);
640
646
  // 隐私/秘密契约:禁止读取的模式
641
647
  if (isReadForbidden(filePath)) {
642
648
  process.stdout.write(JSON.stringify({
@@ -662,6 +668,31 @@ async function cmdCheckWrite() {
662
668
  if (result.severity === "warning") {
663
669
  jsonSafeError(JSON.stringify(result));
664
670
  }
671
+ // 问题六十二: Claude Code 直接 Edit/Write 也必须遵守设计产物就绪门。
672
+ // 设计资产本身允许继续修订;非设计文件在产物包复验通过前禁止写入。
673
+ const relativeFilePath = path.relative(projectRealPath, targetFilePath).replaceAll(path.sep, "/");
674
+ const isDesignArtifactFile = /^docs\/architecture\//.test(relativeFilePath) ||
675
+ /^docs\/api\/openapi\.(?:ya?ml|json)$/.test(relativeFilePath) ||
676
+ /^db\/(?:migrations|schema)\//.test(relativeFilePath);
677
+ if (!isDesignArtifactFile) {
678
+ const { TaskContextManager } = await import("../engine/task_context.js");
679
+ const stateDir = path.join(projectPath, ".soloforge", "state");
680
+ if (fss.existsSync(stateDir)) {
681
+ const manager = new TaskContextManager(stateDir);
682
+ const currentTask = await manager.getCurrentTask();
683
+ const designPack = currentTask?.design_artifact_pack;
684
+ if (designPack && designPack.status !== "implementation_ready") {
685
+ process.stdout.write(JSON.stringify({
686
+ hookSpecificOutput: {
687
+ hookEventName: "PreToolUse",
688
+ permissionDecision: "deny",
689
+ permissionDecisionReason: `设计产物包状态为 ${designPack.status},请先完善 docs/architecture、docs/api/openapi 或 db/migrations|schema 并通过复验,再写入业务实现`,
690
+ },
691
+ }));
692
+ process.exit(0);
693
+ }
694
+ }
695
+ }
665
696
  process.exit(0); // 允许
666
697
  }
667
698
  catch (e) {
@@ -818,8 +849,7 @@ async function cmdValidate() {
818
849
  try {
819
850
  const { config, source } = await resolveProjectConfig(projectPath);
820
851
  if (source === "inferred") {
821
- userInfo("ℹ️ 未找到 .soloforge/config.yaml — 使用自动推断的配置。");
822
- userInfo(" 运行 'soloforge init --auto' 可持久化。");
852
+ userInfo("ℹ️ 配置来源: 自动推断");
823
853
  }
824
854
  else {
825
855
  userInfo("✅ config.yaml 有效");
@@ -1240,6 +1270,97 @@ async function cmdAuditTemplateMechanisms() {
1240
1270
  process.exit(1);
1241
1271
  }
1242
1272
  }
1273
+ async function cmdAuditDesignArtifacts() {
1274
+ debug("CLI", "执行 cmdAuditDesignArtifacts");
1275
+ const isJson = args.includes("--json");
1276
+ const projectPath = resolveProjectPath();
1277
+ const { createDesignArtifactPack, verifyDesignArtifactPack } = await import("../engine/design_artifact_pack.js");
1278
+ const contract = createDesignArtifactPack("design-artifact-audit-cli");
1279
+ const result = verifyDesignArtifactPack(projectPath, contract);
1280
+ if (isJson) {
1281
+ userInfo(JSON.stringify({ command: "audit-design-artifacts", project_path: projectPath, ...result }, null, 2));
1282
+ }
1283
+ else {
1284
+ userInfo(`设计产物包审计: ${projectPath}`);
1285
+ userInfo(` 状态: ${result.status}`);
1286
+ userInfo(` 已检查文件: ${result.checked_files.length}`);
1287
+ userInfo(` hard_fail: ${result.findings.filter((finding) => finding.severity === "hard_fail").length}`);
1288
+ for (const finding of result.findings) {
1289
+ userInfo(` ${finding.severity === "hard_fail" ? "❌" : "⚠️"} [${finding.code}] ${finding.message_zh}`);
1290
+ }
1291
+ if (result.passed)
1292
+ userInfo("✅ 设计产物包复验通过,可作为后续实现输入");
1293
+ }
1294
+ if (!result.passed)
1295
+ process.exit(1);
1296
+ }
1297
+ /**
1298
+ * 存量设计资产升级只负责安全建立复验基线与归档原文。
1299
+ * 修正文档内容仍须经 AI 草案和用户确认后写入,再由 audit 命令真实复验。
1300
+ */
1301
+ async function cmdUpgradeDesignArtifacts() {
1302
+ debug("CLI", "执行 cmdUpgradeDesignArtifacts");
1303
+ const apply = args.includes("--apply");
1304
+ const confirm = args.includes("--confirm");
1305
+ const isJson = args.includes("--json");
1306
+ const projectPath = resolveProjectPath();
1307
+ const { createDesignArtifactPack, verifyDesignArtifactPack } = await import("../engine/design_artifact_pack.js");
1308
+ const contract = createDesignArtifactPack("design-artifact-upgrade-cli");
1309
+ const audit = verifyDesignArtifactPack(projectPath, contract);
1310
+ const presentFiles = audit.checked_files.filter((relativePath) => fss.existsSync(path.join(projectPath, relativePath)));
1311
+ const output = {
1312
+ command: "upgrade-design-artifacts",
1313
+ mode: apply ? "apply" : "dry_run",
1314
+ status: audit.passed ? "implementation_ready" : "needs_revalidation",
1315
+ present_files: presentFiles,
1316
+ findings: audit.findings,
1317
+ next_steps: audit.passed
1318
+ ? ["设计产物已符合当前标准,无需覆盖现有文件"]
1319
+ : ["保留原文归档", "基于 findings 生成修订草案", "用户确认后写入修订文档/OpenAPI/SQL", "重新执行 audit-design-artifacts"],
1320
+ };
1321
+ if (!apply) {
1322
+ if (isJson)
1323
+ userInfo(JSON.stringify(output, null, 2));
1324
+ else {
1325
+ userInfo("设计产物升级计划: dry-run(不会修改现有文档)");
1326
+ userInfo(` 当前状态: ${output.status}`);
1327
+ userInfo(` 已发现现有资产: ${presentFiles.length}`);
1328
+ userInfo(` 待修复项: ${audit.findings.length}`);
1329
+ userInfo(" 使用 --apply --confirm 仅归档现有基线并登记 needs_revalidation;修订内容仍须用户确认。");
1330
+ }
1331
+ return;
1332
+ }
1333
+ if (!confirm) {
1334
+ userError("❌ upgrade-design-artifacts --apply 必须同时提供 --confirm,禁止静默改写或归档现有设计文档");
1335
+ process.exit(1);
1336
+ }
1337
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
1338
+ const archiveDir = path.join(projectPath, ".soloforge", "design-artifacts", "archive", timestamp);
1339
+ fss.mkdirSync(archiveDir, { recursive: true });
1340
+ for (const relativePath of presentFiles) {
1341
+ const target = path.join(archiveDir, relativePath);
1342
+ fss.mkdirSync(path.dirname(target), { recursive: true });
1343
+ fss.copyFileSync(path.join(projectPath, relativePath), target);
1344
+ }
1345
+ const contractDir = path.join(projectPath, ".soloforge", "design-artifacts");
1346
+ fss.mkdirSync(contractDir, { recursive: true });
1347
+ fss.writeFileSync(path.join(contractDir, "upgrade-contract.json"), JSON.stringify({
1348
+ ...contract,
1349
+ status: audit.passed ? "implementation_ready" : "needs_revalidation",
1350
+ baseline_hashes: audit.hashes,
1351
+ findings: audit.findings,
1352
+ verified_at: new Date().toISOString(),
1353
+ archive_dir: path.relative(projectPath, archiveDir),
1354
+ write_policy: "原文仅归档;修订文档须由用户确认后另行写入并重新复验",
1355
+ }, null, 2), "utf-8");
1356
+ const appliedOutput = { ...output, archive_dir: path.relative(projectPath, archiveDir), original_documents_overwritten: false };
1357
+ if (isJson)
1358
+ userInfo(JSON.stringify(appliedOutput, null, 2));
1359
+ else {
1360
+ userInfo(`✅ 已归档现有设计基线: ${appliedOutput.archive_dir}`);
1361
+ userInfo(" 未覆盖现有设计文档;请确认修订草案后重新执行复验。");
1362
+ }
1363
+ }
1243
1364
  async function cmdValidateKnowledge() {
1244
1365
  debug("CLI", "执行 cmdValidateKnowledge");
1245
1366
  const { validateContractRegistry } = await import("../engine/contract_registry.js");
@@ -1447,14 +1568,14 @@ async function cmdSyncTemplates() {
1447
1568
  else {
1448
1569
  userInfo(apply ? "模板同步: apply 模式" : "模板同步: dry-run 模式(不写入文件)");
1449
1570
  userInfo(` 资产总数: ${assets.length}`);
1450
- userInfo(` 安全检查: ${safeCheck.safe ? "" : ""}`);
1571
+ userInfo(` 应用安全: ${safeCheck.safe ? "安全" : "需确认"}`);
1451
1572
  userInfo(` 结果: ${syncResult.success ? "成功" : "失败"}`);
1452
1573
  userInfo(` 新增: ${syncResult.report.added.length}`);
1453
1574
  userInfo(` 更新: ${syncResult.report.updated.length}`);
1454
1575
  userInfo(` 跳过(用户修改): ${syncResult.report.skipped_user_modified.length}`);
1455
1576
  userInfo(` 废弃: ${syncResult.report.deprecated.length}`);
1456
1577
  if (!apply)
1457
- userInfo(" 使用 --apply --confirm 应用同步");
1578
+ userInfo(" 使用 --apply --confirm 应用同步;需确认表示 dry-run 发现现有用户资产,不会自动覆盖");
1458
1579
  }
1459
1580
  if (!syncResult.success)
1460
1581
  process.exit(1);
@@ -1830,8 +1951,8 @@ async function cmdValidateNewIssue() {
1830
1951
  userInfo(JSON.stringify(output, null, 2));
1831
1952
  }
1832
1953
  else {
1833
- userInfo(`问题演进门控: ${output.gate_status}`);
1834
- userInfo(` 已检查 ${allProblems.length} 个既有问题`);
1954
+ userInfo(`需求演进检查: ${output.gate_status}`);
1955
+ userInfo(` 已检查 ${allProblems.length} 个已有功能记录`);
1835
1956
  if (output.duplicate_detected) {
1836
1957
  userInfo(` ⚠ 重复检测: 发现 ${output.duplicates.join(", ")}`);
1837
1958
  for (const d of matchedDetails) {
@@ -1844,7 +1965,7 @@ async function cmdValidateNewIssue() {
1844
1965
  userInfo(` - ${r}`);
1845
1966
  }
1846
1967
  if (output.can_proceed) {
1847
- userInfo(` ✓ 可继续: 问题新增已通过演进门控 (候选ID: ${candidateId})`);
1968
+ userInfo(` ✓ 可继续: 需求新增已通过演进检查 (ID: ${candidateId})`);
1848
1969
  }
1849
1970
  }
1850
1971
  if (!output.can_proceed) {
@@ -2123,4 +2244,58 @@ function getArgValue(flag) {
2123
2244
  return undefined;
2124
2245
  return result;
2125
2246
  }
2247
+ async function cmdAuditTemplateVisibility() {
2248
+ const projectPath = process.env.SOLOFORGE_PROJECT ?? process.cwd();
2249
+ const { auditStandardAssetCoverage } = await import("../engine/standard_asset_coverage.js");
2250
+ const { listBuiltinConsumableAssets } = await import("../engine/consumable_asset_registry.js");
2251
+ const { listTemplateAssetContracts, auditContractCoverage } = await import("../engine/template_asset_contract_registry.js");
2252
+ const { userInfo, userJson } = await import("../engine/logger.js");
2253
+ // 使用权威合同注册表作为单一数据源
2254
+ const contracts = listTemplateAssetContracts();
2255
+ const registeredAssets = listBuiltinConsumableAssets();
2256
+ const consumablePaths = new Set(registeredAssets.map((a) => a.path));
2257
+ const ownerMap = new Map(contracts.map((c) => [c.path, c.owner_mechanism_id]));
2258
+ const consumerMap = new Map(contracts.map((c) => [c.path, [c.mainline_consumer, c.validation_entrypoint].filter(Boolean)]));
2259
+ const visibilityMap = new Map(contracts.map((c) => [c.path, c.asset_visibility]));
2260
+ // 运行覆盖审计(使用真实合同数据)
2261
+ const report = auditStandardAssetCoverage(projectPath, consumablePaths, ownerMap, consumerMap, visibilityMap);
2262
+ // 合同覆盖统计
2263
+ const coverageReport = auditContractCoverage(projectPath);
2264
+ // 可见性统计(从权威合同直接计算)
2265
+ const internalCount = contracts.filter((c) => c.asset_visibility === "soloforge_internal" || c.asset_visibility === "scaffold_only").length;
2266
+ const userVisibleCount = contracts.filter((c) => c.user_visible).length;
2267
+ // 输出报告
2268
+ const isJson = args.includes("--json");
2269
+ const result = {
2270
+ total_assets: report.total_assets,
2271
+ contract_covered: coverageReport.contract_covered,
2272
+ uncovered_assets: coverageReport.uncovered,
2273
+ user_visible_count: userVisibleCount,
2274
+ internal_count: internalCount,
2275
+ unknown_visibility: coverageReport.visibility_unknown,
2276
+ conflict_count: 0,
2277
+ missing_bearer: report.missing_standard_bearer,
2278
+ missing_revalidation: report.missing_revalidation,
2279
+ missing_consumer: report.missing_consumer,
2280
+ missing_owner: report.missing_owner,
2281
+ unregistered: report.unregistered_assets,
2282
+ };
2283
+ if (isJson) {
2284
+ userJson(JSON.stringify(result, null, 2));
2285
+ }
2286
+ else {
2287
+ userInfo("═══ 模板资产可见性审计报告 ═══");
2288
+ userInfo(`总资产数: ${report.total_assets}`);
2289
+ userInfo(`合同覆盖: ${coverageReport.contract_covered}`);
2290
+ userInfo(`未覆盖: ${coverageReport.uncovered}`);
2291
+ userInfo(`用户可见: ${userVisibleCount}`);
2292
+ userInfo(`内部资产: ${internalCount}`);
2293
+ userInfo(`未知可见性: ${coverageReport.visibility_unknown}`);
2294
+ userInfo(`缺标准承载: ${report.missing_standard_bearer}`);
2295
+ userInfo(`缺复验入口: ${report.missing_revalidation}`);
2296
+ userInfo(`缺消费者: ${report.missing_consumer}`);
2297
+ userInfo(`缺 owner: ${report.missing_owner}`);
2298
+ userInfo(`未注册: ${report.unregistered_assets}`);
2299
+ }
2300
+ }
2126
2301
  //# sourceMappingURL=soloforge.js.map