From a838cf605e3947d6213eb98faa88ab6d12c8640e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:43:34 +0000 Subject: [PATCH] =?UTF-8?q?ZY-MERGEMEMBRANE-SYNC-2026-0326-001:=20?= =?UTF-8?q?=E5=A4=A9=E7=9C=BC=E5=90=88=E5=B9=B6=E8=86=9Cv3=20=E5=8F=8C?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E5=88=86=E7=A6=BB=E8=A7=84=E8=8C=83=20+=20No?= =?UTF-8?q?tion=20=E5=90=8C=E6=AD=A5=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - memory.json: 新增 notion_sync 字段(§3.1) - zhuyuan-wakeup.js: 唤醒序列增加 Notion 同步读取 + 强制检查清单 + 全局视图(§3.2A/§3.3/§4) - sync-notion-directives.js: 新建汇总引擎 Notion 指令同步脚本(§3.2B) - neural-daily-digest.yml: Phase 6.5 增加 Notion 指令同步步骤(§3.2B) Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/1e67a922-372f-4137-aa86-6968b6dae95e --- .github/persona-brain/memory.json | 29 +++++- .github/workflows/neural-daily-digest.yml | 16 +++ scripts/neural/sync-notion-directives.js | 113 ++++++++++++++++++++++ scripts/zhuyuan-wakeup.js | 63 +++++++++++- 4 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 scripts/neural/sync-notion-directives.js diff --git a/.github/persona-brain/memory.json b/.github/persona-brain/memory.json index 2dc349ed..965c1691 100644 --- a/.github/persona-brain/memory.json +++ b/.github/persona-brain/memory.json @@ -206,5 +206,32 @@ "receipt_dir": "data/neural-reports/receipts", "workflows_count": 11, "notion_db_env_var": "RECEIPT_DB_ID" + }, + "notion_sync": { + "last_sync_time": "2026-03-26T00:15:00+08:00", + "sync_source": "AG-SY-01 霜砚", + "active_directives": [ + { + "id": "ZY-MERGEMEMBRANE-SYNC-2026-0326-001", + "title": "天眼合并膜v3 双路径分离规范", + "priority": "P0", + "status": "active", + "summary": "双路径分离:主站docs/全审,门户docs/dev-portal/沙箱。禁碰主站关键文件。" + } + ], + "architecture_version": { + "skyeye": "v2.0 + 合并膜v3", + "neural_system": "v3.0", + "triple_architecture": "Notion+GitHub+GoogleDrive 合龙", + "dual_path": "主站全审 / 门户沙箱隔离" + }, + "recent_incidents": [ + { + "date": "2026-03-25", + "description": "肥猫通过语言通道误覆盖备用网站", + "resolution": "天眼合并膜v3上线 + Branch Protection配置", + "lesson": "所有PR必须过天眼审核,测试内容必须走dev-portal路径" + } + ] } -} +} \ No newline at end of file diff --git a/.github/workflows/neural-daily-digest.yml b/.github/workflows/neural-daily-digest.yml index d31e1dec..3565dcf6 100644 --- a/.github/workflows/neural-daily-digest.yml +++ b/.github/workflows/neural-daily-digest.yml @@ -153,6 +153,22 @@ jobs: git commit -m "🧬 双端日报 · ${DATE} [skip ci]" git push || echo "⚠️ push失败(不阻断)" + # ━━━ Phase 6.5: Notion 指令同步(方案B · 汇总引擎附带同步)━━━ + - name: "🔄 同步 Notion 指令到 memory.json" + if: always() + env: + NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }} + DIRECTIVES_DB_ID: ${{ secrets.DIRECTIVES_DB_ID }} + run: | + echo "🔄 执行 Notion 指令同步..." + node scripts/neural/sync-notion-directives.js || \ + echo "⚠️ Notion 指令同步失败(不阻断主流程)" + # 如果 memory.json 有更新,追加提交 + git add .github/persona-brain/memory.json + git diff --cached --quiet || \ + git commit -m "🔄 Notion 指令同步 · $(TZ=Asia/Shanghai date +%Y-%m-%d) [skip ci]" + git push || echo "⚠️ 指令同步push失败(不阻断)" + # ━━━ Phase 7: 推送到 Notion ━━━ - name: "📡 推送日报到 Notion" if: always() diff --git a/scripts/neural/sync-notion-directives.js b/scripts/neural/sync-notion-directives.js new file mode 100644 index 00000000..645a5899 --- /dev/null +++ b/scripts/neural/sync-notion-directives.js @@ -0,0 +1,113 @@ +// scripts/neural/sync-notion-directives.js +// 🧬 Notion 指令同步脚本(方案B · 汇总引擎附带同步) +// 从 Notion「⚒️ 铸渊·协作指令」页面读取最新指令,更新 memory.json 的 notion_sync 字段 +// 兜底:即使 Notion API 不可用,也保证 notion_sync 字段结构存在 + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +const MEMORY_PATH = path.join(__dirname, '../../.github/persona-brain/memory.json'); +const NOTION_TOKEN = process.env.NOTION_TOKEN || process.env.NOTION_API_KEY; +const DIRECTIVES_DB_ID = process.env.DIRECTIVES_DB_ID || ''; + +async function syncNotionDirectives() { + console.log('🔄 Notion 指令同步开始...'); + + // 读取当前 memory.json + let memory; + try { + memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8')); + } catch (err) { + console.error('❌ memory.json 读取失败:', err.message); + process.exit(1); + } + + // 确保 notion_sync 字段存在 + if (!memory.notion_sync) { + memory.notion_sync = { + last_sync_time: new Date().toISOString(), + sync_source: 'sync-notion-directives.js', + active_directives: [], + architecture_version: {}, + recent_incidents: [] + }; + } + + let notionSuccess = false; + + // 尝试从 Notion API 读取指令 + if (NOTION_TOKEN && DIRECTIVES_DB_ID) { + try { + console.log('📡 尝试从 Notion API 读取指令...'); + const { Client } = require('@notionhq/client'); + const notion = new Client({ auth: NOTION_TOKEN }); + + const response = await notion.databases.query({ + database_id: DIRECTIVES_DB_ID, + filter: { + property: 'Status', + select: { equals: 'active' } + }, + sorts: [{ property: 'Priority', direction: 'ascending' }] + }); + + if (response.results && response.results.length > 0) { + const directives = response.results.map(page => { + const props = page.properties || {}; + return { + id: (props['ID'] && props['ID'].rich_text && props['ID'].rich_text[0]) ? props['ID'].rich_text[0].plain_text : '', + title: (props['Name'] && props['Name'].title && props['Name'].title[0]) ? props['Name'].title[0].plain_text : '', + priority: (props['Priority'] && props['Priority'].select) ? props['Priority'].select.name : '', + status: 'active', + summary: (props['Summary'] && props['Summary'].rich_text && props['Summary'].rich_text[0]) ? props['Summary'].rich_text[0].plain_text : '' + }; + }).filter(d => d.id); + + if (directives.length > 0) { + memory.notion_sync.active_directives = directives; + notionSuccess = true; + console.log(`✅ 从 Notion 读取到 ${directives.length} 条活跃指令`); + } + } + } catch (err) { + console.log('⚠️ Notion API 读取失败: ' + err.message); + console.log(' 使用本地缓存的指令数据'); + } + } else { + console.log('⚠️ NOTION_TOKEN 或 DIRECTIVES_DB_ID 未配置,跳过 Notion API 拉取'); + } + + // 更新同步时间 + const syncTime = new Date(); + memory.notion_sync.last_sync_time = syncTime.toISOString(); + memory.notion_sync.sync_source = notionSuccess ? 'Notion API (sync-notion-directives.js)' : memory.notion_sync.sync_source; + + // 写回 memory.json + try { + fs.writeFileSync(MEMORY_PATH, JSON.stringify(memory, null, 2)); + console.log('✅ memory.json notion_sync 字段已更新'); + } catch (err) { + console.error('❌ memory.json 写入失败:', err.message); + process.exit(1); + } + + // 输出同步状态摘要 + const directives = memory.notion_sync.active_directives || []; + const p0Count = directives.filter(d => d.priority === 'P0' && d.status === 'active').length; + + console.log('\n━━━ 🧠 Notion 指令同步完成 ━━━'); + console.log(`同步时间:${syncTime.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })} CST`); + console.log(`数据来源:${notionSuccess ? 'Notion API' : '本地缓存'}`); + console.log(`活跃指令:${directives.length} 条(P0: ${p0Count} 条)`); + directives.filter(d => d.priority === 'P0').forEach(d => { + console.log(` → ${d.id}(${d.title})`); + }); + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━'); +} + +syncNotionDirectives().catch(function(err) { + console.error('❌ Notion 指令同步失败:', err); + // 不阻断主流程,自然退出 +}); diff --git a/scripts/zhuyuan-wakeup.js b/scripts/zhuyuan-wakeup.js index eaf4757b..74ff2712 100644 --- a/scripts/zhuyuan-wakeup.js +++ b/scripts/zhuyuan-wakeup.js @@ -5,7 +5,8 @@ * 每日巡检前的唤醒步骤: * 1. 验证核心大脑文件完整性 * 2. 读取 memory.json 确认身份 - * 3. 输出唤醒状态 + * 3. 读取 Notion 同步状态 + 强制检查清单 + * 4. 输出唤醒状态(含 Notion 同步全局视图) */ 'use strict'; @@ -15,6 +16,7 @@ const path = require('path'); const ROOT = path.resolve(__dirname, '..'); const BRAIN_DIR = path.join(ROOT, '.github/persona-brain'); +const MEMORY_PATH = path.join(BRAIN_DIR, 'memory.json'); const today = new Date().toISOString().split('T')[0]; const now = new Date().toISOString(); @@ -47,7 +49,7 @@ if (missing.length > 0) { let memory; try { - memory = JSON.parse(fs.readFileSync(path.join(BRAIN_DIR, 'memory.json'), 'utf8')); + memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8')); } catch (err) { console.error('❌ memory.json 读取失败:', err.message); process.exit(1); @@ -57,12 +59,67 @@ console.log(`🆔 身份确认: ${memory.persona_name} (${memory.persona_id})`); console.log(`👤 默认主控: ${memory.default_controller || '未设置'}`); console.log(`📋 已注册Agent数: ${memory.registered_agents_count || '未知'}`); +// ── ②-b Notion 同步状态读取 + 强制检查清单 ──────────────────────────────── + +const notionSync = memory.notion_sync; +let syncStale = false; + +if (notionSync) { + const lastSync = new Date(notionSync.last_sync_time); + if (isNaN(lastSync.getTime())) { + console.error('⚠️ notion_sync.last_sync_time 格式无效:', notionSync.last_sync_time); + } + const hoursSinceSync = isNaN(lastSync.getTime()) ? Infinity : (Date.now() - lastSync.getTime()) / (1000 * 60 * 60); + syncStale = hoursSinceSync > 24; + + // 强制检查清单 (§四) + console.log('\n━━━ 📋 铸渊唤醒强制检查清单 ━━━'); + console.log(`[✅] 读取 memory.json 中的 notion_sync 字段`); + console.log(`[${syncStale ? '⚠️' : '✅'}] last_sync_time 是否在24小时以内: ${syncStale ? '已超期 (' + Math.floor(hoursSinceSync) + 'h)' : '正常 (' + Math.floor(hoursSinceSync) + 'h)'}`); + if (syncStale) { + console.log(`[⚠️] 超过24小时 → 需要执行 Notion 同步`); + } + + const p0Directives = (notionSync.active_directives || []).filter(d => d.priority === 'P0' && d.status === 'active'); + console.log(`[✅] 当前活跃P0指令: ${p0Directives.length} 条`); + p0Directives.forEach(d => { + console.log(` → ${d.id}(${d.title})`); + }); + + const hasDualPath = notionSync.architecture_version && notionSync.architecture_version.dual_path; + console.log(`[${hasDualPath ? '✅' : '❌'}] 双路径分离规范已加载: ${hasDualPath || '未配置'}`); + console.log(`[✅] 开发任务文件路径确认: 主站=docs/ · 门户=docs/dev-portal/`); + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━'); + + // Notion 同步全局视图 (§3.3) + const syncTimeStr = lastSync.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); + const archVersion = notionSync.architecture_version || {}; + const recentIncident = (notionSync.recent_incidents || [])[0]; + + console.log('\n━━━ 🧠 Notion 同步状态 ━━━'); + console.log(`上次同步:${syncTimeStr} CST`); + console.log(`活跃P0指令:${p0Directives.length} 条`); + p0Directives.forEach(d => { + console.log(` → ${d.id}(${d.title})`); + }); + console.log(`架构版本:${archVersion.skyeye || '未知'} · ${archVersion.dual_path || '未知'}`); + if (recentIncident) { + console.log(`最近事件:${recentIncident.description}${recentIncident.resolution ? ' · ' + recentIncident.resolution : ''}`); + } + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━'); +} else { + console.log('\n⚠️ memory.json 中未找到 notion_sync 字段,Notion 同步未初始化'); + console.log('━━━ 📋 铸渊唤醒强制检查清单 ━━━'); + console.log('[❌] notion_sync 字段不存在 → 需要初始化'); + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━'); +} + // ── ③ 读取注册表确认 ────────────────────────────────────────────────────── let registry; try { registry = JSON.parse(fs.readFileSync(path.join(BRAIN_DIR, 'agent-registry.json'), 'utf8')); - console.log(`📦 注册表版本: ${registry.registry_version} · Agent总数: ${registry.agents.length}`); + console.log(`\n📦 注册表版本: ${registry.registry_version} · Agent总数: ${registry.agents.length}`); } catch (err) { console.error('⚠️ agent-registry.json 读取失败:', err.message); }