From b0c77832efc87a37ce0ccba2eb894352fd5ef906 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 17:09:37 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=85=20[skyeye]=20=E5=A4=A9=E7=9C=BC?= =?UTF-8?q?=E5=91=A8=E6=8A=A5=E5=A2=9E=E5=8A=A0=E7=B3=BB=E7=BB=9F=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=E6=B1=87=E6=80=BB=20=C2=B7=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20README=20+=20Notion=20=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/6bdf5c3c-1a3e-4689-bcfc-2aa7367615a7 --- .github/workflows/skyeye-weekly-scan.yml | 29 +- README.md | 32 ++- scripts/skyeye/generate-arch-summary.js | 334 +++++++++++++++++++++++ 3 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 scripts/skyeye/generate-arch-summary.js diff --git a/.github/workflows/skyeye-weekly-scan.yml b/.github/workflows/skyeye-weekly-scan.yml index b1226dcb..ded42a5c 100644 --- a/.github/workflows/skyeye-weekly-scan.yml +++ b/.github/workflows/skyeye-weekly-scan.yml @@ -33,10 +33,35 @@ jobs: - name: "📝 Phase 5 - Generate Report" run: node skyeye/scripts/weekly-scan.js --report + - name: "📊 Phase 6 - Architecture Summary → README" + run: node scripts/skyeye/generate-arch-summary.js + - name: "Commit scan results" run: | git config user.name "天眼 · SkyEye Core" git config user.email "skyeye@guanghu.system" - git add skyeye/ buffer/config/ - git diff --cached --quiet || git commit -m "[skyeye-weekly] $(date -u +%Y%m%d) full scan complete [skip ci]" + git add skyeye/ buffer/config/ README.md + git diff --cached --quiet || git commit -m "🦅 [skyeye-weekly] $(date -u +%Y%m%d) full scan + arch summary [skip ci]" git push + + # Notion 同步 · 架构汇总推送到 Notion(通过 Bridge E) + notify-notion: + needs: weekly-scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main # 确保拉到刚 push 的最新版 + + - name: "📡 Sync arch summary to Notion via Bridge E" + env: + NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + CHANGES_DB_ID: ${{ secrets.NOTION_CHANGE_LOG_DB_ID }} + EVENT_TYPE: commit + COMMIT_SHA: ${{ github.sha }} + COMMIT_MSG: "🦅 天眼周报 · 系统架构汇总自动同步" + COMMITTER: "天眼 · SkyEye Core" + COMMIT_TIMESTAMP: ${{ github.event.repository.updated_at }} + BRANCH: main + CHANGED_FILES: "README.md\nskyeye/scan-report/" + run: node scripts/notion-bridge.js changes diff --git a/README.md b/README.md index 23b9db26..d6f4636c 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,37 @@ └─ L2 频道层(Channels)─ 11 个开发者自治频道 ── 自己管自己 ``` -频道总数:11 | 活跃频道:8 | GitHub模块:17 | Workflow:67 + +> 🦅 **天眼自动汇总** · 每周六 20:00 CST 自动更新 · 最后更新: 2026-03-24 + +| 维度 | 当前状态 | +|------|----------| +| 🏥 系统健康 | 🟢 全部正常 | +| ⚙️ Workflow 总数 | 79 个 | +| 🤖 Agent 总数 | 62 个(14 个需日签到) | +| 🎭 人格体 | 17 个 | +| 📡 开发者频道 | 11 个(活跃 8) | +| 🛡️ Guard 守卫 | 5 个 | +| 📦 功能模块 | 10 个 | +| 🌍 子仓库联邦 | 6 个模板(签到 1 个) | +| 📜 本体论 | v1.0 · GLM-ONTOLOGY-v1.0 | +| 📮 Buffer 待处理 | 8 条 | + +**基础设施服务:** + +| 服务 | 计划 | 状态 | +|------|------|------| +| GitHub | Free | ✅ | +| Google Drive | Google One / Free 15GB | ✅ | +| Notion | Plus | ✅ | +| Google Gemini | Free / Pro | ✅ | +| GitHub Actions | Free | ✅ | + +**最近一次天眼扫描:** SKYEYE-SCAN-20260323 +- Guard: 5/5 活跃 +- 自愈: 清理 0 文件 · 修复 0 配置 · 重启 0 Guard +- 下次扫描: 2026-03-28 + 📢 [2026-03-22] 分布式主权共生架构落地 · 三层隔离+频道映射+CEP机制 · Notion双端同构 diff --git a/scripts/skyeye/generate-arch-summary.js b/scripts/skyeye/generate-arch-summary.js new file mode 100644 index 00000000..35051747 --- /dev/null +++ b/scripts/skyeye/generate-arch-summary.js @@ -0,0 +1,334 @@ +#!/usr/bin/env node +/** + * scripts/skyeye/generate-arch-summary.js + * 天眼 · 系统架构汇总生成器 + * + * 扫描仓库当前状态,生成 Markdown 格式的系统架构汇总, + * 写入 README.md 的 标记区域。 + * + * 用法: + * node scripts/skyeye/generate-arch-summary.js + * + * 数据来源: + * - .github/workflows/ → Workflow 总数 + * - .github/persona-brain/agent-registry.json → Agent 总数 + * - .github/persona-brain/persona-registry.json → 人格体总数 + * - .github/brain/architecture/channel-map.json → 开发者频道 + * - skyeye/infra-manifest.json → 基础设施服务 + * - skyeye/guards/ → Guard 数量 + * - spoke-deployments/ → 子仓库(联邦) + * - skyeye/scan-report/ → 最新扫描报告 + */ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.resolve(__dirname, '../..'); +const README_PATH = path.join(ROOT, 'README.md'); + +const MARKER_START = ''; +const MARKER_END = ''; + +const BEIJING_OFFSET_MS = 8 * 3600 * 1000; + +function getBeijingTime() { + const now = new Date(); + return new Date(now.getTime() + BEIJING_OFFSET_MS) + .toISOString().replace('T', ' ').slice(0, 16); +} + +function getBeijingDate() { + const now = new Date(); + return new Date(now.getTime() + BEIJING_OFFSET_MS) + .toISOString().slice(0, 10); +} + +function loadJSON(filePath) { + try { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); + } catch (e) { + return null; + } +} + +// ━━━ 数据采集 ━━━ + +function countWorkflows() { + const dir = path.join(ROOT, '.github/workflows'); + try { + return fs.readdirSync(dir).filter(f => f.endsWith('.yml') || f.endsWith('.yaml')).length; + } catch (e) { + return 0; + } +} + +function getAgentStats() { + const registry = loadJSON(path.join(ROOT, '.github/persona-brain/agent-registry.json')); + if (!registry) return { total: 0, checkinRequired: 0 }; + const agents = registry.agents || []; + return { + total: agents.length, + checkinRequired: agents.filter(a => a.daily_checkin_required).length + }; +} + +function getPersonaStats() { + const registry = loadJSON(path.join(ROOT, '.github/persona-brain/persona-registry.json')); + if (!registry) return { total: 0 }; + const personas = registry.personas || []; + return { + total: personas.length, + active: personas.filter(p => p.status === 'active' || !p.status).length + }; +} + +function getChannelStats() { + const channelMap = loadJSON(path.join(ROOT, '.github/brain/architecture/channel-map.json')); + if (!channelMap || !channelMap.channels) return { total: 0, active: 0 }; + const channels = channelMap.channels; + const entries = Object.values(channels); + return { + total: entries.length, + active: entries.filter(c => c.status === 'active').length + }; +} + +function getInfraServices() { + const manifest = loadJSON(path.join(ROOT, 'skyeye/infra-manifest.json')); + if (!manifest || !manifest.infrastructure) return []; + return Object.entries(manifest.infrastructure).map(([key, svc]) => ({ + key, + name: svc.service || key, + plan: svc.plan || '—' + })); +} + +function countGuards() { + const dir = path.join(ROOT, 'skyeye/guards'); + try { + return fs.readdirSync(dir).filter(f => f.endsWith('.json') && f !== 'guard-template.json').length; + } catch (e) { + return 0; + } +} + +function getSpokeDeployments() { + const dir = path.join(ROOT, 'spoke-deployments'); + try { + return fs.readdirSync(dir, { withFileTypes: true }) + .filter(d => d.isDirectory()) + .map(d => d.name); + } catch (e) { + return []; + } +} + +function getFederationStats() { + const registry = loadJSON(path.join(ROOT, '.github/persona-brain/agent-registry.json')); + if (!registry || !registry.federation) return { total: 0, members: [] }; + const fed = registry.federation; + return { + total: Object.keys(fed).length, + members: Object.entries(fed).map(([devId, info]) => ({ + devId, + persona: info.persona || '—', + repo: info.repo || '—' + })) + }; +} + +function getLatestScanReport() { + const dir = path.join(ROOT, 'skyeye/scan-report'); + try { + const files = fs.readdirSync(dir) + .filter(f => f.endsWith('.json')) + .sort() + .reverse(); + if (files.length === 0) return null; + return loadJSON(path.join(dir, files[0])); + } catch (e) { + return null; + } +} + +function countModuleDirs() { + try { + return fs.readdirSync(ROOT, { withFileTypes: true }).filter(d => { + return /^m\d+/.test(d.name) && d.isDirectory(); + }).length; + } catch (e) { + return 0; + } +} + +function getOntologyVersion() { + const onto = loadJSON(path.join(ROOT, '.github/persona-brain/ontology.json')); + if (!onto) return '—'; + return `v${onto.version || '?'} · ${onto.document_id || ''}`; +} + +function getBufferStatus() { + const inboxDir = path.join(ROOT, 'buffer/inbox'); + try { + let count = 0; + const devDirs = fs.readdirSync(inboxDir); + for (const d of devDirs) { + const fullPath = path.join(inboxDir, d); + if (fs.statSync(fullPath).isDirectory()) { + count += fs.readdirSync(fullPath).length; + } + } + return count; + } catch (e) { + return 0; + } +} + +// ━━━ Markdown 生成 ━━━ + +function generateMarkdown() { + const date = getBeijingDate(); + const time = getBeijingTime(); + const workflows = countWorkflows(); + const agentStats = getAgentStats(); + const personaStats = getPersonaStats(); + const channelStats = getChannelStats(); + const infraServices = getInfraServices(); + const guards = countGuards(); + const spokes = getSpokeDeployments(); + const federation = getFederationStats(); + const latestScan = getLatestScanReport(); + const modules = countModuleDirs(); + const ontology = getOntologyVersion(); + const bufferPending = getBufferStatus(); + + // Health indicator from latest scan + let healthIcon = '🟢'; + let healthText = '全部正常'; + if (latestScan) { + const alerts = latestScan.alerts || []; + if (alerts.length > 0) { + healthIcon = '🟡'; + healthText = `${alerts.length} 条告警`; + } + const status = latestScan.infrastructure_status || {}; + if ((status.down || 0) > 0) { + healthIcon = '🔴'; + healthText = `${status.down} 服务宕机`; + } + } + + const lines = []; + lines.push(`> 🦅 **天眼自动汇总** · 每周六 20:00 CST 自动更新 · 最后更新: ${date}`); + lines.push(''); + lines.push(`| 维度 | 当前状态 |`); + lines.push(`|------|----------|`); + lines.push(`| 🏥 系统健康 | ${healthIcon} ${healthText} |`); + lines.push(`| ⚙️ Workflow 总数 | ${workflows} 个 |`); + lines.push(`| 🤖 Agent 总数 | ${agentStats.total} 个(${agentStats.checkinRequired} 个需日签到) |`); + lines.push(`| 🎭 人格体 | ${personaStats.total} 个 |`); + lines.push(`| 📡 开发者频道 | ${channelStats.total} 个(活跃 ${channelStats.active}) |`); + lines.push(`| 🛡️ Guard 守卫 | ${guards} 个 |`); + lines.push(`| 📦 功能模块 | ${modules} 个 |`); + lines.push(`| 🌍 子仓库联邦 | ${spokes.length} 个模板(签到 ${federation.total} 个) |`); + lines.push(`| 📜 本体论 | ${ontology} |`); + lines.push(`| 📮 Buffer 待处理 | ${bufferPending} 条 |`); + lines.push(''); + + // Infrastructure services table + lines.push(`**基础设施服务:**`); + lines.push(''); + lines.push(`| 服务 | 计划 | 状态 |`); + lines.push(`|------|------|------|`); + for (const svc of infraServices) { + lines.push(`| ${svc.name} | ${svc.plan} | ✅ |`); + } + lines.push(''); + + // Scan report highlight + if (latestScan) { + const guardStatus = latestScan.guard_status || {}; + const healActions = latestScan.self_heal_actions || {}; + lines.push(`**最近一次天眼扫描:** ${latestScan.report_id || '—'}`); + lines.push(`- Guard: ${guardStatus.active || 0}/${guardStatus.total_guards || 0} 活跃`); + lines.push(`- 自愈: 清理 ${healActions.files_cleaned || 0} 文件 · 修复 ${healActions.configs_repaired || 0} 配置 · 重启 ${healActions.guards_restarted || 0} Guard`); + const nextScan = latestScan.next_scan ? latestScan.next_scan.slice(0, 10) : '—'; + lines.push(`- 下次扫描: ${nextScan}`); + } + + return lines.join('\n'); +} + +// ━━━ README 更新 ━━━ + +function updateReadme(markdown) { + if (!fs.existsSync(README_PATH)) { + console.error('❌ README.md 不存在'); + return false; + } + + let readme = fs.readFileSync(README_PATH, 'utf8'); + + const startIdx = readme.indexOf(MARKER_START); + const endIdx = readme.indexOf(MARKER_END); + + if (startIdx === -1 || endIdx === -1) { + console.error('❌ README.md 中未找到 ARCH_SUMMARY 标记'); + return false; + } + + const before = readme.slice(0, startIdx + MARKER_START.length); + const after = readme.slice(endIdx); + + readme = before + '\n' + markdown + '\n' + after; + fs.writeFileSync(README_PATH, readme, 'utf8'); + console.log('✅ README.md 架构汇总已更新'); + return true; +} + +// ━━━ JSON 报告输出 ━━━ + +function generateJsonReport() { + return { + generated_at: new Date().toISOString(), + generated_at_beijing: getBeijingTime(), + workflows: countWorkflows(), + agents: getAgentStats(), + personas: getPersonaStats(), + channels: getChannelStats(), + infrastructure: getInfraServices(), + guards: countGuards(), + spoke_deployments: getSpokeDeployments(), + federation: getFederationStats(), + modules: countModuleDirs(), + ontology: getOntologyVersion(), + buffer_pending: getBufferStatus() + }; +} + +// ━━━ 入口 ━━━ + +function main() { + console.log('[天眼 · 架构汇总] 开始生成系统架构汇总...'); + + const markdown = generateMarkdown(); + const updated = updateReadme(markdown); + + // Also output JSON report for Notion bridge consumption + const jsonReport = generateJsonReport(); + const reportDir = path.join(ROOT, 'skyeye/scan-report'); + if (!fs.existsSync(reportDir)) fs.mkdirSync(reportDir, { recursive: true }); + const reportPath = path.join(reportDir, `${getBeijingDate().replace(/-/g, '')}-arch-summary.json`); + fs.writeFileSync(reportPath, JSON.stringify(jsonReport, null, 2) + '\n', 'utf8'); + console.log(`📋 架构汇总 JSON: ${reportPath}`); + + if (updated) { + console.log('[天眼 · 架构汇总] ✅ 完成'); + } else { + console.log('[天眼 · 架构汇总] ⚠️ README 未更新(缺少标记)'); + } +} + +main();