diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9246fdc..186bce4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,3 +143,19 @@ jobs: CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++ AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-ar run: cargo check --workspace --all-features --locked --target aarch64-unknown-linux-gnu + + # Advisory guard that nexum-runtime stays venue-agnostic: crate graph, symbol + # scan, and nexum:host WIT leaf-ness (scripts/check-venue-agnostic.sh). + # `continue-on-error` keeps this a signal, not a gate, until the physical + # host cut lands; the flip to a blocking gate is tracked for M2. + venue-agnostic: + name: venue-agnostic (advisory) + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: ./.github/actions/rust-setup + - uses: taiki-e/install-action@43aecc8d72668fbcfe75c31400bc4f890f1c5853 # v2.83.2 + with: + tool: wasm-tools,ripgrep + - run: ./scripts/check-venue-agnostic.sh diff --git a/justfile b/justfile index a89e8061..964bba79 100644 --- a/justfile +++ b/justfile @@ -71,6 +71,11 @@ build-e2e: build-m2 build-m3 run-e2e: build-e2e build-engine cargo run -p nexum-cli -- --engine-config engine.e2e.toml +# Assert nexum-runtime is venue-agnostic: crate graph, symbol scan, and +# the nexum:host WIT leaf. Advisory in CI until the physical cut lands. +check-venue-agnostic: + ./scripts/check-venue-agnostic.sh + # Check the entire workspace check: cargo check --target wasm32-wasip2 -p example diff --git a/scripts/check-venue-agnostic.sh b/scripts/check-venue-agnostic.sh new file mode 100755 index 00000000..e3feef76 --- /dev/null +++ b/scripts/check-venue-agnostic.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# Venue-agnosticism check for nexum-runtime: the crate graph reaches no +# videre/intent/venue/cow crate, the sources carry no venue symbol, and +# nexum:host resolves as a leaf WIT package. Advisory in CI until the +# physical cut lands; run locally via `just check-venue-agnostic`. + +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." || exit 2 + +pass() { printf '\033[1;32m[l1 PASS]\033[0m %s\n' "$*" >&2; } +fail() { printf '\033[1;31m[l1 FAIL]\033[0m %s\n' "$*" >&2; status=1; } + +command -v rg >/dev/null || { echo "ripgrep (rg) is required" >&2; exit 2; } + +status=0 + +# 1. Crate graph: nothing venue-shaped reachable from nexum-runtime +# (normal + build edges; dev-deps stay local to the crate). +if tree="$(cargo tree -p nexum-runtime -e normal,build --all-features --prefix none --locked)"; then + reached="$(printf '%s\n' "$tree" | + awk '{print $1}' | sort -u | rg -i 'videre|intent|venue|cow' || true)" + if [[ -n $reached ]]; then + fail "crate graph reaches: $(tr '\n' ' ' <<<"$reached")" + else + pass "crate graph clean" + fi +else + fail "cargo tree failed" +fi + +# 2. Symbol scan: no venue vocabulary anywhere in the crate. Word shapes +# skip std::borrow::Cow, ProviderError, and "intentional". +symbols='\b[Vv]idere|\b[Ii]ntent([_A-Z-]|s?\b)|\b[Vv]enue|\bcow|CoW|\bCow[A-Z]' +rg -n --no-heading -e "$symbols" crates/nexum-runtime +case $? in + 0) fail "venue symbols leak into nexum-runtime" ;; + 1) pass "symbol scan empty" ;; + *) fail "symbol scan errored (crates/nexum-runtime missing?)" ;; +esac + +# 3. WIT DAG: nexum:host is a leaf. No cross-package use/import, and the +# package resolves standalone. +rg -n --no-heading -e '^\s*(use|import)\s+[a-z0-9-]+:' wit/nexum-host +case $? in + 0) fail "nexum:host references another WIT package" ;; + 1) pass "nexum:host has no cross-package reference" ;; + *) fail "WIT scan errored (wit/nexum-host missing?)" ;; +esac +if command -v wasm-tools >/dev/null; then + if wasm-tools component wit wit/nexum-host >/dev/null; then + pass "nexum:host resolves standalone" + else + fail "nexum:host does not resolve standalone" + fi +else + printf '\033[1;33m[l1 WARN]\033[0m wasm-tools not found; WIT resolve skipped\n' >&2 +fi + +exit "$status"