maestro/scripts/scaffold-manifest.mjs
oss-sync b1292e34b2
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (edc775f2)
2026-07-06 01:04:12 +00:00

63 lines
2.4 KiB
JavaScript

// Appends unregistered docs/superpowers/**/*.md entries to manifest.yaml.
// Uses yaml.parseDocument for comment-preserving round-trip.
// Idempotent: re-running adds 0 entries when all docs are already registered.
// Usage: node scripts/scaffold-manifest.mjs
import { readFileSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
import { dirname, resolve, join } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { createRequire } from 'node:module';
import { scaffoldEntryObject, findUnregistered } from './lib/design-index.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const SP = resolve(__dirname, '../docs/superpowers');
// `yaml` lives in ui/node_modules — same resolution pattern as validate-design-docs.mjs
const require = createRequire(pathToFileURL(resolve(__dirname, '../ui/package.json')));
const YAML = await import(pathToFileURL(require.resolve('yaml')).href);
const SUBDIRS = ['specs', 'plans', 'archived/specs', 'archived/plans'];
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();
}
const mfPath = join(SP, 'manifest.yaml');
const rawYaml = existsSync(mfPath) ? readFileSync(mfPath, 'utf-8') : 'docs:\n';
const doc = YAML.parseDocument(rawYaml);
// Ensure `docs` key exists as a sequence (handle null scalar from 'docs:\n' seed)
const existingSeq = doc.get('docs', true);
if (!(existingSeq instanceof YAML.YAMLSeq)) {
doc.set('docs', new YAML.YAMLSeq());
}
const seq = doc.get('docs', true); // true = return the node itself, not the JS value
seq.flow = false; // force block style for human curability
// Build the set of already-registered paths
const registered = new Set(
(seq.items ?? []).map((n) => n.get('path'))
);
const unregistered = findUnregistered(listDocs(), registered);
for (const rel of unregistered) {
const md = readFileSync(join(SP, rel), 'utf-8');
const entry = scaffoldEntryObject(rel, md);
const node = doc.createNode(entry);
// Attach # TODO: verify topic comment to the topic scalar node
const topicItem = node.get('topic', true);
if (topicItem) topicItem.comment = ' TODO: verify topic';
seq.add(node);
}
writeFileSync(mfPath, String(doc), 'utf-8');
console.log(`scaffold: added ${unregistered.length} entries (total ${seq.items.length})`);