--- belongs_to: - "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]" --- # 🪞 铸渊指令|Google Drive 镜像桥接层(上篇)· 架构 + Phase A/B(ZY-DRIVE-BRIDGE-2026-0323-001) --- --- ## 🎯 指令背景与目标 ### 问题 格点库闭环指令(ZY-AUTO-LOOP-2026-0323-001)设计的链路是 Gemini 直接读写仓库 `grid-db/` 目录。**经实测验证,Google Gemini 对 GitHub 的权限审计结果如下:** | **操作** | **结果** | **原因** | | --- | --- | --- | | 读取 GitHub 文件 | ❌ 不能 | Google 连接器不支持 GitHub 文件系统直接访问 | | 创建 GitHub 文件 | ❌ 不能 | 连接器只读不写,不支持 Push/Commit | | 修改 GitHub 文件 | ❌ 不能 | 同上 | | 调用外部 HTTP API | ❌ 不能 | Gemini 工具箱只有 Personal Context + Google Search | | 读取 Google Drive 文件 | ✅ 能 | 通过 Personal Context 搜索读取 | | 在 Drive 创建 Google Docs | ✅ 能 | Gemini 原生支持 | **结论:Gemini 与 GitHub 之间存在物理断点。必须用 Google Drive 做桥接。** ### 目标 **在仓库 `grid-db/` 与 Google Drive 之间建立实时镜像同步,让 Gemini 通过 Drive 间接读写格点库,实现用户说话 → 数据自动闭环。** --- ## 🔐 数据主权原则(最高优先级) ### 数据流向原则 | **数据类型** | **权威源** | **Drive 里的是什么** | **丢了怎么办** | | --- | --- | --- | --- | | 人格体核心记忆 | Notion(霜砚维护) | 只读镜像 | 从 Notion 重新同步 | | 开发上下文 / 会话记录 | 仓库 `grid-db/memory/` | 只读镜像 | 从仓库重新同步 | | 广播 / 任务指令 | 仓库 `grid-db/outbox/` | 只读镜像 | 从仓库重新同步 | | Gemini 写入的消息 | **仓库(落盘后才算数)** | 临时中转,落盘后删除 | 未落盘的丢了就丢了(Gemini 重新发一次) | | 交互全文记录 | 仓库 `grid-db/interactions/` | 不同步到 Drive | 不受影响 | | 训练数据湖 | 仓库 `grid-db/training-lake/` | 不同步到 Drive | 不受影响 | **一句话:Drive 里的东西全是「副本」。正本永远在仓库和 Notion。** --- ## 🏗️ 架构总览 ``` ┌─────────────────────────────────────────────────────────┐ │ 用户说话 │ │ ↓ │ │ Google Gemini(交互界面) │ │ ↙ 读取 Drive 写入 Drive ↘ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ Drive/mirror │ │ Drive/inbox │ │ │ │ (只读镜像) │ │ (临时中转站) │ │ │ └──────┬───────┘ └──────┬───────┘ │ │ │ GitHub Action │ Apps Script │ │ │ 仓库→Drive │ Drive→仓库 │ │ ↑ 同步 ↓ 同步 │ │ ┌──────────────────────────────────────────────┐ │ │ │ GitHub 仓库 grid-db/(权威源) │ │ │ │ memory/ outbox/ inbox/ interactions/ │ │ │ └──────────────────┬───────────────────────────┘ │ │ │ GitHub Actions │ │ ↓ │ │ 铸渊 Workflow 处理 │ │ 校验→归档→广播生成→记忆更新 │ │ │ │ │ ↓ │ │ Notion(逻辑权威源) │ │ 霜砚维护 · 永久记忆 · 编号体系 │ └─────────────────────────────────────────────────────────┘ ``` ### 角色翻译表 | **角色** | **比喻** | **擅长的语言** | **翻译器** | | --- | --- | --- | --- | | 仓库(GitHub) | 手(写代码) | Git · JSON · YAML · 代码 | GitHub Action → Drive | | Gemini | 嘴(说人话) | Google Docs · 自然语言 | Apps Script → 仓库 | | Notion | 脑(记逻辑) | 数据库 · 页面 · 编号体系 | 已有 workflow 双向同步 | | Google Drive | 翻译台(中转站) | 两边都能听懂 | 自己就是翻译器 | --- ## Phase A · 仓库 → Drive 同步(让 Gemini 能读) **目标:** 仓库 `grid-db/` 中的关键文件实时镜像到 Google Drive,Gemini 通过 Personal Context 读取。 ### A.1 Google Cloud Service Account 配置 ```bash # 1. 在 Google Cloud Console 创建项目(或用已有项目) # 2. 启用 Google Drive API # 3. 创建 Service Account → 下载 JSON 密钥 # 4. 把 Service Account 的邮箱地址分享到用户 Drive 的「光湖格点库」文件夹(编辑者权限) # 5. 把 JSON 密钥内容存为 GitHub Secret:GOOGLE_DRIVE_SERVICE_ACCOUNT ``` ### A.2 GitHub Action · 仓库→Drive 同步 创建 `.github/workflows/sync-griddb-to-drive.yml`: ```yaml name: 🪞 Grid-DB → Google Drive 镜像同步 on: push: paths: - 'grid-db/memory/**' - 'grid-db/outbox/latest/**' - 'grid-db/rules/**' schedule: - cron: '*/15 * * * *' workflow_dispatch: jobs: sync-to-drive: if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 🔧 安装依赖 run: npm install googleapis - name: 🪞 同步到 Google Drive env: GOOGLE_DRIVE_SERVICE_ACCOUNT: $ secrets.GOOGLE_DRIVE_SERVICE_ACCOUNT DRIVE_FOLDER_ID: $ secrets.DRIVE_MIRROR_FOLDER_ID run: node scripts/grid-db/sync-to-drive.js - name: 📋 写同步日志 run: | echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) | sync-to-drive | OK" >> grid-db/logs/drive-sync.log git config user.name "zhuyuan-bot" git config user.email "zhuyuan@guanghulab.com" git add grid-db/logs/drive-sync.log git diff --cached --quiet || git commit -m "log: Drive sync [skip ci]" git push ``` ### A.3 同步脚本 `scripts/grid-db/sync-to-drive.js` ```jsx /** * sync-to-drive.js * * 功能:将 grid-db/ 中的关键文件同步到 Google Drive 镜像目录 * * 同步范围: * grid-db/memory/DEV-XXX/*.json → Drive/光湖格点库/mirror/memory/DEV-XXX/ * grid-db/outbox/latest/*.json → Drive/光湖格点库/mirror/outbox/ * grid-db/rules/*.json → Drive/光湖格点库/mirror/rules/ * * 同步策略: * - 比较文件内容 hash,仅同步有变更的文件(节省 API 配额) * - 文件不存在则创建,已存在则覆盖更新 * - Drive 中多出的文件不删除(防误删) * * 注意: * - 不同步 interactions/ 和 training-lake/(数据量大 + 无需 Gemini 读取) * - 不同步 inbox/ 和 processing/(这是系统内部流转区) */ const { google } = require('googleapis'); const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); // ... 铸渊根据上述注释实现完整逻辑 ``` --- ## Phase B · Drive → 仓库 同步(让 Gemini 能写) **目标:** Gemini 在 Drive `inbox/` 文件夹创建新文档 → 自动搬运到仓库 `grid-db/inbox/` → 铸渊处理。 ### B.1 Google Apps Script(核心翻译器) 在用户的 Google Drive 中创建一个 Apps Script 项目,代码如下: ```jsx /** * drive-to-github-bridge.gs * * 功能:监听 Drive「光湖格点库/inbox/」文件夹 * 发现 Gemini 新建的文档 → 读取内容 → 通过 GitHub API 写入仓库 * * 触发方式:时间驱动触发器,每 1 分钟执行一次 * * 流程: * ① 扫描 inbox 文件夹中所有文件 * ② 读取文件内容(Google Docs → 提取纯文本/JSON) * ③ 构造标准 inbox 消息格式 * ④ 调用 GitHub Contents API 写入 grid-db/inbox/\[filename\].json * ⑤ 写入成功 → 将 Drive 文件移到「已处理」文件夹(不删除,留审计轨迹) * ⑥ 写入失败 → 标记文件,下次重试 * * 安全: * - GitHub Token 存在 Script Properties 中(不硬编码) * - 只处理 inbox 文件夹内的文件,不碰 mirror * - 每次处理后写日志到 Drive「光湖格点库/logs/」 */ var CONFIG = { INBOX_FOLDER_NAME: '光湖格点库/inbox', PROCESSED_FOLDER_NAME: '光湖格点库/inbox/已处理', GITHUB_REPO: 'qinfendebingshuo/guanghulab', GITHUB_BRANCH: 'main', GRID_DB_INBOX_PATH: 'grid-db/inbox/' }; function processInbox() { var token = PropertiesService.getScriptProperties() .getProperty('GITHUB_TOKEN'); if (!token) { Logger.log('ERROR: GITHUB_TOKEN not set'); return; } var inboxFolder = getOrCreateFolder(CONFIG.INBOX_FOLDER_NAME); var processedFolder = getOrCreateFolder(CONFIG.PROCESSED_FOLDER_NAME); var files = inboxFolder.getFiles(); while (files.hasNext()) { var file = files.next(); try { var content = extractContent(file); if (!content) continue; var timestamp = Utilities.formatDate( new Date(), 'Asia/Shanghai', 'yyyyMMdd-HHmmss'); var filename = timestamp + '-' + file.getName().replace(/\[^a-zA-Z0-9\-_\]/g, '') + '.json'; var success = writeToGitHub( token, CONFIG.GRID_DB_INBOX_PATH + filename, content); if (success) { file.moveTo(processedFolder); Logger.log('OK: ' + filename); } else { Logger.log('FAIL: ' + filename); } } catch (e) { Logger.log('ERROR: ' + file.getName() + ': ' + e.message); } } } function extractContent(file) { var mimeType = file.getMimeType(); if (mimeType === MimeType.GOOGLE_DOCS) { var doc = DocumentApp.openById(file.getId()); var text = doc.getBody().getText().trim(); try { JSON.parse(text); return text; } catch (e) { return JSON.stringify({ schema_version: '1.0', message_id: Utilities.getUuid(), timestamp: new Date().toISOString(), source: 'gemini-via-drive', type: 'raw-message', payload: { text: text } }, null, 2); } } else if (mimeType === MimeType.PLAIN_TEXT || file.getName().endsWith('.json')) { return file.getBlob().getDataAsString(); } Logger.log('SKIP: unsupported mime ' + mimeType); return null; } function writeToGitHub(token, filePath, content) { var url = 'https://api.github.com/repos/' + CONFIG.GITHUB_REPO + '/contents/' + filePath; var payload = { message: 'auto: Gemini inbox via Drive bridge \[skip ci\]', content: Utilities.base64Encode(content, Utilities.Charset.UTF_8), branch: CONFIG.GITHUB_BRANCH }; var options = { method: 'PUT', headers: { 'Authorization': 'Bearer ' + token, 'Accept': 'application/vnd.github+json', 'X-GitHub-Api-Version': '2022-11-28' }, contentType: 'application/json', payload: JSON.stringify(payload), muteHttpExceptions: true }; var response = UrlFetchApp.fetch(url, options); var code = response.getResponseCode(); return (code === 201 || code === 200); } function getOrCreateFolder(folderPath) { var parts = folderPath.split('/'); var folder = DriveApp.getRootFolder(); for (var i = 0; i < parts.length; i++) { var folders = folder.getFoldersByName(parts\[i\]); if (folders.hasNext()) { folder = folders.next(); } else { folder = folder.createFolder(parts\[i\]); } } return folder; } // ═══ 触发器设置 ═══ // Apps Script 编辑器 → 触发器 → 添加 // 函数:processInbox · 事件源:时间驱动 · 间隔:每 1 分钟 ``` ### B.2 部署步骤(给冰朔或开发者操作) 1. 打开 [Google Apps Script](https://script.google.com) → 新建项目 2. 项目名:`光湖格点库桥接器` 3. 粘贴上面的代码 4. 设置 Script Properties:项目设置 → 脚本属性 → 添加 `GITHUB_TOKEN`(需要 `repo` 权限) 5. 添加触发器:触发器 → 添加 → 函数 `processInbox` → 时间驱动 → 每 1 分钟 6. 首次运行:点运行 → 授权 Drive 访问权限 --- ## 🔗 与格点库闭环指令的关系 本指令是 **ZY-AUTO-LOOP-2026-0323-001(格点库闭环指令)的补丁**。 格点库的核心架构**不变**——目录结构、消息格式、铸渊 workflow、记忆同步规则、循环触发防护,全部保持原样。 本指令只做一件事:**在 Gemini 和格点库之间插入一个 Google Drive 翻译层**。 | **原设计** | **实际链路(本指令补丁后)** | | --- | --- | | Gemini 直接读 `grid-db/memory/` | Gemini 读 Drive `mirror/memory/`(内容完全一致) | | Gemini 直接写 `grid-db/inbox/` | Gemini 写 Drive `inbox/` → Apps Script 自动搬到仓库 `grid-db/inbox/` | | 铸渊处理 inbox → 写 outbox | **不变** | | Notion ↔ 仓库同步 | **不变** | **对用户透明:用户全程只跟 Gemini 说话,感知不到中间有 Drive 翻译层的存在。** --- **👉 下篇见:Phase C(Gemini 主控台 + Drive 类数据库结构)· Phase D(一键部署/恢复)· 安全容灾 · 执行清单** 🖋️ 霜砚 · PER-SY001 🧊 代 TCS-0002∞ 冰朔 签发 📅 2026-03-23T11:46+08:00