soloforge 1.3.2 → 1.3.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 (124) hide show
  1. package/README.md +14 -0
  2. package/dist/adapters/claude_code/server.js +1 -1
  3. package/dist/adapters/claude_code/server.js.map +1 -1
  4. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  5. package/dist/adapters/claude_code/tools.js +385 -15
  6. package/dist/adapters/claude_code/tools.js.map +1 -1
  7. package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
  8. package/dist/adapters/shared/workflow_template.js +3 -2
  9. package/dist/adapters/shared/workflow_template.js.map +1 -1
  10. package/dist/bin/soloforge.d.ts.map +1 -1
  11. package/dist/bin/soloforge.js +296 -1
  12. package/dist/bin/soloforge.js.map +1 -1
  13. package/dist/engine/asset_manifest.d.ts.map +1 -1
  14. package/dist/engine/asset_manifest.js +24 -0
  15. package/dist/engine/asset_manifest.js.map +1 -1
  16. package/dist/engine/backend_implementation_contract.d.ts +51 -0
  17. package/dist/engine/backend_implementation_contract.d.ts.map +1 -0
  18. package/dist/engine/backend_implementation_contract.js +142 -0
  19. package/dist/engine/backend_implementation_contract.js.map +1 -0
  20. package/dist/engine/code_maintainability_observability_contract.d.ts +74 -0
  21. package/dist/engine/code_maintainability_observability_contract.d.ts.map +1 -0
  22. package/dist/engine/code_maintainability_observability_contract.js +473 -0
  23. package/dist/engine/code_maintainability_observability_contract.js.map +1 -0
  24. package/dist/engine/config_write_boundary.d.ts +29 -0
  25. package/dist/engine/config_write_boundary.d.ts.map +1 -0
  26. package/dist/engine/config_write_boundary.js +69 -0
  27. package/dist/engine/config_write_boundary.js.map +1 -0
  28. package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
  29. package/dist/engine/consumable_asset_registry.js +182 -1
  30. package/dist/engine/consumable_asset_registry.js.map +1 -1
  31. package/dist/engine/diagnostic_registry.d.ts +12 -0
  32. package/dist/engine/diagnostic_registry.d.ts.map +1 -1
  33. package/dist/engine/diagnostic_registry.js +62 -0
  34. package/dist/engine/diagnostic_registry.js.map +1 -1
  35. package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -1
  36. package/dist/engine/dual_layer_mechanism_registry.js +318 -1
  37. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  38. package/dist/engine/explicit_asset_registry.d.ts.map +1 -1
  39. package/dist/engine/explicit_asset_registry.js +338 -0
  40. package/dist/engine/explicit_asset_registry.js.map +1 -1
  41. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  42. package/dist/engine/implementation_roadmap_registry.js +112 -2
  43. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  44. package/dist/engine/knowledge_governance_gate.d.ts +38 -0
  45. package/dist/engine/knowledge_governance_gate.d.ts.map +1 -0
  46. package/dist/engine/knowledge_governance_gate.js +123 -0
  47. package/dist/engine/knowledge_governance_gate.js.map +1 -0
  48. package/dist/engine/log_governance.d.ts +25 -0
  49. package/dist/engine/log_governance.d.ts.map +1 -0
  50. package/dist/engine/log_governance.js +76 -0
  51. package/dist/engine/log_governance.js.map +1 -0
  52. package/dist/engine/mechanism_contract_registry.d.ts +1 -0
  53. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  54. package/dist/engine/mechanism_contract_registry.js +172 -0
  55. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  56. package/dist/engine/mechanism_health_check.d.ts +23 -0
  57. package/dist/engine/mechanism_health_check.d.ts.map +1 -0
  58. package/dist/engine/mechanism_health_check.js +140 -0
  59. package/dist/engine/mechanism_health_check.js.map +1 -0
  60. package/dist/engine/next_action_planner.d.ts +19 -0
  61. package/dist/engine/next_action_planner.d.ts.map +1 -0
  62. package/dist/engine/next_action_planner.js +453 -0
  63. package/dist/engine/next_action_planner.js.map +1 -0
  64. package/dist/engine/observability.js +1 -1
  65. package/dist/engine/observability.js.map +1 -1
  66. package/dist/engine/ood_solid_contract.d.ts +51 -0
  67. package/dist/engine/ood_solid_contract.d.ts.map +1 -0
  68. package/dist/engine/ood_solid_contract.js +115 -0
  69. package/dist/engine/ood_solid_contract.js.map +1 -0
  70. package/dist/engine/project_stage_detector.d.ts +17 -0
  71. package/dist/engine/project_stage_detector.d.ts.map +1 -0
  72. package/dist/engine/project_stage_detector.js +185 -0
  73. package/dist/engine/project_stage_detector.js.map +1 -0
  74. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -1
  75. package/dist/engine/release_issue_scenario_registry.js +230 -1
  76. package/dist/engine/release_issue_scenario_registry.js.map +1 -1
  77. package/dist/engine/release_readiness_gate.d.ts +3 -0
  78. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  79. package/dist/engine/release_readiness_gate.js +407 -9
  80. package/dist/engine/release_readiness_gate.js.map +1 -1
  81. package/dist/engine/stale_current_task_detector.d.ts +30 -0
  82. package/dist/engine/stale_current_task_detector.d.ts.map +1 -0
  83. package/dist/engine/stale_current_task_detector.js +168 -0
  84. package/dist/engine/stale_current_task_detector.js.map +1 -0
  85. package/dist/engine/task_stage_detector.d.ts +19 -0
  86. package/dist/engine/task_stage_detector.d.ts.map +1 -0
  87. package/dist/engine/task_stage_detector.js +201 -0
  88. package/dist/engine/task_stage_detector.js.map +1 -0
  89. package/dist/engine/team_awareness.js +6 -6
  90. package/dist/engine/team_awareness.js.map +1 -1
  91. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
  92. package/dist/engine/tool_invocation_contract_registry.js +10 -0
  93. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  94. package/dist/engine/workflow_navigation_contract.d.ts +115 -0
  95. package/dist/engine/workflow_navigation_contract.d.ts.map +1 -0
  96. package/dist/engine/workflow_navigation_contract.js +39 -0
  97. package/dist/engine/workflow_navigation_contract.js.map +1 -0
  98. package/dist/types.d.ts +12 -0
  99. package/dist/types.d.ts.map +1 -1
  100. package/package.json +1 -1
  101. package/templates/knowledge/acceptance_templates/OOD/350/256/276/350/256/241/346/221/230/350/246/201/346/250/241/347/211/210.md +60 -0
  102. package/templates/knowledge/acceptance_templates//344/273/243/347/240/201/346/263/250/351/207/212/344/270/216/346/227/245/345/277/227/351/252/214/346/224/266/346/250/241/346/235/277.md +78 -0
  103. package/templates/knowledge/acceptance_templates//345/220/216/347/253/257/345/256/236/347/216/260/351/252/214/346/224/266/346/270/205/345/215/225.md +46 -0
  104. package/templates/knowledge/procedures/OOD/350/256/276/350/256/241/345/267/245/344/275/234/346/265/201.md +50 -0
  105. package/templates/knowledge/procedures//345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/345/267/245/344/275/234/346/265/201/345/257/274/350/210/252.md +100 -0
  106. package/templates/knowledge/procedures//345/220/216/347/253/257/346/216/245/345/217/243/345/256/236/347/216/260/345/267/245/344/275/234/346/265/201.md +50 -0
  107. package/templates/knowledge/review//344/273/243/347/240/201/345/217/257/347/273/264/346/212/244/346/200/247/344/270/216/345/217/257/350/247/202/346/265/213/346/200/247/345/256/241/346/237/245.md +81 -0
  108. package/templates/knowledge/review_rules/SOLID/344/273/243/347/240/201/345/256/241/346/237/245/350/247/204/345/210/231.md +40 -0
  109. package/templates/knowledge/review_rules//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/256/241/346/237/245/350/247/204/345/210/231.md +38 -0
  110. package/templates/knowledge/rules/OOD/344/270/216SOLID/350/256/276/350/256/241/350/247/204/345/210/231.md +62 -0
  111. package/templates/knowledge/rules//344/273/243/347/240/201/346/263/250/351/207/212/344/270/216/346/227/245/345/277/227/345/245/221/347/272/246/350/247/204/345/210/231.md +121 -0
  112. package/templates/knowledge/rules//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/245/221/347/272/246/350/247/204/345/210/231.md +55 -0
  113. package/templates/knowledge/rules//345/267/245/344/275/234/346/265/201/345/257/274/350/210/252/345/245/221/347/272/246/350/247/204/345/210/231.md +113 -0
  114. package/templates/knowledge/rules//346/225/217/346/204/237/344/277/241/346/201/257/346/227/245/345/277/227/350/247/204/345/210/231.md +69 -0
  115. package/templates/knowledge/rules//346/227/245/345/277/227/346/262/273/347/220/206/350/247/204/345/210/231.md +49 -0
  116. package/templates/knowledge/rules//346/234/272/345/210/266/350/207/252/346/262/273/347/220/206/350/247/204/345/210/231.md +48 -0
  117. 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 +43 -0
  118. 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 +44 -0
  119. package/templates/knowledge/rules//347/237/245/350/257/206/346/262/273/347/220/206/350/247/204/345/210/231.md +50 -0
  120. 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 +47 -0
  121. package/templates/knowledge/rules//351/205/215/347/275/256/350/220/275/347/233/230/350/276/271/347/225/214/350/247/204/345/210/231.md +47 -0
  122. 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 +46 -0
  123. package/templates/patterns/SOLID/350/256/276/350/256/241/350/247/204/350/214/203.md +39 -0
  124. package/templates/patterns//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/350/247/204/350/214/203.md +39 -0
@@ -0,0 +1,115 @@
1
+ /**
2
+ * OOD 与 SOLID 实现契约。
3
+ *
4
+ * 复杂业务编码在执行前必须给出对象职责与依赖边界;审查和交付阶段
5
+ * 使用同一套 finding 口径阻断典型的 SOLID 违规。
6
+ */
7
+ const COMPLEX_OOD_KEYWORDS = /领域|业务规则|状态流转|策略模式|计费策略|订单流转|支付编排|结算规则|工作流编排|重构架构|模块设计|服务设计|领域服务|应用服务设计|domain|aggregate|solid|面向对象|职责拆分|接口抽象|依赖倒置/i;
8
+ const LOW_RISK_KEYWORDS = /错别字|拼写|文案|注释|样式|css|颜色|README|日志文案|配置值|测试数据|fixture/i;
9
+ export function requiresOodSolidContract(intent, route, changedFiles = []) {
10
+ const text = `${intent} ${changedFiles.join(" ")}`;
11
+ if (LOW_RISK_KEYWORDS.test(text) && !COMPLEX_OOD_KEYWORDS.test(text))
12
+ return false;
13
+ const codeRoute = !route || ["code_change", "artifact_generation", "operation", "multi_stage_plan"].includes(route);
14
+ return codeRoute && COMPLEX_OOD_KEYWORDS.test(text);
15
+ }
16
+ export function createOodDesignSummary(taskId, intent) {
17
+ return {
18
+ task_id: taskId,
19
+ status: "required",
20
+ applicability_reason_zh: `该任务涉及复杂对象职责或依赖边界,编码前需补齐 OOD/SOLID 摘要: ${intent}`,
21
+ objects: [],
22
+ interfaces: [],
23
+ dependency_direction: [],
24
+ change_points: [],
25
+ solid_risks: [],
26
+ };
27
+ }
28
+ function hasCompleteDesignSummary(summary) {
29
+ return !!summary
30
+ && summary.objects.length > 0
31
+ && summary.objects.every((item) => item.name.trim().length > 0 && item.responsibility.trim().length > 0)
32
+ && summary.interfaces.length > 0
33
+ && summary.dependency_direction.length > 0
34
+ && summary.change_points.length > 0
35
+ && summary.solid_risks.length > 0;
36
+ }
37
+ export function evaluateOodDesignGate(input) {
38
+ if (!requiresOodSolidContract(input.intent, input.route, input.changed_files)) {
39
+ return {
40
+ applicable: false,
41
+ allowed: true,
42
+ status: "not_applicable",
43
+ reason_zh: "低风险或非对象设计任务,无需引入 OOD/SOLID 工作包",
44
+ findings: [],
45
+ };
46
+ }
47
+ if (!hasCompleteDesignSummary(input.summary)) {
48
+ return {
49
+ applicable: true,
50
+ allowed: false,
51
+ status: "blocked",
52
+ reason_zh: "复杂编码任务缺少完整 OOD/SOLID 设计摘要,不得开始实现",
53
+ required_summary: input.summary ?? createOodDesignSummary(input.task_id, input.intent),
54
+ findings: [],
55
+ };
56
+ }
57
+ return {
58
+ applicable: true,
59
+ allowed: true,
60
+ status: "satisfied",
61
+ reason_zh: "OOD/SOLID 设计摘要已具备,可进入实现并在审查阶段复验",
62
+ required_summary: { ...input.summary, status: "satisfied" },
63
+ findings: [],
64
+ };
65
+ }
66
+ function addFinding(findings, principle, severity, file, evidence, suggestion_zh) {
67
+ findings.push({ principle, severity, file, evidence, suggestion_zh });
68
+ }
69
+ export function reviewSolidCode(fileContents) {
70
+ const findings = [];
71
+ for (const [file, content] of Object.entries(fileContents)) {
72
+ const lowered = file.toLowerCase();
73
+ if (/controller/.test(lowered)
74
+ && /(?:repository\.|mapper\.|entitymanager|save\s*\(|@Transactional|calculate|compute)/i.test(content)) {
75
+ addFinding(findings, "SRP", "hard_fail", file, "Controller 同时出现持久化、事务或业务计算职责", "将业务规则与持久化移入应用服务,Controller 仅处理协议适配、校验和响应映射。");
76
+ }
77
+ if (/(?:service|usecase|application)/.test(lowered)
78
+ && /new\s+(?:RestTemplate|WebClient|HttpClient|Stripe|S3|OpenAI|Twilio|Axios|.*Repository)\s*\(/i.test(content)) {
79
+ addFinding(findings, "DIP", "hard_fail", file, "业务服务直接构造外部依赖或仓储实现", "通过端口接口与依赖注入隔离基础设施实现。");
80
+ }
81
+ if (/interface\s+\w+[\s\S]{0,800}(?:upload|export|notify|delete|approve)[\s\S]{0,800}(?:upload|export|notify|delete|approve)/i.test(content)
82
+ && /(?:UnsupportedOperationException|throw new Error\(['\"]not implemented)/i.test(content)) {
83
+ addFinding(findings, "ISP", "hard_fail", file, "实现被迫抛出未支持操作,接口职责过宽", "拆分为客户端真正需要的细粒度接口。");
84
+ }
85
+ if (/(?:extends|implements)\s+\w+[\s\S]{0,500}(?:UnsupportedOperationException|throw new Error\(['\"]unsupported)/i.test(content)) {
86
+ addFinding(findings, "LSP", "hard_fail", file, "子类型拒绝父契约操作", "重构抽象层级,确保替换后仍满足原契约。");
87
+ }
88
+ const branching = (content.match(/\b(?:if|else if|switch)\s*\([^)]*(?:type|status|kind|strategy)/gi) ?? []).length;
89
+ if (branching >= 3) {
90
+ addFinding(findings, "OCP", "warning", file, "同一变化维度出现多处分支扩展点", "用策略/处理器注册方式隔离新增类型,减少修改既有分支。");
91
+ }
92
+ if (/(?:component|page|\.tsx$|\.vue$)/.test(lowered)
93
+ && /(?:fetch\(|axios\.|apiClient|request\()/i.test(content)
94
+ && /(?:useState|useEffect|computed\(|ref\(|watch\()/i.test(content)
95
+ && /(?:if\s*\(|switch\s*\()/i.test(content)) {
96
+ addFinding(findings, "SRP", "hard_fail", file, "复杂 UI 组件混合远程调用、状态编排与业务判断", "拆分展示组件、状态 hook/composable 与 API client/业务服务。");
97
+ }
98
+ }
99
+ return findings;
100
+ }
101
+ export function hasBlockingSolidFindings(findings) {
102
+ return findings.some((finding) => finding.severity === "hard_fail");
103
+ }
104
+ export function evaluateOverdesignRisk(intent, summary) {
105
+ if (!LOW_RISK_KEYWORDS.test(intent) || !summary || summary.objects.length < 4)
106
+ return [];
107
+ return [{
108
+ principle: "OVERDESIGN",
109
+ severity: "warning",
110
+ file: "OOD设计摘要",
111
+ evidence: "低风险修改引入多个对象与抽象边界",
112
+ suggestion_zh: "保持最小实现,不为简单修改提前引入复杂对象结构。",
113
+ }];
114
+ }
115
+ //# sourceMappingURL=ood_solid_contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ood_solid_contract.js","sourceRoot":"","sources":["../../src/engine/ood_solid_contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 项目阶段检测器 — 问题六十五。
3
+ *
4
+ * 综合项目状态(配置、知识、设计产物、任务)判断当前项目生命周期阶段。
5
+ * 不只看一个字段,综合 config、knowledge、design、task 多维信号。
6
+ */
7
+ import type { ProjectStage, StageExplanation } from "./workflow_navigation_contract.js";
8
+ /**
9
+ * 检测项目当前所处阶段。
10
+ * 综合判断: config 存在性/确认状态、knowledge 可用性、设计产物状态、任务执行状态。
11
+ */
12
+ export declare function detectProjectStage(projectPath: string): Promise<ProjectStage>;
13
+ /**
14
+ * 获取项目阶段的中文解释。
15
+ */
16
+ export declare function explainProjectStage(stage: ProjectStage): StageExplanation;
17
+ //# sourceMappingURL=project_stage_detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project_stage_detector.d.ts","sourceRoot":"","sources":["../../src/engine/project_stage_detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAIxF;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA8HnF;AAsDD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,gBAAgB,CASzE"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * 项目阶段检测器 — 问题六十五。
3
+ *
4
+ * 综合项目状态(配置、知识、设计产物、任务)判断当前项目生命周期阶段。
5
+ * 不只看一个字段,综合 config、knowledge、design、task 多维信号。
6
+ */
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import { resolveProjectConfig, getProjectKnowledgeDir } from "../knowledge/loader.js";
10
+ import { debug } from "./logger.js";
11
+ /**
12
+ * 检测项目当前所处阶段。
13
+ * 综合判断: config 存在性/确认状态、knowledge 可用性、设计产物状态、任务执行状态。
14
+ */
15
+ export async function detectProjectStage(projectPath) {
16
+ debug("项目阶段检测", "开始检测", projectPath);
17
+ const soloforgeDir = path.join(projectPath, ".soloforge");
18
+ const configPath = path.join(soloforgeDir, "config.yaml");
19
+ // 1. 未初始化
20
+ if (!fs.existsSync(soloforgeDir)) {
21
+ return "uninitialized";
22
+ }
23
+ // 2. 已初始化但未持久化配置,不能重复建议 init
24
+ if (!fs.existsSync(configPath)) {
25
+ return "configuration_pending";
26
+ }
27
+ // 3. 配置未确认
28
+ const evidencePath = path.join(soloforgeDir, "config.evidence.json");
29
+ if (!fs.existsSync(evidencePath)) {
30
+ return "configuration_pending";
31
+ }
32
+ try {
33
+ const evidenceRaw = JSON.parse(fs.readFileSync(evidencePath, "utf-8"));
34
+ const confirmedFields = Object.values(evidenceRaw.fields ?? {});
35
+ const allConfirmed = confirmedFields.length > 0
36
+ && confirmedFields.every((f) => f.confidence === "high"
37
+ && (f.confidence_source === "confirmed" || f.confidence_source === "detected"));
38
+ if (!allConfirmed) {
39
+ return "configuration_pending";
40
+ }
41
+ }
42
+ catch {
43
+ return "configuration_pending";
44
+ }
45
+ // 3. 知识就绪检查
46
+ let config;
47
+ try {
48
+ const resolved = await resolveProjectConfig(projectPath);
49
+ config = resolved.config;
50
+ }
51
+ catch {
52
+ return "configuration_pending";
53
+ }
54
+ const knowledgeDir = getProjectKnowledgeDir(config);
55
+ const hasKnowledge = fs.existsSync(knowledgeDir);
56
+ if (!hasKnowledge) {
57
+ return "knowledge_ready";
58
+ }
59
+ // 4-6. 检查任务状态和设计产物
60
+ const stateDir = path.join(soloforgeDir, "state");
61
+ let hasDesignInProgress = false;
62
+ let hasDesignReady = false;
63
+ let hasExecutingTask = false;
64
+ let hasVerifiedDeliveryReady = false;
65
+ let hasDelivered = false;
66
+ if (fs.existsSync(stateDir)) {
67
+ const taskFiles = fs.readdirSync(stateDir).filter((f) => f.startsWith("task-") && f.endsWith(".json"));
68
+ for (const tf of taskFiles) {
69
+ try {
70
+ const task = JSON.parse(fs.readFileSync(path.join(stateDir, tf), "utf-8"));
71
+ // 设计产物检查
72
+ const designPack = task.design_artifact_pack;
73
+ if (designPack) {
74
+ if (designPack.status === "implementation_ready" || designPack.status === "confirmed") {
75
+ hasDesignReady = true;
76
+ }
77
+ else if (designPack.status && designPack.status !== "superseded") {
78
+ hasDesignInProgress = true;
79
+ }
80
+ }
81
+ // 任务执行状态
82
+ const status = task.status;
83
+ if (["executing", "verifying", "learning"].includes(status)) {
84
+ hasExecutingTask = true;
85
+ }
86
+ // 交付就绪
87
+ if (status === "done" && task.verification?.status === "passed") {
88
+ if (task.delivery?.delivery_executed) {
89
+ hasDelivered = true;
90
+ }
91
+ else {
92
+ hasVerifiedDeliveryReady = true;
93
+ }
94
+ }
95
+ }
96
+ catch {
97
+ // 忽略损坏的任务文件
98
+ }
99
+ }
100
+ }
101
+ // 8. 已发布
102
+ if (hasDelivered) {
103
+ return "released";
104
+ }
105
+ // 7. 交付就绪
106
+ if (hasVerifiedDeliveryReady) {
107
+ return "delivery_ready";
108
+ }
109
+ // 6. 开发中
110
+ if (hasExecutingTask) {
111
+ return "development_in_progress";
112
+ }
113
+ // 5. 实现就绪(设计通过审计)
114
+ if (hasDesignReady) {
115
+ return "implementation_ready";
116
+ }
117
+ // 4. 设计进行中
118
+ if (hasDesignInProgress) {
119
+ return "design_in_progress";
120
+ }
121
+ // 3. 知识就绪(默认)
122
+ return "knowledge_ready";
123
+ }
124
+ /** 项目阶段中文标签映射 */
125
+ const PROJECT_STAGE_LABELS = {
126
+ uninitialized: "未初始化",
127
+ configuration_pending: "配置待确认",
128
+ knowledge_ready: "知识就绪",
129
+ design_in_progress: "设计进行中",
130
+ implementation_ready: "实现就绪",
131
+ development_in_progress: "开发进行中",
132
+ delivery_ready: "交付就绪",
133
+ released: "已发布",
134
+ post_release_observation: "发布后观察",
135
+ };
136
+ /** 项目阶段中文描述 */
137
+ const PROJECT_STAGE_DESCRIPTIONS = {
138
+ uninitialized: "项目尚未运行 soloforge init,缺少 .soloforge/ 目录或配置文件",
139
+ configuration_pending: "配置文件存在但字段尚未确认,建议运行 soloforge config confirm 确认关键字段",
140
+ knowledge_ready: "配置已确认、知识库已就绪,可以开始接收开发任务",
141
+ design_in_progress: "架构/数据库/API 设计产物正在进行中,尚未通过审计",
142
+ implementation_ready: "设计产物已通过审计复验,可以开始编码实现",
143
+ development_in_progress: "已有任务在编码/验证阶段",
144
+ delivery_ready: "任务已通过验证,准备交付",
145
+ released: "已发布上线",
146
+ post_release_observation: "发布后观察期,建议验证、监控、收集反馈",
147
+ };
148
+ /** 项目阶段必要证据 */
149
+ const PROJECT_STAGE_EVIDENCE = {
150
+ uninitialized: [],
151
+ configuration_pending: [".soloforge/config.yaml 存在"],
152
+ knowledge_ready: ["config 已确认", "knowledge 目录存在"],
153
+ design_in_progress: ["design_artifact_pack 状态非 implementation_ready"],
154
+ implementation_ready: ["design_artifact_pack.status === implementation_ready"],
155
+ development_in_progress: ["存在 executing/verifying/learning 状态任务"],
156
+ delivery_ready: ["任务验证通过", "delivery readiness 评估通过"],
157
+ released: ["delivery 已执行"],
158
+ post_release_observation: ["已发布"],
159
+ };
160
+ /** 项目阶段可能的下一阶段 */
161
+ const PROJECT_STAGE_NEXT = {
162
+ uninitialized: ["configuration_pending"],
163
+ configuration_pending: ["knowledge_ready", "uninitialized"],
164
+ knowledge_ready: ["design_in_progress", "development_in_progress"],
165
+ design_in_progress: ["implementation_ready"],
166
+ implementation_ready: ["development_in_progress"],
167
+ development_in_progress: ["delivery_ready"],
168
+ delivery_ready: ["released"],
169
+ released: ["post_release_observation"],
170
+ post_release_observation: [],
171
+ };
172
+ /**
173
+ * 获取项目阶段的中文解释。
174
+ */
175
+ export function explainProjectStage(stage) {
176
+ return {
177
+ stage,
178
+ level: "project",
179
+ label_zh: PROJECT_STAGE_LABELS[stage],
180
+ description_zh: PROJECT_STAGE_DESCRIPTIONS[stage],
181
+ required_evidence: PROJECT_STAGE_EVIDENCE[stage],
182
+ next_possible_stages: PROJECT_STAGE_NEXT[stage],
183
+ };
184
+ }
185
+ //# sourceMappingURL=project_stage_detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project_stage_detector.js","sourceRoot":"","sources":["../../src/engine/project_stage_detector.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"release_issue_scenario_registry.d.ts","sourceRoot":"","sources":["../../src/engine/release_issue_scenario_registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE;QACjB,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,gBAAgB,CAAC,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,2BAA2B,CAAC,EAAE,MAAM,CAAC;QACrC,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe;IACf,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAChD;AAyzCD,eAAe;AACf,wBAAgB,wBAAwB,IAAI,aAAa,EAAE,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,GACd;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAqCzL;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAavF"}
1
+ {"version":3,"file":"release_issue_scenario_registry.d.ts","sourceRoot":"","sources":["../../src/engine/release_issue_scenario_registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE;QACjB,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,gBAAgB,CAAC,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,2BAA2B,CAAC,EAAE,MAAM,CAAC;QACrC,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe;IACf,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAChD;AA+hDD,eAAe;AACf,wBAAgB,wBAAwB,IAAI,aAAa,EAAE,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,GACd;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAqCzL;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAavF"}
@@ -396,7 +396,20 @@ const RELEASE_ISSUE_SCENARIOS = [
396
396
  task_id: taskId,
397
397
  decision_workshop: genericWorkshop,
398
398
  });
399
- harness.parseResult(exp2Raw);
399
+ const exp2 = harness.parseResult(exp2Raw);
400
+ if (exp2.diagnostic_code === "SF-OOD-6601") {
401
+ const summary = exp2.ood_solid_summary;
402
+ summary.objects = [{ name: "ReleaseValidationService", responsibility: "编排发布验证和回滚策略" }];
403
+ summary.interfaces = ["ReleaseVerifier", "RollbackExecutor"];
404
+ summary.dependency_direction = ["ReleaseValidationService -> ReleaseVerifier"];
405
+ summary.change_points = ["验证策略", "回滚策略"];
406
+ summary.solid_risks = ["DIP: 执行器通过接口注入", "SRP: 发布编排不承担部署细节"];
407
+ await harness.callTool("sf_expand", {
408
+ task_id: taskId,
409
+ decision_workshop: genericWorkshop,
410
+ ood_solid_summary: summary,
411
+ });
412
+ }
400
413
  }
401
414
  await harness.setupPlanGate(taskId);
402
415
  // 验证前置: sf_verify → sf_record_verification_execution
@@ -1282,6 +1295,222 @@ const RELEASE_ISSUE_SCENARIOS = [
1282
1295
  }
1283
1296
  },
1284
1297
  },
1298
+ // ── 问题六十八: 代码可维护性与可观测性契约 ──
1299
+ {
1300
+ scenario_id: "release-scenario-code-observability-payment-status-no-log",
1301
+ covering_problem: "problem-68",
1302
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1303
+ production_entrypoint: "sf_expand → CodeObservabilityGate → sf_review → reviewMissingLogs → sf_deliver → evaluateDeliveryBlock",
1304
+ expected_outcome: "支付/账单状态更新缺少业务日志 → hard_fail 阻断交付",
1305
+ runner: async () => {
1306
+ const mod = await import("./code_maintainability_observability_contract.js");
1307
+ const findings = mod.reviewMissingLogs({
1308
+ "PaymentService.java": `public void refund(String orderId, BigDecimal amount) {
1309
+ orderRepository.save(order);
1310
+ paymentGateway.refund(orderId, amount);
1311
+ }`,
1312
+ });
1313
+ const blocked = mod.hasBlockingObservabilityFindings(findings);
1314
+ return {
1315
+ scenario_id: "release-scenario-code-observability-payment-status-no-log",
1316
+ status: blocked ? "pass" : "fail",
1317
+ evidence: blocked ? "hard_fail: 支付写操作无日志被检测到" : "未检测到支付写操作无日志",
1318
+ production_trace: { tool_entrypoint: "reviewMissingLogs", diagnostic_codes: [blocked ? "hard_fail" : "missed"], gates_consumed: ["sf_review"] },
1319
+ };
1320
+ },
1321
+ },
1322
+ {
1323
+ scenario_id: "release-scenario-code-observability-permission-denied-no-log",
1324
+ covering_problem: "problem-68",
1325
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1326
+ production_entrypoint: "sf_expand → CodeObservabilityGate → sf_review → reviewMissingLogs → sf_deliver → evaluateDeliveryBlock",
1327
+ expected_outcome: "权限拒绝无安全日志 → hard_fail 阻断",
1328
+ runner: async () => {
1329
+ const mod = await import("./code_maintainability_observability_contract.js");
1330
+ const findings = mod.reviewMissingLogs({
1331
+ "AuthController.java": `public void checkPermission(String userId, String resource) {
1332
+ if (!roleService.hasAccess(userId, resource)) {
1333
+ throw new AccessDeniedException("forbidden");
1334
+ }
1335
+ }`,
1336
+ });
1337
+ const blocked = mod.hasBlockingObservabilityFindings(findings);
1338
+ return {
1339
+ scenario_id: "release-scenario-code-observability-permission-denied-no-log",
1340
+ status: blocked ? "pass" : "fail",
1341
+ evidence: blocked ? "hard_fail: 权限拒绝无日志被检测到" : "未检测到权限拒绝无日志",
1342
+ production_trace: { tool_entrypoint: "reviewMissingLogs", diagnostic_codes: [blocked ? "hard_fail" : "missed"], gates_consumed: ["sf_review"] },
1343
+ };
1344
+ },
1345
+ },
1346
+ {
1347
+ scenario_id: "release-scenario-code-observability-catch-swallow",
1348
+ covering_problem: "problem-68",
1349
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1350
+ production_entrypoint: "sf_expand → CodeObservabilityGate → sf_review → reviewMissingLogs → sf_deliver → evaluateDeliveryBlock",
1351
+ expected_outcome: "catch 后吞异常无日志 → hard_fail 阻断",
1352
+ runner: async () => {
1353
+ const mod = await import("./code_maintainability_observability_contract.js");
1354
+ const findings = mod.reviewMissingLogs({
1355
+ "OrderService.ts": `async processOrder(orderId: string) {
1356
+ try {
1357
+ await this.client.submit(orderId);
1358
+ } catch (e) {
1359
+ return false;
1360
+ }
1361
+ }`,
1362
+ });
1363
+ const blocked = mod.hasBlockingObservabilityFindings(findings);
1364
+ return {
1365
+ scenario_id: "release-scenario-code-observability-catch-swallow",
1366
+ status: blocked ? "pass" : "fail",
1367
+ evidence: blocked ? "hard_fail: catch 吞异常被检测到" : "未检测到 catch 吞异常",
1368
+ production_trace: { tool_entrypoint: "reviewMissingLogs", diagnostic_codes: [blocked ? "hard_fail" : "missed"], gates_consumed: ["sf_review"] },
1369
+ };
1370
+ },
1371
+ },
1372
+ {
1373
+ scenario_id: "release-scenario-code-observability-sensitive-log",
1374
+ covering_problem: "problem-68",
1375
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1376
+ production_entrypoint: "sf_expand → CodeObservabilityGate → sf_review → detectSensitiveLogs → sf_deliver → evaluateDeliveryBlock",
1377
+ expected_outcome: "日志输出 token/password/手机号全量 → hard_fail 阻断",
1378
+ runner: async () => {
1379
+ const mod = await import("./code_maintainability_observability_contract.js");
1380
+ const findings = mod.detectSensitiveLogs({
1381
+ "UserService.ts": `function login(user) {
1382
+ logger.info("user login", { token: "eyJhbGciOiJIUzI1NiJ9.xxxxx", password: user.password, phone: "13812345678" });
1383
+ }`,
1384
+ });
1385
+ const blocked = mod.hasBlockingObservabilityFindings(findings);
1386
+ return {
1387
+ scenario_id: "release-scenario-code-observability-sensitive-log",
1388
+ status: blocked ? "pass" : "fail",
1389
+ evidence: blocked ? `hard_fail: 敏感信息泄漏被检测到 (${findings.length} findings)` : "未检测到敏感信息泄漏",
1390
+ production_trace: { tool_entrypoint: "detectSensitiveLogs", diagnostic_codes: [blocked ? "hard_fail" : "missed"], gates_consumed: ["sf_review"] },
1391
+ };
1392
+ },
1393
+ },
1394
+ {
1395
+ scenario_id: "release-scenario-code-observability-complex-rule-no-comment",
1396
+ covering_problem: "problem-68",
1397
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1398
+ production_entrypoint: "sf_expand → CodeObservabilityGate → sf_review → reviewCommentQuality → sf_deliver",
1399
+ expected_outcome: "复杂金额计算无注释 → warning",
1400
+ runner: async () => {
1401
+ const mod = await import("./code_maintainability_observability_contract.js");
1402
+ const findings = mod.reviewCommentQuality({
1403
+ "BillingService.java": `// 金额计算逻辑
1404
+ public BigDecimal calculateSubsidy(Order order) {
1405
+ BigDecimal base = order.getAmount().multiply(new BigDecimal("0.8"));
1406
+ BigDecimal discount = base.subtract(order.getDeducted());
1407
+ return discount.max(BigDecimal.ZERO);
1408
+ }`,
1409
+ });
1410
+ const hasCommentWarning = findings.some(f => f.category === "missing_comment_complex");
1411
+ // 上面有注释不会触发缺失检测;下面测试无注释的负例:
1412
+ const findingsNoComment = mod.reviewCommentQuality({
1413
+ "金额计算/BillingService.java": `public BigDecimal calculateSubsidy(Order order) {
1414
+ BigDecimal base = order.getAmount().multiply(new BigDecimal("0.8"));
1415
+ BigDecimal discount = base.subtract(order.getDeducted());
1416
+ return discount.max(BigDecimal.ZERO);
1417
+ }`,
1418
+ });
1419
+ const detected = findingsNoComment.some(f => f.category === "missing_comment_complex");
1420
+ return {
1421
+ scenario_id: "release-scenario-code-observability-complex-rule-no-comment",
1422
+ status: detected ? "pass" : "fail",
1423
+ evidence: detected ? "warning: 无注释复杂逻辑被检测到" : "未检测到无注释复杂逻辑",
1424
+ production_trace: { tool_entrypoint: "reviewCommentQuality", diagnostic_codes: [detected ? "warning" : "missed"], gates_consumed: ["sf_review"] },
1425
+ };
1426
+ },
1427
+ },
1428
+ {
1429
+ scenario_id: "release-scenario-code-observability-low-risk-skip",
1430
+ covering_problem: "problem-68",
1431
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1432
+ production_entrypoint: "sf_classify → sf_expand (低风险) → 不触发可观测性门禁",
1433
+ expected_outcome: "简单文案修改不触发代码可维护性/可观测性契约",
1434
+ runner: async () => {
1435
+ const { createToolHarness } = await import("./release_tool_harness.js");
1436
+ const harness = await createToolHarness();
1437
+ try {
1438
+ const intent = "修复 README 文案错别字";
1439
+ const clsRaw = await harness.callTool("sf_classify", { intent });
1440
+ const cls = harness.parseResult(clsRaw);
1441
+ const taskId = cls.task_id;
1442
+ if (!taskId)
1443
+ return { scenario_id: "release-scenario-code-observability-low-risk-skip", status: "fail", error: "sf_classify 未返回 task_id" };
1444
+ const expRaw = await harness.callTool("sf_expand", { task_id: taskId });
1445
+ const exp = harness.parseResult(expRaw);
1446
+ // 低风险任务不应触发 SF-OBS-6801 诊断码
1447
+ const notBlocked = exp.diagnostic_code !== "SF-OBS-6801";
1448
+ return {
1449
+ scenario_id: "release-scenario-code-observability-low-risk-skip",
1450
+ status: notBlocked ? "pass" : "fail",
1451
+ evidence: notBlocked ? "低风险任务正确跳过可观测性门禁" : "低风险任务被错误触发可观测性门禁",
1452
+ production_trace: { tool_entrypoint: "sf_classify+sf_expand", diagnostic_codes: [exp.status ?? "ok", exp.diagnostic_code ?? "none"], gates_consumed: ["sf_classify", "sf_expand"] },
1453
+ };
1454
+ }
1455
+ catch (e) {
1456
+ return { scenario_id: "release-scenario-code-observability-low-risk-skip", status: "fail", error: e.message };
1457
+ }
1458
+ finally {
1459
+ await harness.cleanup();
1460
+ }
1461
+ },
1462
+ },
1463
+ {
1464
+ scenario_id: "release-scenario-code-observability-project-logger-detected",
1465
+ covering_problem: "problem-68",
1466
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1467
+ production_entrypoint: "sf_expand → CodeObservabilityGate → detectProjectLogger",
1468
+ expected_outcome: "Java/Spring/Node/NestJS 项目能正确检测 logger 类型",
1469
+ runner: async () => {
1470
+ const mod = await import("./code_maintainability_observability_contract.js");
1471
+ const javaLogger = mod.detectProjectLogger({
1472
+ "Application.java": "import org.slf4j.LoggerFactory; private static final Logger log = LoggerFactory.getLogger(App.class);",
1473
+ });
1474
+ const pinoLogger = mod.detectProjectLogger({
1475
+ "index.ts": "import pino from 'pino'; const logger = pino();",
1476
+ });
1477
+ const nestjsLogger = mod.detectProjectLogger({
1478
+ "app.service.ts": "import { Logger } from '@nestjs/common';",
1479
+ });
1480
+ const ok = javaLogger.type === "slf4j" && pinoLogger.type === "pino" && nestjsLogger.type === "nestjs_logger";
1481
+ return {
1482
+ scenario_id: "release-scenario-code-observability-project-logger-detected",
1483
+ status: ok ? "pass" : "fail",
1484
+ evidence: ok ? `检测: ${javaLogger.type}, ${pinoLogger.type}, ${nestjsLogger.type}` : `检测失败: ${javaLogger.type}, ${pinoLogger.type}, ${nestjsLogger.type}`,
1485
+ production_trace: { tool_entrypoint: "detectProjectLogger", diagnostic_codes: [javaLogger.type, pinoLogger.type, nestjsLogger.type], gates_consumed: ["sf_expand"] },
1486
+ };
1487
+ },
1488
+ },
1489
+ {
1490
+ scenario_id: "release-scenario-code-observability-migration-audit-log",
1491
+ covering_problem: "problem-68",
1492
+ test_files: ["tests/engine/code_maintainability_observability_contract.test.ts"],
1493
+ production_entrypoint: "sf_expand → CodeObservabilityGate → sf_review → reviewMissingLogs → sf_deliver",
1494
+ expected_outcome: "迁移脚本/数据修复无审计日志 → hard_fail",
1495
+ runner: async () => {
1496
+ const mod = await import("./code_maintainability_observability_contract.js");
1497
+ const findings = mod.reviewMissingLogs({
1498
+ "scripts/data_fix_order_status.ts": `async function migrateOrderStatus() {
1499
+ const orders = await db.query("SELECT * FROM orders WHERE status IS NULL");
1500
+ for (const order of orders) {
1501
+ await db.update("UPDATE orders SET status = 'pending' WHERE id = ?", [order.id]);
1502
+ }
1503
+ }`,
1504
+ });
1505
+ const blocked = mod.hasBlockingObservabilityFindings(findings);
1506
+ return {
1507
+ scenario_id: "release-scenario-code-observability-migration-audit-log",
1508
+ status: blocked ? "pass" : "fail",
1509
+ evidence: blocked ? "hard_fail: 迁移脚本无审计日志被检测到" : "未检测到迁移脚本无审计日志",
1510
+ production_trace: { tool_entrypoint: "reviewMissingLogs", diagnostic_codes: [blocked ? "hard_fail" : "missed"], gates_consumed: ["sf_review"] },
1511
+ };
1512
+ },
1513
+ },
1285
1514
  ];
1286
1515
  /** 获取全量场景定义 */
1287
1516
  export function getReleaseIssueScenarios() {