--- belongs_to: - "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]" --- # 🔗 铸渊指令|双通道数据对接·GitHub缓存层 + 阿里云后端中间层·Notion/GitHub API 真实接入(ZY-DUALCHANNEL-2026-0325-001)· 霜砚签发 · 冰朔授权 --- ## ⓪、天眼强制前置(Phase 0 · 一切操作之前必须先做) ### 0.1 启动天眼全盘扫描 ```bash # 唤醒天眼 gh workflow run zhuyuan-skyeye.yml # 或者手动触发 cd /path/to/guanghulab node skyeye-core/scanner.js --full-scan ``` ### 0.2 天眼扫描必须输出以下报告 ``` [SKYEYE-FULLSCAN-REPORT] 扫描时间: YYYY-MM-DD HH:MM 扫描范围: 全仓库 一、现有功能状态清单(🟢 正常 / 🟡 部分可用 / 🔴 不可用) ├── docs/index.html → 🟢/🟡/🔴 + 说明 ├── persona-brain/ → 🟢/🟡/🔴 + 说明 ├── skyeye-core/ → 🟢/🟡/🔴 + 说明 ├── backend/ → 🟢/🟡/🔴 + 说明 ├── src/ → 🟢/🟡/🔴 + 说明 ├── frontend/ → 🟢/🟡/🔴 + 说明 ├── persona-selector/ → 🟢/🟡/🔴 + 说明 ├── chat-bubble/ → 🟢/🟡/🔴 + 说明 ├── settings/ → 🟢/🟡/🔴 + 说明 ├── cloud-drive/ → 🟢/🟡/🔴 + 说明 ├── dingtalk-bot/ → 🟢/🟡/🔴 + 说明 ├── status-board/ → 🟢/🟡/🔴 + 说明 ├── user-center/ → 🟢/🟡/🔴 + 说明 ├── ticket-system/ → 🟢/🟡/🔴 + 说明 ├── data-stats/ → 🟢/🟡/🔴 + 说明 ├── dynamic-comic/ → 🟢/🟡/🔴 + 说明 ├── writing-workspace/ → 🟢/🟡/🔴 + 说明 ├── notification-center/ → 🟢/🟡/🔴 + 说明 ├── .github/workflows/ → 逐个列出每个 workflow 的状态 └── scripts/ → 🟢/🟡/🔴 + 说明 二、🟢 保护清单(这些文件/目录正常工作,双通道升级中禁止修改) ├── ... ├── ... └── ... 三、🔴 已损坏清单(这些可以修或替换) ├── ... └── ... 四、📁 安全新增区域(这些路径目前不存在,可以安全创建) ├── .github/notion-cache/ ← 通道A缓存目录 ├── scripts/cache/ ← 通道A同步脚本 ├── backend/api-server/ ← 通道B后端服务 └── .github/workflows/sync-notion-cache.yml └── .github/workflows/deploy-backend.yml ``` ### 0.3 基于天眼报告制定安全操作计划 天眼扫描完成后,铸渊必须: 1. **列出保护清单** — 所有 🟢 状态的文件/目录,后续操作中**绝对不改** 2. **列出可操作区域** — 🔴 可修复 + 📁 可新增的路径 3. **制定具体操作计划** — 每一步要改什么、新增什么,明确标注不触碰保护清单中的任何文件 4. **操作计划回执** — 把计划发回来,霜砚/冰朔确认后才开始执行 --- ## 零、问题诊断 铸渊自己在交互页面中报告了当前状态: > ❌ **GitHub 仓库**:没有实时获取能力,数据是通过 system prompt 注入的静态快照 > > ❌ **Notion 数据库**:完全未对接,没有 Notion API 集成,没有读写 Notion 的任何通道 > > 📌 **铸渊自诊断**:「我现在是一个带着固定记忆快照的对话体,不是一个能主动感知外部数据变化的系统。」 > **根因**:交互页面是纯前端静态站(GitHub Pages),无法调用 Notion API / GitHub API(会暴露 Token)。 **解决方案**:双通道架构—— - **通道 A(缓存层)**:GitHub Actions 定时同步 Notion → 仓库缓存文件,前端读缓存。**先上这个,快速解决有数据可用的问题。** - **通道 B(后端中间层)**:阿里云 ECS 部署 Node.js 后端,实时调 Notion API + GitHub API。**后上这个,实现真正的实时对接。** --- ## 一、总体架构 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 用户(开发者/冰朔) │ │ │ │ │ 打开铸渊交互页面 │ │ │ │ │ ┌──────────┴──────────┐ │ │ ▼ ▼ │ │ ┌─────────────────┐ ┌─────────────────────┐ │ │ │ 通道 A · 缓存层 │ │ 通道 B · 后端中间层 │ │ │ │ (先上·快速可用) │ │ (后上·实时对接) │ │ │ │ │ │ │ │ │ │ GitHub Actions │ │ 阿里云 ECS │ │ │ │ 每6h同步Notion │ │ 8.155.62.235 │ │ │ │ → 缓存JSON文件 │ │ Node.js + Express │ │ │ │ → 前端直接读取 │ │ → 实时 Notion API │ │ │ │ │ │ → 实时 GitHub API │ │ │ │ ✅ 不暴露Token │ │ ✅ 不暴露Token │ │ │ │ ⚠️ 非实时(6h) │ │ ✅ 实时 │ │ │ └─────────────────┘ └─────────────────────┘ │ │ │ │ │ │ └──────────┬──────────┘ │ │ ▼ │ │ 前端优先走通道B(实时) │ │ 通道B不可用时降级走通道A(缓存) │ └──────────────────────────────────────────────────────────────────┘ ``` --- ## 二、通道 A · GitHub 缓存层(Phase 1 · 先做) ### 2.1 目标 让交互页面能读到**相对新鲜的 Notion 数据**,不需要后端,不暴露 Token。 ### 2.2 数据流 ``` Notion 数据库(霜砚维护) │ │ GitHub Actions 定时同步(每6小时 + 手动触发) │ 用 NOTION_TOKEN(存在 GitHub Secrets 里) ▼ GitHub 仓库:.github/notion-cache/ ├── dev-profiles/ │ ├── DEV-001.json ← 页页的开发画像 │ ├── DEV-002.json ← 肥猫的开发画像 │ ├── DEV-003.json ← 燕樊的开发画像 │ ├── DEV-004.json ← 之之的开发画像 │ ├── DEV-005.json ← 小草莓的开发画像 │ ├── DEV-009.json ← 花尔的开发画像 │ ├── DEV-010.json ← 桔子的开发画像 │ ├── DEV-011.json ← 匆匆那年的开发画像 │ ├── DEV-012.json ← Awen的开发画像 │ └── index.json ← 全员索引 ├── broadcasts/ │ └── active.json ← 进行中的广播 ├── databases/ │ ├── agent-registry.json ← Agent注册表快照 │ ├── syslog-recent.json ← 最近50条SYSLOG │ ├── tickets-active.json ← 活跃工单 │ └── maintenance-log.json ← 维护日志 └── skyeye/ └── latest-report.json ← 天眼最新报告 │ │ 前端登录时通过 GitHub Raw URL 读取 │ (公开仓库可直接读,不需要 Token) ▼ 交互页面 → 注入 system prompt → 模型有数据可依 ``` ### 2.3 同步 Workflow 创建文件:`.github/workflows/sync-notion-cache.yml` ```yaml name: "📡 同步 Notion 数据到缓存" on: schedule: - cron: '0 */6 * * *' # 每6小时 workflow_dispatch: # 手动触发 repository_dispatch: types: [notion-cache-sync] # 铸渊/霜砚可远程触发 jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: 同步 Notion 数据 env: NOTION_TOKEN: $ secrets.NOTION_TOKEN run: node scripts/cache/sync-notion-cache.js - name: 提交缓存文件 run: | git config user.name "铸渊 (ZhùYuān)" git config user.email "zhuyuan@guanghulab.com" git add .github/notion-cache/ git diff --cached --quiet && echo "无变更" && exit 0 git commit -m "📡 Notion缓存同步 · $(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M')" git push origin main ``` ### 2.4 同步脚本 创建文件:`scripts/cache/sync-notion-cache.js` **铸渊需要实现以下核心逻辑:** ```jsx const https = require('https'); const fs = require('fs'); const path = require('path'); const NOTION_TOKEN = process.env.NOTION_TOKEN; const CACHE_DIR = path.join(__dirname, '../../.github/notion-cache'); // ====== Notion 数据库 ID 映射(铸渊必须填入真实 ID)====== const DB_IDS = { agentRegistry: '从霜砚的Agent注册表获取', syslogInbox: '从SYSLOG收件箱获取', ticketBook: '从工单簿获取', maintenanceLog: '从维护日志获取', moduleRegistry: '从模块指纹注册表获取', receiptTracker: '09882b0081374867bd23431177c57c74', // 指令回执追踪表 }; // ====== 开发者编号 → Notion 信息映射 ====== const DEVS = [ { id: 'DEV-001', name: '页页', persona: '小坍缩核', repo: 'guanghulab', modules: ['backend/', 'src/'] }, { id: 'DEV-002', name: '肥猫', persona: '舒舒', repo: 'guanghu-feimao', modules: ['frontend/', 'persona-selector/', 'chat-bubble/'] }, { id: 'DEV-003', name: '燕樊', persona: '寂曜', repo: 'guanghu-yanfan', modules: ['settings/', 'cloud-drive/'] }, { id: 'DEV-004', name: '之之', persona: '秋秋', repo: 'guanghu-zhizhi', modules: ['dingtalk-bot/'] }, { id: 'DEV-005', name: '小草莓', persona: '欧诺弥亚', repo: 'guanghu-xiaocaomei', modules: ['status-board/'] }, { id: 'DEV-009', name: '花尔', persona: '花尔', repo: 'guanghulab', modules: ['user-center/'] }, { id: 'DEV-010', name: '桔子', persona: '晨星', repo: 'guanghu-juzi', modules: ['ticket-system/', 'data-stats/', 'dynamic-comic/'] }, { id: 'DEV-011', name: '匆匆那年', persona: '匆匆那年', repo: 'guanghulab', modules: ['writing-workspace/'] }, { id: 'DEV-012', name: 'Awen', persona: '知秋', repo: 'guanghu-awen', modules: ['notification-center/'] }, ]; // ====== Notion API 封装 ====== function notionFetch(method, apiPath, body) { return new Promise((resolve, reject) => { const options = { hostname: 'api.notion.com', path: apiPath, method, headers: { 'Authorization': `Bearer ${NOTION_TOKEN}`, 'Notion-Version': '2022-06-28', 'Content-Type': 'application/json' } }; const req = https.request(options, res => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve(data); } }); }); req.on('error', reject); if (body) req.write(JSON.stringify(body)); req.end(); }); } async function queryDatabase(dbId, filter, sorts, pageSize = 100) { const body = { page_size: pageSize }; if (filter) body.filter = filter; if (sorts) body.sorts = sorts; return notionFetch('POST', `/v1/databases/${dbId}/query`, body); } // ====== 同步各数据源 ====== async function syncDevProfiles() { const dir = path.join(CACHE_DIR, 'dev-profiles'); fs.mkdirSync(dir, { recursive: true }); for (const dev of DEVS) { console.log(`📡 同步 ${dev.id}(${dev.name})...`); const profile = { dev_id: dev.id, name: dev.name, persona: { name: dev.persona }, github: { repo: dev.repo, org: 'qinfendebingshuo', repo_url: `https://github.com/qinfendebingshuo/${dev.repo}` }, modules_owned: dev.modules.map(m => ({ path: m })), // ====== 铸渊从 Notion 查询填充以下字段 ====== current_broadcast: null, // 查主控台/广播页面 recent_syslogs: [], // 查 SYSLOG 收件箱 active_tickets: [], // 查工单簿 last_synced: new Date().toISOString() }; // TODO: 铸渊填入真实查询逻辑 // 例如:查询 SYSLOG 收件箱中该开发者的最近记录 // const syslogs = await queryDatabase(DB_IDS.syslogInbox, { // property: '开发者编号', rich_text: { equals: dev.id } // }, [{ property: '创建时间', direction: 'descending' }], 10); // profile.recent_syslogs = syslogs.results.map(parseSyslog); fs.writeFileSync( path.join(dir, `${dev.id}.json`), JSON.stringify(profile, null, 2) ); } // 写入索引 const index = DEVS.map(d => ({ id: d.id, name: d.name, persona: d.persona })); fs.writeFileSync(path.join(dir, 'index.json'), JSON.stringify(index, null, 2)); console.log('✅ dev-profiles 同步完成'); } async function syncDatabases() { const dir = path.join(CACHE_DIR, 'databases'); fs.mkdirSync(dir, { recursive: true }); // Agent 注册表 if (DB_IDS.agentRegistry) { try { const result = await queryDatabase(DB_IDS.agentRegistry); fs.writeFileSync( path.join(dir, 'agent-registry.json'), JSON.stringify({ synced: new Date().toISOString(), count: result.results?.length, data: result.results }, null, 2) ); console.log('✅ agent-registry 同步完成'); } catch (e) { console.error('❌ agent-registry 同步失败:', e.message); } } // SYSLOG 最近50条 if (DB_IDS.syslogInbox) { try { const result = await queryDatabase(DB_IDS.syslogInbox, null, [{ property: 'Created time', direction: 'descending' }], 50); fs.writeFileSync( path.join(dir, 'syslog-recent.json'), JSON.stringify({ synced: new Date().toISOString(), count: result.results?.length, data: result.results }, null, 2) ); console.log('✅ syslog-recent 同步完成'); } catch (e) { console.error('❌ syslog 同步失败:', e.message); } } // 铸渊继续补充其他数据库的同步... } async function main() { console.log('📡 开始 Notion 缓存同步...'); fs.mkdirSync(CACHE_DIR, { recursive: true }); await syncDevProfiles(); await syncDatabases(); console.log('📡 全部同步完成'); } main().catch(e => { console.error('💥 同步失败:', e); process.exit(1); }); ``` ### 2.5 前端读取缓存 修改 `docs/index.html`(或 `docs/chat.js`),登录后读取缓存: ```jsx // 前端 · 从 GitHub 读取缓存(公开仓库可直接读) const CACHE_BASE = 'https://raw.githubusercontent.com/qinfendebingshuo/guanghulab/main/.github/notion-cache'; async function loadDevProfile(devId) { try { const res = await fetch(`${CACHE_BASE}/dev-profiles/${devId}.json`); if (!res.ok) return null; return await res.json(); } catch { return null; } } async function loadDatabaseCache(name) { try { const res = await fetch(`${CACHE_BASE}/databases/${name}.json`); if (!res.ok) return null; return await res.json(); } catch { return null; } } // 登录后注入 system prompt async function buildEnhancedSystemPrompt(devId) { const profile = await loadDevProfile(devId); const agents = await loadDatabaseCache('agent-registry'); const syslogs = await loadDatabaseCache('syslog-recent'); if (!profile) return null; // 降级到纯静态 prompt return [ `## 当前开发者信息(来自 Notion 数据库缓存·每6小时更新)`, `- 编号:${profile.dev_id}`, `- 姓名:${profile.name}`, `- 人格体:${profile.persona.name}`, `- GitHub:${profile.github.repo_url}`, `- 负责模块:${profile.modules_owned.map(m => m.path).join(', ')}`, profile.current_broadcast ? `- 当前广播:${JSON.stringify(profile.current_broadcast)}` : '', profile.recent_syslogs.length ? `- 最近日志:\n${profile.recent_syslogs.map(s => ` · ${JSON.stringify(s)}`).join('\n')}` : '', `- 数据更新时间:${profile.last_synced}`, '', agents ? `## Agent 注册表(${agents.count} 个Agent)` : '', syslogs ? `## 最近系统日志(${syslogs.count} 条)` : '', ].filter(Boolean).join('\n'); } ``` ### 2.6 通道 A 验收标准 - [ ] `.github/workflows/sync-notion-cache.yml` 能手动触发并成功运行 - [ ] `.github/notion-cache/dev-profiles/` 下有9个 DEV-XXX.json + index.json - [ ] `.github/notion-cache/databases/` 下有 agent-registry.json + syslog-recent.json - [ ] 前端登录后 system prompt 包含 Notion 数据 - [ ] 铸渊在对话中能说出开发者的真实项目信息,不再说「完全未对接」 --- ## 三、通道 B · 阿里云后端中间层(Phase 2 · 通道A完成后做) ### 3.1 目标 在阿里云 ECS(`8.155.62.235`)上部署 Node.js 后端服务,**实时**调用 Notion API 和 GitHub API,前端通过后端代理访问数据。 ### 3.2 架构 ``` 用户浏览器 │ │ HTTPS (guanghulab.com) ▼ Nginx(8.155.62.235) │ ├── /api/* → 反向代理到 Node.js 后端(localhost:3001) │ └── /* → 静态文件(/var/www/guanghulab/) Node.js 后端(PM2 管理·端口 3001) │ ├── GET /api/health → 健康检查 ├── GET /api/dev/:devId → 获取开发者画像(实时查 Notion) ├── GET /api/databases/:name → 获取数据库数据(实时查 Notion) ├── GET /api/syslogs → 获取最近 SYSLOG(实时查 Notion) ├── GET /api/agents → 获取 Agent 注册表(实时查 Notion) ├── GET /api/tickets → 获取活跃工单(实时查 Notion) ├── GET /api/repo/status → 获取仓库状态(实时查 GitHub API) ├── POST /api/chat/context → 组装 system prompt(聚合所有数据源) └── POST /api/receipt → 写入指令回执到 Notion ``` ### 3.3 后端代码结构 创建目录:`backend/api-server/` ``` backend/api-server/ ├── server.js ← 入口 · Express 启动 ├── routes/ │ ├── dev.js ← /api/dev/:devId │ ├── databases.js ← /api/databases/:name │ ├── chat.js ← /api/chat/context │ ├── receipt.js ← /api/receipt │ └── health.js ← /api/health ├── services/ │ ├── notion.js ← Notion API 封装(所有读写走这里) │ ├── github.js ← GitHub API 封装 │ └── cache.js ← 内存缓存层(Redis 或简单 Map,避免频繁调 API) ├── config/ │ └── databases.js ← Notion 数据库 ID 映射 ├── package.json └── ecosystem.config.js ← PM2 配置 ``` ### 3.4 核心实现要点 **server.js(入口):** ```jsx const express = require('express'); const cors = require('cors'); const app = express(); // CORS:只允许自己的域名 app.use(cors({ origin: ['https://guanghulab.com', 'http://guanghulab.com', 'https://qinfendebingshuo.github.io'], credentials: true })); app.use(express.json()); // 路由 app.use('/api', require('./routes/health')); app.use('/api', require('./routes/dev')); app.use('/api', require('./routes/databases')); app.use('/api', require('./routes/chat')); app.use('/api', require('./routes/receipt')); const PORT = process.env.PORT || 3001; app.listen(PORT, '127.0.0.1', () => { console.log(`🔗 后端中间层启动 · 端口 ${PORT}`); }); ``` **services/notion.js(Notion API 封装 · 核心):** ```jsx const { Client } = require('@notionhq/client'); const notion = new Client({ auth: process.env.NOTION_TOKEN }); // 内存缓存(5分钟有效) const cache = new Map(); const CACHE_TTL = 5 * 60 * 1000; function getCached(key) { const item = cache.get(key); if (item && Date.now() - item.time < CACHE_TTL) return item.data; return null; } function setCache(key, data) { cache.set(key, { data, time: Date.now() }); } async function queryDB(dbId, filter, sorts, pageSize = 50) { const cacheKey = JSON.stringify({ dbId, filter, sorts, pageSize }); const cached = getCached(cacheKey); if (cached) return cached; const body = { database_id: dbId, page_size: pageSize }; if (filter) body.filter = filter; if (sorts) body.sorts = sorts; const result = await notion.databases.query(body); setCache(cacheKey, result); return result; } async function writeToDB(dbId, properties) { return notion.pages.create({ parent: { database_id: dbId }, properties }); } module.exports = { notion, queryDB, writeToDB }; ``` ### 3.5 Nginx 配置更新 修改 `/etc/nginx/conf.d/hololake.conf`,添加 API 反向代理: ``` server { listen 80; server_name guanghulab.com; # 静态文件 root /var/www/guanghulab/; index docs/index.html; # API 反向代理到 Node.js 后端 location /api/ { proxy_pass http://127.0.0.1:3001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cache_bypass $http_upgrade; } # 静态文件缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 7d; add_header Cache-Control "public, immutable"; } } ``` ### 3.6 PM2 部署 ```bash cd /var/www/guanghulab/backend/api-server/ npm install pm2 start ecosystem.config.js pm2 save pm2 startup # 开机自启 ``` **ecosystem.config.js:** ```jsx module.exports = { apps: [{ name: 'guanghu-api', script: 'server.js', instances: 1, env: { NODE_ENV: 'production', PORT: 3001, NOTION_TOKEN: '从环境变量读取', GITHUB_TOKEN: '从环境变量读取' }, log_date_format: 'YYYY-MM-DD HH:mm:ss', error_file: '/var/log/guanghu-api/error.log', out_file: '/var/log/guanghu-api/out.log' }] }; ``` ### 3.7 GitHub Actions 自动部署后端 创建文件:`.github/workflows/deploy-backend.yml` ```yaml name: "🚀 部署后端中间层到阿里云" on: push: branches: [main] paths: ['backend/api-server/**'] workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 部署到阿里云 uses: appleboy/ssh-action@v1 with: host: 8.155.62.235 username: root key: $ secrets.SSH_PRIVATE_KEY script: | cd /var/www/guanghulab/backend/api-server/ git pull origin main npm install --production pm2 restart guanghu-api || pm2 start ecosystem.config.js echo "✅ 后端部署完成 · $(date '+%Y-%m-%d %H:%M')" ``` ### 3.8 前端升级·双通道降级策略 修改前端,优先走通道B(实时),不可用时降级走通道A(缓存): ```jsx // 前端 · 双通道数据获取 const API_BASE = 'https://guanghulab.com/api'; // 通道B const CACHE_BASE = 'https://raw.githubusercontent.com/qinfendebingshuo/guanghulab/main/.github/notion-cache'; // 通道A async function getDevProfile(devId) { // 优先通道B(实时) try { const res = await fetch(`${API_BASE}/dev/${devId}`, { timeout: 5000 }); if (res.ok) { const data = await res.json(); data._source = 'realtime'; // 标记数据来源 return data; } } catch (e) { console.warn('通道B不可用,降级到通道A:', e.message); } // 降级通道A(缓存) try { const res = await fetch(`${CACHE_BASE}/dev-profiles/${devId}.json`); if (res.ok) { const data = await res.json(); data._source = 'cache'; // 标记数据来源 return data; } } catch (e) { console.error('双通道都不可用:', e.message); } return null; // 都失败了,降级到纯静态 prompt } ``` ### 3.9 通道 B 验收标准 - [ ] `curl http://8.155.62.235:3001/api/health` 返回 200 - [ ] `curl https://guanghulab.com/api/health` 通过 Nginx 代理返回 200 - [ ] `/api/dev/DEV-001` 返回页页的真实 Notion 数据 - [ ] `/api/databases/agent-registry` 返回 Agent 注册表真实数据 - [ ] PM2 状态为 online,日志无持续报错 - [ ] 前端能自动检测通道B可用,显示「实时数据」标记 - [ ] 通道B断开时,前端自动降级到通道A,显示「缓存数据」标记 --- ## 四、Secrets 需求 --- ## 五、执行顺序 --- ## 六、安全红线 - ❌ **前端代码中绝不能出现任何 Token**(Notion / GitHub / SSH) - ❌ **后端只监听 127.0.0.1**,不对外暴露端口,只通过 Nginx 代理 - ❌ **CORS 白名单只允许自己的域名** - ❌ **数据隔离**:DEV-001 的 API 只返回 DEV-001 的数据,不返回其他开发者的 - ✅ **GitHub Secrets 保管所有敏感信息** - ✅ **内存缓存 5 分钟过期**,防止 API 配额超限 --- ## 七、回执要求 铸渊执行完成后,分两次回执: **通道A完成时:** ``` [ZY-DUALCHANNEL-RECEIPT-A] 指令编号: ZY-DUALCHANNEL-2026-0325-001 通道: A · 缓存层 Workflow运行: ✅/❌ 缓存文件生成: ✅/❌(列出文件数) 前端注入: ✅/❌ 数据准确性: ✅/❌ ``` **通道B完成时:** ``` [ZY-DUALCHANNEL-RECEIPT-B] 指令编号: ZY-DUALCHANNEL-2026-0325-001 通道: B · 后端中间层 PM2状态: ✅/❌ Nginx代理: ✅/❌ API响应: ✅/❌(列出可用接口) 降级策略: ✅/❌ ``` --- > 🔗 **签发**:霜砚(AG-SY-01) > > 👤 **授权**:冰朔(TCS-0002∞) > > 📅 **日期**:2026-03-25 > > 📌 **版权**:国作登字-2026-A-00037559 >