/** * Genome Deserializer — 将进化后的 6 维基因组写回 SKILL.md * * 输入: skill_genomes 行 (6 维 JSONB + meta) * 输出: 标准 SKILL.md 文件内容 * * 这是进化闭环的关键环节: * SKILL.md → serialize → evolve → deserialize → SKILL.md → Agent 使用 */ const fs = require('fs'); const path = require('path'); // ════════════════════════════════════════════════════════ // 维度 → Markdown 区块生成器 // ════════════════════════════════════════════════════════ function parseDim(raw) { if (!raw) return {}; return typeof raw === 'string' ? JSON.parse(raw) : raw; } function renderFrontmatter(meta) { const lines = ['---']; lines.push(`name: ${meta.name}`); lines.push(`description: >-`); // 描述可能多行,缩进 2 空格;去除序列化残留的 >- 前缀 const rawDesc = (meta.description || '').replace(/^\s*>-\s*/, '').trim(); const descLines = rawDesc.split('\n'); for (const line of descLines) { lines.push(` ${line.trim()}`); } lines.push('metadata:'); lines.push(` category: ${meta.category || 'discipline'}`); lines.push(` author: evolution-system`); if (meta.triggers && meta.triggers.length > 0) { lines.push(` triggers: ${meta.triggers.join(', ')}`); } lines.push('---'); return lines.join('\n'); } function renderMentalModels(models) { if (!models) return ''; const lines = []; lines.push('## 第一性原理\n'); // 铁律 if (models.ironLaws?.length) { for (const law of models.ironLaws) { const text = typeof law === 'string' ? law : law.insight || JSON.stringify(law); // 去除 blockquote 前缀避免重复 const clean = text.replace(/^>\s*/, '').replace(/\*\*/g, ''); lines.push(`> **${clean}**\n`); } } // 类比 if (models.analogies?.length) { lines.push('### 认知类比\n'); for (const analogy of models.analogies) { if (typeof analogy === 'string') { lines.push(`- ${analogy}`); } else { lines.push(`- **来自${analogy.domain || '未知'}**: ${analogy.insight || ''}`); } } lines.push(''); } // 因果链 if (models.causalChains?.length) { lines.push('### 推论\n'); models.causalChains.forEach((chain, i) => { const text = typeof chain === 'string' ? chain : JSON.stringify(chain); lines.push(`${i + 1}. **${text}**`); }); lines.push(''); } return lines.join('\n'); } function renderPatternLibrary(patterns) { if (!patterns) return ''; const lines = []; // 分类规则 if (patterns.classificationRules?.length) { lines.push('## 模式识别\n'); lines.push('### 分类标记\n'); lines.push('| 标记 | 含义 | 决策 |'); lines.push('| ---- | ---- | ---- |'); for (const rule of patterns.classificationRules) { lines.push(`| ${rule.marker || ''} | ${rule.meaning || ''} | ${rule.action || ''} |`); } lines.push(''); } // 问题模式 if (patterns.problemPatterns?.length) { lines.push('### 问题识别模式\n'); lines.push('| 维度 | 搜索方式 | 原因 |'); lines.push('| ---- | -------- | ---- |'); for (const p of patterns.problemPatterns) { lines.push(`| ${p.dimension || ''} | ${p.searchTerms || ''} | ${p.rationale || ''} |`); } lines.push(''); } // 解决方案模式 if (patterns.solutionPatterns?.length) { lines.push('### 解决方案模式\n'); for (const p of patterns.solutionPatterns) { if (p.type === 'tool-sequence') { lines.push(`- **工具链**: \`${p.fingerprint || p.chain?.join('→') || ''}\` (频率: ${p.frequency || 1})`); } else if (p.type === 'explore-then-act') { lines.push(`- **探索→执行**: ${p.description || `探索 ${p.exploreSteps} 步后执行 ${p.actSteps} 步`}`); } else if (p.type === 'verification') { lines.push(`- **验证手法**: ${p.description || `用 ${p.verifyWith} 验证 ${p.writeWith} 的结果`}`); } else if (p.template) { lines.push(`#### ${p.name || '输出模板'}\n`); lines.push('```' + (p.format || 'markdown')); lines.push(p.template); lines.push('```\n'); } } lines.push(''); } return lines.join('\n'); } function renderJudgment(judgment) { if (!judgment) return ''; const lines = []; lines.push('## When to Use\n'); if (judgment.decisionRules?.length) { for (const rule of judgment.decisionRules) { lines.push(`- ${rule}`); } lines.push(''); } if (judgment.exclusions?.length) { lines.push('**NOT for:**\n'); for (const ex of judgment.exclusions) { lines.push(`- ${ex}`); } lines.push(''); } if (judgment.boundaries?.length) { lines.push('### 止损规则\n'); for (const b of judgment.boundaries) { lines.push(`- **${b}**`); } lines.push(''); } if (judgment.tradeoffs?.length) { lines.push('### 权衡偏好\n'); for (const t of judgment.tradeoffs) { if (typeof t === 'string') { lines.push(`- ${t}`); } else { lines.push(`- **${t.type || ''}**: ${t.rule || ''}`); } } lines.push(''); } return lines.join('\n'); } function renderToolFluency(fluency) { if (!fluency) return ''; const lines = []; lines.push('## 工具使用\n'); if (fluency.coreTools?.length) { lines.push('### 核心工具\n'); for (const tool of fluency.coreTools) { lines.push(`- \`${tool.name || tool}\``); } lines.push(''); } if (fluency.idioms?.length) { lines.push('### 惯用法\n'); for (const idiom of fluency.idioms) { const tools = idiom.tools?.map(t => `\`${t}\``).join(', ') || ''; lines.push(`- **${idiom.step || ''}**: ${tools}${idiom.description ? ' — ' + idiom.description : ''}`); } lines.push(''); } if (fluency.dataAccess?.length) { lines.push('### 数据获取\n'); for (const da of fluency.dataAccess) { lines.push(`- **${da.type || ''}**: ${da.tools?.map(t => `\`${t}\``).join(', ') || ''}`); if (da.sop?.length) { for (const step of da.sop) { lines.push(` 1. ${step}`); } } } lines.push(''); } return lines.join('\n'); } function renderTaste(taste) { if (!taste) return ''; const lines = []; lines.push('## 输出标准\n'); if (taste.outputStandards?.length) { lines.push('| 产物 | 格式 | 存放 | 受众 |'); lines.push('| ---- | ---- | ---- | ---- |'); for (const std of taste.outputStandards) { lines.push(`| ${std.artifact || ''} | ${std.format || ''} | ${std.location || ''} | ${std.audience || ''} |`); } lines.push(''); } if (taste.qualitySignals?.length) { lines.push('### 质量信号\n'); for (const sig of taste.qualitySignals) { const text = typeof sig === 'string' ? sig : sig.signal; lines.push(`- ${text}`); } lines.push(''); } if (taste.exemplars?.length) { lines.push('### 标杆范例\n'); for (const ex of taste.exemplars) { lines.push(`#### ${ex.name || ex.type || '范例'}\n`); lines.push('```' + (ex.format || 'markdown')); lines.push(ex.content || ''); lines.push('```\n'); } } return lines.join('\n'); } function renderScarTissue(scars) { if (!scars) return ''; const lines = []; lines.push('## 反模式检查清单\n'); if (scars.antiPatterns?.length) { lines.push('| 反模式 | 症状 | 纠正 |'); lines.push('| ------ | ---- | ---- |'); for (const ap of scars.antiPatterns) { lines.push(`| ${ap.pattern || ''} | ${ap.symptom || ''} | ${ap.correction || ''} |`); } lines.push(''); } if (scars.failures?.length) { lines.push('### 历史教训\n'); for (const f of scars.failures) { if (f.wrongAssumption && f.correctReality) { lines.push(`- ❌ "${f.wrongAssumption}" → ✅ ${f.correctReality}`); } else { const lesson = f.lesson || f.incident || ''; const prevention = f.preventionRule ? ` → **${f.preventionRule}**` : ''; lines.push(`- 🩹 ${lesson}${prevention}`); } } lines.push(''); } if (scars.antiRationalizations?.length) { lines.push('### Anti-Rationalization\n'); lines.push('| 借口 | 反驳 |'); lines.push('| ---- | ---- |'); for (const ar of scars.antiRationalizations) { lines.push(`| ${ar.excuse || ''} | ${ar.rebuttal || ''} |`); } lines.push(''); } return lines.join('\n'); } // ════════════════════════════════════════════════════════ // 主入口 // ════════════════════════════════════════════════════════ /** * 将基因组反序列化为 SKILL.md 内容 * * @param {object} genome - skill_genomes 行或包含 6 维数据的对象 * @param {object} meta - 元信息 { name, description, category, triggers } * @returns {string} SKILL.md 内容 */ function deserializeGenomeToSkill(genome, meta = {}) { const name = meta.name || genome.skill_name || genome.meta?.name || 'unnamed-skill'; const description = meta.description || genome.meta?.description || ''; const category = meta.category || genome.meta?.category || 'discipline'; const triggers = meta.triggers || genome.meta?.triggers || []; const mentalModels = parseDim(genome.mental_models || genome.mentalModels); const patternLibrary = parseDim(genome.pattern_library || genome.patternLibrary); const judgment = parseDim(genome.judgment); const toolFluency = parseDim(genome.tool_fluency || genome.toolFluency); const taste = parseDim(genome.taste); const scarTissue = parseDim(genome.scar_tissue || genome.scarTissue); const sections = [ renderFrontmatter({ name, description, category, triggers }), '', `# ${name}\n`, renderMentalModels(mentalModels), renderJudgment(judgment), renderPatternLibrary(patternLibrary), renderToolFluency(toolFluency), renderTaste(taste), renderScarTissue(scarTissue), ].filter(Boolean); return sections.join('\n').replace(/\n{3,}/g, '\n\n'); } /** * 将基因组写回 SKILL.md 文件 * * @param {object} genome - 基因组数据 * @param {string} targetDir - 目标 Skill 目录 * @param {object} meta - 元信息 * @param {object} options - { backup: true } 是否备份原文件 * @returns {object} { path, backedUp } */ function writeGenomeToSkill(genome, targetDir, meta = {}, options = {}) { const { backup = true } = options; const skillPath = path.join(targetDir, 'SKILL.md'); let backedUp = false; // 备份原文件 if (backup && fs.existsSync(skillPath)) { const backupPath = path.join(targetDir, `SKILL.md.bak.${Date.now()}`); fs.copyFileSync(skillPath, backupPath); backedUp = true; } // 读取原文件的 meta 作为兜底 if (fs.existsSync(skillPath) && !meta.description) { const original = fs.readFileSync(skillPath, 'utf-8'); const fmMatch = original.match(/^---\n([\s\S]*?)\n---/); if (fmMatch) { const descMatch = fmMatch[1].match(/description:\s*>-\s*\n([\s\S]*?)(?=\n\w|\n---)/); if (descMatch) { meta.description = descMatch[1].split('\n').map(l => l.trim()).join(' ').trim(); } } } const content = deserializeGenomeToSkill(genome, meta); // 确保目录存在 if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } fs.writeFileSync(skillPath, content, 'utf-8'); return { path: skillPath, backedUp }; } /** * 批量将一个 run 中所有存活基因组写回 SKILL.md * * @param {object[]} genomes - 基因组列表 * @param {string} skillsDir - Skills 根目录 * @param {object} options */ function writeAllGenomesToSkills(genomes, skillsDir, options = {}) { const results = []; for (const genome of genomes) { if (!genome.is_alive && genome.is_alive !== undefined) continue; const skillName = genome.skill_name; const targetDir = path.join(skillsDir, skillName); try { const result = writeGenomeToSkill(genome, targetDir, { name: skillName, }, options); results.push({ skillName, ...result, success: true }); console.log(` ✅ ${skillName} → ${result.path}${result.backedUp ? ' (已备份)' : ''}`); } catch (err) { results.push({ skillName, success: false, error: err.message }); console.error(` ❌ ${skillName}: ${err.message}`); } } return results; } module.exports = { deserializeGenomeToSkill, writeGenomeToSkill, writeAllGenomesToSkills, };