Repository navigation
Releases: kannaka-labs/QuantumOS
Release list
QuantumOS v0.6.1
Before more outreach, the installed 0.6.0 package was tested end to end, the way an agent uses it. quantumos-host-tools came from PyPI into clean environments on Windows and Linux, and the hub was driven over MCP in front of Kannaka (MCP and CLI), kannaka-quantum, Kannaktopus, the 0xSCADA CLI and steward. qos-mcp booted the release kernel under QEMU/KVM. The test found the bugs fixed below, and the fixes were re-verified the same way. The v1 contracts (syscall ABI, the MCP tool surface, the society wire protocol) are unchanged.
Sashiko review, with your own model key (ADR-0028)
qos-review(tools/sashiko-review): an MCP server and CLI that runs a Sashiko review of a commit in a
repository you listed. It runs on your machine, with your own model provider and key, and returns the findings to
the caller. Nothing is posted.- Your key is handed only to the Sashiko process, and it is redacted from everything else.
- Every review has a required token cap, which Sashiko enforces.
review_quoteshows the worst case before
anything runs. - The hub asks before
review_start.
qBraid Lab compute in the provider broker (#305)
qbraid_labplugin: the account's Lab server and on-demand instances, priced per minute from qBraid's live profile list. qBraid instances can't be tagged, so a crash between create and record is handled one of two ways. Option b,--qbraid-lab-sole-user: refuse while foreign instances exist, then clean up our own. Option c, the default: never guess; logorphan_possibleand let the person decide.- ADR-0026 (provider broker) and ADR-0027 (ecosystem hub) are Accepted (#304).
Fixed, from an end-to-end test of the installed 0.6.0 package
- Python servers behind the hub start from a uv venv on Windows. uv's venv launcher sets
PYTHONHOMEto its own
interpreter, and every program the hub started inherited it, so a different Python (kannaka-quantum's) failed with
"No module named ...". The hub and its CLI connector now drop the launcher variables unless a server entry sets
them. - An installed package finds a kernel.
QOS_KERNEL=/path/to/kernel.elf32(from a release, checked against
SHA256SUMS.kernel) is now honoured byqos_bootand by the society tools, which take no kernel argument and
could not boot from a pip install before. - The memory bridge finds
kannakaonPATH, and its default build path no longer ends in.exeoff Windows. - The person is no longer asked to approve a call that cannot run: an
askcall to a CLI tool is validated first. - A downstream call that takes longer than
call_timeout_s(default 300 s; set per server) answers with a timeout
instead of holding the agent. - CLI output reaches the agent without terminal colour codes.
hub.example.json's 0xSCADA entries name commands the 0xSCADA CLI has (there is noalarmscommand).
QuantumOS v0.6.0
The v1 contracts frozen in 0.5.1 are unchanged. The syscall ABI, the MCP tool surface of
qos-mcp, and the COM2 / attestation wire all pass their freeze gates. Everything below is
additive.
QuantumOS on Firecracker, with a network and a disk
- PVH boot entry: QuantumOS boots as a Firecracker microVM (#234).
- Networking under Firecracker:
- Storage under Firecracker (#279):
- a block-device indirection (
blkdev_ops_t), with persistence calling onlyblkdev_*; - a virtio-blk driver over both transports;
- the virtio transports now bind several devices at once. Before, a second probe re-pointed
the NIC's registers. - New gate:
ci-smoke-disk-virtio.
- a block-device indirection (
- Disk flush: a cache flush gets up to ~30 s before the disk is called dead, as the ATA
spec allows. A loaded CI runner's fsync had outlasted the old ~1 s (#293).
Kernel
- tcp: a listener table, so a second network service can start (#240).
- modbusd: a Modbus/TCP agent in ring 3, with control writes refused (#239).
- sched: the CPU goes to a waiting shell on COM1 RX. Keystroke echo dropped from ~350 ms
to ~1 ms (#248). - Honest labels:
- waitpid: never reports a recycled pid's previous owner's exit. A program spawned into a
reused pid used to get the old exit code on its parent's first poll; this was the
"stillborn spawn" CI kept retrying past. Every process now has a generation in the exit
ledger (#295).
The public console (qos.ninja-portal.com)
- A throwaway QuantumOS microVM per visitor, in the browser (#245). Each one is restored
from a booted snapshot, so the prompt appears in ~20 ms (#249). Each restored session's
generator is reseeded (ADR-0025, #250). - Funnel metrics:
/stats,/metrics, a page beacon, and a measured timing table (#270,
#271). Internal traffic is tagged and kept out of the visitor counts (#277). - Hardening (#257):
- Keep a machine (#256, #280):
- "Keep this machine" returns a key, shown once. What you
synccomes back when you resume
with it, on a cold boot with the disk attached. - Kept machines are deleted after 7 days without use, with a 2 GB cap. The store is keyed by
a hash of the key.
- "Keep this machine" returns a key, shown once. What you
- Encrypted off-site backup of kept machines to OCI Object Storage: AES-256-GCM before
upload, mirrored deletions, and a dead disk never erases the backup (#282).
Quantum
- A host quantum broker on qBraid, reached from
qsh qpuover COM1 (#269). The simulator
is the default. A real QPU job needs an opt-in, a daily budget, a per-job cap and per-visitor
limits. The cost model is fitted to billed Rigetti jobs (#272), and refusals say the
simulator is free and when limits reset (#273). - A daily calibration circuit with a public, append-only series (#276).
Agents: real resources inside a budget, and one endpoint for the ecosystem
- Bring your own model: any AI can drive the frozen MCP surface (#232). Spend guardrails:
a cheaper default model, a usage report and a token budget (#233). - The provider broker (ADR-0026, Proposed; #283, #288). An agent can quote, provision and
tear down real resources on leases, inside an envelope the person sets:- USD per day and per action, the allowed resource classes, and the longest lease;
- approval with a key only the person holds; no agent op can approve or raise the budget;
- real spending off by default;
- leases are tagged at the provider, reaped at expiry, and cleaned up by tag after a crash,
never touching anything else; - a ledger of estimates and billed costs side by side.
- Plugins:
- Its MCP tools:
broker_quote,broker_provisionand the rest (#292).
- The hub (ADR-0027, Proposed; #297). One MCP endpoint in front of the ecosystem's MCP
servers and CLIs, with allow, ask or deny per tool (#298):- an
askcall is stored exactly and runs only after the person approves it; - CLIs without an MCP server are reached through allowlisted argv templates (#299);
- MCP servers over HTTP, each isolated so one failing server can't take the hub down (#300);
- short-lived bearer tokens are renewed on the open session (#301);
- the example config covers Kannaka memory and swarm, kannaka-quantum, Kannaktopus, the
kannaka, 0xSCADA and steward CLIs, KAX City, and the broker.
- an
The package (quantumos-host-tools)
- New commands:
qos-broker,qos-broker-mcpandqos-hub(thequantumos_agent
package), plus an[oci]extra (#302). - Fix:
mcpis pinned to>=1.10,<2. A fresh install of 0.5.1 resolves mcp 2.x, on
whichqos-mcpcannot even import (FastMCP was renamed). A new CI step builds the wheel,
installs it clean and runs the installed commands (#302).
Docs and CI
QuantumOS v0.5.1
ADR-0020 v1 contract freeze — pre-freeze corrections (guest syscall ABI)
Groundwork before the golden-diff ABI freeze gate lands, so v1 pins a correct
surface (user/usys.h):
- Corrected the
field_info_errno docstring: it cited Linux-14 EFAULT/-22 EINVAL; the syscall actually returns QuantumOSSYSCALL_EFAULT(-2) /
SYSCALL_EINVAL(-1). - Added 5 symmetric user-side twin-ABI
_Static_asserts (udp_req_t=24,
field_imprint_req_t=76,field_recall_req_t=76,field_recall_out_t=136,
user_args_t=516) so a struct-size drift fails BOTH ring builds, not just the
kernel's. - Annotated the intentional errno-band overlaps as frozen-v1 decisions:
svc_restarts()returns-1(not-a-service) sharingSYSCALL_EINVAL, and
qseed_value()returns a raw u64 not partitioned from the negative-errno band. - Split the 6 kernel-side ring-crossing
_k_ttwins (udp_req_k_t,
cap_derive_req_k_t, the fourqpu_*_k_t) out ofkernel/src/syscall.cinto a
new kernel-internal headerkernel/include/kernel/syscall_abi.h, so the
upcoming ABI freeze probe can#includeand compiler-measure them. ABI-neutral
(identical structs,_Static_asserts moved with them).
Added — v1 golden ABI freeze gate (ADR-0020)
contracts/abi/v1.golden freezes the guest+kernel ABI contract — the 35 syscall
numbers, the sub-op namespaces, the errno table, capability permission bits, and
the ring-crossing struct sizes — and CI diffs it on every push/PR. The values are
compiler-measured, not parsed from source: two probe TUs (user/abi_probe.c,
kernel/src/abi_probe_kern.c) emit the contract into a .abi_ents section under
the real build flags, and scripts/extract-abi.py reads it back with objcopy.
The gate cross-checks that the user/kernel twins agree, diffs against the
committed golden (an intended change is a visible golden diff, never silently
regenerated — make regen-abi-golden is human-only), and a teeth-check compiles
a mutated SYS_QPU and asserts the gate reddens, so a broken generator can't ship
vacuously green. New CI job abi-golden (gcc + binutils, no boot, no pip) that
also gates release.
The frozen surface now also pins ring-crossing struct field offsets
(__builtin_offsetof for every field of the six udp/cap_derive/qpu_*
twins, cross-checked user↔kernel) — so a size-preserving field reorder, which
the size check alone would miss, reddens the gate. The capability resource-type
namespace (cap_resource_type_t), the arg-page field offsets, and the device-ID
namespace (net/qpu/com2/console/disk — the resource_id a
CAP_RESOURCE_DEVICE capability names) are frozen too (237 golden entries). With
this, ADR-0020 is Accepted for the guest syscall ABI (contract a) — frozen and
CI-enforced. The MCP-schema lane (contract b), the COM2/attestation lane
(contract c, now unblocked by ADR-0019), and the durable audit-format freeze
remain scoped as deferred follow-ups.
ADR-0021 dynamic-PMM — hardening groundwork (no behavior change)
Groundwork before dynamic PMM sizing lands, all no-ops at the current hardcoded
128 MB (kernel/src/memory.c, kernel/include/kernel/memory.h):
- Added
PMM_PHYS_CEIL(0x40000000) /PMM_MAX_FRAMES(262144) — the 1 GB
identity-map ceilingboot.Salready provides — and clamp the frame count to
it before the bitmap is sized, so no frame the allocator can ever hand out is
unmappable (a>= 1 GBframe would be a #158-class escalation). - A static-layout floor: if a machine reports less RAM than the kernel heap's
backing frames need,pmm_initpanics loudly instead of lettingkheap_init
build the heap on unbacked physical memory. - Guarded the kernel-image reservation loop against a short frame count, asserted
the frame bitmap can't overrun the kernel region, and widened the frame-address
multiply to 64-bit (the clamp was the only thing preventing a 32-bit wrap).
Verified no-op at 128 M: ci-smoke boots to QuantumOS ready with the PMMROVER,
PMMHEAP, and PMMCLAMP self-tests green. The last is a synthetic teeth-check — the
clamp is factored into pmm_clamp_frames() and pmm_clamp_selftest feeds it a
1 GB frame count and asserts it clamps to exactly 262144, so the 1 GB ceiling is
proven load-bearing on the-m 128Mleg without any > 1 GB RAM (revert-confirmed:
removing the clamp panics the boot and reddens the gate). The mmap-driven dynamic
sizing + high-memory feature legs follow in subsequent increments.
ADR-0021 dynamic-PMM — mmap-driven sizing (PR-3)
The 128 * 1024 * 1024 hardcode (and its TODO: Get actual memory size from multiboot) is gone: memory_init now takes the RAM total as a parameter
(memory_init(void) -> memory_init(uint64_t total_memory)), sized from a real
parse of the Multiboot1 memory map. multiboot_parse_memory()
(kernel/src/main.c) treats the e820 map as untrusted bootloader input — the
whole mmap buffer must sit inside the 1 GB identity map with no overflow; each
entry's size must be >= 20 and advance the cursor without walking past the
window (iteration-capped at 1024); only type-1 available regions count; each
region end is overflow-checked and the RAM total is the MAX region end (never
a sum), clamped to PMM_PHYS_CEIL. It falls back to mem_upper, then panics
if neither is present rather than sizing a wild bitmap, and runs only after
boot_validate_multiboot confirms the MB1 magic (parsing a v2 block at v1 offsets
would wild-read like the closed framebuffer bug). Byte-wise mb_rd32/mb_rd64
avoid unaligned access on the untrusted buffer.
The parsed total flows kernel_main -> boot_config.total_memory ->
memory_init -> pmm_init. The frame bitmap is now sized for the 1 GB maximum
(fixed 32 KB) rather than detected RAM, so it always covers the fixed
kernel-image/heap reservations no matter what the mmap reported — structurally
ruling out a small-RAM overrun; frames above the detected total stay
free-but-unreachable (the alloc scan is bounded by total_frames).
A one-line greppable PMMSIZE=<hex> boot marker reports the derived frame count.
New ci-smoke gate asserts it lands in the 128 MB-class window [0x7F00, 0x8000]
— observed 0x7FE0 at -m 128M (QEMU reserves ~128 KB at the top of RAM, which
is exactly why the count is not the naive 0x8000 a hardcode would give).
Revert-confirmed: forcing a 2 GB total clamps to 0x40000 and still boots to
QuantumOS ready (the clamp survives), but trips the gate with frame count 262144 outside window — the gate has teeth. The -m 256M/512M scaling legs (the
true hardcode-vs-live differential) follow in PR-4.
ADR-0021 dynamic-PMM — high-memory proof + differential CI (PR-4), Accepted
Completes the feature and flips ADR-0021 to Accepted. Two new boot self-tests
(kernel/src/memory.c, wired after PMMCLAMP):
pmm_highmem_selftest(PMMHIGH) — the load-bearing proof that dynamic sizing
is safe above 128 MB. On RAM past 128 MB it allocates a top-of-pool frame,
asserts its physical address is genuinely high (>= 128 MB,< 1 GB), and —
the real proof — writes two distinct sentinels through the returned identity VA
and reads them back, so aboot.Sthat mapped only 128 MB (or a wrong/stale
map) faults or mismatches here instead of silently handing out an unreachable
frame. On the-m 128Mleg there is no high frame, so it reports the skip
branch (proving the guard ran — not a vacuous always-pass).pmm_residency_storm_selftest(PMMSTORM) — extends the single-shot heap
reservation proof to a bulk drain: 1024 frames pulled with the rover aimed
straight at the reserved kernel heap, asserting none land in
[__heap_start, __heap_end). Catches a multi-allocation rover regression that
the single-shotPMMHEAPcheck could miss.
New differential CI legs make ci-smoke-mem256 / ci-smoke-mem512 (CI jobs
pmm-differential-256/512, both gating release) boot at 256/512 MB and assert
the frame count lands in that size's window (~0xFFE0 / ~0x1FFE0, i.e. it
~doubles / ~quadruples the 128 MB leg's 0x7FE0) and that the PMMHIGH
writeback took its live branch. This is the true hardcode-vs-live differential
that the -m 128M leg alone cannot show: a 128 MB hardcode prints 0x8000 at
every -m and never the live PMMHIGH. Revert-confirmed two ways — re-hardcoding
memory_init to 128 MB reddens the mem256 sizing window (0x8000 outside
[65280,65536]); broadening the high-memory guard so 256 MB wrongly skips reddens
the mem256 PMMHIGH-live check while sizing still passes (the two gates are
independent). Every "un-fakeable gate" named in the ADR-0021 design is now live.
Build clean under -Werror; format/cppcheck/api-consistency green.
ADR-0022 prereq-2 — scheduler perf/stability baseline (report-only + calibration)
ADR-0022 deferred the COM2-latency fix behind two prerequisites; prereq 1 (the
latency gate) shipped. This is prereq 2: a scheduler perf/stability baseline so a
future scheduler-constant change is measured, not blind (ADR-0016). Measurement-
only — it changes no timer HZ / SCHED_QUANTUM_TICKS / service model.
An adversarial design panel refuted the naive metric: aggregate context switches are
dominated by voluntary yield()s (every long-lived citizen busy-yields with a non-
blocking recv, resetting the quantum counter thousands of times per 10 ms tick), so
switch_count/tick is both quantum-insensitive (a gate on it is vacuous) and host-
throughput dependent (CI-flaky). The fix is a dedicated preempt_count in the
scheduler, incremented only at the timer-quantum-expiry reschedule in scheduler_tick
(never on SYS_YIELD), which is 1/quantum-paced by construction. Exposed as a new
SYSINFO_SCHED sub-op (no new syscall — no ADR-0020 golden churn) on one atomic line
SCHED: switches=.. preempt=.. ticks=.. maxgap=.. spread=.. runnable=.., driven by a
qsh sched command a...
QuantumOS v0.5.0
Post-v0.4.0 increments landed autonomously through the panel → gate (revert-and-confirm)
→ merge pipeline. PRs #187–#190.
Added
qos_qpu_submit— the 22nd MCP tool (#189): an agent can now run a named quantum
circuit (bell/ghz/grover) on the in-OS QPU broker and get the exact integer
result back — capability-gated (onlyswarm_svcholds the submit cap), quota-bounded
(qsub_max), and recorded in the authority ledger (AUDIT_QSUBMIT). The
conscience-before-wallet demo made agent-facing. Gated byci-smoke-qsubmit.- Published to PyPI:
pip install quantumos-host-toolsis live; tagged releases now
auto-publish (thePYPI_API_TOKENsecret is wired intorelease.yml).
Fixed
- PMM heap-reservation gap (#187): the kernel heap's backing frames are now reserved
in the physical allocator, so the low-first rover can never hand a live-heap frame to a
page table or ELF segment (an arbitrary-corruption path reachable only under a large
residency storm). NewPMMHEAPboot self-test, revert-confirmed. - Multiboot2-magic trap (#187): the kernel is Multiboot1-only, so an MB2 magic is now
refused with an honest panic instead of parsing a v2 info block as v1 (which would lose
the cmdline and wild-write the framebuffer). NewMB2REJECTself-test. qos_memory_importdocstring (#190): corrected — each memory's Kannaka similarity
is carried into its slot energy (the docstring had claimed it was not).- Society error identity (#190): the society tools no longer misattribute a failure to
the unrelated single-VM identity (_society_err).
Changed
- Dead-code payoff (#188): deleted the unwired
cap_transferhelper, the
declared-never-definedapic_*prototypes, and five stale duplicate bare headers under
kernel/include/— −641 lines, proven dead by a greenci-smoke.
QuantumOS v0.4.0
The agent-native arc completed and battle-tested. PRs #151–#183.
Added
- Quantum stack (epics #148/#149/#150, PRs #151–#155):
qsv, an exact Gaussian-integer
quantum state-vector citizen (zero rounding, digest-vs-host-mirror CI gate); a capability-gated
kernel QPU job broker (SYS_QPU, opaque circuits only, per-manifestqsubquota); a COM2
quantum-submit transport over the attested bridge; a host gateway dispatching
PennyLane lightning.qubit / lightning.gpu (cuQuantum) / CUDA-Q / qBraid real QPUs, all
cross-oracled against the exact engine (≤1e-9). - Agent society arc (PRs #171–#179): the end-to-end agent-native showcase (
agentdemoboot
token) — an orchestrator citizen delegates narrowed field capabilities to sub-agents it spawns
itself over spawn-time parent↔child IPC channels; content-consensus digests verified per
kernel-vouched sender; division-of-labor private field workspaces; a society of
societies — two kernels exchanging verified society results over the field-sync wire; the
ring-3 roster refactored tokernel/src/citizens.c. - CI gates: qsh singleton-IPC-cap invariant (#176), disk upgrade path — frozen audit-ledger
home survives field growth (#183), qseed-handoff smoke incl. the errno-collision gate (#168).
Fixed
- Adversarial bug-hunt campaign (PRs #156–#167): ~31 real bugs across quantum, networking,
trust-core, process/memory, and lifecycle code — 0 false positives across 8 hunts. Highlights:
closed a ring-3 → whole-OS DoS in syscall copy-in/out (#158→#160,COPYGUARDgate); DNS answers
bound to their query (on-link poisoning, #162); spawn error paths reclaim address spaces (#164);
argv buffer cleared between spawns (#165).