Merge nucleic/olive-ember-seal-q7vk into dev

This commit is contained in:
2026-07-18 15:14:54 -07:00
commit d919c693dd
34 changed files with 624 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
#!/usr/bin/env bash
# narOS rootfs builder (NAROS.md §2.2): mmdebstrap against the pinned Debian snapshot,
# plus (optionally) the local Nucleic package pool. Produces a rootfs tar that CI turns
# into an OCI image (naros-base/…) or the VM payload tarball.
#
# build-rootfs.sh <tier> <arch> [--pool DIR] [--out DIR] [--channel edge|stable]
#
# Needs mmdebstrap and either root or an unshare-capable user. The snapshot mirror serves
# stale Release files by design, hence Check-Valid-Until off (standard snapshot practice).
set -euo pipefail
OS_DIR="$(cd "$(dirname "$0")/.." && pwd)"
TIER="${1:?usage: build-rootfs.sh <tier> <arch> [--pool DIR] [--out DIR] [--channel C]}"
ARCH="${2:?missing arch (arm64|amd64)}"
shift 2
POOL="" OUT="$OS_DIR/dist" CHANNEL="${NAROS_CHANNEL:-edge}"
while [ $# -gt 0 ]; do
case "$1" in
--pool) POOL="$(cd "$2" && pwd)"; shift 2 ;;
--out) OUT="$2"; shift 2 ;;
--channel) CHANNEL="$2"; shift 2 ;;
*) echo "unknown arg: $1" >&2; exit 2 ;;
esac
done
VERSION="$(cat "$OS_DIR/VERSION")"
SNAPSHOT="$(cat "$OS_DIR/SNAPSHOT")"
SUITE="trixie"
MIRROR="https://snapshot.debian.org/archive/debian/${SNAPSHOT}/"
PROFILE="$OS_DIR/mkimage/profiles/$TIER.pkgs"
[ -f "$PROFILE" ] || { echo "no profile for tier '$TIER' ($PROFILE)" >&2; exit 2; }
pkg_list() { grep -vE '^\s*(#|$)' "$1" | tr '\n' ',' | sed 's/,$//'; }
INCLUDE="$(pkg_list "$PROFILE")"
SOURCES=("deb [check-valid-until=no] $MIRROR $SUITE main")
if [ -n "$POOL" ]; then
# Flat file:// repo over the pool; trusted because it is CI's own just-built artifact —
# end-user trust comes from the signed hosted repo (repo/publish.sh), not this path.
if [ ! -f "$POOL/Packages" ] || [ -n "$(find "$POOL" -name '*.deb' -newer "$POOL/Packages" 2>/dev/null)" ]; then
(cd "$POOL" && dpkg-scanpackages --multiversion . > Packages)
fi
# Late packages (profiles/<tier>.late-pkgs) install via a finish hook AFTER every
# Debian package is configured — mandatory for nash-default-shell: apt's configure
# order is not deterministic, so a mid-transaction divert would run the remaining
# Debian postinsts under nash (observed: ca-certificates' UTF-8 filenames mangled).
# The divert must be the image's final configure step.
LATE_DEBS=()
LPROFILE="$OS_DIR/mkimage/profiles/$TIER.late-pkgs"
if [ -f "$LPROFILE" ]; then
while IFS= read -r pkg; do
deb="$(ls "$POOL/${pkg}_"*.deb 2>/dev/null | head -1)"
if [ -n "$deb" ]; then
LATE_DEBS+=("$deb")
elif [ "${NAROS_STRICT:-0}" = "1" ]; then
echo "ERROR: late package $pkg absent from pool" >&2; exit 1
else
echo "WARNING: late package $pkg absent from pool — building WITHOUT it" >&2
fi
done < <(grep -vE '^\s*(#|$)' "$LPROFILE")
fi
NPROFILE="$OS_DIR/mkimage/profiles/$TIER.naros-pkgs"
if [ -f "$NPROFILE" ]; then
# Only request packages the pool actually carries: local builds legitimately lack
# some (e.g. naros-keyring without the signing key). Loud per-package warning;
# NAROS_STRICT=1 (CI) turns any gap into a hard failure.
while IFS= read -r pkg; do
if grep -qx "Package: $pkg" "$POOL/Packages"; then
INCLUDE="$INCLUDE,$pkg"
elif [ "${NAROS_STRICT:-0}" = "1" ]; then
echo "ERROR: $pkg requested by $TIER tier but absent from pool" >&2; exit 1
else
echo "WARNING: $pkg absent from pool — building WITHOUT it" >&2
fi
done < <(grep -vE '^\s*(#|$)' "$NPROFILE")
fi
SOURCES+=("deb [trusted=yes] copy://$POOL ./")
fi
mkdir -p "$OUT"
TAR="$OUT/naros-$TIER-$VERSION-$ARCH.tar"
export NAROS_TIER="$TIER" NAROS_VERSION="$VERSION" NAROS_ARCH="$ARCH" \
NAROS_CHANNEL="$CHANNEL" NAROS_SNAPSHOT="$SNAPSHOT" NAROS_SUITE="$SUITE"
HOOKS=()
if [ "${#LATE_DEBS[@]}" -gt 0 ]; then
LATE_ARGS=""
for deb in "${LATE_DEBS[@]}"; do
b="$(basename "$deb")"
HOOKS+=(--customize-hook="copy-in $deb /tmp")
LATE_ARGS="$LATE_ARGS /tmp/$b"
done
HOOKS+=(--customize-hook="chroot \"\$1\" dpkg -i$LATE_ARGS")
HOOKS+=(--customize-hook="rm -f$(printf ' "$1"%s' $LATE_ARGS)")
fi
HOOKS+=(--customize-hook="$OS_DIR/mkimage/hooks/00-identity.sh"' "$1"')
echo "narOS $VERSION/$CHANNEL: tier=$TIER arch=$ARCH snapshot=$SNAPSHOT pool=${POOL:-none}"
mmdebstrap \
--architectures="$ARCH" \
--variant=apt \
--include="$INCLUDE" \
--aptopt='Acquire::Check-Valid-Until "false"' \
"${HOOKS[@]}" \
"$SUITE" "$TAR" "${SOURCES[@]}"
echo "built $TAR"
+48
View File
@@ -0,0 +1,48 @@
#!/bin/sh
# mmdebstrap customize-hook: stamp narOS identity into the rootfs (NAROS.md §2.3).
# $1 = rootfs dir; NAROS_* env exported by build-rootfs.sh. Debian's own
# /usr/lib/os-release stays intact (ID_LIKE tooling keeps working); we replace only the
# /etc/os-release symlink with the narOS file.
set -eu
R="$1"
rm -f "$R/etc/os-release"
cat > "$R/etc/os-release" <<EOF
NAME="narOS"
PRETTY_NAME="narOS $NAROS_VERSION (Nucleic Agent Runtime OS)"
ID=naros
ID_LIKE=debian
VERSION_ID="$NAROS_VERSION"
VERSION="$NAROS_VERSION ($NAROS_CHANNEL)"
VERSION_CODENAME=$NAROS_SUITE
VARIANT="$NAROS_TIER"
VARIANT_ID=$NAROS_TIER
HOME_URL="https://github.com/abkslm/nucleic"
DOCUMENTATION_URL="https://github.com/abkslm/nucleic/blob/main/docs/NAROS.md"
EOF
mkdir -p "$R/etc/naros"
echo "$NAROS_CHANNEL" > "$R/etc/naros/channel"
echo "$NAROS_SNAPSHOT" > "$R/etc/naros/snapshot-date"
echo "container" > "$R/etc/naros/role"
# Capability manifest (NAROS.md §6.3). Base fields here; toolchain entries are appended
# by the tiers that install them (agent-tier hook, N2). Versions of Nucleic packages are
# queryable via dpkg, listed here for one-stop reads.
nash_ver="$(chroot "$R" dpkg-query -W -f '${Version}' nash 2>/dev/null || echo null)"
[ "$nash_ver" = null ] || nash_ver="\"$nash_ver\""
cat > "$R/etc/naros/manifest.json" <<EOF
{
"os": "naros",
"version": "$NAROS_VERSION",
"channel": "$NAROS_CHANNEL",
"tier": "$NAROS_TIER",
"arch": "$NAROS_ARCH",
"debian": { "suite": "$NAROS_SUITE", "snapshot": "$NAROS_SNAPSHOT" },
"nash": $nash_ver,
"toolchains": {},
"caches": {}
}
EOF
echo "narOS identity: $(. "$R/etc/os-release" && echo "$PRETTY_NAME [$VARIANT/$NAROS_ARCH]")"
+3
View File
@@ -0,0 +1,3 @@
# naros-agent tier (NAROS.md §4, milestone N2 — placeholder until the agent tier lands).
# Will carry: build-essential/pkg-config, python3 + pip/venv, the modern CLI kit, and the
# hooks that add Node (NodeSource), rustup, Go, mise, warm caches, agent CLIs, Playwright.
+5
View File
@@ -0,0 +1,5 @@
# Installed via dpkg -i in a finish hook, after every Debian package is configured.
# nash-default-shell MUST be last-stage: its divert flips /bin/sh to nash, and any
# Debian postinst that runs after the flip runs under nash (see build-rootfs.sh).
nash-default-shell
naros-tier-base
+7
View File
@@ -0,0 +1,7 @@
# Nucleic packages for naros-base, resolved from the local pool when --pool is given.
# The divert package + tier meta are in base.late-pkgs (must configure last); this list
# is what installs alongside the Debian set.
nash
naros-init
naros
naros-keyring
+7
View File
@@ -0,0 +1,7 @@
# naros-base Debian package list (NAROS.md §4). Kept deliberately small — the agent
# toolchain lives in the agent tier. apt itself comes from --variant=apt.
ca-certificates
curl
git
openssh-client
iproute2