- HRPC: bare_os.pkg_index_get, route table schema 3; pkg-swarm-index list/get; pathcap-verify --trusted - POSIX: profile 1.0.17, ctx API 1.53.0, syscalls.json schema 11 + susv4Refs; JSON schemas + matrix/dashboard - Feature bits: BARE_OS_KERNEL_FEATURE_BITS_DOC 16; contract + verify scripts; ctx.d.ts + gen helper sync - Ops: BARE_OS_HOLEPUNCH_DRIFT_TIER1 + tier1Repos; mktemp avoids false XXX marker; /proc boot_budget_summary test list - Docs: contract spine, env appendix, handbook, compatibility matrix, boot budget schema, vault threat model notes Covers bare-os P2P roadmap items 1–20 where implemented in-tree; kernel/lib/bare/README left minimal per maintainer edit.
125 lines
4.1 KiB
JavaScript
125 lines
4.1 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* CI: forbid incomplete-implementation markers in first-party kernel + booter runtime sources only.
|
|
*
|
|
* Scanned: kernel/init.js, kernel/lib/init/init-main.js, all kernel/lib/boot/*.js, kernel/bin/*.js (walk skips bundles),
|
|
* packages/bare-os-coreutils/src (`.js` + `.mjs` Tier-1 sources that ship into `/bin`),
|
|
* packages/bare-os-booter/index.js, packages/bare-os-booter/lib (recursive .js),
|
|
* packages/bare-os-protocol/lib (recursive .js; protocol constants only).
|
|
* Not scanned: kernel/lib/bare/bundles (vendored IIFEs — verify-bundle-markers.mjs,
|
|
* verify-bundle-throws.mjs, docs/audit allowlists). See developer-guide/node-to-bare-modules.md.
|
|
*/
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import process from 'node:process'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
const excludeConfigPath = path.join(
|
|
root,
|
|
'docs/audit/runtime-marker-excludes.json'
|
|
)
|
|
|
|
const MARKER_RE = /\b(TODO|FIXME|HACK|XXX)\b/
|
|
const NOT_IMPLEMENTED_RE = /throw\s+new\s+Error\s*\(\s*['"]Not implemented['"]\s*\)/
|
|
|
|
/** @param {string} dir */
|
|
/** @param {string[]} [exts] */
|
|
function walk(dir, exts = ['.js']) {
|
|
/** @type {string[]} */
|
|
const out = []
|
|
if (!fs.existsSync(dir)) return out
|
|
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
const p = path.join(dir, ent.name)
|
|
if (ent.isDirectory()) {
|
|
if (ent.name === 'bundles') continue
|
|
if (ent.name === 'node_modules') continue
|
|
out.push(...walk(p, exts))
|
|
} else if (ent.isFile()) {
|
|
const ext = path.extname(ent.name)
|
|
if (exts.includes(ext)) out.push(p)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
function loadExcludePrefixes() {
|
|
try {
|
|
const raw = fs.readFileSync(excludeConfigPath, 'utf8')
|
|
const j = JSON.parse(raw)
|
|
const p = Array.isArray(j.pathPrefixes) ? j.pathPrefixes : []
|
|
return p
|
|
.map((s) => String(s || '').replace(/\//g, path.sep))
|
|
.filter(Boolean)
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} rel
|
|
* @param {string[]} excludePrefixes
|
|
*/
|
|
function shouldSkipFile(rel, excludePrefixes) {
|
|
if (rel.startsWith(`packages${path.sep}bare-os-booter${path.sep}test`))
|
|
return true
|
|
if (rel === `packages${path.sep}bare-os-booter${path.sep}test.js`) return true
|
|
if (rel.includes(`${path.sep}bundles${path.sep}`)) return true
|
|
for (const pre of excludePrefixes) {
|
|
if (rel === pre || rel.startsWith(pre + path.sep)) return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
function main() {
|
|
const excludePrefixes = loadExcludePrefixes()
|
|
const files = [
|
|
path.join(root, 'kernel', 'init.js'),
|
|
path.join(root, 'kernel', 'lib', 'init', 'init-main.js'),
|
|
...walk(path.join(root, 'kernel', 'lib', 'init', 'fragments')),
|
|
...walk(path.join(root, 'kernel', 'lib', 'boot')),
|
|
...walk(path.join(root, 'kernel', 'bin')),
|
|
...walk(path.join(root, 'packages', 'bare-os-coreutils', 'src'), [
|
|
'.js',
|
|
'.mjs'
|
|
]),
|
|
...walk(path.join(root, 'packages', 'bare-os-booter', 'lib')),
|
|
...walk(path.join(root, 'packages', 'bare-os-protocol', 'lib')),
|
|
path.join(root, 'packages', 'bare-os-booter', 'index.js')
|
|
]
|
|
|
|
/** @type {string[]} */
|
|
const bad = []
|
|
for (const abs of files) {
|
|
if (!fs.existsSync(abs)) continue
|
|
const rel = path.relative(root, abs)
|
|
if (shouldSkipFile(rel, excludePrefixes)) continue
|
|
const txt = fs.readFileSync(abs, 'utf8')
|
|
for (let i = 0; i < txt.length; i++) {
|
|
const slice = txt.slice(i, i + 200)
|
|
const m = slice.match(MARKER_RE)
|
|
if (m) {
|
|
const line = txt.slice(0, i).split('\n').length
|
|
bad.push(`${rel}:${line}:${m[0]}`)
|
|
break
|
|
}
|
|
}
|
|
const ni = txt.match(NOT_IMPLEMENTED_RE)
|
|
if (ni && ni.index != null) {
|
|
const line = txt.slice(0, ni.index).split('\n').length
|
|
bad.push(`${rel}:${line}:throw new Error(\"Not implemented\")`)
|
|
}
|
|
}
|
|
|
|
if (bad.length) {
|
|
console.error(
|
|
'verify-runtime-no-incomplete-markers: incomplete markers in runtime sources:'
|
|
)
|
|
for (const b of bad) console.error(' ', b)
|
|
process.exit(1)
|
|
}
|
|
console.log('verify-runtime-no-incomplete-markers: OK')
|
|
}
|
|
|
|
main()
|