| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- #!/usr/bin/env node
- const fs = require('fs');
- const path = require('path');
- const {
- PACKAGE_ROOT,
- OUTPUT_CATEGORIES,
- OUTPUT_PERSISTENT_STORES,
- outputsRoot
- } = require('../mcp/src/core/output-paths');
- const DOCS_ALLOWED = new Set(['OUTPUT-STANDARD.md', 'DASHBOARD-DEV-LOG.md', 'RELEASE.md', 'specs', 'guides', 'research', 'generated']);
- const RUN_DIR_RE = /^\d{6}-[a-z0-9\u4e00-\u9fa5-]+$/;
- const DATE_DIR_RE = /^\d{4}-\d{2}-\d{2}$/;
- const problems = [];
- function listEntries(dir) {
- if (!fs.existsSync(dir)) return [];
- return fs.readdirSync(dir, { withFileTypes: true });
- }
- function checkOutputs() {
- const root = outputsRoot();
- for (const entry of listEntries(root)) {
- if (!entry.isDirectory()) {
- problems.push(`outputs 根目录不允许直接放文件:outputs/${entry.name}`);
- continue;
- }
- if (!OUTPUT_CATEGORIES.includes(entry.name)) {
- problems.push(`outputs 下存在未注册类别:outputs/${entry.name}(允许:${OUTPUT_CATEGORIES.join(', ')})`);
- continue;
- }
- checkCategory(path.join(root, entry.name), entry.name);
- }
- }
- function checkCategory(dir, category) {
- const persistentStores = new Set(OUTPUT_PERSISTENT_STORES[category] || []);
- for (const entry of listEntries(dir)) {
- if (!entry.isDirectory()) continue; // latest 模式文件
- if (persistentStores.has('*') || persistentStores.has(entry.name)) continue; // 注册的持续知识库
- if (!DATE_DIR_RE.test(entry.name)) {
- problems.push(`outputs/${category}/${entry.name} 不是 YYYY-MM-DD 日期目录`);
- continue;
- }
- const dateDir = path.join(dir, entry.name);
- for (const run of listEntries(dateDir)) {
- const rel = `outputs/${category}/${entry.name}/${run.name}`;
- if (!run.isDirectory()) {
- problems.push(`${rel} 应为 run 目录而不是文件`);
- continue;
- }
- if (!RUN_DIR_RE.test(run.name)) {
- problems.push(`${rel} 不符合 HHmmss-<slug> 命名`);
- }
- if (!fs.existsSync(path.join(dateDir, run.name, 'manifest.json'))) {
- problems.push(`${rel} 缺少 manifest.json`);
- }
- }
- }
- }
- function checkDocs() {
- const docsDir = path.join(PACKAGE_ROOT, 'docs');
- for (const entry of listEntries(docsDir)) {
- if (!DOCS_ALLOWED.has(entry.name)) {
- problems.push(`docs 第一层存在未注册条目:docs/${entry.name}(允许:${[...DOCS_ALLOWED].join(', ')})`);
- }
- }
- }
- checkOutputs();
- checkDocs();
- if (problems.length) {
- console.error('输出目录标准校验失败:');
- for (const problem of problems) console.error(` - ${problem}`);
- process.exit(1);
- }
- console.log('输出目录标准校验通过(outputs 与 docs 均符合 docs/OUTPUT-STANDARD.md)。');
|