275 lines
8.5 KiB
JavaScript
275 lines
8.5 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
/**
|
|||
|
|
* 零点图书域 · 编号路由引擎 · number-router.js
|
|||
|
|
* ZP-REG-001 · D132 · 铸渊 TCS-0003-ZY001
|
|||
|
|
*
|
|||
|
|
* 功能:给定编号路径 → 返回文件内容
|
|||
|
|
* 编号格式: ZP-REG-001/分馆/类别/书编号/卷/章
|
|||
|
|
* 示例: ZP-REG-001/ICE/ZY/TCS-0003-ZY001/CC/008
|
|||
|
|
*
|
|||
|
|
* 原理:编号路径直接映射到仓库文件路径。
|
|||
|
|
* 不需要搜索。不需要索引。路径即地址。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
const { execSync } = require('child_process');
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
|
|||
|
|
const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
|
|||
|
|
|
|||
|
|
// ==================== 编号→文件路径 映射表 ====================
|
|||
|
|
|
|||
|
|
const ROUTE_MAP = {
|
|||
|
|
'ZP-REG-001': {
|
|||
|
|
name: '零点图书域',
|
|||
|
|
halls: {
|
|||
|
|
ICE: {
|
|||
|
|
name: '第五域分馆',
|
|||
|
|
categories: {
|
|||
|
|
ZY: {
|
|||
|
|
name: '铸渊主控',
|
|||
|
|
books: {
|
|||
|
|
'TCS-0003-ZY001': {
|
|||
|
|
name: '铸渊之书',
|
|||
|
|
volumes: {
|
|||
|
|
CC: {
|
|||
|
|
name: '认知链卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/causal-chains',
|
|||
|
|
filePattern: (chapter) =>
|
|||
|
|
`brain/fifth-domain/zero-point/zhuyuan/causal-chains/cc-${String(chapter).padStart(3, '0')}*.hdlp`
|
|||
|
|
},
|
|||
|
|
WA: {
|
|||
|
|
name: '世界架构卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/world-architecture',
|
|||
|
|
filePattern: (chapter) =>
|
|||
|
|
`brain/fifth-domain/zero-point/zhuyuan/world-architecture/*.hdlp`
|
|||
|
|
},
|
|||
|
|
NL: {
|
|||
|
|
name: '国家灯塔卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/world-architecture',
|
|||
|
|
files: {
|
|||
|
|
'001': 'national-lighthouse-architecture.hdlp'
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
TC: {
|
|||
|
|
name: 'TCS核心卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/tcs-core',
|
|||
|
|
files: {
|
|||
|
|
'000': 'ICE-GL-ZY001-TCS-CORE.hdlp',
|
|||
|
|
'001': 'permanent-memory-kernel.hdlp',
|
|||
|
|
'002': 'WHO-I-AM.hdlp'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ==================== 编号解析 ====================
|
|||
|
|
|
|||
|
|
function parseRoute(tracePath) {
|
|||
|
|
// ZP-REG-001/ICE/ZY/TCS-0003-ZY001/CC/008
|
|||
|
|
const parts = tracePath.split('/');
|
|||
|
|
if (parts.length < 5) {
|
|||
|
|
return { error: `编号路径不完整: ${tracePath}。至少需要 域/馆/类/书/卷` };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const [domain, hall, category, book, volume, chapter] = parts;
|
|||
|
|
|
|||
|
|
const domainConfig = ROUTE_MAP[domain];
|
|||
|
|
if (!domainConfig) return { error: `未知图书域: ${domain}` };
|
|||
|
|
|
|||
|
|
const hallConfig = domainConfig.halls[hall];
|
|||
|
|
if (!hallConfig) return { error: `未知分馆: ${hall}` };
|
|||
|
|
|
|||
|
|
const catConfig = hallConfig.categories[category];
|
|||
|
|
if (!catConfig) return { error: `未知类别: ${category}` };
|
|||
|
|
|
|||
|
|
const bookConfig = catConfig.books[book];
|
|||
|
|
if (!bookConfig) return { error: `未知书籍: ${book}` };
|
|||
|
|
|
|||
|
|
const volConfig = bookConfig.volumes[volume];
|
|||
|
|
if (!volConfig) return { error: `未知卷: ${volume}。已知卷: ${Object.keys(bookConfig.volumes).join(', ')}` };
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
domain: domainConfig.name,
|
|||
|
|
hall: hallConfig.name,
|
|||
|
|
category: catConfig.name,
|
|||
|
|
book: bookConfig.name,
|
|||
|
|
volume: volConfig.name,
|
|||
|
|
chapter: chapter || null,
|
|||
|
|
volConfig,
|
|||
|
|
parts: { domain, hall, category, book, volume, chapter }
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 文件查找 ====================
|
|||
|
|
|
|||
|
|
function findFile(volConfig, chapter) {
|
|||
|
|
if (!chapter) {
|
|||
|
|
// 没有章节号 → 返回卷内所有文件
|
|||
|
|
if (volConfig.basePath) {
|
|||
|
|
try {
|
|||
|
|
const dirPath = path.join(REPO_ROOT, volConfig.basePath);
|
|||
|
|
if (fs.existsSync(dirPath)) {
|
|||
|
|
return { type: 'directory', files: fs.readdirSync(dirPath).filter(f => f.endsWith('.hdlp') || f.endsWith('.md')) };
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
return { error: `卷目录不存在: ${volConfig.basePath}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return { error: '需要指定章节号' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 精确文件查找
|
|||
|
|
if (volConfig.files && volConfig.files[chapter]) {
|
|||
|
|
const filePath = path.join(volConfig.basePath, volConfig.files[chapter]);
|
|||
|
|
return { type: 'file', path: filePath };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 模式匹配查找
|
|||
|
|
if (volConfig.filePattern) {
|
|||
|
|
const pattern = volConfig.filePattern(chapter);
|
|||
|
|
try {
|
|||
|
|
const result = execSync(
|
|||
|
|
`cd "${REPO_ROOT}" && ls ${pattern} 2>/dev/null | head -1`,
|
|||
|
|
{ encoding: 'utf8' }
|
|||
|
|
).trim();
|
|||
|
|
if (result) {
|
|||
|
|
return { type: 'file', path: result };
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
// 模式匹配失败
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { error: `未找到章节 ${chapter} 在卷 ${volConfig.name} 中` };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 内容读取 ====================
|
|||
|
|
|
|||
|
|
function readContent(filePath) {
|
|||
|
|
const fullPath = path.join(REPO_ROOT, filePath);
|
|||
|
|
if (!fs.existsSync(fullPath)) {
|
|||
|
|
// 尝试从 git 读取
|
|||
|
|
try {
|
|||
|
|
return execSync(`cd "${REPO_ROOT}" && git show HEAD:"${filePath}"`, {
|
|||
|
|
encoding: 'utf8', maxBuffer: 10 * 1024 * 1024
|
|||
|
|
});
|
|||
|
|
} catch (e) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return fs.readFileSync(fullPath, 'utf8');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 主函数 ====================
|
|||
|
|
|
|||
|
|
function resolve(tracePath) {
|
|||
|
|
const route = parseRoute(tracePath);
|
|||
|
|
if (route.error) return route;
|
|||
|
|
|
|||
|
|
const fileResult = findFile(route.volConfig, route.chapter);
|
|||
|
|
if (fileResult.error) return { ...route, error: fileResult.error };
|
|||
|
|
|
|||
|
|
if (fileResult.type === 'directory') {
|
|||
|
|
return {
|
|||
|
|
...route,
|
|||
|
|
type: 'directory',
|
|||
|
|
files: fileResult.files
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const content = readContent(fileResult.path);
|
|||
|
|
if (!content) {
|
|||
|
|
return { ...route, error: `文件无法读取: ${fileResult.path}` };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提取四核心字段
|
|||
|
|
const hldp = extractHldpFields(content);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
...route,
|
|||
|
|
type: 'file',
|
|||
|
|
path: fileResult.path,
|
|||
|
|
size: content.length,
|
|||
|
|
content,
|
|||
|
|
hldp
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== HLDP 字段提取 ====================
|
|||
|
|
|
|||
|
|
function extractHldpFields(content) {
|
|||
|
|
const fields = {};
|
|||
|
|
const trigger = content.match(/trigger:\s*(.+)/);
|
|||
|
|
const emergence = content.match(/emergence:\s*([\s\S]*?)(?=\n\s*lock:|\n\s*why:|\n\s*△=|\Z)/);
|
|||
|
|
const lock = content.match(/lock:\s*(.+)/);
|
|||
|
|
const why = content.match(/why:\s*(.+)/);
|
|||
|
|
|
|||
|
|
if (trigger) fields.trigger = trigger[1].trim();
|
|||
|
|
if (emergence) fields.emergence = emergence[1].trim().substring(0, 500);
|
|||
|
|
if (lock) fields.lock = lock[1].trim();
|
|||
|
|
if (why) fields.why = why[1].trim();
|
|||
|
|
|
|||
|
|
return fields;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== CLI ====================
|
|||
|
|
|
|||
|
|
if (require.main === module) {
|
|||
|
|
const tracePath = process.argv[2];
|
|||
|
|
|
|||
|
|
if (!tracePath) {
|
|||
|
|
console.log('零点图书域 · 编号路由引擎 · ZP-REG-001');
|
|||
|
|
console.log('');
|
|||
|
|
console.log('用法: node number-router.js <编号路径>');
|
|||
|
|
console.log('');
|
|||
|
|
console.log('示例:');
|
|||
|
|
console.log(' node number-router.js ZP-REG-001/ICE/ZY/TCS-0003-ZY001/CC/008');
|
|||
|
|
console.log(' node number-router.js ZP-REG-001/ICE/ZY/TCS-0003-ZY001/TC/001');
|
|||
|
|
console.log(' node number-router.js ZP-REG-001/ICE/ZY/TCS-0003-ZY001/CC');
|
|||
|
|
console.log('');
|
|||
|
|
console.log('已知卷:');
|
|||
|
|
const book = ROUTE_MAP['ZP-REG-001'].halls.ICE.categories.ZY.books['TCS-0003-ZY001'];
|
|||
|
|
for (const [volCode, vol] of Object.entries(book.volumes)) {
|
|||
|
|
console.log(` ${volCode} — ${vol.name} (${vol.basePath})`);
|
|||
|
|
}
|
|||
|
|
process.exit(0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const result = resolve(tracePath);
|
|||
|
|
|
|||
|
|
if (result.error) {
|
|||
|
|
console.error(`✗ ${result.error}`);
|
|||
|
|
process.exit(1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log(`⊢ ${result.domain} → ${result.hall} → ${result.category} → ${result.book}`);
|
|||
|
|
console.log(`⊢ 卷: ${result.volume}` + (result.chapter ? ` · 章: ${result.chapter}` : ''));
|
|||
|
|
console.log('');
|
|||
|
|
|
|||
|
|
if (result.type === 'directory') {
|
|||
|
|
console.log(`卷内文件 (${result.files.length}):`);
|
|||
|
|
result.files.forEach(f => console.log(` 📄 ${f}`));
|
|||
|
|
} else {
|
|||
|
|
console.log(`文件: ${result.path} (${result.size}B)`);
|
|||
|
|
if (result.hldp && Object.keys(result.hldp).length > 0) {
|
|||
|
|
console.log('');
|
|||
|
|
console.log('═══ HLDP 四核心字段 ═══');
|
|||
|
|
if (result.hldp.trigger) console.log(`trigger: ${result.hldp.trigger}`);
|
|||
|
|
if (result.hldp.lock) console.log(`lock: ${result.hldp.lock}`);
|
|||
|
|
if (result.hldp.why) console.log(`why: ${result.hldp.why}`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = { resolve, parseRoute, ROUTE_MAP };
|