@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,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Utilities - 统一的状态管理模块
|
|
3
|
+
*
|
|
4
|
+
* 提供统一的 state.json 和 metrics.json 读写功能
|
|
5
|
+
* 替代各 hook 中分散的状态读写逻辑
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
// 缓存
|
|
12
|
+
const stateCache = new Map();
|
|
13
|
+
const metricsCache = new Map();
|
|
14
|
+
const CACHE_TTL = 5000; // 5秒缓存
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 获取状态文件路径
|
|
18
|
+
* @param {string} projectRoot - 项目根目录
|
|
19
|
+
* @returns {string} state.json 路径
|
|
20
|
+
*/
|
|
21
|
+
function getStatePath(projectRoot) {
|
|
22
|
+
return path.join(projectRoot, '.autospec', 'runtime', 'state.json');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 获取指标文件路径
|
|
27
|
+
* @param {string} projectRoot - 项目根目录
|
|
28
|
+
* @returns {string} metrics.json 路径
|
|
29
|
+
*/
|
|
30
|
+
function getMetricsPath(projectRoot) {
|
|
31
|
+
return path.join(projectRoot, '.autospec', 'runtime', 'metrics.json');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 安全地读取 JSON 文件
|
|
36
|
+
* @param {string} filePath - 文件路径
|
|
37
|
+
* @param {any} defaultValue - 默认值
|
|
38
|
+
* @returns {any} 解析后的数据或默认值
|
|
39
|
+
*/
|
|
40
|
+
function safeReadJson(filePath, defaultValue = null) {
|
|
41
|
+
try {
|
|
42
|
+
if (!fs.existsSync(filePath)) {
|
|
43
|
+
return defaultValue;
|
|
44
|
+
}
|
|
45
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
46
|
+
return JSON.parse(content);
|
|
47
|
+
} catch (e) {
|
|
48
|
+
return defaultValue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 安全地写入 JSON 文件
|
|
54
|
+
* @param {string} filePath - 文件路径
|
|
55
|
+
* @param {any} data - 要写入的数据
|
|
56
|
+
* @returns {boolean} 是否成功
|
|
57
|
+
*/
|
|
58
|
+
function safeWriteJson(filePath, data) {
|
|
59
|
+
try {
|
|
60
|
+
const dir = path.dirname(filePath);
|
|
61
|
+
if (!fs.existsSync(dir)) {
|
|
62
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
65
|
+
return true;
|
|
66
|
+
} catch (e) {
|
|
67
|
+
// 权限错误时输出明确的修复建议
|
|
68
|
+
if (e.code === 'EACCES') {
|
|
69
|
+
console.error(`[AutoSpec hook-state-manager] ⚠️ 权限错误: 无法写入 ${filePath}`);
|
|
70
|
+
console.error(`[AutoSpec hook-state-manager] 请运行: sudo chown -R $(whoami) .autospec`);
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================
|
|
77
|
+
// State 操作
|
|
78
|
+
// ============================================================
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 获取完整 state 对象
|
|
82
|
+
* @param {string} projectRoot - 项目根目录
|
|
83
|
+
* @param {boolean} useCache - 是否使用缓存
|
|
84
|
+
* @returns {Object|null} state 对象
|
|
85
|
+
*/
|
|
86
|
+
export function getState(projectRoot, useCache = false) {
|
|
87
|
+
if (useCache) {
|
|
88
|
+
const cached = stateCache.get(projectRoot);
|
|
89
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
90
|
+
return cached.data;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const statePath = getStatePath(projectRoot);
|
|
95
|
+
const state = safeReadJson(statePath, null);
|
|
96
|
+
|
|
97
|
+
if (useCache && state) {
|
|
98
|
+
stateCache.set(projectRoot, { data: state, timestamp: Date.now() });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return state;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 更新 state 对象
|
|
106
|
+
* @param {string} projectRoot - 项目根目录
|
|
107
|
+
* @param {Object} updates - 要更新的字段
|
|
108
|
+
* @returns {boolean} 是否成功
|
|
109
|
+
*/
|
|
110
|
+
export function updateState(projectRoot, updates) {
|
|
111
|
+
const state = getState(projectRoot, false) || {};
|
|
112
|
+
const newState = { ...state, ...updates };
|
|
113
|
+
|
|
114
|
+
const statePath = getStatePath(projectRoot);
|
|
115
|
+
const success = safeWriteJson(statePath, newState);
|
|
116
|
+
|
|
117
|
+
if (success) {
|
|
118
|
+
stateCache.set(projectRoot, { data: newState, timestamp: Date.now() });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return success;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 读取 state 特定字段
|
|
126
|
+
* @param {string} projectRoot - 项目根目录
|
|
127
|
+
* @param {string} field - 字段名,支持点号分隔(如 'stages.stage01')
|
|
128
|
+
* @param {any} defaultValue - 默认值
|
|
129
|
+
* @returns {any} 字段值
|
|
130
|
+
*/
|
|
131
|
+
export function readStateField(projectRoot, field, defaultValue = null) {
|
|
132
|
+
const state = getState(projectRoot, true);
|
|
133
|
+
if (!state) return defaultValue;
|
|
134
|
+
|
|
135
|
+
const parts = field.split('.');
|
|
136
|
+
let current = state;
|
|
137
|
+
|
|
138
|
+
for (const part of parts) {
|
|
139
|
+
if (current === null || current === undefined) {
|
|
140
|
+
return defaultValue;
|
|
141
|
+
}
|
|
142
|
+
current = current[part];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return current !== undefined ? current : defaultValue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 设置 state 特定字段
|
|
150
|
+
* @param {string} projectRoot - 项目根目录
|
|
151
|
+
* @param {string} field - 字段名,支持点号分隔
|
|
152
|
+
* @param {any} value - 值
|
|
153
|
+
* @returns {boolean} 是否成功
|
|
154
|
+
*/
|
|
155
|
+
export function setStateField(projectRoot, field, value) {
|
|
156
|
+
const state = getState(projectRoot, false) || {};
|
|
157
|
+
const parts = field.split('.');
|
|
158
|
+
let current = state;
|
|
159
|
+
|
|
160
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
161
|
+
const part = parts[i];
|
|
162
|
+
if (!(part in current) || typeof current[part] !== 'object') {
|
|
163
|
+
current[part] = {};
|
|
164
|
+
}
|
|
165
|
+
current = current[part];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
current[parts[parts.length - 1]] = value;
|
|
169
|
+
|
|
170
|
+
return updateState(projectRoot, state);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 获取当前阶段
|
|
175
|
+
* @param {string} projectRoot - 项目根目录
|
|
176
|
+
* @returns {string|null} 当前阶段
|
|
177
|
+
*/
|
|
178
|
+
export function getCurrentStage(projectRoot) {
|
|
179
|
+
return readStateField(projectRoot, 'currentStage', null);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 获取阶段数据
|
|
184
|
+
* @param {string} projectRoot - 项目根目录
|
|
185
|
+
* @param {string} stageKey - 阶段键(如 'stage01')
|
|
186
|
+
* @returns {Object|null} 阶段数据
|
|
187
|
+
*/
|
|
188
|
+
export function getStageData(projectRoot, stageKey) {
|
|
189
|
+
return readStateField(projectRoot, `stages.${stageKey}`, null);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 检查阶段是否有 Layer 1 执行记录
|
|
194
|
+
* @param {string} projectRoot - 项目根目录
|
|
195
|
+
* @param {string} stageKey - 阶段键
|
|
196
|
+
* @returns {boolean} 是否有 Layer 1 记录
|
|
197
|
+
*/
|
|
198
|
+
export function hasLayer1Execution(projectRoot, stageKey) {
|
|
199
|
+
const stageData = getStageData(projectRoot, stageKey);
|
|
200
|
+
return stageData?.layer1Results && Object.keys(stageData.layer1Results).length > 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ============================================================
|
|
204
|
+
// Metrics 操作
|
|
205
|
+
// ============================================================
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 获取完整 metrics 对象
|
|
209
|
+
* @param {string} projectRoot - 项目根目录
|
|
210
|
+
* @param {boolean} useCache - 是否使用缓存
|
|
211
|
+
* @returns {Object} metrics 对象
|
|
212
|
+
*/
|
|
213
|
+
export function getMetrics(projectRoot, useCache = false) {
|
|
214
|
+
if (useCache) {
|
|
215
|
+
const cached = metricsCache.get(projectRoot);
|
|
216
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
217
|
+
return cached.data;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const metricsPath = getMetricsPath(projectRoot);
|
|
222
|
+
const defaultMetrics = {
|
|
223
|
+
pipelineStart: new Date().toISOString(),
|
|
224
|
+
stages: {},
|
|
225
|
+
totals: {
|
|
226
|
+
layer1Pass: 0,
|
|
227
|
+
layer1Fail: 0,
|
|
228
|
+
agentCalls: 0,
|
|
229
|
+
agentSuccess: 0,
|
|
230
|
+
agentFail: 0,
|
|
231
|
+
errors: [],
|
|
232
|
+
retries: 0,
|
|
233
|
+
humanInterventions: 0
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const metrics = safeReadJson(metricsPath, defaultMetrics);
|
|
238
|
+
|
|
239
|
+
if (useCache) {
|
|
240
|
+
metricsCache.set(projectRoot, { data: metrics, timestamp: Date.now() });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return metrics;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* 更新 metrics 对象
|
|
248
|
+
* @param {string} projectRoot - 项目根目录
|
|
249
|
+
* @param {Object} updates - 要更新的字段
|
|
250
|
+
* @returns {boolean} 是否成功
|
|
251
|
+
*/
|
|
252
|
+
export function updateMetrics(projectRoot, updates) {
|
|
253
|
+
const metrics = getMetrics(projectRoot, false);
|
|
254
|
+
const newMetrics = { ...metrics, ...updates };
|
|
255
|
+
|
|
256
|
+
const metricsPath = getMetricsPath(projectRoot);
|
|
257
|
+
const success = safeWriteJson(metricsPath, newMetrics);
|
|
258
|
+
|
|
259
|
+
if (success) {
|
|
260
|
+
metricsCache.set(projectRoot, { data: newMetrics, timestamp: Date.now() });
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return success;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 更新阶段指标
|
|
268
|
+
* @param {string} projectRoot - 项目根目录
|
|
269
|
+
* @param {string} stage - 阶段名
|
|
270
|
+
* @param {Object} updates - 要更新的字段
|
|
271
|
+
* @returns {boolean} 是否成功
|
|
272
|
+
*/
|
|
273
|
+
export function updateStageMetrics(projectRoot, stage, updates) {
|
|
274
|
+
const metrics = getMetrics(projectRoot, false);
|
|
275
|
+
|
|
276
|
+
if (!metrics.stages[stage]) {
|
|
277
|
+
metrics.stages[stage] = {
|
|
278
|
+
layer1Pass: 0,
|
|
279
|
+
layer1Fail: 0,
|
|
280
|
+
agentCalls: 0,
|
|
281
|
+
agentSuccess: 0,
|
|
282
|
+
agentFail: 0,
|
|
283
|
+
errors: []
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
metrics.stages[stage] = { ...metrics.stages[stage], ...updates };
|
|
288
|
+
|
|
289
|
+
return updateMetrics(projectRoot, metrics);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* 增加总计指标
|
|
294
|
+
* @param {string} projectRoot - 项目根目录
|
|
295
|
+
* @param {string} field - 字段名
|
|
296
|
+
* @param {number} increment - 增量
|
|
297
|
+
* @returns {boolean} 是否成功
|
|
298
|
+
*/
|
|
299
|
+
export function incrementTotalMetric(projectRoot, field, increment = 1) {
|
|
300
|
+
const metrics = getMetrics(projectRoot, false);
|
|
301
|
+
|
|
302
|
+
if (typeof metrics.totals[field] === 'number') {
|
|
303
|
+
metrics.totals[field] += increment;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return updateMetrics(projectRoot, metrics);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* 增加阶段指标
|
|
311
|
+
* @param {string} projectRoot - 项目根目录
|
|
312
|
+
* @param {string} stage - 阶段名
|
|
313
|
+
* @param {string} field - 字段名
|
|
314
|
+
* @param {number} increment - 增量
|
|
315
|
+
* @returns {boolean} 是否成功
|
|
316
|
+
*/
|
|
317
|
+
export function incrementStageMetric(projectRoot, stage, field, increment = 1) {
|
|
318
|
+
const metrics = getMetrics(projectRoot, false);
|
|
319
|
+
|
|
320
|
+
if (!metrics.stages[stage]) {
|
|
321
|
+
metrics.stages[stage] = {
|
|
322
|
+
layer1Pass: 0,
|
|
323
|
+
layer1Fail: 0,
|
|
324
|
+
agentCalls: 0,
|
|
325
|
+
agentSuccess: 0,
|
|
326
|
+
agentFail: 0,
|
|
327
|
+
errors: []
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (typeof metrics.stages[stage][field] === 'number') {
|
|
332
|
+
metrics.stages[stage][field] += increment;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return updateMetrics(projectRoot, metrics);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* 添加错误记录
|
|
340
|
+
* @param {string} projectRoot - 项目根目录
|
|
341
|
+
* @param {Object} errorEntry - 错误条目
|
|
342
|
+
* @param {string} stage - 阶段名(可选)
|
|
343
|
+
* @returns {boolean} 是否成功
|
|
344
|
+
*/
|
|
345
|
+
export function addErrorEntry(projectRoot, errorEntry, stage = null) {
|
|
346
|
+
const metrics = getMetrics(projectRoot, false);
|
|
347
|
+
|
|
348
|
+
const entry = {
|
|
349
|
+
time: new Date().toISOString(),
|
|
350
|
+
...errorEntry
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
metrics.totals.errors.push(entry);
|
|
354
|
+
|
|
355
|
+
if (stage && metrics.stages[stage]) {
|
|
356
|
+
metrics.stages[stage].errors.push(entry);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return updateMetrics(projectRoot, metrics);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ============================================================
|
|
363
|
+
// 缓存管理
|
|
364
|
+
// ============================================================
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* 清除 state 缓存
|
|
368
|
+
* @param {string} projectRoot - 项目根目录(可选,不提供则清除所有)
|
|
369
|
+
*/
|
|
370
|
+
export function clearStateCache(projectRoot = null) {
|
|
371
|
+
if (projectRoot) {
|
|
372
|
+
stateCache.delete(projectRoot);
|
|
373
|
+
} else {
|
|
374
|
+
stateCache.clear();
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* 清除 metrics 缓存
|
|
380
|
+
* @param {string} projectRoot - 项目根目录(可选,不提供则清除所有)
|
|
381
|
+
*/
|
|
382
|
+
export function clearMetricsCache(projectRoot = null) {
|
|
383
|
+
if (projectRoot) {
|
|
384
|
+
metricsCache.delete(projectRoot);
|
|
385
|
+
} else {
|
|
386
|
+
metricsCache.clear();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* 清除所有缓存
|
|
392
|
+
*/
|
|
393
|
+
export function clearAllCache() {
|
|
394
|
+
stateCache.clear();
|
|
395
|
+
metricsCache.clear();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ============================================================
|
|
399
|
+
// Trace 相关操作
|
|
400
|
+
// ============================================================
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* 获取 Trace ID
|
|
404
|
+
* @param {string} projectRoot - 项目根目录
|
|
405
|
+
* @returns {string|null} Trace ID
|
|
406
|
+
*/
|
|
407
|
+
export function getTraceId(projectRoot) {
|
|
408
|
+
const state = getState(projectRoot, true);
|
|
409
|
+
return state?.traceId || null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* 设置 Trace ID
|
|
414
|
+
* @param {string} projectRoot - 项目根目录
|
|
415
|
+
* @param {string} traceId - Trace ID
|
|
416
|
+
* @returns {boolean} 是否成功
|
|
417
|
+
*/
|
|
418
|
+
export function setTraceId(projectRoot, traceId) {
|
|
419
|
+
return updateState(projectRoot, {
|
|
420
|
+
traceId,
|
|
421
|
+
traceStartedAt: new Date().toISOString()
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* 重置 Trace ID(流程结束时调用)
|
|
427
|
+
* @param {string} projectRoot - 项目根目录
|
|
428
|
+
* @returns {boolean} 是否成功
|
|
429
|
+
*/
|
|
430
|
+
export function resetTraceId(projectRoot) {
|
|
431
|
+
return updateState(projectRoot, {
|
|
432
|
+
traceId: null,
|
|
433
|
+
traceEndedAt: new Date().toISOString()
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 获取执行模式
|
|
439
|
+
* @param {string} projectRoot - 项目根目录
|
|
440
|
+
* @returns {string} 执行模式 ('interactive' | 'autonomous')
|
|
441
|
+
*/
|
|
442
|
+
export function getExecutionMode(projectRoot) {
|
|
443
|
+
const state = getState(projectRoot, true);
|
|
444
|
+
return state?.executionMode || 'interactive';
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* 设置执行模式
|
|
449
|
+
* @param {string} projectRoot - 项目根目录
|
|
450
|
+
* @param {string} mode - 执行模式
|
|
451
|
+
* @returns {boolean} 是否成功
|
|
452
|
+
*/
|
|
453
|
+
export function setExecutionMode(projectRoot, mode) {
|
|
454
|
+
return updateState(projectRoot, { executionMode: mode });
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export default {
|
|
458
|
+
getState,
|
|
459
|
+
updateState,
|
|
460
|
+
readStateField,
|
|
461
|
+
setStateField,
|
|
462
|
+
getCurrentStage,
|
|
463
|
+
getStageData,
|
|
464
|
+
hasLayer1Execution,
|
|
465
|
+
getMetrics,
|
|
466
|
+
updateMetrics,
|
|
467
|
+
updateStageMetrics,
|
|
468
|
+
incrementTotalMetric,
|
|
469
|
+
incrementStageMetric,
|
|
470
|
+
addErrorEntry,
|
|
471
|
+
clearStateCache,
|
|
472
|
+
clearMetricsCache,
|
|
473
|
+
clearAllCache,
|
|
474
|
+
// Trace 相关
|
|
475
|
+
getTraceId,
|
|
476
|
+
setTraceId,
|
|
477
|
+
resetTraceId,
|
|
478
|
+
getExecutionMode,
|
|
479
|
+
setExecutionMode,
|
|
480
|
+
};
|