#!/usr/bin/env node /** * Pretest: BARE_OS_POSIX_PROFILE_VERSION and BARE_OS_POSIX_PROFILE_ID must match * between protocol source, declared profile markdown table, and posix-compliance-matrix.json. */ import fs from 'node:fs' import path from 'node:path' import process from 'node:process' import { fileURLToPath } from 'node:url' import { BARE_OS_POSIX_PROFILE_VERSION, BARE_OS_POSIX_PROFILE_ID } from '../packages/bare-os-protocol/lib/bare-os-posix-profile.js' const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') const declaredPath = path.join(root, 'docs/architecture/POSIX_DECLARED_PROFILE.md') const matrixPath = path.join(root, 'docs/reference/posix-compliance-matrix.json') const syscallsProcPath = path.join( root, 'packages/bare-os-booter/lib/bare-os-syscalls-proc-json.js' ) const ctxApiPath = path.join( root, 'packages/bare-os-booter/lib/bare-os-ctx-api.js' ) const readmePath = path.join(root, 'README.md') function readDeclaredTable() { const text = fs.readFileSync(declaredPath, 'utf8') const verM = text.match(/`BARE_OS_POSIX_PROFILE_VERSION`\s*\|\s*`([^`]+)`/) const idM = text.match(/`BARE_OS_POSIX_PROFILE_ID`\s*\|\s*`([^`]+)`/) return { version: verM ? verM[1].trim() : '', id: idM ? idM[1].trim() : '' } } function readMatrix() { const j = JSON.parse(fs.readFileSync(matrixPath, 'utf8')) return { profileId: String(j.profileId || '').trim(), note: String(j.note || ''), syscallsSchema: j.synthetic_proc && typeof j.synthetic_proc.syscalls_json_schema === 'number' ? j.synthetic_proc.syscalls_json_schema : null } } function readSyscallsSchemaFromSource() { const txt = fs.readFileSync(syscallsProcPath, 'utf8') const m = txt.match(/schemaVersion:\s*(\d+)/) return m ? Number.parseInt(m[1], 10) : null } function readCtxApiVersion() { const txt = fs.readFileSync(ctxApiPath, 'utf8') const m = txt.match(/export const BARE_OS_CTX_API_VERSION = '([^']+)'/) return m ? m[1].trim() : '' } function main() { const dec = readDeclaredTable() const mat = readMatrix() const errors = [] if (dec.version !== BARE_OS_POSIX_PROFILE_VERSION) { errors.push( `POSIX_DECLARED_PROFILE.md table BARE_OS_POSIX_PROFILE_VERSION "${dec.version}" !== bare-os-posix-profile.js "${BARE_OS_POSIX_PROFILE_VERSION}"` ) } if (dec.id !== BARE_OS_POSIX_PROFILE_ID) { errors.push( `POSIX_DECLARED_PROFILE.md table BARE_OS_POSIX_PROFILE_ID "${dec.id}" !== bare-os-posix-profile.js "${BARE_OS_POSIX_PROFILE_ID}"` ) } if (mat.profileId !== BARE_OS_POSIX_PROFILE_ID) { errors.push( `posix-compliance-matrix.json profileId "${mat.profileId}" !== "${BARE_OS_POSIX_PROFILE_ID}"` ) } if (!mat.note.includes(BARE_OS_POSIX_PROFILE_VERSION)) { errors.push( `posix-compliance-matrix.json note must contain profile version "${BARE_OS_POSIX_PROFILE_VERSION}" (for dashboard / operator drift checks)` ) } const wantSys = readSyscallsSchemaFromSource() if (wantSys == null || !Number.isFinite(wantSys)) { errors.push('Could not parse schemaVersion from bare-os-syscalls-proc-json.js') } else if (mat.syscallsSchema !== wantSys) { errors.push( `posix-compliance-matrix.json synthetic_proc.syscalls_json_schema ${mat.syscallsSchema} !== bare-os-syscalls-proc-json schemaVersion ${wantSys}` ) } const ctxVer = readCtxApiVersion() if (ctxVer) { const readme = fs.readFileSync(readmePath, 'utf8') if (!readme.includes('**`' + ctxVer + '`**')) { errors.push( `README.md must mention current ctx API **\`${ctxVer}\`** alongside POSIX profile (single-source triplet)` ) } } if (errors.length) { console.error('verify-posix-profile-triplet: FAIL') for (const e of errors) console.error(' -', e) process.exit(1) } console.log('verify-posix-profile-triplet: OK') } main()