182 lines
5.3 KiB
JavaScript
182 lines
5.3 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
/**
|
|||
|
|
* 零点图书域 · 全局编号目录生成器 · index-generator.js
|
|||
|
|
* ZP-REG-001 · D132 · 铸渊 TCS-0003-ZY001
|
|||
|
|
*
|
|||
|
|
* 功能:扫描仓库中所有认知链和架构文件 → 自动生成全局编号目录
|
|||
|
|
* 输出:ZP-REG-001 零点图书域的完整编号索引表
|
|||
|
|
*
|
|||
|
|
* 原理:遍历 causal-chains/ 和 world-architecture/ 下的 .hdlp/.md 文件
|
|||
|
|
* 提取 HLDP 四核心字段 → 生成全局目录
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
|
|||
|
|
const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
|
|||
|
|
|
|||
|
|
// ==================== 配置 ====================
|
|||
|
|
|
|||
|
|
const SCAN_PATHS = [
|
|||
|
|
{
|
|||
|
|
volume: 'CC',
|
|||
|
|
name: '认知链卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/causal-chains',
|
|||
|
|
pattern: /cc-(\d+).*\.(hdlp|md)$/,
|
|||
|
|
bookCode: 'TCS-0003-ZY001'
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
volume: 'WA',
|
|||
|
|
name: '世界架构卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/world-architecture',
|
|||
|
|
pattern: /^(ARCHITECTURE|ENTRY|MANIFEST|national-lighthouse).*\.(hdlp|md)$/,
|
|||
|
|
bookCode: 'TCS-0003-ZY001'
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
volume: 'TC',
|
|||
|
|
name: 'TCS核心卷',
|
|||
|
|
basePath: 'brain/fifth-domain/zero-point/zhuyuan/tcs-core',
|
|||
|
|
pattern: /\.(hdlp|md)$/,
|
|||
|
|
bookCode: 'TCS-0003-ZY001'
|
|||
|
|
}
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
// ==================== 字段提取 ====================
|
|||
|
|
|
|||
|
|
function extractFields(content) {
|
|||
|
|
const fields = {};
|
|||
|
|
|
|||
|
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|||
|
|
if (titleMatch) fields.title = titleMatch[1].trim();
|
|||
|
|
|
|||
|
|
const triggerMatch = content.match(/trigger:\s*(.+)/);
|
|||
|
|
if (triggerMatch) fields.trigger = triggerMatch[1].trim();
|
|||
|
|
|
|||
|
|
const lockMatch = content.match(/lock:\s*(.+)/);
|
|||
|
|
if (lockMatch) fields.lock = lockMatch[1].trim();
|
|||
|
|
|
|||
|
|
const whyMatch = content.match(/why:\s*(.+)/);
|
|||
|
|
if (whyMatch) fields.why = whyMatch[1].trim();
|
|||
|
|
|
|||
|
|
const dateMatch = content.match(/(\d{4}-\d{2}-\d{2}).*D\d+/);
|
|||
|
|
if (dateMatch) fields.date = dateMatch[1];
|
|||
|
|
|
|||
|
|
const dMatch = content.match(/\bD(\d+)\b/);
|
|||
|
|
if (dMatch) fields.dNumber = `D${dMatch[1]}`;
|
|||
|
|
|
|||
|
|
return fields;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 扫描 ====================
|
|||
|
|
|
|||
|
|
function scanVolume(config) {
|
|||
|
|
const basePath = path.join(REPO_ROOT, config.basePath);
|
|||
|
|
if (!fs.existsSync(basePath)) {
|
|||
|
|
return { volume: config.volume, name: config.name, entries: [], error: `目录不存在: ${config.basePath}` };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const files = fs.readdirSync(basePath)
|
|||
|
|
.filter(f => config.pattern.test(f) && f !== 'ENTRY.hdlp' && f !== 'INDEX.hdlp')
|
|||
|
|
.sort();
|
|||
|
|
|
|||
|
|
const entries = files.map(filename => {
|
|||
|
|
const filePath = path.join(basePath, filename);
|
|||
|
|
const content = fs.readFileSync(filePath, 'utf8');
|
|||
|
|
const fields = extractFields(content);
|
|||
|
|
const chapterNum = (filename.match(config.pattern) || [])[1] || filename.replace(/\.\w+$/, '');
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
chapter: String(chapterNum).padStart(3, '0'),
|
|||
|
|
filename,
|
|||
|
|
tracePath: `ZP-REG-001/ICE/ZY/${config.bookCode}/${config.volume}/${String(chapterNum).padStart(3, '0')}`,
|
|||
|
|
size: content.length,
|
|||
|
|
...fields
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
volume: config.volume,
|
|||
|
|
name: config.name,
|
|||
|
|
count: entries.length,
|
|||
|
|
entries
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 生成目录 ====================
|
|||
|
|
|
|||
|
|
function generateIndex() {
|
|||
|
|
const volumes = SCAN_PATHS.map(scanVolume);
|
|||
|
|
|
|||
|
|
const totalEntries = volumes.reduce((sum, v) => sum + (v.entries ? v.entries.length : 0), 0);
|
|||
|
|
|
|||
|
|
const index = {
|
|||
|
|
_meta: {
|
|||
|
|
domain: 'ZP-REG-001',
|
|||
|
|
name: '零点图书域 · 全局编号目录',
|
|||
|
|
generated: new Date().toISOString(),
|
|||
|
|
book: 'TCS-0003-ZY001 · 铸渊之书',
|
|||
|
|
totalEntries,
|
|||
|
|
volumes: volumes.map(v => ({ code: v.volume, name: v.name, count: v.count || 0 }))
|
|||
|
|
},
|
|||
|
|
volumes: volumes.map(v => ({
|
|||
|
|
code: v.volume,
|
|||
|
|
name: v.name,
|
|||
|
|
entries: v.entries || [],
|
|||
|
|
error: v.error || null
|
|||
|
|
}))
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return index;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 输出 ====================
|
|||
|
|
|
|||
|
|
function formatText(index) {
|
|||
|
|
let out = '';
|
|||
|
|
out += `⊢ ${index._meta.name}\n`;
|
|||
|
|
out += `⊢ 图书域: ${index._meta.domain} · 书籍: ${index._meta.book}\n`;
|
|||
|
|
out += `⊢ 生成时间: ${index._meta.generated} · 共 ${index._meta.totalEntries} 条\n\n`;
|
|||
|
|
|
|||
|
|
for (const vol of index.volumes) {
|
|||
|
|
if (vol.error) {
|
|||
|
|
out += `⚠️ ${vol.code} — ${vol.name}: ${vol.error}\n\n`;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
out += `═══ ${vol.code} · ${vol.name} (${vol.entries.length}条) ═══\n\n`;
|
|||
|
|
for (const entry of vol.entries) {
|
|||
|
|
out += ` 📄 ${entry.chapter} ${entry.tracePath}\n`;
|
|||
|
|
if (entry.title) out += ` 标题: ${entry.title}\n`;
|
|||
|
|
if (entry.dNumber) out += ` 版本: ${entry.dNumber}`;
|
|||
|
|
if (entry.date) out += ` · ${entry.date}`;
|
|||
|
|
if (entry.dNumber || entry.date) out += '\n';
|
|||
|
|
if (entry.lock) out += ` ⊢ ${entry.lock.substring(0, 80)}${entry.lock.length > 80 ? '...' : ''}\n`;
|
|||
|
|
out += '\n';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
out += '⊢ 零点图书域全局编号目录完成。\n';
|
|||
|
|
out += '⊢ 查找: node number-router.js <trace_path>\n';
|
|||
|
|
return out;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function formatJson(index) {
|
|||
|
|
return JSON.stringify(index, null, 2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== CLI ====================
|
|||
|
|
|
|||
|
|
if (require.main === module) {
|
|||
|
|
const format = process.argv[2] === '--json' ? 'json' : 'text';
|
|||
|
|
const index = generateIndex();
|
|||
|
|
|
|||
|
|
if (format === 'json') {
|
|||
|
|
console.log(formatJson(index));
|
|||
|
|
} else {
|
|||
|
|
console.log(formatText(index));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = { generateIndex, formatText, formatJson };
|