soloforge 1.3.3 → 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 (75) hide show
  1. package/README.md +9 -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 +109 -25
  6. package/dist/adapters/claude_code/tools.js.map +1 -1
  7. package/dist/adapters/shared/workflow_template.js +2 -2
  8. package/dist/adapters/shared/workflow_template.js.map +1 -1
  9. package/dist/bin/soloforge.js +65 -0
  10. package/dist/bin/soloforge.js.map +1 -1
  11. package/dist/engine/asset_manifest.d.ts.map +1 -1
  12. package/dist/engine/asset_manifest.js +11 -0
  13. package/dist/engine/asset_manifest.js.map +1 -1
  14. package/dist/engine/code_maintainability_observability_contract.d.ts +74 -0
  15. package/dist/engine/code_maintainability_observability_contract.d.ts.map +1 -0
  16. package/dist/engine/code_maintainability_observability_contract.js +473 -0
  17. package/dist/engine/code_maintainability_observability_contract.js.map +1 -0
  18. package/dist/engine/config_write_boundary.d.ts +29 -0
  19. package/dist/engine/config_write_boundary.d.ts.map +1 -0
  20. package/dist/engine/config_write_boundary.js +69 -0
  21. package/dist/engine/config_write_boundary.js.map +1 -0
  22. package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
  23. package/dist/engine/consumable_asset_registry.js +49 -1
  24. package/dist/engine/consumable_asset_registry.js.map +1 -1
  25. package/dist/engine/diagnostic_registry.d.ts +12 -0
  26. package/dist/engine/diagnostic_registry.d.ts.map +1 -1
  27. package/dist/engine/diagnostic_registry.js +62 -0
  28. package/dist/engine/diagnostic_registry.js.map +1 -1
  29. package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -1
  30. package/dist/engine/dual_layer_mechanism_registry.js +194 -1
  31. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  32. package/dist/engine/explicit_asset_registry.d.ts.map +1 -1
  33. package/dist/engine/explicit_asset_registry.js +134 -0
  34. package/dist/engine/explicit_asset_registry.js.map +1 -1
  35. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  36. package/dist/engine/implementation_roadmap_registry.js +45 -1
  37. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  38. package/dist/engine/knowledge_governance_gate.d.ts +38 -0
  39. package/dist/engine/knowledge_governance_gate.d.ts.map +1 -0
  40. package/dist/engine/knowledge_governance_gate.js +123 -0
  41. package/dist/engine/knowledge_governance_gate.js.map +1 -0
  42. package/dist/engine/log_governance.d.ts +25 -0
  43. package/dist/engine/log_governance.d.ts.map +1 -0
  44. package/dist/engine/log_governance.js +76 -0
  45. package/dist/engine/log_governance.js.map +1 -0
  46. package/dist/engine/mechanism_contract_registry.d.ts +1 -0
  47. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  48. package/dist/engine/mechanism_contract_registry.js +104 -0
  49. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  50. package/dist/engine/mechanism_health_check.d.ts +23 -0
  51. package/dist/engine/mechanism_health_check.d.ts.map +1 -0
  52. package/dist/engine/mechanism_health_check.js +140 -0
  53. package/dist/engine/mechanism_health_check.js.map +1 -0
  54. package/dist/engine/observability.js +1 -1
  55. package/dist/engine/observability.js.map +1 -1
  56. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -1
  57. package/dist/engine/release_issue_scenario_registry.js +216 -0
  58. package/dist/engine/release_issue_scenario_registry.js.map +1 -1
  59. package/dist/engine/release_readiness_gate.d.ts +3 -0
  60. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  61. package/dist/engine/release_readiness_gate.js +260 -8
  62. package/dist/engine/release_readiness_gate.js.map +1 -1
  63. package/dist/engine/team_awareness.js +6 -6
  64. package/dist/engine/team_awareness.js.map +1 -1
  65. package/dist/types.d.ts +4 -0
  66. package/dist/types.d.ts.map +1 -1
  67. package/package.json +1 -1
  68. 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
  69. 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
  70. 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
  71. 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
  72. 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
  73. 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
  74. 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
  75. 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
@@ -0,0 +1,473 @@
1
+ /**
2
+ * 用户项目代码可维护性与可观测性契约。
3
+ *
4
+ * 治理对象是用户项目代码,不是 SoloForge 自身。
5
+ * 覆盖必要注释、结构化日志、错误日志、审计日志、
6
+ * 敏感信息脱敏和低风险跳过。
7
+ */
8
+ /* ── 关键词 ─────────────────────────────────────── */
9
+ const OBSERVABILITY_KEYWORDS = /业务|支付|金额|账单|合同|入住|权限|登录|安全|通知|异步|状态机|审批|补贴|核销|外部系统|webhook|回调|异常处理|重试|补偿|事务|幂等|并发|数据修复|批处理|迁移|Controller|Service|UseCase|Domain|Repository|payment|billing|invoice|contract|permission|auth|security|state|workflow|migration|refund|charge|order/i;
10
+ const LOW_RISK_KEYWORDS = /错别字|拼写|文案|样式|css|颜色|README|配置值|测试数据|fixture|getter|setter|简单类型|类型定义|interface\s+\w+\s*\{|type\s+\w+\s*=/i;
11
+ const CRITICAL_LOG_KEYWORDS = /支付|账单|金额|退款|核销|补贴|缴费|payment|billing|refund|charge|invoice/i;
12
+ const SECURITY_LOG_KEYWORDS = /权限|登录|认证|越权|安全|role|auth|permission|security|access.?denied|forbidden/i;
13
+ const STATE_CHANGE_KEYWORDS = /状态|流转|status|state|transition|pending|approved|rejected|cancelled/i;
14
+ const EXTERNAL_CALL_KEYWORDS = /外部|第三方|API|调用|HTTP|RPC|webhook|callback|RestTemplate|WebClient|fetch|axios/i;
15
+ const MIGRATION_KEYWORDS = /迁移|修复|批处理|migration|batch|data.?fix|script/i;
16
+ const COMPLEX_RULE_KEYWORDS = /金额计算|计算逻辑|领域不变量|状态机|幂等|并发控制|分布式锁|算法|formula|invariant|idempoten|concurr/i;
17
+ const SENSITIVE_PATTERNS = [
18
+ { pattern: /(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key)\s*[:=]\s*["'][^"']{4,}/i, name_zh: "明文密钥/令牌" },
19
+ { pattern: /(?:cookie|session[_-]?id|set[_-]?cookie)\s*[:=]\s*["'][^"']{8,}/i, name_zh: "Cookie/会话" },
20
+ { pattern: /(?:手机号|phone|mobile|cell)\s*[:=]\s*["']?\d{11}/i, name_zh: "手机号全量" },
21
+ { pattern: /(?:身份证|id[_-]?card|id[_-]?number)\s*[:=]\s*["']?\d{15,18}/i, name_zh: "身份证全量" },
22
+ { pattern: /(?:银行卡|bank[_-]?card|card[_-]?number|pan)\s*[:=]\s*["']?\d{13,19}/i, name_zh: "银行卡全量" },
23
+ { pattern: /(?:健康|病历|诊断|处方|health|medical|diagnosis|prescription)/i, name_zh: "健康隐私" },
24
+ ];
25
+ // 日志输出中的敏感信息 — 区分声明与输出
26
+ const LOG_OUTPUT_SENSITIVE_PATTERNS = [
27
+ // logger.info({ token }) / console 输出含 password 字段的对象
28
+ { pattern: /(?:log|logger|LOG|console)\.(?:info|warn|error|debug|log|INFO|WARN|ERROR|DEBUG)\s*\(\s*\{[^}]*(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key|cookie|session[_-]?id)\b/i, name_zh: "日志对象含敏感字段" },
29
+ // console dot log 输出 user.password / log.info(data.secret)
30
+ { pattern: /(?:log|logger|LOG|console)\.(?:info|warn|error|debug|log|INFO|WARN|ERROR|DEBUG)\s*\([^)]*\b\w+\.(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key|cookie|session[_-]?id)\b/i, name_zh: "日志输出敏感属性值" },
31
+ // logger.info("token={}", token) / log.info("password=" + pwd) / log.info("token: %s", t)
32
+ { pattern: /(?:log|logger|LOG|console)\.(?:info|warn|error|debug|log|INFO|WARN|ERROR|DEBUG)\s*\(\s*["'][^"']*\b(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key|cookie|session[_-]?id)\s*[=::]\s*(?:["']?\s*\+|\{?\}|%[sd])/i, name_zh: "日志拼接/格式化敏感值" },
33
+ ];
34
+ /* ── 触发判断 ─────────────────────────────────── */
35
+ export function requiresCodeObservabilityContract(intent, route, changedFiles = []) {
36
+ const text = `${intent} ${changedFiles.join(" ")}`;
37
+ if (LOW_RISK_KEYWORDS.test(text) && !OBSERVABILITY_KEYWORDS.test(text))
38
+ return false;
39
+ const relevantRoute = !route
40
+ || ["code_change", "artifact_generation", "operation", "multi_stage_plan"].includes(route);
41
+ if (!relevantRoute)
42
+ return false;
43
+ if (!OBSERVABILITY_KEYWORDS.test(text))
44
+ return false;
45
+ // 简单修复/调试/查询不触发完整契约
46
+ if (/^(?:修复|调试|排查|查看|分析|解释|为什么|查一下|帮我看看|debug|fix\s+(?:a\s+)?(?:typo|lint|import|build))/i.test(intent.trim()))
47
+ return false;
48
+ return true;
49
+ }
50
+ /* ── 项目 logger 检测 ──────────────────────────── */
51
+ export function detectProjectLogger(fileContents) {
52
+ const allContent = Object.values(fileContents).join("\n");
53
+ if (/import\s+.*(?:LoggerFactory|@Slf4j|log\s*=.*Logger)/.test(allContent) || /log\.(info|warn|error|debug)\s*\(/.test(allContent)) {
54
+ return { type: "slf4j", import_pattern: "LoggerFactory.getLogger", call_pattern: "log.info/warn/error", confidence: "high" };
55
+ }
56
+ if (/import\s+.*(?:pino|from\s+['"]pino['"])/.test(allContent) || /(?:const|let)\s+\w*(?:logger|log)\s*=\s*pino/.test(allContent)) {
57
+ return { type: "pino", import_pattern: "import pino", call_pattern: "logger.info/warn/error", confidence: "high" };
58
+ }
59
+ if (/import\s+.*(?:winston|from\s+['"]winston['"])/.test(allContent) || /createLogger\s*\(/.test(allContent)) {
60
+ return { type: "winston", import_pattern: "import winston", call_pattern: "logger.info/warn/error", confidence: "high" };
61
+ }
62
+ if (/import\s+.*(?:@nestjs|NestJS|Logger\s*}\s*from\s+['"]@nestjs)/.test(allContent)) {
63
+ return { type: "nestjs_logger", import_pattern: "import { Logger } from '@nestjs/common'", call_pattern: "this.logger.log/warn/error", confidence: "high" };
64
+ }
65
+ const fileKeys = Object.keys(fileContents).join(" ");
66
+ const hasFrontendExt = /\.(?:vue|tsx|jsx|svelte)\b/.test(fileKeys);
67
+ const hasFrontendImport = /\.vue\s*['"]|\.tsx\s*['"]|\.jsx\s*['"]|react['"]|vue['"]/.test(allContent);
68
+ if (hasFrontendExt || hasFrontendImport) {
69
+ if (/(?:const|let)\s+\w*(?:logger|Logger)\s*=/.test(allContent)) {
70
+ return { type: "custom_logger", import_pattern: "项目封装 logger", call_pattern: "logger.info/warn/error", confidence: "medium" };
71
+ }
72
+ return { type: "frontend_project", import_pattern: "前端项目", call_pattern: "生产环境禁止 console", confidence: "medium" };
73
+ }
74
+ if (/(?:const|let)\s+\w*(?:logger|Logger)\s*=/.test(allContent)) {
75
+ return { type: "custom_logger", import_pattern: "项目封装 logger", call_pattern: "logger.info/warn/error", confidence: "medium" };
76
+ }
77
+ return { type: "none_detected", import_pattern: "无", call_pattern: "console.log", confidence: "low" };
78
+ }
79
+ /* ── 工作包创建 ───────────────────────────────── */
80
+ export function createCodeObservabilityWorkPackage(taskId, intent, loggerInfo) {
81
+ const text = intent;
82
+ const requiredLogs = [];
83
+ const sensitiveFields = [];
84
+ const requiredComments = [];
85
+ if (CRITICAL_LOG_KEYWORDS.test(text)) {
86
+ requiredLogs.push("支付/金额/退款/核销状态变更必须有业务日志,含对象 ID、操作人、前后状态");
87
+ sensitiveFields.push("payment_amount", "card_number", "bank_account");
88
+ }
89
+ if (SECURITY_LOG_KEYWORDS.test(text)) {
90
+ requiredLogs.push("权限拒绝/越权访问必须有安全日志,含操作人、目标资源、拒绝原因");
91
+ }
92
+ if (STATE_CHANGE_KEYWORDS.test(text)) {
93
+ requiredLogs.push("关键状态流转必须有日志,含流转前后状态和触发原因");
94
+ }
95
+ if (EXTERNAL_CALL_KEYWORDS.test(text)) {
96
+ requiredLogs.push("外部调用失败/超时/重试必须有日志,含目标、响应码/错误、重试次数");
97
+ }
98
+ if (MIGRATION_KEYWORDS.test(text)) {
99
+ requiredLogs.push("数据修复/迁移脚本必须有审计日志,含修复前值、修复后值、影响行数");
100
+ }
101
+ if (COMPLEX_RULE_KEYWORDS.test(text)) {
102
+ requiredComments.push("复杂业务规则必须有注释说明原因(为什么),不得只复述代码行为(做什么)");
103
+ }
104
+ if (/事务|幂等|并发|分布式锁/i.test(text)) {
105
+ requiredComments.push("事务边界、幂等策略、并发控制必须有注释说明设计意图");
106
+ }
107
+ return {
108
+ task_id: taskId,
109
+ status: "required",
110
+ applicability_reason_zh: `该任务涉及业务编码,需确认代码可维护性与可观测性约束: ${intent}`,
111
+ required_logs: requiredLogs,
112
+ required_comments: requiredComments,
113
+ sensitive_fields: sensitiveFields,
114
+ detected_logger: loggerInfo,
115
+ };
116
+ }
117
+ function workPackageSatisfied(wp) {
118
+ return !!wp && wp.status === "satisfied";
119
+ }
120
+ /* ── Gate ─────────────────────────────────────── */
121
+ export function evaluateCodeObservabilityGate(input) {
122
+ if (!requiresCodeObservabilityContract(input.intent, input.route, input.changed_files)) {
123
+ return {
124
+ applicable: false,
125
+ allowed: true,
126
+ status: "not_applicable",
127
+ reason_zh: "低风险或非业务编码任务,不触发代码可维护性/可观测性工作包",
128
+ findings: [],
129
+ };
130
+ }
131
+ const loggerInfo = input.project_files
132
+ ? detectProjectLogger(input.project_files)
133
+ : undefined;
134
+ const wp = input.work_package ?? createCodeObservabilityWorkPackage(input.task_id, input.intent, loggerInfo);
135
+ if (!workPackageSatisfied(wp)) {
136
+ return {
137
+ applicable: true,
138
+ allowed: false,
139
+ status: "blocked",
140
+ reason_zh: "业务编码任务缺少代码可维护性/可观测性工作包,不得开始实现",
141
+ work_package: { ...wp, detected_logger: loggerInfo },
142
+ findings: [],
143
+ };
144
+ }
145
+ return {
146
+ applicable: true,
147
+ allowed: true,
148
+ status: "satisfied",
149
+ reason_zh: "代码可维护性/可观测性工作包已具备,可进入实现",
150
+ work_package: { ...wp, detected_logger: loggerInfo },
151
+ findings: [],
152
+ };
153
+ }
154
+ /* ── Review: 敏感信息检测 ─────────────────────── */
155
+ export function detectSensitiveLogs(fileContents) {
156
+ const findings = [];
157
+ for (const [file, content] of Object.entries(fileContents)) {
158
+ if (/\.(?:test|spec)\./.test(file))
159
+ continue;
160
+ for (const { pattern, name_zh } of SENSITIVE_PATTERNS) {
161
+ if (pattern.test(content)) {
162
+ findings.push({
163
+ category: "sensitive_log_leak",
164
+ severity: "hard_fail",
165
+ file,
166
+ evidence: `日志或输出可能包含敏感信息: ${name_zh}`,
167
+ suggestion_zh: `对 ${name_zh} 字段脱敏后再输出(如仅显示末四位或哈希值)。`,
168
+ });
169
+ }
170
+ }
171
+ for (const { pattern, name_zh } of LOG_OUTPUT_SENSITIVE_PATTERNS) {
172
+ if (pattern.test(content)) {
173
+ findings.push({
174
+ category: "sensitive_log_leak",
175
+ severity: "hard_fail",
176
+ file,
177
+ evidence: `日志输出包含敏感信息: ${name_zh}`,
178
+ suggestion_zh: `禁止在日志中输出敏感字段值,仅记录脱敏值或哈希。`,
179
+ });
180
+ }
181
+ }
182
+ }
183
+ return findings;
184
+ }
185
+ /* ── Review: 缺失日志检测 ─────────────────────── */
186
+ export function reviewMissingLogs(fileContents) {
187
+ const findings = [];
188
+ for (const [file, content] of Object.entries(fileContents)) {
189
+ if (/\.(?:test|spec)\./.test(file))
190
+ continue;
191
+ const lowered = file.toLowerCase();
192
+ const hasLog = /(?:log\.(info|warn|error|debug)|logger\.(info|warn|error|debug|log)|LOG\.(INFO|WARN|ERROR)|console\.(log|error|warn))\s*\(/i.test(content);
193
+ if (CRITICAL_LOG_KEYWORDS.test(`${file} ${content}`)) {
194
+ const hasWriteOp = /\.(?:save|insert|update|delete|create|refund|charge|pay)\s*\(/i.test(content);
195
+ if (hasWriteOp && !/(?:log\.|logger\.|LOG\.)/i.test(content)) {
196
+ findings.push({
197
+ category: "missing_log_critical",
198
+ severity: "hard_fail",
199
+ file,
200
+ evidence: "支付/金额相关写操作缺少业务日志",
201
+ suggestion_zh: "补充包含对象 ID、操作人、金额前后值和操作结果的结构化日志。",
202
+ });
203
+ }
204
+ // 有日志但不可定位 — 支付/金额写操作的日志必须含对象ID或前后状态
205
+ // 事件词(退款/支付/changed/updated)不是可定位字段
206
+ if (hasWriteOp && /(?:log\.|logger\.|LOG\.)/i.test(content)) {
207
+ const logStmts = content.match(/(?:log\.|logger\.|LOG\.|console\.)\s*(?:info|warn|error|debug|log|INFO|WARN|ERROR|DEBUG)\s*\([^)]*\)/gi) ?? [];
208
+ const hasLocatableField = logStmts.some((stmt) => /\w+(?:Id|_id|ID|No|Number|Code)\b/i.test(stmt)
209
+ || /\bid\s*[=::]/i.test(stmt)
210
+ || /(?:before|after|prev|old|new|from|to)\s*[=::]/i.test(stmt)
211
+ || /(?:操作人|操作者|operator|userId|user_id|adminId|staffId)\b/i.test(stmt)
212
+ || /(?:resourceId|target|resource)\s*[=::]/i.test(stmt));
213
+ if (!hasLocatableField) {
214
+ findings.push({
215
+ category: "unlocatable_log",
216
+ severity: "hard_fail",
217
+ file,
218
+ evidence: "支付/金额写操作日志缺少可定位字段(对象ID、前后状态、操作人/目标资源)",
219
+ suggestion_zh: "日志必须包含对象 ID、前后状态或操作人+目标资源,事件词不是可定位字段。",
220
+ });
221
+ }
222
+ }
223
+ }
224
+ if (SECURITY_LOG_KEYWORDS.test(`${file} ${content}`)) {
225
+ const hasPermissionCheck = /(?:permission|auth|role|check|deny|reject|forbidden|authorize)/i.test(content);
226
+ if (hasPermissionCheck && !/(?:log\.|logger\.|LOG\.)/i.test(content)) {
227
+ findings.push({
228
+ category: "missing_log_critical",
229
+ severity: "hard_fail",
230
+ file,
231
+ evidence: "权限校验逻辑缺少安全日志",
232
+ suggestion_zh: "补充包含操作人、目标资源和拒绝原因的安全日志。",
233
+ });
234
+ }
235
+ }
236
+ const catchBlocks = content.match(/catch\s*\([^)]*\)\s*\{[^}]*\}/g) ?? [];
237
+ for (const block of catchBlocks) {
238
+ const hasLogInBlock = /(?:log\.|logger\.|LOG\.|console\.(error|warn))/i.test(block);
239
+ const onlyReturnOrRethrow = /^(?:\s*(?:return\s+(?:false|null|undefined|""|-1|0|[])|;?\s*\})+\s*$)/i.test(block.replace(/\s+/g, " ").trim());
240
+ if (!hasLogInBlock && (onlyReturnOrRethrow || /return\s+(?:false|null|""|-1|0)/i.test(block))) {
241
+ findings.push({
242
+ category: "catch_swallow",
243
+ severity: "hard_fail",
244
+ file,
245
+ evidence: `catch 块吞异常且无日志: ${block.slice(0, 80).replace(/\n/g, " ")}`,
246
+ suggestion_zh: "至少记录异常类型、消息和影响上下文,不得静默忽略。",
247
+ });
248
+ }
249
+ }
250
+ if (STATE_CHANGE_KEYWORDS.test(`${file} ${content}`)) {
251
+ const hasStateUpdate = /(?:status|state)\s*(?:=|\.set|\.update|transition|change)\s*/i.test(content);
252
+ if (hasStateUpdate && !/(?:log\.|logger\.|LOG\.)/i.test(content)) {
253
+ findings.push({
254
+ category: "missing_log_state_change",
255
+ severity: "warning",
256
+ file,
257
+ evidence: "状态变更逻辑缺少流转日志",
258
+ suggestion_zh: "补充状态流转日志,记录变更前后状态和触发原因。",
259
+ });
260
+ }
261
+ }
262
+ if (EXTERNAL_CALL_KEYWORDS.test(`${file} ${content}`)) {
263
+ const hasExternalCall = /(?:fetch|axios|RestTemplate|WebClient|Feign|http\.request|rpc|grpc)/i.test(content);
264
+ if (hasExternalCall && !/(?:log\.|logger\.|LOG\.)/i.test(content)) {
265
+ findings.push({
266
+ category: "missing_log_external",
267
+ severity: "warning",
268
+ file,
269
+ evidence: "外部调用缺少失败/超时日志",
270
+ suggestion_zh: "补充外部调用失败日志,含目标、响应码和重试信息。",
271
+ });
272
+ }
273
+ }
274
+ if (MIGRATION_KEYWORDS.test(`${file} ${content}`)) {
275
+ const hasDataModification = /(?:UPDATE|INSERT|DELETE|update\(|save\(|delete\(|remove\()/i.test(content);
276
+ if (hasDataModification && !/(?:log\.|logger\.|LOG\.|audit|审计)/i.test(content)) {
277
+ findings.push({
278
+ category: "missing_audit_log",
279
+ severity: "hard_fail",
280
+ file,
281
+ evidence: "数据修复/迁移脚本缺少审计日志",
282
+ suggestion_zh: "补充审计日志,记录修复前值、后值和影响行数。",
283
+ });
284
+ }
285
+ }
286
+ if (hasLog && /console\.(log|debug|info)\s*\(/i.test(content) && !/\.(?:test|spec)\./.test(file)) {
287
+ const isFrontendProd = /\.(?:vue|tsx|jsx|svelte)\b/.test(lowered);
288
+ findings.push({
289
+ category: "raw_console_log",
290
+ severity: isFrontendProd ? "hard_fail" : "warning",
291
+ file,
292
+ evidence: "生产代码使用裸 console.log/debug/info",
293
+ suggestion_zh: isFrontendProd
294
+ ? "前端生产代码禁止裸 console 输出,使用项目封装 logger 或移除。"
295
+ : "使用项目 logger 替代 console.log,确保日志可追踪和可过滤。",
296
+ });
297
+ }
298
+ if (hasLog) {
299
+ const logLines = content.match(/(?:log\.info|logger\.info|LOG\.INFO|console\.log)\s*\(\s*["'](?:error|failed|success|done|ok|ok|完成|失败|错误)["']/gi) ?? [];
300
+ for (const _line of logLines) {
301
+ findings.push({
302
+ category: "unlocatable_log",
303
+ severity: "warning",
304
+ file,
305
+ evidence: "日志仅含通用状态词,无业务对象标识",
306
+ suggestion_zh: "日志必须包含事件名、业务对象 ID 和操作上下文,确保可定位。",
307
+ });
308
+ }
309
+ }
310
+ const loopLogPattern = /(?:for|while|forEach|map|flatMap|reduce)\s*\([^)]*\)\s*\{[^}]*(?:log\.|logger\.|console\.)/i;
311
+ if (loopLogPattern.test(content) && !/(?:batch|批量|each|every|per.?item)/i.test(content)) {
312
+ findings.push({
313
+ category: "noisy_log",
314
+ severity: "advisory",
315
+ file,
316
+ evidence: "循环内可能产生刷屏日志",
317
+ suggestion_zh: "在循环内使用 DEBUG 级别,或汇总后以单条日志输出。",
318
+ });
319
+ }
320
+ }
321
+ return findings;
322
+ }
323
+ /* ── Review: 注释质量检测 ─────────────────────── */
324
+ export function reviewCommentQuality(fileContents) {
325
+ const findings = [];
326
+ for (const [file, content] of Object.entries(fileContents)) {
327
+ if (/\.(?:test|spec)\./.test(file))
328
+ continue;
329
+ if (COMPLEX_RULE_KEYWORDS.test(`${file} ${content}`)) {
330
+ const hasFunction = /(?:function\s+\w+|(?:const|let)\s+\w+\s*=\s*(?:async\s+)?\(|(?:public|private|protected)\s+(?:\w+\s+)+\w+\s*\(|def\s+\w+\s*\(|class\s+\w+)/i.test(content);
331
+ const hasComment = /(?:\/\/|\/\*|\*|<!--)/.test(content);
332
+ if (hasFunction && !hasComment) {
333
+ findings.push({
334
+ category: "missing_comment_complex",
335
+ severity: "warning",
336
+ file,
337
+ evidence: "复杂业务规则缺少注释",
338
+ suggestion_zh: "添加注释说明设计意图(为什么),不得只复述代码行为。",
339
+ });
340
+ }
341
+ }
342
+ const commentMatches = content.matchAll(/\/\/\s*(.+)|\/\*\s*([\s\S]*?)\s*\*\//g);
343
+ for (const match of commentMatches) {
344
+ const commentText = (match[1] ?? match[2] ?? "").trim();
345
+ if (!commentText)
346
+ continue;
347
+ const lineStart = match.index ?? 0;
348
+ const afterComment = content.slice(lineStart + match[0].length, lineStart + match[0].length + 200);
349
+ const nextCodeLine = afterComment.split("\n").find((l) => l.trim().length > 0 && !l.trim().startsWith("//") && !l.trim().startsWith("*"));
350
+ if (nextCodeLine) {
351
+ const codeStripped = nextCodeLine.replace(/[{}()\[\];,.]/g, "").trim();
352
+ const commentStripped = commentText.replace(/[{}()\[\];,.]/g, "").trim();
353
+ const codeLower = codeStripped.toLowerCase();
354
+ const commentLower = commentStripped.toLowerCase();
355
+ if (codeLower.length > 10 && commentLower.length > 10) {
356
+ const codeWords = new Set(codeLower.split(/\s+/));
357
+ const commentWords = new Set(commentLower.split(/\s+/));
358
+ let overlap = 0;
359
+ const total = Math.max(codeWords.size, commentWords.size);
360
+ for (const w of codeWords) {
361
+ if (commentWords.has(w) && w.length > 3)
362
+ overlap++;
363
+ }
364
+ if (total > 0 && overlap / total > 0.7) {
365
+ findings.push({
366
+ category: "verbose_comment",
367
+ severity: "advisory",
368
+ file,
369
+ evidence: `注释仅复述代码: "${commentText.slice(0, 60)}"`,
370
+ suggestion_zh: "删除废话注释;如需保留,改为说明设计意图或业务背景。",
371
+ });
372
+ }
373
+ }
374
+ }
375
+ }
376
+ }
377
+ return findings;
378
+ }
379
+ /* ── Review: 项目 logger 使用检查 ─────────────── */
380
+ export function reviewLoggerUsage(fileContents, loggerInfo) {
381
+ const findings = [];
382
+ if (loggerInfo.type === "frontend_project" || loggerInfo.type === "none_detected")
383
+ return findings;
384
+ for (const [file, content] of Object.entries(fileContents)) {
385
+ if (/\.(?:test|spec|d\.ts|\.types\.ts)\./.test(file))
386
+ continue;
387
+ const hasAnyLog = /(?:log\.|logger\.|LOG\.|console\.)/i.test(content);
388
+ if (!hasAnyLog)
389
+ continue;
390
+ const usesProjectLogger = new RegExp(loggerInfo.call_pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\./g, "\\."), "i").test(content);
391
+ const usesConsoleDirectly = /console\.(log|debug|info|warn|error)\s*\(/i.test(content);
392
+ if (usesConsoleDirectly && !usesProjectLogger && loggerInfo.confidence === "high") {
393
+ findings.push({
394
+ category: "wrong_logger",
395
+ severity: "warning",
396
+ file,
397
+ evidence: `使用裸 console 而非项目 logger (${loggerInfo.type})`,
398
+ suggestion_zh: `使用项目 ${loggerInfo.type} logger 确保日志可追踪和可过滤。`,
399
+ });
400
+ }
401
+ }
402
+ return findings;
403
+ }
404
+ /* ── 综合审查入口 ─────────────────────────────── */
405
+ export function reviewCodeObservability(fileContents, loggerInfo) {
406
+ const findings = [];
407
+ findings.push(...detectSensitiveLogs(fileContents));
408
+ findings.push(...reviewMissingLogs(fileContents));
409
+ findings.push(...reviewCommentQuality(fileContents));
410
+ const resolvedLogger = loggerInfo ?? detectProjectLogger(fileContents);
411
+ findings.push(...reviewLoggerUsage(fileContents, resolvedLogger));
412
+ return findings;
413
+ }
414
+ /* ── 低风险跳过判断 ───────────────────────────── */
415
+ export function isLowRiskChange(intent, changedFiles = []) {
416
+ const text = `${intent} ${changedFiles.join(" ")}`;
417
+ if (/^(?:fix\s+)?(?:typo|错别字|拼写|文案|README|注释样式|格式化|lint|import\s*排序)/i.test(text.trim())) {
418
+ return { low_risk: true, reason_zh: "纯文案或格式修改,跳过可维护性/可观测性检查" };
419
+ }
420
+ if (/^(?:get|set|is|has|can)\w*\s*[\({]/i.test(text.trim()) && changedFiles.length <= 1) {
421
+ return { low_risk: true, reason_zh: "简单 getter/setter,跳过可维护性/可观测性检查" };
422
+ }
423
+ const allStyle = changedFiles.length > 0 && changedFiles.every((f) => /\.(?:css|scss|less|styl|style)$/i.test(f));
424
+ if (allStyle) {
425
+ return { low_risk: true, reason_zh: "纯样式修改,跳过可维护性/可观测性检查" };
426
+ }
427
+ const allTest = changedFiles.length > 0 && changedFiles.every((f) => /\.(?:test|spec)\./i.test(f));
428
+ if (allTest && !OBSERVABILITY_KEYWORDS.test(text)) {
429
+ return { low_risk: true, reason_zh: "纯测试文件修改,跳过可维护性/可观测性检查" };
430
+ }
431
+ return { low_risk: false, reason_zh: "" };
432
+ }
433
+ /* ── 阻断判断 ─────────────────────────────────── */
434
+ export function hasBlockingObservabilityFindings(findings) {
435
+ return findings.some((f) => f.severity === "hard_fail");
436
+ }
437
+ export function hasP1OrAboveFindings(findings) {
438
+ return findings.some((f) => f.severity === "hard_fail" || f.severity === "warning");
439
+ }
440
+ /* ── sf_verify changed_files 校验 ─────────────── */
441
+ export function verifyChangedFilesObservability(input) {
442
+ const filtered = {};
443
+ for (const [file, content] of Object.entries(input.file_contents)) {
444
+ if (/\.(?:test|spec|d\.ts|\.types\.ts|\.md|\.json|\.yaml|\.yml|\.lock|\.map)$/i.test(file))
445
+ continue;
446
+ if (input.changed_files.length > 0 && !input.changed_files.some((cf) => file.endsWith(cf) || cf.endsWith(file)))
447
+ continue;
448
+ filtered[file] = content;
449
+ }
450
+ if (Object.keys(filtered).length === 0) {
451
+ return [];
452
+ }
453
+ const lowRisk = isLowRiskChange(input.intent, input.changed_files);
454
+ if (lowRisk.low_risk) {
455
+ return [{ category: "low_risk_skip", severity: "info", file: "", evidence: lowRisk.reason_zh, suggestion_zh: "" }];
456
+ }
457
+ return reviewCodeObservability(filtered);
458
+ }
459
+ /* ── sf_deliver 交付阻断 ──────────────────────── */
460
+ export function evaluateDeliveryBlock(findings) {
461
+ const blocking = findings.filter((f) => f.severity === "hard_fail"
462
+ || (f.severity === "warning" && f.category === "missing_comment_complex"));
463
+ if (blocking.length > 0) {
464
+ const reasons = blocking.map((f) => `[${f.category}] ${f.file}: ${f.evidence}`).join("\n");
465
+ return {
466
+ blocked: true,
467
+ reason_zh: `代码可维护性/可观测性存在 ${blocking.length} 项阻断:\n${reasons}`,
468
+ blocking_findings: blocking,
469
+ };
470
+ }
471
+ return { blocked: false, reason_zh: "", blocking_findings: [] };
472
+ }
473
+ //# sourceMappingURL=code_maintainability_observability_contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code_maintainability_observability_contract.js","sourceRoot":"","sources":["../../src/engine/code_maintainability_observability_contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 配置落盘边界。
3
+ *
4
+ * 区分空项目、已有项目和运行时推断,防止自动推断结果在未确认时写入用户工程。
5
+ */
6
+ export type ConfigWriteContextKind = "greenfield" | "existing_project" | "runtime_inference";
7
+ export interface ConfigWriteContext {
8
+ kind: ConfigWriteContextKind;
9
+ project_path: string;
10
+ evidence: string[];
11
+ confirmed: boolean;
12
+ }
13
+ export interface ConfigWriteDecision {
14
+ allowed: boolean;
15
+ reason_zh: string;
16
+ requires_confirmation: boolean;
17
+ }
18
+ export interface WriteBoundaryViolation {
19
+ target_path: string;
20
+ reason_zh: string;
21
+ }
22
+ export declare function classifyConfigContext(projectDir: string, opts?: {
23
+ runtime_inference?: boolean;
24
+ confirmed?: boolean;
25
+ }): ConfigWriteContext;
26
+ export declare function isWriteAllowed(context: ConfigWriteContext, targetPath: string): ConfigWriteDecision;
27
+ export declare function getWriteConfirmationPrompt(context: ConfigWriteContext, targetPath: string): string;
28
+ export declare function validateWriteBoundary(context: ConfigWriteContext, writes: string[]): WriteBoundaryViolation[];
29
+ //# sourceMappingURL=config_write_boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_write_boundary.d.ts","sourceRoot":"","sources":["../../src/engine/config_write_boundary.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAE7F,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,CAYzI;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,CAsBnG;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAIlG;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,sBAAsB,EAAE,CAS7G"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * 配置落盘边界。
3
+ *
4
+ * 区分空项目、已有项目和运行时推断,防止自动推断结果在未确认时写入用户工程。
5
+ */
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ const PROJECT_MARKERS = [
9
+ "package.json",
10
+ "pom.xml",
11
+ "build.gradle",
12
+ "settings.gradle",
13
+ "pyproject.toml",
14
+ "go.mod",
15
+ "Cargo.toml",
16
+ "src",
17
+ ];
18
+ export function classifyConfigContext(projectDir, opts) {
19
+ if (opts?.runtime_inference) {
20
+ return { kind: "runtime_inference", project_path: projectDir, evidence: ["runtime_inference"], confirmed: opts.confirmed === true };
21
+ }
22
+ const evidence = PROJECT_MARKERS.filter((m) => fs.existsSync(path.join(projectDir, m)));
23
+ const hasSoloforgeState = fs.existsSync(path.join(projectDir, ".soloforge"))
24
+ || fs.existsSync(path.join(projectDir, ".mcp.json"))
25
+ || fs.existsSync(path.join(projectDir, "CLAUDE.md"));
26
+ if (evidence.length === 0 && !hasSoloforgeState) {
27
+ return { kind: "greenfield", project_path: projectDir, evidence: ["empty_project"], confirmed: opts?.confirmed === true };
28
+ }
29
+ return { kind: "existing_project", project_path: projectDir, evidence, confirmed: opts?.confirmed === true };
30
+ }
31
+ export function isWriteAllowed(context, targetPath) {
32
+ const normalized = targetPath.replace(/\\/g, "/");
33
+ const isSoloforgeManaged = normalized.includes(".soloforge/")
34
+ || normalized.endsWith(".mcp.json")
35
+ || normalized.endsWith("CLAUDE.md")
36
+ || normalized.includes(".claude/");
37
+ if (context.kind === "runtime_inference") {
38
+ return {
39
+ allowed: false,
40
+ reason_zh: "运行时推断结果不得自动落盘,请使用 init --auto 或明确确认后写入。",
41
+ requires_confirmation: true,
42
+ };
43
+ }
44
+ if (context.kind === "existing_project" && isSoloforgeManaged && !context.confirmed) {
45
+ return {
46
+ allowed: false,
47
+ reason_zh: "已有项目写入 SoloForge 管理文件需要用户确认。",
48
+ requires_confirmation: true,
49
+ };
50
+ }
51
+ return { allowed: true, reason_zh: "写入边界允许", requires_confirmation: false };
52
+ }
53
+ export function getWriteConfirmationPrompt(context, targetPath) {
54
+ const decision = isWriteAllowed(context, targetPath);
55
+ if (decision.allowed)
56
+ return "无需额外确认。";
57
+ return `即将向 ${context.kind} 项目写入 ${targetPath}。${decision.reason_zh}`;
58
+ }
59
+ export function validateWriteBoundary(context, writes) {
60
+ const violations = [];
61
+ for (const target of writes) {
62
+ const decision = isWriteAllowed(context, target);
63
+ if (!decision.allowed) {
64
+ violations.push({ target_path: target, reason_zh: decision.reason_zh });
65
+ }
66
+ }
67
+ return violations;
68
+ }
69
+ //# sourceMappingURL=config_write_boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_write_boundary.js","sourceRoot":"","sources":["../../src/engine/config_write_boundary.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"consumable_asset_registry.d.ts","sourceRoot":"","sources":["../../src/engine/consumable_asset_registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,YAAY,GACZ,UAAU,GACV,kBAAkB,GAClB,WAAW,GACX,eAAe,GACf,YAAY,CAAC;AAEjB,MAAM,MAAM,SAAS,GACjB,qBAAqB,GACrB,oBAAoB,GACpB,mBAAmB,GACnB,0BAA0B,GAC1B,aAAa,GACb,gBAAgB,GAChB,aAAa,GACb,WAAW,GACX,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,2BAA2B,GAC3B,yBAAyB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,eAAe,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmJD,eAAO,MAAM,yBAAyB,EAAE,kBAAkB,EA0mCzD,CAAC;AAIF;;;GAGG;AACH;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEjF;AAED,wBAAgB,2BAA2B,IAAI,kBAAkB,EAAE,CAElE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAErF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,EAAE,CAEtF"}
1
+ {"version":3,"file":"consumable_asset_registry.d.ts","sourceRoot":"","sources":["../../src/engine/consumable_asset_registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,YAAY,GACZ,UAAU,GACV,kBAAkB,GAClB,WAAW,GACX,eAAe,GACf,YAAY,CAAC;AAEjB,MAAM,MAAM,SAAS,GACjB,qBAAqB,GACrB,oBAAoB,GACpB,mBAAmB,GACnB,0BAA0B,GAC1B,aAAa,GACb,gBAAgB,GAChB,aAAa,GACb,WAAW,GACX,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,2BAA2B,GAC3B,yBAAyB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,eAAe,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmJD,eAAO,MAAM,yBAAyB,EAAE,kBAAkB,EA0pCzD,CAAC;AAIF;;;GAGG;AACH;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEjF;AAED,wBAAgB,2BAA2B,IAAI,kBAAkB,EAAE,CAElE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEtF;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAErF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,EAAE,CAEtF"}