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.
- package/README.md +15 -2
- package/dist/adapters/claude_code/claude_md.d.ts.map +1 -1
- package/dist/adapters/claude_code/claude_md.js +4 -0
- package/dist/adapters/claude_code/claude_md.js.map +1 -1
- package/dist/adapters/claude_code/tools.d.ts +36 -9
- package/dist/adapters/claude_code/tools.d.ts.map +1 -1
- package/dist/adapters/claude_code/tools.js +828 -19
- package/dist/adapters/claude_code/tools.js.map +1 -1
- package/dist/adapters/shared/workflow_template.d.ts +26 -0
- package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
- package/dist/adapters/shared/workflow_template.js +139 -40
- package/dist/adapters/shared/workflow_template.js.map +1 -1
- package/dist/bin/soloforge.d.ts.map +1 -1
- package/dist/bin/soloforge.js +220 -45
- package/dist/bin/soloforge.js.map +1 -1
- package/dist/engine/architecture_decision_workshop.d.ts +58 -0
- package/dist/engine/architecture_decision_workshop.d.ts.map +1 -0
- package/dist/engine/architecture_decision_workshop.js +118 -0
- package/dist/engine/architecture_decision_workshop.js.map +1 -0
- package/dist/engine/asset_manifest.d.ts +7 -1
- package/dist/engine/asset_manifest.d.ts.map +1 -1
- package/dist/engine/asset_manifest.js +36 -15
- package/dist/engine/asset_manifest.js.map +1 -1
- package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
- package/dist/engine/consumable_asset_registry.js +90 -1
- package/dist/engine/consumable_asset_registry.js.map +1 -1
- package/dist/engine/consumption_trace_store.d.ts +8 -8
- package/dist/engine/consumption_trace_store.d.ts.map +1 -1
- package/dist/engine/consumption_trace_store.js +11 -7
- package/dist/engine/consumption_trace_store.js.map +1 -1
- package/dist/engine/decision_workshop.d.ts +160 -0
- package/dist/engine/decision_workshop.d.ts.map +1 -0
- package/dist/engine/decision_workshop.js +279 -0
- package/dist/engine/decision_workshop.js.map +1 -0
- package/dist/engine/design_artifact_pack.d.ts +44 -0
- package/dist/engine/design_artifact_pack.d.ts.map +1 -0
- package/dist/engine/design_artifact_pack.js +167 -0
- package/dist/engine/design_artifact_pack.js.map +1 -0
- package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -1
- package/dist/engine/dual_layer_mechanism_registry.js +294 -0
- package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
- package/dist/engine/evidence_grounding_contract.d.ts +137 -0
- package/dist/engine/evidence_grounding_contract.d.ts.map +1 -0
- package/dist/engine/evidence_grounding_contract.js +410 -0
- package/dist/engine/evidence_grounding_contract.js.map +1 -0
- package/dist/engine/explicit_asset_registry.d.ts +30 -0
- package/dist/engine/explicit_asset_registry.d.ts.map +1 -0
- package/dist/engine/explicit_asset_registry.js +3508 -0
- package/dist/engine/explicit_asset_registry.js.map +1 -0
- package/dist/engine/implementation_roadmap_registry.d.ts +2 -2
- package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
- package/dist/engine/implementation_roadmap_registry.js +163 -6
- package/dist/engine/implementation_roadmap_registry.js.map +1 -1
- package/dist/engine/instruction_contract.d.ts +8 -1
- package/dist/engine/instruction_contract.d.ts.map +1 -1
- package/dist/engine/instruction_contract.js +63 -1
- package/dist/engine/instruction_contract.js.map +1 -1
- package/dist/engine/intent_expander.d.ts.map +1 -1
- package/dist/engine/intent_expander.js +60 -2
- package/dist/engine/intent_expander.js.map +1 -1
- package/dist/engine/intent_router.d.ts +1 -1
- package/dist/engine/intent_router.d.ts.map +1 -1
- package/dist/engine/intent_router.js +2 -1
- package/dist/engine/intent_router.js.map +1 -1
- package/dist/engine/knowledge_injection_boundary.d.ts +3 -0
- package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
- package/dist/engine/knowledge_injection_boundary.js +48 -5
- package/dist/engine/knowledge_injection_boundary.js.map +1 -1
- package/dist/engine/mechanism_contract_registry.d.ts +1 -1
- package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
- package/dist/engine/mechanism_contract_registry.js +138 -0
- package/dist/engine/mechanism_contract_registry.js.map +1 -1
- package/dist/engine/observed_consumption.d.ts +54 -0
- package/dist/engine/observed_consumption.d.ts.map +1 -0
- package/dist/engine/observed_consumption.js +377 -0
- package/dist/engine/observed_consumption.js.map +1 -0
- package/dist/engine/platform_context.d.ts.map +1 -1
- package/dist/engine/platform_context.js +6 -2
- package/dist/engine/platform_context.js.map +1 -1
- package/dist/engine/release_gate_scenario_registry.d.ts +16 -1
- package/dist/engine/release_gate_scenario_registry.d.ts.map +1 -1
- package/dist/engine/release_gate_scenario_registry.js +205 -2
- package/dist/engine/release_gate_scenario_registry.js.map +1 -1
- package/dist/engine/release_issue_scenario_registry.d.ts +64 -0
- package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -0
- package/dist/engine/release_issue_scenario_registry.js +1349 -0
- package/dist/engine/release_issue_scenario_registry.js.map +1 -0
- package/dist/engine/release_readiness_gate.d.ts +8 -0
- package/dist/engine/release_readiness_gate.d.ts.map +1 -1
- package/dist/engine/release_readiness_gate.js +1144 -6
- package/dist/engine/release_readiness_gate.js.map +1 -1
- package/dist/engine/release_tool_harness.d.ts +71 -0
- package/dist/engine/release_tool_harness.d.ts.map +1 -0
- package/dist/engine/release_tool_harness.js +161 -0
- package/dist/engine/release_tool_harness.js.map +1 -0
- package/dist/engine/scaffolder.d.ts.map +1 -1
- package/dist/engine/scaffolder.js +144 -7
- package/dist/engine/scaffolder.js.map +1 -1
- package/dist/engine/standard_asset_contract.d.ts +75 -0
- package/dist/engine/standard_asset_contract.d.ts.map +1 -0
- package/dist/engine/standard_asset_contract.js +388 -0
- package/dist/engine/standard_asset_contract.js.map +1 -0
- package/dist/engine/standard_asset_coverage.d.ts +45 -0
- package/dist/engine/standard_asset_coverage.d.ts.map +1 -0
- package/dist/engine/standard_asset_coverage.js +220 -0
- package/dist/engine/standard_asset_coverage.js.map +1 -0
- package/dist/engine/task_context.d.ts +9 -2
- package/dist/engine/task_context.d.ts.map +1 -1
- package/dist/engine/task_context.js +49 -12
- package/dist/engine/task_context.js.map +1 -1
- package/dist/engine/template_asset_contract_registry.d.ts +162 -0
- package/dist/engine/template_asset_contract_registry.d.ts.map +1 -0
- package/dist/engine/template_asset_contract_registry.js +598 -0
- package/dist/engine/template_asset_contract_registry.js.map +1 -0
- package/dist/engine/template_asset_visibility.d.ts +109 -0
- package/dist/engine/template_asset_visibility.d.ts.map +1 -0
- package/dist/engine/template_asset_visibility.js +321 -0
- package/dist/engine/template_asset_visibility.js.map +1 -0
- package/dist/engine/template_init_sync.d.ts +68 -0
- package/dist/engine/template_init_sync.d.ts.map +1 -0
- package/dist/engine/template_init_sync.js +218 -0
- package/dist/engine/template_init_sync.js.map +1 -0
- package/dist/engine/template_manifest_io.d.ts +10 -0
- package/dist/engine/template_manifest_io.d.ts.map +1 -1
- package/dist/engine/template_manifest_io.js +63 -30
- package/dist/engine/template_manifest_io.js.map +1 -1
- package/dist/engine/template_mechanism_auditor.d.ts +3 -1
- package/dist/engine/template_mechanism_auditor.d.ts.map +1 -1
- package/dist/engine/template_mechanism_auditor.js +27 -24
- package/dist/engine/template_mechanism_auditor.js.map +1 -1
- package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
- package/dist/engine/tool_invocation_contract_registry.js +11 -1
- package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
- package/dist/engine/verifier.d.ts.map +1 -1
- package/dist/engine/verifier.js +3 -40
- package/dist/engine/verifier.js.map +1 -1
- package/dist/engine/workflow_contract_registry.d.ts.map +1 -1
- package/dist/engine/workflow_contract_registry.js +4 -3
- package/dist/engine/workflow_contract_registry.js.map +1 -1
- package/dist/knowledge/index_manager.d.ts +20 -0
- package/dist/knowledge/index_manager.d.ts.map +1 -1
- package/dist/knowledge/index_manager.js +234 -3
- package/dist/knowledge/index_manager.js.map +1 -1
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -4
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模板初始化同步 — init 命令的知识模板复制与全局模式安装。
|
|
3
|
+
*
|
|
4
|
+
* 将 CLI copyKnowledgeTemplates / copyGlobalPatterns 的核心逻辑抽为生产模块,
|
|
5
|
+
* 由 CLI、release gate、observed_consumption 共同调用。
|
|
6
|
+
* 每次调用均记录 consumption_trace,保证 trace 来源真实一致。
|
|
7
|
+
* 同步完成后写入 sync-manifest.json,记录每个同步文件的来源身份元数据。
|
|
8
|
+
*/
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import crypto from "node:crypto";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { getContractDecision } from "./template_asset_contract_registry.js";
|
|
14
|
+
import { recordConsumptionTrace } from "./consumption_trace_store.js";
|
|
15
|
+
const MANIFEST_PATH = ".soloforge/sync-manifest.json";
|
|
16
|
+
/**
|
|
17
|
+
* 读取同步清单。
|
|
18
|
+
*/
|
|
19
|
+
export function readSyncManifest(projectPath) {
|
|
20
|
+
const manifestPath = path.join(projectPath, MANIFEST_PATH);
|
|
21
|
+
if (!fs.existsSync(manifestPath))
|
|
22
|
+
return null;
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 写入同步清单。
|
|
32
|
+
*/
|
|
33
|
+
function writeSyncManifest(projectPath, manifest) {
|
|
34
|
+
const manifestPath = path.join(projectPath, MANIFEST_PATH);
|
|
35
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
36
|
+
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
37
|
+
}
|
|
38
|
+
/** 计算文件 body SHA256(排除健康检查会修改的字段:frontmatter 和 YAML status/updated_at) */
|
|
39
|
+
function fileHash(filePath) {
|
|
40
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
41
|
+
if (filePath.endsWith(".yaml") || filePath.endsWith(".yml")) {
|
|
42
|
+
// YAML 文件: 移除 status 和 updated_at 行后哈希
|
|
43
|
+
const stripped = content.split("\n")
|
|
44
|
+
.filter(line => !/^(status|updated_at)\s*:/.test(line.trim()))
|
|
45
|
+
.join("\n");
|
|
46
|
+
return crypto.createHash("sha256").update(stripped).digest("hex").substring(0, 16);
|
|
47
|
+
}
|
|
48
|
+
// Markdown: 排除 frontmatter 后哈希 body
|
|
49
|
+
const bodyStart = content.indexOf("---", content.indexOf("---") + 3);
|
|
50
|
+
const body = bodyStart >= 0 ? content.substring(bodyStart + 3).trimStart() : content;
|
|
51
|
+
return crypto.createHash("sha256").update(body).digest("hex").substring(0, 16);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 从权威来源(当前安装的模板包)计算 source_contract_path 的 body hash。
|
|
55
|
+
* 用于替代 sync-manifest.json 中用户可编辑的 source_hash。
|
|
56
|
+
* 返回 null 表示权威来源文件不存在(用户可能已卸载/升级包)。
|
|
57
|
+
*/
|
|
58
|
+
export function computeAuthoritativeHash(sourceContractPath) {
|
|
59
|
+
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
60
|
+
const absPath = path.resolve(thisDir, "..", "..", sourceContractPath);
|
|
61
|
+
if (!fs.existsSync(absPath))
|
|
62
|
+
return null;
|
|
63
|
+
return fileHash(absPath);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 按目标 knowledge relativePath 反向解析权威来源身份。
|
|
67
|
+
* 不依赖用户可编辑 manifest 中的 source_contract_path/source_asset_id。
|
|
68
|
+
* 返回 null 表示无对应权威映射(非同步资产或模板包缺失)。
|
|
69
|
+
*/
|
|
70
|
+
export function resolveAuthoritativeIdentity(knowledgeRelPath) {
|
|
71
|
+
const contractPath = `templates/knowledge/${knowledgeRelPath}`;
|
|
72
|
+
const hash = computeAuthoritativeHash(contractPath);
|
|
73
|
+
if (hash === null)
|
|
74
|
+
return null;
|
|
75
|
+
// getContractDecision 同步可用(已由 import 引入)
|
|
76
|
+
// 此函数由 KIM 在 filterByContractGate 中调用,KIM 已 import getContractDecision
|
|
77
|
+
// 直接返回路径和 hash,让 KIM 通过 getContractDecision 获取合同
|
|
78
|
+
return {
|
|
79
|
+
source_contract_path: contractPath,
|
|
80
|
+
source_asset_id: "", // 由 KIM 通过 getContractDecision 填充
|
|
81
|
+
source_hash: hash,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 遍历 templates/knowledge 下所有文件,通过 getContractDecision 门禁,
|
|
86
|
+
* 记录 consumption_trace 后复制到用户项目 .soloforge/knowledge/ 目录。
|
|
87
|
+
* 同步完成后写入 sync-manifest.json 记录来源身份。
|
|
88
|
+
*/
|
|
89
|
+
export async function copyKnowledgeToProject(templatesRootDir, projectPath) {
|
|
90
|
+
const result = {
|
|
91
|
+
copied: 0,
|
|
92
|
+
skipped_internal: 0,
|
|
93
|
+
skipped_no_contract: 0,
|
|
94
|
+
patterns_copied: 0,
|
|
95
|
+
patterns_skipped: 0,
|
|
96
|
+
};
|
|
97
|
+
const knowledgeTemplatesDir = path.join(templatesRootDir, "templates", "knowledge");
|
|
98
|
+
if (!fs.existsSync(knowledgeTemplatesDir))
|
|
99
|
+
return result;
|
|
100
|
+
// 读取现有清单或创建新清单
|
|
101
|
+
const manifest = readSyncManifest(projectPath) ?? { version: 1, entries: {} };
|
|
102
|
+
const stack = [knowledgeTemplatesDir];
|
|
103
|
+
while (stack.length > 0) {
|
|
104
|
+
const currentDir = stack.pop();
|
|
105
|
+
for (const entry of fs.readdirSync(currentDir, { withFileTypes: true })) {
|
|
106
|
+
const srcPath = path.join(currentDir, entry.name);
|
|
107
|
+
if (entry.isDirectory()) {
|
|
108
|
+
stack.push(srcPath);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (!/\.(md|yaml|yml)$/.test(entry.name))
|
|
112
|
+
continue;
|
|
113
|
+
const relPath = path.relative(knowledgeTemplatesDir, srcPath).replace(/\\/g, "/");
|
|
114
|
+
const fullRelPath = `templates/knowledge/${relPath}`;
|
|
115
|
+
const destPath = path.join(projectPath, ".soloforge", "knowledge", relPath);
|
|
116
|
+
const decision = getContractDecision(fullRelPath);
|
|
117
|
+
if (decision.decision === "unregistered") {
|
|
118
|
+
recordConsumptionTrace({
|
|
119
|
+
consumer: "init", asset_id: fullRelPath, asset_path: fullRelPath,
|
|
120
|
+
contract_decision: "unregistered",
|
|
121
|
+
fields_consumed: ["asset_path", "contract_decision", "target_path"],
|
|
122
|
+
matched_reason: "无合同注册",
|
|
123
|
+
task_id_or_route: "copyKnowledgeTemplates",
|
|
124
|
+
consumed_at: new Date().toISOString(),
|
|
125
|
+
});
|
|
126
|
+
result.skipped_no_contract++;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (decision.decision === "denied") {
|
|
130
|
+
recordConsumptionTrace({
|
|
131
|
+
consumer: "init", asset_id: decision.contract?.asset_id ?? fullRelPath,
|
|
132
|
+
asset_path: fullRelPath, contract_decision: "denied",
|
|
133
|
+
fields_consumed: ["asset_path", "contract_decision", "target_path"],
|
|
134
|
+
matched_reason: `内部资产: ${decision.contract?.asset_visibility}`,
|
|
135
|
+
task_id_or_route: "copyKnowledgeTemplates",
|
|
136
|
+
consumed_at: new Date().toISOString(),
|
|
137
|
+
});
|
|
138
|
+
result.skipped_internal++;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (decision.contract && !decision.contract.sync_to_user_project) {
|
|
142
|
+
recordConsumptionTrace({
|
|
143
|
+
consumer: "init", asset_id: decision.contract.asset_id,
|
|
144
|
+
asset_path: fullRelPath, contract_decision: "denied",
|
|
145
|
+
fields_consumed: ["asset_path", "contract_decision", "target_path"],
|
|
146
|
+
matched_reason: "sync_to_user_project=false",
|
|
147
|
+
task_id_or_route: "copyKnowledgeTemplates",
|
|
148
|
+
consumed_at: new Date().toISOString(),
|
|
149
|
+
});
|
|
150
|
+
result.skipped_internal++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (!fs.existsSync(destPath)) {
|
|
154
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
155
|
+
fs.copyFileSync(srcPath, destPath);
|
|
156
|
+
}
|
|
157
|
+
// 写入来源身份元数据到清单
|
|
158
|
+
manifest.entries[relPath] = {
|
|
159
|
+
source_asset_id: decision.contract.asset_id,
|
|
160
|
+
source_contract_path: fullRelPath,
|
|
161
|
+
source_hash: fileHash(srcPath),
|
|
162
|
+
synced_at: new Date().toISOString(),
|
|
163
|
+
};
|
|
164
|
+
recordConsumptionTrace({
|
|
165
|
+
consumer: "init", asset_id: decision.contract.asset_id,
|
|
166
|
+
asset_path: fullRelPath, contract_decision: "allowed",
|
|
167
|
+
fields_consumed: ["asset_path", "contract_decision", "target_path"],
|
|
168
|
+
matched_reason: "复制到用户项目",
|
|
169
|
+
task_id_or_route: "copyKnowledgeTemplates",
|
|
170
|
+
consumed_at: new Date().toISOString(),
|
|
171
|
+
declared_consumer: decision.contract.mainline_consumer,
|
|
172
|
+
});
|
|
173
|
+
result.copied++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
writeSyncManifest(projectPath, manifest);
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 安装全局模式到指定目录。
|
|
181
|
+
* 遍历 templates/patterns 下所有文件,记录 consumption_trace。
|
|
182
|
+
*/
|
|
183
|
+
export async function copyPatternsToGlobal(templatesRootDir, patternsDestDir) {
|
|
184
|
+
let copied = 0;
|
|
185
|
+
let skipped = 0;
|
|
186
|
+
const templatesDir = path.join(templatesRootDir, "templates", "patterns");
|
|
187
|
+
if (!fs.existsSync(templatesDir))
|
|
188
|
+
return { copied: 0, skipped: 0 };
|
|
189
|
+
fs.mkdirSync(patternsDestDir, { recursive: true });
|
|
190
|
+
const files = fs.readdirSync(templatesDir).filter(f => f.endsWith(".md"));
|
|
191
|
+
for (const f of files) {
|
|
192
|
+
const src = path.join(templatesDir, f);
|
|
193
|
+
const dest = path.join(patternsDestDir, f);
|
|
194
|
+
const fullRelPath = `templates/patterns/${f}`;
|
|
195
|
+
const decision = getContractDecision(fullRelPath);
|
|
196
|
+
recordConsumptionTrace({
|
|
197
|
+
consumer: "init",
|
|
198
|
+
asset_id: decision.contract?.asset_id ?? fullRelPath,
|
|
199
|
+
asset_path: fullRelPath,
|
|
200
|
+
contract_decision: decision.decision === "allowed" ? "allowed" : decision.decision === "denied" ? "denied" : "unregistered",
|
|
201
|
+
fields_consumed: ["asset_path", "contract_decision", "target_path"],
|
|
202
|
+
matched_reason: decision.decision === "allowed" ? "全局模式可复制" : `${decision.decision}`,
|
|
203
|
+
task_id_or_route: "copyGlobalPatterns",
|
|
204
|
+
consumed_at: new Date().toISOString(),
|
|
205
|
+
});
|
|
206
|
+
if (decision.decision === "allowed") {
|
|
207
|
+
if (!fs.existsSync(dest)) {
|
|
208
|
+
fs.copyFileSync(src, dest);
|
|
209
|
+
copied++;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
skipped++;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return { copied, skipped };
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=template_init_sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template_init_sync.js","sourceRoot":"","sources":["../../src/engine/template_init_sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,7 +25,17 @@ export declare function writeFileSyncRecursive(filePath: string, content: string
|
|
|
25
25
|
* templates/patterns/{file} → .soloforge/knowledge/patterns/{file}(全局模式项目级副本)
|
|
26
26
|
* templates/scaffolds/* → 不纳入模板同步(由 scaffold 命令管理)
|
|
27
27
|
*/
|
|
28
|
+
export interface ManifestBuildStats {
|
|
29
|
+
included: number;
|
|
30
|
+
skipped_internal: number;
|
|
31
|
+
skipped_unregistered: number;
|
|
32
|
+
skipped_scaffold: string[];
|
|
33
|
+
}
|
|
28
34
|
export declare function buildTemplateManifestFromSource(sourceDir: string, packageVersion: string): TemplateManifestEntry[];
|
|
35
|
+
export declare function buildTemplateManifestWithStats(sourceDir: string, packageVersion: string): {
|
|
36
|
+
manifest: TemplateManifestEntry[];
|
|
37
|
+
stats: ManifestBuildStats;
|
|
38
|
+
};
|
|
29
39
|
/** 读取项目已安装清单,不存在返回 null */
|
|
30
40
|
export declare function loadProjectManifest(projectPath: string): TemplateManifestEntry[] | null;
|
|
31
41
|
/** 写入项目已安装清单 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template_manifest_io.d.ts","sourceRoot":"","sources":["../../src/engine/template_manifest_io.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"template_manifest_io.d.ts","sourceRoot":"","sources":["../../src/engine/template_manifest_io.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAK/E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAItC,2BAA2B;AAC3B,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE1D;AAED,mCAAmC;AACnC,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED,wBAAwB;AACxB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAO1E;AAID,kBAAkB;AAClB,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGvF;AAID;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAiBD,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACrB,qBAAqB,EAAE,CAGzB;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACrB;IAAE,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAyFlE;AAMD,2BAA2B;AAC3B,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,IAAI,CAQvF;AAED,gBAAgB;AAChB,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,qBAAqB,EAAE,GAChC,IAAI,CAGN;AAMD,aAAa;AACb,MAAM,WAAW,kBAAkB;IACjC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,0BAA0B;AAC1B,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAOjF;AAED,eAAe;AACf,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAEzF"}
|
|
@@ -8,6 +8,8 @@ import { createHash } from "node:crypto";
|
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { findConsumableAssetByPath } from "./consumable_asset_registry.js";
|
|
11
|
+
import { getContractDecision } from "./template_asset_contract_registry.js";
|
|
12
|
+
import { recordConsumptionTrace } from "./consumption_trace_store.js";
|
|
11
13
|
// ── 哈希工具 ──
|
|
12
14
|
/** 计算内容的 SHA-256 十六进制摘要 */
|
|
13
15
|
export function sha256Hex(content) {
|
|
@@ -39,41 +41,57 @@ export function writeFileSyncRecursive(filePath, content) {
|
|
|
39
41
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
40
42
|
fs.writeFileSync(filePath, content);
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
/** 递归扫描目录下所有 .md/.yaml/.yml 文件 */
|
|
45
|
+
function walkDirRecursive(dir) {
|
|
46
|
+
const results = [];
|
|
47
|
+
const stack = [dir];
|
|
48
|
+
while (stack.length > 0) {
|
|
49
|
+
const current = stack.pop();
|
|
50
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
51
|
+
const absPath = path.join(current, entry.name);
|
|
52
|
+
if (entry.isDirectory()) {
|
|
53
|
+
stack.push(absPath);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (/\.(md|yaml|yml)$/.test(entry.name))
|
|
57
|
+
results.push(absPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
54
62
|
export function buildTemplateManifestFromSource(sourceDir, packageVersion) {
|
|
63
|
+
const { manifest } = buildTemplateManifestWithStats(sourceDir, packageVersion);
|
|
64
|
+
return manifest;
|
|
65
|
+
}
|
|
66
|
+
export function buildTemplateManifestWithStats(sourceDir, packageVersion) {
|
|
55
67
|
const manifest = [];
|
|
56
|
-
const
|
|
57
|
-
//
|
|
58
|
-
const knowledgeSubDirs = [
|
|
59
|
-
"procedures", "domain", "product_profiles", "acceptance_templates",
|
|
60
|
-
"review_rules", "patterns/core", "checklists", "templates", "rules",
|
|
61
|
-
];
|
|
62
|
-
// 扫描知识模板
|
|
68
|
+
const stats = { included: 0, skipped_internal: 0, skipped_unregistered: 0, skipped_scaffold: [] };
|
|
69
|
+
// 递归扫描 templates/knowledge 下所有文件(不使用硬编码子目录列表)
|
|
63
70
|
const knowledgeDir = path.join(sourceDir, "knowledge");
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
71
|
+
if (fs.existsSync(knowledgeDir)) {
|
|
72
|
+
const knowledgeFiles = walkDirRecursive(knowledgeDir);
|
|
73
|
+
for (const absSource of knowledgeFiles) {
|
|
74
|
+
const relFromKnowledge = path.relative(knowledgeDir, absSource).replace(/\\/g, "/");
|
|
75
|
+
const relSource = `templates/knowledge/${relFromKnowledge}`;
|
|
76
|
+
const file = path.basename(absSource);
|
|
77
|
+
// 合同门禁: 逐文件调用 getContractDecision
|
|
78
|
+
const decision = getContractDecision(relSource);
|
|
79
|
+
if (decision.decision === "denied") {
|
|
80
|
+
recordConsumptionTrace({ consumer: "sync_templates", asset_id: decision.contract?.asset_id ?? relSource, asset_path: relSource, contract_decision: "denied", fields_consumed: ["asset_path", "contract_decision", "source_hash"], matched_reason: "内部资产跳过", task_id_or_route: "buildTemplateManifest", consumed_at: new Date().toISOString() });
|
|
81
|
+
stats.skipped_internal++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (decision.decision === "unregistered") {
|
|
85
|
+
recordConsumptionTrace({ consumer: "sync_templates", asset_id: relSource, asset_path: relSource, contract_decision: "unregistered", fields_consumed: ["asset_path", "contract_decision", "source_hash"], matched_reason: "未注册资产跳过", task_id_or_route: "buildTemplateManifest", consumed_at: new Date().toISOString() });
|
|
86
|
+
stats.skipped_unregistered++;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
72
89
|
const sourceHash = hashFile(absSource) ?? "";
|
|
73
90
|
const asset = findConsumableAssetByPath(relSource);
|
|
74
|
-
const
|
|
91
|
+
const subDir = path.dirname(relFromKnowledge);
|
|
92
|
+
const targetPath = `.soloforge/knowledge/${relFromKnowledge}`;
|
|
75
93
|
// 推导 sovereignty
|
|
76
|
-
const isCore =
|
|
94
|
+
const isCore = relFromKnowledge.startsWith("patterns/core/") ||
|
|
77
95
|
(asset?.consumption_mode === "required" && asset?.asset_kind === "capability_knowledge_doc");
|
|
78
96
|
manifest.push({
|
|
79
97
|
asset_id: asset?.id ?? `tpl-${subDir}-${file}`,
|
|
@@ -87,6 +105,8 @@ export function buildTemplateManifestFromSource(sourceDir, packageVersion) {
|
|
|
87
105
|
source_package_version: packageVersion,
|
|
88
106
|
sovereignty: isCore ? "core" : "normal",
|
|
89
107
|
});
|
|
108
|
+
recordConsumptionTrace({ consumer: "sync_templates", asset_id: asset?.id ?? `tpl-${subDir}-${file}`, asset_path: relSource, contract_decision: "allowed", fields_consumed: ["asset_path", "contract_decision", "source_hash"], matched_reason: "清单收录", task_id_or_route: "buildTemplateManifest", consumed_at: new Date().toISOString() });
|
|
109
|
+
stats.included++;
|
|
90
110
|
}
|
|
91
111
|
}
|
|
92
112
|
// 扫描全局模式(项目级副本)
|
|
@@ -96,6 +116,17 @@ export function buildTemplateManifestFromSource(sourceDir, packageVersion) {
|
|
|
96
116
|
for (const file of files) {
|
|
97
117
|
const relSource = `templates/patterns/${file}`;
|
|
98
118
|
const absSource = path.join(patternsDir, file);
|
|
119
|
+
const decision = getContractDecision(relSource);
|
|
120
|
+
if (decision.decision === "denied") {
|
|
121
|
+
recordConsumptionTrace({ consumer: "sync_templates", asset_id: decision.contract?.asset_id ?? relSource, asset_path: relSource, contract_decision: "denied", fields_consumed: ["asset_path", "contract_decision", "source_hash"], matched_reason: "内部资产跳过", task_id_or_route: "buildTemplateManifest", consumed_at: new Date().toISOString() });
|
|
122
|
+
stats.skipped_internal++;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (decision.decision === "unregistered") {
|
|
126
|
+
recordConsumptionTrace({ consumer: "sync_templates", asset_id: relSource, asset_path: relSource, contract_decision: "unregistered", fields_consumed: ["asset_path", "contract_decision", "source_hash"], matched_reason: "未注册资产跳过", task_id_or_route: "buildTemplateManifest", consumed_at: new Date().toISOString() });
|
|
127
|
+
stats.skipped_unregistered++;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
99
130
|
const sourceHash = hashFile(absSource) ?? "";
|
|
100
131
|
const asset = findConsumableAssetByPath(relSource);
|
|
101
132
|
manifest.push({
|
|
@@ -110,9 +141,11 @@ export function buildTemplateManifestFromSource(sourceDir, packageVersion) {
|
|
|
110
141
|
source_package_version: packageVersion,
|
|
111
142
|
sovereignty: "normal",
|
|
112
143
|
});
|
|
144
|
+
recordConsumptionTrace({ consumer: "sync_templates", asset_id: asset?.id ?? `pat-${file}`, asset_path: relSource, contract_decision: "allowed", fields_consumed: ["asset_path", "contract_decision", "source_hash"], matched_reason: "清单收录", task_id_or_route: "buildTemplateManifest", consumed_at: new Date().toISOString() });
|
|
145
|
+
stats.included++;
|
|
113
146
|
}
|
|
114
147
|
}
|
|
115
|
-
return manifest;
|
|
148
|
+
return { manifest, stats };
|
|
116
149
|
}
|
|
117
150
|
// ── 清单持久化 ──
|
|
118
151
|
const MANIFEST_FILE = ".soloforge/manifest.json";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template_manifest_io.js","sourceRoot":"","sources":["../../src/engine/template_manifest_io.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,yBAAyB,EAA+B,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"template_manifest_io.js","sourceRoot":"","sources":["../../src/engine/template_manifest_io.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,7 +77,9 @@ export interface TemplateMechanismAuditReport {
|
|
|
77
77
|
* @param rootDir - 项目根目录
|
|
78
78
|
* @returns 完整的审计报告
|
|
79
79
|
*/
|
|
80
|
-
export declare function auditTemplateMechanisms(rootDir: string
|
|
80
|
+
export declare function auditTemplateMechanisms(rootDir: string, options?: {
|
|
81
|
+
workflowContentOverride?: string;
|
|
82
|
+
}): TemplateMechanismAuditReport;
|
|
81
83
|
/**
|
|
82
84
|
* 检查资产是否允许注入到当前上下文。
|
|
83
85
|
* 基于资产消费模式、所属机制状态、当前路由和工作流进行多重校验。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template_mechanism_auditor.d.ts","sourceRoot":"","sources":["../../src/engine/template_mechanism_auditor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAA+B,KAAK,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACtG,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EAEzB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"template_mechanism_auditor.d.ts","sourceRoot":"","sources":["../../src/engine/template_mechanism_auditor.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import path from "node:path";
|
|
|
9
9
|
import { listBuiltinConsumableAssets } from "./consumable_asset_registry.js";
|
|
10
10
|
import { listMechanismLayerMaps, checkDualLayerCompleteness, } from "./dual_layer_mechanism_registry.js";
|
|
11
11
|
import { WORKFLOW_TEMPLATE_HARD_RULES } from "./asset_manifest.js";
|
|
12
|
+
import { generateWorkflowRules } from "../adapters/shared/workflow_template.js";
|
|
12
13
|
import { debug } from "./logger.js";
|
|
13
14
|
// ── 模板扫描目录 ──
|
|
14
15
|
const TEMPLATE_SCAN_DIRS = [
|
|
@@ -39,7 +40,7 @@ const ENFORCED_PROMISE_PATTERNS = [
|
|
|
39
40
|
* @param rootDir - 项目根目录
|
|
40
41
|
* @returns 完整的审计报告
|
|
41
42
|
*/
|
|
42
|
-
export function auditTemplateMechanisms(rootDir) {
|
|
43
|
+
export function auditTemplateMechanisms(rootDir, options) {
|
|
43
44
|
debug("TemplateMechanismAuditor", "开始模板机制审计");
|
|
44
45
|
const assets = listBuiltinConsumableAssets();
|
|
45
46
|
const maps = listMechanismLayerMaps();
|
|
@@ -82,6 +83,8 @@ export function auditTemplateMechanisms(rootDir) {
|
|
|
82
83
|
// 5. 仅代码的机制
|
|
83
84
|
const codeOnlyMechanisms = [];
|
|
84
85
|
for (const m of maps) {
|
|
86
|
+
if (m.status === "experimental_dual_layer")
|
|
87
|
+
continue;
|
|
85
88
|
const completeness = checkDualLayerCompleteness(m);
|
|
86
89
|
if (!completeness.has_template_layer && completeness.has_code_layer) {
|
|
87
90
|
codeOnlyMechanisms.push({
|
|
@@ -166,7 +169,8 @@ export function auditTemplateMechanisms(rootDir) {
|
|
|
166
169
|
// 11. 薄模板发现(厚重内容、过大模板)
|
|
167
170
|
const thinTemplateFindings = computeThinTemplateFindings(rootDir);
|
|
168
171
|
// 12. 工作流硬性规则发现
|
|
169
|
-
const
|
|
172
|
+
const wfContent = options?.workflowContentOverride ?? generateWorkflowRules({});
|
|
173
|
+
const workflowHardRuleFindings = computeWorkflowHardRuleFindings(rootDir, mechanismMap, wfContent);
|
|
170
174
|
// 计算统计数量
|
|
171
175
|
const allFindings = [
|
|
172
176
|
...driftFindings,
|
|
@@ -276,6 +280,8 @@ function computeDriftFindings(maps, assets, rootDir) {
|
|
|
276
280
|
const findings = [];
|
|
277
281
|
const assetPathSet = new Set(assets.map((a) => a.path));
|
|
278
282
|
for (const m of maps) {
|
|
283
|
+
if (m.status === "experimental_dual_layer")
|
|
284
|
+
continue;
|
|
279
285
|
if ((m.priority === "P0" || m.priority === "P1") && m.status !== "dual_layer_enforced") {
|
|
280
286
|
findings.push({
|
|
281
287
|
severity: "hard_fail",
|
|
@@ -522,31 +528,28 @@ function computeThinTemplateFindings(rootDir) {
|
|
|
522
528
|
* 检查工作流模板硬性规则的一致性。
|
|
523
529
|
* 校验 marker 与 manifest 的对应关系、source_ref 有效性和机制状态。
|
|
524
530
|
*/
|
|
525
|
-
function computeWorkflowHardRuleFindings(rootDir, mechanismMap) {
|
|
531
|
+
function computeWorkflowHardRuleFindings(rootDir, mechanismMap, workflowContent) {
|
|
526
532
|
const findings = [];
|
|
527
533
|
const registeredRules = new Map(WORKFLOW_TEMPLATE_HARD_RULES.map(r => [r.rule_id, r]));
|
|
528
|
-
|
|
529
|
-
// 收集模板文件中所有 marker
|
|
534
|
+
// 收集生成输出中所有 marker(单真源方向: manifest → hardRuleTag → 输出)
|
|
530
535
|
const markerIds = new Set();
|
|
531
536
|
const markerMechanisms = new Map();
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
});
|
|
549
|
-
}
|
|
537
|
+
const content = workflowContent ?? generateWorkflowRules({});
|
|
538
|
+
const markerRegex = /@sf-hard-rule\s+id=(\S+)\s+mechanism=(\S+)/g;
|
|
539
|
+
let match;
|
|
540
|
+
while ((match = markerRegex.exec(content)) !== null) {
|
|
541
|
+
markerIds.add(match[1]);
|
|
542
|
+
markerMechanisms.set(match[1], match[2]);
|
|
543
|
+
}
|
|
544
|
+
// 检查 1: marker → manifest(marker 存在但未在 manifest 中注册)
|
|
545
|
+
for (const markerId of markerIds) {
|
|
546
|
+
if (!registeredRules.has(markerId)) {
|
|
547
|
+
findings.push({
|
|
548
|
+
severity: "hard_fail",
|
|
549
|
+
mechanism_id: "workflow_hard_rule",
|
|
550
|
+
finding_type: "unregistered_hard_rule",
|
|
551
|
+
message: `@sf-hard-rule id=${markerId} 未在 WORKFLOW_TEMPLATE_HARD_RULES 中注册`,
|
|
552
|
+
});
|
|
550
553
|
}
|
|
551
554
|
}
|
|
552
555
|
// 检查 2: manifest → marker(manifest 规则在模板中无对应 marker)
|
|
@@ -609,7 +612,7 @@ function computeWorkflowHardRuleFindings(rootDir, mechanismMap) {
|
|
|
609
612
|
message: `manifest rule ${rule.rule_id} mechanism_id=${rule.mechanism_id} 未在机制注册表中找到`,
|
|
610
613
|
});
|
|
611
614
|
}
|
|
612
|
-
else if (mech.status !== "dual_layer_enforced") {
|
|
615
|
+
else if (mech.status !== "dual_layer_enforced" && mech.status !== "experimental_dual_layer") {
|
|
613
616
|
findings.push({
|
|
614
617
|
severity: "hard_fail",
|
|
615
618
|
mechanism_id: rule.mechanism_id,
|