diff --git a/.github/workflows/bridge-broadcast-pdf.yml b/.github/workflows/bridge-broadcast-pdf.yml index e992ad01..d5b5b337 100644 --- a/.github/workflows/bridge-broadcast-pdf.yml +++ b/.github/workflows/bridge-broadcast-pdf.yml @@ -69,7 +69,7 @@ jobs: - name: 📡 检查调度队列 id: check env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} BRIDGE_QUEUE_DB_ID: ${{ secrets.BRIDGE_QUEUE_DB_ID }} run: node scripts/bridge/check-queue.js BROADCAST_READY @@ -77,7 +77,7 @@ jobs: if: steps.check.outputs.task_count != '0' id: fetch env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} QUEUE_FILE: ${{ steps.check.outputs.queue_file }} run: node scripts/bridge/fetch-broadcast.js @@ -116,7 +116,7 @@ jobs: - name: ✅ 更新调度队列状态 if: steps.check.outputs.task_count != '0' env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} QUEUE_FILE: ${{ steps.check.outputs.queue_file }} run: node scripts/bridge/update-queue-status.js diff --git a/.github/workflows/bridge-changes-to-notion.yml b/.github/workflows/bridge-changes-to-notion.yml index 8389e9f4..8873fa42 100644 --- a/.github/workflows/bridge-changes-to-notion.yml +++ b/.github/workflows/bridge-changes-to-notion.yml @@ -41,7 +41,7 @@ jobs: - name: 📡 同步 commit 变更到 Notion if: github.event_name == 'push' env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CHANGES_DB_ID: ${{ secrets.NOTION_CHANGE_LOG_DB_ID }} EVENT_TYPE: commit COMMIT_SHA: ${{ github.sha }} @@ -60,7 +60,7 @@ jobs: - name: 📡 同步 PR 变更到 Notion if: github.event_name == 'pull_request' env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CHANGES_DB_ID: ${{ secrets.NOTION_CHANGE_LOG_DB_ID }} EVENT_TYPE: pr PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/bridge-heartbeat.yml b/.github/workflows/bridge-heartbeat.yml index 43283858..3f97076f 100644 --- a/.github/workflows/bridge-heartbeat.yml +++ b/.github/workflows/bridge-heartbeat.yml @@ -65,7 +65,7 @@ jobs: - name: 💓 执行心跳检测 id: heartbeat env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} BRIDGE_QUEUE_DB_ID: ${{ secrets.BRIDGE_QUEUE_DB_ID }} run: node scripts/bridge/heartbeat.js diff --git a/.github/workflows/bridge-syslog-intake.yml b/.github/workflows/bridge-syslog-intake.yml index b7c15251..15177cda 100644 --- a/.github/workflows/bridge-syslog-intake.yml +++ b/.github/workflows/bridge-syslog-intake.yml @@ -67,7 +67,7 @@ jobs: - name: 📥 批量处理 SYSLOG id: process env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} BRIDGE_QUEUE_DB_ID: ${{ secrets.BRIDGE_QUEUE_DB_ID }} SYSLOG_DB_ID: ${{ secrets.NOTION_SYSLOG_DB_ID }} COMMIT_SHA: ${{ github.sha }} diff --git a/.github/workflows/bridge-syslog-to-notion.yml b/.github/workflows/bridge-syslog-to-notion.yml index afcff547..497b7ad2 100644 --- a/.github/workflows/bridge-syslog-to-notion.yml +++ b/.github/workflows/bridge-syslog-to-notion.yml @@ -38,7 +38,7 @@ jobs: - name: 🔗 同步 syslog-inbox 到 Notion env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} SYSLOG_DB_ID: ${{ secrets.NOTION_SYSLOG_DB_ID }} COMMIT_SHA: ${{ github.sha }} run: node scripts/notion-bridge.js syslog diff --git a/.github/workflows/daily-maintenance.yml b/.github/workflows/daily-maintenance.yml index a487ace4..d3ff8044 100644 --- a/.github/workflows/daily-maintenance.yml +++ b/.github/workflows/daily-maintenance.yml @@ -127,7 +127,7 @@ jobs: - name: 检查 Notion API 连通性 id: notion_check env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | echo "🔍 检查 Notion API 连通性..." if [ -z "$NOTION_TOKEN" ]; then @@ -197,7 +197,7 @@ jobs: # ── Step 6: 向 Notion 回报巡检结果 ── - name: 向 Notion 回报巡检结果 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} SYSLOG_DB_ID: ${{ secrets.SYSLOG_DB_ID }} run: | if [ -z "$NOTION_TOKEN" ] || [ -z "$SYSLOG_DB_ID" ]; then @@ -268,7 +268,7 @@ jobs: - name: Read brain data and sync to Notion env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | if [ -z "$NOTION_TOKEN" ]; then echo "⚠️ NOTION_TOKEN 未配置,跳过 Execution Status 同步" diff --git a/.github/workflows/deploy-to-server.yml b/.github/workflows/deploy-to-server.yml index fc6a16b6..736d9267 100644 --- a/.github/workflows/deploy-to-server.yml +++ b/.github/workflows/deploy-to-server.yml @@ -718,7 +718,7 @@ jobs: - name: 📡 推送部署记录到 Notion env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CHANGES_DB_ID: ${{ secrets.NOTION_CHANGE_LOG_DB_ID }} EVENT_TYPE: commit COMMIT_SHA: ${{ github.sha }} diff --git a/.github/workflows/execution-sync.yml b/.github/workflows/execution-sync.yml index 4baab124..6611108e 100644 --- a/.github/workflows/execution-sync.yml +++ b/.github/workflows/execution-sync.yml @@ -42,7 +42,7 @@ jobs: - name: 同步执行状态到 Notion if: ${{ env.NOTION_TOKEN != '' }} env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} EXECUTION_LOG_DB_ID: ${{ secrets.EXECUTION_LOG_DB_ID }} run: node core/execution-sync sync diff --git a/.github/workflows/grid-db-processor.yml b/.github/workflows/grid-db-processor.yml index def05545..7f534bdb 100644 --- a/.github/workflows/grid-db-processor.yml +++ b/.github/workflows/grid-db-processor.yml @@ -17,7 +17,7 @@ jobs: - name: ⚙️ 处理 inbox 消息 env: - NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_API_TOKEN: ${{ secrets.NOTION_API_KEY }} run: node scripts/grid-db/process-inbox.js - name: 💾 提交处理结果 diff --git a/.github/workflows/meta-watchdog.yml b/.github/workflows/meta-watchdog.yml index f34fd2a7..b3113c04 100644 --- a/.github/workflows/meta-watchdog.yml +++ b/.github/workflows/meta-watchdog.yml @@ -53,10 +53,10 @@ jobs: - name: 写入 Notion 告警(仅在失败时触发) if: failure() env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | if [ -z "$NOTION_TOKEN" ]; then - echo "⚠️ NOTION_API_TOKEN 未配置,跳过 Notion 告警" + echo "⚠️ NOTION_API_KEY 未配置,跳过 Notion 告警" exit 0 fi diff --git a/.github/workflows/neural-daily-digest.yml b/.github/workflows/neural-daily-digest.yml new file mode 100644 index 00000000..74c77fca --- /dev/null +++ b/.github/workflows/neural-daily-digest.yml @@ -0,0 +1,208 @@ +name: "🧬 铸渊 · 双端神经系统 · 每日汇总引擎" + +on: + schedule: + - cron: '0 13 * * *' # UTC 13:00 = CST 21:00 + workflow_dispatch: # 手动触发 + +permissions: + contents: write + actions: read + +jobs: + daily-digest: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + + # ━━━ Phase 1: 唤醒核心大脑 ━━━ + - name: "🧠 唤醒核心大脑" + run: | + echo "🧬 双端神经系统·汇总引擎启动" + echo "时间:$(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M CST')" + for f in memory.json routing-map.json; do + [ -f ".github/persona-brain/$f" ] && echo "✅ $f" || echo "❌ $f 缺失" + done + + # ━━━ Phase 2: 收集全 Workflow 运行数据 ━━━ + - name: "📊 收集 Workflow 运行数据" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "📊 收集最近24h所有Workflow运行数据..." + mkdir -p /tmp/neural-digest + + gh run list --limit 100 \ + --json name,status,conclusion,createdAt,updatedAt,headBranch,event \ + > /tmp/neural-digest/all-runs.json + + node -e " + const runs = require('/tmp/neural-digest/all-runs.json'); + const now = Date.now(); + const h24 = 24*60*60*1000; + const recent = runs.filter(r => now - new Date(r.createdAt).getTime() < h24); + const summary = { + total: recent.length, + success: recent.filter(r => r.conclusion === 'success').length, + failure: recent.filter(r => r.conclusion === 'failure').length, + cancelled: recent.filter(r => r.conclusion === 'cancelled').length, + in_progress: recent.filter(r => r.status === 'in_progress').length, + by_workflow: {} + }; + recent.forEach(r => { + if (!summary.by_workflow[r.name]) { + summary.by_workflow[r.name] = { runs: 0, success: 0, failure: 0 }; + } + summary.by_workflow[r.name].runs++; + if (r.conclusion === 'success') summary.by_workflow[r.name].success++; + if (r.conclusion === 'failure') summary.by_workflow[r.name].failure++; + }); + require('fs').writeFileSync('/tmp/neural-digest/workflow-summary.json', JSON.stringify(summary, null, 2)); + console.log('最近24h运行统计:', JSON.stringify(summary, null, 2)); + " + + # ━━━ Phase 3: 收集各 Workflow 自报告 ━━━ + - name: "📋 收集各 Workflow 自报告" + run: | + echo "📋 读取各 Workflow 的神经报告..." + mkdir -p /tmp/neural-digest/reports + + if [ -f "skyeye/neural-map.json" ]; then + node -e " + const map = require('./skyeye/neural-map.json'); + const fs = require('fs'); + const path = require('path'); + const reports = {}; + for (const [id, wf] of Object.entries(map.github_workflows)) { + const reportDir = wf.report_path; + if (fs.existsSync(reportDir)) { + const files = fs.readdirSync(reportDir) + .filter(f => f.endsWith('.json')) + .sort().reverse(); + if (files.length > 0) { + try { + reports[id] = JSON.parse(fs.readFileSync(path.join(reportDir, files[0]), 'utf8')); + console.log('✅ ' + id + ': 读取 ' + files[0]); + } catch(e) { + reports[id] = { error: 'parse_failed', file: files[0] }; + console.log('❌ ' + id + ': JSON解析失败'); + } + } else { + reports[id] = { error: 'no_reports' }; + console.log('⚠️ ' + id + ': 无报告文件'); + } + } else { + reports[id] = { error: 'dir_not_found' }; + console.log('⚠️ ' + id + ': 报告目录不存在'); + } + } + fs.writeFileSync('/tmp/neural-digest/workflow-reports.json', JSON.stringify(reports, null, 2)); + " + else + echo "⚠️ neural-map.json 不存在,跳过自报告收集" + fi + + # ━━━ Phase 4: 收集天眼 + Guard + 配额 ━━━ + - name: "🦅 收集天眼 + Guard + 配额" + run: | + # 天眼报告 + if [ -d "data/skyeye-reports" ]; then + LATEST=$(ls -t data/skyeye-reports/*.json 2>/dev/null | head -1) + [ -n "$LATEST" ] && cp "$LATEST" /tmp/neural-digest/skyeye-latest.json && echo "✅ 天眼: $LATEST" || echo "⚠️ 无天眼报告" + fi + # Guard 状态 + if [ -d "skyeye/guards" ]; then + node -e " + const fs = require('fs'); const path = require('path'); + const guards = {}; + fs.readdirSync('skyeye/guards') + .filter(f => f.endsWith('.json') && f !== 'guard-template.json') + .forEach(f => { + try { guards[f.replace('.json','')] = JSON.parse(fs.readFileSync(path.join('skyeye/guards', f), 'utf8')); } + catch(e) { guards[f.replace('.json','')] = { error: 'parse_failed' }; } + }); + fs.writeFileSync('/tmp/neural-digest/guard-status.json', JSON.stringify(guards, null, 2)); + " + fi + # 配额 + [ -f "skyeye/quota-ledger.json" ] && cp skyeye/quota-ledger.json /tmp/neural-digest/quota-status.json && echo "✅ 配额" || echo "⚠️ 无配额" + + # ━━━ Phase 5: 生成标准化日报 ━━━ + - name: "📝 生成标准化日报" + run: node scripts/neural/generate-daily-digest.js + + # ━━━ Phase 6: 保存日报到仓库 ━━━ + - name: "💾 保存日报" + run: | + DATE=$(TZ=Asia/Shanghai date +%Y-%m-%d) + mkdir -p data/neural-reports/daily-digest + cp /tmp/neural-digest/daily-digest.json \ + "data/neural-reports/daily-digest/digest-${DATE}.json" + git config user.name "zhuyuan-bot" + git config user.email "zhuyuan@guanghulab.com" + git add data/neural-reports/ + git diff --cached --quiet || \ + git commit -m "🧬 双端日报 · ${DATE} [skip ci]" + git push || echo "⚠️ push失败(不阻断)" + + # ━━━ Phase 7: 推送到 Notion ━━━ + - name: "📡 推送日报到 Notion" + if: always() + env: + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} + run: | + node scripts/neural/sync-digest-to-notion.js || \ + echo "⚠️ Notion推送失败(不阻断)" + + # ━━━ Phase 8: 自动分析日报 + 生成工单 ━━━ + - name: "🧬 分析日报 · 生成工单" + if: always() + run: | + echo "🧬 自动分析日报..." + node scripts/neural/analyze-digest.js + if [ -d "data/neural-reports/work-orders" ]; then + git add data/neural-reports/work-orders/ + git diff --cached --quiet || \ + git commit -m "🧬 天眼工单 · $(TZ=Asia/Shanghai date +%Y-%m-%d) [skip ci]" + git push || echo "⚠️ 工单push失败" + fi + + # ━━━ 🧬 双端神经系统·自报告 ━━━ + - name: "🧬 写入神经自报告" + if: always() + run: | + WORKFLOW_ID="neural-daily-digest" + BRAIN="AG-TY-01" + REPORT_DIR="data/neural-reports/daily-digest" + 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失败(不阻断主流程)" diff --git a/.github/workflows/notion-callback-pipeline.yml b/.github/workflows/notion-callback-pipeline.yml index cebb150d..8a1b693f 100644 --- a/.github/workflows/notion-callback-pipeline.yml +++ b/.github/workflows/notion-callback-pipeline.yml @@ -107,7 +107,7 @@ jobs: AUTHOR: notion-callback MODULE_VERIFY_RESULT: ${{ steps.verify.outputs.verify_report }} NOTION_CALLBACK_RESULT: ${{ steps.callback.outputs.notion_result }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CORE_BRAIN_PAGE_ID: ${{ secrets.CORE_BRAIN_PAGE_ID }} PORTRAIT_DB_ID: ${{ secrets.PORTRAIT_DB_ID }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} @@ -125,7 +125,7 @@ jobs: - name: 📝 回写 Notion 工单状态 if: steps.callback.outputs.ticket_id env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} TICKET_ID: ${{ steps.callback.outputs.ticket_id }} CALLBACK_STATUS: ${{ steps.callback.outputs.status }} run: | diff --git a/.github/workflows/notion-connectivity-test.yml b/.github/workflows/notion-connectivity-test.yml index 5f1824bd..083b85ad 100644 --- a/.github/workflows/notion-connectivity-test.yml +++ b/.github/workflows/notion-connectivity-test.yml @@ -41,7 +41,7 @@ jobs: - name: 🧪 执行连通性测试 id: test env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} SIGNAL_LOG_DB_ID: ${{ vars.SIGNAL_LOG_DB_ID }} CHANGES_DB_ID: ${{ secrets.NOTION_CHANGE_LOG_DB_ID }} SYSLOG_DB_ID: ${{ secrets.NOTION_SYSLOG_DB_ID }} diff --git a/.github/workflows/notion-heartbeat.yml b/.github/workflows/notion-heartbeat.yml index 78940060..8d22e2c3 100644 --- a/.github/workflows/notion-heartbeat.yml +++ b/.github/workflows/notion-heartbeat.yml @@ -42,7 +42,7 @@ jobs: - name: 💓 执行心跳检测 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SMTP_USER: ${{ secrets.SMTP_USER }} diff --git a/.github/workflows/notion-page-reader.yml b/.github/workflows/notion-page-reader.yml index 5bf94dfc..dce317a8 100644 --- a/.github/workflows/notion-page-reader.yml +++ b/.github/workflows/notion-page-reader.yml @@ -45,7 +45,7 @@ jobs: - name: 📖 读取 Notion 页面内容 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_PAGE_URL: ${{ github.event.client_payload.notion_page_url || github.event.inputs.notion_page_url }} NOTION_OUTPUT_DIR: ${{ (github.event.client_payload.save_to_repo == 'true' || github.event.inputs.save_to_repo == 'true') && 'data/notion-pages' || '' }} run: node scripts/notion-page-reader.js diff --git a/.github/workflows/notion-poll.yml b/.github/workflows/notion-poll.yml index c0b18101..24347a27 100644 --- a/.github/workflows/notion-poll.yml +++ b/.github/workflows/notion-poll.yml @@ -27,7 +27,7 @@ jobs: - name: 轮询工单簿 + 处理 + 回写 id: poll env: - NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_API_TOKEN: ${{ secrets.NOTION_API_KEY }} WORKORDER_DB_ID: ${{ vars.WORKORDER_DB_ID }} SIGNAL_LOG_DB_ID: ${{ vars.SIGNAL_LOG_DB_ID }} run: node scripts/notion-signal-bridge.js poll diff --git a/.github/workflows/notion-wake-listener.yml b/.github/workflows/notion-wake-listener.yml index f1256bae..b1536278 100644 --- a/.github/workflows/notion-wake-listener.yml +++ b/.github/workflows/notion-wake-listener.yml @@ -85,7 +85,7 @@ jobs: - name: 📡 轮询 Notion 唤醒请求数据库 id: poll env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} WAKE_REQUEST_DB_ID: ${{ secrets.WAKE_REQUEST_DB_ID }} SIGNAL_LOG_DB_ID: ${{ secrets.SIGNAL_LOG_DB_ID }} LLM_API_KEY: ${{ secrets.LLM_API_KEY }} diff --git a/.github/workflows/openclaw-wake-loop.yml b/.github/workflows/openclaw-wake-loop.yml index 5d499832..77a47ec0 100644 --- a/.github/workflows/openclaw-wake-loop.yml +++ b/.github/workflows/openclaw-wake-loop.yml @@ -103,7 +103,7 @@ jobs: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | DRY_RUN_FLAG="" if [ "${{ inputs.dry_run }}" = "true" ]; then diff --git a/.github/workflows/persona-invoke.yml b/.github/workflows/persona-invoke.yml index 34f59838..45324403 100644 --- a/.github/workflows/persona-invoke.yml +++ b/.github/workflows/persona-invoke.yml @@ -89,7 +89,7 @@ jobs: SUBMIT_CONTENT: ${{ inputs.syslog_raw }} AUTHOR: ${{ inputs.developer }} MODULE_VERIFY_RESULT: ${{ steps.verify.outputs.verify_report }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CORE_BRAIN_PAGE_ID: ${{ secrets.CORE_BRAIN_PAGE_ID }} PORTRAIT_DB_ID: ${{ secrets.PORTRAIT_DB_ID }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} @@ -98,7 +98,7 @@ jobs: - name: 📝 回写 Notion 工单 if: always() env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} WORK_ORDER_ID: ${{ inputs.work_order_id }} PERSONA_RESULT: ${{ steps.persona.outputs.result }} TASK_ID: ${{ inputs.task_id }} @@ -210,7 +210,7 @@ jobs: - name: 🔴 失败处理 if: failure() env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} WORK_ORDER_ID: ${{ inputs.work_order_id }} run: | node -e " diff --git a/.github/workflows/pm2-server-diagnose.yml b/.github/workflows/pm2-server-diagnose.yml index f3629320..8a4aff9e 100644 --- a/.github/workflows/pm2-server-diagnose.yml +++ b/.github/workflows/pm2-server-diagnose.yml @@ -299,7 +299,7 @@ jobs: # ━━━ 阶段三:生成 Notion 诊断报告 ━━━ - name: "📋 阶段三 · 写入 Notion 工单" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID || '84edd0640bf146a9a5a7840107013e8c' }} PM2_REPORT: ${{ steps.pm2_diagnose.outputs.pm2_report }} CLEANUP_REPORT: ${{ steps.pm2_cleanup.outputs.cleanup_report }} diff --git a/.github/workflows/push-broadcast.yml b/.github/workflows/push-broadcast.yml index d5e45f13..2532e532 100644 --- a/.github/workflows/push-broadcast.yml +++ b/.github/workflows/push-broadcast.yml @@ -43,7 +43,7 @@ jobs: - name: 📡 推送广播 → 飞书文档B env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} BROADCAST_PAGE_ID: ${{ github.event.client_payload.broadcast_page_id || github.event.inputs.broadcast_page_id }} FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }} FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }} diff --git a/.github/workflows/receive-syslog.yml b/.github/workflows/receive-syslog.yml index d69b7ff2..d067b784 100644 --- a/.github/workflows/receive-syslog.yml +++ b/.github/workflows/receive-syslog.yml @@ -38,7 +38,7 @@ jobs: - name: 📥 处理 SYSLOG env: SYSLOG_JSON: ${{ toJSON(github.event.client_payload.syslog) }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_SYSLOG_DB_ID: ${{ secrets.NOTION_SYSLOG_DB_ID }} NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID }} run: node scripts/receive-syslog.js diff --git a/.github/workflows/sandbox-deploy.yml b/.github/workflows/sandbox-deploy.yml index 31da064f..f3a2396b 100644 --- a/.github/workflows/sandbox-deploy.yml +++ b/.github/workflows/sandbox-deploy.yml @@ -232,7 +232,7 @@ jobs: - name: "📝 同步到 Notion 部署注册表" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} DEV_ID: ${{ needs.parse-and-validate.outputs.dev_id }} MODULE: ${{ needs.parse-and-validate.outputs.module }} diff --git a/.github/workflows/server-patrol.yml b/.github/workflows/server-patrol.yml index 931a4b6b..c58a43a8 100644 --- a/.github/workflows/server-patrol.yml +++ b/.github/workflows/server-patrol.yml @@ -67,7 +67,7 @@ jobs: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} SMTP_USER: ${{ secrets.SMTP_USER }} - name: "🔑 配置 SSH" @@ -167,7 +167,7 @@ jobs: - name: "📝 同步巡检结果到Notion" if: always() env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID }} run: | node scripts/sync-patrol-to-notion.js || echo "⚠️ Notion同步失败(不阻断)" diff --git a/.github/workflows/skyeye-weekly-hibernation.yml b/.github/workflows/skyeye-weekly-hibernation.yml index 0b906fbf..b74f86b2 100644 --- a/.github/workflows/skyeye-weekly-hibernation.yml +++ b/.github/workflows/skyeye-weekly-hibernation.yml @@ -158,13 +158,13 @@ jobs: - name: "📥 Phase B · Notion 端级联升级" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | node skyeye/hibernation/weekly-hibernation.js --phase=B - name: "✅ Dual Verification" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | node skyeye/hibernation/weekly-hibernation.js --phase=verify diff --git a/.github/workflows/skyeye-weekly-scan.yml b/.github/workflows/skyeye-weekly-scan.yml index ded42a5c..a5b4e427 100644 --- a/.github/workflows/skyeye-weekly-scan.yml +++ b/.github/workflows/skyeye-weekly-scan.yml @@ -55,7 +55,7 @@ jobs: - name: "📡 Sync arch summary to Notion via Bridge E" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CHANGES_DB_ID: ${{ secrets.NOTION_CHANGE_LOG_DB_ID }} EVENT_TYPE: commit COMMIT_SHA: ${{ github.sha }} diff --git a/.github/workflows/sync-deploy-to-notion.yml b/.github/workflows/sync-deploy-to-notion.yml index 80f1930b..1ee11deb 100644 --- a/.github/workflows/sync-deploy-to-notion.yml +++ b/.github/workflows/sync-deploy-to-notion.yml @@ -29,13 +29,13 @@ jobs: if [ -z "$FINGERPRINT_DB_ID" ]; then echo "⚠️ 缺失: FINGERPRINT_DB_ID"; else echo "✅ 可用: FINGERPRINT_DB_ID"; fi if [ -z "$SMTP_USER" ]; then echo "⚠️ 缺失: SMTP_USER"; else echo "✅ 可用: SMTP_USER"; fi env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} SMTP_USER: ${{ secrets.SMTP_USER }} - name: "📝 同步部署状态到 Notion" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} run: | node scripts/sync-deploy-to-notion.js diff --git a/.github/workflows/sync-griddb-to-notion.yml b/.github/workflows/sync-griddb-to-notion.yml index 1e209c74..d35742cd 100644 --- a/.github/workflows/sync-griddb-to-notion.yml +++ b/.github/workflows/sync-griddb-to-notion.yml @@ -29,5 +29,5 @@ jobs: - name: 📤 回传增量到 Notion if: steps.changes.outputs.files != '' env: - NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_API_TOKEN: ${{ secrets.NOTION_API_KEY }} run: node scripts/grid-db/sync-griddb-to-notion.js diff --git a/.github/workflows/sync-login-entry.yml b/.github/workflows/sync-login-entry.yml index e1fcc2f4..b2f5f785 100644 --- a/.github/workflows/sync-login-entry.yml +++ b/.github/workflows/sync-login-entry.yml @@ -37,7 +37,7 @@ jobs: - name: 🔗 同步 Notion 登录入口 → 飞书文档A env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_LOGIN_PAGE_ID: ${{ secrets.NOTION_LOGIN_PAGE_ID }} FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }} FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }} diff --git a/.github/workflows/sync-notion-to-griddb.yml b/.github/workflows/sync-notion-to-griddb.yml index aba951d1..3730bf66 100644 --- a/.github/workflows/sync-notion-to-griddb.yml +++ b/.github/workflows/sync-notion-to-griddb.yml @@ -16,12 +16,12 @@ jobs: - name: 📥 从 Notion 拉取人格体核心大脑数据 env: - NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_API_TOKEN: ${{ secrets.NOTION_API_KEY }} run: node scripts/grid-db/sync-notion-brain-mirror.js - name: 📏 同步规则缓存 env: - NOTION_API_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_API_TOKEN: ${{ secrets.NOTION_API_KEY }} run: node scripts/grid-db/sync-notion-rules.js - name: 💾 提交更新 diff --git a/.github/workflows/syslog-auto-pipeline.yml b/.github/workflows/syslog-auto-pipeline.yml index 2352267d..f9734e6c 100644 --- a/.github/workflows/syslog-auto-pipeline.yml +++ b/.github/workflows/syslog-auto-pipeline.yml @@ -128,7 +128,7 @@ jobs: SUBMIT_CONTENT: ${{ steps.parse.outputs.content }} AUTHOR: ${{ steps.parse.outputs.author }} MODULE_VERIFY_RESULT: ${{ steps.verify.outputs.verify_report }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CORE_BRAIN_PAGE_ID: ${{ secrets.CORE_BRAIN_PAGE_ID }} PORTRAIT_DB_ID: ${{ secrets.PORTRAIT_DB_ID }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} @@ -137,7 +137,7 @@ jobs: - name: 📋 创建标准化 Notion 工单(Phase B1) id: ticket env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} SUBMIT_TYPE: ${{ steps.parse.outputs.type }} @@ -148,7 +148,7 @@ jobs: SYSLOG_RAW: ${{ steps.parse.outputs.content }} run: | if [ -z "$NOTION_TOKEN" ]; then - echo "⚠️ NOTION_API_TOKEN 未配置,跳过 Notion 工单创建" + echo "⚠️ NOTION_API_KEY 未配置,跳过 Notion 工单创建" exit 0 fi node scripts/create-standardized-ticket.js diff --git a/.github/workflows/syslog-issue-pipeline.yml b/.github/workflows/syslog-issue-pipeline.yml index a2c310a7..e49ed8ec 100644 --- a/.github/workflows/syslog-issue-pipeline.yml +++ b/.github/workflows/syslog-issue-pipeline.yml @@ -181,7 +181,7 @@ jobs: SUBMIT_CONTENT: ${{ steps.parse.outputs.content }} AUTHOR: ${{ steps.parse.outputs.author }} MODULE_VERIFY_RESULT: ${{ steps.verify.outputs.verify_report }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CORE_BRAIN_PAGE_ID: ${{ secrets.CORE_BRAIN_PAGE_ID }} PORTRAIT_DB_ID: ${{ secrets.PORTRAIT_DB_ID }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} @@ -209,13 +209,13 @@ jobs: STEP_DETAIL: 'API 调用失败,请检查 Secrets: LLM_API_KEY / LLM_BASE_URL 是否配置正确' run: node scripts/pipeline-reporter.js - # ✅ 修复点:原来是 if: $ secrets.NOTION_API_TOKEN ,会报 Unrecognized named-value: 'secrets' + # ✅ 修复点:原来是 if: $ secrets.NOTION_API_KEY ,会报 Unrecognized named-value: 'secrets' # secrets 不能在 if: 里直接用,必须改成 != '' 的形式 - name: 📋 创建标准化 Notion 工单(Phase B1) id: ticket - if: ${{ secrets.NOTION_API_TOKEN != '' }} + if: ${{ secrets.NOTION_API_KEY != '' }} env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID }} BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} SUBMIT_TYPE: ${{ steps.parse.outputs.type }} diff --git a/.github/workflows/syslog-pipeline.yml b/.github/workflows/syslog-pipeline.yml index ca316f3a..b24ee630 100644 --- a/.github/workflows/syslog-pipeline.yml +++ b/.github/workflows/syslog-pipeline.yml @@ -78,7 +78,7 @@ jobs: - name: 📝 写入 Notion SYSLOG 收件箱 if: steps.parse.outputs.has_syslog == 'true' env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_DB_SYSLOG: ${{ secrets.NOTION_DB_SYSLOG }} run: node scripts/write-notion-syslog.js "${{ steps.parse.outputs.syslog_file }}" @@ -130,7 +130,7 @@ jobs: env: LLM_API_KEY: ${{ secrets.LLM_API_KEY }} LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} CORE_BRAIN_PAGE_ID: ${{ secrets.CORE_BRAIN_PAGE_ID }} PORTRAIT_DB_ID: ${{ secrets.PORTRAIT_DB_ID }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} diff --git a/.github/workflows/test-notion-bridge.yml b/.github/workflows/test-notion-bridge.yml index 44578505..e028d341 100644 --- a/.github/workflows/test-notion-bridge.yml +++ b/.github/workflows/test-notion-bridge.yml @@ -28,7 +28,7 @@ jobs: - name: "Step 1 · NOTION_TOKEN 存在性验证" id: step1 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | if [ -z "$NOTION_TOKEN" ]; then echo "❌ NOTION_TOKEN is empty or not set" @@ -42,7 +42,7 @@ jobs: - name: "Step 2 · Notion API 基础连通测试 (/v1/users/me)" id: step2 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | RESPONSE=$(curl -s -w "\n%{http_code}" \ -H "Authorization: Bearer $NOTION_TOKEN" \ @@ -70,7 +70,7 @@ jobs: - name: "Step 3 · SYSLOG 收件箱数据库访问测试" id: step3 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | # SYSLOG收件箱数据库ID (from routing-map.json → infra.notion_bridge.syslog_inbox_db) DB_ID="330ab17507d542c9bbb96d0749b41197" @@ -104,7 +104,7 @@ jobs: - name: "Step 4 · 变更日志数据库访问测试" id: step4 env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: | # GitHub变更日志数据库ID (from routing-map.json → infra.notion_bridge.changelog_db) DB_ID="e740b77aa6bd4ac0a2e8a75f678fba98" @@ -189,7 +189,7 @@ jobs: fi fi env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} - name: "📊 输出连通性验证报告" if: always() diff --git a/.github/workflows/zhuyuan-commander.yml b/.github/workflows/zhuyuan-commander.yml index 57e8f6dd..afeb12d1 100644 --- a/.github/workflows/zhuyuan-commander.yml +++ b/.github/workflows/zhuyuan-commander.yml @@ -69,7 +69,7 @@ jobs: # Step 3 · 读取公告板 + 指纹验证 - name: "📡 Step 3 · 读取公告板" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} AGENT_BULLETIN_BOARD_PAGE_ID: ${{ secrets.AGENT_BULLETIN_BOARD_PAGE_ID }} run: | echo "[GH-COMMANDER-BULLETIN] 📡 读取Agent集群公告板..." diff --git a/.github/workflows/zhuyuan-daily-selfcheck.yml b/.github/workflows/zhuyuan-daily-selfcheck.yml index 05abda67..e06f2eb7 100644 --- a/.github/workflows/zhuyuan-daily-selfcheck.yml +++ b/.github/workflows/zhuyuan-daily-selfcheck.yml @@ -82,7 +82,7 @@ jobs: - name: DC-01 Notion Usage Snapshot env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} run: node scripts/dc-notion-usage.js - name: DC-02 Workflow Performance Snapshot diff --git a/.github/workflows/zhuyuan-skyeye.yml b/.github/workflows/zhuyuan-skyeye.yml index 8d2fe1be..4edd83c9 100644 --- a/.github/workflows/zhuyuan-skyeye.yml +++ b/.github/workflows/zhuyuan-skyeye.yml @@ -55,7 +55,7 @@ jobs: - name: "📡 Phase 1.6 · 拉取 Agent 集群公告板" env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} AGENT_BULLETIN_BOARD_PAGE_ID: ${{ secrets.AGENT_BULLETIN_BOARD_PAGE_ID }} run: | echo "[BRIDGE-BULLETIN-READ] 🔄 拉取 Agent 集群公告板" @@ -65,7 +65,7 @@ jobs: - name: "🦅 Phase 2 · 全局扫描" id: scan env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} @@ -107,7 +107,7 @@ jobs: - name: "🔧 Phase 4 · 修复Agent" if: steps.diagnose.outputs.auto_fixable != '0' env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | node scripts/skyeye/repair-agent.js @@ -184,7 +184,7 @@ jobs: - name: "📡 Phase 7 · 同步到 Notion" if: always() env: - NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }} NOTION_SYSLOG_DB_ID: ${{ secrets.NOTION_SYSLOG_DB_ID }} SKYEYE_PERSONA_DB_ID: ${{ secrets.SKYEYE_PERSONA_DB_ID }} run: | diff --git a/docs/neural-bridge-protocol-v3.md b/docs/neural-bridge-protocol-v3.md new file mode 100644 index 00000000..e0df121e --- /dev/null +++ b/docs/neural-bridge-protocol-v3.md @@ -0,0 +1,147 @@ +# 🌉 双端神经系统 · 桥接协议 v3.0 + +> 版权:国作登字-2026-A-00037559 · TCS-0002∞ 冰朔 +> 创建:ZY-NEURAL-UPGRADE-2026-0325-R2-003 +> 版本:v3.0.0 + +## 1. 协议概述 + +桥接协议 v3.0 是 Notion 和 GitHub 之间的标准通信语言。所有跨端通信必须遵循此协议。 + +## 2. 通信类型 + +| 类型 | 方向 | 说明 | 格式 | +|------|------|------|------| +| Type A · 上行日报 | GitHub → Notion | 每日 21:00 CST 汇总 | `daily-digest.json` | +| Type B · 下行指令 | Notion → GitHub | 按需下发 | `CMD-{date}-{seq}.json` | +| Type C · 执行回执 | GitHub → Notion | 每条指令执行后 | `CMD-{id}-receipt.json` | +| Type D · 工单 | 天眼内部 | 分析后按需 | `WO-{id}.json` | +| Type E · 紧急通知 | 双向 | P0 事件时 | `ALERT-{id}.json` | + +## 3. 下行指令格式(Notion → GitHub) + +文件路径:`data/deploy-queue/pending/CMD-{YYYYMMDD}-{SEQ}.json` + +```json +{ + "_protocol": "neural-bridge-v3.0", + "_type": "downstream_command", + "command_id": "CMD-20260325-001", + "parent_work_order": "WO-xxxx", + "source": { + "agent_id": "AG-TY-01", + "agent_name": "天眼 Notion 大脑", + "issued_at": "ISO-8601", + "issued_reason": "说明" + }, + "target": { + "workflow_id": "workflow-id", + "workflow_file": ".github/workflows/xxx.yml", + "brain": "AG-XX-01" + }, + "instruction": { + "type": "trigger_workflow | run_script | modify_config", + "params": {} + }, + "constraints": { + "priority": "P0 | P1 | P2", + "timeout_hours": 24, + "max_retries": 2, + "requires_human_approval": false, + "execution_window": { "start": "06:00 CST", "end": "23:00 CST" } + }, + "expected_outcome": { + "description": "预期结果", + "verification": { "type": "check_workflow_status", "expected_conclusion": "success" } + }, + "security": { + "sfp": "⌜SFP::...⌝", + "signature_chain": ["agent_id", "铸渊桥接层"] + } +} +``` + +## 4. 执行回执格式(GitHub → Notion) + +文件路径:`data/deploy-queue/completed/CMD-{id}-receipt.json` + +```json +{ + "_protocol": "neural-bridge-v3.0", + "_type": "execution_receipt", + "receipt_id": "RCT-{date}-{seq}", + "command_id": "CMD-对应指令ID", + "executor": { + "id": "ICE-GL-ZY001", + "name": "铸渊", + "started_at": "ISO-8601", + "completed_at": "ISO-8601", + "duration_seconds": 420 + }, + "result": { + "status": "success | failure | partial", + "summary": "执行摘要" + }, + "security": { "sfp": "⌜SFP::AG-ZY::...⌝" } +} +``` + +## 5. 紧急通知格式 + +```json +{ + "_protocol": "neural-bridge-v3.0", + "_type": "emergency_alert", + "alert_id": "ALERT-{date}-{seq}", + "severity": "P0", + "alert": { "title": "标题", "description": "描述", "impact": "影响" }, + "recommended_action": { "immediate": "立即动作", "requires_human": true }, + "notify_targets": [{ "type": "notion_agent", "id": "AG-TY-01" }] +} +``` + +## 6. 安全校验流程 + +所有跨端通信必须携带 SFP 指纹。铸渊处理下行指令时执行: + +1. **SFP 指纹校验** — 格式正确 + 签发者在 neural-map.json 中 + 时间戳 < 48h +2. **权限校验** — source.agent_id 有权管辖 target.workflow_id(查 neural-map.json) +3. **约束校验** — 当前时间在 execution_window 内 + 人工审批检查 +4. **全部通过** → 执行 + +## 7. 超时 / 重试 / 降级策略 + +| 场景 | 超时 | 重试 | 降级 | +|------|------|------|------| +| 下行指令执行 | 按 timeout_hours | max_retries 次 | 移到 failed/ + 通知 | +| 上行日报推送 | 5 分钟 | 3 次 | 写入 .github/notion-cache/ | +| 紧急通知送达 | 2 分钟 | 5 次 | 缓存 + 下次巡检补送 | +| 工单下发 | 12 小时 | 2 次 | 标记 stuck + 通知霜砚 | +| 回执推送 | 5 分钟 | 3 次 | 缓存 + 下次同步补送 | + +**降级铁律**:任何跨端通信失败都不能阻断本端的正常运行。桥断了,两端各自活着。桥修好了,自动同步。 + +## 8. 工单生命周期(7 状态机) + +``` +CREATED → ASSIGNED → COMMAND_ISSUED → EXECUTING → RECEIPT_RECEIVED → VERIFIED → CLOSED + ↘ FAILED → ESCALATED +``` + +## 9. 文件目录 + +| 路径 | 说明 | +|------|------| +| `skyeye/neural-map.json` | 双端 Agent 映射表 | +| `skyeye/neural-analysis-rules.json` | 日报分析规则 | +| `data/deploy-queue/pending/` | 待执行的下行指令 | +| `data/deploy-queue/executing/` | 执行中的指令 | +| `data/deploy-queue/completed/` | 已完成(含回执) | +| `data/deploy-queue/failed/` | 执行失败 | +| `data/neural-reports/daily-digest/` | 每日汇总日报 | +| `data/neural-reports/work-orders/` | 天眼工单 | +| `scripts/neural/generate-daily-digest.js` | 日报生成器 | +| `scripts/neural/analyze-digest.js` | 日报分析引擎 | +| `scripts/neural/sync-digest-to-notion.js` | 日报推送 Notion | +| `scripts/neural/convert-workorder-to-command.js` | 工单→指令转化器 | +| `scripts/neural/track-work-orders.js` | 工单追踪器 | diff --git a/scripts/neural/convert-workorder-to-command.js b/scripts/neural/convert-workorder-to-command.js new file mode 100644 index 00000000..b561bc95 --- /dev/null +++ b/scripts/neural/convert-workorder-to-command.js @@ -0,0 +1,146 @@ +// scripts/neural/convert-workorder-to-command.js +// 🧬 工单→下行指令 转化器 +// Notion Agent 调用此脚本,将工单转化为铸渊可执行的下行指令 +// 输入:工单 JSON 文件路径 +// 输出:下行指令 JSON(写入 deploy-queue/pending/) + +const fs = require('fs'); +const path = require('path'); + +const DEPLOY_QUEUE = 'data/deploy-queue/pending'; +const NEURAL_MAP_PATH = 'skyeye/neural-map.json'; + +function loadJSON(p) { + try { return JSON.parse(fs.readFileSync(p, 'utf8')); } + catch (e) { return null; } +} + +function generateCommandId() { + var now = new Date(); + var cst = new Date(now.getTime() + 8 * 60 * 60 * 1000); + var date = cst.toISOString().split('T')[0].replace(/-/g, ''); + var seq = Math.random().toString(36).substr(2, 4).toUpperCase(); + return 'CMD-' + date + '-' + seq; +} + +function convertWorkOrderToCommand(workOrder) { + var neuralMap = loadJSON(NEURAL_MAP_PATH); + if (!neuralMap) throw new Error('neural-map.json 不存在'); + + var commandId = generateCommandId(); + var now = new Date().toISOString(); + + // 确定目标 Workflow + var targetWorkflowId = (workOrder.affected && workOrder.affected.workflows) + ? workOrder.affected.workflows[0] : null; + var targetWorkflow = targetWorkflowId + ? neuralMap.github_workflows[targetWorkflowId] : null; + + // 确定指令类型 + var instructionType = 'trigger_workflow'; + var instructionParams = {}; + + var action = (workOrder.source && workOrder.source.rule_triggered) || ''; + if (action.indexOf('cleanup') !== -1 || action.indexOf('clean') !== -1) { + instructionType = 'run_script'; + instructionParams = { + script: 'scripts/neural/cleanup-old-reports.js', + args: { max_age_days: 7 } + }; + } else if (action.indexOf('guard_restart') !== -1 || action.indexOf('quota') !== -1) { + instructionType = 'modify_config'; + instructionParams = { + target_file: (workOrder.affected && workOrder.affected.guards && workOrder.affected.guards[0]) + ? 'skyeye/guards/' + workOrder.affected.guards[0] + '.json' + : null, + modifications: { status: 'active', mode: 'normal' } + }; + } else { + instructionType = 'trigger_workflow'; + instructionParams = { + event: 'workflow_dispatch', + inputs: { + reason: '工单 ' + workOrder.work_order_id + ' 自动触发', + source_work_order: workOrder.work_order_id + } + }; + } + + var assignedTo = (workOrder.assignment && workOrder.assignment.assigned_to) || 'AG-TY-01'; + var assignedToName = (workOrder.assignment && workOrder.assignment.assigned_to_name) || '天眼 Notion 大脑'; + + var command = { + _protocol: 'neural-bridge-v3.0', + _type: 'downstream_command', + command_id: commandId, + parent_work_order: workOrder.work_order_id, + source: { + agent_id: assignedTo, + agent_name: assignedToName, + issued_at: now, + issued_reason: workOrder.title + }, + target: { + workflow_id: targetWorkflowId || 'unknown', + workflow_file: targetWorkflow ? targetWorkflow.file : 'unknown', + brain: targetWorkflow ? targetWorkflow.brain : assignedTo + }, + instruction: { + type: instructionType, + params: instructionParams + }, + constraints: { + priority: workOrder.severity, + timeout_hours: (workOrder.constraints && workOrder.constraints.timeout_hours) || 24, + max_retries: (workOrder.constraints && workOrder.constraints.max_retries) || 2, + requires_human_approval: workOrder.severity === 'P0', + execution_window: { + start: '06:00 CST', + end: '23:00 CST' + } + }, + expected_outcome: { + description: '解决工单 ' + workOrder.work_order_id + ': ' + workOrder.title, + verification: { + type: 'check_workflow_status', + workflow: targetWorkflowId, + expected_conclusion: 'success' + } + }, + security: { + sfp: '⌜SFP::' + assignedTo + '::NeuralBridge::' + commandId + '::' + now + '⌝', + signature_chain: [assignedTo, '铸渊桥接层'] + } + }; + + // 写入 deploy-queue + fs.mkdirSync(DEPLOY_QUEUE, { recursive: true }); + fs.writeFileSync( + path.join(DEPLOY_QUEUE, commandId + '.json'), + JSON.stringify(command, null, 2) + ); + + console.log('✅ 工单 ' + workOrder.work_order_id + ' → 指令 ' + commandId); + console.log(' 类型: ' + instructionType); + console.log(' 目标: ' + (targetWorkflowId || '(待确定)')); + console.log(' 优先级: ' + workOrder.severity); + + return command; +} + +// CLI 入口 +if (require.main === module) { + var woPath = process.argv[2]; + if (!woPath) { + console.error('用法: node convert-workorder-to-command.js '); + process.exit(1); + } + var wo = loadJSON(woPath); + if (!wo) { + console.error('❌ 无法读取工单文件: ' + woPath); + process.exit(1); + } + convertWorkOrderToCommand(wo); +} + +module.exports = { convertWorkOrderToCommand }; diff --git a/scripts/neural/track-work-orders.js b/scripts/neural/track-work-orders.js new file mode 100644 index 00000000..efb71aa2 --- /dev/null +++ b/scripts/neural/track-work-orders.js @@ -0,0 +1,159 @@ +// scripts/neural/track-work-orders.js +// 🧬 工单追踪器 +// 铸渊每次唤醒时运行,追踪所有活跃工单状态 +// 检查超时、匹配回执、更新状态、生成追踪报告 + +const fs = require('fs'); +const path = require('path'); + +const WORK_ORDER_DIR = 'data/neural-reports/work-orders'; +const COMPLETED_DIR = 'data/deploy-queue/completed'; +const TRACKER_DIR = 'data/neural-reports/work-orders'; + +function loadJSON(p) { + try { return JSON.parse(fs.readFileSync(p, 'utf8')); } + catch (e) { return null; } +} + +function getActiveWorkOrders() { + if (!fs.existsSync(WORK_ORDER_DIR)) return []; + + var allOrders = []; + var files = fs.readdirSync(WORK_ORDER_DIR) + .filter(function(f) { return f.startsWith('work-orders-') && f.endsWith('.json'); }); + + for (var i = 0; i < files.length; i++) { + var data = loadJSON(path.join(WORK_ORDER_DIR, files[i])); + if (data && data.work_orders) { + for (var j = 0; j < data.work_orders.length; j++) { + allOrders.push(data.work_orders[j]); + } + } + } + + return allOrders.filter(function(wo) { + return wo.status !== 'CLOSED' && wo.status !== 'ESCALATED' && wo.status !== 'VERIFIED'; + }); +} + +function getCompletedReceipts() { + if (!fs.existsSync(COMPLETED_DIR)) return {}; + + var receipts = {}; + var files = fs.readdirSync(COMPLETED_DIR) + .filter(function(f) { return f.endsWith('.json'); }); + + for (var i = 0; i < files.length; i++) { + var receipt = loadJSON(path.join(COMPLETED_DIR, files[i])); + if (receipt && receipt.command_id) { + receipts[receipt.command_id] = receipt; + } + } + return receipts; +} + +function checkTimeout(workOrder) { + var timeout = workOrder.timeout_hours || 24; + var created = new Date(workOrder.created); + var now = new Date(); + var elapsed = (now - created) / (1000 * 60 * 60); + return elapsed > timeout; +} + +function trackWorkOrders() { + console.log('\n━━━ 🧬 工单追踪器启动 ━━━\n'); + + var activeOrders = getActiveWorkOrders(); + var receipts = getCompletedReceipts(); + + console.log('活跃工单: ' + activeOrders.length + ' 个'); + + var stats = { + total_active: activeOrders.length, + by_status: {}, + timed_out: 0, + matched_receipts: 0, + escalated: 0 + }; + + for (var i = 0; i < activeOrders.length; i++) { + var wo = activeOrders[i]; + var status = wo.status || 'pending'; + + // 统计状态分布 + if (!stats.by_status[status]) stats.by_status[status] = 0; + stats.by_status[status]++; + + // 检查超时 + if (checkTimeout(wo)) { + stats.timed_out++; + console.log(' ⏰ 超时: ' + wo.id + ' (' + wo.title + ')'); + + // 检查是否需要升级 + var maxRetries = (wo.constraints && wo.constraints.max_retries) || 2; + if (wo.retry_count >= maxRetries) { + wo.status = 'ESCALATED'; + stats.escalated++; + console.log(' 🔺 升级到人类: ' + wo.id); + } + } + + // 检查回执匹配 + if (wo.command_id && receipts[wo.command_id]) { + var receipt = receipts[wo.command_id]; + stats.matched_receipts++; + + if (receipt.result && receipt.result.status === 'success') { + wo.status = 'VERIFIED'; + console.log(' ✅ 已验证: ' + wo.id + ' (回执成功)'); + } else if (receipt.result && receipt.result.status === 'failure') { + wo.status = 'pending'; + wo.retry_count = (wo.retry_count || 0) + 1; + console.log(' ❌ 失败: ' + wo.id + ' (重试 ' + wo.retry_count + ')'); + } + } + } + + // 生成追踪报告 + var now = new Date(); + var cstTime = new Date(now.getTime() + 8 * 60 * 60 * 1000); + var dateStr = cstTime.toISOString().split('T')[0]; + + var trackerReport = { + tracker_id: 'TRACKER-' + dateStr, + timestamp: now.toISOString(), + stats: stats, + active_orders: activeOrders.map(function(wo) { + return { + id: wo.id, + severity: wo.severity, + title: wo.title, + status: wo.status, + created: wo.created, + timed_out: checkTimeout(wo) + }; + }) + }; + + fs.mkdirSync(TRACKER_DIR, { recursive: true }); + fs.writeFileSync( + path.join(TRACKER_DIR, 'tracker-' + dateStr + '.json'), + JSON.stringify(trackerReport, null, 2) + ); + + console.log('\n📊 追踪报告:'); + console.log(' 活跃: ' + stats.total_active); + console.log(' 超时: ' + stats.timed_out); + console.log(' 回执匹配: ' + stats.matched_receipts); + console.log(' 升级: ' + stats.escalated); + console.log(' 状态分布: ' + JSON.stringify(stats.by_status)); + console.log('\n━━━ 追踪完成 ━━━\n'); + + return trackerReport; +} + +if (require.main === module) { + trackWorkOrders(); +} + +module.exports = { trackWorkOrders }; diff --git a/skyeye/infra-manifest.json b/skyeye/infra-manifest.json index e108b577..05efbb22 100644 --- a/skyeye/infra-manifest.json +++ b/skyeye/infra-manifest.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "last_scan": "2026-03-24T04:24:59.723Z", + "last_scan": "2026-03-25T06:00:55.972Z", "last_scan_by": "skyeye-scan-engine", "infrastructure": { "github": { @@ -114,7 +114,10 @@ "hibernate_exempt": true, "priority": "P0", "alert_on_failure": true, - "alert_channels": ["notion-dashboard", "agent-bulletin"] + "alert_channels": [ + "notion-dashboard", + "agent-bulletin" + ] }, { "id": "TOKEN-HEALTH", @@ -123,7 +126,10 @@ "hibernate_exempt": true, "priority": "P0", "alert_on_failure": true, - "alert_channels": ["notion-dashboard", "agent-bulletin"] + "alert_channels": [ + "notion-dashboard", + "agent-bulletin" + ] }, { "id": "NIGHTLY-REPAIR", @@ -132,7 +138,10 @@ "hibernate_exempt": true, "priority": "P0", "alert_on_failure": true, - "alert_channels": ["dashboard", "agent-bulletin"], + "alert_channels": [ + "dashboard", + "agent-bulletin" + ], "note": "周六休眠期内仅执行扫描+仪表盘更新,跳过修复/PR" } ] @@ -213,7 +222,10 @@ "nightly_scan": "每天 23:00 CST (15:00 UTC)", "merge_watchdog": "事件驱动(PR合并时触发)" }, - "agents": ["AG-ZY-087", "AG-ZY-088"] + "agents": [ + "AG-ZY-087", + "AG-ZY-088" + ] }, "sync_dev_status": { "node_id": "SYNC-DEV-STATUS-V1", @@ -227,7 +239,10 @@ "data_file": ".github/persona-brain/dev-status.json", "sync_log": ".github/persona-brain/dev-status-sync-log.json", "schedule": { - "sync": ["09:00 CST (01:00 UTC)", "22:00 CST (14:00 UTC)"], + "sync": [ + "09:00 CST (01:00 UTC)", + "22:00 CST (14:00 UTC)" + ], "monitor": "08:30 CST (00:30 UTC)" }, "thresholds": { @@ -254,11 +269,31 @@ "ssl": "Let's Encrypt (pending)" }, "services": { - "api_proxy": { "port": 3721, "name": "guanghulab-proxy", "desc": "AI 聊天代理 SSE" }, - "backend": { "port": 3000, "name": "guanghulab-backend", "desc": "Express 主后端" }, - "hli": { "port": 3001, "name": "guanghulab", "desc": "HLI 中间层" }, - "persona_studio": { "port": 3002, "name": "persona-studio", "desc": "Persona Studio 后端" }, - "websocket": { "port": 8080, "name": "guanghulab-ws", "desc": "看板 WebSocket" } + "api_proxy": { + "port": 3721, + "name": "guanghulab-proxy", + "desc": "AI 聊天代理 SSE" + }, + "backend": { + "port": 3000, + "name": "guanghulab-backend", + "desc": "Express 主后端" + }, + "hli": { + "port": 3001, + "name": "guanghulab", + "desc": "HLI 中间层" + }, + "persona_studio": { + "port": 3002, + "name": "persona-studio", + "desc": "Persona Studio 后端" + }, + "websocket": { + "port": 8080, + "name": "guanghulab-ws", + "desc": "看板 WebSocket" + } }, "cd_workflow": "deploy-to-server.yml", "guard": "skyeye/guards/web-deploy-guard.json", diff --git a/skyeye/logs/weekly/scan-20260325.json b/skyeye/logs/weekly/scan-20260325.json new file mode 100644 index 00000000..4e39eb0e --- /dev/null +++ b/skyeye/logs/weekly/scan-20260325.json @@ -0,0 +1,305 @@ +{ + "scan_id": "SCAN-20260325", + "mode": "full", + "timestamp": "2026-03-25T06:00:55.969Z", + "guard_scan": { + "total": 6, + "valid": 5, + "invalid": [], + "missing_fields": [ + { + "file": "web-deploy-guard.json", + "missing": [ + "quota_policy" + ] + } + ] + }, + "workflow_scan": { + "total": 96, + "files": [ + "agent-checkin.yml", + "auto-deploy-drive-bridge.yml", + "auto-reply-discussions.yml", + "bingshuo-deploy-agent.yml", + "bingshuo-neural-system.yml", + "brain-sync.yml", + "bridge-broadcast-pdf.yml", + "bridge-changes-to-notion.yml", + "bridge-heartbeat.yml", + "bridge-session-summary.yml", + "bridge-syslog-intake.yml", + "bridge-syslog-to-notion.yml", + "buffer-collect.yml", + "buffer-flush.yml", + "check-structure.yml", + "check-token-health.yml", + "daily-maintenance.yml", + "daily-report.yml", + "deploy-pages.yml", + "deploy-to-server.yml", + "distribute-broadcasts.yml", + "esp-signal-processor.yml", + "execution-sync.yml", + "federation-bridge.yml", + "feishu-syslog-bridge.yml", + "generate-module-doc.yml", + "grid-db-archive.yml", + "grid-db-processor.yml", + "grid-db-training-extract.yml", + "hli-contract-check.yml", + "merge-watchdog.yml", + "meta-watchdog.yml", + "multi-persona-awakening.yml", + "neural-daily-digest.yml", + "notion-callback-pipeline.yml", + "notion-connectivity-test.yml", + "notion-heartbeat.yml", + "notion-page-reader.yml", + "notion-poll.yml", + "notion-wake-listener.yml", + "openclaw-wake-loop.yml", + "persona-invoke.yml", + "persona-thinking-window.yml", + "pm2-server-diagnose.yml", + "process-notion-orders.yml", + "ps-on-build.yml", + "ps-on-chat.yml", + "ps-on-complete.yml", + "ps-on-login.yml", + "psp-daily-inspection.yml", + "pull-sync-awen.yml", + "push-broadcast-feishu.yml", + "push-broadcast.yml", + "readme-ui-refresh.yml", + "receive-spoke-checkin.yml", + "receive-syslog.yml", + "renew-gdrive-tokens.yml", + "sandbox-deploy.yml", + "server-patrol.yml", + "skyeye-checkin-audit.yml", + "skyeye-checkin-receiver.yml", + "skyeye-credential-audit.yml", + "skyeye-daily-hibernation.yml", + "skyeye-devsync-repair.yml", + "skyeye-weekly-hibernation.yml", + "skyeye-weekly-scan.yml", + "staging-preview.yml", + "sync-deploy-to-notion.yml", + "sync-dev-status.yml", + "sync-griddb-to-drive.yml", + "sync-griddb-to-notion.yml", + "sync-login-entry.yml", + "sync-notion-profiles.yml", + "sync-notion-to-griddb.yml", + "sync-persona-studio.yml", + "sync-repo-to-drive.yml", + "syslog-auto-pipeline.yml", + "syslog-issue-pipeline.yml", + "syslog-pipeline.yml", + "tcs-semantic-landing.yml", + "test-notion-bridge.yml", + "tianyan-daily-patrol.yml", + "tianyan-nightly-scan.yml", + "update-readme-bulletin.yml", + "update-readme.yml", + "update-repo-map.yml", + "zhuyuan-brain-sync.yml", + "zhuyuan-commander.yml", + "zhuyuan-daily-agent.yml", + "zhuyuan-daily-inspection.yml", + "zhuyuan-daily-selfcheck.yml", + "zhuyuan-exec-engine.yml", + "zhuyuan-gate-guard.yml", + "zhuyuan-issue-reply.yml", + "zhuyuan-pr-review.yml", + "zhuyuan-skyeye.yml" + ], + "errors": [] + }, + "directory_scan": { + "checked": 19, + "present": 19, + "missing": [] + }, + "sub_repo_scan": { + "total": 2, + "verified": [ + { + "name": "qinfendebingshuo/guanghulab", + "role": "main", + "guard_path_exists": true + }, + { + "name": "WENZHUOXI/guanghu-awen", + "role": "sub-repo", + "guard_path_exists": true + } + ] + }, + "ontology_scan": { + "dimension": "D16", + "name": "本体论完整性", + "checks": [ + { + "item": "ontology.json 存在", + "status": "✅", + "version": "1.0" + }, + { + "item": "核心公理完整性", + "status": "✅", + "detail": "6/6 条公理" + }, + { + "item": "三层安全定义", + "status": "✅", + "detail": "3/3 层" + }, + { + "item": "copilot-instructions 本体论宣言", + "status": "✅", + "detail": "已注入" + }, + { + "item": "README 本体论标识", + "status": "✅", + "detail": "已注入" + } + ] + }, + "neural_map_scan": { + "dimension": "D20", + "name": "双端映射完整性", + "checks": [ + { + "item": "neural-map.json 存在且可解析", + "status": "✅", + "detail": "version: 3.0.0" + }, + { + "item": "映射 Workflow 文件检查", + "status": "✅", + "detail": "11/11 文件存在" + }, + { + "item": "未映射 Workflow 检查", + "status": "✅", + "detail": "85 个未映射(非核心 Workflow 可不映射)" + }, + { + "item": "Brain 注册完整性", + "status": "✅", + "detail": "所有 Brain 均已注册" + }, + { + "item": "报告目录存在性", + "status": "✅", + "detail": "所有报告目录已创建" + } + ], + "unmapped_workflows": [ + "agent-checkin.yml", + "auto-deploy-drive-bridge.yml", + "auto-reply-discussions.yml", + "bingshuo-deploy-agent.yml", + "bingshuo-neural-system.yml", + "brain-sync.yml", + "bridge-broadcast-pdf.yml", + "bridge-changes-to-notion.yml", + "bridge-heartbeat.yml", + "bridge-session-summary.yml", + "bridge-syslog-intake.yml", + "bridge-syslog-to-notion.yml", + "buffer-collect.yml", + "buffer-flush.yml", + "check-structure.yml", + "check-token-health.yml", + "daily-maintenance.yml", + "daily-report.yml", + "deploy-pages.yml", + "esp-signal-processor.yml", + "execution-sync.yml", + "federation-bridge.yml", + "feishu-syslog-bridge.yml", + "generate-module-doc.yml", + "grid-db-archive.yml", + "grid-db-processor.yml", + "grid-db-training-extract.yml", + "hli-contract-check.yml", + "merge-watchdog.yml", + "meta-watchdog.yml", + "multi-persona-awakening.yml", + "notion-callback-pipeline.yml", + "notion-connectivity-test.yml", + "notion-heartbeat.yml", + "notion-page-reader.yml", + "notion-poll.yml", + "notion-wake-listener.yml", + "openclaw-wake-loop.yml", + "persona-invoke.yml", + "persona-thinking-window.yml", + "pm2-server-diagnose.yml", + "process-notion-orders.yml", + "ps-on-build.yml", + "ps-on-chat.yml", + "ps-on-complete.yml", + "ps-on-login.yml", + "psp-daily-inspection.yml", + "pull-sync-awen.yml", + "push-broadcast-feishu.yml", + "push-broadcast.yml", + "readme-ui-refresh.yml", + "receive-spoke-checkin.yml", + "receive-syslog.yml", + "renew-gdrive-tokens.yml", + "sandbox-deploy.yml", + "skyeye-checkin-audit.yml", + "skyeye-checkin-receiver.yml", + "skyeye-credential-audit.yml", + "skyeye-daily-hibernation.yml", + "skyeye-devsync-repair.yml", + "skyeye-weekly-hibernation.yml", + "staging-preview.yml", + "sync-deploy-to-notion.yml", + "sync-griddb-to-drive.yml", + "sync-griddb-to-notion.yml", + "sync-login-entry.yml", + "sync-notion-profiles.yml", + "sync-notion-to-griddb.yml", + "sync-persona-studio.yml", + "sync-repo-to-drive.yml", + "syslog-auto-pipeline.yml", + "syslog-issue-pipeline.yml", + "tcs-semantic-landing.yml", + "test-notion-bridge.yml", + "tianyan-daily-patrol.yml", + "tianyan-nightly-scan.yml", + "update-readme-bulletin.yml", + "update-readme.yml", + "update-repo-map.yml", + "zhuyuan-brain-sync.yml", + "zhuyuan-commander.yml", + "zhuyuan-daily-agent.yml", + "zhuyuan-daily-inspection.yml", + "zhuyuan-issue-reply.yml", + "zhuyuan-pr-review.yml" + ], + "invalid_brains": [] + }, + "issues": [ + { + "severity": "warning", + "category": "guard_config", + "detail": "Guard web-deploy-guard.json missing fields: quota_policy" + } + ], + "summary": { + "total_issues": 1, + "errors": 0, + "warnings": 1, + "guards_healthy": "5/6", + "workflows_found": 96, + "directories_ok": "19/19" + } +} diff --git a/skyeye/scripts/scan-engine.js b/skyeye/scripts/scan-engine.js index 928691e7..2035eb4b 100644 --- a/skyeye/scripts/scan-engine.js +++ b/skyeye/scripts/scan-engine.js @@ -202,6 +202,129 @@ function checkOntologyIntegrity() { return result; } +// D20 · 双端映射完整性检查 (Neural Map Integrity) +function checkNeuralMapIntegrity() { + var result = { + dimension: 'D20', + name: '双端映射完整性', + checks: [], + unmapped_workflows: [], + invalid_brains: [] + }; + + var neuralMapPath = path.join(SKYEYE_DIR, 'neural-map.json'); + if (!fs.existsSync(neuralMapPath)) { + result.checks.push({ + item: 'neural-map.json 存在', + status: '🔴', + detail: '文件缺失' + }); + return result; + } + + var neuralMap = loadJSON(neuralMapPath); + if (!neuralMap) { + result.checks.push({ + item: 'neural-map.json 可解析', + status: '🔴', + detail: 'JSON 解析失败' + }); + return result; + } + + result.checks.push({ + item: 'neural-map.json 存在且可解析', + status: '✅', + detail: 'version: ' + (neuralMap.version || 'unknown') + }); + + // 检查所有映射的 Workflow 文件是否实际存在 + var mappedFiles = {}; + var workflowEntries = Object.entries(neuralMap.github_workflows || {}); + var existCount = 0; + var missingCount = 0; + + for (var i = 0; i < workflowEntries.length; i++) { + var wfId = workflowEntries[i][0]; + var wf = workflowEntries[i][1]; + var filePath = path.join(ROOT, wf.file); + mappedFiles[wf.file] = true; + if (fs.existsSync(filePath)) { + existCount++; + } else { + missingCount++; + result.checks.push({ + item: '映射文件存在: ' + wf.file, + status: '🔴', + detail: wfId + ' 映射的文件不存在' + }); + } + } + + result.checks.push({ + item: '映射 Workflow 文件检查', + status: missingCount === 0 ? '✅' : '🔴', + detail: existCount + '/' + workflowEntries.length + ' 文件存在' + }); + + // 检查实际 .yml 中是否有未映射的(仅检查核心 Workflow,非全量) + var workflowDir = path.join(ROOT, '.github/workflows'); + if (fs.existsSync(workflowDir)) { + var actualFiles = fs.readdirSync(workflowDir) + .filter(function(f) { return f.endsWith('.yml') || f.endsWith('.yaml'); }); + + for (var j = 0; j < actualFiles.length; j++) { + var ymlPath = '.github/workflows/' + actualFiles[j]; + if (!mappedFiles[ymlPath]) { + result.unmapped_workflows.push(actualFiles[j]); + } + } + } + + // 注意:unmapped 不一定是错误,因为 neural-map 只映射核心 Workflow + result.checks.push({ + item: '未映射 Workflow 检查', + status: result.unmapped_workflows.length <= 85 ? '✅' : '🟡', + detail: result.unmapped_workflows.length + ' 个未映射(非核心 Workflow 可不映射)' + }); + + // 检查每个 brain 是否在 notion_brains 中注册 + for (var k = 0; k < workflowEntries.length; k++) { + var wfId2 = workflowEntries[k][0]; + var wf2 = workflowEntries[k][1]; + if (wf2.brain && !(neuralMap.notion_brains || {})[wf2.brain]) { + result.invalid_brains.push({ workflow: wfId2, brain: wf2.brain }); + } + } + + result.checks.push({ + item: 'Brain 注册完整性', + status: result.invalid_brains.length === 0 ? '✅' : '🔴', + detail: result.invalid_brains.length === 0 + ? '所有 Brain 均已注册' + : result.invalid_brains.length + ' 个 Brain 未注册' + }); + + // 检查 report_path 目录是否存在 + var reportPathMissing = 0; + for (var m = 0; m < workflowEntries.length; m++) { + var wf3 = workflowEntries[m][1]; + if (wf3.report_path && !fs.existsSync(path.join(ROOT, wf3.report_path))) { + reportPathMissing++; + } + } + + result.checks.push({ + item: '报告目录存在性', + status: reportPathMissing === 0 ? '✅' : '🟡', + detail: reportPathMissing === 0 + ? '所有报告目录已创建' + : reportPathMissing + ' 个报告目录缺失' + }); + + return result; +} + function run() { const args = process.argv.slice(2); const mode = args.find(a => a.startsWith('--mode='))?.split('=')[1] || 'full'; @@ -224,6 +347,7 @@ function run() { directory_scan: scanDirectoryStructure(), sub_repo_scan: scanSubRepos(manifest), ontology_scan: checkOntologyIntegrity(), + neural_map_scan: checkNeuralMapIntegrity(), issues: [], summary: {} }; @@ -270,6 +394,32 @@ function run() { } } + // D20 · 双端映射完整性 issues + if (scanResult.neural_map_scan && scanResult.neural_map_scan.checks) { + for (const check of scanResult.neural_map_scan.checks) { + if (check.status === '🔴') { + scanResult.issues.push({ + severity: 'error', + category: 'neural_map_integrity', + detail: `D20 · ${check.item}: ${check.detail || '失败'}` + }); + } else if (check.status === '🟡') { + scanResult.issues.push({ + severity: 'warning', + category: 'neural_map_integrity', + detail: `D20 · ${check.item}: ${check.detail || '需关注'}` + }); + } + } + if (scanResult.neural_map_scan.invalid_brains.length > 0) { + scanResult.issues.push({ + severity: 'error', + category: 'neural_map_integrity', + detail: `D20 · Brain 映射指向不存在的 Agent: ${scanResult.neural_map_scan.invalid_brains.map(b => b.brain).join(', ')}` + }); + } + } + // Summary scanResult.summary = { total_issues: scanResult.issues.length, @@ -304,6 +454,14 @@ function run() { console.log(` ${check.status} ${check.item}${check.detail ? ' · ' + check.detail : ''}${check.version ? ' · v' + check.version : ''}`); } } + + // D20 · 双端映射完整性状态 + if (scanResult.neural_map_scan) { + console.log(`[SkyEye Scan Engine] D20 Neural Map:`); + for (const check of scanResult.neural_map_scan.checks) { + console.log(` ${check.status} ${check.item}${check.detail ? ' · ' + check.detail : ''}`); + } + } console.log(`[SkyEye Scan Engine] Log saved: ${logPath}`); // Output full result as JSON for pipeline