@chongyan/autospec 1.0.1
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/LICENSE +21 -0
- package/README.en.md +472 -0
- package/README.md +476 -0
- package/bin/autospec.js +3 -0
- package/knowledge/README.md +144 -0
- package/knowledge/checklists/code.md +182 -0
- package/knowledge/checklists/design.md +196 -0
- package/knowledge/checklists/release.md +70 -0
- package/knowledge/checklists/requirement.md +169 -0
- package/knowledge/checklists/test.md +46 -0
- package/knowledge/config/README.en.md +44 -0
- package/knowledge/config/README.md +44 -0
- package/knowledge/config/role-composition.yaml +98 -0
- package/knowledge/config/role-extensions.yaml +140 -0
- package/knowledge/config/skill-compositions.yaml +142 -0
- package/knowledge/config/team-stage.yaml +95 -0
- package/knowledge/config/team-tasks.yaml +139 -0
- package/knowledge/config/team-triggers.yaml +198 -0
- package/knowledge/config/validation-patterns.yaml +137 -0
- package/knowledge/domain/README.md +115 -0
- package/knowledge/domain/flows/README.md +194 -0
- package/knowledge/domain/glossary.md +143 -0
- package/knowledge/domain/rules.md +138 -0
- package/knowledge/environment/README.en.md +36 -0
- package/knowledge/environment/README.md +87 -0
- package/knowledge/environment/component-knowledge.md +316 -0
- package/knowledge/environment/detection-patterns.yaml +502 -0
- package/knowledge/environment/middleware-knowledge.md +237 -0
- package/knowledge/environment/template-registry.md +321 -0
- package/knowledge/guides/domain-driven-design.md +345 -0
- package/knowledge/guides/knowledge-management.md +369 -0
- package/knowledge/guides/requirement-engineering.md +329 -0
- package/knowledge/guides/stages/ai-effect-evaluator.md +93 -0
- package/knowledge/guides/stages/code-implementer.md +205 -0
- package/knowledge/guides/stages/code-reviewer.md +111 -0
- package/knowledge/guides/stages/consistency-checker.md +177 -0
- package/knowledge/guides/stages/design-planner.md +401 -0
- package/knowledge/guides/stages/design-reviewer.md +83 -0
- package/knowledge/guides/stages/integration-test-runner.md +105 -0
- package/knowledge/guides/stages/release-checker.md +205 -0
- package/knowledge/guides/stages/requirement-analyzer.md +195 -0
- package/knowledge/guides/stages/requirement-reviewer.md +83 -0
- package/knowledge/guides/stages/security-reviewer.md +89 -0
- package/knowledge/guides/stages/test-context-analyzer.md +250 -0
- package/knowledge/guides/stages/test-generator.md +241 -0
- package/knowledge/guides/stages/test-planner.md +183 -0
- package/knowledge/guides/stages/test-reviewer.md +76 -0
- package/knowledge/guides/stages/unit-test-runner.md +83 -0
- package/knowledge/guides/support/ai-agent-analyzer.md +362 -0
- package/knowledge/guides/support/ai-anomaly-analyzer.md +213 -0
- package/knowledge/guides/support/ai-artifact-evaluator.md +192 -0
- package/knowledge/guides/support/ai-capability-analyzer.md +193 -0
- package/knowledge/guides/support/ai-component-analyzer.md +169 -0
- package/knowledge/guides/support/ai-data-validator.md +276 -0
- package/knowledge/guides/support/ai-evaluation-planner.md +374 -0
- package/knowledge/guides/support/ai-path-evaluator.md +274 -0
- package/knowledge/guides/support/ai-pipeline-evaluator.md +219 -0
- package/knowledge/guides/support/ai-rag-analyzer.md +339 -0
- package/knowledge/guides/support/ai-task-assessor.md +418 -0
- package/knowledge/guides/support/ai-test-diagnostics.md +133 -0
- package/knowledge/guides/support/complexity-assessor.md +268 -0
- package/knowledge/guides/support/component-discovery.md +183 -0
- package/knowledge/guides/support/environment-scanner.md +207 -0
- package/knowledge/guides/support/environment-validator.md +207 -0
- package/knowledge/guides/support/knowledge-generator.md +234 -0
- package/knowledge/guides/support/methodology-extractor.md +55 -0
- package/knowledge/guides/support/pipeline-protocol.md +438 -0
- package/knowledge/guides/support/practice-logger.md +359 -0
- package/knowledge/guides/support/scope-inference.md +174 -0
- package/knowledge/guides/support/skill-distiller.md +91 -0
- package/knowledge/guides/support/skill-updater.md +45 -0
- package/knowledge/guides/support/skill-validator.md +72 -0
- package/knowledge/guides/support/team-orchestrator.md +323 -0
- package/knowledge/guides/support/tech-stack-analyzer.md +139 -0
- package/knowledge/guides/support/test-runner.md +254 -0
- package/knowledge/guides/system-design.md +352 -0
- package/knowledge/organization/ai-native-team.md +318 -0
- package/knowledge/organization/team-metrics.md +228 -0
- package/knowledge/principles/constitution.md +134 -0
- package/knowledge/principles/core-principles.md +368 -0
- package/knowledge/principles/design-philosophy.md +877 -0
- package/knowledge/principles/evolution.md +553 -0
- package/knowledge/process/01-requirement.md +113 -0
- package/knowledge/process/02-design.md +123 -0
- package/knowledge/process/03-implementation.md +90 -0
- package/knowledge/process/04-review.md +80 -0
- package/knowledge/process/05-testing.md +90 -0
- package/knowledge/process/06-delivery.md +88 -0
- package/knowledge/process/README.en.md +38 -0
- package/knowledge/process/README.md +48 -0
- package/knowledge/process/ai-sdlc.md +475 -0
- package/knowledge/process/overview.md +319 -0
- package/knowledge/standards/code-review.md +876 -0
- package/knowledge/standards/coding-style.md +940 -0
- package/knowledge/standards/data-consistency.md +1085 -0
- package/knowledge/standards/document-versioning.md +210 -0
- package/knowledge/standards/risk-detection.md +186 -0
- package/knowledge/templates/ai-evaluation.md +150 -0
- package/knowledge/templates/api-design.md +117 -0
- package/knowledge/templates/database-design.md +132 -0
- package/knowledge/templates/domain-driven-design.md +321 -0
- package/knowledge/templates/product-proposal.md +201 -0
- package/knowledge/templates/system-design.md +227 -0
- package/knowledge/templates/task-breakdown.md +107 -0
- package/knowledge/templates/test-case.md +170 -0
- package/package.json +53 -0
- package/plugins/.claude-plugin/plugin.json +134 -0
- package/plugins/agents/roles/ai-engineer.md +129 -0
- package/plugins/agents/roles/backend-engineer.md +165 -0
- package/plugins/agents/roles/ceo.md +94 -0
- package/plugins/agents/roles/data-engineer.md +135 -0
- package/plugins/agents/roles/devops-engineer.md +181 -0
- package/plugins/agents/roles/frontend-engineer.md +129 -0
- package/plugins/agents/roles/product-owner.md +98 -0
- package/plugins/agents/roles/quality-engineer.md +129 -0
- package/plugins/agents/roles/security-engineer.md +180 -0
- package/plugins/agents/roles/tech-lead.md +97 -0
- package/plugins/agents/support/blind-comparator.md +88 -0
- package/plugins/agents/support/consistency-checker.md +103 -0
- package/plugins/agents/support/failure-diagnostician.md +141 -0
- package/plugins/agents/support/independent-reviewer.md +80 -0
- package/plugins/agents/support/safety-auditor.md +121 -0
- package/plugins/agents/support/skill-benchmarker.md +86 -0
- package/plugins/agents/support/skill-forger.md +105 -0
- package/plugins/agents/support/stage-gate-evaluator.md +121 -0
- package/plugins/agents/support/test-coverage-reviewer.md +73 -0
- package/plugins/benchmarks/templates/README.md +44 -0
- package/plugins/benchmarks/templates/commands/explore-template.yaml +48 -0
- package/plugins/benchmarks/templates/pipeline/agile-template.yaml +84 -0
- package/plugins/benchmarks/templates/pipeline/waterfall-template.yaml +106 -0
- package/plugins/benchmarks/templates/skills/requirement-analyzer-template.yaml +48 -0
- package/plugins/commands/README.en.md +96 -0
- package/plugins/commands/README.md +96 -0
- package/plugins/commands/apply.md +191 -0
- package/plugins/commands/archive.md +76 -0
- package/plugins/commands/env-export.md +79 -0
- package/plugins/commands/env-sync.md +640 -0
- package/plugins/commands/env-template.md +223 -0
- package/plugins/commands/env-update.md +264 -0
- package/plugins/commands/env-validate.md +176 -0
- package/plugins/commands/env.md +79 -0
- package/plugins/commands/explore.md +76 -0
- package/plugins/commands/field-evolve.md +536 -0
- package/plugins/commands/memory.md +249 -0
- package/plugins/commands/project-evolve.md +821 -0
- package/plugins/commands/propose.md +93 -0
- package/plugins/commands/review.md +140 -0
- package/plugins/commands/run.md +224 -0
- package/plugins/commands/status.md +62 -0
- package/plugins/commands/validate.md +108 -0
- package/plugins/hooks/README.en.md +56 -0
- package/plugins/hooks/README.md +56 -0
- package/plugins/hooks/ai-project-guard.js +329 -0
- package/plugins/hooks/artifact-evaluation-hook.js +237 -0
- package/plugins/hooks/constitution-guard.js +211 -0
- package/plugins/hooks/environment-autocommit.js +264 -0
- package/plugins/hooks/environment-manager.js +778 -0
- package/plugins/hooks/execution-tracker.js +354 -0
- package/plugins/hooks/frozen-zone-guard.js +140 -0
- package/plugins/hooks/layer1-validator.js +423 -0
- package/plugins/hooks/lib/artifact-evaluator.js +414 -0
- package/plugins/hooks/lib/benchmarks/change-detector.js +390 -0
- package/plugins/hooks/lib/benchmarks/evaluator.js +605 -0
- package/plugins/hooks/lib/benchmarks/integration-example.js +169 -0
- package/plugins/hooks/lib/data-and-ai-detector.js +275 -0
- package/plugins/hooks/lib/detection-pattern-loader.js +865 -0
- package/plugins/hooks/lib/directory-discovery.js +395 -0
- package/plugins/hooks/lib/environment-config-loader.js +341 -0
- package/plugins/hooks/lib/environment-detector.js +553 -0
- package/plugins/hooks/lib/environment-evolver.js +564 -0
- package/plugins/hooks/lib/environment-registry.js +813 -0
- package/plugins/hooks/lib/execution-path.js +427 -0
- package/plugins/hooks/lib/hook-error-recorder.js +245 -0
- package/plugins/hooks/lib/hook-logger.js +538 -0
- package/plugins/hooks/lib/hook-runner.js +97 -0
- package/plugins/hooks/lib/hook-runner.sh +44 -0
- package/plugins/hooks/lib/hook-state-manager.js +480 -0
- package/plugins/hooks/lib/memory-extractor.js +377 -0
- package/plugins/hooks/lib/memory-manager.js +673 -0
- package/plugins/hooks/lib/metrics-analyzer.js +489 -0
- package/plugins/hooks/lib/project-evolution/auto-fixer.js +511 -0
- package/plugins/hooks/lib/project-evolution/memory-manager.js +346 -0
- package/plugins/hooks/lib/project-evolution/pattern-detector.js +476 -0
- package/plugins/hooks/lib/project-evolution/semantic-indexer.js +480 -0
- package/plugins/hooks/lib/project-structure-detector.js +326 -0
- package/plugins/hooks/lib/rollback-tracker.js +346 -0
- package/plugins/hooks/lib/source-code-scanner.js +596 -0
- package/plugins/hooks/lib/technology-stack-detector.js +374 -0
- package/plugins/hooks/lib/test-failure-analyzer.js +375 -0
- package/plugins/hooks/lib/test-failure-fixer.js +268 -0
- package/plugins/hooks/lib/trace-context.js +277 -0
- package/plugins/hooks/lib/validation-patterns.js +415 -0
- package/plugins/hooks/memory-sync.js +171 -0
- package/plugins/hooks/pipeline-observer.js +413 -0
- package/plugins/hooks/scope-sentinel.js +204 -0
- package/plugins/hooks/trace-initialization.js +169 -0
- package/plugins/memory/templates/code-quality.yaml +149 -0
- package/plugins/memory/templates/multi-system.yaml +155 -0
- package/plugins/memory/templates/team-habits.yaml +119 -0
- package/plugins/memory/templates/testing.yaml +121 -0
- package/plugins/skills/README.en.md +47 -0
- package/plugins/skills/README.md +104 -0
- package/plugins/skills/benchmark-executor/README.md +93 -0
- package/plugins/skills/benchmark-executor/SKILL.md +647 -0
- package/plugins/skills/benchmark-generator/SKILL.md +349 -0
- package/plugins/skills/delivery-stage/SKILL.md +203 -0
- package/plugins/skills/design-stage/SKILL.md +216 -0
- package/plugins/skills/evolution-process/SKILL.md +291 -0
- package/plugins/skills/exploration-phase/SKILL.md +133 -0
- package/plugins/skills/implementation-stage/SKILL.md +179 -0
- package/plugins/skills/layer1-validation/SKILL.md +79 -0
- package/plugins/skills/pending-dashboard/SKILL.md +109 -0
- package/plugins/skills/project-evolution/SKILL.md +847 -0
- package/plugins/skills/requirement-stage/SKILL.md +183 -0
- package/plugins/skills/skill-forge/SKILL.md +223 -0
- package/plugins/skills/skill-forge/references/description-guide.md +92 -0
- package/plugins/skills/skill-forge/references/quality-rubric.md +104 -0
- package/plugins/skills/skill-forge/references/skill-template.md +106 -0
- package/plugins/skills/startup-guard/SKILL.md +38 -0
- package/plugins/skills/testing-stage/SKILL.md +195 -0
- package/scripts/cli/global-init.js +288 -0
- package/scripts/cli/global.js +324 -0
- package/scripts/cli/index.js +55 -0
- package/scripts/cli/init.js +382 -0
- package/scripts/cli/list.js +69 -0
- package/scripts/cli/org.js +340 -0
- package/scripts/cli/update.js +44 -0
- package/scripts/config/commands.config.js +145 -0
- package/scripts/config/hooks.config.js +197 -0
- package/scripts/evolution/evolution-router.js +273 -0
- package/scripts/evolution/evolution-signal-collector.js +307 -0
- package/scripts/evolution/knowledge-loader.js +346 -0
- package/scripts/evolution/marketplace.js +317 -0
- package/scripts/evolution/version-manager.js +371 -0
- package/scripts/install/agents.js +106 -0
- package/scripts/install/commands.js +133 -0
- package/scripts/install/constants.js +424 -0
- package/scripts/install/hook-logger.js +536 -0
- package/scripts/install/hooks.js +110 -0
- package/scripts/install/index.js +39 -0
- package/scripts/install/skills.js +95 -0
- package/scripts/postinstall.js +25 -0
- package/scripts/state.js +376 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Context - Trace ID 生成和管理模块
|
|
3
|
+
*
|
|
4
|
+
* 提供全链路追踪能力,支持:
|
|
5
|
+
* - Trace ID 生成和管理
|
|
6
|
+
* - Event ID 生成
|
|
7
|
+
* - Trace 日志读写
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { getState, updateState } from './hook-state-manager.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 生成 Trace ID
|
|
16
|
+
* 格式: trace-{timestamp}-{random8}
|
|
17
|
+
* @returns {string} Trace ID
|
|
18
|
+
*/
|
|
19
|
+
export function generateTraceId() {
|
|
20
|
+
const timestamp = Date.now();
|
|
21
|
+
const random = Math.random().toString(36).substring(2, 10);
|
|
22
|
+
return `trace-${timestamp}-${random}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 生成 Event ID
|
|
27
|
+
* 格式: evt-{timestamp}-{random6}
|
|
28
|
+
* @returns {string} Event ID
|
|
29
|
+
*/
|
|
30
|
+
export function generateEventId() {
|
|
31
|
+
const timestamp = Date.now();
|
|
32
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
33
|
+
return `evt-${timestamp}-${random}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 获取或创建 Trace ID
|
|
38
|
+
* 从 state.json 获取现有 traceId,如不存在则创建新的
|
|
39
|
+
* @param {string} projectRoot - 项目根目录
|
|
40
|
+
* @returns {string} Trace ID
|
|
41
|
+
*/
|
|
42
|
+
export function getOrCreateTraceId(projectRoot) {
|
|
43
|
+
const state = getState(projectRoot);
|
|
44
|
+
|
|
45
|
+
if (state?.traceId) {
|
|
46
|
+
return state.traceId;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 创建新的 Trace ID
|
|
50
|
+
const traceId = generateTraceId();
|
|
51
|
+
|
|
52
|
+
// 更新 state.json
|
|
53
|
+
updateState(projectRoot, {
|
|
54
|
+
traceId,
|
|
55
|
+
traceStartedAt: new Date().toISOString()
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return traceId;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 获取当前 Trace ID
|
|
63
|
+
* @param {string} projectRoot - 项目根目录
|
|
64
|
+
* @returns {string|null} Trace ID 或 null
|
|
65
|
+
*/
|
|
66
|
+
export function getTraceId(projectRoot) {
|
|
67
|
+
const state = getState(projectRoot);
|
|
68
|
+
return state?.traceId || null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 设置 Trace ID
|
|
73
|
+
* @param {string} projectRoot - 项目根目录
|
|
74
|
+
* @param {string} traceId - Trace ID
|
|
75
|
+
* @returns {boolean} 是否成功
|
|
76
|
+
*/
|
|
77
|
+
export function setTraceId(projectRoot, traceId) {
|
|
78
|
+
return updateState(projectRoot, {
|
|
79
|
+
traceId,
|
|
80
|
+
traceStartedAt: new Date().toISOString()
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 重置 Trace ID(流程结束时调用)
|
|
86
|
+
* @param {string} projectRoot - 项目根目录
|
|
87
|
+
* @returns {boolean} 是否成功
|
|
88
|
+
*/
|
|
89
|
+
export function resetTraceId(projectRoot) {
|
|
90
|
+
return updateState(projectRoot, {
|
|
91
|
+
traceId: null,
|
|
92
|
+
traceStartedAt: null,
|
|
93
|
+
traceEndedAt: new Date().toISOString()
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 获取 Trace 日志文件路径
|
|
99
|
+
* @param {string} projectRoot - 项目根目录
|
|
100
|
+
* @param {string} traceId - Trace ID
|
|
101
|
+
* @returns {string} 日志文件路径
|
|
102
|
+
*/
|
|
103
|
+
export function getTraceLogPath(projectRoot, traceId) {
|
|
104
|
+
return path.join(projectRoot, '.autospec', 'logs', 'traces', `${traceId}.json`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 确保 Trace 日志目录存在
|
|
109
|
+
* @param {string} projectRoot - 项目根目录
|
|
110
|
+
*/
|
|
111
|
+
export function ensureTraceLogDir(projectRoot) {
|
|
112
|
+
const traceDir = path.join(projectRoot, '.autospec', 'logs', 'traces');
|
|
113
|
+
if (!fs.existsSync(traceDir)) {
|
|
114
|
+
fs.mkdirSync(traceDir, { recursive: true });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 读取 Trace 日志
|
|
120
|
+
* @param {string} projectRoot - 项目根目录
|
|
121
|
+
* @param {string} traceId - Trace ID
|
|
122
|
+
* @returns {Object} Trace 日志对象
|
|
123
|
+
*/
|
|
124
|
+
export function readTraceLog(projectRoot, traceId) {
|
|
125
|
+
const logPath = getTraceLogPath(projectRoot, traceId);
|
|
126
|
+
|
|
127
|
+
if (!fs.existsSync(logPath)) {
|
|
128
|
+
return {
|
|
129
|
+
traceId,
|
|
130
|
+
startedAt: new Date().toISOString(),
|
|
131
|
+
events: [],
|
|
132
|
+
summary: {}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
return JSON.parse(fs.readFileSync(logPath, 'utf-8'));
|
|
138
|
+
} catch {
|
|
139
|
+
return {
|
|
140
|
+
traceId,
|
|
141
|
+
startedAt: new Date().toISOString(),
|
|
142
|
+
events: [],
|
|
143
|
+
summary: {}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 写入 Trace 日志
|
|
150
|
+
* @param {string} projectRoot - 项目根目录
|
|
151
|
+
* @param {string} traceId - Trace ID
|
|
152
|
+
* @param {Object} logData - 日志数据
|
|
153
|
+
*/
|
|
154
|
+
export function writeTraceLog(projectRoot, traceId, logData) {
|
|
155
|
+
ensureTraceLogDir(projectRoot);
|
|
156
|
+
const logPath = getTraceLogPath(projectRoot, traceId);
|
|
157
|
+
fs.writeFileSync(logPath, JSON.stringify(logData, null, 2), 'utf-8');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 追加事件到 Trace 日志
|
|
162
|
+
* @param {string} projectRoot - 项目根目录
|
|
163
|
+
* @param {Object} event - 事件对象
|
|
164
|
+
*/
|
|
165
|
+
export function appendTraceEvent(projectRoot, event) {
|
|
166
|
+
const traceId = event.traceId || getTraceId(projectRoot);
|
|
167
|
+
|
|
168
|
+
if (!traceId) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const logData = readTraceLog(projectRoot, traceId);
|
|
173
|
+
logData.events.push(event);
|
|
174
|
+
logData.updatedAt = new Date().toISOString();
|
|
175
|
+
|
|
176
|
+
// 更新摘要
|
|
177
|
+
updateTraceSummary(logData);
|
|
178
|
+
|
|
179
|
+
writeTraceLog(projectRoot, traceId, logData);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 更新 Trace 摘要
|
|
184
|
+
* @param {Object} logData - 日志数据
|
|
185
|
+
*/
|
|
186
|
+
function updateTraceSummary(logData) {
|
|
187
|
+
const events = logData.events;
|
|
188
|
+
|
|
189
|
+
logData.summary = {
|
|
190
|
+
totalEvents: events.length,
|
|
191
|
+
eventTypes: {},
|
|
192
|
+
stageStats: {},
|
|
193
|
+
toolStats: {},
|
|
194
|
+
errorCount: 0,
|
|
195
|
+
rollbackCount: 0
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
for (const event of events) {
|
|
199
|
+
// 统计事件类型
|
|
200
|
+
const type = event.type || 'unknown';
|
|
201
|
+
logData.summary.eventTypes[type] = (logData.summary.eventTypes[type] || 0) + 1;
|
|
202
|
+
|
|
203
|
+
// 统计阶段
|
|
204
|
+
if (event.stage) {
|
|
205
|
+
logData.summary.stageStats[event.stage] = (logData.summary.stageStats[event.stage] || 0) + 1;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 统计工具
|
|
209
|
+
if (event.tool) {
|
|
210
|
+
logData.summary.toolStats[event.tool] = (logData.summary.toolStats[event.tool] || 0) + 1;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 统计错误
|
|
214
|
+
if (event.type === 'error' || event.type === 'layer1_fail') {
|
|
215
|
+
logData.summary.errorCount++;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 统计回退
|
|
219
|
+
if (event.type === 'rollback') {
|
|
220
|
+
logData.summary.rollbackCount++;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 创建标准化事件对象
|
|
227
|
+
* @param {string} projectRoot - 项目根目录
|
|
228
|
+
* @param {string} type - 事件类型
|
|
229
|
+
* @param {Object} data - 事件数据
|
|
230
|
+
* @returns {Object} 标准化事件对象
|
|
231
|
+
*/
|
|
232
|
+
export function createEvent(projectRoot, type, data = {}) {
|
|
233
|
+
const state = getState(projectRoot);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
eventId: generateEventId(),
|
|
237
|
+
traceId: state?.traceId || null,
|
|
238
|
+
timestamp: new Date().toISOString(),
|
|
239
|
+
type,
|
|
240
|
+
source: data.source || 'unknown',
|
|
241
|
+
stage: state?.currentStage || null,
|
|
242
|
+
tool: data.tool || null,
|
|
243
|
+
action: data.action || null,
|
|
244
|
+
data: data.data || {},
|
|
245
|
+
meta: {
|
|
246
|
+
projectRoot,
|
|
247
|
+
executionMode: state?.executionMode || 'interactive'
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* 记录事件(便捷方法)
|
|
254
|
+
* @param {string} projectRoot - 项目根目录
|
|
255
|
+
* @param {string} type - 事件类型
|
|
256
|
+
* @param {Object} data - 事件数据
|
|
257
|
+
*/
|
|
258
|
+
export function recordEvent(projectRoot, type, data = {}) {
|
|
259
|
+
const event = createEvent(projectRoot, type, data);
|
|
260
|
+
appendTraceEvent(projectRoot, event);
|
|
261
|
+
return event;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export default {
|
|
265
|
+
generateTraceId,
|
|
266
|
+
generateEventId,
|
|
267
|
+
getOrCreateTraceId,
|
|
268
|
+
getTraceId,
|
|
269
|
+
setTraceId,
|
|
270
|
+
resetTraceId,
|
|
271
|
+
getTraceLogPath,
|
|
272
|
+
readTraceLog,
|
|
273
|
+
writeTraceLog,
|
|
274
|
+
appendTraceEvent,
|
|
275
|
+
createEvent,
|
|
276
|
+
recordEvent
|
|
277
|
+
};
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Patterns - 统一的验证模式定义
|
|
3
|
+
*
|
|
4
|
+
* 合并了 layer1-validator.js 和 ai-project-guard.js 中的验证模式
|
|
5
|
+
* 提供统一的验证命令检测和类型识别功能
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================
|
|
9
|
+
// Layer 1 验证命令模式 - 按类别分组
|
|
10
|
+
// ============================================================
|
|
11
|
+
|
|
12
|
+
export const VALIDATION_PATTERNS = {
|
|
13
|
+
// 测试相关
|
|
14
|
+
test: /\b(npm test|npm run test|jest|mocha|pytest|py\.test|go test|cargo test|vitest|ava|tap|unittest|nose)\b/,
|
|
15
|
+
|
|
16
|
+
// 构建相关
|
|
17
|
+
build: /\b(npm run build|cargo build|go build|make|gradle|mvn|tsc|webpack|vite|parcel|rollup)\b/,
|
|
18
|
+
|
|
19
|
+
// 代码检查/Lint
|
|
20
|
+
lint: /\b(eslint|tslint|standard|xo|flake8|pylint|rubocop|shellcheck|yamllint|markdownlint|stylelint)\b/,
|
|
21
|
+
|
|
22
|
+
// 类型检查
|
|
23
|
+
typecheck: /\b(npx tsc|tsc --noEmit|tsc -p|flow|mypy|pyright|pytype)\b/,
|
|
24
|
+
|
|
25
|
+
// 代码格式化
|
|
26
|
+
format: /\b(prettier|black|gofmt|rustfmt|autopep8|yapf|clang-format)\b/,
|
|
27
|
+
|
|
28
|
+
// 其他验证工具
|
|
29
|
+
other: /\b(helm lint|kubectl apply --dry-run|terraform validate|terraform plan|docker build|snyk test|brakeman|bandit)\b/
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// ============================================================
|
|
33
|
+
// AI 项目效果验证模式
|
|
34
|
+
// ============================================================
|
|
35
|
+
|
|
36
|
+
export const EVAL_PATTERNS = {
|
|
37
|
+
// 测试
|
|
38
|
+
test: /\b(pytest|jest|mocha|unittest|test|npm test)\b/,
|
|
39
|
+
|
|
40
|
+
// LLM 评估
|
|
41
|
+
llm_eval: /\b(eval|evaluate|benchmark|bench|ragas|deepeval)\b/i,
|
|
42
|
+
|
|
43
|
+
// 代码检查
|
|
44
|
+
lint: /\b(lint|flake8|eslint|pylint|tslint)\b/,
|
|
45
|
+
|
|
46
|
+
// 类型检查
|
|
47
|
+
type_check: /\b(tsc|mypy|type-check|pyright)\b/,
|
|
48
|
+
|
|
49
|
+
// 性能测试
|
|
50
|
+
performance: /\b(bench|perf|load-test|stress|locust|k6)\b/i
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// ============================================================
|
|
54
|
+
// 测试框架检测模式
|
|
55
|
+
// ============================================================
|
|
56
|
+
|
|
57
|
+
export const TEST_FRAMEWORK_PATTERNS = [
|
|
58
|
+
{ pattern: /\bpytest\b/, name: 'pytest' },
|
|
59
|
+
{ pattern: /\bjest\b/, name: 'jest' },
|
|
60
|
+
{ pattern: /\bmocha\b/, name: 'mocha' },
|
|
61
|
+
{ pattern: /\bunittest\b/, name: 'unittest' },
|
|
62
|
+
{ pattern: /\bnpm test\b/, name: 'npm' },
|
|
63
|
+
{ pattern: /\bvitest\b/, name: 'vitest' },
|
|
64
|
+
{ pattern: /\bava\b/, name: 'ava' },
|
|
65
|
+
{ pattern: /\btap\b/, name: 'tap' },
|
|
66
|
+
{ pattern: /\bnose\b/, name: 'nose' },
|
|
67
|
+
{ pattern: /\bcargo test\b/, name: 'cargo' },
|
|
68
|
+
{ pattern: /\bgo test\b/, name: 'go test' }
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
// ============================================================
|
|
72
|
+
// 安全检测模式
|
|
73
|
+
// ============================================================
|
|
74
|
+
|
|
75
|
+
export const SENSITIVE_PATTERNS = {
|
|
76
|
+
// 文件操作
|
|
77
|
+
file_write: /\b(echo|tee|write|put|create|copy|move|mkdir|touch)\b/i,
|
|
78
|
+
|
|
79
|
+
// 网络操作
|
|
80
|
+
network: /\b(curl|wget|nc|netcat|ssh|scp|rsync|ftp|sftp)\b/i,
|
|
81
|
+
|
|
82
|
+
// 环境变量访问
|
|
83
|
+
env_access: /\benv|printenv|export\b/i,
|
|
84
|
+
|
|
85
|
+
// 权限操作
|
|
86
|
+
privilege: /\b(chmod|chown|chgrp|sudo|su|passwd|useradd|userdel)\b/i,
|
|
87
|
+
|
|
88
|
+
// 包管理器安装
|
|
89
|
+
pip_install: /\bpip\s+install/i,
|
|
90
|
+
npm_install: /\bnpm\s+install/i,
|
|
91
|
+
|
|
92
|
+
// Docker 操作
|
|
93
|
+
docker: /\bdocker\s+(run|exec|build)/i,
|
|
94
|
+
|
|
95
|
+
// Python 执行
|
|
96
|
+
python_exec: /\bpython\s+[-c]/i
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// ============================================================
|
|
100
|
+
// 敏感信息检测模式
|
|
101
|
+
// ============================================================
|
|
102
|
+
|
|
103
|
+
export const SENSITIVE_INFO_PATTERNS = [
|
|
104
|
+
/password\s*[:=]\s*['"][^'"]+['"]/i,
|
|
105
|
+
/secret\s*[:=]\s*['"][^'"]+['"]/i,
|
|
106
|
+
/api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i,
|
|
107
|
+
/token\s*[:=]\s*['"][^'"]+['"]/i,
|
|
108
|
+
/private[_-]?key\s*[:=]\s*['"][^'"]+['"]/i,
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
// ============================================================
|
|
112
|
+
// 危险命令模式
|
|
113
|
+
// ============================================================
|
|
114
|
+
|
|
115
|
+
export const DANGEROUS_PATTERNS = [
|
|
116
|
+
/rm\s+-rf/,
|
|
117
|
+
/sudo/,
|
|
118
|
+
/mkfs/,
|
|
119
|
+
/dd\s+if=/,
|
|
120
|
+
/>\s*\/dev\/null/,
|
|
121
|
+
/:\(\)\s*\{\s*:\|\:&\s*\};/ // Fork bomb
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
// ============================================================
|
|
125
|
+
// 检测函数
|
|
126
|
+
// ============================================================
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 检测 Layer 1 验证命令类型
|
|
130
|
+
* @param {string} command - 命令字符串
|
|
131
|
+
* @returns {string|null} 验证类型或 null
|
|
132
|
+
*/
|
|
133
|
+
export function detectValidationType(command) {
|
|
134
|
+
const cmd = command.toLowerCase();
|
|
135
|
+
for (const [type, pattern] of Object.entries(VALIDATION_PATTERNS)) {
|
|
136
|
+
if (pattern.test(cmd)) {
|
|
137
|
+
return type;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 检查是否为 Layer 1 验证命令
|
|
145
|
+
* @param {string} command - 命令字符串
|
|
146
|
+
* @returns {boolean} 是否是验证命令
|
|
147
|
+
*/
|
|
148
|
+
export function isLayer1Validation(command) {
|
|
149
|
+
return Object.values(VALIDATION_PATTERNS).some(p => p.test(command));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 检测 AI 效果验证命令类型
|
|
154
|
+
* @param {string} command - 命令字符串
|
|
155
|
+
* @returns {Array} 检测到的命令类型数组
|
|
156
|
+
*/
|
|
157
|
+
export function detectEvalCommands(command) {
|
|
158
|
+
const commands = [];
|
|
159
|
+
const cmd = command.toLowerCase();
|
|
160
|
+
|
|
161
|
+
for (const [type, pattern] of Object.entries(EVAL_PATTERNS)) {
|
|
162
|
+
if (pattern.test(cmd)) {
|
|
163
|
+
const cmdInfo = { type, command };
|
|
164
|
+
if (type === 'test') {
|
|
165
|
+
cmdInfo.framework = detectTestFramework(command);
|
|
166
|
+
}
|
|
167
|
+
commands.push(cmdInfo);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return commands;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 检测测试框架
|
|
176
|
+
* @param {string} command - 命令字符串
|
|
177
|
+
* @returns {string} 测试框架名称
|
|
178
|
+
*/
|
|
179
|
+
export function detectTestFramework(command) {
|
|
180
|
+
const cmd = command.toLowerCase();
|
|
181
|
+
for (const { pattern, name } of TEST_FRAMEWORK_PATTERNS) {
|
|
182
|
+
if (pattern.test(cmd)) {
|
|
183
|
+
return name;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return 'unknown';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 检查命令是否包含敏感操作
|
|
191
|
+
* @param {string} command - 命令字符串
|
|
192
|
+
* @returns {Object} 安全问题数组
|
|
193
|
+
*/
|
|
194
|
+
export function checkCommandSecurity(command) {
|
|
195
|
+
const issues = [];
|
|
196
|
+
const cmd = command.toLowerCase();
|
|
197
|
+
|
|
198
|
+
// 检查 pip install 未指定版本
|
|
199
|
+
if (SENSITIVE_PATTERNS.pip_install.test(command)) {
|
|
200
|
+
if (!/==|>=|<=|~=/.test(command) && !/-r\s+requirements/.test(command)) {
|
|
201
|
+
issues.push({
|
|
202
|
+
severity: 'MEDIUM',
|
|
203
|
+
type: 'unpinned_dependency',
|
|
204
|
+
message: 'pip install 未指定版本号',
|
|
205
|
+
recommendation: '建议添加 ==version 或使用 requirements.txt 锁定版本'
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 检查 npm install 未指定版本
|
|
211
|
+
if (SENSITIVE_PATTERNS.npm_install.test(command)) {
|
|
212
|
+
if (!/@\d/.test(command) && !/--save/.test(command)) {
|
|
213
|
+
issues.push({
|
|
214
|
+
severity: 'LOW',
|
|
215
|
+
type: 'unpinned_npm_dependency',
|
|
216
|
+
message: 'npm install 建议指定版本',
|
|
217
|
+
recommendation: '建议添加 @version 或使用 package-lock.json'
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 检查 Docker 特权模式
|
|
223
|
+
if (SENSITIVE_PATTERNS.docker.test(command)) {
|
|
224
|
+
if (/\b--privileged\b/.test(command)) {
|
|
225
|
+
issues.push({
|
|
226
|
+
severity: 'HIGH',
|
|
227
|
+
type: 'docker_privileged',
|
|
228
|
+
message: 'Docker 使用特权模式运行',
|
|
229
|
+
recommendation: '特权模式有安全风险,确认是否必要'
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 检查 Python 执行代码
|
|
235
|
+
if (SENSITIVE_PATTERNS.python_exec.test(command)) {
|
|
236
|
+
if (/\bexec\(|\beval\(|\bcompile\(/.test(command)) {
|
|
237
|
+
issues.push({
|
|
238
|
+
severity: 'HIGH',
|
|
239
|
+
type: 'python_code_execution',
|
|
240
|
+
message: 'Python 使用动态代码执行',
|
|
241
|
+
recommendation: '确认代码来源可信,避免执行不可信输入'
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 检查特权提升
|
|
247
|
+
if (SENSITIVE_PATTERNS.privilege.test(command)) {
|
|
248
|
+
if (/sudo\s+(?!apt|yum|dnf)/.test(command)) {
|
|
249
|
+
issues.push({
|
|
250
|
+
severity: 'HIGH',
|
|
251
|
+
type: 'privilege_escalation',
|
|
252
|
+
message: '检测到权限提升操作',
|
|
253
|
+
recommendation: '确认是否为预期的系统管理操作'
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// 检查网络请求
|
|
259
|
+
if (SENSITIVE_PATTERNS.network.test(command)) {
|
|
260
|
+
const urlMatch = command.match(/(?:curl|wget)\s+["']?([^"'\s]+)/);
|
|
261
|
+
if (urlMatch) {
|
|
262
|
+
const url = urlMatch[1];
|
|
263
|
+
if (!url.startsWith('https://')) {
|
|
264
|
+
issues.push({
|
|
265
|
+
severity: 'MEDIUM',
|
|
266
|
+
type: 'insecure_network',
|
|
267
|
+
message: '使用非 HTTPS 协议',
|
|
268
|
+
recommendation: '建议使用 HTTPS 确保传输安全'
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// 检查可疑域名
|
|
273
|
+
const suspiciousDomains = ['pastebin', 'gist.github', 'transfer.sh'];
|
|
274
|
+
if (suspiciousDomains.some(d => url.includes(d))) {
|
|
275
|
+
issues.push({
|
|
276
|
+
severity: 'HIGH',
|
|
277
|
+
type: 'suspicious_download',
|
|
278
|
+
message: '从公共分享服务下载代码',
|
|
279
|
+
recommendation: '确认下载来源可信,检查代码安全性'
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 检查环境变量访问
|
|
286
|
+
if (SENSITIVE_PATTERNS.env_access.test(command)) {
|
|
287
|
+
const sensitiveVars = ['AWS_', 'DATABASE_URL', 'API_KEY', 'SECRET', 'PASSWORD', 'TOKEN'];
|
|
288
|
+
for (const v of sensitiveVars) {
|
|
289
|
+
if (command.includes(v)) {
|
|
290
|
+
issues.push({
|
|
291
|
+
severity: 'MEDIUM',
|
|
292
|
+
type: 'sensitive_env_access',
|
|
293
|
+
message: `访问敏感环境变量:${v}`,
|
|
294
|
+
recommendation: '确认是否需要在日志中显示敏感信息'
|
|
295
|
+
});
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return issues;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* 检查内容是否包含硬编码敏感信息
|
|
306
|
+
* @param {string} content - 要检查的内容
|
|
307
|
+
* @returns {boolean} 是否包含敏感信息
|
|
308
|
+
*/
|
|
309
|
+
export function checkSensitiveInfo(content) {
|
|
310
|
+
for (const pattern of SENSITIVE_INFO_PATTERNS) {
|
|
311
|
+
if (pattern.test(content)) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* 检查命令是否包含危险操作
|
|
320
|
+
* @param {string} command - 命令字符串
|
|
321
|
+
* @returns {boolean} 是否包含危险操作
|
|
322
|
+
*/
|
|
323
|
+
export function checkDangerousCommand(command) {
|
|
324
|
+
for (const pattern of DANGEROUS_PATTERNS) {
|
|
325
|
+
if (pattern.test(command)) {
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// ============================================================
|
|
333
|
+
// 指标提取函数
|
|
334
|
+
// ============================================================
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 提取测试指标
|
|
338
|
+
* @param {string} stdout - 标准输出
|
|
339
|
+
* @param {string} stderr - 标准错误
|
|
340
|
+
* @returns {Object} 测试指标对象
|
|
341
|
+
*/
|
|
342
|
+
export function extractTestMetrics(stdout, stderr) {
|
|
343
|
+
const metrics = {};
|
|
344
|
+
const output = (stdout || '') + (stderr || '');
|
|
345
|
+
|
|
346
|
+
// pytest
|
|
347
|
+
const pytestMatch = output.match(/(\d+) passed/);
|
|
348
|
+
if (pytestMatch) metrics.passed = parseInt(pytestMatch[1]);
|
|
349
|
+
|
|
350
|
+
const pytestFailed = output.match(/(\d+) failed/);
|
|
351
|
+
if (pytestFailed) metrics.failed = parseInt(pytestFailed[1]);
|
|
352
|
+
|
|
353
|
+
// jest
|
|
354
|
+
const jestMatch = output.match(/Tests:\s+(\d+)\s+passed/);
|
|
355
|
+
if (jestMatch) metrics.passed = parseInt(jestMatch[1]);
|
|
356
|
+
|
|
357
|
+
const jestFailed = output.match(/(\d+)\s+failed/);
|
|
358
|
+
if (jestFailed) metrics.failed = parseInt(jestFailed[1]);
|
|
359
|
+
|
|
360
|
+
return metrics;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* 提取 Lint 指标
|
|
365
|
+
* @param {string} stdout - 标准输出
|
|
366
|
+
* @param {string} stderr - 标准错误
|
|
367
|
+
* @returns {Object} Lint 指标对象
|
|
368
|
+
*/
|
|
369
|
+
export function extractLintMetrics(stdout, stderr) {
|
|
370
|
+
const metrics = {};
|
|
371
|
+
const output = (stdout || '') + (stderr || '');
|
|
372
|
+
|
|
373
|
+
const errorMatch = output.match(/(\d+)\s+error/i);
|
|
374
|
+
if (errorMatch) metrics.errors = parseInt(errorMatch[1]);
|
|
375
|
+
|
|
376
|
+
const warningMatch = output.match(/(\d+)\s+warning/i);
|
|
377
|
+
if (warningMatch) metrics.warnings = parseInt(warningMatch[1]);
|
|
378
|
+
|
|
379
|
+
return metrics;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* 提取类型检查指标
|
|
384
|
+
* @param {string} stdout - 标准输出
|
|
385
|
+
* @param {string} stderr - 标准错误
|
|
386
|
+
* @returns {Object} 类型检查指标对象
|
|
387
|
+
*/
|
|
388
|
+
export function extractTypeMetrics(stdout, stderr) {
|
|
389
|
+
const metrics = {};
|
|
390
|
+
const output = (stdout || '') + (stderr || '');
|
|
391
|
+
|
|
392
|
+
const errorMatch = output.match(/(\d+)\s+error/i);
|
|
393
|
+
if (errorMatch) metrics.errors = parseInt(errorMatch[1]);
|
|
394
|
+
|
|
395
|
+
return metrics;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export default {
|
|
399
|
+
VALIDATION_PATTERNS,
|
|
400
|
+
EVAL_PATTERNS,
|
|
401
|
+
TEST_FRAMEWORK_PATTERNS,
|
|
402
|
+
SENSITIVE_PATTERNS,
|
|
403
|
+
SENSITIVE_INFO_PATTERNS,
|
|
404
|
+
DANGEROUS_PATTERNS,
|
|
405
|
+
detectValidationType,
|
|
406
|
+
isLayer1Validation,
|
|
407
|
+
detectEvalCommands,
|
|
408
|
+
detectTestFramework,
|
|
409
|
+
checkCommandSecurity,
|
|
410
|
+
checkSensitiveInfo,
|
|
411
|
+
checkDangerousCommand,
|
|
412
|
+
extractTestMetrics,
|
|
413
|
+
extractLintMetrics,
|
|
414
|
+
extractTypeMetrics,
|
|
415
|
+
};
|