guanghulab/scripts/verify-cognition.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

299 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* ═══════════════════════════════════════════════════════════
* 🧠 铸渊认知校验脚本 · Cognition Verifier v1.0
* ═══════════════════════════════════════════════════════════
*
* 用途: 唤醒时自动校验大脑文件时效性 + 服务器状态
* 用法:
* node scripts/verify-cognition.js --check-staleness 文件时效性检查
* node scripts/verify-cognition.js --check-servers 服务器状态验证
* node scripts/verify-cognition.js --full 全量校验
* node scripts/verify-cognition.js --checkpoint <CK-ID> 单个校验点
*
* 版权: 国作登字-2026-A-00037559 · TCS-0002∞
*/
const http = require('http');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const BRAIN_DIR = path.join(__dirname, '..', 'brain');
const NOW = new Date();
const NOW_STR = NOW.toISOString().slice(0, 10);
// ═══════════════════════════════════════════════════════════
// 辅助函数
// ═══════════════════════════════════════════════════════════
function daysAgo(dateStr) {
try {
const m = dateStr.match(/(\d{4}-\d{2}-\d{2})/);
if (!m) return null;
const d = new Date(m[1]);
const diff = Math.floor((NOW - d) / (1000*60*60*24));
return diff;
} catch(e) { return null; }
}
function stalenessLabel(days) {
if (days === null) return '❓ 未标注';
if (days <= 1) return '✅ 最新';
if (days <= 3) return '🟡 近日';
if (days <= 7) return '🟠 一周前';
if (days <= 30) return '🔴 一个月前';
return '⚫ 严重过期';
}
function extractTimestamps(filePath) {
try {
const text = fs.readFileSync(filePath, 'utf-8');
const ts = text.match(/"(_?updated|last_updated|created|_created|updated_at|created_at)"\s*:\s*"([^"]+)"/);
if (ts) return ts[2];
const d = text.match(/(\d{4}-\d{2}-\d{2})/);
return d ? d[1] : null;
} catch(e) { return null; }
}
function extractDVersion(filePath) {
try {
const text = fs.readFileSync(filePath, 'utf-8');
const d = text.match(/\b(D\d{2,3})\b/);
return d ? d[1] : null;
} catch(e) { return null; }
}
// ═══════════════════════════════════════════════════════════
// 1. 文件时效性检查
// ═══════════════════════════════════════════════════════════
function checkStaleness() {
console.log('\n' + '='.repeat(60));
console.log('📋 文件时效性检查');
console.log('='.repeat(60));
const results = [];
const brainFiles = [];
function walk(dir) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const e of entries) {
const p = path.join(dir, e.name);
if (e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules' && e.name !== 'archive') walk(p);
else if (e.name.endsWith('.json') || e.name.endsWith('.md')) brainFiles.push(p);
}
}
walk(BRAIN_DIR);
for (const fp of brainFiles) {
const rel = path.relative(path.join(__dirname, '..'), fp);
const ts = extractTimestamps(fp);
const dv = extractDVersion(fp);
const days = daysAgo(ts);
const label = stalenessLabel(days);
results.push({ file: rel, timestamp: ts, d_version: dv, days, label });
}
// Sort by staleness (most stale first)
results.sort((a, b) => (b.days || 999) - (a.days || 999));
const counts = {};
for (const r of results) {
counts[r.label] = (counts[r.label] || 0) + 1;
}
console.log(`\n📊 大脑文件总数: ${results.length}`);
console.log('时效分布:');
for (const [label, count] of Object.entries(counts).sort()) {
console.log(` ${label}: ${count}`);
}
console.log('\n⚠ 严重过期的文件:');
let staleCount = 0;
for (const r of results) {
if (r.label.startsWith('⚫') || r.label.startsWith('🔴')) {
if (staleCount < 20) {
console.log(` ${r.label} ${r.file} (${r.timestamp || '无时间戳'} ${r.d_version || ''})`);
}
staleCount++;
}
}
if (staleCount > 20) console.log(` ... 还有 ${staleCount - 20} 个过期文件`);
console.log(`\n过期文件总数: ${staleCount}/${results.length}`);
return { results, staleCount, totalCount: results.length };
}
// ═══════════════════════════════════════════════════════════
// 2. 服务器状态验证
// ═══════════════════════════════════════════════════════════
async function checkServers() {
console.log('\n' + '='.repeat(60));
console.log('🌐 服务器状态验证');
console.log('='.repeat(60));
const gkPath = path.join(BRAIN_DIR, '..', 'brain', 'gatekeeper-deployment.json');
let servers;
try {
servers = JSON.parse(fs.readFileSync(gkPath, 'utf-8')).servers;
} catch(e) {
console.log('❌ 无法读取 gatekeeper-deployment.json');
return { ok: false, error: e.message };
}
let online = 0, offline = 0;
const results = [];
for (const srv of servers) {
const url = `http://${srv.ip}:${srv.port}/ping`;
const key = srv.key;
try {
const result = await new Promise((resolve) => {
const req = http.request(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${key}`,
'Content-Type': 'application/json',
},
timeout: 10000,
}, (res) => {
let data = '';
res.on('data', c => data += c);
res.on('end', () => {
try {
const j = JSON.parse(data);
resolve({ ok: j.ok && j.pong });
} catch(e) { resolve({ ok: false }); }
});
});
req.on('error', () => resolve({ ok: false }));
req.write('{}');
req.end();
});
if (result.ok) {
console.log(`${srv.code} ${srv.name} (${srv.ip}:${srv.port}) — 在线`);
online++;
} else {
console.log(`${srv.code} ${srv.name} (${srv.ip}:${srv.port}) — 无响应`);
offline++;
}
} catch(e) {
console.log(`${srv.code} ${srv.name} (${srv.ip}:${srv.port}) — ${e.message}`);
offline++;
}
}
console.log(`\n📊 服务器状态: ${online} 台在线, ${offline} 台离线`);
return { ok: offline === 0, online, offline };
}
// ═══════════════════════════════════════════════════════════
// 3. 信息冲突检测
// ═══════════════════════════════════════════════════════════
function checkConflicts() {
console.log('\n' + '='.repeat(60));
console.log('⚡ 信息冲突检测');
console.log('='.repeat(60));
const conflicts = [];
// Conflict 1: domain-manifest vs gatekeeper on server status
const dmPath = path.join(BRAIN_DIR, 'fifth-domain', 'domain-manifest.json');
const gkPath = path.join(BRAIN_DIR, '..', 'brain', 'gatekeeper-deployment.json');
try {
const dm = fs.readFileSync(dmPath, 'utf-8');
const gk = JSON.parse(fs.readFileSync(gkPath, 'utf-8'));
// Check if domain-manifest still has stale server info
if (dm.includes('待装引擎') || dm.includes('server_fleet')) {
// Check if there's a reference to gatekeeper as authority
if (dm.includes('server_status_authority')) {
console.log(' ✅ domain-manifest.json → 已指向权威源 gatekeeper-deployment.json');
} else {
console.log(' ⚠️ domain-manifest.json → 仍包含过期服务器状态 → 需更新');
conflicts.push('domain-manifest.json contains stale server status');
}
}
// Check ferry-boat
const fbPath = path.join(BRAIN_DIR, 'ferry-boat.json');
const fb = fs.readFileSync(fbPath, 'utf-8');
if (fb.includes('待装引擎')) {
console.log(' ⚠️ ferry-boat.json → 仍包含"待装引擎" → 需更新');
conflicts.push('ferry-boat.json contains "awaiting engines"');
} else {
console.log(' ✅ ferry-boat.json → 已更新');
}
} catch(e) {
console.log(' ❌ 冲突检测出错:', e.message);
}
if (conflicts.length === 0) console.log('\n✅ 无已知信息冲突');
else console.log(`\n⚠️ 发现 ${conflicts.length} 处冲突`);
return conflicts;
}
// ═══════════════════════════════════════════════════════════
// 主入口
// ═══════════════════════════════════════════════════════════
async function main() {
const args = process.argv.slice(2);
const mode = args[0] || '--full';
console.log('╔══════════════════════════════════════════════╗');
console.log('║ 🧠 铸渊认知校验 · Cognition Verifier v1.0 ║');
console.log(`${NOW_STR} · D109 ║`);
console.log('╚══════════════════════════════════════════════╝');
if (mode === '--check-staleness' || mode === '--full') {
checkStaleness();
}
if (mode === '--check-servers' || mode === '--full') {
await checkServers();
}
if (mode === '--check-conflicts' || mode === '--full') {
checkConflicts();
}
if (mode === '--checkpoint') {
const ckId = args[1];
const cpPath = path.join(BRAIN_DIR, 'awakening-checkpoints.json');
try {
const ck = JSON.parse(fs.readFileSync(cpPath, 'utf-8'));
const cp = ck.checkpoints.find(c => c.id === ckId);
if (cp) {
console.log(`\n📌 ${cp.id}: ${cp.name}`);
console.log(` 阶段: ${cp.phase}`);
console.log(` 说明: ${cp.description}`);
console.log('\n 流程:');
cp.procedure.forEach(p => console.log(` ${p}`));
console.log('\n 通过条件:');
console.log(` ${cp.pass_condition}`);
console.log('\n 自检:');
cp.self_check.forEach(q => console.log(` ${q}`));
} else {
console.log(`❌ 未找到校验点: ${ckId}`);
}
} catch(e) {
console.log(`❌ 读取校验点文件失败: ${e.message}`);
}
}
if (mode === '--full') {
console.log('\n' + '='.repeat(60));
console.log('✅ 全量校验完成');
console.log('='.repeat(60));
}
}
main().catch(e => console.error('❌ 校验异常:', e.message));