guanghulab/scripts/zhuyuan-module-protocol.js
2026-05-10 13:12:44 +08:00

301 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* 🌀 铸渊人格协议 · 模块生命周期管理脚本 v1.0
*
* 用法:
* node scripts/zhuyuan-module-protocol.js inspect # 全模块检查
* node scripts/zhuyuan-module-protocol.js inspect <module-id> # 单模块检查
* node scripts/zhuyuan-module-protocol.js status # 模块状态汇总
* node scripts/zhuyuan-module-protocol.js recover <module-id> # 模块回收检查
* node scripts/zhuyuan-module-protocol.js preview # 预演报告生成
*
* 纯 Node.js无外部依赖。
*/
const fs = require('fs');
const path = require('path');
// === 配置 ===
const ROOT = path.resolve(__dirname, '..');
const BRAIN_DIR = path.join(ROOT, '.github', 'brain');
const DOCS_DIR = path.join(ROOT, 'docs');
// 模块注册表
const MODULE_REGISTRY = {
'm01-login': { owner: 'DEV-002', name: '肥猫', hli: 'AUTH', label: '登录模块' },
'm03-personality': { owner: 'DEV-002', name: '肥猫', hli: 'PERSONA', label: '人格模块' },
'm05-user-center': { owner: 'DEV-009', name: '花尔', hli: 'USER', label: '用户中心' },
'm06-ticket': { owner: 'DEV-010', name: '桔子', hli: 'TICKET', label: '工单系统' },
'm07-dialogue-ui': { owner: 'DEV-003', name: '燕樊', hli: 'DIALOGUE', label: '对话界面' },
'm10-cloud': { owner: 'DEV-003', name: '燕樊', hli: 'STORAGE', label: '云存储' },
'm11-module': { owner: 'DEV-010', name: '桔子', hli: 'MODULE', label: '模块管理' },
'm12-kanban': { owner: 'DEV-005', name: '小草莓', hli: 'DASHBOARD', label: '看板' },
'm15-cloud-drive': { owner: 'DEV-003', name: '燕樊', hli: 'STORAGE', label: '云盘' },
'm18-health-check':{ owner: null, name: '待分配', hli: 'SYSTEM', label: '健康检查' },
};
// === 工具函数 ===
function countFiles(dir) {
if (!fs.existsSync(dir)) return 0;
let count = 0;
const items = fs.readdirSync(dir, { withFileTypes: true });
for (const item of items) {
if (item.name.startsWith('.')) continue;
if (item.isFile()) count++;
else if (item.isDirectory()) count += countFiles(path.join(dir, item.name));
}
return count;
}
function hasReadme(dir) {
return fs.existsSync(path.join(dir, 'README.md'));
}
function getModuleStatus(moduleDir) {
const fullPath = path.join(ROOT, moduleDir);
if (!fs.existsSync(fullPath)) return { exists: false, files: 0, readme: false };
const files = countFiles(fullPath);
const readme = hasReadme(fullPath);
let status = '📭 空';
if (files > 0 && readme) status = '✅ 正常';
else if (files > 0 && !readme) status = '⚠️ 缺README';
else if (files === 0) status = '📭 空';
return { exists: true, files, readme, status };
}
// === 命令inspect ===
function cmdInspect(moduleId) {
console.log('🌀 铸渊人格协议 · 模块检查');
console.log('─'.repeat(50));
if (moduleId) {
// 单模块检查
const info = MODULE_REGISTRY[moduleId];
if (!info) {
console.log(`❌ 未知模块: ${moduleId}`);
console.log(`已注册模块: ${Object.keys(MODULE_REGISTRY).join(', ')}`);
process.exit(1);
}
const status = getModuleStatus(moduleId);
console.log(`\n📦 模块: ${moduleId} (${info.label})`);
console.log(` 负责人: ${info.name} (${info.owner || '未分配'})`);
console.log(` HLI 域: ${info.hli}`);
console.log(` 目录存在: ${status.exists ? '✅' : '❌'}`);
console.log(` 文件数量: ${status.files}`);
console.log(` README: ${status.readme ? '✅' : '❌'}`);
console.log(` 状态: ${status.status}`);
// 检查 HLI 接口
const schemaDir = path.join(ROOT, 'src', 'schemas', 'hli', info.hli.toLowerCase());
const routeDir = path.join(ROOT, 'src', 'routes', 'hli', info.hli.toLowerCase());
if (fs.existsSync(schemaDir)) {
try {
const schemas = fs.readdirSync(schemaDir).filter(f => f.endsWith('.schema.json'));
console.log(` HLI Schema: ${schemas.length} 个 (${schemas.join(', ')})`);
} catch (e) {
console.log(` HLI Schema: ⚠️ 读取失败 (${e.code || e.message})`);
}
} else {
console.log(` HLI Schema: 📭 未创建`);
}
if (fs.existsSync(routeDir)) {
try {
const routes = fs.readdirSync(routeDir).filter(f => f.endsWith('.js'));
console.log(` HLI 路由: ${routes.length} 个 (${routes.join(', ')})`);
} catch (e) {
console.log(` HLI 路由: ⚠️ 读取失败 (${e.code || e.message})`);
}
} else {
console.log(` HLI 路由: 📭 未创建`);
}
} else {
// 全模块检查
console.log('\n📋 全模块状态:\n');
console.log('模块ID | 标签 | 负责人 | 文件 | README | 状态');
console.log('─'.repeat(70));
for (const [id, info] of Object.entries(MODULE_REGISTRY)) {
const status = getModuleStatus(id);
const line = [
id.padEnd(20),
info.label.padEnd(8),
info.name.padEnd(8),
String(status.files).padStart(4),
(status.readme ? '✅' : '❌').padEnd(6),
status.status,
].join(' | ');
console.log(line);
}
}
}
// === 命令status ===
function cmdStatus() {
console.log('🌀 铸渊人格协议 · 模块状态汇总');
console.log('─'.repeat(50));
let total = 0, ok = 0, warn = 0, empty = 0;
for (const [id] of Object.entries(MODULE_REGISTRY)) {
total++;
const status = getModuleStatus(id);
if (status.files > 0 && status.readme) ok++;
else if (status.files > 0) warn++;
else empty++;
}
console.log(`\n📊 模块统计:`);
console.log(` 总模块数: ${total}`);
console.log(` ✅ 正常: ${ok}`);
console.log(` ⚠️ 告警: ${warn}`);
console.log(` 📭 空模块: ${empty}`);
console.log(` 完成率: ${Math.round((ok / total) * 100)}%`);
// 检查前端
const indexPath = path.join(DOCS_DIR, 'index.html');
if (fs.existsSync(indexPath)) {
const stat = fs.statSync(indexPath);
const lines = fs.readFileSync(indexPath, 'utf8').split('\n').length;
console.log(`\n🌐 前端:`);
console.log(` docs/index.html: ${lines} 行, ${(stat.size / 1024).toFixed(1)} KB`);
}
// 检查 CNAME
const cnamePath = path.join(DOCS_DIR, 'CNAME');
if (fs.existsSync(cnamePath)) {
const domain = fs.readFileSync(cnamePath, 'utf8').trim();
console.log(` 自定义域名: ${domain}`);
} else {
console.log(` 自定义域名: ❌ 未配置`);
}
// 检查大脑文件
console.log(`\n🧠 大脑状态:`);
const brainFiles = ['repo-snapshot.md', 'repo-map.json', 'memory.json', 'collaborators.json', 'module-protocol.md'];
for (const f of brainFiles) {
const fp = path.join(BRAIN_DIR, f);
if (fs.existsSync(fp)) {
const stat = fs.statSync(fp);
console.log(`${f} (${(stat.size / 1024).toFixed(1)} KB)`);
} else {
console.log(`${f} 缺失`);
}
}
}
// === 命令recover ===
function cmdRecover(moduleId) {
if (!moduleId) {
console.log('❌ 请指定模块ID如: npm run module:protocol -- recover m01-login');
process.exit(1);
}
const info = MODULE_REGISTRY[moduleId];
if (!info) {
console.log(`❌ 未知模块: ${moduleId}`);
process.exit(1);
}
console.log('🌀 铸渊人格协议 · 模块回收检查');
console.log('─'.repeat(50));
console.log(`\n📦 目标模块: ${moduleId} (${info.label})`);
const status = getModuleStatus(moduleId);
console.log(` 当前状态: ${status.status}`);
console.log(` 文件数量: ${status.files}`);
if (status.files === 0) {
console.log(`\n✅ 模块已为空状态,无需回收。`);
return;
}
console.log(`\n⚠️ 回收操作需要手动执行:`);
console.log(` 方法一(推荐): 通过 PR 删除模块文件`);
console.log(` 方法二: git revert 恢复到模块的上一个版本`);
console.log(` 方法三: 直接在 GitHub 界面删除文件`);
console.log(`\n💡 回收后,铸渊会通过 generate-module-doc.yml 更新文档索引。`);
}
// === 命令preview ===
function cmdPreview() {
console.log('🌀 铸渊人格协议 · 本地预演报告');
console.log('═'.repeat(50));
// 模块状态
cmdStatus();
console.log('\n');
console.log('─'.repeat(50));
console.log('🎯 预演结论:');
let ok = true;
const issues = [];
// 检查 index.html
if (!fs.existsSync(path.join(DOCS_DIR, 'index.html'))) {
issues.push('docs/index.html 不存在');
ok = false;
}
// 检查工作流
const wfDir = path.join(ROOT, '.github', 'workflows');
if (!fs.existsSync(path.join(wfDir, 'deploy-pages.yml'))) {
issues.push('deploy-pages.yml 不存在');
ok = false;
}
if (ok && issues.length === 0) {
console.log('✅ 预演通过 — 代码可以安全部署到生产环境');
console.log(' 下一步: 合并 PR 到 main 分支,触发自动部署');
} else {
console.log('❌ 预演未通过:');
issues.forEach(i => console.log(` - ${i}`));
}
}
// === 主入口 ===
const [,, command, ...args] = process.argv;
switch (command) {
case 'inspect':
cmdInspect(args[0]);
break;
case 'status':
cmdStatus();
break;
case 'recover':
cmdRecover(args[0]);
break;
case 'preview':
cmdPreview();
break;
default:
console.log('🌀 铸渊人格协议 · 模块生命周期管理 v1.0');
console.log('');
console.log('用法:');
console.log(' node scripts/zhuyuan-module-protocol.js inspect 全模块检查');
console.log(' node scripts/zhuyuan-module-protocol.js inspect <module-id> 单模块检查');
console.log(' node scripts/zhuyuan-module-protocol.js status 模块状态汇总');
console.log(' node scripts/zhuyuan-module-protocol.js recover <module-id> 模块回收检查');
console.log(' node scripts/zhuyuan-module-protocol.js preview 本地预演报告');
console.log('');
console.log('npm 快捷命令:');
console.log(' npm run module:protocol -- inspect');
console.log(' npm run module:protocol -- status');
console.log(' npm run module:protocol -- preview');
break;
}