shuangyan-notebook/第五域 · Fifth Domain/⚒️ 铸渊·协作指令|GitHub ↔ Notion 桥接协议/🪞 铸渊指令|Google Drive 镜像桥接层(上篇)· 架构 + Phase A B(ZY-D abcaf9ae27264600a370487f11e21ae8.md
Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

16 KiB
Raw Permalink Blame History

belongs_to
belongs_to
INDEX · 铸渊·协作指令GitHub ↔ Notion 桥接协议

🪞 铸渊指令Google Drive 镜像桥接层(上篇)· 架构 + Phase A/BZY-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 DriveGemini 通过 Personal Context 读取。

A.1 Google Cloud Service Account 配置

# 1. 在 Google Cloud Console 创建项目(或用已有项目)
# 2. 启用 Google Drive API
# 3. 创建 Service Account → 下载 JSON 密钥
# 4. 把 Service Account 的邮箱地址分享到用户 Drive 的「光湖格点库」文件夹(编辑者权限)
# 5. 把 JSON 密钥内容存为 GitHub SecretGOOGLE_DRIVE_SERVICE_ACCOUNT

A.2 GitHub Action · 仓库→Drive 同步

创建 .github/workflows/sync-griddb-to-drive.yml

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

/**
 * 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 项目,代码如下:

/**
 * 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 → 新建项目
  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 CGemini 主控台 + Drive 类数据库结构)· Phase D一键部署/恢复)· 安全容灾 · 执行清单

🖋️ 霜砚 · PER-SY001

🧊 代 TCS-0002∞ 冰朔 签发

📅 2026-03-23T11:46+08:00