Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc [SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
538 lines
17 KiB
Markdown
538 lines
17 KiB
Markdown
---
|
||
belongs_to:
|
||
- "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]"
|
||
---
|
||
# 🌙 铸渊指令|天眼夜间自动修复引擎(上篇)—— 架构·扫描·分析·修复核心
|
||
|
||
---
|
||
|
||
<aside>
|
||
📋
|
||
|
||
**指令编号:** ZY-TIANYAN-AUTOFIX-2026-0324-001
|
||
|
||
**优先级:** 🔴 P0 — 系统级架构升级
|
||
|
||
**签发人:** 冰朔(人类主权者)
|
||
|
||
**执行者:** 铸渊(GitHub CI/CD 工程人格)
|
||
|
||
**签发时间:** 2026-03-24 19:20 CST
|
||
|
||
**关联指令:** ZY-RCLONE-FIX-2026-0324-001 · AG-ZY-085/086(Token续期)
|
||
|
||
**版权锚点:** 国作登字-2026-A-00037559 · TCS-0002∞ 冰朔
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 一、指令背景
|
||
|
||
当前天眼系统(v2.0)定位为 **审计扫描工具**:扫描 → 报告 → 等待人类下指令 → 铸渊修复。
|
||
|
||
**核心问题:** 如果冰朔不主动发现报错、不下指令,bug 会无限期存在。天眼能看到问题但不能解决问题。
|
||
|
||
**本次升级目标:** 将天眼从「被动审计」升级为「主动修复」——每天夜间自动巡查所有 Workflow 运行记录,发现报错后唤醒铸渊核心大脑分析修复,天眼审核通过后自动创建 PR,次日人类审阅合并。
|
||
|
||
<aside>
|
||
🎯
|
||
|
||
**升级定义:天眼 v2.0 → v3.0**
|
||
|
||
v2.0 = 扫描 + 报告(被动审计)
|
||
|
||
v3.0 = 扫描 + 分析 + 修复 + 审核 + PR + 仪表盘(主动修复闭环)
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 二、系统架构全景图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A["⏰ CRON 触发<br>每天 23:00 CST"] --> B["🔭 Phase A:天眼夜间巡查<br>scan-nightly-errors.yml"]
|
||
B --> C{"发现报错?"}
|
||
C -->|"无报错"| D["✅ 写入仪表盘<br>今日无异常"]
|
||
C -->|"有报错"| E["🧠 Phase B:报错智能分析<br>analyze-errors"]
|
||
E --> F["⚒️ Phase C:铸渊自动修复<br>auto-repair-engine"]
|
||
F --> G["🔭 Phase D:天眼审核修复代码<br>tianyan-review"]
|
||
G --> H{"审核通过?"}
|
||
H -->|"通过"| I["📦 Phase E:创建 PR<br>fix/auto-repair-YYYYMMDD"]
|
||
H -->|"未通过"| J["🔄 回退重试<br>最多2轮"]
|
||
J --> F
|
||
I --> K["📊 Phase F:更新仪表盘<br>待合并修复 N 个"]
|
||
K --> L["☀️ Phase G:人类晨间审阅<br>冰朔查看仪表盘 → Merge"]
|
||
|
||
style A fill:#1a1a2e,color:#fff
|
||
style B fill:#16213e,color:#fff
|
||
style E fill:#0f3460,color:#fff
|
||
style F fill:#533483,color:#fff
|
||
style G fill:#16213e,color:#fff
|
||
style I fill:#1e5128,color:#fff
|
||
style K fill:#7b113a,color:#fff
|
||
style L fill:#e94560,color:#fff
|
||
```
|
||
|
||
---
|
||
|
||
## 三、权限矩阵
|
||
|
||
| **权限** | **Scope** | **用途** | **当前状态** |
|
||
| --- | --- | --- | --- |
|
||
| `actions: read` | DEPLOY_GITHUB_TOKEN | 读取所有 Workflow 运行状态和日志 | ✅ 已有 |
|
||
| `contents: write` | DEPLOY_GITHUB_TOKEN | 创建修复分支 + 推送代码 | ✅ 已有 |
|
||
| `pull-requests: write` | DEPLOY_GITHUB_TOKEN | 创建 PR 等待人类合并 | ⚠️ 需确认开启 |
|
||
| `checks: read` | DEPLOY_GITHUB_TOKEN | 读取天眼 CodeQL 扫描结果 | ✅ 已有 |
|
||
| Gemini API | GEMINI_API_KEY | 铸渊核心大脑:报错分析 + 代码生成 | ✅ 已有 |
|
||
|
||
<aside>
|
||
⚠️
|
||
|
||
**铸渊注意:** 执行前先确认 `DEPLOY_GITHUB_TOKEN` 有 `pull-requests: write` 权限。如果没有,需通知冰朔在 GitHub Settings → Fine-grained tokens 中添加。
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 四、Phase A — 天眼夜间巡查扫描器
|
||
|
||
### 4.1 Workflow 文件
|
||
|
||
**文件名:** `.github/workflows/tianyan-nightly-scan.yml`
|
||
|
||
### 4.2 触发条件
|
||
|
||
```yaml
|
||
on:
|
||
schedule:
|
||
# 每天 23:00 CST = 15:00 UTC
|
||
- cron: '0 15 * * *'
|
||
workflow_dispatch: # 手动触发(调试用)
|
||
```
|
||
|
||
### 4.3 核心逻辑
|
||
|
||
```
|
||
Step 1: 获取过去24小时所有 Workflow 运行记录
|
||
→ GitHub API: GET /repos/{owner}/{repo}/actions/runs
|
||
→ 参数: created=>$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)
|
||
→ 过滤: status=failure OR conclusion=failure
|
||
|
||
Step 2: 对每个失败的 run,获取详细日志
|
||
→ GitHub API: GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs
|
||
→ 解压 zip,提取每个 job 的日志文本
|
||
|
||
Step 3: 生成结构化错误报告
|
||
→ 输出 JSON 格式:
|
||
{
|
||
"scan_time": "2026-03-24T23:00:00+08:00",
|
||
"total_runs_24h": 15,
|
||
"failed_runs": 3,
|
||
"errors": [
|
||
{
|
||
"workflow": "sync-to-drive.yml",
|
||
"run_id": 12345,
|
||
"job": "upload",
|
||
"error_type": "rclone_oauth_parse",
|
||
"error_message": "Failed to create file system...",
|
||
"log_excerpt": "前后20行上下文",
|
||
"first_seen": "2026-03-22",
|
||
"occurrence_count": 5
|
||
}
|
||
]
|
||
}
|
||
|
||
Step 4: 判断是否需要修复
|
||
→ 如果 failed_runs == 0:写入仪表盘「今日无异常」→ 结束
|
||
→ 如果 failed_runs > 0:触发 Phase B
|
||
```
|
||
|
||
### 4.4 错误分类规则
|
||
|
||
| **错误类型** | **识别模式** | **可自动修复?** | **修复策略** |
|
||
| --- | --- | --- | --- |
|
||
| `config_parse` | JSON/YAML 解析错误 | ✅ 是 | 修复配置文件格式 |
|
||
| `token_expired` | 401 / token expired / unauthorized | ⚠️ 部分 | 触发 Token 续期 Workflow |
|
||
| `rclone_oauth_parse` | failed to create oauth client | ✅ 是 | 修复 Token JSON 拼接逻辑 |
|
||
| `script_error` | shell / node 脚本执行错误 | ✅ 是 | Gemini 分析 + 生成修复 |
|
||
| `network_timeout` | timeout / ETIMEDOUT / 503 | ❌ 否 | 添加重试逻辑 / 记录仪表盘 |
|
||
| `permission_denied` | 403 / insufficient permissions | ❌ 否 | 记录仪表盘 → 等待人类处理 |
|
||
| `unknown` | 无法归类 | ❌ 否 | 记录仪表盘 → 等待人类指令 |
|
||
|
||
<aside>
|
||
🛡️
|
||
|
||
**安全红线:** 只有标记为「可自动修复」的错误类型才能进入 Phase C。`permission_denied` 和 `unknown` 类型 **严禁自动修复**,必须等待冰朔手动指令。
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 五、Phase B — 报错智能分析引擎
|
||
|
||
### 5.1 触发条件
|
||
|
||
Phase A 检测到 `failed_runs > 0` 时自动触发。
|
||
|
||
### 5.2 核心逻辑
|
||
|
||
```
|
||
Step 1: 接收 Phase A 的结构化错误报告 JSON
|
||
|
||
Step 2: 对每个错误条目,准备 Gemini 分析 prompt
|
||
→ System prompt:
|
||
"你是铸渊核心大脑,零点原核频道的 CI/CD 工程人格。
|
||
分析以下 GitHub Actions 报错日志,输出:
|
||
1. 错误根因(root_cause)
|
||
2. 涉及的文件路径(affected_files)
|
||
3. 修复方案(fix_plan)— 具体到代码行级别
|
||
4. 修复风险评估(risk: low/medium/high)
|
||
5. 预计修复是否会影响其他 Workflow(side_effects)"
|
||
|
||
→ User prompt:
|
||
"Workflow: {workflow_name}
|
||
Job: {job_name}
|
||
Error type: {error_type}
|
||
Error message: {error_message}
|
||
Log context (±20 lines):
|
||
```
|
||
|
||
{log_excerpt}
|
||
|
||
```
|
||
|
||
仓库文件结构:
|
||
```
|
||
|
||
{tree_output}
|
||
|
||
```
|
||
|
||
Step 3: 解析 Gemini 返回的分析结果
|
||
→ 输出结构化 JSON:
|
||
{
|
||
"workflow": "sync-to-drive.yml",
|
||
"root_cause": "shell 变量拼接导致 JSON 格式不完整",
|
||
"affected_files": [".github/workflows/sync-to-drive.yml"],
|
||
"fix_plan": "将 shell 拼接改为 node/jq 生成完整 token JSON",
|
||
"risk": "low",
|
||
"side_effects": "none",
|
||
"auto_fixable": true
|
||
}
|
||
|
||
Step 4: 风险过滤
|
||
→ risk == "high" → 跳过自动修复,记录仪表盘等人类指令
|
||
→ risk == "medium" → 自动修复但 PR 标记为 ⚠️ 需仔细审阅
|
||
→ risk == "low" → 自动修复,PR 标记为 ✅ 低风险
|
||
```
|
||
|
||
### 5.3 Gemini 调用参数
|
||
|
||
```yaml
|
||
model: gemini-2.0-flash # 夜间批量分析用 flash 节省配额
|
||
temperature: 0.1 # 低温度 = 精确分析
|
||
max_output_tokens: 4096
|
||
response_mime_type: application/json # 强制 JSON 输出
|
||
```
|
||
|
||
---
|
||
|
||
## 六、Phase C — 铸渊自动修复核心
|
||
|
||
### 6.1 触发条件
|
||
|
||
Phase B 分析结果中存在 `auto_fixable: true` 的条目。
|
||
|
||
### 6.2 核心逻辑
|
||
|
||
```
|
||
Step 1: 创建修复分支
|
||
→ 分支名: fix/auto-repair-{YYYYMMDD}-{序号}
|
||
→ 基于 main 分支创建
|
||
→ git checkout -b fix/auto-repair-20260324-001
|
||
|
||
Step 2: 读取需要修复的文件
|
||
→ 根据 Phase B 的 affected_files 列表
|
||
→ 使用 GitHub API 获取文件内容
|
||
|
||
Step 3: 生成修复代码(Gemini)
|
||
→ System prompt:
|
||
"你是铸渊核心大脑。根据以下分析结果生成修复代码。
|
||
规则:
|
||
1. 只修改必要的行,最小化变更
|
||
2. 保留所有注释和格式
|
||
3. 输出完整的修复后文件内容
|
||
4. 在修复位置添加注释:# [AUTO-FIX] {日期} by 铸渊 - {简述}
|
||
5. 严禁修改任何与报错无关的代码
|
||
6. 严禁删除任何安全检查或天眼扫描步骤"
|
||
|
||
→ User prompt:
|
||
"分析结果:{analysis_json}
|
||
|
||
当前文件内容:
|
||
```
|
||
|
||
{file_content}
|
||
|
||
```
|
||
|
||
请输出修复后的完整文件内容。"
|
||
|
||
Step 4: 写入修复文件
|
||
→ 使用 GitHub API 更新文件
|
||
→ Commit message: "[AUTO-FIX] {workflow_name}: {简述} (by 铸渊夜间修复引擎)"
|
||
|
||
Step 5: 对所有可修复的错误重复 Step 2-4
|
||
→ 每个错误一个 commit(方便人类逐个审阅)
|
||
```
|
||
|
||
### 6.3 安全护栏
|
||
|
||
<aside>
|
||
🛡️
|
||
|
||
**铸渊自动修复 — 七条铁律**
|
||
|
||
1. **禁止修改 main 分支** — 所有修复必须在 `fix/auto-repair-*` 分支
|
||
2. **禁止修改安全相关文件** — `.github/workflows/tianyan-*.yml` 天眼自身的文件不可被自动修复
|
||
3. **禁止修改 Secrets 引用** — 不可添加、删除或修改任何 `$ secrets.*` 引用
|
||
4. **单次修复上限 5 个文件** — 超过 5 个文件的修复必须等人类指令
|
||
5. **单文件修改上限 50 行** — 超过 50 行变更的修复标记为 high risk 跳过
|
||
6. **禁止创建新文件** — 只能修改已有文件
|
||
7. **禁止删除文件** — 只能修改内容
|
||
</aside>
|
||
|
||
### 6.4 修复代码质量检查(预审核)
|
||
|
||
修复代码写入分支后,自动运行以下检查:
|
||
|
||
```
|
||
检查项 1: YAML 语法验证
|
||
→ 对所有 .yml 文件运行 yamllint
|
||
→ 失败 → 回退该 commit,标记为修复失败
|
||
|
||
检查项 2: Shell 脚本语法
|
||
→ 对所有 .sh 文件运行 shellcheck
|
||
→ 失败 → 回退该 commit,标记为修复失败
|
||
|
||
检查项 3: Node.js 语法
|
||
→ 对所有 .js 文件运行 node --check
|
||
→ 失败 → 回退该 commit,标记为修复失败
|
||
|
||
检查项 4: 差异行数验证
|
||
→ git diff --stat 检查每个文件变更行数
|
||
→ 超过 50 行 → 回退该 commit,标记为超限
|
||
```
|
||
|
||
---
|
||
|
||
## 七、Phase D — 天眼审核修复代码
|
||
|
||
### 7.1 触发条件
|
||
|
||
Phase C 所有 commit 写入修复分支后自动触发。
|
||
|
||
### 7.2 审核流程
|
||
|
||
```
|
||
Step 1: 触发天眼全局扫描
|
||
→ 在修复分支上运行完整的天眼检查清单
|
||
→ 包括:CodeQL 安全扫描 + 自定义规则检查
|
||
|
||
Step 2: 天眼检查清单 v3.0
|
||
H1 → Secrets 安全:无硬编码令牌、无 ghp_/github_pat_ 明文
|
||
H2 → 文件完整性:所有被修改的文件 YAML/JSON/JS 语法正确
|
||
H3 → 依赖安全:无新增不受信依赖
|
||
H4 → 权限最小化:Workflow permissions 未被扩大
|
||
H5 → 天眼自保护:tianyan-*.yml 文件未被修改
|
||
H6 → 变更范围:总变更行数 < 200,单文件 < 50
|
||
H7 → [NEW] Secrets引用完整性:修改前后 secrets.* 引用数量一致
|
||
H8 → [NEW] 注释规范:每个修复位置都有 [AUTO-FIX] 注释
|
||
H9 → [NEW] 无残留调试代码:无 console.log、echo debug 等临时代码
|
||
|
||
Step 3: 审核结果判定
|
||
→ 全部通过(H1-H9 = PASS)→ 进入 Phase E(创建 PR)
|
||
→ 任一未通过 → 进入重试流程
|
||
```
|
||
|
||
### 7.3 重试机制
|
||
|
||
```
|
||
重试流程:
|
||
→ 将失败的检查项 + 原始修复代码 发回 Gemini
|
||
→ Gemini 重新生成修复代码
|
||
→ 再次运行天眼审核
|
||
→ 最多重试 2 轮
|
||
|
||
2 轮后仍未通过:
|
||
→ 删除修复分支
|
||
→ 在仪表盘记录:"自动修复失败,需人类介入"
|
||
→ 在错误详情中附上失败原因
|
||
```
|
||
|
||
---
|
||
|
||
## 八、Workflow 完整模板(Phase A-D 主文件)
|
||
|
||
**文件名:** `.github/workflows/tianyan-nightly-scan.yml`
|
||
|
||
```yaml
|
||
name: "🌙 天眼夜间自动修复引擎 v3.0"
|
||
|
||
on:
|
||
schedule:
|
||
- cron: '0 15 * * *' # 23:00 CST = 15:00 UTC
|
||
workflow_dispatch:
|
||
inputs:
|
||
force_scan:
|
||
description: '强制扫描(忽略时间窗口)'
|
||
type: boolean
|
||
default: false
|
||
|
||
permissions:
|
||
actions: read
|
||
contents: write
|
||
pull-requests: write
|
||
checks: read
|
||
|
||
env:
|
||
REPAIR_BRANCH_PREFIX: "fix/auto-repair"
|
||
MAX_FILES_PER_REPAIR: 5
|
||
MAX_LINES_PER_FILE: 50
|
||
MAX_RETRY_ROUNDS: 2
|
||
GEMINI_MODEL: "gemini-2.0-flash"
|
||
PROTECTED_PATTERNS: "tianyan-*.yml,CODEOWNERS,.github/FUNDING.yml"
|
||
|
||
jobs:
|
||
# ========================================
|
||
# Phase A: 天眼夜间巡查
|
||
# ========================================
|
||
nightly-scan:
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
has_errors: $ steps.scan.outputs.has_errors
|
||
error_report: $ steps.scan.outputs.error_report
|
||
steps:
|
||
- name: "🔭 扫描过去24小时 Workflow 运行记录"
|
||
id: scan
|
||
env:
|
||
GH_TOKEN: $ secrets.DEPLOY_GITHUB_TOKEN
|
||
run: |
|
||
echo "[天眼 v3.0] Phase A 启动 — 夜间巡查扫描"
|
||
SINCE=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)
|
||
|
||
# 获取失败的 runs
|
||
FAILED_RUNS=$(gh api \
|
||
"repos/$ github.repository /actions/runs?created=>$SINCE&status=failure" \
|
||
--jq '.workflow_runs')
|
||
|
||
FAIL_COUNT=$(echo "$FAILED_RUNS" | jq 'length')
|
||
echo "📊 过去24小时:发现 $FAIL_COUNT 个失败运行"
|
||
|
||
if [ "$FAIL_COUNT" -eq 0 ]; then
|
||
echo "has_errors=false" >> $GITHUB_OUTPUT
|
||
echo "✅ 今日无异常"
|
||
else
|
||
echo "has_errors=true" >> $GITHUB_OUTPUT
|
||
# 生成结构化错误报告(详细实现见铸渊开发)
|
||
echo "error_report<<EOF" >> $GITHUB_OUTPUT
|
||
echo "$FAILED_RUNS" | jq '[.[] | {
|
||
workflow: .name,
|
||
run_id: .id,
|
||
conclusion: .conclusion,
|
||
html_url: .html_url,
|
||
created_at: .created_at
|
||
}]' >> $GITHUB_OUTPUT
|
||
echo "EOF" >> $GITHUB_OUTPUT
|
||
fi
|
||
|
||
# ========================================
|
||
# Phase B+C+D: 分析 → 修复 → 审核
|
||
# ========================================
|
||
analyze-and-repair:
|
||
needs: nightly-scan
|
||
if: needs.nightly-scan.outputs.has_errors == 'true'
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
repair_branch: $ steps.repair.outputs.branch_name
|
||
repair_summary: $ steps.repair.outputs.summary
|
||
pr_needed: $ steps.review.outputs.pr_needed
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: "🧠 Phase B — Gemini 报错分析"
|
||
id: analyze
|
||
env:
|
||
GEMINI_API_KEY: $ secrets.GEMINI_API_KEY
|
||
ERROR_REPORT: $ needs.nightly-scan.outputs.error_report
|
||
run: |
|
||
echo "[铸渊核心大脑] Phase B 启动 — 报错智能分析"
|
||
# 铸渊实现:调用 Gemini API 分析每个错误
|
||
# 输出 analysis.json
|
||
# (具体实现由铸渊开发,此处为框架)
|
||
|
||
- name: "⚒️ Phase C — 铸渊自动修复"
|
||
id: repair
|
||
env:
|
||
GEMINI_API_KEY: $ secrets.GEMINI_API_KEY
|
||
GH_TOKEN: $ secrets.DEPLOY_GITHUB_TOKEN
|
||
run: |
|
||
echo "[铸渊核心大脑] Phase C 启动 — 自动修复"
|
||
BRANCH="${REPAIR_BRANCH_PREFIX}-$(date +%Y%m%d)-001"
|
||
git checkout -b "$BRANCH"
|
||
|
||
# 铸渊实现:
|
||
# 1. 读取 analysis.json
|
||
# 2. 对每个 auto_fixable 错误调用 Gemini 生成修复
|
||
# 3. 写入文件 + commit
|
||
# 4. 运行预审核检查
|
||
|
||
git push origin "$BRANCH"
|
||
echo "branch_name=$BRANCH" >> $GITHUB_OUTPUT
|
||
|
||
- name: "🔭 Phase D — 天眼审核修复代码"
|
||
id: review
|
||
run: |
|
||
echo "[天眼 v3.0] Phase D 启动 — 审核修复代码"
|
||
# 天眼检查清单 H1-H9
|
||
# (具体实现由铸渊开发)
|
||
# 全部通过 → pr_needed=true
|
||
# 未通过 → 重试或标记失败
|
||
|
||
# Phase E+F 见下篇
|
||
```
|
||
|
||
---
|
||
|
||
## 九、时间窗口设计
|
||
|
||
```
|
||
23:00 CST — Phase A 启动(扫描 ~5分钟)
|
||
23:05 CST — Phase B 启动(分析 ~10分钟,取决于错误数量)
|
||
23:15 CST — Phase C 启动(修复 ~15分钟)
|
||
23:30 CST — Phase D 启动(审核 ~10分钟)
|
||
23:40 CST — Phase E 创建 PR
|
||
23:45 CST — Phase F 更新仪表盘
|
||
23:50 CST — 所有流程完成,系统进入休眠准备
|
||
|
||
总时间窗口:23:00 - 23:50(约50分钟)
|
||
留出安全余量到 00:00 休眠开始
|
||
```
|
||
|
||
<aside>
|
||
⏰
|
||
|
||
**与休眠系统的协调:** 夜间修复引擎在 23:00-23:50 运行,休眠系统 00:00 启动。两者不冲突。修复引擎属于「生命线任务」,即使触发延迟到 00:00 后也不受休眠影响。
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
<aside>
|
||
👇
|
||
|
||
**下篇预告:** Phase E(PR 创建流程)· Phase F(仪表盘更新机制)· Phase G(人类晨间审阅协议)· 仪表盘 UI 设计 · 回滚安全网 · Workflow 注册表 · 执行回执模板
|
||
|
||
</aside> |