Skip to content

feat(kernel): division-of-labor society — per-specialist writable field workspaces #282

feat(kernel): division-of-labor society — per-specialist writable field workspaces

feat(kernel): division-of-labor society — per-specialist writable field workspaces #282

Workflow file for this run

# Build and test automation
name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
jobs:
build:
name: Build and Test
runs-on: ubuntu-latest
strategy:
matrix:
arch: [x86_64]
build_type: [debug, release]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
# Install cross-compiler toolchain (Ubuntu 24.04 compatible)
sudo apt-get install -y build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo
sudo apt-get install -y gdb-multiarch qemu-system-x86 grub-pc-bin xorriso nasm
# Use system gcc with -m64 flag for x86_64 target, or install cross-compiler from source
# For now, use the standard gcc with appropriate flags
which gcc && gcc --version
- name: Build kernel (Debug)
if: matrix.build_type == 'debug'
run: |
make clean
make BUILD_TYPE=debug
- name: Build kernel (Release)
if: matrix.build_type == 'release'
run: |
make clean
make BUILD_TYPE=release
- name: Run unit tests
run: |
make test
- name: Check kernel boots
timeout-minutes: 5
run: |
timeout 30s make run || echo "Boot test completed (timeout expected)"
- name: Generate build artifacts
run: |
make dump > build_dump.txt
ls -la build/ > build_files.txt
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: quantumos-build-${{ matrix.arch }}-${{ matrix.build_type }}
path: |
build/
build_dump.txt
build_files.txt
retention-days: 30
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check for unsafe functions
run: |
echo "Scanning for unsafe C functions..."
UNSAFE_FOUND=0
# Check for dangerous functions that should never be used.
# Match actual call sites (word boundary + open paren), not any
# substring — "num_targets" and comment prose like "the caller
# gets nothing" are not gets() calls.
if find . -name "*.c" -o -name "*.h" | xargs grep -lE "\b(gets|sprintf)[[:space:]]*\(" 2>/dev/null | grep -v test; then
echo "ERROR: Found usage of dangerous functions (gets, sprintf without bounds)"
UNSAFE_FOUND=1
fi
# Warn about potentially unsafe functions (strcpy, strcat)
echo ""
echo "Checking for potentially unsafe functions (warnings)..."
find . -name "*.c" -o -name "*.h" | xargs grep -n "strcpy\|strcat" 2>/dev/null || true
# Check for shell execution functions (should be rare in kernel code)
if find . -name "*.c" | xargs grep -lE "\bsystem[[:space:]]*\(" 2>/dev/null | grep -v test; then
echo "ERROR: Found system() calls in non-test code"
UNSAFE_FOUND=1
fi
if [ $UNSAFE_FOUND -eq 1 ]; then
echo "Security scan FAILED"
exit 1
fi
echo "Security scan PASSED"
code-quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install tools
run: |
sudo apt-get update
sudo apt-get install -y clang-format cppcheck
- name: Check code formatting
run: |
echo "Checking code formatting with clang-format..."
FORMAT_ERRORS=0
for file in $(find . -name "*.c" -o -name "*.h" | grep -v build/); do
if ! clang-format --dry-run --Werror "$file" 2>/dev/null; then
echo "Formatting issue in: $file"
FORMAT_ERRORS=$((FORMAT_ERRORS + 1))
fi
done
if [ $FORMAT_ERRORS -gt 0 ]; then
echo "Found $FORMAT_ERRORS files with formatting issues"
echo "Run 'clang-format -i <file>' to fix"
exit 1
fi
echo "Code formatting check PASSED"
- name: Static analysis
run: |
echo "Running cppcheck static analysis..."
# Run cppcheck but filter out noise from system headers and focus on errors
find . -name "*.c" -not -path "./build/*" | xargs cppcheck \
--enable=warning,performance,portability \
--error-exitcode=1 \
--suppress=missingIncludeSystem \
--suppress=unusedFunction \
-I kernel/include \
2>&1
echo "Static analysis PASSED"
- name: Check for TODO/FIXME comments
run: |
echo "Checking for TODO/FIXME/XXX comments..."
grep -rn "TODO\|FIXME\|XXX" --include="*.c" --include="*.h" . || echo "No TODO/FIXME/XXX comments found"
echo "(This is informational only, not a failure)"
documentation:
name: Documentation Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history to compare changes
- name: Check required documentation files exist
run: |
echo "Checking required documentation files..."
MISSING=0
if [ ! -f README.md ]; then
echo "ERROR: README.md is missing"
MISSING=1
fi
if [ ! -f CONTRIBUTING.md ]; then
echo "ERROR: CONTRIBUTING.md is missing"
MISSING=1
fi
if [ ! -f LICENSE ]; then
echo "ERROR: LICENSE is missing"
MISSING=1
fi
if [ $MISSING -eq 1 ]; then
exit 1
fi
echo "Required documentation files exist"
documentation-sync:
name: Documentation Sync Check
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history to compare changes
- name: Check documentation updated with code changes
run: |
echo "Checking if documentation is updated with code changes..."
# Get the base branch (usually main or develop)
BASE_BRANCH="${{ github.base_ref }}"
# Get list of changed files in this PR
CHANGED_FILES=$(git diff --name-only origin/$BASE_BRANCH...HEAD)
echo "Changed files in this PR:"
echo "$CHANGED_FILES"
echo ""
# Check if any C source or header files were changed
CODE_CHANGED=0
if echo "$CHANGED_FILES" | grep -E '\.(c|h)$' | grep -v test; then
CODE_CHANGED=1
echo "Code files (.c/.h) were modified"
fi
# Check if any documentation files were changed
DOCS_CHANGED=0
if echo "$CHANGED_FILES" | grep -E '\.(md|rst|txt)$|^docs/'; then
DOCS_CHANGED=1
echo "Documentation files were modified"
fi
# If code changed but no docs changed, check if it's a significant change
if [ $CODE_CHANGED -eq 1 ] && [ $DOCS_CHANGED -eq 0 ]; then
echo ""
echo "WARNING: Code files were changed but no documentation was updated."
echo ""
# Check for new public functions in headers (these require documentation)
NEW_FUNCS=$(git diff origin/$BASE_BRANCH...HEAD -- '*.h' | grep "^+" | grep -E "^[^/]*\(" | grep -v "static" | grep -v "#define" || true)
if [ -n "$NEW_FUNCS" ]; then
echo "ERROR: New public functions were added without documentation updates:"
echo "$NEW_FUNCS"
echo ""
echo "Please update the relevant documentation (README.md, API docs, etc.)"
echo "to describe these new functions."
exit 1
fi
# Check for changes to public API (function signature changes)
API_CHANGES=$(git diff origin/$BASE_BRANCH...HEAD -- 'kernel/include/*.h' | grep "^[-+]" | grep -E "(status_t|void|int|uint|bool).*\(" || true)
if [ -n "$API_CHANGES" ]; then
echo "WARNING: API changes detected in headers:"
echo "$API_CHANGES"
echo ""
echo "Consider updating documentation to reflect these API changes."
echo "(This is a warning, not blocking the PR)"
fi
fi
echo ""
echo "Documentation sync check completed"
- name: Validate API documentation matches headers
run: |
echo "Validating API documentation consistency..."
# Run the API consistency check script if it exists
if [ -f ./scripts/check-api-consistency.sh ]; then
chmod +x ./scripts/check-api-consistency.sh
./scripts/check-api-consistency.sh
else
echo "API consistency script not found, skipping"
fi
performance:
name: Performance Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 time nasm
- name: Build kernel
run: make clean && make
- name: Performance benchmarks
run: |
echo "=== Performance Benchmarks ===" > performance_report.txt
echo "" >> performance_report.txt
# Measure clean build time
echo "Measuring clean build time..."
make clean
START_TIME=$(date +%s.%N)
make
END_TIME=$(date +%s.%N)
BUILD_TIME=$(echo "$END_TIME - $START_TIME" | bc)
echo "Clean build time: ${BUILD_TIME}s" >> performance_report.txt
# Measure incremental build time (no changes)
echo "Measuring incremental build time..."
START_TIME=$(date +%s.%N)
make
END_TIME=$(date +%s.%N)
INCR_TIME=$(echo "$END_TIME - $START_TIME" | bc)
echo "Incremental build time: ${INCR_TIME}s" >> performance_report.txt
# Measure boot time
echo "Measuring boot time..."
timeout 10s qemu-system-x86_64 -kernel build/x86_64/kernel.elf32 \
-serial stdio -m 128M -display none -no-reboot 2>&1 | head -50 > boot_output.txt || true
echo "" >> performance_report.txt
echo "Boot output captured (first 50 lines)" >> performance_report.txt
# Check kernel binary size
KERNEL_SIZE=$(stat -c%s build/x86_64/kernel.elf 2>/dev/null || echo "unknown")
echo "Kernel size: ${KERNEL_SIZE} bytes" >> performance_report.txt
echo "" >> performance_report.txt
echo "Performance tests completed at $(date)" >> performance_report.txt
cat performance_report.txt
- name: Upload performance data
uses: actions/upload-artifact@v4
with:
name: performance-data
path: |
performance_report.txt
boot_output.txt
retention-days: 7
code-coverage:
name: Code Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm lcov
# gcov (--coverage) cannot instrument the freestanding kernel image:
# the gcov runtime needs libc, the kernel links with -nostdlib, so an
# instrumented build always dies at link on undefined __gcov_* symbols.
# Build normally, exercise the test paths, and let the report below say
# honestly that line coverage is not measurable until an in-kernel gcov
# runtime exists. Functional coverage lives in the smoke/integration jobs.
- name: Build kernel
run: |
make clean
make
- name: Run tests
run: |
# Run the test suite
make test || true
# Boot the kernel briefly to execute initialization code paths
timeout 5s qemu-system-x86_64 -kernel build/x86_64/kernel.elf32 \
-serial stdio -m 128M -display none -no-reboot 2>&1 || true
- name: Generate coverage report
run: |
echo "=== Code Coverage Report ===" > coverage_summary.txt
# Collect coverage data
lcov --capture --directory . --output-file coverage.info 2>/dev/null || true
# Filter out system headers
lcov --remove coverage.info '/usr/*' --output-file coverage.info 2>/dev/null || true
# Generate summary
if [ -f coverage.info ]; then
lcov --list coverage.info >> coverage_summary.txt 2>/dev/null || true
# Extract coverage percentage
COVERAGE=$(lcov --summary coverage.info 2>&1 | grep "lines" | awk '{print $2}' || echo "unknown")
echo "" >> coverage_summary.txt
echo "Total line coverage: $COVERAGE" >> coverage_summary.txt
# Generate HTML report
genhtml coverage.info --output-directory coverage_html 2>/dev/null || true
else
echo "Coverage data not available (kernel code may not support gcov)" >> coverage_summary.txt
echo "Note: Freestanding kernel code requires special handling for coverage" >> coverage_summary.txt
fi
cat coverage_summary.txt
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: code-coverage
path: |
coverage_summary.txt
coverage.info
coverage_html/
retention-days: 30
if-no-files-found: warn
quantum-tests:
name: Quantum Component Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 python3 python3-pip nasm
pip3 install qiskit --break-system-packages || true # Quantum simulator (optional)
- name: Build kernel
run: make clean && make
- name: Test quantum components
run: |
echo "=== Quantum Component Tests ===" > quantum_test_results.txt
QUANTUM_FAILURES=0
# Check quantum headers exist
echo "Checking quantum headers..." >> quantum_test_results.txt
if [ -f kernel/include/quantum_types.h ]; then
echo " [PASS] quantum_types.h found" >> quantum_test_results.txt
else
echo " [FAIL] quantum_types.h missing" >> quantum_test_results.txt
QUANTUM_FAILURES=$((QUANTUM_FAILURES + 1))
fi
# Check for quantum-related source files
echo "" >> quantum_test_results.txt
echo "Checking quantum source files..." >> quantum_test_results.txt
QUANTUM_SOURCES=$(find . -name "*quantum*.c" -o -name "*qubit*.c" | wc -l)
echo " Found $QUANTUM_SOURCES quantum-related source files" >> quantum_test_results.txt
# Verify quantum types are properly defined
echo "" >> quantum_test_results.txt
echo "Checking quantum type definitions..." >> quantum_test_results.txt
if grep -q "typedef.*qubit" kernel/include/quantum_types.h 2>/dev/null; then
echo " [PASS] Qubit type defined" >> quantum_test_results.txt
else
echo " [WARN] Qubit type not found" >> quantum_test_results.txt
fi
if grep -q "typedef.*quantum_state" kernel/include/quantum_types.h 2>/dev/null; then
echo " [PASS] Quantum state type defined" >> quantum_test_results.txt
else
echo " [WARN] Quantum state type not found" >> quantum_test_results.txt
fi
echo "" >> quantum_test_results.txt
if [ $QUANTUM_FAILURES -gt 0 ]; then
echo "Quantum tests: $QUANTUM_FAILURES failures" >> quantum_test_results.txt
cat quantum_test_results.txt
exit 1
fi
echo "Quantum component tests PASSED" >> quantum_test_results.txt
cat quantum_test_results.txt
- name: Upload quantum test results
uses: actions/upload-artifact@v4
with:
name: quantum-test-results
path: quantum_test_results.txt
retention-days: 7
resonant-experiment:
name: Resonant Scheduler Experiment (SCHED_RESONANT, honest measurement)
runs-on: ubuntu-latest
needs: [build]
# The dormant ghostOS resonant scheduler (issue #21) wired behind
# SCHED_RESONANT=1. Default builds never link it; this job keeps the
# experiment reproducible and publishes its honest verdict (it loses to
# round-robin) on every run. Not a required check — a negative result.
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm
- name: Build + boot with the resonant scheduler and print the comparison
run: make ci-smoke-resonant
qseed-handoff:
name: qseed Handoff + errno-collision gate (SYS_QSEED provenance)
runs-on: ubuntu-latest
needs: [build]
# Single-sourced `make ci-smoke-qseed` (mirrors the mcp-gate/society-gate
# convention). Boots with the seed FFFFFFFFFFFFFFFC — deliberately the value
# that collides with the EPERM (-4) errno sentinel — and proves end to end:
# (1) the kernel accepts the qseed handoff and ghostd traces its noise to it,
# (2) paradoxd still resolves under a qseed, and (3) the qsh `qseed` command
# reports the real seed instead of misreading it as a denial (#167). The
# Integration job's inline Test 1d only ever booted DEADBEEF, so none of the
# -4 collision path was enforced in CI before.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm
- name: Boot a qseed handoff and assert provenance + the errno-collision gate
run: make ci-smoke-qseed
quiet-boot:
name: Quiet-Boot Test (clean interactive console)
runs-on: ubuntu-latest
needs: [build]
# Boot with `-append quiet` and prove the interactive console is CLEAN — the
# periodic timer-tick heartbeat and the demo services' steady-state chatter
# are silenced — WHILE the shell still comes up and answers 'help'. The
# default boot (which keeps all that output, and whose gates depend on it)
# is unchanged; quiet is strictly opt-in.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm
- name: Prove a quiet boot yields a clean, usable console
run: make ci-smoke-quiet
real-hw-boot:
name: Real-Hardware Boot Path (GRUB ISO + PS/2 keyboard — epic #101)
runs-on: ubuntu-latest
needs: [build]
# Two gates for the serial-less laptop path: (1) boot the GRUB-built ISO
# with -cdrom — the real bootloader handoff, not QEMU's -kernel shortcut —
# to the shell + a citizen gate, with the VGA screen console active;
# (2) drive qsh entirely through PS/2 scancodes injected via the QEMU
# monitor, proving the i8042/IRQ1 input path a laptop keyboard uses.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm grub-pc-bin xorriso mtools
- name: Boot the GRUB ISO to the shell (console image, VGA text)
run: make ci-smoke-iso
- name: Type into qsh via PS/2 scancodes
run: make ci-smoke-kbd
- name: Boot with no COM1 UART at all (the serial-less laptop shape)
run: make ci-smoke-noserial
- name: Assert ring-3 output is visible on the VGA screen
run: make ci-smoke-screen
- name: Every framebuffer banner character has a glyph
run: python3 scripts/check_fb_font.py
persistence:
name: Persistence Test (two boots, one disk — epic #71)
runs-on: ubuntu-latest
needs: [build]
# The storage capstone: boot the SAME ATA disk image twice; boot 1 writes a
# file to the RAM overlay and syncs it to disk, boot 2 restores it and reads
# the content back. A REQUIRED gate — persistence is a core-OS claim, and the
# two-boot design makes a spurious green impossible (fresh image per run,
# content checked only in boot 2's log which never types it).
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm
- name: Prove persistence across reboots
run: make ci-smoke-disk
quantum-gateway:
name: Quantum Gateway Cross-Oracle (exact engine vs PennyLane — epic #149)
runs-on: ubuntu-latest
# Phase 2 of the quantum stack: the host gateway dispatches the SAME opaque
# circuit wire format the in-OS broker uses to PennyLane lightning.qubit,
# and this gate asserts the two independent engines — the freestanding exact
# integer simulator (qsv_mirror) and Xanadu's C++ float state vector — agree
# to 1e-9 on Bell/GHZ/Grover, with a teeth check that a wrong circuit
# DISAGREES. Hermetic (pinned wheels); no OS boot needed.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pinned PennyLane + Lightning
run: pip install "pennylane==0.45.1" "pennylane-lightning==0.45.0" "numpy>=2.0"
- name: Cross-oracle (exact integer engine vs lightning.qubit)
run: python scripts/test_qsv_oracle.py
quantum-com2:
name: COM2 Quantum-Submit (host → broker → qpud over the wire — epic #149 B1)
runs-on: ubuntu-latest
needs: [build]
# Phase 2 transport: a host agent frames an opaque circuit over the attested
# COM2 bridge, swarm_svc forwards it to the SYS_QPU broker, qpud runs it, and
# the exact result returns over a wire the host never typed. PennyLane is
# installed so the cross-oracle leg (OS wire result vs lightning.qubit) runs.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pinned PennyLane + Lightning (for the cross-oracle leg)
run: pip install "pennylane==0.45.1" "pennylane-lightning==0.45.0" "numpy>=2.0"
- name: Prove host→broker→qpud over COM2
run: make ci-smoke-qsubmit
networking:
name: Networking Test (rtl8139 + user-net ARP — epic #73)
runs-on: ubuntu-latest
needs: [build]
# Boot with an rtl8139 NIC on QEMU's user-mode network and prove the link
# layer end to end: SLIRP's gateway (10.0.2.2) always answers ARP, so an
# ARP request that gets a reply exercises PCI enumeration, the driver, the
# TX path, the RX interrupt, and ARP parsing. A required gate.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
# python3 + curl drive the hermetic TCP test's loopback HTTP server
# (epic #82); installed explicitly rather than relying on the runner
# image's preinstall.
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm python3 curl
- name: ARP-resolve the SLIRP gateway through the rtl8139 driver
run: make ci-smoke-net
- name: Fetch a web page over the ring-3 TCP client (epic #82)
run: make ci-smoke-http
- name: Fetch the live status page FROM QuantumOS (TCP server + httpd, epic #98)
run: make ci-smoke-httpd
- name: Two guests exchange UDP over a raw L2 (static IP + ARP responder, epic #97)
run: make ci-smoke-2net
- name: Two kernels couple their oscillator fields over UDP (epic #97)
run: make ci-smoke-fieldsync
integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential qemu-system-x86 nasm
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: quantumos-build-x86_64-debug
path: build-artifacts/
- name: Prepare build directory
run: |
mkdir -p build/x86_64
cp -r build-artifacts/* build/ 2>/dev/null || cp -r build-artifacts/* build/x86_64/ 2>/dev/null || true
find build/ -name "*.elf" -exec ls -la {} \;
- name: Integration tests
run: |
echo "=== Integration Tests ===" > integration_results.txt
INTEGRATION_FAILURES=0
# Find the kernel ELF
KERNEL_ELF=$(find build/ -name "kernel.elf32" | head -1)
if [ -z "$KERNEL_ELF" ]; then
echo "[FAIL] Kernel ELF not found in artifacts" >> integration_results.txt
cat integration_results.txt
exit 1
fi
echo "Using kernel: $KERNEL_ELF" >> integration_results.txt
# Test 1: Kernel boot sequence
echo "" >> integration_results.txt
echo "Test 1: Kernel boot sequence..." >> integration_results.txt
timeout 15s qemu-system-x86_64 -kernel "$KERNEL_ELF" \
-serial stdio -m 128M -display none -no-reboot 2>&1 | tee boot_output.txt || true
if grep -q "QuantumOS ready" boot_output.txt 2>/dev/null; then
echo " [PASS] Kernel booted to idle loop (QuantumOS ready)" >> integration_results.txt
else
echo " [FAIL] Kernel did not reach 'QuantumOS ready'" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1b: ghostOS phase-1 gate — the ring-3 ghostd service must
# recall all three noisy probes to their stored patterns (issue #48)
echo "" >> integration_results.txt
echo "Test 1b: ghostd associative-memory self-test..." >> integration_results.txt
if grep -q "GHOSTD: 3/3 RECALL OK" boot_output.txt 2>/dev/null; then
echo " [PASS] ghostd recalled 3/3 patterns (GHOSTD: 3/3 RECALL OK)" >> integration_results.txt
else
echo " [FAIL] ghostd self-test gate missing (GHOSTD: 3/3 RECALL OK)" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1c: ghostOS phase-2 honesty gate (issue #49) — this seedless
# boot must name the noise source as a plain PRNG and NEVER claim
# quantum provenance, and the capless SYS_QRAND caller must be denied.
echo "" >> integration_results.txt
echo "Test 1c: ghostd noise-source honesty + QRAND capability gate..." >> integration_results.txt
if grep -q "GHOSTD: noise source = prng (no qseed)" boot_output.txt 2>/dev/null \
&& ! grep -q "GHOSTD: noise source = qseed-derived" boot_output.txt 2>/dev/null; then
echo " [PASS] ghostd reported 'prng (no qseed)' with no false quantum claim" >> integration_results.txt
else
echo " [FAIL] ghostd noise-source honesty gate failed on a seedless boot" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
if grep -q "QRAND: capless caller denied (EPERM)" boot_output.txt 2>/dev/null; then
echo " [PASS] capless SYS_QRAND denied (QRAND: capless caller denied)" >> integration_results.txt
else
echo " [FAIL] capless SYS_QRAND was not denied" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1d: ghostOS phase-2 qseed handoff (issue #49) — boot WITH a
# quantum-entropy seed on the kernel command line; the kernel must
# echo it accepted the handoff AND ghostd must trace its noise to it.
echo "" >> integration_results.txt
echo "Test 1d: qseed handoff -> ghostd quantum noise provenance..." >> integration_results.txt
timeout 15s qemu-system-x86_64 -kernel "$KERNEL_ELF" \
-append "qseed=DEADBEEFCAFEBABE" \
-serial stdio -m 128M -display none -no-reboot 2>&1 | tee boot_output_qseed.txt || true
if grep -q "Boot entropy accepted from cmdline (qseed=)" boot_output_qseed.txt 2>/dev/null \
&& grep -q "GHOSTD: noise source = qseed-derived" boot_output_qseed.txt 2>/dev/null \
&& grep -q "GHOSTD: 3/3 RECALL OK" boot_output_qseed.txt 2>/dev/null; then
echo " [PASS] qseed accepted + ghostd noise = qseed-derived + 3/3 recall" >> integration_results.txt
else
echo " [FAIL] qseed handoff did not reach ghostd as quantum provenance" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1e: ghostOS phase-3 gate (issue #50) — paradoxd must resolve the
# canned contradiction (deterministic RESOLVED line), deny an
# unauthorised targeted send, and demonstrate the ghostd field coupling
# by transitioning its CONVERGENT<->DIVERGENT phase machine gated on R.
echo "" >> integration_results.txt
echo "Test 1e: paradoxd resolution + capability + ghostd coupling..." >> integration_results.txt
if grep -q "PARADOXD: RESOLVED" boot_output.txt 2>/dev/null; then
echo " [PASS] paradoxd resolved the contradiction (PARADOXD: RESOLVED)" >> integration_results.txt
else
echo " [FAIL] paradoxd resolution gate missing (PARADOXD: RESOLVED)" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
if grep -q "PARADOXD: capless send denied (EPERM)" boot_output.txt 2>/dev/null; then
echo " [PASS] unauthorised send denied (PARADOXD: capless send denied)" >> integration_results.txt
else
echo " [FAIL] unauthorised send was not denied" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
if grep -q "PARADOXD: phase ->" boot_output.txt 2>/dev/null; then
echo " [PASS] paradoxd/ghostd field coupling drove a phase transition" >> integration_results.txt
else
echo " [FAIL] no phase transition (paradoxd/ghostd coupling)" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1f: ghostd phase-4 device gate (issue #51) — the capless
# ghost-test must be denied SYS_COM2 (only swarm_svc holds the COM2
# device capability).
echo "" >> integration_results.txt
echo "Test 1f: COM2 device capability gate..." >> integration_results.txt
if grep -q "COM2: capless caller denied (EPERM)" boot_output.txt 2>/dev/null; then
echo " [PASS] capless SYS_COM2 denied (COM2: capless caller denied)" >> integration_results.txt
else
echo " [FAIL] capless SYS_COM2 was not denied" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1g: ghostd phase-4 swarm bridge (issue #51) — boot with COM2
# routed to a file and verify the ring-3 swarm_svc's Lamport-signed boot
# attestation with the host-side verifier, in BOTH modes: seedless
# (qseed=none) and with a qseed handoff (attested qseed == cmdline).
echo "" >> integration_results.txt
echo "Test 1g: swarm bridge Lamport-signed boot attestation..." >> integration_results.txt
timeout 15s qemu-system-x86_64 -kernel "$KERNEL_ELF" \
-serial stdio -serial file:com2_seedless.bin \
-m 128M -display none -no-reboot 2>&1 | tee boot_output_swarm.txt || true
if grep -q "SWARM: boot attestation emitted" boot_output_swarm.txt 2>/dev/null; then
echo " [PASS] swarm console gate present (SWARM: boot attestation emitted)" >> integration_results.txt
else
echo " [FAIL] swarm console gate missing" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
if python3 scripts/verify_attestation.py com2_seedless.bin --qseed none >> integration_results.txt 2>&1; then
echo " [PASS] seedless boot attestation verified (qseed=none)" >> integration_results.txt
else
echo " [FAIL] seedless boot attestation did not verify" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
timeout 15s qemu-system-x86_64 -kernel "$KERNEL_ELF" \
-append "qseed=DEADBEEFCAFEBABE" \
-serial stdio -serial file:com2_qseed.bin \
-m 128M -display none -no-reboot 2>&1 | tee boot_output_swarm_qseed.txt || true
if python3 scripts/verify_attestation.py com2_qseed.bin --qseed DEADBEEFCAFEBABE >> integration_results.txt 2>&1; then
echo " [PASS] qseed boot attestation verified (attested qseed == cmdline)" >> integration_results.txt
else
echo " [FAIL] qseed boot attestation did not verify" >> integration_results.txt
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
fi
# Test 1h: interactive shell session (epic #62 phase 1, issue #63) —
# pipe a scripted command session into the serial console. The ring-3
# qsh service (sole holder of the console capability) must execute it:
# the first command arrives byte-intact across the boot handoff, ps
# shows the shell observing ITSELF running, free/uptime answer with
# live kernel stats, ghost fetches ghostd's field status over
# capability IPC, qrand draws from the shell's declared quantum-pool
# cap, the capless caller is denied SYS_CONS, and after `exit` the
# watchdog restarts the shell (reborn banner).
echo "" >> integration_results.txt
echo "Test 1h: interactive shell session (qsh)..." >> integration_results.txt
( printf 'help\nps\nfree\nuptime\ndate\nghost\nqrand\nls\ncat /docs/hello.txt\nrun /bin/hello\nrun /bin/args alpha quantumos\nrun /bin/libqtest\nrun /bin/consciousnessd\nrun /bin/qtop\nrun /bin/life\nimprint the cat sat on the mat\nimprint pure quantum wave dynamics\nimprint hello little world\nrecall the cxt sxt on thx mxt\nfieldtest\nwrite /data/note ramfs-works\nls /data\nrm /data/note\nsync\naudit\nmanifest\nexit\n'; sleep 20 ) | \
timeout 18s qemu-system-x86_64 -kernel "$KERNEL_ELF" \
-serial stdio -m 128M -display none -no-reboot 2>&1 | tee boot_output_shell.txt || true
SHELL_GATES="QSH: QuantumOS interactive shell ready|qsh commands:|qsh RUNNING|MEM: heap free=|qsh: uptime |qsh: ghost R=|qsh: qrand |Welcome to QuantumOS|FS: etc/motd|The initrd is real|HELLO: greetings from /bin/hello|exited (code 42)|ARGS: argc=3|ARGS: argv[1]=alpha|ARGS: argv[2]=quantumos|qsh: wrote |FS: data/note|qsh: removed|FSW: capless caller denied (EPERM)|qsh: sync failed (no disk)|SPAWN: capless caller denied (EPERM)|CONS: capless caller denied (EPERM)|QSH: reborn|LIBQ: self-test OK|LIBQ printf d=-7 u=42 x=beef s=ok|consciousnessd: CONSCIOUSNESS EMERGED|kannakad: RESONANCE VERIFIED|quantumd: QUANTUM VERIFIED|qtop: DASHBOARD RENDERED|LIFE: glider intact after 16 generations (live=5)|FIELD: imprinted slot 2|FIELD: winner=\"the cat sat on the mat\" slot=0 score=|FIELD: cross-region denied (EPERM)|FIELD: empty-probe ok (n=0)|FIELD: capless imprint denied (EPERM)|FIELD: capless recall denied (EPERM)|manifest self-test: PASS (MDENY recorded)|QUOTA ENFORCED pid=|AUDIT: seq=|MANIFEST: pid=|DELEG ISSUED sub=|DELEG ENFORCED pid=|DELEG REVOKED pid=|CPUKILL: pid=|QSV: grover3 h=15 amp=176 p=121/128 norm=OK|QSV: PROOF COMPLETE|QPU: bell via broker job=|QPU: grover3 via broker job=|QPU: quota ENFORCED (third submit refused)|QPU: capless submit denied (EPERM)"
echo "$SHELL_GATES" | tr '|' '\n' | while IFS= read -r gate; do
if grep -qF "$gate" boot_output_shell.txt 2>/dev/null; then
echo " [PASS] shell gate present: $gate" >> integration_results.txt
else
echo " [FAIL] shell gate missing: $gate" >> integration_results.txt
echo "SHELL_GATE_FAILED" >> shell_gate_failures.txt
fi
done
if [ -f shell_gate_failures.txt ]; then
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + $(wc -l < shell_gate_failures.txt)))
fi
# Negative gate (epic #135): the spawn quota must be ENFORCED, never
# broken. The SHELL_GATES loop above is presence-only and CANNOT express
# absence, so this is a dedicated block — quota-test prints "QUOTA
# BROKEN <detail>" only if the second over-quota spawn was NOT refused.
if grep -qF "QUOTA BROKEN" boot_output_shell.txt 2>/dev/null; then
echo " [FAIL] spawn quota NOT enforced (QUOTA BROKEN present)" >> integration_results.txt
grep -F "QUOTA BROKEN" boot_output_shell.txt >> integration_results.txt || true
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
else
echo " [PASS] spawn quota enforced (no QUOTA BROKEN)" >> integration_results.txt
fi
# Negative gate (epic #137): capability delegation must be enforced. The
# sub-agent prints "DELEG BROKEN <detail>" only if the narrowed cap did
# not behave (recall failed, imprint was allowed, or the cascade-revoke
# was not observed). Presence of the positive DELEG markers is checked
# in SHELL_GATES above; this dedicated block asserts the absence.
if grep -qF "DELEG BROKEN" boot_output_shell.txt 2>/dev/null; then
echo " [FAIL] capability delegation NOT enforced (DELEG BROKEN present)" >> integration_results.txt
grep -F "DELEG BROKEN" boot_output_shell.txt >> integration_results.txt || true
INTEGRATION_FAILURES=$((INTEGRATION_FAILURES + 1))
else
echo " [PASS] capability delegation enforced (no DELEG BROKEN)" >> integration_results.txt
fi
# Test 2: Check for kernel panic or errors
echo "" >> integration_results.txt
echo "Test 2: Checking for kernel panics..." >> integration_results.txt
if grep -qi "panic\|error\|fault" boot_output.txt 2>/dev/null; then
echo " [WARN] Potential error messages in boot output" >> integration_results.txt
grep -i "panic\|error\|fault" boot_output.txt >> integration_results.txt || true
else
echo " [PASS] No panic/error messages detected" >> integration_results.txt
fi
# Test 3: Memory initialization
echo "" >> integration_results.txt
echo "Test 3: Memory initialization..." >> integration_results.txt
if grep -qi "memory\|heap\|page" boot_output.txt 2>/dev/null; then
echo " [PASS] Memory-related output detected" >> integration_results.txt
else
echo " [INFO] No memory initialization output (may be normal)" >> integration_results.txt
fi
echo "" >> integration_results.txt
echo "Integration tests completed" >> integration_results.txt
cat integration_results.txt
if [ $INTEGRATION_FAILURES -gt 0 ]; then
exit 1
fi
# MCP server lifecycle (epics #99, #125): the full agent-facing loop
# (boot -> attested identity -> ghostd status -> imprint/recall ->
# run-with-args -> sysinfo -> qrand -> fs -> fetch -> injection refusal ->
# crypto-tamper refusal -> shutdown) driven through qos_bridge, the same
# code path the FastMCP tools delegate to. Run against the downloaded
# kernel artifact, stdlib-only (no `mcp` package, no pip). Invoked via the
# single-sourced `make ci-smoke-mcp-gate` target so the gate timeout is
# defined in exactly one place (the Makefile), never drifting from a
# duplicated literal here. The gate target has no `kernel` prerequisite, so
# this does not rebuild against the artifact. The test owns and reaps its
# own QEMU (finally + atexit + signal handler + PR_SET_PDEATHSIG).
- name: MCP server lifecycle (epics #99, #125)
run: |
KERNEL_ELF=$(find build/ -name "kernel.elf32" | head -1)
echo "Using kernel: $KERNEL_ELF"
QOS_KERNEL="$KERNEL_ELF" make ci-smoke-mcp-gate
# Agent society (epic #131): two attested QuantumOS VMs coupled into one
# holographic field, driven through QosSociety (the same code path the
# qos_society_* MCP tools use) — the MCP-driven generalization of the
# ci-smoke-fieldsync two-kernel coupling, with attestation-gated reporting.
# Invoked via the single-sourced make target (timeout lives in the Makefile).
- name: Agent society coupling (epic #131)
run: |
KERNEL_ELF=$(find build/ -name "kernel.elf32" | head -1)
echo "Using kernel: $KERNEL_ELF"
QOS_KERNEL="$KERNEL_ELF" make ci-smoke-society-gate
# N-way society (epic #139): three kernels mean-field-couple on a shared
# mcast L2. Separate single-sourced timeout; the gate FAILS LOUD if host
# multicast is unavailable (never a silent green — a skipped coupling gate
# proves nothing).
- name: N-way society coupling (epic #139)
run: |
KERNEL_ELF=$(find build/ -name "kernel.elf32" | head -1)
echo "Using kernel: $KERNEL_ELF"
QOS_KERNEL="$KERNEL_ELF" make ci-smoke-society3-gate
- name: Upload integration test results
uses: actions/upload-artifact@v4
with:
name: integration-test-results
path: |
integration_results.txt
boot_output.txt
retention-days: 7
release:
name: Release Preparation
runs-on: ubuntu-latest
needs: [build, security, code-quality, documentation, integration]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
# mtools: required by grub-mkrescue on ubuntu-latest — without it the
# ISO build fails (kernel.iso is now a hard error, not a silent skip)
sudo apt-get install -y build-essential qemu-system-x86 grub-pc-bin xorriso mtools nasm
- name: Build release
run: |
make clean
make BUILD_TYPE=release
make build/x86_64/kernel.iso
- name: Generate release notes
run: |
echo "# QuantumOS Release $(date +%Y%m%d)" > release_notes.md
echo "" >> release_notes.md
echo "## Build Information" >> release_notes.md
echo "- Build date: $(date)" >> release_notes.md
echo "- Git commit: ${{ github.sha }}" >> release_notes.md
echo "- Kernel size: $(stat -c%s build/x86_64/kernel.elf) bytes" >> release_notes.md
echo "" >> release_notes.md
echo "## Changes" >> release_notes.md
git log --oneline -10 >> release_notes.md || echo "- See commit history" >> release_notes.md
echo "" >> release_notes.md
echo "## Installation" >> release_notes.md
echo "See README.md for installation instructions." >> release_notes.md
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: |
build/x86_64/kernel.elf
build/x86_64/kernel.iso
release_notes.md
retention-days: 90