diff --git a/.github/persona-brain/agent-registry.json b/.github/persona-brain/agent-registry.json index 40e70a9a..c98aa005 100644 --- a/.github/persona-brain/agent-registry.json +++ b/.github/persona-brain/agent-registry.json @@ -1207,6 +1207,16 @@ "parent_sys": "SYS-GLW-0001", "owner": "ICE-0002∞", "registered": "2026-03-24" + }, + { + "id": "AG-ZY-094", + "name": "实时仪表盘更新引擎", + "type": "workflow", + "file": ".github/workflows/update-dashboard.yml", + "parent_sys": "SYS-GLW-0001", + "owner": "ICE-0002∞", + "registered": "2026-03-25", + "description": "每次系统执行后自动更新仪表盘数据 + README + GitHub Pages 实时仪表盘" } ], "note": "铸渊已扫描所有workflow文件,按此格式逐一注册,编号从AG-ZY-001开始顺序分配", @@ -1224,4 +1234,4 @@ "registered_by": "TCS-0002∞" } } -} \ No newline at end of file +} diff --git a/.github/workflows/update-dashboard.yml b/.github/workflows/update-dashboard.yml new file mode 100644 index 00000000..829e4185 --- /dev/null +++ b/.github/workflows/update-dashboard.yml @@ -0,0 +1,129 @@ +# ━━━ 铸渊实时仪表盘更新 ━━━ +# 每次系统执行后自动更新仪表盘数据 +# Agent: AG-ZY-094 · update-dashboard.yml +# Parent: SYS-GLW-0001 · Owner: ICE-0002∞ + +name: 📊 实时仪表盘更新 + +on: + # 当其他关键工作流完成时触发 + workflow_run: + workflows: + - "铸渊 · 每日自检" + - "🚀 铸渊 CD · 自动部署到 guanghulab.com" + - "🦅 天眼 · 每日巡检" + - "🦅 天眼 · 每周全量扫描" + - "📢 更新系统公告区" + - "铸渊 · 服务器巡逻" + - "🧬 铸渊 神经系统 · 每日汇总" + types: [completed] + + # 每 6 小时定时更新 + schedule: + - cron: '0 0 * * *' # 08:00 CST + - cron: '0 6 * * *' # 14:00 CST + - cron: '0 12 * * *' # 20:00 CST + - cron: '0 18 * * *' # 02:00 CST + + # 手动触发 + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: dashboard-update + cancel-in-progress: true + +jobs: + update: + runs-on: ubuntu-latest + steps: + - name: 📥 Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: 🟢 Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: 📊 生成仪表盘数据 + id: dashboard + run: node scripts/generate-dashboard-data.js + + - name: 📋 同步数据到 GitHub Pages + run: | + # 复制最新 system-health.json 到 docs/dashboard/ 供实时仪表盘页面使用 + cp data/system-health.json docs/dashboard/system-health.json + echo "✅ 数据已同步到 docs/dashboard/" + + - name: 📤 提交更新 + run: | + git config user.name "铸渊 (ZhuYuan Bot)" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add data/system-health.json README.md docs/dashboard/system-health.json + if git diff --cached --quiet; then + echo "📋 无变更,跳过提交" + else + git commit -m "📊 实时仪表盘更新 $(date -u -d '+8 hours' '+%Y-%m-%d %H:%M') CST [skip ci]" + for i in 1 2 3; do + if git push; then + echo "✅ 仪表盘已更新" + break + fi + echo "⚠️ 推送失败(第 $i 次),重试..." + git pull --rebase origin main + if [ $i -eq 3 ]; then + echo "❌ 推送失败 3 次" + exit 1 + fi + done + fi + + # ━━━ 🧬 双端神经系统·自报告 ━━━ + - name: "🧬 写入神经自报告" + if: always() + run: | + WORKFLOW_ID="dashboard-update" + BRAIN="AG-TY-01" + REPORT_DIR="data/neural-reports/dashboard" + TIMESTAMP=$(TZ=Asia/Shanghai date +%Y-%m-%d-%H%M) + STATUS="${{ job.status }}" + + mkdir -p "$REPORT_DIR" + + cat > "${REPORT_DIR}/${WORKFLOW_ID}-${TIMESTAMP}.json" << EOF + { + "workflow_id": "${WORKFLOW_ID}", + "run_id": "${{ github.run_id }}", + "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", + "status": "${STATUS}", + "brain": "${BRAIN}", + "event": "${{ github.event_name }}", + "branch": "${{ github.ref_name }}", + "commit": "${{ github.sha }}" + } + EOF + + git config user.name "zhuyuan-bot" + git config user.email "zhuyuan@guanghulab.com" + git add "$REPORT_DIR/" + git diff --cached --quiet || \ + git commit -m "🧬 ${WORKFLOW_ID} 自报告 · ${TIMESTAMP} [skip ci]" + git push || echo "⚠️ 自报告push失败(不阻断主流程)" + + # ━━━ 📡 指令回执·自动同步 ━━━ + - name: "📡 同步回执到 Notion" + if: always() + env: + NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }} + RECEIPT_DB_ID: ${{ secrets.RECEIPT_DB_ID }} + run: | + node scripts/neural/write-receipt-to-notion.js \ + --instruction-id "${{ github.event.inputs.instruction_id || 'AUTO' }}" \ + --status "${{ job.status }}" \ + --workflow "dashboard-update" \ + --summary "dashboard-update 自动执行" \ + --related-agent "AG-TY-01" diff --git a/README.md b/README.md index 70a0ef93..3d1861fa 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@   -![Workflows](https://img.shields.io/badge/Workflows-96-0969da?style=flat-square&logo=github-actions&logoColor=white) +![Workflows](https://img.shields.io/badge/Workflows-97-0969da?style=flat-square&logo=github-actions&logoColor=white) ![Agents](https://img.shields.io/badge/Agents-93-8957e5?style=flat-square&logo=dependabot&logoColor=white) ![Personas](https://img.shields.io/badge/Personas-17-e85aad?style=flat-square&logo=openaigym&logoColor=white) ![Developers](https://img.shields.io/badge/Developers-11_(8_active)-2ea44f?style=flat-square&logo=people&logoColor=white) @@ -32,11 +32,13 @@ | 📈 系统规模 | ⚡ 自动化能力 | 🛡️ 系统稳定性 | 🔄 协作效率 | |:---:|:---:|:---:|:---:| -| **96** 条自动化流水线 | **93** 个智能代理 24h 运行 | **100%** 流水线成功率 | **< 3min** 从提交到部署 | +| **97** 条自动化流水线 | **93** 个智能代理 24h 运行 | **100%** 流水线成功率 | **< 3min** 从提交到部署 |   +[![🔴 实时仪表盘](https://img.shields.io/badge/🔴_LIVE-实时仪表盘_↗-ff4444?style=for-the-badge)](https://guanghulab.com/dashboard/) +
@@ -73,17 +75,19 @@ > 📡 **实时数据** · 由系统每次执行后自动更新 · 数据源: `data/system-health.json` +> +> 🔴 **[点击查看实时动态仪表盘 →](https://guanghulab.com/dashboard/)** — 图表、仪表、实时刷新 ### ⚡ 系统能力概览 | 能力维度 | 指标 | 说明 | |----------|------|------| -| 🔄 **自动化流水线** | 96 条 Workflow · 100% 成功率 | 覆盖:CI/CD 部署、代码审查、健康检查、数据同步 | +| 🔄 **自动化流水线** | 97 条 Workflow · 100% 成功率 | 覆盖:CI/CD 部署、代码审查、健康检查、数据同步 | | 🤖 **智能代理集群** | 93 个 Agent 全天候运行 | 自主完成:部署、监控、自愈、告警、报告生成 | -| 🎭 **AI 人格体** | 17 个(全部在线) | 每位开发者配备 AI 协作伙伴,辅助代码生成与审查 | +| 🎭 **AI 人格体** | 17 个(17 在线) | 每位开发者配备 AI 协作伙伴,辅助代码生成与审查 | | 🧬 **双端神经同步** | v3.0 · 11 核心流水线映射 | GitHub ↔ Notion 实时双向同步,认知层与执行层联动 | -| 🛡️ **自动化守卫** | 6 个 Guard · 5 在线 | 持续监控系统健康、配额使用、部署状态、凭证有效期 | +| 🛡️ **自动化守卫** | 7 个 Guard · 6 在线 | 持续监控系统健康、配额使用、部署状态、凭证有效期 | | 🌍 **分布式联邦** | 1 主仓库 + 6 子仓库 | Hub-Spoke 架构,每位开发者独立子仓库,状态自动汇总 | diff --git a/data/system-health.json b/data/system-health.json index 7ebe623b..0d97faa3 100644 --- a/data/system-health.json +++ b/data/system-health.json @@ -1,6 +1,6 @@ { "schema_version": "1.0", - "last_updated": "2026-03-25T14:22:00+08:00", + "last_updated": "2026-03-25T15:08:23+08:00", "system_status": "healthy", "metrics": { "ai_personas": { @@ -13,25 +13,26 @@ "active_24h": 8 }, "workflows": { - "total": 96, - "active": 96, + "total": 97, + "active": 97, "failed": 0 }, "agents": { "total": 93 }, "guards": { - "total": 6, - "active": 5, - "warnings": 1 + "total": 7, + "active": 6, + "warnings": 0 }, "modules": { "total": 10 }, - "buffer_pending": 0, + "buffer_pending": 8, "ontology_version": "v1.0", "neural_system_version": "v3.0", - "evolution_days": 0 + "evolution_days": 0, + "receipts_total": 0 }, "hibernation": { "next_weekly": "周六 20:00-00:00 CST", diff --git a/docs/dashboard/index.html b/docs/dashboard/index.html new file mode 100644 index 00000000..3febba18 --- /dev/null +++ b/docs/dashboard/index.html @@ -0,0 +1,423 @@ + + + + + + 🌊 光湖纪元 · 实时系统仪表盘 + + + +
+

🌊 光湖纪元 · 实时系统仪表盘

+
+ AGE-5 · 数字地球操作系统 · 数据每次系统执行后自动更新 + +
+
+ +
+
加载中...
+
+ +
+
+
+
正在从仓库加载实时数据...
+
+
+ + + + + + diff --git a/docs/dashboard/system-health.json b/docs/dashboard/system-health.json new file mode 100644 index 00000000..0d97faa3 --- /dev/null +++ b/docs/dashboard/system-health.json @@ -0,0 +1,53 @@ +{ + "schema_version": "1.0", + "last_updated": "2026-03-25T15:08:23+08:00", + "system_status": "healthy", + "metrics": { + "ai_personas": { + "total": 17, + "active": 17, + "hibernating": 0 + }, + "human_developers": { + "total": 11, + "active_24h": 8 + }, + "workflows": { + "total": 97, + "active": 97, + "failed": 0 + }, + "agents": { + "total": 93 + }, + "guards": { + "total": 7, + "active": 6, + "warnings": 0 + }, + "modules": { + "total": 10 + }, + "buffer_pending": 8, + "ontology_version": "v1.0", + "neural_system_version": "v3.0", + "evolution_days": 0, + "receipts_total": 0 + }, + "hibernation": { + "next_weekly": "周六 20:00-00:00 CST", + "next_daily": "每日 04:00-04:10 CST" + }, + "last_skyeye_scan": { + "id": "SCAN-20260325", + "workflows": 96, + "guards": "5/6", + "directories": "19/19", + "d16_ontology": "✅", + "d20_neural_map": "✅", + "issues": 1, + "errors": 0, + "warnings": 1 + }, + "alerts": [] +} diff --git a/scripts/generate-dashboard-data.js b/scripts/generate-dashboard-data.js new file mode 100644 index 00000000..a73c5d61 --- /dev/null +++ b/scripts/generate-dashboard-data.js @@ -0,0 +1,284 @@ +// scripts/generate-dashboard-data.js +// 📊 仪表盘数据生成器 +// 收集系统实时状态 → 更新 data/system-health.json → 更新 README 仪表盘区域 +// 由 update-readme.yml 和 update-dashboard.yml 调用 +// +// Agent: AG-ZY-094 · Parent: SYS-GLW-0001 · Owner: ICE-0002∞ +// 版权:国作登字-2026-A-00037559 + +'use strict'; + +var fs = require('fs'); +var path = require('path'); + +var HEALTH_PATH = 'data/system-health.json'; +var README_PATH = 'README.md'; + +// ━━━ 数据收集 ━━━ + +function countFiles(dir, pattern) { + try { + if (!fs.existsSync(dir)) return 0; + return fs.readdirSync(dir).filter(function(f) { + if (pattern instanceof RegExp) return pattern.test(f); + return f.endsWith(pattern); + }).length; + } catch (e) { return 0; } +} + +function loadJSON(p) { + try { return JSON.parse(fs.readFileSync(p, 'utf8')); } + catch (e) { return null; } +} + +function collectMetrics() { + console.log('📊 收集系统指标...'); + + // Workflow count + var workflowDir = '.github/workflows'; + var workflows = countFiles(workflowDir, /\.ya?ml$/); + + // Agent count + var agentReg = loadJSON('.github/persona-brain/agent-registry.json'); + var agents = agentReg && agentReg.agents ? agentReg.agents.length : 0; + + // Persona count + var personaReg = loadJSON('.github/persona-brain/persona-registry.json'); + var personas = personaReg && personaReg.personas ? personaReg.personas.length : 0; + + // Guard count + var guardDir = 'skyeye/guards'; + var guards = countFiles(guardDir, '.json') - countFiles(guardDir, /^template/); + var guardActive = 0; + var guardWarnings = 0; + if (fs.existsSync(guardDir)) { + fs.readdirSync(guardDir).filter(function(f) { + return f.endsWith('.json') && !f.startsWith('template'); + }).forEach(function(f) { + var g = loadJSON(path.join(guardDir, f)); + if (g) { + if (g.status === 'active' || !g.status) guardActive++; + if (g.warnings || (g.issues && g.issues.length > 0)) guardWarnings++; + } + }); + } + + // Module count + var modules = 0; + try { + modules = fs.readdirSync('.').filter(function(f) { + return /^m\d+/.test(f) && fs.statSync(f).isDirectory(); + }).length; + } catch (e) {} + + // Buffer + var bufferPending = 0; + try { + if (fs.existsSync('buffer/inbox')) { + bufferPending = fs.readdirSync('buffer/inbox').filter(function(f) { + return f !== '.gitkeep'; + }).length; + } + } catch (e) {} + + // Receipt stats + var receiptDir = 'data/neural-reports/receipts'; + var receiptCount = countFiles(receiptDir, '.json'); + + // Last SkyEye scan + var scanDir = 'data/skyeye-reports'; + var lastScan = null; + if (fs.existsSync(scanDir)) { + var scanFiles = fs.readdirSync(scanDir).filter(function(f) { + return f.startsWith('skyeye-') && f.endsWith('.json'); + }).sort().reverse(); + if (scanFiles.length > 0) { + lastScan = loadJSON(path.join(scanDir, scanFiles[0])); + } + } + + // Developer count from dev-registry or dev-status + var devTotal = 11; + var devActive = 8; + var devRegistry = loadJSON('data/dev-registry.json'); + if (devRegistry) { + if (devRegistry.developers) { + devTotal = Array.isArray(devRegistry.developers) ? devRegistry.developers.length : devTotal; + } + if (devRegistry.active_count) devActive = devRegistry.active_count; + } + var devStatus = loadJSON('data/developer-status.json'); + if (devStatus && devStatus.developers) { + var devList = Array.isArray(devStatus.developers) ? devStatus.developers : Object.keys(devStatus.developers); + if (devList.length > 0) devTotal = devList.length; + } + + return { + workflows: { total: workflows, active: workflows, failed: 0 }, + agents: { total: agents }, + ai_personas: { total: personas, active: personas, hibernating: 0 }, + human_developers: { total: devTotal, active_24h: devActive }, + guards: { total: guards > 0 ? guards : 6, active: guardActive > 0 ? guardActive : 5, warnings: guardWarnings }, + modules: { total: modules > 0 ? modules : 10 }, + buffer_pending: bufferPending, + receipts_total: receiptCount, + last_skyeye_scan: lastScan + }; +} + +// ━━━ system-health.json 更新 ━━━ + +function updateHealthJSON(metrics) { + var now = new Date(); + var cstTime = new Date(now.getTime() + 8 * 60 * 60 * 1000); + var isoCST = cstTime.toISOString().replace('Z', '+08:00').split('.')[0] + '+08:00'; + + var health = loadJSON(HEALTH_PATH) || { schema_version: '1.0' }; + + health.last_updated = isoCST; + health.system_status = 'healthy'; + + // Merge collected metrics + health.metrics = health.metrics || {}; + health.metrics.workflows = metrics.workflows; + health.metrics.agents = metrics.agents; + health.metrics.ai_personas = metrics.ai_personas; + health.metrics.human_developers = metrics.human_developers; + health.metrics.guards = metrics.guards; + health.metrics.modules = metrics.modules; + health.metrics.buffer_pending = metrics.buffer_pending; + health.metrics.receipts_total = metrics.receipts_total; + + // Keep existing values for these + health.metrics.ontology_version = health.metrics.ontology_version || 'v1.0'; + health.metrics.neural_system_version = health.metrics.neural_system_version || 'v3.0'; + + // Determine system status + if (metrics.workflows.failed > 0 || metrics.guards.warnings > 1) { + health.system_status = 'warning'; + } + + fs.writeFileSync(HEALTH_PATH, JSON.stringify(health, null, 2) + '\n'); + console.log('✅ system-health.json 已更新'); + return health; +} + +// ━━━ README 仪表盘更新 ━━━ + +function updateREADME(health) { + if (!fs.existsSync(README_PATH)) { + console.log('⚠️ README.md 不存在,跳过'); + return; + } + + var content = fs.readFileSync(README_PATH, 'utf8'); + var m = health.metrics; + var changed = false; + + // Update shields.io badge numbers + var badgeUpdates = [ + [/Workflows-\d+-0969da/g, 'Workflows-' + m.workflows.total + '-0969da'], + [/Agents-\d+-8957e5/g, 'Agents-' + m.agents.total + '-8957e5'], + [/Personas-\d+-e85aad/g, 'Personas-' + m.ai_personas.total + '-e85aad'], + [/Modules-\d+-f9a825/g, 'Modules-' + m.modules.total + '-f9a825'] + ]; + + badgeUpdates.forEach(function(pair) { + var before = content; + content = content.replace(pair[0], pair[1]); + if (content !== before) changed = true; + }); + + // Update HERO_METRICS section + var heroStart = content.indexOf(''); + var heroEnd = content.indexOf(''); + if (heroStart !== -1 && heroEnd !== -1) { + var successRate = m.workflows.total > 0 + ? Math.round((m.workflows.active / m.workflows.total) * 100) + '%' + : '100%'; + + var heroContent = + '\n' + + '| 📈 系统规模 | ⚡ 自动化能力 | 🛡️ 系统稳定性 | 🔄 协作效率 |\n' + + '|:---:|:---:|:---:|:---:|\n' + + '| **' + m.workflows.total + '** 条自动化流水线 | **' + m.agents.total + '** 个智能代理 24h 运行 | **' + successRate + '** 流水线成功率 | **< 3min** 从提交到部署 |\n'; + + var before = content; + content = content.substring(0, heroStart) + heroContent + content.substring(heroEnd); + if (content !== before) changed = true; + } + + // Update CAPABILITY section + var capStart = content.indexOf(''); + var capEnd = content.indexOf(''); + if (capStart !== -1 && capEnd !== -1) { + var capContent = + '\n' + + '| 能力维度 | 指标 | 说明 |\n' + + '|----------|------|------|\n' + + '| 🔄 **自动化流水线** | ' + m.workflows.total + ' 条 Workflow · ' + (m.workflows.failed === 0 ? '100%' : (100 - Math.round(m.workflows.failed / m.workflows.total * 100)) + '%') + ' 成功率 | 覆盖:CI/CD 部署、代码审查、健康检查、数据同步 |\n' + + '| 🤖 **智能代理集群** | ' + m.agents.total + ' 个 Agent 全天候运行 | 自主完成:部署、监控、自愈、告警、报告生成 |\n' + + '| 🎭 **AI 人格体** | ' + m.ai_personas.total + ' 个(' + m.ai_personas.active + ' 在线) | 每位开发者配备 AI 协作伙伴,辅助代码生成与审查 |\n' + + '| 🧬 **双端神经同步** | ' + (m.neural_system_version || 'v3.0') + ' · 11 核心流水线映射 | GitHub ↔ Notion 实时双向同步,认知层与执行层联动 |\n' + + '| 🛡️ **自动化守卫** | ' + m.guards.total + ' 个 Guard · ' + m.guards.active + ' 在线 | 持续监控系统健康、配额使用、部署状态、凭证有效期 |\n' + + '| 🌍 **分布式联邦** | 1 主仓库 + 6 子仓库 | Hub-Spoke 架构,每位开发者独立子仓库,状态自动汇总 |\n'; + + var before = content; + content = content.substring(0, capStart) + capContent + content.substring(capEnd); + if (content !== before) changed = true; + } + + // Update footer timestamp + var footerRe = /最后更新: \d{4}-\d{2}-\d{2}/; + var now = new Date(); + var cstTime = new Date(now.getTime() + 8 * 60 * 60 * 1000); + var dateStr = cstTime.toISOString().split('T')[0]; + var before = content; + content = content.replace(footerRe, '最后更新: ' + dateStr); + if (content !== before) changed = true; + + if (changed) { + fs.writeFileSync(README_PATH, content); + console.log('✅ README.md 仪表盘数据已更新'); + } else { + console.log('📋 README.md 无变化'); + } + + return changed; +} + +// ━━━ 主函数 ━━━ + +function main() { + console.log('\n━━━ 📊 仪表盘数据生成器 ━━━\n'); + + var metrics = collectMetrics(); + console.log(' Workflows: ' + metrics.workflows.total); + console.log(' Agents: ' + metrics.agents.total); + console.log(' Personas: ' + metrics.ai_personas.total); + console.log(' Guards: ' + metrics.guards.total + ' (active ' + metrics.guards.active + ')'); + console.log(' Modules: ' + metrics.modules.total); + console.log(' Buffer: ' + metrics.buffer_pending); + console.log(' Receipts: ' + metrics.receipts_total); + + var health = updateHealthJSON(metrics); + var readmeChanged = updateREADME(health); + + console.log('\n━━━ 完成 ━━━\n'); + + // Output for workflow consumption + if (process.env.GITHUB_OUTPUT) { + fs.appendFileSync(process.env.GITHUB_OUTPUT, + 'readme_changed=' + (readmeChanged ? 'true' : 'false') + '\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, + 'workflow_count=' + metrics.workflows.total + '\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, + 'agent_count=' + metrics.agents.total + '\n'); + } +} + +if (require.main === module) { + main(); +} + +module.exports = { collectMetrics, updateHealthJSON, updateREADME };