Initial commit with translated description
This commit is contained in:
147
scripts/human_report.js
Normal file
147
scripts/human_report.js
Normal file
@@ -0,0 +1,147 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const REPO_ROOT = path.resolve(__dirname, '..');
|
||||
const IN_FILE = path.join(REPO_ROOT, 'evolution_history_full.md');
|
||||
const OUT_FILE = path.join(REPO_ROOT, 'evolution_human_summary.md');
|
||||
|
||||
function generateHumanReport() {
|
||||
if (!fs.existsSync(IN_FILE)) return console.error("No input file");
|
||||
|
||||
const content = fs.readFileSync(IN_FILE, 'utf8');
|
||||
const entries = content.split('---').map(e => e.trim()).filter(e => e.length > 0);
|
||||
|
||||
const categories = {
|
||||
'Security & Stability': [],
|
||||
'Performance & Optimization': [],
|
||||
'Tooling & Features': [],
|
||||
'Documentation & Process': []
|
||||
};
|
||||
|
||||
const componentMap = {}; // Component -> Change List
|
||||
|
||||
entries.forEach(entry => {
|
||||
// Extract basic info
|
||||
const lines = entry.split('\n');
|
||||
const header = lines[0]; // ### Title (Date)
|
||||
const body = lines.slice(1).join('\n');
|
||||
|
||||
const dateMatch = header.match(/\((.*?)\)/);
|
||||
const dateStr = dateMatch ? dateMatch[1] : '';
|
||||
const time = dateStr.split(' ')[1] || ''; // HH:mm:ss
|
||||
|
||||
// Classify
|
||||
let category = 'Tooling & Features';
|
||||
let component = 'System';
|
||||
let summary = '';
|
||||
|
||||
const lowerBody = body.toLowerCase();
|
||||
|
||||
// Detect Component
|
||||
if (lowerBody.includes('feishu-card')) component = 'feishu-card';
|
||||
else if (lowerBody.includes('feishu-sticker')) component = 'feishu-sticker';
|
||||
else if (lowerBody.includes('git-sync')) component = 'git-sync';
|
||||
else if (lowerBody.includes('capability-evolver') || lowerBody.includes('evolve.js')) component = 'capability-evolver';
|
||||
else if (lowerBody.includes('interaction-logger')) component = 'interaction-logger';
|
||||
else if (lowerBody.includes('chat-to-image')) component = 'chat-to-image';
|
||||
else if (lowerBody.includes('safe_publish')) component = 'capability-evolver';
|
||||
|
||||
// Detect Category
|
||||
if (lowerBody.includes('security') || lowerBody.includes('permission') || lowerBody.includes('auth') || lowerBody.includes('harden')) {
|
||||
category = 'Security & Stability';
|
||||
} else if (lowerBody.includes('optimiz') || lowerBody.includes('performance') || lowerBody.includes('memory') || lowerBody.includes('fast')) {
|
||||
category = 'Performance & Optimization';
|
||||
} else if (lowerBody.includes('doc') || lowerBody.includes('readme')) {
|
||||
category = 'Documentation & Process';
|
||||
}
|
||||
|
||||
// Extract Human Summary (First meaningful line that isn't Status/Action/Date)
|
||||
const summaryLines = lines.filter(l =>
|
||||
!l.startsWith('###') &&
|
||||
!l.startsWith('Status:') &&
|
||||
!l.startsWith('Action:') &&
|
||||
l.trim().length > 10
|
||||
);
|
||||
|
||||
if (summaryLines.length > 0) {
|
||||
// Clean up the line
|
||||
summary = summaryLines[0]
|
||||
.replace(/^-\s*/, '') // Remove bullets
|
||||
.replace(/\*\*/g, '') // Remove bold
|
||||
.replace(/`/, '')
|
||||
.trim();
|
||||
|
||||
// Deduplicate
|
||||
const key = `${component}:${summary.substring(0, 20)}`;
|
||||
const exists = categories[category].some(i => i.key === key);
|
||||
|
||||
if (!exists && !summary.includes("Stability Scan OK") && !summary.includes("Workspace Sync")) {
|
||||
categories[category].push({ time, component, summary, key });
|
||||
|
||||
if (!componentMap[component]) componentMap[component] = [];
|
||||
componentMap[component].push(summary);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// --- Generate Markdown ---
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
let md = `# Evolution Summary: The Day in Review (${today})\n\n`;
|
||||
md += `> Overview: Grouped summary of changes extracted from evolution history.\n\n`;
|
||||
|
||||
// Section 1: By Theme (Evolution Direction)
|
||||
md += `## 1. Evolution Direction\n`;
|
||||
|
||||
for (const [cat, items] of Object.entries(categories)) {
|
||||
if (items.length === 0) continue;
|
||||
md += `### ${cat}\n`;
|
||||
// Group by component within theme
|
||||
const compGroup = {};
|
||||
items.forEach(i => {
|
||||
if (!compGroup[i.component]) compGroup[i.component] = [];
|
||||
compGroup[i.component].push(i.summary);
|
||||
});
|
||||
|
||||
for (const [comp, sums] of Object.entries(compGroup)) {
|
||||
// Unique summaries only
|
||||
const uniqueSums = [...new Set(sums)];
|
||||
uniqueSums.forEach(s => {
|
||||
md += `- **${comp}**: ${s}\n`;
|
||||
});
|
||||
}
|
||||
md += `\n`;
|
||||
}
|
||||
|
||||
// Section 2: By Timeline (High Level)
|
||||
md += `## 2. Timeline of Critical Events\n`;
|
||||
// Flatten and sort all items by time
|
||||
const allItems = [];
|
||||
Object.values(categories).forEach(list => allItems.push(...list));
|
||||
allItems.sort((a, b) => a.time.localeCompare(b.time));
|
||||
|
||||
// Filter for "Critical" keywords
|
||||
const criticalItems = allItems.filter(i =>
|
||||
i.summary.toLowerCase().includes('fix') ||
|
||||
i.summary.toLowerCase().includes('patch') ||
|
||||
i.summary.toLowerCase().includes('create') ||
|
||||
i.summary.toLowerCase().includes('optimiz')
|
||||
);
|
||||
|
||||
criticalItems.forEach(i => {
|
||||
md += `- \`${i.time}\` (${i.component}): ${i.summary}\n`;
|
||||
});
|
||||
|
||||
// Section 3: Package Adjustments
|
||||
md += `\n## 3. Package & Documentation Adjustments\n`;
|
||||
const comps = Object.keys(componentMap).sort();
|
||||
comps.forEach(comp => {
|
||||
const count = new Set(componentMap[comp]).size;
|
||||
md += `- **${comp}**: Received ${count} significant updates.\n`;
|
||||
});
|
||||
|
||||
fs.writeFileSync(OUT_FILE, md);
|
||||
console.log("Human report generated.");
|
||||
}
|
||||
|
||||
generateHumanReport();
|
||||
|
||||
Reference in New Issue
Block a user