59 lines
2.6 KiB
JavaScript
59 lines
2.6 KiB
JavaScript
// Validates docs/superpowers/manifest.yaml against files on disk.
|
|
// Usage: node scripts/validate-design-docs.mjs [--check]
|
|
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
import { dirname, resolve, join } from 'node:path';
|
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
import { createRequire } from 'node:module';
|
|
import { validateManifest } from './lib/design-index.mjs';
|
|
import { buildIndex } from './gen-design-index.mjs';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const SP = resolve(__dirname, '../docs/superpowers');
|
|
|
|
// `yaml` lives in ui/node_modules — resolve relative to ui/package.json,
|
|
// exactly like scripts/validate-help-docs.mjs does.
|
|
let parseYaml;
|
|
try {
|
|
const require = createRequire(pathToFileURL(resolve(__dirname, '../ui/package.json')));
|
|
({ parse: parseYaml } = await import(pathToFileURL(require.resolve('yaml')).href));
|
|
} catch {
|
|
console.error("design-docs validation: cannot load 'yaml' from ui/node_modules — run `npm --prefix ui install`");
|
|
process.exit(1);
|
|
}
|
|
|
|
const SUBDIRS = ['specs', 'plans', 'archived/specs', 'archived/plans'];
|
|
|
|
export function listDocs() {
|
|
const out = [];
|
|
for (const d of SUBDIRS) {
|
|
const abs = join(SP, d);
|
|
if (!existsSync(abs)) continue;
|
|
for (const f of readdirSync(abs)) if (f.endsWith('.md')) out.push(`${d}/${f}`);
|
|
}
|
|
return out.sort();
|
|
}
|
|
|
|
// Main guard: only run validation side-effects when executed directly.
|
|
// Importing this module (e.g. to use listDocs) will NOT trigger the block below.
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
// FIX I-1: guard against missing manifest.yaml (Task 3 hasn't generated it yet)
|
|
const manifestRaw = existsSync(join(SP, 'manifest.yaml'))
|
|
? readFileSync(join(SP, 'manifest.yaml'), 'utf-8')
|
|
: 'docs: []';
|
|
const manifest = parseYaml(manifestRaw) ?? { docs: [] };
|
|
const { errors, warnings } = validateManifest(manifest.docs ?? [], listDocs());
|
|
|
|
for (const w of warnings) console.warn(`[warn] ${w}`);
|
|
for (const e of errors) console.error(`[error] ${e}`);
|
|
|
|
if (process.argv.includes('--check')) {
|
|
const cur = existsSync(join(SP, 'index.md')) ? readFileSync(join(SP, 'index.md'), 'utf-8') : '';
|
|
if (cur !== buildIndex()) {
|
|
console.error('[error] index.md is stale — run node scripts/gen-design-index.mjs');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
if (errors.length) { console.error(`design-docs validation FAILED (${errors.length} errors)`); process.exit(1); }
|
|
console.log(`design-docs validation OK (${(manifest.docs ?? []).length} entries, ${warnings.length} warnings)`);
|
|
}
|