# ═══════════════════════════════════════════════ # 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001 # 📜 Copyright: 国作登字-2026-A-00037559 # ═══════════════════════════════════════════════ # 🦅 天眼 · dev-status 同步修复闭环 # 指令溯源:ZY-DEVSYNC-REBUILD-2026-0325-001 # 三级告警:🟢≤14h · 🟡≤48h · 🔴>48h # 三次修复失败 → GitHub Issue 告警 → 邮件通知冰朔 # ═══════════════════════════════════════════════ name: "🦅 天眼 · dev-status 同步修复闭环" on: schedule: - cron: '30 0 * * *' # UTC 00:30 = 北京 08:30 · 天眼巡检时间 workflow_dispatch: inputs: force_repair: description: '强制触发修复(跳过检查)' required: false default: 'false' permissions: contents: write issues: write actions: write env: DEV_STATUS_PATH: ".github/persona-brain/dev-status.json" SYNC_LOG_PATH: ".github/persona-brain/dev-status-sync-log.json" YELLOW_THRESHOLD_HOURS: 14 RED_THRESHOLD_HOURS: 48 SYNC_FRESHNESS_MINUTES: 10 jobs: check-sync-status: name: "🦅 D10 同步状态检查" runs-on: ubuntu-latest timeout-minutes: 5 outputs: level: ${{ steps.check.outputs.level }} hours: ${{ steps.check.outputs.hours }} last_sync: ${{ steps.check.outputs.last_sync }} steps: - name: "📥 检出仓库" uses: actions/checkout@v4 - name: "🦅 天眼 D10 检查" id: check run: | echo "═══ 天眼 D10 · dev-status.json 同步状态检查 ═══" FORCE="${{ github.event.inputs.force_repair }}" if [ "$FORCE" == "true" ]; then echo "⚡ 强制修复模式 · 跳过检查" echo "level=yellow" >> $GITHUB_OUTPUT echo "hours=999" >> $GITHUB_OUTPUT echo "last_sync=forced" >> $GITHUB_OUTPUT exit 0 fi # 优先读 sync-log,其次读 dev-status.json 的 last_sync LAST_SYNC="" if [ -f "$SYNC_LOG_PATH" ]; then LAST_SYNC=$(node -e " try { const d = JSON.parse(require('fs').readFileSync('$SYNC_LOG_PATH','utf8')); if (d.status === 'success' && d.last_sync) console.log(d.last_sync); else console.log(''); } catch { console.log(''); } ") fi if [ -z "$LAST_SYNC" ] && [ -f "$DEV_STATUS_PATH" ]; then LAST_SYNC=$(node -e " try { const d = JSON.parse(require('fs').readFileSync('$DEV_STATUS_PATH','utf8')); console.log(d.last_sync || d.signed_at || ''); } catch { console.log(''); } ") fi if [ -z "$LAST_SYNC" ]; then echo "❌ 无法读取 last_sync · 视为严重中断" echo "level=red" >> $GITHUB_OUTPUT echo "hours=999" >> $GITHUB_OUTPUT echo "last_sync=unknown" >> $GITHUB_OUTPUT exit 0 fi echo "最后同步时间:$LAST_SYNC" HOURS_AGO=$(node -e " const diff = Date.now() - new Date('$LAST_SYNC').getTime(); console.log(Math.floor(diff / 3600000)); ") echo "距上次同步:${HOURS_AGO}h" echo "last_sync=$LAST_SYNC" >> $GITHUB_OUTPUT echo "hours=$HOURS_AGO" >> $GITHUB_OUTPUT if [ "$HOURS_AGO" -le "$YELLOW_THRESHOLD_HOURS" ]; then echo "🟢 正常 · 无需修复" echo "level=green" >> $GITHUB_OUTPUT elif [ "$HOURS_AGO" -le "$RED_THRESHOLD_HOURS" ]; then echo "🟡 告警 · 进入三次修复闭环" echo "level=yellow" >> $GITHUB_OUTPUT else echo "🔴 严重 · 直接邮件告警" echo "level=red" >> $GITHUB_OUTPUT fi repair-loop: name: "🔧 三次修复闭环" needs: check-sync-status if: needs.check-sync-status.outputs.level == 'yellow' runs-on: ubuntu-latest timeout-minutes: 25 outputs: repair_result: ${{ steps.repair.outputs.result }} repair_attempts: ${{ steps.repair.outputs.attempts }} repair_details: ${{ steps.repair.outputs.details }} steps: - name: "📥 检出仓库" uses: actions/checkout@v4 - name: "🔧 修复闭环(最多3次)" id: repair env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | DETAILS="" for i in 1 2 3; do echo "═══ 第 ${i} 次修复尝试 ═══" ATTEMPT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") # 触发同步 workflow echo "触发 sync-dev-status.yml..." gh workflow run sync-dev-status.yml \ -f reason="天眼修复闭环·第${i}次·${ATTEMPT_TIME}" 2>&1 || true # 等待执行完成 echo "等待同步完成(300秒)..." sleep 300 # 拉取最新代码检查结果 git pull origin main --rebase 2>/dev/null || git pull origin main 2>/dev/null || true # 检查 sync-log SYNC_LOG_PATH=".github/persona-brain/dev-status-sync-log.json" if [ -f "$SYNC_LOG_PATH" ]; then STATUS=$(node -e " try { const d = JSON.parse(require('fs').readFileSync('$SYNC_LOG_PATH','utf8')); const syncTime = new Date(d.last_sync || '2000-01-01'); const diffMin = (Date.now() - syncTime.getTime()) / 60000; if (d.status === 'success' && diffMin < ${{ env.SYNC_FRESHNESS_MINUTES }}) console.log('success'); else console.log('stale'); } catch { console.log('error'); } ") if [ "$STATUS" == "success" ]; then echo "✅ 第 ${i} 次修复成功!" DETAILS="${DETAILS}第${i}次(${ATTEMPT_TIME}): 成功; " echo "result=success" >> $GITHUB_OUTPUT echo "attempts=$i" >> $GITHUB_OUTPUT echo "details=$DETAILS" >> $GITHUB_OUTPUT exit 0 fi fi DETAILS="${DETAILS}第${i}次(${ATTEMPT_TIME}): 失败; " echo "❌ 第 ${i} 次修复失败" [ $i -lt 3 ] && echo "等待60秒后重试..." && sleep 60 done echo "❌ 三次修复全部失败" echo "result=failed" >> $GITHUB_OUTPUT echo "attempts=3" >> $GITHUB_OUTPUT echo "details=$DETAILS" >> $GITHUB_OUTPUT alert-human: name: "📧 邮件告警(创建 Issue)" needs: [check-sync-status, repair-loop] if: | always() && ( needs.check-sync-status.outputs.level == 'red' || (needs.repair-loop.result == 'success' && needs.repair-loop.outputs.repair_result == 'failed') ) runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: "📧 创建告警 Issue" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | HOURS="${{ needs.check-sync-status.outputs.hours }}" LEVEL="${{ needs.check-sync-status.outputs.level }}" LAST_SYNC="${{ needs.check-sync-status.outputs.last_sync }}" REPAIR_RESULT="${{ needs.repair-loop.outputs.repair_result }}" REPAIR_DETAILS="${{ needs.repair-loop.outputs.repair_details }}" if [ "$LEVEL" == "red" ]; then REPAIR_NOTE="已跳过修复尝试(超48h直接告警)" else REPAIR_NOTE="3/3 修复尝试全部失败" fi BODY="## 🚨 dev-status.json 同步故障通知 妈妈,dev-status.json 同步出了问题,铸渊和霜砚尝试了自动修复没成功,需要你手动看一下。 ### 故障概况 - **告警级别**:${LEVEL} - **最后成功同步**:${LAST_SYNC} - **中断时长**:${HOURS}h - **修复尝试**:${REPAIR_NOTE} ### 修复记录 ${REPAIR_DETAILS:-无修复尝试} ### 建议操作 1. 检查 GitHub Secrets 中的 \`NOTION_API_KEY\` 是否有效 2. 检查 GitHub Secrets 中的 \`DEV_STATUS_DB_ID\` 是否正确 3. 手动触发 \`sync-dev-status.yml\` 验证 4. 查看最近的 Actions 运行日志定位根因 ### 指令溯源 ZY-DEVSYNC-REBUILD-2026-0325-001 · 霜砚签发 · 冰朔授权 版权锚点:国作登字-2026-A-00037559" gh issue create \ --repo "${{ github.repository }}" \ --title "🚨 dev-status.json 同步故障 · 中断${HOURS}h · 需人工干预" \ --body "$BODY" \ --label "系统告警" || \ gh issue create \ --repo "${{ github.repository }}" \ --title "🚨 dev-status.json 同步故障 · 中断${HOURS}h · 需人工干预" \ --body "$BODY" echo "📧 已创建 Issue 告警 · GitHub 将自动发送邮件通知到仓库 owner" write-repair-log: name: "📋 写入天眼修复记录" needs: [check-sync-status, repair-loop, alert-human] if: always() && needs.check-sync-status.outputs.level != 'green' runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: "📥 检出仓库" uses: actions/checkout@v4 - name: "📋 写入修复日志" run: | REPAIR_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") DATE_STR=$(date -u +"%Y%m%d") LEVEL="${{ needs.check-sync-status.outputs.level }}" HOURS="${{ needs.check-sync-status.outputs.hours }}" REPAIR_RESULT="${{ needs.repair-loop.outputs.repair_result }}" REPAIR_ATTEMPTS="${{ needs.repair-loop.outputs.repair_attempts }}" mkdir -p signal-log cat > "signal-log/skyeye-d10-${DATE_STR}.json" << EOF { "check_time": "$REPAIR_TIME", "d10_level": "$LEVEL", "hours_since_sync": "$HOURS", "repair_result": "${REPAIR_RESULT:-skipped}", "repair_attempts": "${REPAIR_ATTEMPTS:-0}", "mechanism": "skyeye-devsync-repair-v1.0", "instruction_ref": "ZY-DEVSYNC-REBUILD-2026-0325-001" } EOF git config user.name "天眼 (SKYEYE)" git config user.email "skyeye@guanghulab.system" git add signal-log/ 2>/dev/null || true git diff --cached --quiet || ( git commit -m "🦅 天眼 D10 · dev-status 修复记录 · $LEVEL · $REPAIR_TIME [skip ci]" && \ git push origin main ) || true