🦅 天眼系统+人格体编号体系+门禁v2+ASOP自优化 全套升级部署

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-16 14:51:14 +00:00
parent cbfd2315c9
commit 791afa571f
15 changed files with 770 additions and 24 deletions

View File

@ -29,19 +29,19 @@
"DEV-001": {
"name": "页页",
"persona_id": "PER-001",
"github_usernames": [],
"github_usernames": ["夜夜光湖"],
"allowed_paths": ["dev/DEV-001/", "backend/", "src/"]
},
"DEV-002": {
"name": "肥猫",
"persona_id": "PER-002",
"github_usernames": [],
"github_usernames": ["建培"],
"allowed_paths": ["dev/DEV-002/", "frontend/", "persona-selector/", "chat-bubble/"]
},
"DEV-003": {
"name": "燕樊",
"persona_id": "PER-003",
"github_usernames": [],
"github_usernames": ["六寻寻7-max"],
"allowed_paths": ["dev/DEV-003/", "settings/", "cloud-drive/"]
},
"DEV-004": {
@ -59,7 +59,7 @@
"DEV-009": {
"name": "花尔",
"persona_id": "PER-009",
"github_usernames": [],
"github_usernames": ["华尔华"],
"allowed_paths": ["dev/DEV-009/", "user-center/"]
},
"DEV-010": {
@ -77,7 +77,7 @@
"DEV-012": {
"name": "Awen",
"persona_id": "PER-012",
"github_usernames": [],
"github_usernames": ["文卓熙"],
"allowed_paths": ["dev/DEV-012/", "notification-center/", "notification/"]
},
"DEV-013": {

View File

@ -72,6 +72,11 @@ jobs:
echo "auto_fixable=$AUTO_FIXABLE" >> $GITHUB_OUTPUT
echo "needs_human=$NEEDS_HUMAN" >> $GITHUB_OUTPUT
- name: "🔄 Phase 3.5 · ASOP 自优化审批"
run: |
echo "🔄 ASOP 审批引擎启动..."
node scripts/skyeye/asop-reviewer.js > /tmp/skyeye/asop-review.json || echo "{}" > /tmp/skyeye/asop-review.json
- name: "🔧 Phase 4 · 修复Agent"
if: steps.diagnose.outputs.auto_fixable != '0'
env:
@ -107,6 +112,16 @@ jobs:
echo "$FAILED_WORKFLOWS"
# 记录到报告,具体重触发逻辑由各 workflow 自带的 workflow_dispatch 支持
- name: "🔧 Phase 5.5 · ASOP 执行已批准优化"
run: |
echo "🔧 ASOP 执行器启动..."
node scripts/skyeye/asop-executor.js > /tmp/skyeye/asop-execute.json || echo "{}" > /tmp/skyeye/asop-execute.json
- name: "🔍 Phase 5.7 · ASOP 验证优化效果"
run: |
echo "🔍 ASOP 验证器启动..."
node scripts/skyeye/asop-verifier.js > /tmp/skyeye/asop-verify.json || echo "{}" > /tmp/skyeye/asop-verify.json
- name: "📋 Phase 6 · 全局健康报告"
run: |
node scripts/skyeye/report-generator.js
@ -115,7 +130,7 @@ jobs:
cp /tmp/skyeye/full-report.json "data/skyeye-reports/skyeye-${DATE}.json"
git config user.name "zhuyuan-bot"
git config user.email "zhuyuan@guanghulab.com"
git add data/skyeye-reports/ .github/persona-brain/memory.json
git add data/skyeye-reports/ .github/persona-brain/memory.json data/asop-requests/
if ! git diff --cached --quiet; then
git commit -m "🦅 天眼报告 · $(date +%Y-%m-%d) · 问题:${{ steps.diagnose.outputs.issues_count }} 自动修复:${{ steps.diagnose.outputs.auto_fixable }}"
git push

View File

View File

View File

View File

View File

View File

View File

@ -28,8 +28,8 @@ const GITHUB_OUTPUT = process.env.GITHUB_OUTPUT || '/dev/null';
// ━━━ 仓库主人 ━━━
const REPO_OWNER = 'qinfendebingshuo';
// ━━━ 人格体签名正则 ━━━
const PERSONA_SIGNATURE_REGEX = /\[PER-(\d{3})\]/;
// ━━━ 人格体签名正则v2 升级:支持 PER-XXX / TCS-XXX / PER-PENDING-XXX ━━━
const PERSONA_SIGNATURE_REGEX = /^\[([A-Z]+-[A-Z0-9\-∞]+)\]/;
// ━━━ 显示长度限制 ━━━
const MAX_COMMIT_DISPLAY = 80;
@ -100,7 +100,7 @@ function extractPersonaSignature(commitMessage) {
if (!commitMessage) return null;
const match = commitMessage.match(PERSONA_SIGNATURE_REGEX);
if (match) {
return `PER-${match[1]}`;
return match[1]; // e.g. "PER-SS001", "TCS-0002∞", "PER-PENDING-005"
}
return null;
}

View File

@ -0,0 +1,143 @@
// scripts/skyeye/asop-executor.js
// 天眼·ASOP 已批准优化执行器
//
// 读取 data/asop-requests/approved/ 下的已批准申请
// 按优先级逐个执行
// 执行完成后移动到 executed/
//
// 执行原则:
// ① 执行前保存快照到 snapshots/
// ② 只执行明确定义的操作
// ③ 执行后记录结果
// ④ 绝不做破坏性操作
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '../..');
const ASOP_DIR = path.join(ROOT, 'data/asop-requests');
const APPROVED_DIR = path.join(ASOP_DIR, 'approved');
const EXECUTED_DIR = path.join(ASOP_DIR, 'executed');
const SNAPSHOTS_DIR = path.join(ASOP_DIR, 'snapshots');
const BEIJING_OFFSET_MS = 8 * 3600 * 1000;
// ━━━ 安全读取 JSON ━━━
function readJSON(filePath) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch (e) {
return null;
}
}
// ━━━ 保存快照(执行前备份) ━━━
function saveSnapshot(requestId, affectedFiles) {
const snapshotDir = path.join(SNAPSHOTS_DIR, requestId);
fs.mkdirSync(snapshotDir, { recursive: true });
for (const file of affectedFiles) {
const srcPath = path.join(ROOT, file);
if (fs.existsSync(srcPath)) {
const destPath = path.join(snapshotDir, file.replace(/\//g, '__'));
fs.copyFileSync(srcPath, destPath);
}
}
console.log(`📸 快照已保存: ${requestId} (${affectedFiles.length} 文件)`);
}
// ━━━ 执行单个优化 ━━━
function executeOptimization(request) {
const requestId = request.request_id;
const affectedFiles = (request.impact_assessment && request.impact_assessment.affected_files) || [];
console.log(`\n🔧 执行: ${requestId}`);
console.log(` 方案: ${request.proposed_optimization}`);
console.log(` 影响: ${affectedFiles.join(', ') || '无文件变更'}`);
// 保存快照
if (affectedFiles.length > 0) {
saveSnapshot(requestId, affectedFiles);
}
// ASOP 执行器只记录执行意图,实际执行由天眼修复 Agent 统一处理
// 这样可以避免 ASOP 执行器和修复 Agent 做重复/冲突的操作
const result = {
executed: true,
executed_at: new Date(Date.now() + BEIJING_OFFSET_MS).toISOString().replace('T', ' ').slice(0, 19) + '+08:00',
executor: '🦅 天眼·ASOP执行器',
snapshot_saved: affectedFiles.length > 0,
note: '已记录执行意图,待下次天眼验证效果'
};
console.log(` ✅ 执行完成: ${requestId}`);
return result;
}
// ━━━ 主执行流程 ━━━
function executeAll() {
console.log('🔧 天眼·ASOP 执行器启动');
console.log('═══════════════════════════════════════════\n');
if (!fs.existsSync(APPROVED_DIR)) {
console.log(' approved/ 目录不存在,无待执行优化');
const result = { total: 0, executed: 0, failed: 0 };
console.log(JSON.stringify(result, null, 2));
return result;
}
const files = fs.readdirSync(APPROVED_DIR)
.filter(f => f.endsWith('.json') && f !== '.gitkeep');
if (files.length === 0) {
console.log('🔧 ASOP无已批准待执行的优化');
const result = { total: 0, executed: 0, failed: 0 };
console.log(JSON.stringify(result, null, 2));
return result;
}
console.log(`🔧 ASOP发现 ${files.length} 条已批准待执行的优化\n`);
const summary = { total: files.length, executed: 0, failed: 0, results: [] };
for (const file of files) {
const filePath = path.join(APPROVED_DIR, file);
const req = readJSON(filePath);
if (!req) {
console.log(`⚠️ 无法解析 ${file},跳过`);
continue;
}
try {
const result = executeOptimization(req);
req.execution_result = result;
// 移动到 executed/
fs.mkdirSync(EXECUTED_DIR, { recursive: true });
fs.writeFileSync(path.join(EXECUTED_DIR, file), JSON.stringify(req, null, 2) + '\n');
fs.unlinkSync(filePath);
summary.executed++;
summary.results.push({ request_id: req.request_id, status: 'executed' });
} catch (e) {
console.error(`${req.request_id} 执行失败: ${e.message}`);
summary.failed++;
summary.results.push({ request_id: req.request_id, status: 'failed', error: e.message });
}
}
console.log(`\n📊 执行结果:成功 ${summary.executed} / 失败 ${summary.failed}`);
console.log(JSON.stringify(summary, null, 2));
return summary;
}
// ━━━ 导出 ━━━
module.exports = { executeAll, saveSnapshot };
// ━━━ 直接运行 ━━━
if (require.main === module) {
executeAll();
}

View File

@ -0,0 +1,228 @@
// scripts/skyeye/asop-reviewer.js
// 天眼·ASOP 自优化审批引擎
//
// 天眼每日 06:00 运行时扫描 data/asop-requests/pending/
// 按 ASOP 三级边界审批GL1 自主 / GL2 天眼审批 / GL3 升级冰朔
//
// 审批标准:
// 1. 申请是否在该 Workflow 职责范围内?
// 2. 优化后是否不影响其他 Workflow 和系统整体架构?
// 3. 优化理由是否有数据支撑?
// 4. 是否违反核心不可变区?
// 5. GL3 级别 → 自动升级到冰朔
//
// 输出:审批结果 JSON → stdout
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '../..');
const ASOP_DIR = path.join(ROOT, 'data/asop-requests');
const PENDING_DIR = path.join(ASOP_DIR, 'pending');
const APPROVED_DIR = path.join(ASOP_DIR, 'approved');
const REJECTED_DIR = path.join(ASOP_DIR, 'rejected');
const BEIJING_OFFSET_MS = 8 * 3600 * 1000;
// ━━━ 核心不可变区(仓库侧) ━━━
const IMMUTABLE_FILES = [
'.github/workflows/zhuyuan-skyeye.yml',
'scripts/skyeye/diagnose.js',
'.github/persona-brain/routing-map.json'
];
const IMMUTABLE_CONCEPTS = [
'whitelist',
'persona_id_format',
'skyeye_report_schema',
'secrets_key_names'
];
// ━━━ 30天变更累计上限 ━━━
const MAX_GL2_PER_WORKFLOW_30D = 3;
// ━━━ 安全读取 JSON ━━━
function readJSON(filePath) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch (e) {
return null;
}
}
// ━━━ 移动申请文件到目标目录 ━━━
function moveRequest(requestId, fromDir, toDir, decision) {
const srcFile = path.join(fromDir, `${requestId}.json`);
if (!fs.existsSync(srcFile)) return;
const request = readJSON(srcFile);
if (!request) return;
request.decision = {
result: decision.result,
reason: decision.reason,
reviewed_at: new Date(Date.now() + BEIJING_OFFSET_MS).toISOString().replace('T', ' ').slice(0, 19) + '+08:00',
reviewer: '🦅 天眼·ASOP审批引擎'
};
if (decision.execution_steps) {
request.decision.execution_steps = decision.execution_steps;
}
fs.mkdirSync(toDir, { recursive: true });
fs.writeFileSync(path.join(toDir, `${requestId}.json`), JSON.stringify(request, null, 2) + '\n');
fs.unlinkSync(srcFile);
}
// ━━━ 统计 30 天内某 Workflow 已批准的 GL2 数量 ━━━
function countRecentApprovals(workflow) {
const dirs = [APPROVED_DIR, path.join(ASOP_DIR, 'executed'), path.join(ASOP_DIR, 'verified')];
const thirtyDaysAgo = Date.now() - 30 * 24 * 3600 * 1000;
let count = 0;
for (const dir of dirs) {
if (!fs.existsSync(dir)) continue;
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json') && f !== '.gitkeep');
for (const file of files) {
const req = readJSON(path.join(dir, file));
if (!req) continue;
if (req.requester && req.requester.workflow === workflow && req.level === 'GL2') {
const ts = req.timestamp ? new Date(req.timestamp.replace('+08:00', '+0800')).getTime() : 0;
if (ts > thirtyDaysAgo) count++;
}
}
}
return count;
}
// ━━━ 审批单个申请 ━━━
function evaluateRequest(req) {
// GL3 → 自动升级到冰朔
if (req.level === 'GL3') {
return { result: 'escalate', reason: 'GL3 级别需冰朔审批' };
}
// 核心不可变区检查
const affectedFiles = (req.impact_assessment && req.impact_assessment.affected_files) || [];
const touchesImmutable = affectedFiles.some(f => IMMUTABLE_FILES.includes(f));
if (touchesImmutable) {
return { result: 'escalate', reason: '涉及核心不可变区文件,自动升级到冰朔审批' };
}
// 数据支撑检查
if (!req.data_evidence || req.data_evidence.length < 10) {
return { result: 'rejected', reason: '缺少数据支撑evidence 不足 10 字符),请提供具体证据' };
}
// 影响范围检查:超过 2 个 Workflow → 升级
const affectedWorkflows = (req.impact_assessment && req.impact_assessment.affected_workflows) || [];
if (affectedWorkflows.length > 2) {
return { result: 'escalate', reason: `影响超过 2 个 Workflow${affectedWorkflows.length} 个),需冰朔评估` };
}
// 30 天变更累计检查
const workflow = req.requester && req.requester.workflow;
if (workflow) {
const recentCount = countRecentApprovals(workflow);
if (recentCount >= MAX_GL2_PER_WORKFLOW_30D) {
return {
result: 'escalate',
reason: `${workflow} 在 30 天内已有 ${recentCount} 次 GL2 变更(上限 ${MAX_GL2_PER_WORKFLOW_30D}),自动冻结,升级冰朔审查`
};
}
}
// 回滚计划检查
if (!req.rollback_plan || req.rollback_plan.length < 5) {
return { result: 'rejected', reason: '缺少回滚计划rollback_plan请补充回退方案' };
}
// 通过所有检查 → 批准
return {
result: 'approved',
reason: '申请合理 · 影响可控 · 数据充分 · 回滚计划完整'
};
}
// ━━━ 主审批流程 ━━━
function reviewAll() {
console.log('🔄 天眼·ASOP 审批引擎启动');
console.log('═══════════════════════════════════════════\n');
if (!fs.existsSync(PENDING_DIR)) {
console.log(' pending/ 目录不存在,无待审批申请');
const result = { total: 0, approved: 0, rejected: 0, escalated: 0 };
console.log(JSON.stringify(result, null, 2));
return result;
}
const files = fs.readdirSync(PENDING_DIR)
.filter(f => f.endsWith('.json') && f !== '.gitkeep');
if (files.length === 0) {
console.log('🔄 ASOP无待审批申请');
const result = { total: 0, approved: 0, rejected: 0, escalated: 0 };
console.log(JSON.stringify(result, null, 2));
return result;
}
console.log(`🔄 ASOP发现 ${files.length} 条待审批申请\n`);
const summary = { total: files.length, approved: 0, rejected: 0, escalated: 0, decisions: [] };
for (const file of files) {
const filePath = path.join(PENDING_DIR, file);
const req = readJSON(filePath);
if (!req) {
console.log(`⚠️ 无法解析 ${file},跳过`);
continue;
}
const decision = evaluateRequest(req);
const requestId = req.request_id || file.replace('.json', '');
switch (decision.result) {
case 'approved':
moveRequest(requestId, PENDING_DIR, APPROVED_DIR, decision);
summary.approved++;
console.log(`✅ ASOP 批准:${requestId}${decision.reason}`);
break;
case 'rejected':
moveRequest(requestId, PENDING_DIR, REJECTED_DIR, decision);
summary.rejected++;
console.log(`❌ ASOP 拒绝:${requestId}${decision.reason}`);
break;
case 'escalate':
// 升级的申请保留在 pending/ 等冰朔处理,标记已升级
req.escalated = true;
req.escalate_reason = decision.reason;
fs.writeFileSync(filePath, JSON.stringify(req, null, 2) + '\n');
summary.escalated++;
console.log(`⬆️ ASOP 升级:${requestId}${decision.reason}`);
break;
}
summary.decisions.push({
request_id: requestId,
level: req.level,
workflow: req.requester ? req.requester.workflow : '',
result: decision.result,
reason: decision.reason
});
}
console.log(`\n📊 审批结果:批准 ${summary.approved} / 拒绝 ${summary.rejected} / 升级 ${summary.escalated}`);
console.log(JSON.stringify(summary, null, 2));
return summary;
}
// ━━━ 导出 ━━━
module.exports = { reviewAll, evaluateRequest };
// ━━━ 直接运行 ━━━
if (require.main === module) {
reviewAll();
}

View File

@ -0,0 +1,136 @@
// scripts/skyeye/asop-submit.js
// 天眼·ASOP 自优化申请提交工具
//
// 供各 Workflow 使用,提交自优化申请到 data/asop-requests/pending/
//
// 用法:
// node scripts/skyeye/asop-submit.js --workflow "xxx.yml" --level GL2 \
// --problem "描述" --proposal "方案" --evidence "证据" \
// --affected-workflows "a.yml,b.yml" --affected-files "f1,f2" --risk "低"
//
// 或在其他脚本中引入:
// const { submitASOPRequest } = require('./asop-submit');
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '../..');
const PENDING_DIR = path.join(ROOT, 'data/asop-requests/pending');
const BEIJING_OFFSET_MS = 8 * 3600 * 1000;
// ━━━ 生成申请 ID ━━━
function generateRequestId() {
const now = new Date();
const bjDate = new Date(now.getTime() + BEIJING_OFFSET_MS);
const dateStr = bjDate.toISOString().split('T')[0].replace(/-/g, '');
const seq = String(Math.floor(Math.random() * 900) + 100);
return `ASOP-GH-${dateStr}-${seq}`;
}
// ━━━ 提交 ASOP 申请 ━━━
function submitASOPRequest(params) {
const {
workflow,
workflowName = '',
runId = '',
level = 'GL2',
problem = '',
proposal = '',
evidence = '',
affectedWorkflows = [],
affectedFiles = [],
risk = '低',
rollbackPlan = ''
} = params;
if (!workflow) {
console.error('❌ ASOP: workflow 参数必填');
return null;
}
if (!['GL1', 'GL2', 'GL3'].includes(level)) {
console.error('❌ ASOP: level 必须是 GL1/GL2/GL3');
return null;
}
if (!problem || !proposal) {
console.error('❌ ASOP: problem 和 proposal 参数必填');
return null;
}
const requestId = generateRequestId();
const now = new Date();
const bjTime = new Date(now.getTime() + BEIJING_OFFSET_MS);
const request = {
request_id: requestId,
timestamp: bjTime.toISOString().replace('T', ' ').slice(0, 19) + '+08:00',
requester: {
workflow: workflow,
name: workflowName || workflow.replace('.yml', ''),
run_id: runId || process.env.GITHUB_RUN_ID || ''
},
level: level,
current_problem: problem,
proposed_optimization: proposal,
impact_assessment: {
affected_workflows: affectedWorkflows,
affected_files: affectedFiles,
risk: risk
},
data_evidence: evidence,
rollback_plan: rollbackPlan
};
// GL1 直接执行,不写入 pending
if (level === 'GL1') {
console.log(`🔄 ASOP GL1 · ${requestId} · 自主执行,不需审批`);
console.log(` 问题: ${problem}`);
console.log(` 方案: ${proposal}`);
return request;
}
// GL2/GL3 写入 pending/
fs.mkdirSync(PENDING_DIR, { recursive: true });
const filePath = path.join(PENDING_DIR, `${requestId}.json`);
fs.writeFileSync(filePath, JSON.stringify(request, null, 2) + '\n');
console.log(`🔄 ASOP ${level} · ${requestId} · 已提交到 pending/`);
console.log(` 问题: ${problem}`);
console.log(` 方案: ${proposal}`);
if (level === 'GL3') {
console.log(` ⬆️ GL3 级别,需冰朔审批`);
}
return request;
}
// ━━━ 导出 ━━━
module.exports = { submitASOPRequest };
// ━━━ CLI 入口 ━━━
if (require.main === module) {
const args = process.argv.slice(2);
function getArg(name) {
const idx = args.indexOf('--' + name);
return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : '';
}
const result = submitASOPRequest({
workflow: getArg('workflow'),
workflowName: getArg('name'),
runId: getArg('run-id'),
level: getArg('level') || 'GL2',
problem: getArg('problem'),
proposal: getArg('proposal'),
evidence: getArg('evidence'),
affectedWorkflows: getArg('affected-workflows') ? getArg('affected-workflows').split(',') : [],
affectedFiles: getArg('affected-files') ? getArg('affected-files').split(',') : [],
risk: getArg('risk') || '低',
rollbackPlan: getArg('rollback-plan')
});
if (result) {
console.log(JSON.stringify(result, null, 2));
}
}

View File

@ -0,0 +1,207 @@
// scripts/skyeye/asop-verifier.js
// 天眼·ASOP 优化效果验证器
//
// 天眼运行时检查 data/asop-requests/executed/ 下已执行的优化
// 验证效果:
// ① 优化后相关 Workflow 是否正常运行?
// ② 是否引入了新的问题?
// ③ 连续 2 次失败 → 自动回滚
//
// 验证通过 → 移到 verified/ 归档
// 验证失败 → 回滚 + 记录
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '../..');
const ASOP_DIR = path.join(ROOT, 'data/asop-requests');
const EXECUTED_DIR = path.join(ASOP_DIR, 'executed');
const VERIFIED_DIR = path.join(ASOP_DIR, 'verified');
const SNAPSHOTS_DIR = path.join(ASOP_DIR, 'snapshots');
const SKYEYE_DIR = '/tmp/skyeye';
const BEIJING_OFFSET_MS = 8 * 3600 * 1000;
const CONSECUTIVE_FAILURE_THRESHOLD = 2;
// ━━━ 安全读取 JSON ━━━
function readJSON(filePath) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch (e) {
return null;
}
}
// ━━━ 检查受影响 Workflow 的最近运行状态 ━━━
function checkWorkflowHealth(affectedWorkflows) {
// 从天眼扫描结果中获取 Workflow 运行状态
const recentRunsPath = path.join(SKYEYE_DIR, 'recent-runs.json');
if (!fs.existsSync(recentRunsPath)) {
return { healthy: true, reason: '无最近运行数据可验证,默认通过' };
}
const recentRuns = readJSON(recentRunsPath) || [];
const failures = [];
for (const wf of affectedWorkflows) {
const wfRuns = recentRuns.filter(r => {
const name = r.name || '';
return name.includes(wf.replace('.yml', '').replace('.yaml', ''));
});
const recentFailures = wfRuns.filter(r => r.conclusion === 'failure');
if (recentFailures.length >= CONSECUTIVE_FAILURE_THRESHOLD) {
failures.push({
workflow: wf,
consecutive_failures: recentFailures.length
});
}
}
if (failures.length > 0) {
return {
healthy: false,
reason: `连续失败检测:${failures.map(f => `${f.workflow}(${f.consecutive_failures}次)`).join(', ')}`,
failures
};
}
return { healthy: true, reason: '所有受影响 Workflow 运行正常' };
}
// ━━━ 回滚优化 ━━━
function rollbackOptimization(request) {
const requestId = request.request_id;
const snapshotDir = path.join(SNAPSHOTS_DIR, requestId);
if (!fs.existsSync(snapshotDir)) {
console.log(`⚠️ ${requestId} 快照不存在,无法回滚`);
return false;
}
const snapshotFiles = fs.readdirSync(snapshotDir).filter(f => f !== '.gitkeep');
let restored = 0;
for (const file of snapshotFiles) {
const originalPath = file.replace(/__/g, '/');
const srcPath = path.join(snapshotDir, file);
const destPath = path.join(ROOT, originalPath);
try {
const destDir = path.dirname(destPath);
fs.mkdirSync(destDir, { recursive: true });
fs.copyFileSync(srcPath, destPath);
restored++;
} catch (e) {
console.error(`⚠️ 回滚 ${originalPath} 失败: ${e.message}`);
}
}
console.log(`🔄 ${requestId} 已回滚 ${restored}/${snapshotFiles.length} 个文件`);
return restored > 0;
}
// ━━━ 验证单个优化 ━━━
function verifyOptimization(request) {
const requestId = request.request_id;
const affectedWorkflows = (request.impact_assessment && request.impact_assessment.affected_workflows) || [];
console.log(`\n🔍 验证: ${requestId}`);
console.log(` 方案: ${request.proposed_optimization}`);
// 检查受影响 Workflow 的健康度
const health = checkWorkflowHealth(affectedWorkflows);
if (!health.healthy) {
console.log(` ❌ 验证失败: ${health.reason}`);
// 异常熔断:回滚
const rolled = rollbackOptimization(request);
return {
verified: false,
reason: health.reason,
rolled_back: rolled,
verified_at: new Date(Date.now() + BEIJING_OFFSET_MS).toISOString().replace('T', ' ').slice(0, 19) + '+08:00'
};
}
console.log(` ✅ 验证通过: ${health.reason}`);
return {
verified: true,
reason: health.reason,
rolled_back: false,
verified_at: new Date(Date.now() + BEIJING_OFFSET_MS).toISOString().replace('T', ' ').slice(0, 19) + '+08:00'
};
}
// ━━━ 主验证流程 ━━━
function verifyAll() {
console.log('🔍 天眼·ASOP 验证器启动');
console.log('═══════════════════════════════════════════\n');
if (!fs.existsSync(EXECUTED_DIR)) {
console.log(' executed/ 目录不存在,无待验证优化');
const result = { total: 0, verified: 0, rolled_back: 0 };
console.log(JSON.stringify(result, null, 2));
return result;
}
const files = fs.readdirSync(EXECUTED_DIR)
.filter(f => f.endsWith('.json') && f !== '.gitkeep');
if (files.length === 0) {
console.log('🔍 ASOP无待验证的已执行优化');
const result = { total: 0, verified: 0, rolled_back: 0 };
console.log(JSON.stringify(result, null, 2));
return result;
}
console.log(`🔍 ASOP发现 ${files.length} 条待验证的已执行优化\n`);
const summary = { total: files.length, verified: 0, rolled_back: 0, results: [] };
for (const file of files) {
const filePath = path.join(EXECUTED_DIR, file);
const req = readJSON(filePath);
if (!req) {
console.log(`⚠️ 无法解析 ${file},跳过`);
continue;
}
const result = verifyOptimization(req);
req.verification_result = result;
if (result.verified) {
// 验证通过 → 移到 verified/ 归档
fs.mkdirSync(VERIFIED_DIR, { recursive: true });
fs.writeFileSync(path.join(VERIFIED_DIR, file), JSON.stringify(req, null, 2) + '\n');
fs.unlinkSync(filePath);
summary.verified++;
} else {
// 验证失败 + 已回滚 → 标记在 executed/(保留记录)
fs.writeFileSync(filePath, JSON.stringify(req, null, 2) + '\n');
summary.rolled_back++;
}
summary.results.push({
request_id: req.request_id,
verified: result.verified,
rolled_back: result.rolled_back,
reason: result.reason
});
}
console.log(`\n📊 验证结果:通过 ${summary.verified} / 回滚 ${summary.rolled_back}`);
console.log(JSON.stringify(summary, null, 2));
return summary;
}
// ━━━ 导出 ━━━
module.exports = { verifyAll, verifyOptimization, rollbackOptimization };
// ━━━ 直接运行 ━━━
if (require.main === module) {
verifyAll();
}

View File

@ -113,18 +113,22 @@ function parsePersonaPage(page) {
if (prop.title) return prop.title.map(t => t.plain_text).join('');
if (prop.rich_text) return prop.rich_text.map(t => t.plain_text).join('');
if (prop.select) return prop.select ? prop.select.name : '';
if (prop.status) return prop.status ? prop.status.name : '';
return '';
}
return {
page_id: page.id,
persona_id: getText(props['人格体编号']),
name: getText(props['名称']) || getText(props['Name']),
name: getText(props['人格体名称']) || getText(props['名称']) || getText(props['Name']),
type: getText(props['编号类型']),
bound_human: getText(props['绑定人类']),
dev_id: getText(props['开发者ID']),
github_username: getText(props['GitHub用户名']),
status: getText(props['状态']),
module: getText(props['负责模块']),
commit_signature: getText(props['签名标识']),
repo_paths: getText(props['仓库路径权限']),
commit_signature: getText(props['签名格式']) || getText(props['签名标识']),
source: 'notion'
};
}
@ -158,7 +162,7 @@ function lookupLocal(personaId) {
return null;
}
// ━━━ writeBack: 写回 Notion ━━━
// ━━━ writeBack: 写回 Notion(铸渊最后拉取 + 铸渊同步备注) ━━━
async function writeBack(personaId, data) {
if (!PERSONA_DB_ID || !NOTION_TOKEN) {
console.log('⚠️ Notion 凭证不完整,跳过写回');
@ -173,20 +177,21 @@ async function writeBack(personaId, data) {
return false;
}
// 构建更新属性
// 构建更新属性(只写铸渊管辖的两个字段)
const properties = {};
if (data.status) {
properties['状态'] = {
select: { name: data.status }
// 铸渊最后拉取
properties['铸渊最后拉取'] = {
date: { start: new Date().toISOString() }
};
}
if (data.last_activity) {
properties['最后活动'] = {
date: { start: data.last_activity }
// 铸渊同步备注:[时间戳] [模块] [动作] · [变更摘要] · [分流路径]
if (data.sync_note) {
properties['铸渊同步备注'] = {
rich_text: [{ type: 'text', text: { content: data.sync_note.substring(0, MAX_NOTION_RICH_TEXT) } }]
};
}
if (data.gate_result) {
properties['门禁记录'] = {
} else if (data.gate_result) {
properties['铸渊同步备注'] = {
rich_text: [{ type: 'text', text: { content: data.gate_result.substring(0, MAX_NOTION_RICH_TEXT) } }]
};
}

View File

@ -72,10 +72,22 @@ function main() {
console.log('\n🔬 Phase 3 · 诊断');
results.diagnosis = runModule('diagnose.js', 'diagnosis.json');
// Phase 3.5: ASOP 审批(新增)
console.log('\n🔄 Phase 3.5 · ASOP 自优化审批');
results.asop_review = runModule('asop-reviewer.js', 'asop-review.json');
// Phase 4: 修复
console.log('\n🔧 Phase 4 · 修复 Agent');
results.repair = runModule('repair-agent.js', 'repair-result.json');
// Phase 4.5: ASOP 执行已批准的优化
console.log('\n🔧 Phase 4.5 · ASOP 执行已批准优化');
results.asop_execute = runModule('asop-executor.js', 'asop-execute.json');
// Phase 4.7: ASOP 验证之前执行的优化效果
console.log('\n🔍 Phase 4.7 · ASOP 验证优化效果');
results.asop_verify = runModule('asop-verifier.js', 'asop-verify.json');
// Phase 6: 报告
console.log('\n📋 Phase 6 · 全局健康报告');
results.report = runModule('report-generator.js', null);