ZY-MERGEMEMBRANE-SYNC-2026-0326-001: 天眼合并膜v3 双路径分离规范 + Notion 同步机制
- 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
This commit is contained in:
parent
ef9f3c2c1a
commit
a838cf605e
|
|
@ -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路径"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
// 不阻断主流程,自然退出
|
||||
});
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue