/** * Canonical booter boot-step identifiers emitted through {@link emitBooterBootStep} * (lifecycle / diagnostics). Keep in sync with `emitBooterBootPhase` call sites in `index.js`. */ export const BARE_OS_BOOTER_BOOT_STEPS = Object.freeze([ 'vfs', 'ctx', 'repl', 'initd', 'kernel_invoke' ]) /** * @param {string} step * @returns {boolean} */ export function isKnownBareOsBooterBootStep(step) { return BARE_OS_BOOTER_BOOT_STEPS.includes(String(step)) } /** * @param {{ * bootReadyStateRef: { booterPhases: string[], booterStages: string[] }, * bootStartedMs: number, * bootHrtimeNowNs?: (() => bigint) | null, * bootEventSubs: Iterable<(ev: Record) => unknown>, * diagnosticsSubs: Iterable<(ev: Record) => unknown>, * sessionId: string, * lifecycleSchemaVersion: string | number * }} deps */ export function createBooterBootEmitter(deps) { const { bootReadyStateRef, bootStartedMs, bootHrtimeNowNs = null, bootEventSubs, diagnosticsSubs, sessionId, lifecycleSchemaVersion } = deps function emitBooterBootStep(step) { const p = String(step) const arr = bootReadyStateRef.booterPhases const arrSt = bootReadyStateRef.booterStages if (!arr.includes(p)) arr.push(p) if (!arrSt.includes(p)) arrSt.push(p) const ev = { type: 'boot', phase: 'booter:' + p, ms: Date.now() - bootStartedMs, ts: Date.now(), sessionId, lifecycleSchemaVersion, ...(bootHrtimeNowNs ? { monotonicNs: String(bootHrtimeNowNs()) } : {}) } for (const fn of bootEventSubs) { Promise.resolve(fn(ev)).catch(() => {}) } for (const fn of diagnosticsSubs) { Promise.resolve(fn({ ...ev, source: 'booter' })).catch(() => {}) } } function emitBooterBootPhase(phase) { return emitBooterBootStep(phase) } return { emitBooterBootStep, emitBooterBootPhase } }