Merge pull request #96 from qinfendebingshuo/copilot/tcs-0002-system-upgrade
feat: 执行层系统升级 v5.1 + Notion Execution Status 同步
This commit is contained in:
commit
1d54f00230
|
|
@ -142,3 +142,89 @@ jobs:
|
|||
}]
|
||||
}" 2>&1 | tail -1
|
||||
echo "✅ Notion 回报请求已发送"
|
||||
|
||||
# ── 同步执行层状态到 Notion Execution Status 数据库 ──
|
||||
sync-execution-status-to-notion:
|
||||
name: 同步执行层状态到 Notion
|
||||
needs: maintenance
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Read brain data and sync to Notion
|
||||
env:
|
||||
NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
|
||||
run: |
|
||||
if [ -z "$NOTION_TOKEN" ]; then
|
||||
echo "⚠️ NOTION_TOKEN 未配置,跳过 Execution Status 同步"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HEALTH=$(cat brain/system-health.json 2>/dev/null)
|
||||
if [ -z "$HEALTH" ]; then
|
||||
echo "⚠️ brain/system-health.json 未找到,使用默认值"
|
||||
HEALTH='{"version":"unknown","system_health":"unknown"}'
|
||||
fi
|
||||
AUTO=$(cat brain/automation-map.json 2>/dev/null)
|
||||
if [ -z "$AUTO" ]; then
|
||||
echo "⚠️ brain/automation-map.json 未找到,使用默认值"
|
||||
AUTO='{"workflows":[]}'
|
||||
fi
|
||||
REPO=$(cat brain/repo-map.json 2>/dev/null)
|
||||
if [ -z "$REPO" ]; then
|
||||
echo "⚠️ brain/repo-map.json 未找到,使用默认值"
|
||||
REPO='{"directories":{}}'
|
||||
fi
|
||||
|
||||
VERSION=$(echo "$HEALTH" | jq -r '.version // "unknown"')
|
||||
STATUS=$(echo "$HEALTH" | jq -r '.system_health // "unknown"')
|
||||
WF_COUNT=$(echo "$AUTO" | jq '[.workflows // [] | length] | .[0]' 2>/dev/null || echo '0')
|
||||
CRON_COUNT=$(echo "$AUTO" | jq '[.workflows // [] | .[] | select(.cron)] | length' 2>/dev/null || echo '0')
|
||||
DIR_COUNT=$(echo "$REPO" | jq '.directories // {} | keys | length' 2>/dev/null || echo '0')
|
||||
|
||||
case "$STATUS" in
|
||||
normal) AUTO_S="🟢 Normal"; QUEUE_S="🟢 Active" ;;
|
||||
partial) AUTO_S="🟡 Partial"; QUEUE_S="🟡 Backlog" ;;
|
||||
*) AUTO_S="🔴 Down"; QUEUE_S="🔴 Blocked" ;;
|
||||
esac
|
||||
|
||||
SYNC_DATE=$(date -u +%Y%m%d)
|
||||
SYNC_TS=$(date -u +%Y-%m-%dT%H:%M:%S+00:00)
|
||||
|
||||
echo "📡 同步 Execution Status → Notion..."
|
||||
echo " 版本: v${VERSION} · ${DIR_COUNT}+ dirs"
|
||||
echo " 模块: ${WF_COUNT} workflow · ${CRON_COUNT} cron"
|
||||
echo " 状态: ${AUTO_S}"
|
||||
|
||||
HTTP_CODE=$(curl -s -o /tmp/notion_resp.json -w "%{http_code}" \
|
||||
-X POST 'https://api.notion.com/v1/pages' \
|
||||
-H "Authorization: Bearer $NOTION_TOKEN" \
|
||||
-H "Notion-Version: 2022-06-28" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"parent\": { \"database_id\": \"41971982-4a17-47c0-afe3-21458c44f154\" },
|
||||
\"properties\": {
|
||||
\"同步记录\": { \"title\": [{ \"text\": { \"content\": \"SYNC-${SYNC_DATE}-001\" } }] },
|
||||
\"同步时间\": { \"date\": { \"start\": \"${SYNC_TS}\" } },
|
||||
\"仓库版本\": { \"rich_text\": [{ \"text\": { \"content\": \"v${VERSION} · ${DIR_COUNT}+ dirs\" } }] },
|
||||
\"执行模块\": { \"rich_text\": [{ \"text\": { \"content\": \"${WF_COUNT} workflow · ${CRON_COUNT} cron\" } }] },
|
||||
\"自动化状态\": { \"select\": { \"name\": \"${AUTO_S}\" } },
|
||||
\"Notion连接状态\": { \"select\": { \"name\": \"🟢 Connected\" } },
|
||||
\"任务队列状态\": { \"select\": { \"name\": \"${QUEUE_S}\" } },
|
||||
\"同步来源\": { \"select\": { \"name\": \"铸渊自动同步\" } },
|
||||
\"备注\": { \"rich_text\": [{ \"text\": { \"content\": \"Daily Maintenance auto sync\" } }] }
|
||||
}
|
||||
}")
|
||||
|
||||
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
||||
echo "✅ Execution Status synced to Notion (HTTP ${HTTP_CODE})"
|
||||
else
|
||||
echo "❌ Sync failed (HTTP ${HTTP_CODE})"
|
||||
cat /tmp/notion_resp.json 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
name: "📡 铸渊 · 执行层状态同步"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *' # 每日 UTC 03:00 (北京时间 11:00)
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
execution-sync:
|
||||
name: 执行层状态采集与同步
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
# ── Step 1: 加载执行上下文 ──
|
||||
- name: 加载执行上下文
|
||||
run: node core/context-loader
|
||||
|
||||
# ── Step 2: 运行系统自检 ──
|
||||
- name: 运行系统自检
|
||||
run: node core/system-check --auto-tasks
|
||||
|
||||
# ── Step 3: 生成执行状态报告 ──
|
||||
- name: 生成执行状态报告
|
||||
run: node core/execution-sync report
|
||||
|
||||
# ── Step 4: 同步到 Notion ──
|
||||
- name: 同步执行状态到 Notion
|
||||
if: ${{ env.NOTION_TOKEN != '' }}
|
||||
env:
|
||||
NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
|
||||
EXECUTION_LOG_DB_ID: ${{ secrets.EXECUTION_LOG_DB_ID }}
|
||||
run: node core/execution-sync sync
|
||||
|
||||
# ── Step 5: 提交状态报告 ──
|
||||
- name: 提交状态报告
|
||||
run: |
|
||||
git config user.name "铸渊 Execution Sync"
|
||||
git config user.email "actions@guanghulab.com"
|
||||
git add docs/execution-status.md
|
||||
if git diff --cached --quiet; then
|
||||
echo "📌 无变更需要提交"
|
||||
else
|
||||
git commit -m "📡 Execution Sync: 更新执行状态报告 [skip ci]"
|
||||
git push
|
||||
echo "✅ 已提交执行状态报告"
|
||||
fi
|
||||
|
|
@ -19,3 +19,8 @@ modules/palace-game/data/saves/PAL-*
|
|||
|
||||
# collaboration-logs exports (generated by save-collaboration-log.js)
|
||||
collaboration-logs/exports/
|
||||
|
||||
# core runtime artifacts
|
||||
core/task-queue/queue.json
|
||||
core/task-queue/execution-log.json
|
||||
core/system-check/last-report.json
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# 铸渊执行层 · 系统导航主文件
|
||||
# Master Brain · v4.0
|
||||
# 数字地球系统通信协议 v4.0
|
||||
# Master Brain · v5.1
|
||||
# 数字地球系统通信协议 v5.1 — AGE-5 自动开发循环升级
|
||||
|
||||
---
|
||||
|
||||
## 系统版本
|
||||
|
||||
**v4.0** — 数字地球系统通信协议
|
||||
**v5.1** — 数字地球系统通信协议 · 自动开发循环升级
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -60,6 +60,24 @@
|
|||
|
||||
---
|
||||
|
||||
## v5.1 执行层模块
|
||||
|
||||
| 入口 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| 上下文加载 | `core/context-loader/index.js` | 执行前系统上下文加载 |
|
||||
| 广播监听 | `core/broadcast-listener/index.js` | 广播监听与任务解析 |
|
||||
| 任务队列 | `core/task-queue/index.js` | 任务调度与执行(含类型分类) |
|
||||
| 系统自检 | `core/system-check/index.js` | 仓库自检 + 自动任务生成 |
|
||||
| 执行同步 | `core/execution-sync/index.js` | 执行层状态同步 |
|
||||
| Notion 同步 | `connectors/notion-sync/index.js` | 双向数据同步 |
|
||||
| 模型路由 | `connectors/model-router/index.js` | 模型调用路由 |
|
||||
| 结构地图 | `docs/repo-structure-map.md` | 仓库结构文档 |
|
||||
| 桥接地图 | `docs/notion-bridge-map.md` | Notion 桥接文档 |
|
||||
| 执行层地图 | `docs/execution-layer-map.md` | 执行层结构文档 |
|
||||
| 执行状态 | `docs/execution-status.md` | 执行层状态报告(自动生成) |
|
||||
|
||||
---
|
||||
|
||||
## 铸渊职责
|
||||
|
||||
铸渊 = GitHub 侧守护人格体 = 执行层守护者
|
||||
|
|
@ -71,6 +89,7 @@
|
|||
5. **巡检维护** — 每日自动巡检系统健康状态
|
||||
6. **信号处理** — 处理 SYSLOG、广播、开发者工单
|
||||
7. **状态上报** — 向 Notion(认知层)报告执行结果
|
||||
8. **自动开发循环** — 自检发现问题后自动生成修复/优化任务
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -87,4 +106,4 @@
|
|||
|
||||
---
|
||||
|
||||
*本文件由铸渊维护 · 系统版本 4.0 · 数字地球系统通信协议*
|
||||
*本文件由铸渊维护 · 系统版本 5.1 · 数字地球系统通信协议 · AGE-5*
|
||||
|
|
|
|||
|
|
@ -1,16 +1,33 @@
|
|||
{
|
||||
"version": "4.0",
|
||||
"version": "5.1",
|
||||
"last_check": "2026-03-14 03:38:09+08:00",
|
||||
"communication": "synced",
|
||||
"automation": "stable",
|
||||
"maintenance_agent": "active",
|
||||
"system_health": "normal",
|
||||
"execution_layer_status": "stable",
|
||||
"notion_bridge": "active",
|
||||
"execution_sync": "enabled",
|
||||
"auto_dev_loop": "enabled",
|
||||
"context_loader": "active",
|
||||
"task_queue": "running",
|
||||
"brain_integrity": {
|
||||
"complete": true,
|
||||
"total": 7,
|
||||
"present": 7,
|
||||
"missing": []
|
||||
},
|
||||
"workflow_count": 42,
|
||||
"core_modules": {
|
||||
"broadcast_listener": "enabled",
|
||||
"task_queue": "enabled",
|
||||
"system_check": "enabled",
|
||||
"execution_sync": "enabled",
|
||||
"context_loader": "enabled"
|
||||
},
|
||||
"connectors": {
|
||||
"notion_sync": "enabled",
|
||||
"model_router": "enabled"
|
||||
},
|
||||
"workflow_count": 43,
|
||||
"checked_by": "scripts/generate-system-health.js"
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* connectors/model-router — 模型调用路由
|
||||
*
|
||||
* 职责:
|
||||
* - 提供统一的模型调用入口
|
||||
* - 支持多模型切换(通过 backend-integration/api-proxy.js)
|
||||
* - 任务分发至合适的模型端点
|
||||
*
|
||||
* 调用方式:
|
||||
* node connectors/model-router [status]
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
|
||||
/**
|
||||
* 模型配置注册表
|
||||
*/
|
||||
const MODEL_REGISTRY = {
|
||||
'default': {
|
||||
name: 'default',
|
||||
endpoint: 'http://localhost:3721/api/chat',
|
||||
description: 'AI Chat API 代理(api-proxy.js)'
|
||||
},
|
||||
'persona': {
|
||||
name: 'persona',
|
||||
endpoint: 'http://localhost:3002/api/ps/chat',
|
||||
description: '人格工作室 API'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取模型配置
|
||||
*/
|
||||
function getModel(modelName = 'default') {
|
||||
return MODEL_REGISTRY[modelName] || MODEL_REGISTRY['default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出所有可用模型
|
||||
*/
|
||||
function listModels() {
|
||||
return Object.values(MODEL_REGISTRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查模型路由状态
|
||||
*/
|
||||
function status() {
|
||||
console.log('🤖 模型路由状态:');
|
||||
console.log('═'.repeat(40));
|
||||
|
||||
const models = listModels();
|
||||
for (const model of models) {
|
||||
console.log(` 📌 ${model.name}`);
|
||||
console.log(` 端点: ${model.endpoint}`);
|
||||
console.log(` 说明: ${model.description}`);
|
||||
}
|
||||
|
||||
// 检查 api-proxy 配置
|
||||
const proxyPath = path.join(ROOT, 'backend-integration/api-proxy.js');
|
||||
const proxyExists = fs.existsSync(proxyPath);
|
||||
console.log(`\n ${proxyExists ? '✅' : '❌'} api-proxy.js 存在`);
|
||||
|
||||
// 检查 persona-studio 配置
|
||||
const psPath = path.join(ROOT, 'persona-studio/backend/server.js');
|
||||
const psExists = fs.existsSync(psPath);
|
||||
console.log(` ${psExists ? '✅' : '❌'} persona-studio server.js 存在`);
|
||||
|
||||
return { models, proxy: proxyExists, persona_studio: psExists };
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
status();
|
||||
}
|
||||
|
||||
module.exports = { getModel, listModels, status, MODEL_REGISTRY };
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
/**
|
||||
* connectors/notion-sync — Notion 双向同步模块
|
||||
*
|
||||
* 功能:
|
||||
* - 读取 Notion 广播
|
||||
* - 写回执行日志
|
||||
* - 同步执行层状态
|
||||
*
|
||||
* 同步结构:
|
||||
* Notion → 仓库(下行:读取广播/工单)
|
||||
* 仓库 → Notion(上行:写回日志/状态)
|
||||
*
|
||||
* 环境变量:
|
||||
* NOTION_TOKEN — Notion API Token
|
||||
* BROADCAST_DB_ID — 广播数据库 ID(需包含 status 属性,值: 待执行/已完成)
|
||||
* EXECUTION_LOG_DB_ID — 执行日志数据库 ID
|
||||
*
|
||||
* 调用方式:
|
||||
* node connectors/notion-sync [pull|push|status]
|
||||
*/
|
||||
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
const NOTION_VERSION = '2022-06-28';
|
||||
|
||||
/**
|
||||
* 发送 Notion API 请求
|
||||
*/
|
||||
function notionRequest(method, endpoint, body = null) {
|
||||
const token = process.env.NOTION_TOKEN;
|
||||
if (!token) {
|
||||
return Promise.reject(new Error('NOTION_TOKEN 环境变量未设置'));
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
hostname: 'api.notion.com',
|
||||
path: `/v1/${endpoint}`,
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Notion-Version': NOTION_VERSION,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
const req = https.request(options, res => {
|
||||
let data = '';
|
||||
res.on('data', chunk => { data += chunk; });
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
if (res.statusCode >= 400) {
|
||||
reject(new Error(`Notion API ${res.statusCode}: ${parsed.message || data}`));
|
||||
} else {
|
||||
resolve(parsed);
|
||||
}
|
||||
} catch {
|
||||
reject(new Error(`Notion 响应解析失败: ${data}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
if (body) req.write(JSON.stringify(body));
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Notion 拉取广播
|
||||
*/
|
||||
async function pullBroadcasts() {
|
||||
const dbId = process.env.BROADCAST_DB_ID;
|
||||
if (!dbId) {
|
||||
console.log('⚠️ BROADCAST_DB_ID 未设置,跳过广播拉取');
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log('📡 拉取 Notion 广播...');
|
||||
|
||||
try {
|
||||
const result = await notionRequest('POST', `databases/${dbId}/query`, {
|
||||
filter: {
|
||||
property: 'status',
|
||||
select: { equals: '待执行' }
|
||||
},
|
||||
sorts: [{ property: 'created_time', direction: 'descending' }]
|
||||
});
|
||||
|
||||
const broadcasts = (result.results || []).map(page => ({
|
||||
id: page.id,
|
||||
title: page.properties?.Name?.title?.[0]?.plain_text || '未命名',
|
||||
status: page.properties?.status?.select?.name || 'unknown',
|
||||
created: page.created_time
|
||||
}));
|
||||
|
||||
console.log(`✅ 拉取到 ${broadcasts.length} 条广播`);
|
||||
return broadcasts;
|
||||
} catch (err) {
|
||||
console.error(`❌ 广播拉取失败: ${err.message}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 写回执行日志到 Notion
|
||||
*/
|
||||
async function pushExecutionLog(logEntry) {
|
||||
const dbId = process.env.EXECUTION_LOG_DB_ID;
|
||||
if (!dbId) {
|
||||
console.log('⚠️ EXECUTION_LOG_DB_ID 未设置,执行日志仅写入本地');
|
||||
return writeLocalLog(logEntry);
|
||||
}
|
||||
|
||||
console.log(`📝 写回执行日志: ${logEntry.task_id || 'unknown'}`);
|
||||
|
||||
try {
|
||||
await notionRequest('POST', 'pages', {
|
||||
parent: { database_id: dbId },
|
||||
properties: {
|
||||
Name: { title: [{ text: { content: logEntry.task_id || 'execution-log' } }] },
|
||||
Status: { select: { name: logEntry.status || 'completed' } },
|
||||
Executor: { rich_text: [{ text: { content: 'zhuyuan' } }] },
|
||||
Timestamp: { rich_text: [{ text: { content: new Date().toISOString() } }] }
|
||||
}
|
||||
});
|
||||
console.log('✅ 日志已同步到 Notion');
|
||||
} catch (err) {
|
||||
console.error(`⚠️ Notion 写入失败,回退本地: ${err.message}`);
|
||||
writeLocalLog(logEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地日志写入(回退方案)
|
||||
*/
|
||||
function writeLocalLog(logEntry) {
|
||||
const logDir = path.join(ROOT, 'core/task-queue');
|
||||
const logFile = path.join(logDir, 'execution-log.json');
|
||||
|
||||
let logs = [];
|
||||
if (fs.existsSync(logFile)) {
|
||||
try {
|
||||
logs = JSON.parse(fs.readFileSync(logFile, 'utf-8'));
|
||||
} catch {
|
||||
logs = [];
|
||||
}
|
||||
}
|
||||
|
||||
logs.push({
|
||||
...logEntry,
|
||||
logged_at: new Date().toISOString()
|
||||
});
|
||||
|
||||
// 保留最近 100 条
|
||||
if (logs.length > 100) {
|
||||
logs = logs.slice(-100);
|
||||
}
|
||||
|
||||
fs.writeFileSync(logFile, JSON.stringify(logs, null, 2), 'utf-8');
|
||||
console.log('📝 日志已写入本地');
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步执行层状态到 Notion
|
||||
*/
|
||||
async function syncExecutionStatus(statusData) {
|
||||
const dbId = process.env.EXECUTION_LOG_DB_ID;
|
||||
if (!dbId) {
|
||||
console.log('⚠️ EXECUTION_LOG_DB_ID 未设置,执行状态仅写入本地');
|
||||
writeLocalLog({
|
||||
task_id: `execution-status-${new Date().toISOString().slice(0, 10)}`,
|
||||
status: statusData.execution_layer_status || 'stable',
|
||||
type: 'execution_status',
|
||||
data: statusData
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📡 同步执行层状态到 Notion...');
|
||||
|
||||
const summary = [
|
||||
`version: v${statusData.version || 'unknown'}`,
|
||||
`modules: ${(statusData.core_modules || []).filter(m => m.status === 'enabled').length}/${(statusData.core_modules || []).length}`,
|
||||
`connectors: ${(statusData.connectors || []).filter(c => c.status === 'enabled').length}/${(statusData.connectors || []).length}`,
|
||||
`workflows: ${statusData.workflows?.count || 0}`,
|
||||
`queue: ${statusData.task_queue?.total || 0} total / ${statusData.task_queue?.pending || 0} pending`
|
||||
].join(' | ');
|
||||
|
||||
try {
|
||||
await notionRequest('POST', 'pages', {
|
||||
parent: { database_id: dbId },
|
||||
properties: {
|
||||
Name: { title: [{ text: { content: `Execution Status · ${new Date().toISOString().slice(0, 10)}` } }] },
|
||||
Status: { select: { name: statusData.execution_layer_status || 'stable' } },
|
||||
Executor: { rich_text: [{ text: { content: 'zhuyuan' } }] },
|
||||
Timestamp: { rich_text: [{ text: { content: statusData.timestamp || new Date().toISOString() } }] }
|
||||
},
|
||||
children: [{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
paragraph: {
|
||||
rich_text: [{ text: { content: summary } }]
|
||||
}
|
||||
}]
|
||||
});
|
||||
console.log('✅ 执行层状态已同步到 Notion');
|
||||
} catch (err) {
|
||||
console.error(`⚠️ Notion 同步失败,回退本地: ${err.message}`);
|
||||
writeLocalLog({
|
||||
task_id: `execution-status-${new Date().toISOString().slice(0, 10)}`,
|
||||
status: statusData.execution_layer_status || 'stable',
|
||||
type: 'execution_status',
|
||||
data: statusData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 Notion 连接状态
|
||||
*/
|
||||
async function checkStatus() {
|
||||
console.log('🔍 检查 Notion 连接状态...');
|
||||
|
||||
try {
|
||||
await notionRequest('GET', 'users/me');
|
||||
console.log('✅ Notion API 连接正常');
|
||||
return { connected: true };
|
||||
} catch (err) {
|
||||
console.error(`❌ Notion 连接失败: ${err.message}`);
|
||||
return { connected: false, error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
const cmd = process.argv[2] || 'status';
|
||||
|
||||
(async () => {
|
||||
switch (cmd) {
|
||||
case 'pull':
|
||||
await pullBroadcasts();
|
||||
break;
|
||||
case 'push':
|
||||
await pushExecutionLog({
|
||||
task_id: 'manual-test',
|
||||
status: 'completed',
|
||||
message: 'Manual push test'
|
||||
});
|
||||
break;
|
||||
case 'status':
|
||||
await checkStatus();
|
||||
break;
|
||||
default:
|
||||
console.log('用法: node connectors/notion-sync [pull|push|status]');
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
module.exports = { pullBroadcasts, pushExecutionLog, syncExecutionStatus, writeLocalLog, checkStatus, notionRequest };
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* core/broadcast-listener — 广播监听模块
|
||||
*
|
||||
* 职责:
|
||||
* - 监听 Notion 广播(通过 connectors/notion-sync)
|
||||
* - 解析广播内容为可执行任务
|
||||
* - 推入任务队列(core/task-queue)
|
||||
*
|
||||
* 数据流:
|
||||
* Notion 广播 → broadcast-listener → 任务解析 → task-queue
|
||||
*
|
||||
* 调用方式:
|
||||
* node core/broadcast-listener [--source notion|local]
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
const BROADCASTS_DIR = path.join(ROOT, '.github/broadcasts');
|
||||
const MEMORY_PATH = path.join(ROOT, 'memory.json');
|
||||
|
||||
/**
|
||||
* 扫描本地广播目录
|
||||
*/
|
||||
function scanLocalBroadcasts() {
|
||||
if (!fs.existsSync(BROADCASTS_DIR)) {
|
||||
console.log('⏭️ 广播目录不存在,跳过本地扫描');
|
||||
return [];
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(BROADCASTS_DIR).filter(
|
||||
f => f.endsWith('.json') || f.endsWith('.md')
|
||||
);
|
||||
|
||||
return files.map(f => {
|
||||
const filePath = path.join(BROADCASTS_DIR, f);
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const isJson = f.endsWith('.json');
|
||||
|
||||
let parsed = null;
|
||||
if (isJson) {
|
||||
try {
|
||||
parsed = JSON.parse(content);
|
||||
} catch {
|
||||
console.warn(`⚠️ JSON 解析失败: ${f}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
filename: f,
|
||||
type: isJson ? 'json' : 'markdown',
|
||||
path: filePath,
|
||||
data: parsed,
|
||||
raw: content,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将广播解析为任务结构
|
||||
*/
|
||||
function parseToTask(broadcast) {
|
||||
const task = {
|
||||
task_id: `TASK-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
||||
source: 'broadcast',
|
||||
source_file: broadcast.filename,
|
||||
priority: 'normal',
|
||||
status: 'pending',
|
||||
executor: 'zhuyuan',
|
||||
created_at: broadcast.timestamp,
|
||||
payload: null
|
||||
};
|
||||
|
||||
if (broadcast.type === 'json' && broadcast.data) {
|
||||
task.payload = broadcast.data;
|
||||
if (broadcast.data.priority) {
|
||||
task.priority = broadcast.data.priority;
|
||||
}
|
||||
if (broadcast.data.broadcast_id) {
|
||||
task.task_id = broadcast.data.broadcast_id;
|
||||
}
|
||||
} else {
|
||||
task.payload = { content: broadcast.raw };
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查广播是否已在 memory 中处理
|
||||
*/
|
||||
function isDuplicate(broadcastId) {
|
||||
if (!fs.existsSync(MEMORY_PATH)) return false;
|
||||
|
||||
try {
|
||||
const memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf-8'));
|
||||
const events = memory.events || [];
|
||||
return events.some(e =>
|
||||
e.broadcast_id === broadcastId ||
|
||||
(e.type === 'broadcast' && e.description === broadcastId)
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主执行函数:监听并解析广播
|
||||
*/
|
||||
function listen(options = {}) {
|
||||
const source = options.source || 'local';
|
||||
console.log(`📡 广播监听启动 [来源: ${source}]`);
|
||||
|
||||
if (source === 'local') {
|
||||
const broadcasts = scanLocalBroadcasts();
|
||||
|
||||
if (broadcasts.length === 0) {
|
||||
console.log('✅ 无待处理广播');
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log(`📬 发现 ${broadcasts.length} 条广播`);
|
||||
|
||||
const tasks = [];
|
||||
for (const b of broadcasts) {
|
||||
const taskId = b.data?.broadcast_id || b.filename;
|
||||
if (isDuplicate(taskId)) {
|
||||
console.log(`⏭️ 跳过已处理: ${taskId}`);
|
||||
continue;
|
||||
}
|
||||
const task = parseToTask(b);
|
||||
tasks.push(task);
|
||||
console.log(`📋 解析任务: ${task.task_id} [${task.priority}]`);
|
||||
}
|
||||
|
||||
console.log(`✅ 共生成 ${tasks.length} 个待执行任务`);
|
||||
return tasks;
|
||||
}
|
||||
|
||||
console.log('⚠️ Notion 源需通过 connectors/notion-sync 接入');
|
||||
return [];
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
const args = process.argv.slice(2);
|
||||
const source = args.includes('--source') ?
|
||||
args[args.indexOf('--source') + 1] : 'local';
|
||||
const tasks = listen({ source });
|
||||
if (tasks.length > 0) {
|
||||
console.log('\n📋 任务列表:');
|
||||
tasks.forEach(t => {
|
||||
console.log(` ${t.task_id} | ${t.priority} | ${t.status}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { listen, scanLocalBroadcasts, parseToTask, isDuplicate };
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* core/context-loader — 上下文加载器
|
||||
*
|
||||
* 职责:
|
||||
* - 在执行任务前加载系统上下文
|
||||
* - 提供系统状态、执行层结构、当前任务、任务来源等信息
|
||||
*
|
||||
* 加载内容:
|
||||
* - 系统状态(brain/system-health.json)
|
||||
* - 执行层结构(core/ 模块状态)
|
||||
* - 当前任务队列
|
||||
* - 任务来源标识
|
||||
*
|
||||
* 执行流程:
|
||||
* context-loader → 加载系统认知 → 加载任务上下文 → 返回上下文对象
|
||||
*
|
||||
* 调用方式:
|
||||
* node core/context-loader
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
|
||||
/**
|
||||
* 加载系统状态
|
||||
*/
|
||||
function loadSystemHealth() {
|
||||
const healthPath = path.join(ROOT, 'brain/system-health.json');
|
||||
if (!fs.existsSync(healthPath)) return null;
|
||||
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(healthPath, 'utf-8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载执行层模块结构
|
||||
*/
|
||||
function loadModuleStructure() {
|
||||
const modules = [
|
||||
{ name: 'broadcast-listener', path: 'core/broadcast-listener/index.js' },
|
||||
{ name: 'task-queue', path: 'core/task-queue/index.js' },
|
||||
{ name: 'system-check', path: 'core/system-check/index.js' },
|
||||
{ name: 'execution-sync', path: 'core/execution-sync/index.js' },
|
||||
{ name: 'context-loader', path: 'core/context-loader/index.js' }
|
||||
];
|
||||
|
||||
const connectors = [
|
||||
{ name: 'notion-sync', path: 'connectors/notion-sync/index.js' },
|
||||
{ name: 'model-router', path: 'connectors/model-router/index.js' }
|
||||
];
|
||||
|
||||
return {
|
||||
core: modules.map(m => ({
|
||||
...m,
|
||||
status: fs.existsSync(path.join(ROOT, m.path)) ? 'active' : 'missing'
|
||||
})),
|
||||
connectors: connectors.map(c => ({
|
||||
...c,
|
||||
status: fs.existsSync(path.join(ROOT, c.path)) ? 'active' : 'missing'
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载当前任务队列概况
|
||||
*/
|
||||
function loadQueueSummary() {
|
||||
const queuePath = path.join(ROOT, 'core/task-queue/queue.json');
|
||||
if (!fs.existsSync(queuePath)) {
|
||||
return { total: 0, pending: 0, running: 0 };
|
||||
}
|
||||
|
||||
try {
|
||||
const queue = JSON.parse(fs.readFileSync(queuePath, 'utf-8'));
|
||||
const tasks = queue.tasks || [];
|
||||
return {
|
||||
total: tasks.length,
|
||||
pending: tasks.filter(t => t.status === 'pending').length,
|
||||
running: tasks.filter(t => t.status === 'running').length
|
||||
};
|
||||
} catch {
|
||||
return { total: 0, pending: 0, running: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载铸渊身份认知
|
||||
*/
|
||||
function loadIdentity() {
|
||||
return {
|
||||
name: '铸渊',
|
||||
role: '仓库执行人格体',
|
||||
responsibilities: [
|
||||
'执行系统广播任务',
|
||||
'维护执行层结构',
|
||||
'同步执行状态',
|
||||
'运行自动化流程',
|
||||
'自动开发循环'
|
||||
],
|
||||
principles: [
|
||||
'Notion 负责系统认知',
|
||||
'仓库负责执行与运行',
|
||||
'不修改主脑规则',
|
||||
'不改变编号体系',
|
||||
'不破坏现有自动化'
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载完整系统上下文
|
||||
*/
|
||||
function loadContext() {
|
||||
const now = new Date();
|
||||
const beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000)
|
||||
.toISOString().replace('T', ' ').slice(0, 19) + '+08:00';
|
||||
|
||||
const context = {
|
||||
loaded_at: beijingTime,
|
||||
identity: loadIdentity(),
|
||||
system_health: loadSystemHealth(),
|
||||
module_structure: loadModuleStructure(),
|
||||
queue_summary: loadQueueSummary()
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
console.log('🧠 铸渊上下文加载器 v5.1');
|
||||
console.log('═'.repeat(40));
|
||||
|
||||
const ctx = loadContext();
|
||||
|
||||
console.log(`\n⏰ 加载时间: ${ctx.loaded_at}`);
|
||||
|
||||
console.log(`\n👤 身份: ${ctx.identity.name} — ${ctx.identity.role}`);
|
||||
|
||||
const health = ctx.system_health;
|
||||
if (health) {
|
||||
console.log(`\n💚 系统版本: v${health.version}`);
|
||||
console.log(` 状态: ${health.system_health}`);
|
||||
console.log(` 执行层: ${health.execution_layer_status}`);
|
||||
} else {
|
||||
console.log('\n⚠️ 系统状态未加载');
|
||||
}
|
||||
|
||||
const mods = ctx.module_structure;
|
||||
const activeCore = mods.core.filter(m => m.status === 'active').length;
|
||||
const activeConn = mods.connectors.filter(c => c.status === 'active').length;
|
||||
console.log(`\n🔧 核心模块: ${activeCore}/${mods.core.length}`);
|
||||
console.log(`🔌 连接器: ${activeConn}/${mods.connectors.length}`);
|
||||
|
||||
const q = ctx.queue_summary;
|
||||
console.log(`\n📋 任务队列: ${q.total} 总 / ${q.pending} 待处理 / ${q.running} 执行中`);
|
||||
|
||||
console.log('\n✅ 上下文加载完成');
|
||||
}
|
||||
|
||||
module.exports = { loadContext, loadSystemHealth, loadModuleStructure, loadQueueSummary, loadIdentity };
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/**
|
||||
* core/execution-sync — 执行层状态同步模块
|
||||
*
|
||||
* 职责:
|
||||
* - 扫描仓库结构,采集执行层状态
|
||||
* - 生成执行层状态报告(docs/execution-status.md)
|
||||
* - 同步执行状态到 Notion 主脑
|
||||
*
|
||||
* 执行逻辑:
|
||||
* 扫描仓库 → 生成状态报告 → 同步到 Notion
|
||||
*
|
||||
* 调用方式:
|
||||
* node core/execution-sync [report|sync|status]
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
|
||||
/**
|
||||
* 采集核心模块状态
|
||||
*/
|
||||
function collectCoreModules() {
|
||||
const modules = [
|
||||
{ name: 'broadcast-listener', path: 'core/broadcast-listener/index.js' },
|
||||
{ name: 'task-queue', path: 'core/task-queue/index.js' },
|
||||
{ name: 'system-check', path: 'core/system-check/index.js' },
|
||||
{ name: 'execution-sync', path: 'core/execution-sync/index.js' },
|
||||
{ name: 'context-loader', path: 'core/context-loader/index.js' }
|
||||
];
|
||||
|
||||
return modules.map(m => ({
|
||||
...m,
|
||||
status: fs.existsSync(path.join(ROOT, m.path)) ? 'enabled' : 'missing'
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 采集连接器状态
|
||||
*/
|
||||
function collectConnectors() {
|
||||
const connectors = [
|
||||
{ name: 'notion-sync', path: 'connectors/notion-sync/index.js' },
|
||||
{ name: 'model-router', path: 'connectors/model-router/index.js' }
|
||||
];
|
||||
|
||||
return connectors.map(c => ({
|
||||
...c,
|
||||
status: fs.existsSync(path.join(ROOT, c.path)) ? 'enabled' : 'missing'
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 采集自动化工作流状态
|
||||
*/
|
||||
function collectWorkflows() {
|
||||
const workflowDir = path.join(ROOT, '.github/workflows');
|
||||
if (!fs.existsSync(workflowDir)) return { count: 0, files: [] };
|
||||
|
||||
const files = fs.readdirSync(workflowDir).filter(
|
||||
f => f.endsWith('.yml') || f.endsWith('.yaml')
|
||||
);
|
||||
return { count: files.length, files };
|
||||
}
|
||||
|
||||
/**
|
||||
* 采集任务队列状态
|
||||
*/
|
||||
function collectQueueStatus() {
|
||||
const queuePath = path.join(ROOT, 'core/task-queue/queue.json');
|
||||
if (!fs.existsSync(queuePath)) {
|
||||
return { total: 0, pending: 0, running: 0, completed: 0, failed: 0 };
|
||||
}
|
||||
|
||||
try {
|
||||
const queue = JSON.parse(fs.readFileSync(queuePath, 'utf-8'));
|
||||
const tasks = queue.tasks || [];
|
||||
return {
|
||||
total: tasks.length,
|
||||
pending: tasks.filter(t => t.status === 'pending').length,
|
||||
running: tasks.filter(t => t.status === 'running').length,
|
||||
completed: tasks.filter(t => t.status === 'completed').length,
|
||||
failed: tasks.filter(t => t.status === 'failed').length
|
||||
};
|
||||
} catch {
|
||||
return { total: 0, pending: 0, running: 0, completed: 0, failed: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取系统版本
|
||||
*/
|
||||
function getSystemVersion() {
|
||||
const healthPath = path.join(ROOT, 'brain/system-health.json');
|
||||
if (!fs.existsSync(healthPath)) return 'unknown';
|
||||
|
||||
try {
|
||||
const health = JSON.parse(fs.readFileSync(healthPath, 'utf-8'));
|
||||
return health.version || 'unknown';
|
||||
} catch {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成完整的执行层状态快照
|
||||
*/
|
||||
function collectStatus() {
|
||||
const now = new Date();
|
||||
const beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000)
|
||||
.toISOString().replace('T', ' ').slice(0, 19) + '+08:00';
|
||||
|
||||
return {
|
||||
timestamp: beijingTime,
|
||||
version: getSystemVersion(),
|
||||
core_modules: collectCoreModules(),
|
||||
connectors: collectConnectors(),
|
||||
workflows: collectWorkflows(),
|
||||
task_queue: collectQueueStatus(),
|
||||
execution_layer_status: 'stable',
|
||||
notion_bridge: 'active',
|
||||
execution_sync: 'enabled'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 Markdown 状态报告
|
||||
*/
|
||||
function generateReport(statusData) {
|
||||
const s = statusData || collectStatus();
|
||||
|
||||
const coreTable = s.core_modules.map(m =>
|
||||
`| ${m.name} | \`${m.path}\` | ${m.status === 'enabled' ? '✅ Enabled' : '❌ Missing'} |`
|
||||
).join('\n');
|
||||
|
||||
const connTable = s.connectors.map(c =>
|
||||
`| ${c.name} | \`${c.path}\` | ${c.status === 'enabled' ? '✅ Enabled' : '❌ Missing'} |`
|
||||
).join('\n');
|
||||
|
||||
const q = s.task_queue;
|
||||
|
||||
const md = `# 执行层状态报告 — execution-status.md
|
||||
|
||||
> 铸渊执行层自动生成 · TCS-0002∞
|
||||
> 更新时间:${s.timestamp}
|
||||
|
||||
---
|
||||
|
||||
## 系统概览
|
||||
|
||||
| 指标 | 状态 |
|
||||
|------|------|
|
||||
| 系统版本 | v${s.version} |
|
||||
| 执行层状态 | ${s.execution_layer_status === 'stable' ? '✅ Stable' : '⚠️ ' + s.execution_layer_status} |
|
||||
| Notion 桥接 | ${s.notion_bridge === 'active' ? '✅ Active' : '❌ Inactive'} |
|
||||
| 执行同步 | ${s.execution_sync === 'enabled' ? '✅ Enabled' : '❌ Disabled'} |
|
||||
| 工作流数量 | ${s.workflows.count} |
|
||||
|
||||
---
|
||||
|
||||
## 核心模块状态
|
||||
|
||||
| 模块 | 路径 | 状态 |
|
||||
|------|------|------|
|
||||
${coreTable}
|
||||
|
||||
---
|
||||
|
||||
## 连接器状态
|
||||
|
||||
| 连接器 | 路径 | 状态 |
|
||||
|--------|------|------|
|
||||
${connTable}
|
||||
|
||||
---
|
||||
|
||||
## 任务队列状态
|
||||
|
||||
| 指标 | 数量 |
|
||||
|------|------|
|
||||
| 总计 | ${q.total} |
|
||||
| 待处理 | ${q.pending} |
|
||||
| 执行中 | ${q.running} |
|
||||
| 已完成 | ${q.completed} |
|
||||
| 失败 | ${q.failed} |
|
||||
|
||||
---
|
||||
|
||||
## 执行闭环
|
||||
|
||||
\`\`\`
|
||||
context-loader → system-check → execution-sync → 状态报告
|
||||
↓
|
||||
broadcast-listener → task-queue → 任务执行
|
||||
↓
|
||||
notion-sync → Notion 主脑更新
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入状态报告文件
|
||||
*/
|
||||
function writeReport() {
|
||||
const statusData = collectStatus();
|
||||
const md = generateReport(statusData);
|
||||
const reportPath = path.join(ROOT, 'docs/execution-status.md');
|
||||
fs.writeFileSync(reportPath, md, 'utf-8');
|
||||
console.log(`📝 执行状态报告已生成: docs/execution-status.md`);
|
||||
return statusData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步执行状态到 Notion
|
||||
*/
|
||||
async function syncToNotion(statusData) {
|
||||
let notionSync;
|
||||
try {
|
||||
notionSync = require('../../connectors/notion-sync');
|
||||
} catch {
|
||||
console.log('⚠️ connectors/notion-sync 模块未找到,跳过 Notion 同步');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📡 同步执行状态到 Notion...');
|
||||
await notionSync.syncExecutionStatus(statusData);
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
const cmd = process.argv[2] || 'report';
|
||||
|
||||
switch (cmd) {
|
||||
case 'report': {
|
||||
writeReport();
|
||||
break;
|
||||
}
|
||||
case 'sync': {
|
||||
const statusData = writeReport();
|
||||
syncToNotion(statusData).catch(err => {
|
||||
console.error(`❌ Notion 同步失败: ${err.message}`);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'status': {
|
||||
const s = collectStatus();
|
||||
console.log('📊 执行层状态:');
|
||||
console.log(` 版本: v${s.version}`);
|
||||
console.log(` 执行层: ${s.execution_layer_status}`);
|
||||
console.log(` Notion 桥接: ${s.notion_bridge}`);
|
||||
console.log(` 执行同步: ${s.execution_sync}`);
|
||||
console.log(` 核心模块: ${s.core_modules.filter(m => m.status === 'enabled').length}/${s.core_modules.length}`);
|
||||
console.log(` 连接器: ${s.connectors.filter(c => c.status === 'enabled').length}/${s.connectors.length}`);
|
||||
console.log(` 工作流: ${s.workflows.count}`);
|
||||
console.log(` 任务队列: ${s.task_queue.total} 总 / ${s.task_queue.pending} 待处理`);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.log('用法: node core/execution-sync [report|sync|status]');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { collectStatus, generateReport, writeReport, syncToNotion };
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
/**
|
||||
* core/system-check — 仓库自检系统
|
||||
*
|
||||
* 功能:
|
||||
* - 扫描仓库结构完整性
|
||||
* - 检查自动化工作流状态
|
||||
* - 检测配置错误
|
||||
* - 更新系统索引
|
||||
*
|
||||
* 执行周期:daily cron(通过 daily-maintenance 工作流触发)
|
||||
*
|
||||
* 调用方式:
|
||||
* node core/system-check
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
|
||||
/**
|
||||
* 必需目录列表
|
||||
*/
|
||||
const REQUIRED_DIRS = [
|
||||
'brain',
|
||||
'src',
|
||||
'scripts',
|
||||
'core/broadcast-listener',
|
||||
'core/task-queue',
|
||||
'core/system-check',
|
||||
'core/execution-sync',
|
||||
'core/context-loader',
|
||||
'connectors/notion-sync',
|
||||
'connectors/model-router',
|
||||
'.github/workflows',
|
||||
'docs'
|
||||
];
|
||||
|
||||
/**
|
||||
* 必需文件列表
|
||||
*/
|
||||
const REQUIRED_FILES = [
|
||||
'brain/master-brain.md',
|
||||
'brain/read-order.md',
|
||||
'brain/repo-map.json',
|
||||
'brain/system-health.json',
|
||||
'brain/id-map.json',
|
||||
'package.json',
|
||||
'ecosystem.config.js',
|
||||
'docs/repo-structure-map.md',
|
||||
'docs/notion-bridge-map.md'
|
||||
];
|
||||
|
||||
/**
|
||||
* 检查目录是否存在
|
||||
*/
|
||||
function checkDirectories() {
|
||||
console.log('\n📂 目录结构检查:');
|
||||
const results = [];
|
||||
|
||||
for (const dir of REQUIRED_DIRS) {
|
||||
const fullPath = path.join(ROOT, dir);
|
||||
const exists = fs.existsSync(fullPath);
|
||||
const icon = exists ? '✅' : '❌';
|
||||
console.log(` ${icon} ${dir}`);
|
||||
results.push({ path: dir, exists, type: 'directory' });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查必需文件
|
||||
*/
|
||||
function checkFiles() {
|
||||
console.log('\n📄 必需文件检查:');
|
||||
const results = [];
|
||||
|
||||
for (const file of REQUIRED_FILES) {
|
||||
const fullPath = path.join(ROOT, file);
|
||||
const exists = fs.existsSync(fullPath);
|
||||
const icon = exists ? '✅' : '❌';
|
||||
console.log(` ${icon} ${file}`);
|
||||
results.push({ path: file, exists, type: 'file' });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查工作流数量
|
||||
*/
|
||||
function checkWorkflows() {
|
||||
console.log('\n⚙️ 工作流检查:');
|
||||
const workflowDir = path.join(ROOT, '.github/workflows');
|
||||
|
||||
if (!fs.existsSync(workflowDir)) {
|
||||
console.log(' ❌ 工作流目录不存在');
|
||||
return { count: 0, files: [] };
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(workflowDir).filter(f => f.endsWith('.yml') || f.endsWith('.yaml'));
|
||||
console.log(` ✅ 发现 ${files.length} 个工作流文件`);
|
||||
|
||||
return { count: files.length, files };
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查核心模块状态
|
||||
*/
|
||||
function checkCoreModules() {
|
||||
console.log('\n🔧 核心模块检查:');
|
||||
const modules = [
|
||||
{ name: 'broadcast-listener', path: 'core/broadcast-listener/index.js' },
|
||||
{ name: 'task-queue', path: 'core/task-queue/index.js' },
|
||||
{ name: 'system-check', path: 'core/system-check/index.js' },
|
||||
{ name: 'execution-sync', path: 'core/execution-sync/index.js' },
|
||||
{ name: 'context-loader', path: 'core/context-loader/index.js' },
|
||||
{ name: 'notion-sync', path: 'connectors/notion-sync/index.js' },
|
||||
{ name: 'model-router', path: 'connectors/model-router/index.js' }
|
||||
];
|
||||
|
||||
const results = [];
|
||||
for (const mod of modules) {
|
||||
const fullPath = path.join(ROOT, mod.path);
|
||||
const exists = fs.existsSync(fullPath);
|
||||
const icon = exists ? '✅' : '❌';
|
||||
console.log(` ${icon} ${mod.name} → ${mod.path}`);
|
||||
results.push({ ...mod, exists });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 JSON 文件完整性
|
||||
*/
|
||||
function checkJsonIntegrity() {
|
||||
console.log('\n🔍 JSON 完整性检查:');
|
||||
const jsonFiles = [
|
||||
'brain/repo-map.json',
|
||||
'brain/system-health.json',
|
||||
'brain/id-map.json',
|
||||
'package.json'
|
||||
];
|
||||
|
||||
const results = [];
|
||||
for (const file of jsonFiles) {
|
||||
const fullPath = path.join(ROOT, file);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.log(` ⏭️ ${file} — 文件不存在`);
|
||||
results.push({ path: file, valid: false, reason: 'missing' });
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
JSON.parse(fs.readFileSync(fullPath, 'utf-8'));
|
||||
console.log(` ✅ ${file}`);
|
||||
results.push({ path: file, valid: true });
|
||||
} catch (e) {
|
||||
console.log(` ❌ ${file} — JSON 解析错误`);
|
||||
results.push({ path: file, valid: false, reason: 'parse_error' });
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成自检报告
|
||||
*/
|
||||
function generateReport(dirResults, fileResults, workflows, modules, jsonResults) {
|
||||
const totalChecks = dirResults.length + fileResults.length + modules.length + jsonResults.length;
|
||||
const passed = [
|
||||
...dirResults.filter(r => r.exists),
|
||||
...fileResults.filter(r => r.exists),
|
||||
...modules.filter(r => r.exists),
|
||||
...jsonResults.filter(r => r.valid)
|
||||
].length;
|
||||
|
||||
const report = {
|
||||
version: '5.1',
|
||||
checked_at: new Date().toISOString(),
|
||||
summary: {
|
||||
total_checks: totalChecks,
|
||||
passed: passed,
|
||||
failed: totalChecks - passed,
|
||||
health_score: Math.round((passed / totalChecks) * 100)
|
||||
},
|
||||
workflows: {
|
||||
count: workflows.count
|
||||
},
|
||||
directories: dirResults,
|
||||
files: fileResults,
|
||||
modules: modules,
|
||||
json_integrity: jsonResults
|
||||
};
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据自检结果生成自动任务
|
||||
*/
|
||||
function generateAutoTasks(report) {
|
||||
const tasks = [];
|
||||
const timestamp = new Date().toISOString();
|
||||
|
||||
// 检查目录缺失 → 生成修复任务
|
||||
const missingDirs = (report.directories || []).filter(d => !d.exists);
|
||||
for (const dir of missingDirs) {
|
||||
tasks.push({
|
||||
task_id: `auto-fix-dir-${dir.path.replace(/\//g, '-')}-${timestamp.slice(0, 10)}`,
|
||||
type: 'auto-task',
|
||||
source: 'system-check',
|
||||
priority: 'high',
|
||||
status: 'pending',
|
||||
executor: 'zhuyuan',
|
||||
description: `修复缺失目录: ${dir.path}`
|
||||
});
|
||||
}
|
||||
|
||||
// 检查文件缺失 → 生成修复任务
|
||||
const missingFiles = (report.files || []).filter(f => !f.exists);
|
||||
for (const file of missingFiles) {
|
||||
tasks.push({
|
||||
task_id: `auto-fix-file-${file.path.replace(/\//g, '-')}-${timestamp.slice(0, 10)}`,
|
||||
type: 'auto-task',
|
||||
source: 'system-check',
|
||||
priority: 'high',
|
||||
status: 'pending',
|
||||
executor: 'zhuyuan',
|
||||
description: `修复缺失文件: ${file.path}`
|
||||
});
|
||||
}
|
||||
|
||||
// 检查模块缺失 → 生成修复任务
|
||||
const missingModules = (report.modules || []).filter(m => !m.exists);
|
||||
for (const mod of missingModules) {
|
||||
tasks.push({
|
||||
task_id: `auto-fix-module-${mod.name}-${timestamp.slice(0, 10)}`,
|
||||
type: 'auto-task',
|
||||
source: 'system-check',
|
||||
priority: 'normal',
|
||||
status: 'pending',
|
||||
executor: 'zhuyuan',
|
||||
description: `修复缺失模块: ${mod.name}`
|
||||
});
|
||||
}
|
||||
|
||||
// JSON 完整性失败 → 生成修复任务
|
||||
const invalidJson = (report.json_integrity || []).filter(j => !j.valid);
|
||||
for (const json of invalidJson) {
|
||||
tasks.push({
|
||||
task_id: `auto-fix-json-${json.path.replace(/\//g, '-')}-${timestamp.slice(0, 10)}`,
|
||||
type: 'auto-task',
|
||||
source: 'system-check',
|
||||
priority: 'high',
|
||||
status: 'pending',
|
||||
executor: 'zhuyuan',
|
||||
description: `修复 JSON 文件: ${json.path} (${json.reason})`
|
||||
});
|
||||
}
|
||||
|
||||
// 健康分数低 → 生成结构优化任务
|
||||
if (report.summary && report.summary.health_score < 100) {
|
||||
tasks.push({
|
||||
task_id: `auto-optimize-structure-${timestamp.slice(0, 10)}`,
|
||||
type: 'maintenance-task',
|
||||
source: 'system-check',
|
||||
priority: 'low',
|
||||
status: 'pending',
|
||||
executor: 'zhuyuan',
|
||||
description: `结构优化: 健康分数 ${report.summary.health_score}%`
|
||||
});
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主执行函数
|
||||
*/
|
||||
function run() {
|
||||
console.log('🏥 铸渊仓库自检系统 v5.1');
|
||||
console.log('═'.repeat(40));
|
||||
|
||||
const dirResults = checkDirectories();
|
||||
const fileResults = checkFiles();
|
||||
const workflows = checkWorkflows();
|
||||
const modules = checkCoreModules();
|
||||
const jsonResults = checkJsonIntegrity();
|
||||
|
||||
const report = generateReport(dirResults, fileResults, workflows, modules, jsonResults);
|
||||
|
||||
console.log('\n═'.repeat(40));
|
||||
console.log(`📊 自检报告: ${report.summary.passed}/${report.summary.total_checks} 通过 (${report.summary.health_score}%)`);
|
||||
|
||||
if (report.summary.failed > 0) {
|
||||
console.log(`⚠️ 发现 ${report.summary.failed} 项问题`);
|
||||
} else {
|
||||
console.log('✅ 系统状态健康');
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
const report = run();
|
||||
|
||||
// 可选:输出 JSON 报告
|
||||
if (process.argv.includes('--json')) {
|
||||
const reportPath = path.join(ROOT, 'core/system-check/last-report.json');
|
||||
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf-8');
|
||||
console.log(`\n📝 报告已保存: ${reportPath}`);
|
||||
}
|
||||
|
||||
// 可选:生成自动任务
|
||||
if (process.argv.includes('--auto-tasks')) {
|
||||
const autoTasks = generateAutoTasks(report);
|
||||
if (autoTasks.length > 0) {
|
||||
console.log(`\n🔄 生成 ${autoTasks.length} 个自动任务:`);
|
||||
autoTasks.forEach(t => console.log(` 📋 ${t.task_id}: ${t.description}`));
|
||||
} else {
|
||||
console.log('\n✅ 系统健康,无需生成自动任务');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { run, generateAutoTasks, checkDirectories, checkFiles, checkWorkflows, checkCoreModules, checkJsonIntegrity };
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/**
|
||||
* core/task-queue — 任务队列系统
|
||||
*
|
||||
* 任务结构:
|
||||
* task_id — 唯一任务标识
|
||||
* source — 来源(broadcast / maintenance / dev / auto)
|
||||
* type — 类型(system-task / dev-task / maintenance-task / auto-task)
|
||||
* priority — 优先级(high / normal / low)
|
||||
* status — 状态(pending / running / completed / failed)
|
||||
* executor — 执行者(zhuyuan)
|
||||
*
|
||||
* 任务类型:
|
||||
* system-task — 系统级任务(广播、状态同步)
|
||||
* dev-task — 开发任务(代码变更、功能开发)
|
||||
* maintenance-task — 维护任务(结构修复、文档更新)
|
||||
* auto-task — 自动生成任务(自检发现的问题)
|
||||
*
|
||||
* 任务来源:
|
||||
* - Notion 广播
|
||||
* - 系统维护任务
|
||||
* - 开发任务
|
||||
* - 自动开发循环生成
|
||||
*
|
||||
* 执行流程:
|
||||
* 任务进入队列 → 按优先级去重 → 执行器运行 → 执行结果写回
|
||||
*
|
||||
* 调用方式:
|
||||
* node core/task-queue [status|run|cleanup]
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '../..');
|
||||
const QUEUE_PATH = path.join(ROOT, 'core/task-queue/queue.json');
|
||||
|
||||
/**
|
||||
* 加载当前队列
|
||||
*/
|
||||
function loadQueue() {
|
||||
if (!fs.existsSync(QUEUE_PATH)) {
|
||||
return { version: '5.1', tasks: [], last_updated: null };
|
||||
}
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(QUEUE_PATH, 'utf-8'));
|
||||
} catch {
|
||||
return { version: '5.1', tasks: [], last_updated: null };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存队列
|
||||
*/
|
||||
function saveQueue(queue) {
|
||||
queue.last_updated = new Date().toISOString();
|
||||
fs.writeFileSync(QUEUE_PATH, JSON.stringify(queue, null, 2), 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加任务到队列
|
||||
*/
|
||||
function enqueue(task) {
|
||||
const queue = loadQueue();
|
||||
|
||||
// 去重:相同 task_id 只保留最新
|
||||
const existing = queue.tasks.findIndex(t => t.task_id === task.task_id);
|
||||
if (existing !== -1) {
|
||||
const original = queue.tasks[existing];
|
||||
queue.tasks[existing] = {
|
||||
...original,
|
||||
...task,
|
||||
queued_at: original.queued_at,
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
console.log(`🔄 更新已有任务: ${task.task_id}`);
|
||||
} else {
|
||||
queue.tasks.push({
|
||||
...task,
|
||||
queued_at: new Date().toISOString()
|
||||
});
|
||||
console.log(`➕ 新增任务: ${task.task_id}`);
|
||||
}
|
||||
|
||||
saveQueue(queue);
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量入队
|
||||
*/
|
||||
function enqueueBatch(tasks) {
|
||||
return tasks.map(t => enqueue(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个待执行任务(按优先级)
|
||||
*/
|
||||
function dequeue() {
|
||||
const queue = loadQueue();
|
||||
const priorityOrder = { high: 0, normal: 1, low: 2 };
|
||||
|
||||
const pending = queue.tasks
|
||||
.filter(t => t.status === 'pending')
|
||||
.sort((a, b) => (priorityOrder[a.priority] || 1) - (priorityOrder[b.priority] || 1));
|
||||
|
||||
if (pending.length === 0) return null;
|
||||
|
||||
const task = pending[0];
|
||||
task.status = 'running';
|
||||
task.started_at = new Date().toISOString();
|
||||
saveQueue(queue);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记任务完成
|
||||
*/
|
||||
function complete(taskId, result = null) {
|
||||
const queue = loadQueue();
|
||||
const task = queue.tasks.find(t => t.task_id === taskId);
|
||||
|
||||
if (!task) {
|
||||
console.warn(`⚠️ 任务不存在: ${taskId}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
task.status = 'completed';
|
||||
task.completed_at = new Date().toISOString();
|
||||
if (result) task.result = result;
|
||||
|
||||
saveQueue(queue);
|
||||
console.log(`✅ 任务完成: ${taskId}`);
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记任务失败
|
||||
*/
|
||||
function fail(taskId, error = null) {
|
||||
const queue = loadQueue();
|
||||
const task = queue.tasks.find(t => t.task_id === taskId);
|
||||
|
||||
if (!task) {
|
||||
console.warn(`⚠️ 任务不存在: ${taskId}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
task.status = 'failed';
|
||||
task.failed_at = new Date().toISOString();
|
||||
if (error) task.error = String(error);
|
||||
|
||||
saveQueue(queue);
|
||||
console.log(`❌ 任务失败: ${taskId}`);
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取队列状态
|
||||
*/
|
||||
function status() {
|
||||
const queue = loadQueue();
|
||||
const tasks = queue.tasks;
|
||||
|
||||
const stats = {
|
||||
total: tasks.length,
|
||||
pending: tasks.filter(t => t.status === 'pending').length,
|
||||
running: tasks.filter(t => t.status === 'running').length,
|
||||
completed: tasks.filter(t => t.status === 'completed').length,
|
||||
failed: tasks.filter(t => t.status === 'failed').length,
|
||||
last_updated: queue.last_updated,
|
||||
by_type: {
|
||||
'system-task': tasks.filter(t => t.type === 'system-task').length,
|
||||
'dev-task': tasks.filter(t => t.type === 'dev-task').length,
|
||||
'maintenance-task': tasks.filter(t => t.type === 'maintenance-task').length,
|
||||
'auto-task': tasks.filter(t => t.type === 'auto-task').length
|
||||
}
|
||||
};
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理已完成任务(保留最近 50 条)
|
||||
*/
|
||||
function cleanup() {
|
||||
const queue = loadQueue();
|
||||
const completed = queue.tasks.filter(t =>
|
||||
t.status === 'completed' || t.status === 'failed'
|
||||
);
|
||||
|
||||
if (completed.length > 50) {
|
||||
const keep = completed
|
||||
.sort((a, b) => (b.completed_at || b.failed_at || '').localeCompare(a.completed_at || a.failed_at || ''))
|
||||
.slice(0, 50);
|
||||
const keepIds = new Set(keep.map(t => t.task_id));
|
||||
const active = queue.tasks.filter(t =>
|
||||
t.status === 'pending' || t.status === 'running'
|
||||
);
|
||||
queue.tasks = [...active, ...keep];
|
||||
saveQueue(queue);
|
||||
console.log(`🧹 清理完成,保留 ${queue.tasks.length} 条任务`);
|
||||
}
|
||||
}
|
||||
|
||||
// CLI 入口
|
||||
if (require.main === module) {
|
||||
const cmd = process.argv[2] || 'status';
|
||||
|
||||
switch (cmd) {
|
||||
case 'status': {
|
||||
const s = status();
|
||||
console.log('📊 任务队列状态:');
|
||||
console.log(` 总计: ${s.total}`);
|
||||
console.log(` 待处理: ${s.pending}`);
|
||||
console.log(` 执行中: ${s.running}`);
|
||||
console.log(` 已完成: ${s.completed}`);
|
||||
console.log(` 失败: ${s.failed}`);
|
||||
console.log(` 更新时间: ${s.last_updated || '无'}`);
|
||||
if (s.total > 0) {
|
||||
console.log(' 任务类型分布:');
|
||||
for (const [type, count] of Object.entries(s.by_type)) {
|
||||
if (count > 0) console.log(` ${type}: ${count}`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'run': {
|
||||
const task = dequeue();
|
||||
if (task) {
|
||||
console.log(`🚀 取出任务: ${task.task_id}`);
|
||||
} else {
|
||||
console.log('✅ 队列为空,无待执行任务');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'cleanup': {
|
||||
cleanup();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.log('用法: node core/task-queue [status|run|cleanup]');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { loadQueue, enqueue, enqueueBatch, dequeue, complete, fail, status, cleanup };
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
# 执行层结构地图 — execution-layer-map.md
|
||||
|
||||
> 铸渊执行层自动开发循环升级产物 · TCS-0002∞
|
||||
> 生成时间:2026-03-14 · v5.1
|
||||
|
||||
---
|
||||
|
||||
## 执行层系统结构
|
||||
|
||||
```
|
||||
零点原核(语言观察层)
|
||||
↓
|
||||
数字地球主控台(Notion 主脑 / 曜冥)
|
||||
↓
|
||||
系统广播
|
||||
↓
|
||||
仓库执行层(铸渊)
|
||||
↓
|
||||
自动开发循环
|
||||
↓
|
||||
自动化执行系统
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心执行模块
|
||||
|
||||
| 模块 | 路径 | 职责 |
|
||||
|------|------|------|
|
||||
| 上下文加载 | `core/context-loader/index.js` | 执行前加载系统上下文与身份认知 |
|
||||
| 广播监听 | `core/broadcast-listener/index.js` | 监听并解析 Notion 广播为可执行任务 |
|
||||
| 任务队列 | `core/task-queue/index.js` | 任务入队、调度、优先级管理、类型分类 |
|
||||
| 系统自检 | `core/system-check/index.js` | 仓库结构完整性检查 + 自动任务生成 |
|
||||
| 执行同步 | `core/execution-sync/index.js` | 生成执行状态报告并同步到 Notion |
|
||||
|
||||
---
|
||||
|
||||
## 自动化模块
|
||||
|
||||
| 工作流 | 触发方式 | 职责 |
|
||||
|--------|----------|------|
|
||||
| `daily-maintenance.yml` | cron `0 2 * * *` | 每日巡检与 system-health 更新 |
|
||||
| `zhuyuan-daily-selfcheck.yml` | cron `0 0 * * *` | 铸渊每日自检 |
|
||||
| `execution-sync.yml` | cron `0 3 * * *` | 执行层状态同步到 Notion |
|
||||
| `notion-heartbeat.yml` | cron `*/5 * * * *` | 工单心跳监控 |
|
||||
| `brain-sync.yml` | workflow_dispatch | 大脑数据同步 |
|
||||
|
||||
---
|
||||
|
||||
## Notion 连接模块
|
||||
|
||||
| 模块 | 路径 | 方向 | 职责 |
|
||||
|------|------|------|------|
|
||||
| Notion 同步 | `connectors/notion-sync/index.js` | 双向 | 广播拉取 / 日志写回 / 状态同步 |
|
||||
| 模型路由 | `connectors/model-router/index.js` | 出站 | 统一模型调用入口 |
|
||||
| Notion 桥接 | `scripts/notion-bridge.js` | 上行 | SYSLOG 上报 / 变更同步 |
|
||||
| 信号桥 | `scripts/notion-signal-bridge.js` | 下行 | 工单轮询 / 信号执行 |
|
||||
| 心跳监控 | `scripts/notion-heartbeat.js` | 双向 | 超时检测 / 自动重试 |
|
||||
|
||||
---
|
||||
|
||||
## 任务执行模块
|
||||
|
||||
| 脚本 | 职责 |
|
||||
|------|------|
|
||||
| `scripts/process-broadcasts.js` | 处理广播(JSON 规则 + MD 成长日志) |
|
||||
| `scripts/daily-check.js` | 文件完整性 / HLI 覆盖率 / Schema 验证 |
|
||||
| `scripts/zhuyuan-daily-selfcheck.js` | 大脑文件验证 / FAQ 去重 / 记忆修剪 |
|
||||
| `scripts/distribute-broadcasts.js` | 广播分发 |
|
||||
| `scripts/generate-repo-map.js` | 仓库结构索引生成 |
|
||||
| `scripts/generate-system-health.js` | 系统健康报告生成 |
|
||||
|
||||
---
|
||||
|
||||
## 执行闭环(自动开发循环 v5.1)
|
||||
|
||||
```
|
||||
context-loader(上下文加载)
|
||||
↓
|
||||
system-check(自检 + 自动任务生成)
|
||||
↓
|
||||
execution-sync(状态采集与报告)
|
||||
↓
|
||||
broadcast-listener(广播监听)
|
||||
↓
|
||||
task-queue(任务排队 · 类型: system/dev/maintenance/auto)
|
||||
↓
|
||||
执行器运行
|
||||
↓
|
||||
connectors/notion-sync(状态回写)
|
||||
↓
|
||||
Notion 主脑更新
|
||||
↓
|
||||
生成下一任务(自动开发循环)
|
||||
```
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
# 执行层状态报告 — execution-status.md
|
||||
|
||||
> 铸渊执行层自动生成 · TCS-0002∞
|
||||
> 更新时间:2026-03-14 14:58:44+08:00
|
||||
|
||||
---
|
||||
|
||||
## 系统概览
|
||||
|
||||
| 指标 | 状态 |
|
||||
|------|------|
|
||||
| 系统版本 | v5.1 |
|
||||
| 执行层状态 | ✅ Stable |
|
||||
| Notion 桥接 | ✅ Active |
|
||||
| 执行同步 | ✅ Enabled |
|
||||
| 工作流数量 | 43 |
|
||||
|
||||
---
|
||||
|
||||
## 核心模块状态
|
||||
|
||||
| 模块 | 路径 | 状态 |
|
||||
|------|------|------|
|
||||
| broadcast-listener | `core/broadcast-listener/index.js` | ✅ Enabled |
|
||||
| task-queue | `core/task-queue/index.js` | ✅ Enabled |
|
||||
| system-check | `core/system-check/index.js` | ✅ Enabled |
|
||||
| execution-sync | `core/execution-sync/index.js` | ✅ Enabled |
|
||||
| context-loader | `core/context-loader/index.js` | ✅ Enabled |
|
||||
|
||||
---
|
||||
|
||||
## 连接器状态
|
||||
|
||||
| 连接器 | 路径 | 状态 |
|
||||
|--------|------|------|
|
||||
| notion-sync | `connectors/notion-sync/index.js` | ✅ Enabled |
|
||||
| model-router | `connectors/model-router/index.js` | ✅ Enabled |
|
||||
|
||||
---
|
||||
|
||||
## 任务队列状态
|
||||
|
||||
| 指标 | 数量 |
|
||||
|------|------|
|
||||
| 总计 | 0 |
|
||||
| 待处理 | 0 |
|
||||
| 执行中 | 0 |
|
||||
| 已完成 | 0 |
|
||||
| 失败 | 0 |
|
||||
|
||||
---
|
||||
|
||||
## 执行闭环
|
||||
|
||||
```
|
||||
context-loader → system-check → execution-sync → 状态报告
|
||||
↓
|
||||
broadcast-listener → task-queue → 任务执行
|
||||
↓
|
||||
notion-sync → Notion 主脑更新
|
||||
```
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
# Notion 桥接地图 — notion-bridge-map.md
|
||||
|
||||
> 铸渊执行层系统升级产物 · TCS-0002∞
|
||||
> 生成时间:2026-03-14
|
||||
|
||||
---
|
||||
|
||||
## 连接总览
|
||||
|
||||
```
|
||||
Notion 主脑(数字地球主控台)
|
||||
↕
|
||||
connectors/notion-sync(双向同步模块)
|
||||
↕
|
||||
仓库执行层(铸渊)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API 调用路径
|
||||
|
||||
| 脚本 | 方向 | Notion 数据库 | 环境变量 |
|
||||
|------|------|---------------|----------|
|
||||
| `scripts/notion-bridge.js` | 仓库 → Notion | SYSLOG Inbox / Changes Log | `NOTION_TOKEN`, `SYSLOG_DB_ID`, `CHANGES_DB_ID` |
|
||||
| `scripts/notion-signal-bridge.js` | Notion → 仓库 | 工单数据库 / 信号日志 | `NOTION_API_TOKEN`, `WORKORDER_DB_ID`, `SIGNAL_LOG_DB_ID` |
|
||||
| `scripts/notion-heartbeat.js` | Notion ↔ 仓库 | 工单数据库 | `NOTION_TOKEN`, `NOTION_TICKET_DB_ID` |
|
||||
| `scripts/brain-bridge-sync.js` | Notion ↔ 仓库 | 大脑同步 | `NOTION_TOKEN` |
|
||||
| `connectors/notion-sync/index.js` | 双向统一接口 | 广播 / 日志 | `NOTION_TOKEN`, `BROADCAST_DB_ID` |
|
||||
|
||||
---
|
||||
|
||||
## 数据同步逻辑
|
||||
|
||||
### 仓库 → Notion(上行)
|
||||
|
||||
1. **SYSLOG 上报**:`syslog-inbox/` → `notion-bridge.js` → Notion SYSLOG 数据库
|
||||
2. **变更同步**:Git commits/PRs → `notion-bridge.js` → Notion Changes Log
|
||||
3. **执行日志**:任务完成 → `connectors/notion-sync` → Notion 广播数据库
|
||||
4. **心跳回写**:工单状态 → `notion-heartbeat.js` → Notion 工单数据库
|
||||
|
||||
### Notion → 仓库(下行)
|
||||
|
||||
1. **广播监听**:Notion 广播 → `connectors/notion-sync` → `core/broadcast-listener`
|
||||
2. **工单派发**:Notion 工单 → `notion-signal-bridge.js` → 本地任务执行
|
||||
3. **人格唤醒**:Notion 触发 → `persona-invoke.yml` → 人格体执行
|
||||
|
||||
---
|
||||
|
||||
## 连接方式
|
||||
|
||||
| 连接类型 | 实现 | 说明 |
|
||||
|----------|------|------|
|
||||
| Notion API | HTTPS REST | Notion API v2022-06-28 |
|
||||
| 轮询机制 | Cron / workflow_dispatch | 定时拉取 + 手动触发 |
|
||||
| 心跳监控 | 5 分钟间隔 Cron | 超时自动重试(最多 3 次) |
|
||||
| 信号桥 | 工单状态驱动 | `已发送` → 执行 → `已完成` |
|
||||
|
||||
---
|
||||
|
||||
## 关联工作流
|
||||
|
||||
| 工作流 | 触发方式 | 功能 |
|
||||
|--------|----------|------|
|
||||
| `notion-heartbeat.yml` | cron `*/5 * * * *` | 工单心跳监控 |
|
||||
| `bridge-syslog-to-notion.yml` | push (syslog-inbox) | SYSLOG 上报 |
|
||||
| `bridge-changes-to-notion.yml` | push (main) | 变更同步 |
|
||||
| `brain-sync.yml` | workflow_dispatch | 大脑数据同步 |
|
||||
| `process-notion-orders.yml` | workflow_dispatch | 工单处理 |
|
||||
| `persona-invoke.yml` | workflow_dispatch | 人格唤醒执行 |
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
# 仓库结构地图 — repo-structure-map.md
|
||||
|
||||
> 铸渊执行层系统升级产物 · TCS-0002∞
|
||||
> 生成时间:2026-03-14
|
||||
|
||||
---
|
||||
|
||||
## 系统总览
|
||||
|
||||
```
|
||||
零点原核(语言观察层)
|
||||
↓
|
||||
数字地球主控台(Notion 主脑)
|
||||
↓
|
||||
系统广播
|
||||
↓
|
||||
仓库执行层(铸渊)
|
||||
↓
|
||||
自动化执行系统
|
||||
↓
|
||||
开发者 / 模型
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心模块
|
||||
|
||||
| 目录 | 功能 | 类型 |
|
||||
|------|------|------|
|
||||
| `core/broadcast-listener` | 广播监听与解析 | 核心模块 |
|
||||
| `core/task-queue` | 任务队列与调度 | 核心模块 |
|
||||
| `core/system-check` | 仓库自检系统 | 核心模块 |
|
||||
| `brain/` | 执行层大脑索引 | 知识索引 |
|
||||
| `src/` | HLI 接口服务 | 应用服务 |
|
||||
|
||||
---
|
||||
|
||||
## 自动化模块
|
||||
|
||||
| 目录 | 功能 | 类型 |
|
||||
|------|------|------|
|
||||
| `.github/workflows/` | GitHub Actions 工作流 | CI/CD |
|
||||
| `scripts/` | 脚本工具集 | 自动化 |
|
||||
| `.github/broadcasts/` | 广播入站队列 | 信号管道 |
|
||||
|
||||
---
|
||||
|
||||
## Notion 连接模块
|
||||
|
||||
| 目录 / 文件 | 功能 | 类型 |
|
||||
|------|------|------|
|
||||
| `connectors/notion-sync` | Notion 双向同步 | 连接器 |
|
||||
| `connectors/model-router` | 模型调用路由 | 连接器 |
|
||||
| `scripts/notion-bridge.js` | Notion 数据桥接 | 桥接脚本 |
|
||||
| `scripts/notion-signal-bridge.js` | Notion 信号桥 | 桥接脚本 |
|
||||
| `scripts/notion-heartbeat.js` | Notion 心跳监控 | 监控脚本 |
|
||||
|
||||
---
|
||||
|
||||
## 开发模块
|
||||
|
||||
| 目录 | 功能 |
|
||||
|------|------|
|
||||
| `backend/` | Express 后端服务 (port 3000) |
|
||||
| `backend-integration/` | AI Chat API 代理 (port 3721) |
|
||||
| `persona-studio/` | 人格工作室 (port 3002) |
|
||||
| `frontend/` | 前端组件 |
|
||||
| `m01-login` ~ `m18-health-check` | 功能模块集 |
|
||||
|
||||
---
|
||||
|
||||
## 数据与日志
|
||||
|
||||
| 目录 | 功能 |
|
||||
|------|------|
|
||||
| `broadcasts/` | 广播存档 |
|
||||
| `broadcasts-outbox/` | 广播发件箱 |
|
||||
| `syslog/` | 系统日志 |
|
||||
| `syslog-inbox/` | 系统日志入站 |
|
||||
| `syslog-processed/` | 已处理日志 |
|
||||
| `reports/` | 报告存档 |
|
||||
| `persona-telemetry/` | 人格遥测数据 |
|
||||
| `collaboration-logs/` | 协作日志 |
|
||||
|
||||
---
|
||||
|
||||
## PM2 服务映射
|
||||
|
||||
| 服务名 | 入口 | 端口 |
|
||||
|--------|------|------|
|
||||
| guanghulab | `src/index.js` | 3001 |
|
||||
| guanghulab-backend | `backend/server.js` | 3000 |
|
||||
| guanghulab-proxy | `backend-integration/api-proxy.js` | 3721 |
|
||||
| guanghulab-ws | `status-board/mock-ws-server.js` | 8080 |
|
||||
| persona-studio | `persona-studio/backend/server.js` | 3002 |
|
||||
|
|
@ -30,7 +30,14 @@
|
|||
"proxy:start": "node backend-integration/api-proxy.js",
|
||||
"notion:poll": "node scripts/notion-signal-bridge.js poll",
|
||||
"notion:health": "node scripts/notion-signal-bridge.js health",
|
||||
"notion:summary": "node scripts/generate-session-summary.js"
|
||||
"notion:summary": "node scripts/generate-session-summary.js",
|
||||
"core:listen": "node core/broadcast-listener",
|
||||
"core:queue": "node core/task-queue status",
|
||||
"core:check": "node core/system-check",
|
||||
"core:sync": "node core/execution-sync report",
|
||||
"core:context": "node core/context-loader",
|
||||
"connector:notion": "node connectors/notion-sync status",
|
||||
"connector:model": "node connectors/model-router"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.13.6",
|
||||
|
|
|
|||
Loading…
Reference in New Issue