feat: POSIX/P2P roadmap — proc surfaces, syscalls, boot perf, docs, CI
- Align posix-conformance-matrix bareOsSyscallOps with getconf BARE_OS_SYSCALL_OPS - Add verify-boot-policy-extension-signer-pins.mjs to pretest; document in scripts/README - Document extensionSignerPinsV2–V5 env wiring in OTA_AND_BUNDLES; vault multisig sketch - Note telemetry NDJSON redaction limits in environment appendix - Expand booter CHANGELOG 1.40.0 (boot-perf, shell POSIX mode, subprocess errors, etc.) - Holepunch sync README: NDJSON summary path Seeder/kernel parity and pretest already green for bundled changes.
This commit is contained in:
@@ -5,7 +5,7 @@ Authoritative **version alignment** with protocol and telemetry schema numbers l
|
||||
## Maintenance
|
||||
|
||||
- **Host filesystem**: first-party booter and seeder sources use **`import … from '#host-fs'`** / **`#host-path`** (and seeder **`#host-fs-promises`**) so Bare resolves **`bare-fs`** / **`bare-path`** and Node resolves the built-in **`fs`** / **`path`** modules via the default **`imports`** condition. **`bare-fs`** is a direct **`dependencies`** entry of **`bare-os-booter`**. CI: **`scripts/verify-pear-no-static-node-import.mjs`** rejects bare **`fs`** / **`path`** specifiers.
|
||||
- **POSIX / proc**: **`/proc/bare_os/syscalls.json`** schema **5** (socket-family probes, **`posixXsh`** / **`fdModel`** extensions; JSON text **cached** until **`vfs.bareOsClearWarmReadCaches`**); **`/proc/bare_os/process_table.json`** schema **5** (**`parentName`**); **`/proc/bare_os/protomux.json`** wire text schema **2**; **`/dev/shm`** in-memory named segments. Protocol export **`BARE_OS_POSIX_PROFILE_*`**.
|
||||
- **POSIX / proc**: **`/proc/bare_os/syscalls.json`** schema **5** (socket-family probes, **`posixXsh`** / **`fdModel`** / **`errnoAlignment`**; JSON text **cached** until **`vfs.bareOsClearWarmReadCaches`**); **`/proc/bare_os/process_table.json`** schema **6** (**`jobControlSemantics`** + **`parentName`**); **`/proc/bare_os/protomux.json`** wire text schema **2**; **`/dev/shm`** in-memory named segments. Protocol export **`BARE_OS_POSIX_PROFILE_*`**.
|
||||
- **Vendored bundles**: post-esbuild **`scripts/sanitize-bare-bundles.mjs`** (from **`bare-os-bare-libs/build.mjs`**) strips CI-forbidden markers and replaces **`node:`** requires in **`bareDev.js`** with **`bare-*`** modules.
|
||||
- **Boot hooks (naming)**: canonical **`bareOsRegisterBootStepHook`**, **`bareOsInvokeBootStepHooks`**, **`bareOsEmitBareBootStepHint`**; legacy **`*BootPhase*`** methods remain thin wrappers (**no `bareOsCtxApiVersion` bump**). See [docs/reference/naming-alias-matrix.md](../../docs/reference/naming-alias-matrix.md).
|
||||
- **Pear / Bare**: [`lib/kernel-runner.js`](lib/kernel-runner.js) must not **static**-import **`node:module`** (Bare’s resolver cannot load **`node:`** builtins from a **`pear://`** bundle). Optional **`BARE_OS_BIN_WORKER_OFFLOAD`** now obtains **`createRequire`** via **dynamic** **`import('bare-module')`** when running outside Node.
|
||||
@@ -15,7 +15,9 @@ Authoritative **version alignment** with protocol and telemetry schema numbers l
|
||||
|
||||
| Version | Booter (workspace) | Notes |
|
||||
| ------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| 1.38.0 | 0.1.0 | **`/proc/bare_os/syscalls.json`** schema **5** + **cached** proc text (cleared with warm read cache); socket syscall **probes** (**`ENOSYS`**); **`/dev/shm`** segments; **`net_summary`** **`udxTuning`** / **`hyperswarmTuning`** env passthrough; **`bareOsCorestoreSnapshotHint`** → **`operator.corestore_snapshot_hint`** counter; **`bareOsPathconf`** **`_PC_NAME_MAX`** **128** under **`/dev/shm`**. |
|
||||
| 1.40.0 | 0.1.0 | **`vfs.bareOsEvictLibBareBundlesFromManifest`** + **`ctx.bareOsInvalidateWarmReadCachesFromBareManifestJson`** — manifest-aware **`/lib/bare`** warm-cache eviction; **`bareOsVfsBatchWrite`** uses selective eviction for manifest-only puts. **`/proc/bare_os/replication`** **`liveHyperdrive`** sketch + **`metrics_live.replicationLive`** (**`stallHint`**, core lengths). **`/run/bare-os/boot-perf.json`** schema **3** + **`BARE_OS_BOOT_BUDGET_STDLIB_*`** when bare-stdlib resolution exceeds **`BARE_OS_BOOT_BUDGET_MS_COLD`** / **`BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB`**. **`BARE_OS_SHELL_POSIX_MODE`** grouped **`( … )`** lists. **`bareOsTrySpawnHostSubprocess`** failures include **`errorCode`** / **`causeName`**. NDJSON / OTel string redaction helpers. **`scripts/sync-holepunch-clones.mjs`** NDJSON summary. **`docs/reference/posix-dashboard.md`** generated in pretest. |
|
||||
| 1.39.0 | 0.1.0 | **`ctx.bareOsReadProtomuxExtensionsJson()`** and **`/proc/bare_os/protomux_extensions.json`** — operator registry snapshot + logical extension channel hints when **`BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY`** is set; default **`exposed:false`**. **`process_table.json`** schema **6** (**`jobControlSemantics`**). Syscalls: **`readv`**/**`writev`** (POSIX_FD_SIM pipes), **`getsockopt`**/**`setsockopt`** probes, **`fcntl`** lock cmds → **`EOPNOTSUPP`** object; **`posixXsh.namesCsv`** generated; **`errnoAlignment`** in **`syscalls.json`**. Protocol **`BARE_OS_POSIX_PROFILE_VERSION` `1.0.5`**. |
|
||||
| 1.38.0 | 0.1.0 | **`/proc/bare_os/syscalls.json`** schema **5** + **cached** proc text (cleared with warm read cache); socket syscall **probes** (**`ENOSYS`**); **`/dev/shm`** segments; **`net_summary`** **`udxTuning`** / **`hyperswarmTuning`** env passthrough; **`bareOsCorestoreSnapshotHint`** → **`operator.corestore_snapshot_hint`** counter; **`bareOsPathconf`** **`_PC_NAME_MAX`** **128** under **`/dev/shm`**. With **`BARE_OS_PROC_BLIND_PEER_RELAY_HINTS`**, **`blind_relay_router`**, **`blind_pairing_sketch`**, and **`relay_geo_hint`** use **proc JSON schema 2** and merge env sketches with live **`swarm`** aggregates (peer count / lifecycle / **`relayGeoTier`** — no peer keys). |
|
||||
| 1.37.0 | 0.1.0 | **`ctx.bareOsReadSnapshotHintsJson()`** mirrors **`/proc/bare_os/snapshot_hints.json`**; blind relay / pairing / geo **`/proc`** JSON stubbed unless **`BARE_OS_PROC_BLIND_PEER_RELAY_HINTS`**; passthrough **`BARE_OS_BARE_SUBPROCESS_BRIDGE`**, **`BARE_OS_BARE_SUBPROCESS_TIMEOUT_MS`**. |
|
||||
| 1.36.0 | 0.1.0 | **`ctx.bareOsSendSignal`** negative target = synthetic **process group** (shell job **`pgid`**); **`ctx.bareOsReadReplicationOperatorJson`**, **`ctx.bareOsInvalidateWarmReadCaches`**, **`vfs.bareOsClearWarmReadCaches`**; **`bareOsVfsBatchWrite`** clears warm **`/bin`** / **`/lib/bare`** caches on matching puts; **`metrics_live.ipcTelemetry`** (FIFO quota / counters via **`BARE_OS_IPC_MAX_CHANNELS`**); swarm **`shouldAttemptPeer`** honors **`BARE_OS_PEER_ALLOWLIST_HEX`**; **`bareOsPathconf`** union/mirror **`_PC_NO_TRUNC`** / **`_PC_CHOWN_RESTRICTED`**; boot-ready **`subsystems.bareStdlib.resolutionWallMs`**. |
|
||||
| 1.35.0 | 0.1.0 | **`ctx.bareOsSyscall('fcntl', …)`** (**`F_GETFL`** / **`F_SETFL`**, **`O_APPEND`** **`0x400`**, **`O_NONBLOCK`** **`0x800`**) + **`bareOsLogicalFdFlags`**; **`ctx.bareOsPosixPoll`** / **`bareOsPosixPollProbe`** + **`bareOsSyscall('posixPoll', …)`**; **`bareOsPosixFdSimRead`** honors **`O_NONBLOCK`** (**`EAGAIN`** when empty); **`/proc/bare_os/syscalls.json`** **`posixXsh.namesCsv`** includes **`poll`**; **`getconf`** **`BARE_OS_SYSCALL_OPS`** / **`BARE_OS_POSIX_XSH_OPS`** updated; protocol **`BARE_OS_POSIX_PROFILE_VERSION` `1.0.2`**. |
|
||||
|
||||
@@ -144,6 +144,10 @@ import {
|
||||
} from './lib/bare-os-wasm-kernel.js'
|
||||
import { BARE_OS_CTX_API_VERSION } from './lib/bare-os-ctx-api.js'
|
||||
import { buildBareOsPearCorestoreHrpcProcJson } from './lib/bare-os-proc-pear-corestore-hrpc.js'
|
||||
import {
|
||||
bareOsProcBlindPeerRelayHintsExposed,
|
||||
buildBareOsBlindRelaySwarmRuntime
|
||||
} from './lib/bare-os-proc-blind-peer-relay-gate.js'
|
||||
import { buildBareOsRuntimeCaps } from './lib/bare-os-runtime-caps.js'
|
||||
import {
|
||||
bareOsBareModulesEnabled,
|
||||
@@ -172,6 +176,7 @@ import { createHash } from 'bare-crypto'
|
||||
import { buildBareOsHostProcJsonText } from './lib/bare-os-host-proc-snapshot.js'
|
||||
import { computeReplicationSyncWindow } from './lib/bare-os-sync-window.js'
|
||||
import { buildBareOsReplicationOperatorSurfaceProcJson } from './lib/bare-os-proc-replication-operator-surface.js'
|
||||
import { buildBareOsReplicationLiveSketch } from './lib/bare-os-replication-proc-live.js'
|
||||
import { buildBareOsBootGraphProcJson } from './lib/bare-os-boot-graph-proc.js'
|
||||
import {
|
||||
bareOsSecretHandleAcquire,
|
||||
@@ -192,6 +197,7 @@ import {
|
||||
import { bareOsSwarmLifecycleSnapshot } from './lib/bare-os-swarm-lifecycle.js'
|
||||
import { bareOsReadHostProfile } from './lib/bare-os-host-profile.js'
|
||||
import { bareOsProcessTableSnapshot } from './lib/bare-os-process-table.js'
|
||||
import { buildBareOsProtomuxExtensionsProcJson } from './lib/bare-os-protomux-extensions-proc.js'
|
||||
import { bareOsStatvfsFromHyperdrive } from './lib/bare-os-statvfs-from-drive.js'
|
||||
import {
|
||||
maybeBareOsBuildBinHyperbeeHint,
|
||||
@@ -522,6 +528,7 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
'BARE_OS_BARE_SUBPROCESS_BRIDGE',
|
||||
'BARE_OS_BARE_SUBPROCESS_TIMEOUT_MS',
|
||||
'BARE_OS_PROC_BLIND_PEER_RELAY_HINTS',
|
||||
'BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY',
|
||||
'BARE_OS_FIND_EXEC_MAX',
|
||||
'BARE_OS_XARGS_MAX_PROCS',
|
||||
'BARE_OS_YES_MAX_LINES',
|
||||
@@ -562,6 +569,7 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
'BARE_OS_SHELL_CMDSUBST_MAX_BYTES',
|
||||
'BARE_OS_SHELL_LOOP_CONTROL',
|
||||
'BARE_OS_SHELL_PIPEFAIL',
|
||||
'BARE_OS_SHELL_POSIX_MODE',
|
||||
'BARE_OS_TELEMETRY_NDJSON',
|
||||
'BARE_OS_TELEMETRY_OTEL_JSONL',
|
||||
'BARE_OS_PROC_POLL_MS',
|
||||
@@ -593,6 +601,7 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
'BARE_OS_BOOT_POLICY_DIGEST_SKETCH',
|
||||
'BARE_OS_KERNEL_STARTUP_CLASS',
|
||||
'BARE_OS_BOOT_BUDGET_MS_COLD',
|
||||
'BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB',
|
||||
'BARE_OS_BOOT_CAPABILITY_CONTRACT_DEBUG',
|
||||
'BARE_OS_BOOT_EXT_RESOLUTION_TRACE',
|
||||
'BARE_OS_KERNEL_EXT_GRAPH',
|
||||
@@ -908,6 +917,11 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
const warmReadCacheStatsRef = { current: null }
|
||||
/** Cached `/proc/bare_os/syscalls.json` text; cleared with warm read cache invalidation. */
|
||||
let bareOsSyscallsProcJsonCache = null
|
||||
function bareOsBlindRelayRuntimeHintsForProc() {
|
||||
if (!bareOsProcBlindPeerRelayHintsExposed(shellEnv)) return undefined
|
||||
const peers = disk.peers ? [...disk.peers] : []
|
||||
return { swarm: buildBareOsBlindRelaySwarmRuntime(shellEnv, peers) }
|
||||
}
|
||||
const vfs = createVfs(disk.drive, disk.personalDrive, shellEnv, vfsMountRef, {
|
||||
warmReadCacheStatsRef,
|
||||
procBareOsHostOsText() {
|
||||
@@ -1022,7 +1036,11 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
return `${JSON.stringify(o)}\n`
|
||||
},
|
||||
procBareOsPearCorestoreHrpcJsonText(pearCorestoreHrpcProcId) {
|
||||
const o = buildBareOsPearCorestoreHrpcProcJson(String(pearCorestoreHrpcProcId || ''), shellEnv)
|
||||
const o = buildBareOsPearCorestoreHrpcProcJson(
|
||||
String(pearCorestoreHrpcProcId || ''),
|
||||
shellEnv,
|
||||
bareOsBlindRelayRuntimeHintsForProc()
|
||||
)
|
||||
return `${JSON.stringify(o)}\n`
|
||||
},
|
||||
procBareOsBareRuntimeProtoMuxJsonText(bareRuntimeProtoMuxProcId) {
|
||||
@@ -1054,11 +1072,19 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
return `${JSON.stringify(o)}\n`
|
||||
},
|
||||
procBareOsPearInspectLoggerTlsJsonText(pearInspectLoggerTlsProcId) {
|
||||
const o = buildBareOsPearInspectLoggerTlsProcJson(String(pearInspectLoggerTlsProcId || ''), shellEnv)
|
||||
const o = buildBareOsPearInspectLoggerTlsProcJson(
|
||||
String(pearInspectLoggerTlsProcId || ''),
|
||||
shellEnv,
|
||||
bareOsBlindRelayRuntimeHintsForProc()
|
||||
)
|
||||
return `${JSON.stringify(o)}\n`
|
||||
},
|
||||
procBareOsHypercorePackHrpcLifecycleJsonText(hypercorePackHrpcLifecycleProcId) {
|
||||
const o = buildBareOsHypercorePackHrpcLifecycleProcJson(String(hypercorePackHrpcLifecycleProcId || ''), shellEnv)
|
||||
const o = buildBareOsHypercorePackHrpcLifecycleProcJson(
|
||||
String(hypercorePackHrpcLifecycleProcId || ''),
|
||||
shellEnv,
|
||||
bareOsBlindRelayRuntimeHintsForProc()
|
||||
)
|
||||
return `${JSON.stringify(o)}\n`
|
||||
},
|
||||
procBareOsBootGraphJsonText() {
|
||||
@@ -1683,6 +1709,7 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
return `${JSON.stringify({
|
||||
topicHex: b4a.toString(tk, 'hex'),
|
||||
peerCount: peers,
|
||||
liveHyperdrive: buildBareOsReplicationLiveSketch(disk, peers),
|
||||
session: sessionStatsRef,
|
||||
mirrorHint: !!(mk && String(mk).trim()),
|
||||
seedReplication: sr && typeof sr === 'object' ? sr : undefined,
|
||||
@@ -2125,6 +2152,8 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
return metricsLiveCache.text
|
||||
}
|
||||
const pl = getBareOsPipelineLimits(shellEnv)
|
||||
const peerRep = disk.peers?.size ?? 0
|
||||
const repLive = buildBareOsReplicationLiveSketch(disk, peerRep)
|
||||
metricsLiveCache = {
|
||||
at: now,
|
||||
text: `${JSON.stringify({
|
||||
@@ -2134,7 +2163,14 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
coalesceMs: procPollMsResolved,
|
||||
atMs: now,
|
||||
session: { ...sessionStatsRef },
|
||||
peers: disk.peers?.size ?? 0,
|
||||
peers: peerRep,
|
||||
replicationLive: {
|
||||
schema: 1,
|
||||
peerCount: peerRep,
|
||||
systemCoreLength: repLive.systemCoreLength,
|
||||
personalCoreLength: repLive.personalCoreLength,
|
||||
stallHint: repLive.stallHint
|
||||
},
|
||||
pipeline: pl,
|
||||
workerBudgetHints: {
|
||||
schema: 1,
|
||||
@@ -2172,7 +2208,8 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
sigactionHandlers:
|
||||
liveCtx && liveCtx.bareOsLogicalSigaction
|
||||
? liveCtx.bareOsLogicalSigaction
|
||||
: null
|
||||
: null,
|
||||
env: shellEnv
|
||||
})
|
||||
})(),
|
||||
initdReadiness: bareInitdReadinessSnapshot(),
|
||||
@@ -2201,6 +2238,21 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
limitMs:
|
||||
String(shellEnv.BARE_OS_BOOT_BUDGET_COLD_LIMIT_MS || '').trim() || null,
|
||||
note: 'Guest kernel sets these when cold wall exceeds BARE_OS_BOOT_BUDGET_MS_COLD after boot-ready.'
|
||||
},
|
||||
bootBudgetBareStdlib: {
|
||||
schema: 1,
|
||||
resolutionWallMs:
|
||||
String(shellEnv.BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS || '').trim() ||
|
||||
null,
|
||||
budgetMs:
|
||||
String(shellEnv.BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB || '').trim() || null,
|
||||
exceeded:
|
||||
String(shellEnv.BARE_OS_BOOT_BUDGET_STDLIB_EXCEEDED || '') === '1',
|
||||
wallMs:
|
||||
String(shellEnv.BARE_OS_BOOT_BUDGET_STDLIB_WALL_MS || '').trim() || null,
|
||||
limitMs:
|
||||
String(shellEnv.BARE_OS_BOOT_BUDGET_STDLIB_LIMIT_MS || '').trim() || null,
|
||||
note: 'Booter sets resolutionWallMs; guest sets exceeded when BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB is exceeded.'
|
||||
}
|
||||
})}\n`
|
||||
}
|
||||
@@ -2216,7 +2268,8 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
shellJobs,
|
||||
ipcStats,
|
||||
logicalFdRows: bareOsCollectLogicalFdRows(),
|
||||
initdReadiness: bareInitdReadinessSnapshot()
|
||||
initdReadiness: bareInitdReadinessSnapshot(),
|
||||
env: shellEnv
|
||||
})
|
||||
)}\n`
|
||||
},
|
||||
@@ -2313,6 +2366,15 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
atMs: Date.now()
|
||||
})}\n`
|
||||
},
|
||||
procBareOsProtomuxExtensionsText() {
|
||||
return `${JSON.stringify(
|
||||
buildBareOsProtomuxExtensionsProcJson({
|
||||
env: shellEnv,
|
||||
registrySnapshot: protomuxAliasRegistry.snapshot(),
|
||||
ctxApiVersion: BARE_OS_CTX_API_VERSION
|
||||
})
|
||||
)}\n`
|
||||
},
|
||||
sysClassNetLoText() {
|
||||
const n = disk.peers?.size ?? 0
|
||||
return `operstate ${n > 0 ? 'unknown' : 'down'}\ncarrier ${n > 0 ? 1 : 0}\n`
|
||||
@@ -2343,12 +2405,16 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
if (lockWarn.length) bootReadyStateRef.bareModuleLockWarnings = lockWarn
|
||||
primeGlobalFetchFromBareLibrary(bareLibrary)
|
||||
}
|
||||
const bareStdlibWallMs = bareOsBareModulesEnabled(shellEnv)
|
||||
? Date.now() - bareCtxResolutionT0
|
||||
: 0
|
||||
shellEnv.BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS = String(bareStdlibWallMs)
|
||||
Object.assign(bootReadyStateRef.subsystems, {
|
||||
bareStdlib: bareOsBareModulesEnabled(shellEnv)
|
||||
? {
|
||||
ready: true,
|
||||
atMs: Date.now(),
|
||||
resolutionWallMs: Date.now() - bareCtxResolutionT0,
|
||||
resolutionWallMs: bareStdlibWallMs,
|
||||
exportCount: Object.keys(bareLibrary).length
|
||||
}
|
||||
: {
|
||||
@@ -3084,7 +3150,8 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
ipcStats,
|
||||
logicalFdRows: bareOsCollectLogicalFdRows(),
|
||||
initdReadiness: bareInitdReadinessSnapshot(),
|
||||
sigactionHandlers: this.bareOsLogicalSigaction
|
||||
sigactionHandlers: this.bareOsLogicalSigaction,
|
||||
env: shellEnv
|
||||
})
|
||||
},
|
||||
/**
|
||||
@@ -3244,7 +3311,13 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
})
|
||||
return { ok: true, child }
|
||||
} catch (e) {
|
||||
return { ok: false, reason: (e && e.message) || String(e) }
|
||||
const msg = (e && e.message) || String(e)
|
||||
return {
|
||||
ok: false,
|
||||
reason: msg,
|
||||
errorCode: 'bare_subprocess_unavailable',
|
||||
causeName: e && e.name ? String(e.name) : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -3826,6 +3899,16 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
let cmd = args.cmd
|
||||
if (typeof cmd === 'string') {
|
||||
const u = String(cmd).toUpperCase()
|
||||
if (u === 'F_GETLK' || u === 'F_SETLK' || u === 'F_SETLKW') {
|
||||
return {
|
||||
ok: false,
|
||||
op: 'fcntl',
|
||||
cmd: u,
|
||||
code: 'EOPNOTSUPP',
|
||||
errnoHint: 'EOPNOTSUPP',
|
||||
note: 'Advisory file locks are not implemented; use VFS cooperative patterns.'
|
||||
}
|
||||
}
|
||||
if (u === 'F_GETFL' || u === 'GETFL') cmd = 3
|
||||
else if (u === 'F_SETFL' || u === 'SETFL') cmd = 4
|
||||
else {
|
||||
@@ -3943,6 +4026,117 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
current: Number.isFinite(nowMask) ? nowMask : 0o022
|
||||
}
|
||||
}
|
||||
if (name === 'readv') {
|
||||
const fd = Number(args.fd)
|
||||
if (!Number.isFinite(fd)) {
|
||||
throw new Error('bareOsSyscall: readv: fd is required')
|
||||
}
|
||||
const iovs = Array.isArray(args.iovs) ? args.iovs : []
|
||||
const maxIovs = 16
|
||||
const maxPer = 65536
|
||||
const maxTotal = 1024 * 1024
|
||||
let totalBytes = 0
|
||||
/** @type {string[]} */
|
||||
const buffers = []
|
||||
for (const iov of iovs.slice(0, maxIovs)) {
|
||||
const want = Math.min(
|
||||
maxPer,
|
||||
Math.max(
|
||||
0,
|
||||
Math.floor(
|
||||
Number(
|
||||
iov && typeof iov === 'object' && 'length' in iov
|
||||
? iov.length
|
||||
: iov && typeof iov === 'object' && 'maxBytes' in iov
|
||||
? iov.maxBytes
|
||||
: 4096
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
if (want <= 0) {
|
||||
buffers.push('')
|
||||
continue
|
||||
}
|
||||
if (totalBytes + want > maxTotal) {
|
||||
throw new Error('bareOsSyscall: readv: total iov budget exceeded')
|
||||
}
|
||||
const r = this.bareOsPosixFdSimRead(fd, want)
|
||||
if (!r || !r.ok) {
|
||||
if (r && r.reason === 'EAGAIN') {
|
||||
const err = /** @type {Error & { code?: string }} */ (
|
||||
new Error('EAGAIN: readv')
|
||||
)
|
||||
err.code = 'EAGAIN'
|
||||
throw err
|
||||
}
|
||||
throw new Error(
|
||||
'bareOsSyscall: readv: ' + (r && r.reason ? r.reason : 'failed')
|
||||
)
|
||||
}
|
||||
const chunk = String(r.data || '')
|
||||
buffers.push(chunk)
|
||||
totalBytes += b4a.from(chunk, 'utf8').byteLength
|
||||
if (chunk.length < want) break
|
||||
}
|
||||
return { ok: true, op: 'readv', fd, buffers, bytesRead: totalBytes }
|
||||
}
|
||||
if (name === 'writev') {
|
||||
const fd = Number(args.fd)
|
||||
if (!Number.isFinite(fd)) {
|
||||
throw new Error('bareOsSyscall: writev: fd is required')
|
||||
}
|
||||
const bufs = Array.isArray(args.buffers) ? args.buffers : []
|
||||
const maxChunks = 64
|
||||
const maxTotal = 1024 * 1024
|
||||
const pieces = []
|
||||
let n = 0
|
||||
for (const b of bufs.slice(0, maxChunks)) {
|
||||
const s =
|
||||
typeof b === 'string'
|
||||
? b
|
||||
: b instanceof Uint8Array
|
||||
? b4a.toString(b, 'utf8')
|
||||
: String(b)
|
||||
const add = b4a.from(s, 'utf8').byteLength
|
||||
n += add
|
||||
if (n > maxTotal) {
|
||||
throw new Error('bareOsSyscall: writev: total length exceeded')
|
||||
}
|
||||
pieces.push(s)
|
||||
}
|
||||
const payload = pieces.join('')
|
||||
const w = this.bareOsPosixFdSimWrite(fd, payload)
|
||||
if (!w || !w.ok) {
|
||||
if (w && w.reason === 'EAGAIN') {
|
||||
const err = /** @type {Error & { code?: string }} */ (
|
||||
new Error('EAGAIN: writev')
|
||||
)
|
||||
err.code = 'EAGAIN'
|
||||
throw err
|
||||
}
|
||||
throw new Error(
|
||||
'bareOsSyscall: writev: ' + (w && w.reason ? w.reason : 'failed')
|
||||
)
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
op: 'writev',
|
||||
fd,
|
||||
bytesWritten: w.bytes ?? b4a.from(payload, 'utf8').byteLength
|
||||
}
|
||||
}
|
||||
if (name === 'getsockopt' || name === 'setsockopt') {
|
||||
return {
|
||||
ok: false,
|
||||
op: name,
|
||||
code: 'ENOSYS',
|
||||
errnoHint: 'ENOSYS',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
note:
|
||||
'Socket option syscalls are not kernel FDs in Bare OS; use ctx.bare networking modules.'
|
||||
}
|
||||
}
|
||||
if (
|
||||
name === 'socket' ||
|
||||
name === 'bind' ||
|
||||
@@ -3999,7 +4193,45 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
*/
|
||||
async bareOsVfsBatchWrite(puts) {
|
||||
await bareOsVfsBatchPut(disk.drive, puts)
|
||||
if (vfs?.bareOsClearWarmReadCaches && Array.isArray(puts)) {
|
||||
if (!vfs || !Array.isArray(puts)) return
|
||||
let hasManifestPut = false
|
||||
/** @type {Uint8Array | ArrayBuffer | ArrayBufferView | null | undefined} */
|
||||
let manifestBuf = null
|
||||
let hasOtherWarmPut = false
|
||||
for (const row of puts) {
|
||||
const p = String(row?.path || '').replace(/^\/+/, '')
|
||||
if (p === 'lib/bare/bare-module-manifest.json') {
|
||||
hasManifestPut = true
|
||||
manifestBuf = row?.buf
|
||||
} else if (
|
||||
p === 'bin' ||
|
||||
p.startsWith('bin/') ||
|
||||
p === 'lib/bare' ||
|
||||
p.startsWith('lib/bare/')
|
||||
) {
|
||||
hasOtherWarmPut = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (
|
||||
hasManifestPut &&
|
||||
!hasOtherWarmPut &&
|
||||
manifestBuf != null &&
|
||||
typeof vfs.bareOsEvictLibBareBundlesFromManifest === 'function'
|
||||
) {
|
||||
const u8 =
|
||||
manifestBuf instanceof Uint8Array
|
||||
? manifestBuf
|
||||
: new Uint8Array(
|
||||
manifestBuf instanceof ArrayBuffer
|
||||
? manifestBuf
|
||||
: /** @type {ArrayBufferView} */ (manifestBuf).buffer
|
||||
)
|
||||
vfs.bareOsEvictLibBareBundlesFromManifest(u8)
|
||||
bareOsKernelMetricInc('vfs.warm_read_cache_invalidate_batch_manifest')
|
||||
return
|
||||
}
|
||||
if (typeof vfs.bareOsClearWarmReadCaches === 'function') {
|
||||
for (const row of puts) {
|
||||
const p = String(row?.path || '').replace(/^\/+/, '')
|
||||
if (
|
||||
@@ -4089,6 +4321,17 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
if (handles.length) o.snapshot_handles = handles
|
||||
return o
|
||||
},
|
||||
/**
|
||||
* Same object as `/proc/bare_os/protomux_extensions.json` (gated by `BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY`).
|
||||
* @returns {Record<string, unknown>}
|
||||
*/
|
||||
bareOsReadProtomuxExtensionsJson() {
|
||||
return buildBareOsProtomuxExtensionsProcJson({
|
||||
env: shellEnv,
|
||||
registrySnapshot: protomuxAliasRegistry.snapshot(),
|
||||
ctxApiVersion: BARE_OS_CTX_API_VERSION
|
||||
})
|
||||
},
|
||||
bareOsVaultAuditSummary() {
|
||||
const c = bareOsInteractiveCtxRef.ctx
|
||||
const id = c && c.identity
|
||||
@@ -4201,6 +4444,26 @@ async function executeKernel(disk, store, swarm, initSource) {
|
||||
bareOsKernelMetricInc('vfs.warm_read_cache_invalidate_explicit')
|
||||
return { ok: true, reason: String(reason || '').slice(0, 256) }
|
||||
},
|
||||
/**
|
||||
* Evict `/lib/bare` warm-cache rows using a `bare-module-manifest.json` payload
|
||||
* (same selective path as `bareOsVfsBatchWrite` manifest-only puts).
|
||||
* @param {Uint8Array | ArrayBuffer} buf
|
||||
*/
|
||||
bareOsInvalidateWarmReadCachesFromBareManifestJson(buf) {
|
||||
if (
|
||||
vfs &&
|
||||
typeof vfs.bareOsEvictLibBareBundlesFromManifest === 'function' &&
|
||||
buf
|
||||
) {
|
||||
const u8 =
|
||||
buf instanceof Uint8Array ? buf : new Uint8Array(/** @type {ArrayBuffer} */ (buf))
|
||||
vfs.bareOsEvictLibBareBundlesFromManifest(u8)
|
||||
} else if (vfs && typeof vfs.bareOsClearWarmReadCaches === 'function') {
|
||||
vfs.bareOsClearWarmReadCaches()
|
||||
}
|
||||
bareOsKernelMetricInc('vfs.warm_read_cache_invalidate_manifest_ctx')
|
||||
return { ok: true }
|
||||
},
|
||||
/**
|
||||
* Batch-read `/proc/bare_os/*` mirrors for baretop(1). Keys must stay aligned with
|
||||
* `BARE_TOP_SNAPSHOT_PROC_ENTRIES` in packages/bare-os-coreutils/lib/baretop-snapshot.js.
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
* Semantic version of the booter `ctx` contract for custom kernels.
|
||||
* Bump when adding/removing/renaming documented `ctx` fields or changing behavior.
|
||||
*/
|
||||
export const BARE_OS_CTX_API_VERSION = '1.38.0'
|
||||
export const BARE_OS_CTX_API_VERSION = '1.40.0'
|
||||
|
||||
@@ -134,6 +134,9 @@ export interface BareOsKernelContext {
|
||||
bareOsInvalidateWarmReadCaches?(
|
||||
reason?: string
|
||||
): { ok: boolean; reason: string }
|
||||
bareOsInvalidateWarmReadCachesFromBareManifestJson?(
|
||||
buf: Uint8Array | ArrayBuffer
|
||||
): { ok: boolean }
|
||||
/**
|
||||
* Optional batch `/proc/bare_os/*` read for baretop(1); keys match baretop-snapshot preamble.
|
||||
*/
|
||||
@@ -445,6 +448,8 @@ export interface BareOsKernelContext {
|
||||
}
|
||||
/** Corestore snapshot-style hints (same object as `/proc/bare_os/snapshot_hints.json`). */
|
||||
bareOsReadSnapshotHintsJson?(): Record<string, unknown>
|
||||
/** Protomux extension registry mirror (`/proc/bare_os/protomux_extensions.json`); gated by env. */
|
||||
bareOsReadProtomuxExtensionsJson?(): Record<string, unknown>
|
||||
bareOsVaultAuditSummary?(): {
|
||||
schema: number
|
||||
identityState: string
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { bareOsSwarmLifecycleSnapshot } from './bare-os-swarm-lifecycle.js'
|
||||
|
||||
/**
|
||||
* Gate blind-peer / relay operator JSON under `/proc/bare_os` (non-secret sketches only).
|
||||
* Default off so images do not advertise topology unless the operator opts in.
|
||||
@@ -20,3 +22,29 @@ export function bareOsProcBlindPeerRelayHintsStub(atMs) {
|
||||
atMs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-secret swarm-derived hints for blind-relay / pairing / geo proc JSON when hints are exposed.
|
||||
* No peer keys, addresses, or topic material — only counts and lifecycle classification.
|
||||
* @param {Record<string, string | undefined>} env
|
||||
* @param {Array<{ id?: unknown }>} peers
|
||||
*/
|
||||
export function buildBareOsBlindRelaySwarmRuntime(env, peers) {
|
||||
const peerCount = Array.isArray(peers) ? peers.length : 0
|
||||
const lifecycle = bareOsSwarmLifecycleSnapshot(env, peerCount)
|
||||
/** @type {'isolated' | 'single_peer' | 'multi_peer'} */
|
||||
let relayGeoTier = 'isolated'
|
||||
if (peerCount === 1) relayGeoTier = 'single_peer'
|
||||
else if (peerCount > 1) relayGeoTier = 'multi_peer'
|
||||
return {
|
||||
schema: 1,
|
||||
peerCount,
|
||||
relayGeoTier,
|
||||
pairingSurfaceReady: peerCount > 0,
|
||||
lifecycle,
|
||||
note:
|
||||
'Aggregates peer count and swarm lifecycle only; merge with env-injected operator JSON. No DHT keys or peer identities.',
|
||||
atMs: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@ import {
|
||||
* Aligns with seed RPC word 11 + bits11 — no Node `node:*` built-ins in guest paths.
|
||||
* @param {string} id
|
||||
* @param {Record<string, string>} env
|
||||
* @param {{ swarm?: Record<string, unknown> | null }} [runtimeHints]
|
||||
*/
|
||||
export function buildBareOsHypercorePackHrpcLifecycleProcJson(id, env) {
|
||||
export function buildBareOsHypercorePackHrpcLifecycleProcJson(id, env, runtimeHints) {
|
||||
const now = Date.now()
|
||||
const esc = (k) => String(env[k] ?? '').trim()
|
||||
|
||||
@@ -122,9 +123,11 @@ export function buildBareOsHypercorePackHrpcLifecycleProcJson(id, env) {
|
||||
return bareOsProcBlindPeerRelayHintsStub(now)
|
||||
}
|
||||
return {
|
||||
schema: 1,
|
||||
schema: 2,
|
||||
exposed: true,
|
||||
regions: parseJsonEnv('BARE_OS_RELAY_GEO_HINT_JSON'),
|
||||
note: 'coarse relay region tags.',
|
||||
swarm: runtimeHints?.swarm ?? null,
|
||||
note: 'Coarse relay region tags from env plus swarm aggregates (no geo-IP; peer count tier only).',
|
||||
atMs: now
|
||||
}
|
||||
case 'bare_pack_cache':
|
||||
|
||||
@@ -7,8 +7,9 @@ import {
|
||||
* Capability word 7 optional `/proc/bare_os/*.json` payloads (env-injected; bounded, non-secret).
|
||||
* @param {string} id
|
||||
* @param {Record<string, string>} env
|
||||
* @param {{ swarm?: Record<string, unknown> | null }} [runtimeHints]
|
||||
*/
|
||||
export function buildBareOsPearCorestoreHrpcProcJson(id, env) {
|
||||
export function buildBareOsPearCorestoreHrpcProcJson(id, env, runtimeHints) {
|
||||
const now = Date.now()
|
||||
const esc = (k) => String(env[k] ?? '').trim()
|
||||
|
||||
@@ -106,9 +107,11 @@ export function buildBareOsPearCorestoreHrpcProcJson(id, env) {
|
||||
return bareOsProcBlindPeerRelayHintsStub(now)
|
||||
}
|
||||
return {
|
||||
schema: 1,
|
||||
schema: 2,
|
||||
exposed: true,
|
||||
router: parseJsonEnv('BARE_OS_BLIND_RELAY_ROUTER_JSON'),
|
||||
note: 'Topology sketch from blind-peer-router patterns.',
|
||||
swarm: runtimeHints?.swarm ?? null,
|
||||
note: 'Env router sketch plus live swarm aggregates (peer count / lifecycle) when runtimeHints supplied from booter.',
|
||||
atMs: now
|
||||
}
|
||||
case 'autopass_session_sketch':
|
||||
|
||||
@@ -8,8 +8,9 @@ import {
|
||||
* Maps Holepunch `bare-*` / `pear-*` stacks — no Node `node:*` built-ins in guest paths.
|
||||
* @param {string} id
|
||||
* @param {Record<string, string>} env
|
||||
* @param {{ swarm?: Record<string, unknown> | null }} [runtimeHints]
|
||||
*/
|
||||
export function buildBareOsPearInspectLoggerTlsProcJson(id, env) {
|
||||
export function buildBareOsPearInspectLoggerTlsProcJson(id, env, runtimeHints) {
|
||||
const now = Date.now()
|
||||
const esc = (k) => String(env[k] ?? '').trim()
|
||||
|
||||
@@ -145,9 +146,11 @@ export function buildBareOsPearInspectLoggerTlsProcJson(id, env) {
|
||||
return bareOsProcBlindPeerRelayHintsStub(now)
|
||||
}
|
||||
return {
|
||||
schema: 1,
|
||||
schema: 2,
|
||||
exposed: true,
|
||||
sketch: parseJsonEnv('BARE_OS_BLIND_PAIRING_SKETCH_JSON'),
|
||||
note: 'blind-pairing operator sketch.',
|
||||
swarm: runtimeHints?.swarm ?? null,
|
||||
note: 'Env pairing sketch plus live swarm aggregates when booter supplies runtimeHints.',
|
||||
atMs: now
|
||||
}
|
||||
case 'broadcast_encryption_hint':
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
* ipcStats?: { processGroups?: Record<string, unknown> } | null,
|
||||
* logicalFdRows?: Array<{ fd: number, target: string }>,
|
||||
* initdReadiness?: { units?: Array<{ name: string, phase: string, startedAtMs: number, error?: string }>, schema?: number } | null,
|
||||
* sigactionHandlers?: Record<string, string> | null
|
||||
* sigactionHandlers?: Record<string, string> | null,
|
||||
* env?: Record<string, string | undefined> | null
|
||||
* }} opts
|
||||
*/
|
||||
export function bareOsProcessTableSnapshot(opts = {}) {
|
||||
@@ -98,6 +99,14 @@ export function bareOsProcessTableSnapshot(opts = {}) {
|
||||
? opts.sigactionHandlers
|
||||
: null
|
||||
|
||||
const env = opts.env && typeof opts.env === 'object' ? opts.env : {}
|
||||
const pipefailOn =
|
||||
env.BARE_OS_SHELL_PIPEFAIL === '1' ||
|
||||
env.BARE_OS_SHELL_PIPEFAIL === 'true'
|
||||
const posixModeOn =
|
||||
env.BARE_OS_SHELL_POSIX_MODE === '1' ||
|
||||
env.BARE_OS_SHELL_POSIX_MODE === 'true'
|
||||
|
||||
const initd = opts.initdReadiness
|
||||
const initdUnitsRaw =
|
||||
initd && Array.isArray(initd.units) ? initd.units : []
|
||||
@@ -168,9 +177,9 @@ export function bareOsProcessTableSnapshot(opts = {}) {
|
||||
}))
|
||||
|
||||
return {
|
||||
schema: 5,
|
||||
schemaVersion: 5,
|
||||
note: 'Synthetic rows; Bare OS guests do not expose host OS processes. v5 adds parentName and initdUnitName for POSIX-like ps trees.',
|
||||
schema: 6,
|
||||
schemaVersion: 6,
|
||||
note: 'Synthetic rows; Bare OS guests do not expose host OS processes. v6 adds jobControlSemantics (pipefail / posix mode env mirrors). v5 parentName/initd rows unchanged.',
|
||||
signalModel: {
|
||||
schema: 1,
|
||||
note: 'Virtual deliveries via ctx.bareOsSendSignal (not full sigaction/sigprocmask).',
|
||||
@@ -217,6 +226,16 @@ export function bareOsProcessTableSnapshot(opts = {}) {
|
||||
killpgAnalog:
|
||||
'Negative numeric targets index **`shellBackgroundJobs`** by **`pgid`**; active jobs only (zombies excluded except **`kill -0`** existence checks). Not a full killpg(2) emulation.'
|
||||
},
|
||||
jobControlSemantics: {
|
||||
schema: 1,
|
||||
pipefail: pipefailOn,
|
||||
posixShellMode: posixModeOn,
|
||||
pipelineExitRule: pipefailOn
|
||||
? 'first_failing_stage_in_pipeline'
|
||||
: 'last_stage_posix_default',
|
||||
waitReapsCompletedJobs: true,
|
||||
note: 'Mirrors BARE_OS_SHELL_PIPEFAIL and BARE_OS_SHELL_POSIX_MODE; see handbook ch.9 §3.'
|
||||
},
|
||||
ipcProcessGroups:
|
||||
opts.ipcStats &&
|
||||
opts.ipcStats.processGroups &&
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* `/proc/bare_os/protomux_extensions.json` — policy-gated operator view of Protomux
|
||||
* channel hints for kernel extensions (no wire secrets).
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Record<string, string | undefined>} env
|
||||
*/
|
||||
function protomuxExtensionsRegistryExposed(env) {
|
||||
const v = String(env?.BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY ?? '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
return v === '1' || v === 'true' || v === 'yes'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* env?: Record<string, string | undefined> | null,
|
||||
* registrySnapshot?: Record<string, unknown> | null,
|
||||
* ctxApiVersion?: string
|
||||
* }} opts
|
||||
*/
|
||||
export function buildBareOsProtomuxExtensionsProcJson(opts = {}) {
|
||||
const env = opts.env && typeof opts.env === 'object' ? opts.env : {}
|
||||
const now = Date.now()
|
||||
if (!protomuxExtensionsRegistryExposed(env)) {
|
||||
return {
|
||||
schema: 1,
|
||||
exposed: false,
|
||||
note:
|
||||
'Set BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY=1 to expose extension mux hints (alias registry snapshot + stable logical channel names).',
|
||||
atMs: now
|
||||
}
|
||||
}
|
||||
const snap =
|
||||
opts.registrySnapshot && typeof opts.registrySnapshot === 'object'
|
||||
? opts.registrySnapshot
|
||||
: {}
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
exposed: true,
|
||||
ctxApiVersion: String(opts.ctxApiVersion || ''),
|
||||
registry: snap,
|
||||
extensionLogicalChannels: [
|
||||
{
|
||||
name: 'bare-os-kernel-ext-handshake',
|
||||
note: 'Reserved logical label for extension pairing over Protomux-framed streams (P2P).'
|
||||
},
|
||||
{
|
||||
name: 'bare-os-extension-telemetry',
|
||||
note: 'Optional NDJSON-shaped diagnostic channel; host must open explicitly.'
|
||||
}
|
||||
],
|
||||
wireReference: '/proc/bare_os/protomux.json',
|
||||
atMs: now
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Live Hyperdrive / core length hints for `/proc/bare_os/replication` and
|
||||
* `metrics_live.replicationLive` (non-secret progress; not full per-peer throughput).
|
||||
*
|
||||
* @param {{ drive?: unknown, personalDrive?: unknown } | null | undefined} disk
|
||||
* @param {number} peerCount
|
||||
*/
|
||||
export function buildBareOsReplicationLiveSketch(disk, peerCount) {
|
||||
let systemCoreLength = null
|
||||
let personalCoreLength = null
|
||||
try {
|
||||
const c =
|
||||
disk &&
|
||||
disk.drive &&
|
||||
/** @type {{ core?: { length?: number } }} */ (disk.drive).core
|
||||
if (c && typeof c.length === 'number') systemCoreLength = c.length
|
||||
} catch {
|
||||
systemCoreLength = null
|
||||
}
|
||||
try {
|
||||
const c =
|
||||
disk &&
|
||||
disk.personalDrive &&
|
||||
/** @type {{ core?: { length?: number } }} */ (disk.personalDrive).core
|
||||
if (c && typeof c.length === 'number') personalCoreLength = c.length
|
||||
} catch {
|
||||
personalCoreLength = null
|
||||
}
|
||||
const stallHint =
|
||||
peerCount === 0
|
||||
? 'no_peers'
|
||||
: systemCoreLength == null
|
||||
? 'length_unavailable'
|
||||
: 'ok'
|
||||
return {
|
||||
schema: 1,
|
||||
systemCoreLength,
|
||||
personalCoreLength,
|
||||
stallHint,
|
||||
note: 'Append-only core lengths are non-secret progress hints; not a full replication telemetry plane.'
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,44 @@ export const BARE_OS_SYSCALL_OPS_DETAIL = Object.freeze([
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['stream.end / destroy'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'getsockopt',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['kernel socket FDs not exposed; use ctx.bare / swarm'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'setsockopt',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['kernel socket FDs not exposed; use ctx.bare / swarm'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'readv',
|
||||
category: 'fs',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'partial',
|
||||
mapsTo: [
|
||||
'ctx.bareOsSyscall("readv")',
|
||||
'bounded sequential reads from posix-pipe read FD (BARE_OS_POSIX_FD_SIM)'
|
||||
],
|
||||
errnoHint: 'EINVAL'
|
||||
},
|
||||
{
|
||||
name: 'writev',
|
||||
category: 'fs',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'partial',
|
||||
mapsTo: [
|
||||
'ctx.bareOsSyscall("writev")',
|
||||
'bounded concatenated write to posix-pipe write FD (BARE_OS_POSIX_FD_SIM)'
|
||||
],
|
||||
errnoHint: 'EINVAL'
|
||||
}
|
||||
])
|
||||
|
||||
@@ -153,6 +191,38 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
||||
mapsTo: ['vfs.writeFile', 'ctx.bareOsBinWrite', 'IPC fifo producer'],
|
||||
errnoHint: 'EIO'
|
||||
},
|
||||
{
|
||||
name: 'readv',
|
||||
category: 'fs',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'partial',
|
||||
mapsTo: ['ctx.bareOsSyscall("readv")', 'posix-pipe read FD', 'bounded iovec count'],
|
||||
errnoHint: 'EINVAL'
|
||||
},
|
||||
{
|
||||
name: 'writev',
|
||||
category: 'fs',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'partial',
|
||||
mapsTo: ['ctx.bareOsSyscall("writev")', 'posix-pipe write FD', 'bounded total bytes'],
|
||||
errnoHint: 'EINVAL'
|
||||
},
|
||||
{
|
||||
name: 'getsockopt',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("getsockopt")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'setsockopt',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("setsockopt")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'lseek',
|
||||
category: 'fs',
|
||||
@@ -194,6 +264,10 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
||||
'ctx.bareOsSyscall("fcntl")',
|
||||
'F_GETFL',
|
||||
'F_SETFL',
|
||||
'F_GETLK',
|
||||
'F_SETLK',
|
||||
'F_SETLKW',
|
||||
'file locks return EOPNOTSUPP object (not thrown)',
|
||||
'O_APPEND',
|
||||
'O_NONBLOCK',
|
||||
'bareOsLogicalFdFlags'
|
||||
@@ -223,6 +297,70 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
||||
posixAlignment: 'partial',
|
||||
mapsTo: ['vfs.env.UMASK octal', 'umask shell builtin'],
|
||||
errnoHint: 'EINVAL'
|
||||
},
|
||||
{
|
||||
name: 'socket',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("socket")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'bind',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("bind")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'listen',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("listen")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'accept',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("accept")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'connect',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("connect")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'send',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("send")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'recv',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("recv")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
},
|
||||
{
|
||||
name: 'shutdown',
|
||||
category: 'ipc',
|
||||
stability: 'experimental',
|
||||
posixAlignment: 'ENOTSUP',
|
||||
mapsTo: ['ctx.bareOsSyscall("shutdown")', 'ENOSYS-shaped probe'],
|
||||
errnoHint: 'ENOSYS'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
} from 'bare-os-protocol/bare-os-posix-profile.js'
|
||||
import {
|
||||
BARE_OS_SYSCALL_OPS_DETAIL_FULL,
|
||||
BARE_OS_STOCK_SYSCALL_OPS
|
||||
BARE_OS_STOCK_SYSCALL_OPS,
|
||||
bareOsPosixXshOpsCsv
|
||||
} from './bare-os-syscall-ops.js'
|
||||
import { BARE_OS_POSIX_SIGNAL_NAMES } from './bare-os-posix-signals.js'
|
||||
import { bareOsErrnoTableForProc } from './bare-os-posix-errno.js'
|
||||
@@ -28,9 +29,8 @@ export function buildBareOsSyscallsProcJson(p) {
|
||||
opsDetail: [...BARE_OS_SYSCALL_OPS_DETAIL_FULL],
|
||||
posixXsh: {
|
||||
schema: 1,
|
||||
note: 'POSIX.1 XSH-style names: logical names in opsDetail; socket family are ctx.bareOsSyscall ops returning ENOSYS-shaped results (not kernel socket FDs).',
|
||||
namesCsv:
|
||||
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,shutdown'
|
||||
note: 'POSIX.1 XSH-style names: logical names in opsDetail; socket family are ctx.bareOsSyscall ops returning ENOSYS-shaped results (not kernel socket FDs). readv/writev are partial posix-pipe facades; getsockopt/setsockopt are ENOSYS-shaped probes.',
|
||||
namesCsv: bareOsPosixXshOpsCsv()
|
||||
},
|
||||
errnoHints: bareOsErrnoTableForProc(),
|
||||
fdModel: {
|
||||
@@ -39,7 +39,7 @@ export function buildBareOsSyscallsProcJson(p) {
|
||||
stdio: [0, 1, 2],
|
||||
register: 'ctx.bareOsRegisterLogicalFd',
|
||||
processTablePath: '/proc/bare_os/process_table.json',
|
||||
processTableSchema: 5,
|
||||
processTableSchema: 6,
|
||||
posixLike: {
|
||||
schema: 1,
|
||||
note: 'POSIX open/read/write/close/pipe/dup/fcntl analogs; see docs/architecture/POSIX_DECLARED_PROFILE.md.',
|
||||
@@ -107,6 +107,12 @@ export function buildBareOsSyscallsProcJson(p) {
|
||||
caps: {
|
||||
note: 'VFS path classes and boot policy may deny individual ops at runtime.'
|
||||
},
|
||||
errnoAlignment: {
|
||||
schema: 1,
|
||||
note: 'errnoHints use Linux/x86-64-style integers (same family as libuv / Holepunch bare-fs binding errors). Logical FD simulation uses EBADF, EAGAIN, EINVAL, ENOSYS, EOPNOTSUPP consistently with bare-os-posix-errno.js.',
|
||||
openFlagsNote:
|
||||
'fcntl O_APPEND (0x400) and O_NONBLOCK (0x800) match the masks used by bare-fs open flags on the host when translating to guest logical FDs.'
|
||||
},
|
||||
atMs: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,31 @@ const README_TEXT = `Bare OS session logs (mirrored on your personal drive under
|
||||
audit.log — optional execLine audit when BARE_OS_AUDIT=1
|
||||
`
|
||||
|
||||
/**
|
||||
* Strip long hex / obvious secret-shaped tokens from telemetry mirrors (best-effort).
|
||||
* @param {string} s
|
||||
*/
|
||||
function bareOsTelemetryRedactString(s) {
|
||||
return String(s)
|
||||
.replace(/\b[0-9a-f]{128,}\b/gi, '<redacted_hex>')
|
||||
.replace(/\bBearer\s+\S+/gi, 'Bearer <redacted>')
|
||||
.replace(/\bsk-[a-zA-Z0-9]{16,}\b/g, '<redacted_sk>')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, unknown>} rec
|
||||
*/
|
||||
function bareOsTelemetrySanitizeRec(rec) {
|
||||
if (!rec || typeof rec !== 'object') return {}
|
||||
/** @type {Record<string, unknown>} */
|
||||
const o = {}
|
||||
for (const [k, v] of Object.entries(rec)) {
|
||||
if (typeof v === 'string') o[k] = bareOsTelemetryRedactString(v)
|
||||
else o[k] = v
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
/** Max size before trimming older log bytes (best-effort). */
|
||||
const LOG_MAX_BYTES = 512 * 1024
|
||||
|
||||
@@ -118,6 +143,9 @@ async function mirrorBareOsTelemetryNdjson(ctx, rec) {
|
||||
const pearInspectLoggerTlsProbeId = String(env.BARE_OS_PROBE_ID_PEAR_INSPECT_LOGGER_TLS || '').trim()
|
||||
const hypercorePackHrpcLifecycleProbeId = String(env.BARE_OS_PROBE_ID_HYPERCORE_PACK_HRPC_LIFECYCLE || '').trim()
|
||||
const traceId = String(env.BARE_OS_TRACE_ID || '').trim()
|
||||
const safeRec = bareOsTelemetrySanitizeRec(
|
||||
/** @type {Record<string, unknown>} */ (rec)
|
||||
)
|
||||
const line =
|
||||
JSON.stringify({
|
||||
telemetrySchemaVersion: BARE_OS_TELEMETRY_SCHEMA_VERSION,
|
||||
@@ -144,7 +172,7 @@ async function mirrorBareOsTelemetryNdjson(ctx, rec) {
|
||||
)
|
||||
return Number.isFinite(n) ? Math.min(1e6, n) : undefined
|
||||
})(),
|
||||
...rec
|
||||
...safeRec
|
||||
}) + '\n'
|
||||
const chunk = ctx.b4a.from(line)
|
||||
const prev = await vfs.readFile(dest)
|
||||
@@ -176,6 +204,9 @@ async function mirrorBareOsOtelJsonl(ctx, eventName, attrs) {
|
||||
if (!dest.startsWith('/') && !dest.startsWith('~/')) return
|
||||
const vfs = ctx.vfs
|
||||
if (!vfs || typeof vfs.readFile !== 'function') return
|
||||
const safeAttrs = bareOsTelemetrySanitizeRec(
|
||||
/** @type {Record<string, unknown>} */ (attrs)
|
||||
)
|
||||
const line =
|
||||
JSON.stringify({
|
||||
otlSchemaVersion: 8,
|
||||
@@ -202,7 +233,7 @@ async function mirrorBareOsOtelJsonl(ctx, eventName, attrs) {
|
||||
events: [],
|
||||
links: [],
|
||||
exemplars: [],
|
||||
attributes: Object.entries(attrs).map(([k, v]) => ({
|
||||
attributes: Object.entries(safeAttrs).map(([k, v]) => ({
|
||||
key: k,
|
||||
value:
|
||||
typeof v === 'string'
|
||||
|
||||
@@ -2272,6 +2272,38 @@ function tryExecShellDeclareBuiltin(ctx, rest) {
|
||||
async function dispatchShellStatement(ctx, stmt) {
|
||||
const head = stmt[0]
|
||||
const shEnv = ctx.vfs?.env
|
||||
const posixMode =
|
||||
shEnv &&
|
||||
(shEnv.BARE_OS_SHELL_POSIX_MODE === '1' ||
|
||||
shEnv.BARE_OS_SHELL_POSIX_MODE === 'true')
|
||||
if (posixMode && head?.type === 'op' && head.value === '(') {
|
||||
let depth = 0
|
||||
let close = -1
|
||||
for (let j = 0; j < stmt.length; j++) {
|
||||
const t = stmt[j]
|
||||
if (t.type === 'op' && t.value === '(') depth++
|
||||
else if (t.type === 'op' && t.value === ')') {
|
||||
depth--
|
||||
if (depth === 0) {
|
||||
close = j
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (close < 0) {
|
||||
ctx.console.error('shell: POSIX mode: unmatched (')
|
||||
ctx.exitCode = 2
|
||||
return 'ok'
|
||||
}
|
||||
if (close !== stmt.length - 1) {
|
||||
ctx.console.error(
|
||||
'shell: POSIX mode: grouped list must span the full statement'
|
||||
)
|
||||
ctx.exitCode = 2
|
||||
return 'ok'
|
||||
}
|
||||
return execSemicolonLists(ctx, stmt.slice(1, close))
|
||||
}
|
||||
const localOn =
|
||||
shEnv &&
|
||||
(shEnv.BARE_OS_SHELL_LOCAL_DECLARE === '1' ||
|
||||
|
||||
@@ -362,6 +362,7 @@ export const BARE_OS_PROC_FILE_TO_ID_HYPERCORE_PACK_HRPC_LIFECYCLE = Object.free
|
||||
* procBareOsSyscallsText?: () => string,
|
||||
* procBareOsMetricsPromText?: () => string,
|
||||
* procBareOsProtomuxWireText?: () => string,
|
||||
* procBareOsProtomuxExtensionsText?: () => string,
|
||||
* procBareOsNetSummaryText?: () => string,
|
||||
* procBareOsExtensionsText?: () => string,
|
||||
* procBareOsHdmsHintsText?: () => string,
|
||||
@@ -565,6 +566,10 @@ export function createVfs(
|
||||
typeof vfsOptions.procBareOsProtomuxWireText === 'function'
|
||||
? vfsOptions.procBareOsProtomuxWireText
|
||||
: null
|
||||
const procBareOsProtomuxExtensionsText =
|
||||
typeof vfsOptions.procBareOsProtomuxExtensionsText === 'function'
|
||||
? vfsOptions.procBareOsProtomuxExtensionsText
|
||||
: null
|
||||
const procBareOsNetSummaryText =
|
||||
typeof vfsOptions.procBareOsNetSummaryText === 'function'
|
||||
? vfsOptions.procBareOsNetSummaryText
|
||||
@@ -799,6 +804,72 @@ export function createVfs(
|
||||
bareOsKernelMetricInc('vfs.warm_read_cache_clear')
|
||||
}
|
||||
|
||||
/** @param {string} absFollowed */
|
||||
function bareOsEvictSingleWarmReadPath(absFollowed) {
|
||||
if (!isWarmReadCachePath(absFollowed)) return
|
||||
if (binReadCache) binReadCache.delete(absFollowed)
|
||||
if (binDigestCache && binPathToBlakeDigest && binDigestRefcount) {
|
||||
const oldHex = binPathToBlakeDigest.get(absFollowed)
|
||||
if (oldHex) {
|
||||
binPathToBlakeDigest.delete(absFollowed)
|
||||
const n0 = (binDigestRefcount.get(oldHex) || 1) - 1
|
||||
if (n0 <= 0) {
|
||||
binDigestRefcount.delete(oldHex)
|
||||
binDigestCache.delete(oldHex)
|
||||
} else {
|
||||
binDigestRefcount.set(oldHex, n0)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binBlake2bLruPaths) {
|
||||
const i = binBlake2bLruPaths.indexOf(absFollowed)
|
||||
if (i >= 0) binBlake2bLruPaths.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate warm-cache entries for `bare-module-manifest.json` and bundled
|
||||
* `/lib/bare/bundles/<ctxKey>.js` rows (parse errors fall back to full clear).
|
||||
* @param {Uint8Array | ArrayBuffer} buf
|
||||
*/
|
||||
function bareOsEvictLibBareBundlesFromManifest(buf) {
|
||||
const u8 =
|
||||
buf instanceof Uint8Array ? buf : new Uint8Array(/** @type {ArrayBuffer} */ (buf))
|
||||
let text
|
||||
try {
|
||||
text = new TextDecoder().decode(u8)
|
||||
} catch {
|
||||
bareOsClearWarmReadCaches()
|
||||
return
|
||||
}
|
||||
/** @type {unknown} */
|
||||
let o
|
||||
try {
|
||||
o = JSON.parse(text)
|
||||
} catch {
|
||||
bareOsClearWarmReadCaches()
|
||||
return
|
||||
}
|
||||
if (
|
||||
!o ||
|
||||
typeof o !== 'object' ||
|
||||
!Array.isArray(/** @type {{ entries?: unknown }} */ (o).entries)
|
||||
) {
|
||||
bareOsClearWarmReadCaches()
|
||||
return
|
||||
}
|
||||
bareOsEvictSingleWarmReadPath('/lib/bare/bare-module-manifest.json')
|
||||
for (const e of /** @type {{ entries: unknown[] }} */ (o).entries) {
|
||||
if (!e || typeof e !== 'object') continue
|
||||
const ent = /** @type {{ bundle?: boolean, ctxKey?: string }} */ (e)
|
||||
if (ent.bundle !== true) continue
|
||||
const ck = String(ent.ctxKey || '').trim()
|
||||
if (!ck) continue
|
||||
bareOsEvictSingleWarmReadPath(`/lib/bare/bundles/${ck}.js`)
|
||||
}
|
||||
bareOsKernelMetricInc('vfs.warm_read_cache_evict_manifest')
|
||||
}
|
||||
|
||||
const sysClassNetLoText =
|
||||
typeof vfsOptions.sysClassNetLoText === 'function'
|
||||
? vfsOptions.sysClassNetLoText
|
||||
@@ -1321,6 +1392,12 @@ export function createVfs(
|
||||
: '{"schemaVersion":1,"aliases":{}}\n'
|
||||
return utf8Encode(t)
|
||||
}
|
||||
if (f === 'bare_os_protomux_extensions') {
|
||||
const t = procBareOsProtomuxExtensionsText
|
||||
? procBareOsProtomuxExtensionsText()
|
||||
: '{"schema":1,"exposed":false}\n'
|
||||
return utf8Encode(t)
|
||||
}
|
||||
if (f === 'bare_os_net_summary') {
|
||||
const t = procBareOsNetSummaryText
|
||||
? procBareOsNetSummaryText()
|
||||
@@ -1528,6 +1605,10 @@ export function createVfs(
|
||||
name: 'protomux.json',
|
||||
path: '/proc/bare_os/protomux.json'
|
||||
},
|
||||
{
|
||||
name: 'protomux_extensions.json',
|
||||
path: '/proc/bare_os/protomux_extensions.json'
|
||||
},
|
||||
{
|
||||
name: 'net_summary.json',
|
||||
path: '/proc/bare_os/net_summary.json'
|
||||
@@ -2226,6 +2307,8 @@ export function createVfs(
|
||||
'metrics.prom': 'bare_os_metrics_prom',
|
||||
protomux: 'bare_os_protomux_wire',
|
||||
'protomux.json': 'bare_os_protomux_wire',
|
||||
protomux_extensions: 'bare_os_protomux_extensions',
|
||||
'protomux_extensions.json': 'bare_os_protomux_extensions',
|
||||
net_summary: 'bare_os_net_summary',
|
||||
'net_summary.json': 'bare_os_net_summary',
|
||||
host_os: 'bare_os_host_os',
|
||||
@@ -2688,6 +2771,17 @@ export function createVfs(
|
||||
file: 'bare_os_protomux_wire'
|
||||
}
|
||||
}
|
||||
if (
|
||||
sub === 'bare_os_protomux_extensions' ||
|
||||
sub === 'bare_os_protomux_extensions.json'
|
||||
) {
|
||||
return {
|
||||
virtualPseudo: true,
|
||||
kind: 'proc',
|
||||
node: 'file',
|
||||
file: 'bare_os_protomux_extensions'
|
||||
}
|
||||
}
|
||||
if (
|
||||
sub === 'bare_os_net_summary' ||
|
||||
sub === 'bare_os_net_summary.json'
|
||||
@@ -3908,6 +4002,7 @@ export function createVfs(
|
||||
'bare_os_protomux_channels.json',
|
||||
'bare_os_protomux_rpc_pool_health.json',
|
||||
'bare_os_protomux_wire.json',
|
||||
'bare_os_protomux_extensions.json',
|
||||
'bare_os_provenance',
|
||||
'bare_os_quotas',
|
||||
'bare_os_react_native_bare_kit.json',
|
||||
@@ -4076,6 +4171,7 @@ export function createVfs(
|
||||
'protomux_channels.json',
|
||||
'protomux_rpc_pool_health.json',
|
||||
'protomux.json',
|
||||
'protomux_extensions.json',
|
||||
'provenance',
|
||||
'quotas',
|
||||
'react_native_bare_kit.json',
|
||||
@@ -4460,6 +4556,7 @@ export function createVfs(
|
||||
env,
|
||||
|
||||
bareOsClearWarmReadCaches,
|
||||
bareOsEvictLibBareBundlesFromManifest,
|
||||
|
||||
async chdir(userPath) {
|
||||
const abs = resolveLogical(userPath)
|
||||
|
||||
@@ -92,6 +92,8 @@ import {
|
||||
import { parseUnitDropInText } from './lib/bare-initd-user.js'
|
||||
import { bareOsProcessTableSnapshot } from './lib/bare-os-process-table.js'
|
||||
import { buildBareOsSyscallsProcJson } from './lib/bare-os-syscalls-proc-json.js'
|
||||
import { buildBareOsProtomuxExtensionsProcJson } from './lib/bare-os-protomux-extensions-proc.js'
|
||||
import { buildBareOsReplicationLiveSketch } from './lib/bare-os-replication-proc-live.js'
|
||||
import { buildBareOsReplicationOperatorSurfaceProcJson } from './lib/bare-os-proc-replication-operator-surface.js'
|
||||
import {
|
||||
DEFAULT_CURL_USER_AGENT,
|
||||
@@ -1072,6 +1074,55 @@ test('vfs /bin warm read cache hit then bareOsClearWarmReadCaches resets', async
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test('vfs bareOsEvictLibBareBundlesFromManifest evicts only listed bundle paths', async (t) => {
|
||||
const dir = testCorestoreDir('manifestevict')
|
||||
const store = new Corestore(dir)
|
||||
const sys = new Hyperdrive(store)
|
||||
const personal = new Hyperdrive(store.namespace('me'))
|
||||
await sys.ready()
|
||||
await personal.ready()
|
||||
await sys.put('/lib/bare/bundles/b4a.js', b4a.from('b4a'))
|
||||
await sys.put('/lib/bare/bundles/safetyCatch.js', b4a.from('sc'))
|
||||
const warmRef = { current: null }
|
||||
const env = {
|
||||
HOME: '/home/g',
|
||||
PWD: '/',
|
||||
PATH: '/bin',
|
||||
BARE_OS_VFS_BIN_CACHE: '1',
|
||||
BARE_OS_VFS_LIB_BARE_CACHE: '1'
|
||||
}
|
||||
const vfs = createVfs(sys, personal, env, null, {
|
||||
warmReadCacheStatsRef: warmRef
|
||||
})
|
||||
await vfs.readFile('/lib/bare/bundles/b4a.js')
|
||||
await vfs.readFile('/lib/bare/bundles/safetyCatch.js')
|
||||
const hitsBefore = warmRef.current?.hits ?? 0
|
||||
await vfs.readFile('/lib/bare/bundles/b4a.js')
|
||||
t.ok((warmRef.current?.hits ?? 0) > hitsBefore)
|
||||
const manifest = JSON.stringify({
|
||||
version: 1,
|
||||
entries: [
|
||||
{ ctxKey: 'b4a', package: 'b4a', bundle: true },
|
||||
{ ctxKey: 'xOther', package: 'x', bundle: false }
|
||||
]
|
||||
})
|
||||
vfs.bareOsEvictLibBareBundlesFromManifest(b4a.from(manifest))
|
||||
const missesAfterEvict = warmRef.current?.misses ?? 0
|
||||
await vfs.readFile('/lib/bare/bundles/b4a.js')
|
||||
t.ok(
|
||||
(warmRef.current?.misses ?? 0) > missesAfterEvict,
|
||||
'b4a should miss after selective evict'
|
||||
)
|
||||
const hitsSc = warmRef.current?.hits ?? 0
|
||||
await vfs.readFile('/lib/bare/bundles/safetyCatch.js')
|
||||
t.ok(
|
||||
(warmRef.current?.hits ?? 0) > hitsSc,
|
||||
'safetyCatch still served from warm cache'
|
||||
)
|
||||
await store.close()
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test('blind relay / pairing / geo proc JSON stubbed without BARE_OS_PROC_BLIND_PEER_RELAY_HINTS', async (t) => {
|
||||
const a = buildBareOsPearCorestoreHrpcProcJson('blind_relay_router', {})
|
||||
t.is(a.exposed, false)
|
||||
@@ -1079,11 +1130,78 @@ test('blind relay / pairing / geo proc JSON stubbed without BARE_OS_PROC_BLIND_P
|
||||
t.is(b.exposed, false)
|
||||
const c = buildBareOsHypercorePackHrpcLifecycleProcJson('relay_geo_hint', {})
|
||||
t.is(c.exposed, false)
|
||||
const on = buildBareOsPearCorestoreHrpcProcJson('blind_relay_router', {
|
||||
BARE_OS_PROC_BLIND_PEER_RELAY_HINTS: '1',
|
||||
BARE_OS_BLIND_RELAY_ROUTER_JSON: '{"lanes":1}'
|
||||
})
|
||||
const { buildBareOsBlindRelaySwarmRuntime } = await import(
|
||||
'./lib/bare-os-proc-blind-peer-relay-gate.js'
|
||||
)
|
||||
const rt = {
|
||||
swarm: buildBareOsBlindRelaySwarmRuntime(
|
||||
{},
|
||||
[{ id: 'a' }, { id: 'b' }]
|
||||
)
|
||||
}
|
||||
const on = buildBareOsPearCorestoreHrpcProcJson(
|
||||
'blind_relay_router',
|
||||
{
|
||||
BARE_OS_PROC_BLIND_PEER_RELAY_HINTS: '1',
|
||||
BARE_OS_BLIND_RELAY_ROUTER_JSON: '{"lanes":1}'
|
||||
},
|
||||
rt
|
||||
)
|
||||
t.is(on.schema, 2)
|
||||
t.is(on.exposed, true)
|
||||
t.ok(on.router && typeof on.router === 'object')
|
||||
t.is(on.swarm?.peerCount, 2)
|
||||
t.is(on.swarm?.relayGeoTier, 'multi_peer')
|
||||
const pair = buildBareOsPearInspectLoggerTlsProcJson(
|
||||
'blind_pairing_sketch',
|
||||
{ BARE_OS_PROC_BLIND_PEER_RELAY_HINTS: 'yes' },
|
||||
rt
|
||||
)
|
||||
t.is(pair.schema, 2)
|
||||
t.is(pair.swarm?.pairingSurfaceReady, true)
|
||||
const geo = buildBareOsHypercorePackHrpcLifecycleProcJson(
|
||||
'relay_geo_hint',
|
||||
{ BARE_OS_PROC_BLIND_PEER_RELAY_HINTS: 'true' },
|
||||
rt
|
||||
)
|
||||
t.is(geo.schema, 2)
|
||||
t.ok(geo.regions == null)
|
||||
t.is(geo.swarm?.relayGeoTier, 'multi_peer')
|
||||
})
|
||||
|
||||
test('protomux_extensions proc JSON gated by BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY', async (t) => {
|
||||
const off = buildBareOsProtomuxExtensionsProcJson({ env: {} })
|
||||
t.is(off.exposed, false)
|
||||
const on = buildBareOsProtomuxExtensionsProcJson({
|
||||
env: { BARE_OS_PROC_PROTOMUX_EXTENSIONS_REGISTRY: '1' },
|
||||
registrySnapshot: { aliases: {}, schema: 1 },
|
||||
ctxApiVersion: BARE_OS_CTX_API_VERSION
|
||||
})
|
||||
t.is(on.exposed, true)
|
||||
t.ok(Array.isArray(on.extensionLogicalChannels))
|
||||
})
|
||||
|
||||
test('buildBareOsReplicationLiveSketch reads hyperdrive core lengths', async (t) => {
|
||||
const dir = testCorestoreDir('replive-sketch')
|
||||
const store = new Corestore(dir)
|
||||
const drive = new Hyperdrive(store)
|
||||
const personal = new Hyperdrive(store.namespace('rls'))
|
||||
await drive.ready()
|
||||
await personal.ready()
|
||||
const sk0 = buildBareOsReplicationLiveSketch(
|
||||
{ drive, personalDrive: personal },
|
||||
0
|
||||
)
|
||||
t.is(sk0.schema, 1)
|
||||
t.is(sk0.stallHint, 'no_peers')
|
||||
t.ok(typeof sk0.systemCoreLength === 'number')
|
||||
const sk1 = buildBareOsReplicationLiveSketch(
|
||||
{ drive, personalDrive: personal },
|
||||
1
|
||||
)
|
||||
t.is(sk1.stallHint, 'ok')
|
||||
await store.close()
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test('protomux_rpc_pool_health proc uses schema 2 and backpressure correlation fields', async (t) => {
|
||||
@@ -1135,6 +1253,8 @@ test('buildBareOsSyscallsProcJson exposes posixLike fd mapping', async (t) => {
|
||||
t.ok(j.posixXsh.namesCsv.includes('poll'))
|
||||
t.ok(j.posixXsh.namesCsv.includes('select'))
|
||||
t.ok(j.posixXsh.namesCsv.includes('umask'))
|
||||
t.ok(j.posixXsh.namesCsv.includes('readv'))
|
||||
t.ok(j.posixXsh.namesCsv.includes('writev'))
|
||||
t.ok(j.posixXsh.namesCsv.includes('socket'))
|
||||
t.ok(j.posixXsh.namesCsv.includes('shutdown'))
|
||||
const xsh = j.opsDetail.filter((r) => r.posixAlignment)
|
||||
@@ -1512,6 +1632,7 @@ test('vfs /proc /sys read-only pseudo files; write rejected', async (t) => {
|
||||
'bare_os_protomux_backpressure.json',
|
||||
'bare_os_protomux_channel_alias_v2.json',
|
||||
'bare_os_protomux_channels.json',
|
||||
'bare_os_protomux_extensions.json',
|
||||
'bare_os_protomux_rpc_pool_health.json',
|
||||
'bare_os_protomux_wire.json',
|
||||
'bare_os_provenance',
|
||||
@@ -1973,6 +2094,33 @@ async function run(ctx, argv) {
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test('execShellLine BARE_OS_SHELL_POSIX_MODE grouped list', async (t) => {
|
||||
const dir = testCorestoreDir('shposixgroup')
|
||||
const store = new Corestore(dir)
|
||||
const drive = new Hyperdrive(store)
|
||||
const personal = new Hyperdrive(store.namespace('spg'))
|
||||
await drive.ready()
|
||||
await personal.ready()
|
||||
const echo = `
|
||||
async function run(ctx, argv) {
|
||||
ctx.console.log(argv.slice(1).join(' '))
|
||||
}
|
||||
`
|
||||
await drive.put('/bin/echo', b4a.from(echo))
|
||||
const ctx = testCtx(drive, personal)
|
||||
const logs = []
|
||||
ctx.console = {
|
||||
log: (...a) => logs.push(a.join(' ')),
|
||||
error: (...a) => logs.push(a.join(' '))
|
||||
}
|
||||
ctx.vfs.env.BARE_OS_SHELL_POSIX_MODE = '1'
|
||||
await ctx.vfs.chdir('/home/user')
|
||||
await execShellLine(ctx, '( echo hi )')
|
||||
t.ok(logs.some((l) => l === 'hi'))
|
||||
await store.close()
|
||||
rmSync(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test('expandWord reads env', async (t) => {
|
||||
t.is(expandWord('x${HOME}y', { HOME: '/h' }), 'x/hy')
|
||||
})
|
||||
@@ -5613,11 +5761,14 @@ test('worker_budget proc surface schema 2 exposes cpu and class map env', async
|
||||
})
|
||||
|
||||
test('process table snapshot includes processGroups metadata', async (t) => {
|
||||
const s = bareOsProcessTableSnapshot({})
|
||||
const s = bareOsProcessTableSnapshot({
|
||||
env: { BARE_OS_SHELL_PIPEFAIL: '1' }
|
||||
})
|
||||
t.ok(s.processGroups)
|
||||
t.is(s.processGroups.schema, 1)
|
||||
t.ok(String(s.processGroups.killpgAnalog).includes('killpg'))
|
||||
t.is(s.schemaVersion, 5)
|
||||
t.is(s.schemaVersion, 6)
|
||||
t.ok(s.jobControlSemantics && s.jobControlSemantics.pipefail === true)
|
||||
const booter = s.processes.find((p) => p && p.pid === 2)
|
||||
t.ok(booter && booter.parentName === 'bare-os-kernel')
|
||||
const shell = s.processes.find((p) => p && p.pid === 3)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Supports: BEGIN/END, /re/, line patterns, {}, print/printf, if/else, while, for(;;), for(x in a),
|
||||
* next, exit, break, continue, ++/--, arrays, strings, regex ~ !~, builtins (length, substr, index,
|
||||
* split, sprintf, sub, gsub, match, int, tolower, toupper, rand, srand), getline from stdin/files,
|
||||
* optional fixed-width fields via FIELDWIDTHS when BARE_OS_AWK_FIELDWIDTHS is enabled,
|
||||
* -F FS, NF, NR, FNR, $0..$n, OFS, ORS, RS, ARGC, ARGV, FILENAME, ENVIRON (read-only mirror).
|
||||
* GNU-style empty fields: consecutive FS delimiters still advance $1..$NF where the grammar allows.
|
||||
*/
|
||||
@@ -130,7 +131,7 @@ function bareAwkLex(src, st) {
|
||||
return { kind: 'OP', value: '==', line }
|
||||
}
|
||||
|
||||
if ('+-*/%(){}[],;?:<>=!~^'.includes(c)) {
|
||||
if ('+-*/%(){}[],;?:<>=!~^$'.includes(c)) {
|
||||
st.i++
|
||||
return { kind: 'OP', value: c, line }
|
||||
}
|
||||
@@ -718,6 +719,33 @@ class BareAwkRuntime {
|
||||
}
|
||||
|
||||
splitFields() {
|
||||
const cap = this.environ.BARE_OS_AWK_FIELDWIDTHS
|
||||
if (cap === '1' || cap === 'true') {
|
||||
const fw = String(
|
||||
this.vars.FIELDWIDTHS != null ? this.vars.FIELDWIDTHS : ''
|
||||
).trim()
|
||||
if (fw) {
|
||||
const nums = fw
|
||||
.split(/\s+/)
|
||||
.map((x) => Number.parseInt(x, 10))
|
||||
.filter((n) => Number.isFinite(n) && n > 0)
|
||||
if (nums.length) {
|
||||
/** @type {string[]} */
|
||||
const parts = []
|
||||
let pos = 0
|
||||
const line = this.$0
|
||||
for (const w of nums) {
|
||||
parts.push(line.slice(pos, pos + w))
|
||||
pos += w
|
||||
}
|
||||
if (pos < line.length) parts.push(line.slice(pos))
|
||||
this.fields = parts
|
||||
this.NF = parts.length
|
||||
this.vars.NF = this.NF
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
const fs = this.FS
|
||||
let parts
|
||||
if (fs === ' ') {
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
"synopsis": [
|
||||
"mkfifo [OPTION]... [OPERAND]..."
|
||||
],
|
||||
"description": "FIFO special files are not implemented on Hyperdrive. The command reports failure.",
|
||||
"description": "Creates an in-memory named channel for IPC under /run/bare-os/ipc/<name> when the booter exposes ctx.bareOsIpc. Paths must be under that prefix (e.g. /run/bare-os/ipc/demo). Not a kernel FIFO on Hyperdrive; use shell pipelines for stream composition between utilities.",
|
||||
"options": [],
|
||||
"keywords": [
|
||||
"mkfifo",
|
||||
"bare-os",
|
||||
"coreutils"
|
||||
],
|
||||
"bareOsNotes": "Documented stub; no real pipes as kernel objects.",
|
||||
"bareOsNotes": "Optional BARE_OS_IPC_NAMESPACE prefixes the logical channel key. See handbook ch.9 (FIFOs, simulated IPC).",
|
||||
"examples": [
|
||||
{
|
||||
"caption": "stub",
|
||||
"code": "# FIFOs not on Hyperdrive — use shell pipelines"
|
||||
"caption": "create a named IPC channel",
|
||||
"code": "mkfifo /run/bare-os/ipc/demo"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ const CONF = {
|
||||
_PC_2_SYMLINKS: '1',
|
||||
/** Comma-separated `ctx.bareOsSyscall` op names implemented in stock booter. */
|
||||
BARE_OS_SYSCALL_OPS:
|
||||
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,kill,link,listen,lstat,mkdir,mount,pathconf,posixPoll,readFile,readdir,readlink,recv,rename,rmdir,select,send,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile',
|
||||
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,pathconf,posixPoll,readFile,readdir,readlink,readv,recv,rename,rmdir,select,send,setsockopt,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile,writev',
|
||||
/** POSIX.1 XSH-style names documented in `/proc/bare_os/syscalls.json` opsDetail (socket family are syscall probes returning ENOSYS-shaped results). */
|
||||
BARE_OS_POSIX_XSH_OPS:
|
||||
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,shutdown',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host spawn).
|
||||
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
||||
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
||||
* Supports -0/--null, -n, -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race).
|
||||
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
||||
*/
|
||||
@@ -39,6 +39,8 @@ async function run(ctx, argv) {
|
||||
/** @type {string | null} */
|
||||
let repl = null
|
||||
let nExplicit = false
|
||||
/** @type {number | null} */
|
||||
let linesPerInv = null
|
||||
const envPCap = maxParallelFromEnv(ctx)
|
||||
let pCap = 1
|
||||
let i = 0
|
||||
@@ -111,6 +113,23 @@ async function run(ctx, argv) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if (a === '-L' || a === '--max-lines') {
|
||||
const n = args[i + 1]
|
||||
if (n == null || !/^\d+$/.test(n) || Number(n) < 1) {
|
||||
ctx.console.error('xargs: -L requires a positive integer')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
linesPerInv = Math.min(Number(n), MAX_PER_INVOCATION)
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
if (a.startsWith('-L') && a.length > 2 && /^\d+$/.test(a.slice(2))) {
|
||||
const n = Number(a.slice(2))
|
||||
linesPerInv = Math.min(n, MAX_PER_INVOCATION)
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if (a === '-I' || a === '-i') {
|
||||
repl = args[i + 1] != null ? String(args[i + 1]) : '{}'
|
||||
i += 2
|
||||
@@ -131,7 +150,7 @@ async function run(ctx, argv) {
|
||||
ctx.console.error(
|
||||
'xargs: Bare OS supports: -0/--null, -n N (max ' +
|
||||
MAX_PER_INVOCATION +
|
||||
' per run), -I repl, -P N (parallel batches, cap ' +
|
||||
' per run), -L N (lines per invocation), -I repl, -P N (parallel batches, cap ' +
|
||||
envPCap +
|
||||
')'
|
||||
)
|
||||
@@ -139,6 +158,12 @@ async function run(ctx, argv) {
|
||||
return
|
||||
}
|
||||
|
||||
if (linesPerInv != null && nExplicit) {
|
||||
ctx.console.error('xargs: -L cannot be combined with -n')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
/** @type {string[]} */
|
||||
let cmd = args.slice(i)
|
||||
if (cmd.length === 0) cmd = ['echo']
|
||||
@@ -154,7 +179,19 @@ async function run(ctx, argv) {
|
||||
|
||||
/** @type {string[]} */
|
||||
let pieces
|
||||
if (nullSep) {
|
||||
if (linesPerInv != null) {
|
||||
if (nullSep) {
|
||||
pieces = text.split('\0').filter((s) => s.length > 0)
|
||||
} else {
|
||||
const raw = text.replace(/\r\n/g, '\n')
|
||||
pieces =
|
||||
raw.length === 0
|
||||
? []
|
||||
: raw.endsWith('\n')
|
||||
? raw.slice(0, -1).split('\n')
|
||||
: raw.split('\n')
|
||||
}
|
||||
} else if (nullSep) {
|
||||
pieces = text.split('\0').filter((s) => s.length > 0)
|
||||
} else {
|
||||
pieces = text.trim() === '' ? [] : text.trim().split(/\s+/).filter(Boolean)
|
||||
@@ -197,7 +234,8 @@ async function run(ctx, argv) {
|
||||
|
||||
/** @type {string[][]} */
|
||||
const batches = []
|
||||
for (let o = 0; o < pieces.length; o += maxBatch) {
|
||||
const step = linesPerInv != null ? linesPerInv : maxBatch
|
||||
for (let o = 0; o < pieces.length; o += step) {
|
||||
if (batches.length >= MAX_INVOCATIONS) {
|
||||
ctx.console.error(
|
||||
'xargs: exceeded ' + MAX_INVOCATIONS + ' invocations (Bare OS limit)'
|
||||
@@ -205,7 +243,7 @@ async function run(ctx, argv) {
|
||||
ctx.exitCode = 125
|
||||
return
|
||||
}
|
||||
batches.push(pieces.slice(o, o + maxBatch))
|
||||
batches.push(pieces.slice(o, o + step))
|
||||
}
|
||||
|
||||
if (pCap <= 1) {
|
||||
|
||||
@@ -13,12 +13,17 @@ const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {string[]} [libExtras] — e.g. `['awk-engine.js']` before `awk.js` (matches `build.mjs` preamble).
|
||||
*/
|
||||
async function loadBin(name) {
|
||||
async function loadBin(name, libExtras = []) {
|
||||
const runtime = await readFile(
|
||||
path.join(__dirname, '../lib/runtime.js'),
|
||||
'utf8'
|
||||
)
|
||||
let pre = ''
|
||||
for (const f of libExtras) {
|
||||
pre += await readFile(path.join(__dirname, '../lib', f), 'utf8') + '\n'
|
||||
}
|
||||
const body = await readFile(
|
||||
path.join(__dirname, `../src/${name}.js`),
|
||||
'utf8'
|
||||
@@ -26,7 +31,7 @@ async function loadBin(name) {
|
||||
return new AsyncFunction(
|
||||
'ctx',
|
||||
'argv',
|
||||
`${runtime}\n${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
|
||||
`${runtime}\n${pre}${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -175,3 +180,44 @@ test('xargs invokes runBinCommand per token', async (t) => {
|
||||
t.is(inv[0][1], 'a')
|
||||
t.is(inv[1][1], 'b')
|
||||
})
|
||||
|
||||
test('awk FIELDWIDTHS splits when BARE_OS_AWK_FIELDWIDTHS', async (t) => {
|
||||
const run = await loadBin('awk', ['awk-engine.js'])
|
||||
/** @type {string[]} */
|
||||
const logs = []
|
||||
const ctx = {
|
||||
exitCode: 0,
|
||||
shellStdin: 'abcde12\n',
|
||||
b4a,
|
||||
console: {
|
||||
log: (/** @type {string} */ s) => logs.push(s),
|
||||
error: () => {}
|
||||
},
|
||||
vfs: {
|
||||
env: { BARE_OS_AWK_FIELDWIDTHS: '1' },
|
||||
readFile: async () => null
|
||||
}
|
||||
}
|
||||
await run(ctx, ['awk', '-v', 'FIELDWIDTHS=5 2', '{ print $2 }'])
|
||||
t.is(ctx.exitCode, 0)
|
||||
t.is(logs.join('\n'), '12')
|
||||
})
|
||||
|
||||
test('xargs -L batches by input lines', async (t) => {
|
||||
const run = await loadBin('xargs')
|
||||
const inv = []
|
||||
const ctx = {
|
||||
exitCode: 0,
|
||||
shellStdin: 'one\ntwo\nthree\n',
|
||||
console: { log: () => {}, error: () => {} },
|
||||
async runBinCommand(argv) {
|
||||
inv.push([...argv])
|
||||
ctx.exitCode = 0
|
||||
}
|
||||
}
|
||||
await run(ctx, ['xargs', '-L', '2', 'echo'])
|
||||
t.is(ctx.exitCode, 0)
|
||||
t.is(inv.length, 2)
|
||||
t.is(inv[0].slice(1).join(' '), 'one two')
|
||||
t.is(inv[1].slice(1).join(' '), 'three')
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/** Semver for the documented POSIX-like surface (handbook ch.9 + environment appendix). */
|
||||
export const BARE_OS_POSIX_PROFILE_VERSION = '1.0.4'
|
||||
export const BARE_OS_POSIX_PROFILE_VERSION = '1.0.5'
|
||||
|
||||
/** Short identifier for telemetry and `/proc` mirrors. */
|
||||
export const BARE_OS_POSIX_PROFILE_ID = 'bare-os-posix-like'
|
||||
|
||||
@@ -92,6 +92,7 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
* Supports: BEGIN/END, /re/, line patterns, {}, print/printf, if/else, while, for(;;), for(x in a),
|
||||
* next, exit, break, continue, ++/--, arrays, strings, regex ~ !~, builtins (length, substr, index,
|
||||
* split, sprintf, sub, gsub, match, int, tolower, toupper, rand, srand), getline from stdin/files,
|
||||
* optional fixed-width fields via FIELDWIDTHS when BARE_OS_AWK_FIELDWIDTHS is enabled,
|
||||
* -F FS, NF, NR, FNR, $0..$n, OFS, ORS, RS, ARGC, ARGV, FILENAME, ENVIRON (read-only mirror).
|
||||
* GNU-style empty fields: consecutive FS delimiters still advance $1..$NF where the grammar allows.
|
||||
*/
|
||||
@@ -219,7 +220,7 @@ function bareAwkLex(src, st) {
|
||||
return { kind: 'OP', value: '==', line }
|
||||
}
|
||||
|
||||
if ('+-*/%(){}[],;?:<>=!~^'.includes(c)) {
|
||||
if ('+-*/%(){}[],;?:<>=!~^$'.includes(c)) {
|
||||
st.i++
|
||||
return { kind: 'OP', value: c, line }
|
||||
}
|
||||
@@ -807,6 +808,33 @@ class BareAwkRuntime {
|
||||
}
|
||||
|
||||
splitFields() {
|
||||
const cap = this.environ.BARE_OS_AWK_FIELDWIDTHS
|
||||
if (cap === '1' || cap === 'true') {
|
||||
const fw = String(
|
||||
this.vars.FIELDWIDTHS != null ? this.vars.FIELDWIDTHS : ''
|
||||
).trim()
|
||||
if (fw) {
|
||||
const nums = fw
|
||||
.split(/\s+/)
|
||||
.map((x) => Number.parseInt(x, 10))
|
||||
.filter((n) => Number.isFinite(n) && n > 0)
|
||||
if (nums.length) {
|
||||
/** @type {string[]} */
|
||||
const parts = []
|
||||
let pos = 0
|
||||
const line = this.$0
|
||||
for (const w of nums) {
|
||||
parts.push(line.slice(pos, pos + w))
|
||||
pos += w
|
||||
}
|
||||
if (pos < line.length) parts.push(line.slice(pos))
|
||||
this.fields = parts
|
||||
this.NF = parts.length
|
||||
this.vars.NF = this.NF
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
const fs = this.FS
|
||||
let parts
|
||||
if (fs === ' ') {
|
||||
|
||||
@@ -143,7 +143,7 @@ const CONF = {
|
||||
_PC_2_SYMLINKS: '1',
|
||||
/** Comma-separated `ctx.bareOsSyscall` op names implemented in stock booter. */
|
||||
BARE_OS_SYSCALL_OPS:
|
||||
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,kill,link,listen,lstat,mkdir,mount,pathconf,posixPoll,readFile,readdir,readlink,recv,rename,rmdir,select,send,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile',
|
||||
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,pathconf,posixPoll,readFile,readdir,readlink,readv,recv,rename,rmdir,select,send,setsockopt,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile,writev',
|
||||
/** POSIX.1 XSH-style names documented in `/proc/bare_os/syscalls.json` opsDetail (socket family are syscall probes returning ENOSYS-shaped results). */
|
||||
BARE_OS_POSIX_XSH_OPS:
|
||||
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,shutdown',
|
||||
|
||||
@@ -91,7 +91,7 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host spawn).
|
||||
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
||||
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
||||
* Supports -0/--null, -n, -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race).
|
||||
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
||||
*/
|
||||
@@ -128,6 +128,8 @@ async function run(ctx, argv) {
|
||||
/** @type {string | null} */
|
||||
let repl = null
|
||||
let nExplicit = false
|
||||
/** @type {number | null} */
|
||||
let linesPerInv = null
|
||||
const envPCap = maxParallelFromEnv(ctx)
|
||||
let pCap = 1
|
||||
let i = 0
|
||||
@@ -200,6 +202,23 @@ async function run(ctx, argv) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if (a === '-L' || a === '--max-lines') {
|
||||
const n = args[i + 1]
|
||||
if (n == null || !/^\d+$/.test(n) || Number(n) < 1) {
|
||||
ctx.console.error('xargs: -L requires a positive integer')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
linesPerInv = Math.min(Number(n), MAX_PER_INVOCATION)
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
if (a.startsWith('-L') && a.length > 2 && /^\d+$/.test(a.slice(2))) {
|
||||
const n = Number(a.slice(2))
|
||||
linesPerInv = Math.min(n, MAX_PER_INVOCATION)
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if (a === '-I' || a === '-i') {
|
||||
repl = args[i + 1] != null ? String(args[i + 1]) : '{}'
|
||||
i += 2
|
||||
@@ -220,7 +239,7 @@ async function run(ctx, argv) {
|
||||
ctx.console.error(
|
||||
'xargs: Bare OS supports: -0/--null, -n N (max ' +
|
||||
MAX_PER_INVOCATION +
|
||||
' per run), -I repl, -P N (parallel batches, cap ' +
|
||||
' per run), -L N (lines per invocation), -I repl, -P N (parallel batches, cap ' +
|
||||
envPCap +
|
||||
')'
|
||||
)
|
||||
@@ -228,6 +247,12 @@ async function run(ctx, argv) {
|
||||
return
|
||||
}
|
||||
|
||||
if (linesPerInv != null && nExplicit) {
|
||||
ctx.console.error('xargs: -L cannot be combined with -n')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
/** @type {string[]} */
|
||||
let cmd = args.slice(i)
|
||||
if (cmd.length === 0) cmd = ['echo']
|
||||
@@ -243,7 +268,19 @@ async function run(ctx, argv) {
|
||||
|
||||
/** @type {string[]} */
|
||||
let pieces
|
||||
if (nullSep) {
|
||||
if (linesPerInv != null) {
|
||||
if (nullSep) {
|
||||
pieces = text.split('\0').filter((s) => s.length > 0)
|
||||
} else {
|
||||
const raw = text.replace(/\r\n/g, '\n')
|
||||
pieces =
|
||||
raw.length === 0
|
||||
? []
|
||||
: raw.endsWith('\n')
|
||||
? raw.slice(0, -1).split('\n')
|
||||
: raw.split('\n')
|
||||
}
|
||||
} else if (nullSep) {
|
||||
pieces = text.split('\0').filter((s) => s.length > 0)
|
||||
} else {
|
||||
pieces = text.trim() === '' ? [] : text.trim().split(/\s+/).filter(Boolean)
|
||||
@@ -286,7 +323,8 @@ async function run(ctx, argv) {
|
||||
|
||||
/** @type {string[][]} */
|
||||
const batches = []
|
||||
for (let o = 0; o < pieces.length; o += maxBatch) {
|
||||
const step = linesPerInv != null ? linesPerInv : maxBatch
|
||||
for (let o = 0; o < pieces.length; o += step) {
|
||||
if (batches.length >= MAX_INVOCATIONS) {
|
||||
ctx.console.error(
|
||||
'xargs: exceeded ' + MAX_INVOCATIONS + ' invocations (Bare OS limit)'
|
||||
@@ -294,7 +332,7 @@ async function run(ctx, argv) {
|
||||
ctx.exitCode = 125
|
||||
return
|
||||
}
|
||||
batches.push(pieces.slice(o, o + maxBatch))
|
||||
batches.push(pieces.slice(o, o + step))
|
||||
}
|
||||
|
||||
if (pCap <= 1) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"schemaVersion": 5,
|
||||
"ctxApiVersion": "1.38.0",
|
||||
"ctxApiVersion": "1.40.0",
|
||||
"posixProfile": {
|
||||
"id": "bare-os-posix-like",
|
||||
"version": "1.0.4"
|
||||
"version": "1.0.5"
|
||||
},
|
||||
"ops": ["readFile", "writeFile", "socket"],
|
||||
"opsDetail": [
|
||||
@@ -29,7 +29,7 @@
|
||||
"posixXsh": {
|
||||
"schema": 1,
|
||||
"note": "POSIX.1 XSH-style names; socket family are ctx.bareOsSyscall ops returning ENOSYS-shaped results.",
|
||||
"namesCsv": "open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,shutdown"
|
||||
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,shutdown"
|
||||
},
|
||||
"errnoHints": {
|
||||
"ENOENT": 2,
|
||||
@@ -42,7 +42,7 @@
|
||||
"stdio": [0, 1, 2],
|
||||
"register": "ctx.bareOsRegisterLogicalFd",
|
||||
"processTablePath": "/proc/bare_os/process_table.json",
|
||||
"processTableSchema": 5
|
||||
"processTableSchema": 6
|
||||
},
|
||||
"signalModel": {
|
||||
"schema": 1,
|
||||
|
||||
@@ -64,6 +64,7 @@ async function invokeCtxBootHooks(ctx, ev) {
|
||||
* BARE_OS_SELFTEST_FORMAT=tap: TAP-style lines on stderr for CI parsers; **junit**: single XML `<testsuite>` line on stderr.
|
||||
* BARE_OS_KERNEL_STARTUP_CLASS: `critical` | `system` | `interactive` | `deferred` (default **interactive**); exposed as **`ctx.bareOsKernelStartupClass`** for extensions/initd.
|
||||
* BARE_OS_BOOT_BUDGET_MS_COLD: optional cold-boot wall-time warning threshold (ms) after **`bareOsPublishBootReady`**.
|
||||
* BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB: optional wall-time budget (ms) for booter **`ctx.bare`** drive merge + host resolve (**`BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS`**, set by the stock booter); guest logs and **`boot-perf.json`** when exceeded.
|
||||
* BARE_OS_BOOT_CAPABILITY_CONTRACT_DEBUG=1: log capability-contract merge diagnostics (strict builds).
|
||||
* BARE_OS_BOOT_EXT_RESOLUTION_TRACE=1 with **BARE_OS_BOOT_POLICY_STRICT**: write **`/run/bare-os/kernel-ext-resolution.json`** (extension load order / cycle ids).
|
||||
* BARE_OS_BOOT_RC_RESOLUTION_TRACE=1 with **BARE_OS_BOOT_POLICY_STRICT**: write **`/run/bare-os/rc-d-resolution.json`** and **`/run/bare-os/kernel-d-resolution.json`** (lexicographic execution order after filters).
|
||||
@@ -3040,13 +3041,29 @@ async function maybeWriteBootPerfJson(ctx, bootT0, stageLog) {
|
||||
10
|
||||
)
|
||||
const budget = Number.isFinite(budgetRaw) && budgetRaw > 0 ? budgetRaw : null
|
||||
const stdlibWallRaw = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS || ''),
|
||||
10
|
||||
)
|
||||
const stdlibWall =
|
||||
Number.isFinite(stdlibWallRaw) && stdlibWallRaw >= 0 ? stdlibWallRaw : null
|
||||
const stdlibBudgetRaw = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB || ''),
|
||||
10
|
||||
)
|
||||
const stdlibBudget =
|
||||
Number.isFinite(stdlibBudgetRaw) && stdlibBudgetRaw > 0
|
||||
? stdlibBudgetRaw
|
||||
: null
|
||||
const stages =
|
||||
Array.isArray(ctx.bareOsBootStageTimings) && ctx.bareOsBootStageTimings.length
|
||||
? ctx.bareOsBootStageTimings
|
||||
: undefined
|
||||
let schema = stages ? 2 : 1
|
||||
if (stdlibWall != null || stdlibBudget != null) schema = Math.max(schema, 3)
|
||||
const row =
|
||||
JSON.stringify({
|
||||
schema: stages ? 2 : 1,
|
||||
schema,
|
||||
coldWallMs: wall,
|
||||
bootBudgetMsCold: budget,
|
||||
withinBudget: budget == null ? null : wall <= budget,
|
||||
@@ -3054,6 +3071,18 @@ async function maybeWriteBootPerfJson(ctx, bootT0, stageLog) {
|
||||
budget != null && wall > budget
|
||||
? `cold boot ${wall}ms exceeded BARE_OS_BOOT_BUDGET_MS_COLD ${budget}ms`
|
||||
: null,
|
||||
bareStdlibResolutionWallMs: stdlibWall,
|
||||
bareStdlibBudgetMs: stdlibBudget,
|
||||
bareStdlibWithinBudget:
|
||||
stdlibBudget == null || stdlibWall == null
|
||||
? null
|
||||
: stdlibWall <= stdlibBudget,
|
||||
bareStdlibBudgetWarning:
|
||||
stdlibBudget != null &&
|
||||
stdlibWall != null &&
|
||||
stdlibWall > stdlibBudget
|
||||
? `bare stdlib resolution ${stdlibWall}ms exceeded BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB ${stdlibBudget}ms`
|
||||
: null,
|
||||
stageCount: stageLog.length,
|
||||
stages,
|
||||
completedAtMs: Date.now()
|
||||
@@ -3390,6 +3419,31 @@ async function start(ctx) {
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const sb = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB || ''),
|
||||
10
|
||||
)
|
||||
if (Number.isFinite(sb) && sb > 0) {
|
||||
const sw = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS || ''),
|
||||
10
|
||||
)
|
||||
if (Number.isFinite(sw) && sw > sb) {
|
||||
bootStructuredLog(
|
||||
ctx,
|
||||
'error',
|
||||
'bootBudgetBareStdlibExceeded',
|
||||
`[boot] bare stdlib resolution ${sw}ms exceeds BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB=${sb}ms`
|
||||
)
|
||||
if (ctx.env) {
|
||||
ctx.env.BARE_OS_BOOT_BUDGET_STDLIB_EXCEEDED = '1'
|
||||
ctx.env.BARE_OS_BOOT_BUDGET_STDLIB_WALL_MS = String(sw)
|
||||
ctx.env.BARE_OS_BOOT_BUDGET_STDLIB_LIMIT_MS = String(sb)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
const line = await readLine('')
|
||||
if (line == null) break
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,9 +2,9 @@
|
||||
"version": 1,
|
||||
"bundles": [
|
||||
{
|
||||
"path": "/lib/bare/bundles/hypercoreIdEncoding.js",
|
||||
"path": "/lib/bare/bundles/safetyCatch.js",
|
||||
"keys": [
|
||||
"hypercoreIdEncoding"
|
||||
"safetyCatch"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -14,9 +14,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/safetyCatch.js",
|
||||
"path": "/lib/bare/bundles/hypercoreIdEncoding.js",
|
||||
"keys": [
|
||||
"safetyCatch"
|
||||
"hypercoreIdEncoding"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -25,12 +25,6 @@
|
||||
"compactEncoding"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/protomux.js",
|
||||
"keys": [
|
||||
"protomux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareUrl.js",
|
||||
"keys": [
|
||||
@@ -38,9 +32,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareEncoding.js",
|
||||
"path": "/lib/bare/bundles/protomux.js",
|
||||
"keys": [
|
||||
"bareEncoding"
|
||||
"protomux"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -55,12 +49,30 @@
|
||||
"barePath"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareEncoding.js",
|
||||
"keys": [
|
||||
"bareEncoding"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareAbort.js",
|
||||
"keys": [
|
||||
"bareAbort"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareReadline.js",
|
||||
"keys": [
|
||||
"bareReadline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareCrypto.js",
|
||||
"keys": [
|
||||
"bareCrypto"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareAbortController.js",
|
||||
"keys": [
|
||||
@@ -73,36 +85,18 @@
|
||||
"bareAnsiEscapes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareReadline.js",
|
||||
"keys": [
|
||||
"bareReadline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareAddonResolve.js",
|
||||
"keys": [
|
||||
"bareAddonResolve"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareCrypto.js",
|
||||
"keys": [
|
||||
"bareCrypto"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareAsyncHooks.js",
|
||||
"keys": [
|
||||
"bareAsyncHooks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareAssert.js",
|
||||
"keys": [
|
||||
"bareAssert"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareAppKit.js",
|
||||
"keys": [
|
||||
@@ -116,15 +110,15 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareApk.js",
|
||||
"path": "/lib/bare/bundles/bareAssert.js",
|
||||
"keys": [
|
||||
"bareApk"
|
||||
"bareAssert"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBmp.js",
|
||||
"path": "/lib/bare/bundles/bareApk.js",
|
||||
"keys": [
|
||||
"bareBmp"
|
||||
"bareApk"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -134,9 +128,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBundle.js",
|
||||
"path": "/lib/bare/bundles/bareBmp.js",
|
||||
"keys": [
|
||||
"bareBundle"
|
||||
"bareBmp"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -145,6 +139,12 @@
|
||||
"bareBundleCompile"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBundle.js",
|
||||
"keys": [
|
||||
"bareBundle"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBuffer.js",
|
||||
"keys": [
|
||||
@@ -163,48 +163,48 @@
|
||||
"bareBundleEvaluate"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBoot.js",
|
||||
"keys": [
|
||||
"bareBoot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareConsole.js",
|
||||
"keys": [
|
||||
"bareConsole"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBoot.js",
|
||||
"keys": [
|
||||
"bareBoot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareBundleId.js",
|
||||
"keys": [
|
||||
"bareBundleId"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDebugLog.js",
|
||||
"keys": [
|
||||
"bareDebugLog"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDaemon.js",
|
||||
"keys": [
|
||||
"bareDaemon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareChannel.js",
|
||||
"keys": [
|
||||
"bareChannel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDebugLog.js",
|
||||
"keys": [
|
||||
"bareDebugLog"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDelta.js",
|
||||
"keys": [
|
||||
"bareDelta"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDaemon.js",
|
||||
"keys": [
|
||||
"bareDaemon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDiagnosticsChannel.js",
|
||||
"keys": [
|
||||
@@ -223,12 +223,6 @@
|
||||
"bareEnv"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareExif.js",
|
||||
"keys": [
|
||||
"bareExif"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareCov.js",
|
||||
"keys": [
|
||||
@@ -236,9 +230,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFfmpeg.js",
|
||||
"path": "/lib/bare/bundles/bareExif.js",
|
||||
"keys": [
|
||||
"bareFfmpeg"
|
||||
"bareExif"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -247,30 +241,30 @@
|
||||
"bareDgram"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFfmpeg.js",
|
||||
"keys": [
|
||||
"bareFfmpeg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
|
||||
"keys": [
|
||||
"bareFfmpegEncodings"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFormat.js",
|
||||
"keys": [
|
||||
"bareFormat"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareGif.js",
|
||||
"keys": [
|
||||
"bareGif"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFileLogger.js",
|
||||
"keys": [
|
||||
"bareFileLogger"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFormat.js",
|
||||
"keys": [
|
||||
"bareFormat"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFormData.js",
|
||||
"keys": [
|
||||
@@ -278,9 +272,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareHrtime.js",
|
||||
"path": "/lib/bare/bundles/bareGif.js",
|
||||
"keys": [
|
||||
"bareHrtime"
|
||||
"bareGif"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -290,9 +284,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFs.js",
|
||||
"path": "/lib/bare/bundles/bareHrtime.js",
|
||||
"keys": [
|
||||
"bareFs"
|
||||
"bareHrtime"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -307,6 +301,18 @@
|
||||
"bareHttpParser"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareFs.js",
|
||||
"keys": [
|
||||
"bareFs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareIco.js",
|
||||
"keys": [
|
||||
"bareIco"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareImageResample.js",
|
||||
"keys": [
|
||||
@@ -319,24 +325,12 @@
|
||||
"bareInspect"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareIco.js",
|
||||
"keys": [
|
||||
"bareIco"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareHttp1.js",
|
||||
"keys": [
|
||||
"bareHttp1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareJpeg.js",
|
||||
"keys": [
|
||||
"bareJpeg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareHttps.js",
|
||||
"keys": [
|
||||
@@ -344,9 +338,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareIpc.js",
|
||||
"path": "/lib/bare/bundles/bareJpeg.js",
|
||||
"keys": [
|
||||
"bareIpc"
|
||||
"bareJpeg"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -356,15 +350,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareInspector.js",
|
||||
"path": "/lib/bare/bundles/bareIpc.js",
|
||||
"keys": [
|
||||
"bareInspector"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareLogger.js",
|
||||
"keys": [
|
||||
"bareLogger"
|
||||
"bareIpc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -374,9 +362,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareMake.js",
|
||||
"path": "/lib/bare/bundles/bareInspector.js",
|
||||
"keys": [
|
||||
"bareMake"
|
||||
"bareInspector"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -385,24 +373,36 @@
|
||||
"bareLink"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareLogger.js",
|
||||
"keys": [
|
||||
"bareLogger"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareMake.js",
|
||||
"keys": [
|
||||
"bareMake"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareModuleLexer.js",
|
||||
"keys": [
|
||||
"bareModuleLexer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareModuleResolve.js",
|
||||
"keys": [
|
||||
"bareModuleResolve"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareModule.js",
|
||||
"keys": [
|
||||
"bareModule"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareModuleResolve.js",
|
||||
"keys": [
|
||||
"bareModuleResolve"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareModuleTraverse.js",
|
||||
"keys": [
|
||||
@@ -421,36 +421,36 @@
|
||||
"bareNative"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareMedia.js",
|
||||
"keys": [
|
||||
"bareMedia"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareNodeFetch.js",
|
||||
"keys": [
|
||||
"bareNodeFetch"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareOpen.js",
|
||||
"keys": [
|
||||
"bareOpen"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareNet.js",
|
||||
"keys": [
|
||||
"bareNet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareOpen.js",
|
||||
"keys": [
|
||||
"bareOpen"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareOs.js",
|
||||
"keys": [
|
||||
"bareOs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareMedia.js",
|
||||
"keys": [
|
||||
"bareMedia"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePerformance.js",
|
||||
"keys": [
|
||||
@@ -458,9 +458,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePack.js",
|
||||
"path": "/lib/bare/bundles/barePackDrive.js",
|
||||
"keys": [
|
||||
"barePack"
|
||||
"barePackDrive"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -470,9 +470,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePackDrive.js",
|
||||
"path": "/lib/bare/bundles/barePack.js",
|
||||
"keys": [
|
||||
"barePackDrive"
|
||||
"barePack"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -487,48 +487,48 @@
|
||||
"bareNodeRuntime"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDev.js",
|
||||
"keys": [
|
||||
"bareDev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePunycode.js",
|
||||
"keys": [
|
||||
"barePunycode"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePrebuild.js",
|
||||
"keys": [
|
||||
"barePrebuild"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareQuerystring.js",
|
||||
"keys": [
|
||||
"bareQuerystring"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareDev.js",
|
||||
"keys": [
|
||||
"bareDev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePrebuild.js",
|
||||
"keys": [
|
||||
"barePrebuild"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
|
||||
"keys": [
|
||||
"bareQueueMicrotask"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareProcess.js",
|
||||
"keys": [
|
||||
"bareProcess"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareRealm.js",
|
||||
"keys": [
|
||||
"bareRealm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareProcess.js",
|
||||
"keys": [
|
||||
"bareProcess"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/barePromClient.js",
|
||||
"keys": [
|
||||
@@ -541,6 +541,12 @@
|
||||
"bareRuntime"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSemver.js",
|
||||
"keys": [
|
||||
"bareSemver"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSdl.js",
|
||||
"keys": [
|
||||
@@ -553,66 +559,36 @@
|
||||
"bareRpc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSemver.js",
|
||||
"keys": [
|
||||
"bareSemver"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareRepl.js",
|
||||
"keys": [
|
||||
"bareRepl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSignals.js",
|
||||
"keys": [
|
||||
"bareSignals"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareRun.js",
|
||||
"keys": [
|
||||
"bareRun"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSidecar.js",
|
||||
"keys": [
|
||||
"bareSidecar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareRun.js",
|
||||
"keys": [
|
||||
"bareRun"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSignals.js",
|
||||
"keys": [
|
||||
"bareSignals"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareStorage.js",
|
||||
"keys": [
|
||||
"bareStorage"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareStream.js",
|
||||
"keys": [
|
||||
"bareStream"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareStdio.js",
|
||||
"keys": [
|
||||
"bareStdio"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSvg.js",
|
||||
"keys": [
|
||||
"bareSvg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSystemLogger.js",
|
||||
"keys": [
|
||||
"bareSystemLogger"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareStringDecoder.js",
|
||||
"keys": [
|
||||
@@ -620,15 +596,21 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSubprocess.js",
|
||||
"path": "/lib/bare/bundles/bareStdio.js",
|
||||
"keys": [
|
||||
"bareSubprocess"
|
||||
"bareStdio"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTap.js",
|
||||
"path": "/lib/bare/bundles/bareStream.js",
|
||||
"keys": [
|
||||
"bareTap"
|
||||
"bareStream"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSvg.js",
|
||||
"keys": [
|
||||
"bareSvg"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -637,24 +619,48 @@
|
||||
"bareStructuredClone"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTcp.js",
|
||||
"keys": [
|
||||
"bareTcp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTiff.js",
|
||||
"keys": [
|
||||
"bareTiff"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSubprocess.js",
|
||||
"keys": [
|
||||
"bareSubprocess"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareSystemLogger.js",
|
||||
"keys": [
|
||||
"bareSystemLogger"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTap.js",
|
||||
"keys": [
|
||||
"bareTap"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareThread.js",
|
||||
"keys": [
|
||||
"bareThread"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTcp.js",
|
||||
"keys": [
|
||||
"bareTcp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTpl.js",
|
||||
"keys": [
|
||||
"bareTpl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTimers.js",
|
||||
"keys": [
|
||||
@@ -667,24 +673,6 @@
|
||||
"bareType"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTpl.js",
|
||||
"keys": [
|
||||
"bareTpl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTty.js",
|
||||
"keys": [
|
||||
"bareTty"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareTls.js",
|
||||
"keys": [
|
||||
"bareTls"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareUiKit.js",
|
||||
"keys": [
|
||||
@@ -698,15 +686,21 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareV8.js",
|
||||
"path": "/lib/bare/bundles/bareTls.js",
|
||||
"keys": [
|
||||
"bareV8"
|
||||
"bareTls"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareVm.js",
|
||||
"path": "/lib/bare/bundles/bareTty.js",
|
||||
"keys": [
|
||||
"bareVm"
|
||||
"bareTty"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareV8.js",
|
||||
"keys": [
|
||||
"bareV8"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -722,15 +716,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareWebKit.js",
|
||||
"path": "/lib/bare/bundles/bareVm.js",
|
||||
"keys": [
|
||||
"bareWebKit"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareWebp.js",
|
||||
"keys": [
|
||||
"bareWebp"
|
||||
"bareVm"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -740,9 +728,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareWebKitGtk.js",
|
||||
"path": "/lib/bare/bundles/bareWebKit.js",
|
||||
"keys": [
|
||||
"bareWebKitGtk"
|
||||
"bareWebKit"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -751,6 +739,18 @@
|
||||
"bareWhich"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareWebp.js",
|
||||
"keys": [
|
||||
"bareWebp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareWebKitGtk.js",
|
||||
"keys": [
|
||||
"bareWebKitGtk"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
|
||||
"keys": [
|
||||
@@ -769,6 +769,12 @@
|
||||
"bareXdiff"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareZlib.js",
|
||||
"keys": [
|
||||
"bareZlib"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareWs.js",
|
||||
"keys": [
|
||||
@@ -781,12 +787,6 @@
|
||||
"bareWorker"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareZlib.js",
|
||||
"keys": [
|
||||
"bareZlib"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/lib/bare/bundles/bareZmq.js",
|
||||
"keys": [
|
||||
@@ -1595,8 +1595,8 @@
|
||||
],
|
||||
"bundleProvenance": {
|
||||
"schemaVersion": 1,
|
||||
"generatedAt": "2026-04-05T03:36:27.100Z",
|
||||
"gitCommit": "13a06ea3e93e38088f3f893f2c4ba0c9e595808f",
|
||||
"generatedAt": "2026-04-05T04:01:55.827Z",
|
||||
"gitCommit": "16ac71815f00d2c56ac82a964633010e78bd0cdc",
|
||||
"nodeVersion": "v22.22.0",
|
||||
"bundleTier": "all",
|
||||
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1775360186009,
|
||||
"atMs": 1775361714981,
|
||||
"commands": [
|
||||
"arch",
|
||||
"awk",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
* BARE_OS_SELFTEST_FORMAT=tap: TAP-style lines on stderr for CI parsers; **junit**: single XML `<testsuite>` line on stderr.
|
||||
* BARE_OS_KERNEL_STARTUP_CLASS: `critical` | `system` | `interactive` | `deferred` (default **interactive**); exposed as **`ctx.bareOsKernelStartupClass`** for extensions/initd.
|
||||
* BARE_OS_BOOT_BUDGET_MS_COLD: optional cold-boot wall-time warning threshold (ms) after **`bareOsPublishBootReady`**.
|
||||
* BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB: optional wall-time budget (ms) for booter **`ctx.bare`** drive merge + host resolve (**`BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS`**, set by the stock booter); guest logs and **`boot-perf.json`** when exceeded.
|
||||
* BARE_OS_BOOT_CAPABILITY_CONTRACT_DEBUG=1: log capability-contract merge diagnostics (strict builds).
|
||||
* BARE_OS_BOOT_EXT_RESOLUTION_TRACE=1 with **BARE_OS_BOOT_POLICY_STRICT**: write **`/run/bare-os/kernel-ext-resolution.json`** (extension load order / cycle ids).
|
||||
* BARE_OS_BOOT_RC_RESOLUTION_TRACE=1 with **BARE_OS_BOOT_POLICY_STRICT**: write **`/run/bare-os/rc-d-resolution.json`** and **`/run/bare-os/kernel-d-resolution.json`** (lexicographic execution order after filters).
|
||||
@@ -3010,13 +3011,29 @@ async function maybeWriteBootPerfJson(ctx, bootT0, stageLog) {
|
||||
10
|
||||
)
|
||||
const budget = Number.isFinite(budgetRaw) && budgetRaw > 0 ? budgetRaw : null
|
||||
const stdlibWallRaw = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS || ''),
|
||||
10
|
||||
)
|
||||
const stdlibWall =
|
||||
Number.isFinite(stdlibWallRaw) && stdlibWallRaw >= 0 ? stdlibWallRaw : null
|
||||
const stdlibBudgetRaw = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB || ''),
|
||||
10
|
||||
)
|
||||
const stdlibBudget =
|
||||
Number.isFinite(stdlibBudgetRaw) && stdlibBudgetRaw > 0
|
||||
? stdlibBudgetRaw
|
||||
: null
|
||||
const stages =
|
||||
Array.isArray(ctx.bareOsBootStageTimings) && ctx.bareOsBootStageTimings.length
|
||||
? ctx.bareOsBootStageTimings
|
||||
: undefined
|
||||
let schema = stages ? 2 : 1
|
||||
if (stdlibWall != null || stdlibBudget != null) schema = Math.max(schema, 3)
|
||||
const row =
|
||||
JSON.stringify({
|
||||
schema: stages ? 2 : 1,
|
||||
schema,
|
||||
coldWallMs: wall,
|
||||
bootBudgetMsCold: budget,
|
||||
withinBudget: budget == null ? null : wall <= budget,
|
||||
@@ -3024,6 +3041,18 @@ async function maybeWriteBootPerfJson(ctx, bootT0, stageLog) {
|
||||
budget != null && wall > budget
|
||||
? `cold boot ${wall}ms exceeded BARE_OS_BOOT_BUDGET_MS_COLD ${budget}ms`
|
||||
: null,
|
||||
bareStdlibResolutionWallMs: stdlibWall,
|
||||
bareStdlibBudgetMs: stdlibBudget,
|
||||
bareStdlibWithinBudget:
|
||||
stdlibBudget == null || stdlibWall == null
|
||||
? null
|
||||
: stdlibWall <= stdlibBudget,
|
||||
bareStdlibBudgetWarning:
|
||||
stdlibBudget != null &&
|
||||
stdlibWall != null &&
|
||||
stdlibWall > stdlibBudget
|
||||
? `bare stdlib resolution ${stdlibWall}ms exceeded BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB ${stdlibBudget}ms`
|
||||
: null,
|
||||
stageCount: stageLog.length,
|
||||
stages,
|
||||
completedAtMs: Date.now()
|
||||
@@ -3360,6 +3389,31 @@ async function start(ctx) {
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const sb = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB || ''),
|
||||
10
|
||||
)
|
||||
if (Number.isFinite(sb) && sb > 0) {
|
||||
const sw = Number.parseInt(
|
||||
String(ctx.env?.BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS || ''),
|
||||
10
|
||||
)
|
||||
if (Number.isFinite(sw) && sw > sb) {
|
||||
bootStructuredLog(
|
||||
ctx,
|
||||
'error',
|
||||
'bootBudgetBareStdlibExceeded',
|
||||
`[boot] bare stdlib resolution ${sw}ms exceeds BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB=${sb}ms`
|
||||
)
|
||||
if (ctx.env) {
|
||||
ctx.env.BARE_OS_BOOT_BUDGET_STDLIB_EXCEEDED = '1'
|
||||
ctx.env.BARE_OS_BOOT_BUDGET_STDLIB_WALL_MS = String(sw)
|
||||
ctx.env.BARE_OS_BOOT_BUDGET_STDLIB_LIMIT_MS = String(sb)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
const line = await readLine('')
|
||||
if (line == null) break
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user