feat: Enhance documentation diagnosis and category mapping

- Introduced action to diagnose documentation structure, identifying redundancies and conflicts.
- Added centralized category mappings in JSON format for improved detection and strategy application.
- Updated existing functions to utilize new mappings for taxonomy and strategy matching.
- Implemented new detection patterns for documentation redundancy and conflict.
- Expanded state schema to include documentation diagnosis results.
- Enhanced severity criteria and strategy selection guide to accommodate new documentation issues.
This commit is contained in:
catlog22
2026-01-14 21:07:52 +08:00
parent 1f5ce9c03a
commit 266f6f11ec
10 changed files with 1340 additions and 946 deletions

View File

@@ -85,62 +85,55 @@ RULES:
### Phase 2: Spec 匹配
基于 `specs/dimension-mapping.md` 规则为每个维度匹配检测模式和修复策略:
基于 `specs/category-mappings.json` 配置为每个维度匹配检测模式和修复策略:
```javascript
// 加载集中式映射配置
const mappings = JSON.parse(Read('specs/category-mappings.json'));
function matchSpecs(dimensions) {
// 加载映射规则
const mappingRules = loadMappingRules();
return dimensions.map(dim => {
// 匹配 taxonomy pattern
const taxonomyMatch = findTaxonomyMatch(dim.inferred_category, mappingRules);
const taxonomyMatch = findTaxonomyMatch(dim.inferred_category);
// 匹配 strategy
const strategyMatch = findStrategyMatch(dim.inferred_category, mappingRules);
const strategyMatch = findStrategyMatch(dim.inferred_category);
// 判断是否满足(核心标准:有修复策略)
const hasFix = strategyMatch !== null && strategyMatch.strategies.length > 0;
return {
dimension_id: dim.id,
taxonomy_match: taxonomyMatch,
strategy_match: strategyMatch,
has_fix: hasFix,
needs_gemini_analysis: taxonomyMatch === null // 无内置检测时需要 Gemini 深度分析
needs_gemini_analysis: taxonomyMatch === null || mappings.categories[dim.inferred_category]?.needs_gemini_analysis
};
});
}
function findTaxonomyMatch(category, rules) {
const patternMapping = {
'context_explosion': { category: 'context_explosion', pattern_ids: ['CTX-001', 'CTX-002', 'CTX-003', 'CTX-004', 'CTX-005'], severity_hint: 'high' },
'memory_loss': { category: 'memory_loss', pattern_ids: ['MEM-001', 'MEM-002', 'MEM-003', 'MEM-004', 'MEM-005'], severity_hint: 'high' },
'dataflow_break': { category: 'dataflow_break', pattern_ids: ['DF-001', 'DF-002', 'DF-003', 'DF-004', 'DF-005'], severity_hint: 'critical' },
'agent_failure': { category: 'agent_failure', pattern_ids: ['AGT-001', 'AGT-002', 'AGT-003', 'AGT-004', 'AGT-005', 'AGT-006'], severity_hint: 'high' },
'performance': { category: 'performance', pattern_ids: ['CTX-001', 'CTX-003'], severity_hint: 'medium' },
'error_handling': { category: 'error_handling', pattern_ids: ['AGT-001', 'AGT-002'], severity_hint: 'medium' }
function findTaxonomyMatch(category) {
const config = mappings.categories[category];
if (!config || config.pattern_ids.length === 0) return null;
return {
category: category,
pattern_ids: config.pattern_ids,
severity_hint: config.severity_hint
};
return patternMapping[category] || null;
}
function findStrategyMatch(category, rules) {
const strategyMapping = {
'context_explosion': { strategies: ['sliding_window', 'path_reference', 'context_summarization', 'structured_state'], risk_levels: ['low', 'low', 'low', 'medium'] },
'memory_loss': { strategies: ['constraint_injection', 'state_constraints_field', 'checkpoint_restore', 'goal_embedding'], risk_levels: ['low', 'low', 'low', 'medium'] },
'dataflow_break': { strategies: ['state_centralization', 'schema_enforcement', 'field_normalization'], risk_levels: ['medium', 'low', 'low'] },
'agent_failure': { strategies: ['error_wrapping', 'result_validation', 'flatten_nesting'], risk_levels: ['low', 'low', 'medium'] },
'prompt_quality': { strategies: ['structured_prompt', 'output_schema', 'grounding_context', 'format_enforcement'], risk_levels: ['low', 'low', 'medium', 'low'] },
'architecture': { strategies: ['phase_decomposition', 'interface_contracts', 'plugin_architecture'], risk_levels: ['medium', 'medium', 'high'] },
'performance': { strategies: ['token_budgeting', 'parallel_execution', 'result_caching', 'lazy_loading'], risk_levels: ['low', 'low', 'low', 'low'] },
'error_handling': { strategies: ['graceful_degradation', 'error_propagation', 'structured_logging'], risk_levels: ['low', 'low', 'low'] },
'output_quality': { strategies: ['quality_gates', 'output_validation', 'template_enforcement'], risk_levels: ['low', 'low', 'low'] },
'user_experience': { strategies: ['progress_tracking', 'status_communication', 'interactive_checkpoints'], risk_levels: ['low', 'low', 'low'] }
function findStrategyMatch(category) {
const config = mappings.categories[category];
if (!config) {
// Fallback to custom from config
return mappings.fallback;
}
return {
strategies: config.strategies,
risk_levels: config.risk_levels
};
// Fallback to custom
return strategyMapping[category] || { strategies: ['custom'], risk_levels: ['medium'] };
}
```
@@ -224,11 +217,10 @@ function detectAmbiguities(dimensions, specMatches) {
}
function suggestInterpretations(dim) {
// 基于关键词推荐可能的解释
const categories = [
'context_explosion', 'memory_loss', 'dataflow_break', 'agent_failure',
'prompt_quality', 'architecture', 'performance', 'error_handling'
];
// 基于 mappings 配置推荐可能的解释
const categories = Object.keys(mappings.categories).filter(
cat => cat !== 'authoring_principles_violation' // 排除内部检测类别
);
return categories.slice(0, 4); // 返回最常见的 4 个作为选项
}
@@ -240,12 +232,10 @@ function hasConflictingKeywords(keywords) {
}
function getKeywordCategoryHint(keyword) {
// 从 mappings.keywords 构建查找表(合并中英文关键词)
const keywordMap = {
'慢': 'performance', 'slow': 'performance',
'遗忘': 'memory_loss', 'forget': 'memory_loss',
'状态': 'dataflow_break', 'state': 'dataflow_break',
'agent': 'agent_failure', '失败': 'agent_failure',
'token': 'context_explosion', '上下文': 'context_explosion'
...mappings.keywords.chinese,
...mappings.keywords.english
};
return keywordMap[keyword.toLowerCase()];
}
@@ -281,33 +271,13 @@ async function handleAmbiguities(ambiguities, dimensions) {
}
function getCategoryLabel(category) {
const labels = {
'context_explosion': '上下文膨胀',
'memory_loss': '指令遗忘',
'dataflow_break': '数据流问题',
'agent_failure': 'Agent 协调问题',
'prompt_quality': '提示词质量',
'architecture': '架构问题',
'performance': '性能问题',
'error_handling': '错误处理',
'custom': '其他问题'
};
return labels[category] || category;
// 从 mappings 配置加载标签
return mappings.category_labels_chinese[category] || category;
}
function getCategoryDescription(category) {
const descriptions = {
'context_explosion': 'Token 累积导致上下文过大',
'memory_loss': '早期指令或约束在后期丢失',
'dataflow_break': '状态数据在阶段间不一致',
'agent_failure': '子 Agent 调用失败或结果异常',
'prompt_quality': '提示词模糊导致输出不稳定',
'architecture': '阶段划分或模块结构不合理',
'performance': '执行慢或 Token 消耗高',
'error_handling': '错误恢复机制不完善',
'custom': '需要自定义分析的问题'
};
return descriptions[category] || '需要进一步分析';
// 从 mappings 配置加载描述
return mappings.category_descriptions[category] || 'Requires further analysis';
}
```

View File

@@ -0,0 +1,299 @@
# Action: Diagnose Documentation Structure
检测目标 skill 中的文档冗余和冲突问题。
## Purpose
- 检测重复定义State Schema、映射表、类型定义等
- 检测冲突定义(优先级定义不一致、实现与文档漂移等)
- 生成合并和解决冲突的建议
## Preconditions
- [ ] `state.status === 'running'`
- [ ] `state.target_skill !== null`
- [ ] `!state.diagnosis.docs`
- [ ] 用户指定 focus_areas 包含 'docs' 或 'all',或需要全面诊断
## Detection Patterns
### DOC-RED-001: 核心定义重复
检测 State Schema、核心接口等在多处定义
```javascript
async function detectDefinitionDuplicates(skillPath) {
const patterns = [
{ name: 'state_schema', regex: /interface\s+(TuningState|State)\s*\{/g },
{ name: 'fix_strategy', regex: /type\s+FixStrategy\s*=/g },
{ name: 'issue_type', regex: /type:\s*['"]?(context_explosion|memory_loss|dataflow_break)/g }
];
const files = Glob('**/*.md', { cwd: skillPath });
const duplicates = [];
for (const pattern of patterns) {
const matches = [];
for (const file of files) {
const content = Read(`${skillPath}/${file}`);
if (pattern.regex.test(content)) {
matches.push({ file, pattern: pattern.name });
}
}
if (matches.length > 1) {
duplicates.push({
type: pattern.name,
files: matches.map(m => m.file),
severity: 'high'
});
}
}
return duplicates;
}
```
### DOC-RED-002: 硬编码配置重复
检测 action 文件中硬编码与 spec 文档的重复:
```javascript
async function detectHardcodedDuplicates(skillPath) {
const actionFiles = Glob('phases/actions/*.md', { cwd: skillPath });
const specFiles = Glob('specs/*.md', { cwd: skillPath });
const duplicates = [];
for (const actionFile of actionFiles) {
const content = Read(`${skillPath}/${actionFile}`);
// 检测硬编码的映射对象
const hardcodedPatterns = [
/const\s+\w*[Mm]apping\s*=\s*\{/g,
/patternMapping\s*=\s*\{/g,
/strategyMapping\s*=\s*\{/g
];
for (const pattern of hardcodedPatterns) {
if (pattern.test(content)) {
duplicates.push({
type: 'hardcoded_mapping',
file: actionFile,
description: '硬编码映射可能与 specs/ 中的定义重复',
severity: 'high'
});
}
}
}
return duplicates;
}
```
### DOC-CON-001: 优先级定义冲突
检测 P0-P3 等优先级在不同文件中的定义不一致:
```javascript
async function detectPriorityConflicts(skillPath) {
const files = Glob('**/*.md', { cwd: skillPath });
const priorityDefs = {};
const priorityPattern = /\*\*P(\d+)\*\*[:\s]+([^\|]+)/g;
for (const file of files) {
const content = Read(`${skillPath}/${file}`);
let match;
while ((match = priorityPattern.exec(content)) !== null) {
const priority = `P${match[1]}`;
const definition = match[2].trim();
if (!priorityDefs[priority]) {
priorityDefs[priority] = [];
}
priorityDefs[priority].push({ file, definition });
}
}
const conflicts = [];
for (const [priority, defs] of Object.entries(priorityDefs)) {
const uniqueDefs = [...new Set(defs.map(d => d.definition))];
if (uniqueDefs.length > 1) {
conflicts.push({
key: priority,
definitions: defs,
severity: 'critical'
});
}
}
return conflicts;
}
```
### DOC-CON-002: 实现与文档漂移
检测硬编码与文档表格的不一致:
```javascript
async function detectImplementationDrift(skillPath) {
// 比较 category-mappings.json 与 specs/*.md 中的表格
const mappingsFile = `${skillPath}/specs/category-mappings.json`;
if (!fileExists(mappingsFile)) {
return []; // 无集中配置,跳过
}
const mappings = JSON.parse(Read(mappingsFile));
const conflicts = [];
// 与 dimension-mapping.md 对比
const dimMapping = Read(`${skillPath}/specs/dimension-mapping.md`);
for (const [category, config] of Object.entries(mappings.categories)) {
// 检查策略是否在文档中提及
for (const strategy of config.strategies || []) {
if (!dimMapping.includes(strategy)) {
conflicts.push({
type: 'mapping',
key: `${category}.strategies`,
issue: `策略 ${strategy} 在 JSON 中定义但未在文档中提及`
});
}
}
}
return conflicts;
}
```
## Execution
```javascript
async function executeDiagnosis(state, workDir) {
console.log('=== Diagnosing Documentation Structure ===');
const skillPath = state.target_skill.path;
const issues = [];
// 1. 检测冗余
const definitionDups = await detectDefinitionDuplicates(skillPath);
const hardcodedDups = await detectHardcodedDuplicates(skillPath);
for (const dup of [...definitionDups, ...hardcodedDups]) {
issues.push({
id: `DOC-RED-${issues.length + 1}`,
type: 'doc_redundancy',
severity: dup.severity,
location: { files: dup.files || [dup.file] },
description: dup.description || `${dup.type} 在多处定义`,
evidence: dup.files || [dup.file],
root_cause: '缺乏单一真相来源',
impact: '维护困难,易产生不一致',
suggested_fix: 'consolidate_to_ssot'
});
}
// 2. 检测冲突
const priorityConflicts = await detectPriorityConflicts(skillPath);
const driftConflicts = await detectImplementationDrift(skillPath);
for (const conflict of priorityConflicts) {
issues.push({
id: `DOC-CON-${issues.length + 1}`,
type: 'doc_conflict',
severity: 'critical',
location: { files: conflict.definitions.map(d => d.file) },
description: `${conflict.key} 在不同文件中定义不一致`,
evidence: conflict.definitions.map(d => `${d.file}: ${d.definition}`),
root_cause: '定义更新后未同步',
impact: '行为不可预测',
suggested_fix: 'reconcile_conflicting_definitions'
});
}
// 3. 生成报告
const severity = issues.some(i => i.severity === 'critical') ? 'critical' :
issues.some(i => i.severity === 'high') ? 'high' :
issues.length > 0 ? 'medium' : 'none';
const result = {
status: 'completed',
issues_found: issues.length,
severity: severity,
execution_time_ms: Date.now() - startTime,
details: {
patterns_checked: ['DOC-RED-001', 'DOC-RED-002', 'DOC-CON-001', 'DOC-CON-002'],
patterns_matched: issues.map(i => i.id.split('-').slice(0, 2).join('-')),
evidence: issues.flatMap(i => i.evidence),
recommendations: generateRecommendations(issues)
},
redundancies: issues.filter(i => i.type === 'doc_redundancy'),
conflicts: issues.filter(i => i.type === 'doc_conflict')
};
// 写入诊断结果
Write(`${workDir}/diagnosis/docs-diagnosis.json`, JSON.stringify(result, null, 2));
return {
stateUpdates: {
'diagnosis.docs': result,
issues: [...state.issues, ...issues]
},
outputFiles: [`${workDir}/diagnosis/docs-diagnosis.json`],
summary: `文档诊断完成:发现 ${issues.length} 个问题 (${severity})`
};
}
function generateRecommendations(issues) {
const recommendations = [];
if (issues.some(i => i.type === 'doc_redundancy')) {
recommendations.push('使用 consolidate_to_ssot 策略合并重复定义');
recommendations.push('考虑创建 specs/category-mappings.json 集中管理配置');
}
if (issues.some(i => i.type === 'doc_conflict')) {
recommendations.push('使用 reconcile_conflicting_definitions 策略解决冲突');
recommendations.push('建立文档同步检查机制');
}
return recommendations;
}
```
## Output
### State Updates
```javascript
{
stateUpdates: {
'diagnosis.docs': {
status: 'completed',
issues_found: N,
severity: 'critical|high|medium|low|none',
redundancies: [...],
conflicts: [...]
},
issues: [...existingIssues, ...newIssues]
}
}
```
### Output Files
- `${workDir}/diagnosis/docs-diagnosis.json` - 完整诊断结果
## Error Handling
| Error | Recovery |
|-------|----------|
| 文件读取失败 | 记录警告,继续处理其他文件 |
| 正则匹配超时 | 跳过该模式,记录 skipped |
| JSON 解析失败 | 跳过配置对比,仅进行模式检测 |
## Next Actions
- 如果发现 critical 问题 → 优先进入 action-propose-fixes
- 如果无问题 → 继续下一个诊断或 action-generate-report