#!/usr/bin/env node /** * Fail if `kernel/` and `packages/bare-os-seeder/kernel/` differ. * Compares the **entire** recursive file set (relative paths + byte contents), not only `init.js`. * Run after coreutils build so `bin/*` and `share/man/man.json` match when both trees were refreshed. */ import fs from 'node:fs' import path from 'node:path' import process from 'node:process' import { fileURLToPath } from 'node:url' import { assertKernelInitJsMatchesRecipe } from './lib/kernel-init-bundle.mjs' const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') const canonical = path.join(root, 'kernel') const vendored = path.join(root, 'packages/bare-os-seeder/kernel') function walkFiles(dir, base) { /** @type {string[]} */ const out = [] if (!fs.existsSync(dir)) { throw new Error(`Missing directory: ${dir}`) } for (const ent of fs.readdirSync(dir, { withFileTypes: true })) { const p = path.join(dir, ent.name) const rel = path.relative(base, p) if (ent.isDirectory()) { out.push(...walkFiles(p, base)) } else if (ent.isFile()) { out.push(rel) } } return out } function main() { try { assertKernelInitJsMatchesRecipe(canonical) } catch (e) { console.error( e instanceof Error ? e.message : e, '(verify-kernel-seeder-parity)' ) process.exit(1) } const a = new Set(walkFiles(canonical, canonical)) const b = new Set(walkFiles(vendored, vendored)) const onlyA = [...a].filter((x) => !b.has(x)).sort() const onlyB = [...b].filter((x) => !a.has(x)).sort() if (onlyA.length || onlyB.length) { console.error( 'kernel/ vs packages/bare-os-seeder/kernel/: file set mismatch' ) if (onlyA.length) console.error('Only in kernel/:', onlyA.join(', ')) if (onlyB.length) console.error('Only in seeder kernel/:', onlyB.join(', ')) console.error( 'Remediate from repo root: rsync -a --delete kernel/ packages/bare-os-seeder/kernel/' ) process.exit(1) } /** @type {string[]} */ const diffs = [] for (const rel of [...a].sort()) { const pa = path.join(canonical, rel) const pb = path.join(vendored, rel) const ba = fs.readFileSync(pa) const bb = fs.readFileSync(pb) if (!ba.equals(bb)) diffs.push(rel) } if (diffs.length) { console.error( 'kernel/ vs packages/bare-os-seeder/kernel/: content differs for:', diffs.join(', ') ) console.error( 'Remediate: edit canonical kernel/ only, then: node scripts/bundle-kernel-init.mjs && rsync -a --delete kernel/ packages/bare-os-seeder/kernel/' ) process.exit(1) } const required = [ 'init.js', 'lib/init/init-main.js', 'lib/init/fragments/20-init-boot-policy.js', 'lib/init/fragments/30-init-kernel-extensions.js', 'lib/boot/00-pear-multisig-shape.js', 'lib/boot/01-invoke-ctx-hooks.js', 'lib/bare/manifest.json', 'lib/bare/bare-module-manifest.json' ] for (const rel of required) { const pa = path.join(canonical, rel) if (!fs.existsSync(pa)) { console.error('verify-kernel-seeder-parity: required file missing in kernel/:', rel) process.exit(1) } } /** Staged /bin scripts must carry the BARE_OS_BIN_API pragma (see coreutils runtime). */ const badBin = [] for (const rel of [...a].sort()) { if (!rel.startsWith('bin/')) continue const pa = path.join(canonical, rel) if (!fs.statSync(pa).isFile()) continue const head = fs.readFileSync(pa, 'utf8').slice(0, 400) if (!head.includes('BARE_OS_BIN_API')) badBin.push(rel) } if (badBin.length) { console.error( 'kernel/bin missing BARE_OS_BIN_API pragma:', badBin.join(', ') ) process.exit(1) } console.log('kernel/ and packages/bare-os-seeder/kernel/ are identical.') } main()