# Changelog

A curated record of capOS's shipped milestones: the significant, externally
visible capabilities the system has demonstrated.

Each entry documents one landed milestone with the evidence that backs it -- a
shipped feature with measured behavior, a security finding closed with its fix
and verification commands, a scaling proof with its data, or a benchmark with
its host caveats -- named, dated to the commit it landed at, and reproducible.

## 2026-06-09

### Remote-session Web UI server-side session hardening -- Review C high closed

- The capOS-served Web UI (`remote-session-web-ui`) no longer derives its
  `capos_remote_session` cookie from the accept counter. It now mints an opaque,
  high-entropy server-side session id -- a one-way SHA-256 (domain-separated,
  base64url) over the kernel-CSPRNG backend `SessionInfo.session_id` -- and a
  per-session double-submit CSRF token from the same seed under a distinct
  label. The raw backend id never crosses to the browser (the digest is
  one-way). Landed at `91743ed4`.
- Server-side enforcement added before request dispatch: token rotation on
  login/re-login, cookie expiry + fail-closed rejection on logout and on a
  replayed rotated-out id, idle (30 min) and absolute (12 h) lifetime bounds via
  absolute monotonic deadlines, `Host` (DNS-rebinding) and `Origin` validation,
  and a required `X-CSRF-Token` double-submit on state-changing requests. The
  session cookie is `Secure` when `X-Forwarded-Proto: https` reports HTTPS
  ingress; the plaintext loopback proof stays explicitly non-`Secure`. This
  matches the committed operator-bundle/host-bridge CSRF contract; no
  schema/kernel/ABI change.
- Evidence: `make run-cloud-prod-remote-session-web-ui-l4` (local QEMU/cloudboot)
  now drives stale-token, CSRF (missing/mismatch), `Origin` (missing/cross-site),
  `Host`, idle/absolute expiry, cookie-attribute, and login/re-login rotation
  denial gates, each failing closed before any backend-held capability call
  (`report.json` `sessionHardening`: all gates true, `tokenLen` 43). Local proof
  only; not private GCE reachability, public ingress, or TLS.

## 2026-06-04

### Userspace TCP over the capability NIC -- TcpListener/TcpSocket round trip

- A userspace process now completes a full `TcpListener`/`TcpSocket` round trip
  over `smoltcp` driven entirely through capabilities: frames cross the
  `Nic` capability, the kernel-owned keep-armed sustained-receive RX pool
  (`Nic.receivePoll @4`) feeds smoltcp's RX token across the multi-frame TCP
  handshake, and no host-physical or device-usable address is exposed to
  userspace. This is the first userspace TCP (connection-oriented, multi-frame)
  path in capOS, landed at `002c5927` (Phase C slice 7c-iii).
- It rests on the sustained-receive ABI that lifted the prior single-frame
  `Nic.receive` blocker (slice 7d, `Nic.receivePoll @4`, kernel-owned bounce
  pool with per-recycle scrub + slot-generation bump, no per-frame device
  reset). Evidence: the `run-cloud-prod-network-stack-smoltcp-tcp-listener-roundtrip`
  QEMU proof exercises listen/accept/echo over the userspace stack.
- Remaining for the full Phase C userspace L4 stack: the `cap/network.rs`
  production-contract relocation (parent task
  `cloud-prod-userspace-network-stack-smoltcp-local-proof`), after which the
  TLS-client handshake, self-hosted Web-UI L4, and IPv6-TCP tracks unblock.

## 2026-06-02

### Real-GCE virtio-net NIC bind -- the GCE Polling Path track closes

- The billable real-GCE proof passed: a real `e2-small` instance
  (`europe-west3-a`, image `capos-test-1780412056-e1cb`, source commit
  `1fb65683`) booted the production non-`qemu` cloud kernel from the legacy
  datapath manifest, the kernel-brokered legacy polled path bound the live GCE
  virtio 0.9 NIC (`00:04.0`, `1af4:1000`), and the run passed the
  `tools/cloudboot/run-test.sh --require-provider-nic-proof` gate. Run
  `1780412056-e1cb`; `teardown_status=complete`, no leaked sandbox resources.
- This is the first real-hardware attestation of the legacy bind. Every stage
  ran end to end on GCE: candidate select over PIO BAR0 (`iobase=0xc040`), I/O +
  bus-master enable (`command=0x0107`), real GCE device MAC read
  (`src_mac=42:01:0a:c8:00:12`), `NET_F_MAC` negotiation
  (`device_features=0x204399a7`), **full 4096-entry vring materialization**
  (`rx_queue_size=4096 tx_queue_size=4096 rx_vring_pages=28 tx_vring_pages=28` --
  the ~110 KiB/28-page contiguous `frame::alloc_contiguous` per queue that QEMU
  cannot emulate, since QEMU caps queue size at 1024), a broadcast DHCP DISCOVER
  TX, and a real device->host RX DMA within the TSC-governed wall-clock budget
  (`rx_used_len=532 ethertype=0x0800` IPv4, `rx_clock_usable=true`, `rx_iters=1`).
  Marker:
  `cloudboot-evidence: provider-nic-bound 0000.00.04.0-vendor.1af4-dev.1000-iobar.0-iobase.c040-usedidx.1-usedid.0-usedlen.532-ethertype.0800-txusedidx.1-srcmac.42010ac80012`
  from `cap::provider_nic_bind_proof::report_real_completion_legacy`.
- The bind reached the device only after three distinct real-hardware premise
  conflicts were closed by prior local slices, each found by a bounded billable
  run: modern-only candidate select vs the legacy device (5b), the QEMU-SLIRP-only
  RX stimulus vs GCE anti-spoofing (5c, real-MAC DHCP DISCOVER + accept-any
  wall-clock RX), and the device's 4096-entry queue exceeding the prior 1024 bound
  (5d, `MAX_LEGACY_QUEUE_SIZE` raised to the spec max 32768).
- Honest scope: this is a **kernel-brokered, polling-only** data-path attestation
  (`userspace_driver_authority=kernel-brokered-legacy-polled`,
  `interrupt_model=polled-no-msix`, `device_autonomous_raise=not-claimed`,
  `direct_dma=blocked`, `host_physical_user_visible=0`). It is **not** a claim of
  userspace-driver authority, device-autonomous MSI-X delivery, an L4 socket
  round-trip (raw-frame reachability per the slice-5 Option-A decision; L4 is
  networking-proposal Phase C), or cloud storage readiness. It retires the
  `cloud-gcp-virtio-net-nic-driver` blocker.
- Reproduce: build the cloudboot image with
  `make capos-cloudboot-image MANIFEST_SOURCE=system-cloud-provider-virtio-net-legacy-datapath.cue`,
  confirm `make run-cloud-provider-nic-bound-legacy` (and
  `make run-cloud-provider-nic-bound-legacy-large-queue`) green on the build
  commit, then `tools/cloudboot/run-test.sh --require-provider-nic-proof`
  (BILLABLE; operator-authorized 2026-05-27, commit `2aaeaa53`).

## 2026-05-30

### Device Driver Foundation -- production bind-stack qemu-gate dissolution

- Umbrella `cloud-prod-ddf-bindstack-qemu-gate-dissolution` closed at commit
  `fdc8eb66`. The production (non-`qemu`) cloud kernel's device-authority surface
  is now always-built code fronted by fail-closed runtime capability probes,
  graduated off the overloaded `qemu` gate and the per-proof `cloud_*_proof`
  feature modules it previously hid behind, while `iommu.rs` stays gated and
  brokered bounce-buffer-only DMA (no host-physical/IOVA export) is preserved.
  Landed as six reviewed slices:
  - `29a76850` -- RX MSI-X `Interrupt.wait` waiter-wakeup determinism: the
    provider-consumer flake was a synthetic-dispatch ordering race, fixed by
    gating injection on the owner being parked in `cap_enter`
    (`sched::thread_blocked_on_cap_enter`); 28/28 `make run-ddf-provider-consumer`
    (baseline ~18% flake).
  - `ef2548b3` -- grant-source de-specialization: the prod
    `{dmapool,devicemmio,interrupt}_grant_source` statics stage an arbitrary
    enumerated function through one `stage_with_class` entry point taking a
    `ProdGrantClass` descriptor (`cap::prod_grant_source_class`), bit-identical.
  - `b7d30ec3` -- MSI-X program/attach/arm/unmask + kernel-injected-dispatch
    wait graduated into always-built `cap::interrupt_programmed` /
    `device_interrupt::wait_kernel_injected_dispatch`.
  - `82c2ed53` / `b2168e05` / `ad6da6ce` -- the `device_manager` backend port:
    always-built `ProductionDeviceTable` device-record/handle backend,
    per-record bounce-buffer DMA-pool backend, and interrupt-route backend
    (parent `cloud-prod-device-manager-backend-port`).
  - `fdc8eb66` -- split test-harness affordances off the `qemu` feature.
  - Reproduction: `make run-cloud-devicemmio-grant`, `make run-cloud-dmapool-grant`,
    `make run-cloud-interrupt-grant`, `make run-cloud-provider-cap-waiter`,
    `make run-cloud-provider-nvme-readonly-bind`, `make run-ddf-provider-consumer`,
    `make run-net`. Remaining DDF work -- userspace virtio-net RX/multiqueue and
    NVMe I/O-queue provider readiness, plus live cloud bind -- is tracked by the
    separate provider-parent tasks, not this umbrella.

## 2026-05-23

### Device Driver Foundation -- userspace virtio-net provider closeout

- Commit `c86374f8` (`2026-05-23 16:51 UTC`) closes the first local bounded
  userspace virtio-net provider-driver proof for Task 6. The provider-consumer
  smoke now asserts one stable closeout line tying together selected queue `1`
  TX descriptor/avail/doorbell/used-ring/CQ ownership across the full QEMU TX
  queue depth, bounded queue `0` RX synthetic-token CQ identity, selected TX/RX
  MSI-X/LAPIC wait/ack/EOI, selected-route mask/unmask/reset/reassignment,
  teardown, stale-handle blocking, and no silent provider fallback. Reproduction:
  `make run-ddf-provider-consumer`, `make run-net`. This remains bounded local
  QEMU provider evidence over manager-owned bounce buffers; live hardware RX
  used-ring ownership, full virtio-net ownership, direct DMA/IOMMU, cloud
  NIC/storage readiness, and virtio block/storage drivers remain separate work.

### Device Driver Foundation -- provider TX full-depth CQ ownership

- Commit `e248d42b` (`2026-05-23 13:36 UTC`) extends selected userspace
  virtio-net TX CQ ownership from the prior four-outstanding window to the full
  eight-entry TX queue depth used by QEMU. The smoke now proves eight live
  manager-owned bounce buffers, descriptor/avail publication and notify
  doorbells for descriptors `0` through `7`, wrong-order completion fail-closed
  at descriptor `7`, in-order CQ identity delivery/ack for all eight
  descriptors, ninth allocation rejection without pool expansion, teardown-only
  drain for seven incomplete descriptors, and release retirement of seven
  delivered but unacknowledged CQ events. Reproduction:
  `make run-ddf-provider-consumer`, `make run-net`.

### Device Driver Foundation -- provider RX wait/ack dispatch-token proof

- The provider-consumer smoke now promotes the provider RX interrupt grant's
  wait/ack path beyond the blocked skeleton for one selected RX dispatch token.
  `rx_interrupt.wait` can pend, stay unpromoted by generic route delivery-count
  advancement, and wake only after a selected RX MSI-X/LAPIC dispatch validates
  the live RX issue, selected RX source, source generation, route generation,
  virtio-net owner, and driver-unmasked route state. The paired
  `rx_interrupt.acknowledge` accounts exactly one bounded RX hardware-dispatch
  ack for the delivered zero-CQ RX event; pre-event, masked-route, duplicate,
  and stale-after-release wait/ack attempts remain fail-closed. Reproduction:
  `make run-ddf-provider-consumer`. RX descriptor publication, RX CQ identity,
  real hardware IRQ acknowledgement/deferred EOI, direct DMA/IOMMU, full
  virtio-net ownership, cloud NIC/storage readiness, and production driver
  readiness remain open.

### POSIX Adapter -- File/Directory fd closeout

- Commit `f97d9833` (`2026-05-23 06:23 UTC`): the
  `posix-file-directory-client-capos-rt` task closes the v0
  File/Directory fd surface on top of the existing Storage Phase 3
  RAM-backed `Directory` cap. `libcapos-posix` now implements `lseek()` over
  the per-fd file position and `readdir()` as a lazy `Directory.list`
  snapshot, while preserving the existing pipe, UDP, Console, and
  TerminalSession fd paths. The new `make run-posix-file` proof boots a live C
  process that creates a file through `open()`, writes, seeks, reads, lists
  the root directory with `opendir()` / `readdir()`, closes both handles, and
  asserts relative paths still fail closed. Remaining P1.4 dash-port work is
  the printf/string subset, signal/time stubs, identity stubs, dash
  vendoring/patching, multi-TU C build, and `run-posix-shell-smoke`.

### Device Driver Foundation -- provider TX release retires three unacked CQ events

- The provider-consumer smoke now extends the selected TX release-retirement
  path to three delivered but unacknowledged bounded provider TX CQ events in
  one live issue. The smoke completes descriptors `0`, `1`, and `2`, consumes
  all three through `tx_interrupt.wait`, skips all acknowledgements, proves the
  stale-bound in-flight descriptor remains in fixed `DMABuffer` slot `3`, and
  asserts provider `tx_interrupt` release retires three pending provider
  completion acks without hardware acknowledgement. The claim remains bounded
  CQ teardown evidence only; deferred EOI, hardware acknowledgement, hardware
  IRQ ownership, direct DMA/IOMMU, full CQ ownership, full userspace
  virtio-net ownership, cloud NIC/storage readiness, and production driver
  readiness remain open. Reproduction: `make run-ddf-provider-consumer`.

### Device Driver Foundation -- provider TX release retires unacked CQ event

- Commit `11eeab2e`: the provider-consumer smoke now proves release-time
  retirement for a delivered but unacknowledged bounded provider TX CQ event.
  The smoke drives a selected TX completion through
  `DMABuffer.completeDescriptor` and `tx_interrupt.wait`, deliberately skips
  `tx_interrupt.acknowledge`, releases the provider `tx_interrupt` cap, and
  asserts the release proof records one pending provider completion ack retired
  from the ledger. The stale post-release `acknowledge` path remains revoked;
  the completed buffer can still be freed normally; and deferred EOI, hardware
  acknowledgement, hardware IRQ ownership, direct DMA/IOMMU, full CQ
  ownership, full userspace virtio-net ownership, cloud NIC/storage readiness,
  and production driver readiness remain open. Reproduction:
  `make run-ddf-provider-consumer`.

### Device Driver Foundation -- provider RX descriptor boundary proof

- Commit `2bd5add5`: the provider-consumer smoke now records an explicit
  provider RX queue `0` descriptor boundary while the live RX interrupt issue
  is active. The proof keeps the existing
  `DMABuffer.submitDescriptor(queue=0)` / `completeDescriptor(queue=0)` path
  as neutral bounce-buffer accounting and asserts that RX ring publication,
  provider CQ publication, provider IRQ delivery, hardware acknowledgement,
  and direct DMA remain blocked while kernel RX cohabitation is unresolved.
  Reproduction: `make run-ddf-provider-consumer`. Honest caveat: RX descriptor
  publication, RX CQ identity, RX waiter delivery, direct DMA/IOMMU, full
  virtio-net ownership, cloud NIC/storage readiness, and production driver
  readiness remain open.

## 2026-05-17

### Kernel -- scheduler/IPC recoverable-panic surface closed

- The scheduler and IPC hot-path `.expect()/.unwrap()` sites that could
  panic on stale run-queue or thread-metadata invariants are now hardened
  across the seven hot-path functions. `block_current_on_cap_enter` logs
  and returns `false` (yielding `u64::MAX` at the syscall boundary);
  `next_start_context` logs and returns `None` so the caller's retry loop
  (`kernel_idle_entry`, `start_current_cpu`, `start_ap`) selects another
  thread; and `schedule()`, `exit_current()`, `exit_current_thread`, and
  `capos_block_current_syscall()` drop the scheduler lock and `crate::hcf()`
  on the dispatch/exit/block paths that have no caller-side recovery,
  matching the canonical last-process-exited halt. `retain_endpoint_queue`
  (`kernel/src/cap/endpoint.rs`) breaks with a diagnostic kprintln on a
  queue-length mismatch instead of panicking on `pop_front()`. The
  `PhysFrame::from_start_address(cr3_phys)` panics on the exit and
  syscall-entry paths are intentionally retained: corrupted CR3 is genuine
  memory-state corruption, not transient queue inconsistency. An explorer
  audit confirmed no recoverable panic surface remains (2026-05-17 00:41
  UTC).

### Kernel -- resource quota fields fully wired

- All three sub-items from the prior "partially wired" resource-quota
  finding are now enforced (closed 2026-05-16 19:19 UTC). The per-process
  carrier (`capos_config::ResourceProfile` on `Process::resource_profile`)
  lands the profile at spawn from `SessionMetadata::profile` via
  `RamAccountStore`. `ringScratchLimitBytes` sizes the per-process
  input/output/reply scratch buffers and rejects oversize CALLs with
  `CAP_ERR_INVALID_REQUEST`; `replyScratchLimitBytes` clamps the exception
  reply-scratch buffer to the profile ceiling (closed 2026-05-16 20:52 UTC),
  fixing the #175 asymmetry that produced spurious
  `CAP_ERR_APPLICATION_EXCEPTION_TRUNCATED` on small-ring processes;
  `endpointQueueLimit` and `inFlightCallLimit` carry the owner profile's
  values into `Endpoint::try_new`, clamped by the kernel ceilings
  `MAX_QUEUED_CALLS=32` / `MAX_IN_FLIGHT_CALLS=32`. Scope caveat: the
  endpoint-scoped bounds are per-endpoint relative to the owner profile,
  not a strict per-process counter across all endpoints the owner holds.
  ResourceProfileRecord `@13` is tombstoned as `retired13`. Reproduction:
  `make run-ring-scratch-limit`, `make run-reply-scratch-limit`,
  `make run-endpoint-queue-limit`, `make run-in-flight-call-limit`.

### Device Driver Foundation -- Hardware-audit userspace service (durable-audit Step 2b)

- Commits `037256ce` (initial slice) and the remediation follow-up on the
  same `ddf-audit-userspace-service` branch: durable-audit Step 2b of 4
  delivers `demos/hardware-audit-service`, which polls
  `HardwareAuditLog.drain` with the cursor protocol from Step 2a,
  accumulates records in memory, and serves a typed
  `HardwareAuditReader.snapshot` over a kernel-allocated Endpoint
  retagged for the consumer. The reader cursor is fail-closed: an
  `expectedSequence` outside `{0, current drain cursor, any retained
  record's sequence}` -- or a malformed-capnp param payload -- is
  rejected with a typed `InvalidArgument` exception, mirroring the
  kernel-side `HardwareAuditLog.drain` rejection so a stale or forged
  cursor cannot silently skip or repeat records. The schema docstring
  for `HardwareAuditReader` now states this contract explicitly.
  Reproduction: `make run-ddf-audit-service-smoke` proves
  boot-record accumulation, a service-handoff snapshot, a
  release-triggered follow-up snapshot, `signatureStatus = "unsigned"`,
  and the negative cursor-mismatch rejection (matched on both the
  service-side `snapshot-rejected exception_type=invalid-argument` and
  the consumer-side `cursor-mismatch rejected ok
  exception_type=invalid-argument` markers). Steps 3 (segment signing
  with key management routed through the cryptography proposal) and 4
  (durable Store-backed persistence with a defined rotation contract)
  remain open follow-ons.

## 2026-05-16

### POSIX Adapter -- P1.4 Slices 3 and 4: functional file I/O end-to-end

- P1.4 Slice 3 (FdBacking File/Directory/Terminal variants and the
  `make run-posix-file-backing-smoke` proof of Terminal routing) landed at
  `ae58f936` (closing merge `4c70a03d`). P1.4 Slice 4 (absolute-path
  resolver, functional `open()`/`opendir()` over the bootstrap-granted root
  `Directory` cap, per-fd file position tracked across `read()`/`write()`,
  and the `make run-posix-open-smoke` proof of create+write+close, then
  re-open for read, plus relative-path rejection) landed at `94b29177`
  (closing merge `de4235f9`). `closedir()` releases the local slot only.
  This is the first non-shell POSIX subsystem to reach functional parity:
  `open(path, flags)` -- `read`/`write` -- `close` works end-to-end through
  `libcapos-posix` on top of the Storage Phase 3 RAM-backed `Directory`
  authority. Reproduction:
  `make run-posix-file-backing-smoke` (Slice 3),
  `make run-posix-open-smoke` (Slice 4), and the existing
  `make run-posix-stdio-smoke` regression remains green. Honest caveat:
  the remaining v0 dash port work is stdio adoption (Slice 5), env vector
  (Slice 6), printf/string subset (Slice 7), signal/time/identity stubs
  (Slices 8-10), and dash vendoring + smoke (Slices 11-13).

### Scheduler -- Phase F remote-CPU nohz activation via reschedule IPI

- Commit `8c1601ac`: the Phase F auto-nohz preflight no longer requires
  the lease's target CPU to be the current CPU for the `namedRing =
  none` compute-lease shape. When the single-CPU `allowedCpuMask`
  targets a different scheduler CPU, the kernel parks a bounded
  remote-activation request in the target CPU's per-CPU slot and
  sends a reschedule-style IPI; the target CPU drains the request
  from its IPI handler (timer-handler backstop) and re-runs the full
  disqualification check locally under `try_lock` before arming its
  own one-shot deadline -- remote activation is never trusted blind.
  Reproduction: `make run-scheduler-cpu-isolation-lease`.

### Device Driver Foundation -- virtio-net provider RX bootstrap-grant skeleton

- Commit `b710d4fd`: the provider RX path now mirrors the provider TX
  bootstrap-grant authority at the skeleton level over the selected
  virtio-net RX MSI-X route. Adds
  `validate_provider_rx_interrupt_route` as the receive-queue
  counterpart of the TX route validator (same admission shape, same
  active/resetting state gate, same `interrupt_owner_for_device_owner`
  mapping; only the `PciMsixInterruptRole::RxQueue` role tag differs)
  plus matching `cap::interrupt_grant_source` init/build/release
  entry points. Skeleton only: live RX DMA, completion delivery, and
  hostile-smoke coverage remain open.

### Device Driver Foundation -- provider RX selected-route MSI-X control

- Commits `5ea850c3`, `1d2be684`, and `9f3f8a8c`: the provider RX
  `rx_interrupt` cap validates the live RX issue and selected virtio-net RX
  route before bounded mask/unmask of the selected RX MSI-X table
  vector-control bit and route state. The provider-consumer smoke asserts
  vector-control readback,
  delivery-count preservation, stale methods after release, and
  release-while-masked cleanup back to `driver-unmasked`; cleanup failure
  leaves the live issue uncleared so future RX cap issuance stays blocked on
  uncertain route state. RX wait/ack, descriptors, provider CQ identity,
  hardware acknowledgement, deferred EOI, full RX ownership, direct DMA/IOMMU,
  cloud readiness, and production userspace driver readiness remain open.

### SSH session -- explicit UserSession.logout failure-path proof

- Commit `9e7328e6`: `test(ssh-public-key-session)` proves the explicit
  `UserSession.logout` failure path, closing part of the open
  REVIEW_FINDINGS Low item.

### Storage Phase 2 closed in docs

- Storage & Naming Phase 2 (schema BlockDevice/File/Directory
  interfaces) was marked done in `docs/tasks/done/2026/`
  (commit `0551941c`) after Phase 3 slices 1--3 shipped on
  2026-05-14. A separate task-state reconciliation sweep (`ad280bf2`,
  closing merge `189d4af2`) realigned `docs/tasks/` directory state
  with `docs/tasks/README.md` ground truth.

### Production Provenance Milestone

- Landed across `1feee12b`..`6f775925` (2026-05-16). All GitHub Actions
  steps pinned to immutable commit SHAs, Rust nightly pinned to an
  exact date, and OVMF/qemu-system-x86/xorriso pinned to exact apt
  versions in the QEMU smoke apt-install. Each CI run publishes a
  build-provenance artifact and PRs run an advisory cross-run compare
  against the base-branch artifact. Reproduction:
  `make build-provenance` produces the provenance artifact locally;
  CI artifacts appear as `build-provenance-<sha>` per qemu-smoke run.
  Full pin inventory and bump procedure:
  `docs/trusted-build-inputs.md`. Honest caveats: the PR compare step
  is advisory-only (not PR-blocking); URL-based download-and-verify
  for OVMF and other pre-built tool binaries (Option B) remains future
  hardening.

## 2026-05-14

### Device Driver Foundation -- IOMMU VT-d remapping closed across A1/A2/B/C

- The QEMU Intel IOMMU remapping milestone closed across four reviewed slices
  in a single day: A1 active-programmed legacy-mode table (`3a60a401`), A2
  hardware-DMA translation proof through virtio-rng with an observed VT-d
  fault on an unmapped IOVA (`dfedf574`), B register-based context-cache /
  IOTLB invalidation with an ordered scrub-after-invalidate revocation cycle
  (`24eb587e`), and C two-phase revocation with hostile stale-handle /
  stale-completion smokes (closing merge `274ff63f`, follow-up `873eef56`).
  Reproduction: `make run-iommu-remapping` asserts `table program proof`,
  `invalidation proof`, `hostile stale-handle proof`, and
  `hostile stale-completion proof` all as `proof_result=ok` (QEMU 8.2.2).
  Honest caveat: QEMU-only evidence
  (`hostile_hardware_isolation=not-claimed`); the live virtio-net DMA path
  still uses bounce buffers, and production userspace-driver IOMMU authority
  remains open.

### Device Driver Foundation -- virtio-net provider four-outstanding TX window

- The userspace virtio-net provider TX path reached a four-outstanding
  completion-queue window with full provider descriptor/avail publication,
  one notify doorbell per descriptor, real IRQ-dispatch-backed
  `tx_interrupt` wait/ack/mask/unmask, per-event provider CQ identity, and a
  four-slot bounce-buffer pool. The provider notify doorbell write moved off
  the broker into the provider's own scoped notify-MMIO cap (`ef979d17`),
  and the harness now proves a general `write32` verb fails closed on that
  same notify cap (`95a65e99`). Reproduction:
  `make run-ddf-provider-consumer`, `make run-net`.

### Scheduler -- per-CPU CPL0 kernel idle thread closed

- The user-mode idle process was replaced with a per-CPU CPL0 kernel idle
  thread across Increments 1a..2e (final merge `2bba8d11`). All four idle
  dispatch sites route through the CPL0 idle context: `schedule()` timer
  path, `capos_block_current_syscall` (block path), `exit_current` and
  `exit_current_thread` (two exit paths). Each scheduler CPU slot owns a
  dedicated CPL0 idle kernel stack and `CpuContext`; the synthetic idle
  `Process` record is retained only so the idle `ThreadRef` resolves through
  the scheduler's ThreadRef-centric bookkeeping. A TLB-flush drain in
  `kernel_timer_interrupt_handler` closes the CPL0 idle-residency gap.
  Reproduction: `make run-scheduler-cpu-isolation-lease` asserts
  `idle_path=cooperative-cpl0` for the boot/AP loop and
  `idle_path=cpl0-dispatch-{timer,block,exit}` for the dispatch sites.

### Scheduler -- per-CPU nohz tick suppression and SQPOLL-driven activation

- Phase F got its first real nohz increments: per-CPU periodic-tick
  suppression for the single-runnable window (commit `9e269e31`) and
  SQPOLL-driven auto-nohz activation for ring-coupled leases
  (commit `8edd2314`), built on per-CPU CPL0 idle-thread context
  infrastructure (commit `5ac6b08f`). Generic full-nohz and timeout-based
  auto-revoke remain future work.

### Storage -- Phase 2 schema + Phase 3 slices 1--3

- Phase 2 added schema-only `BlockDevice` / `File` / `Directory` / `DirEntry`
  interfaces (commit `4c0d940c`). Phase 3 then delivered three kernel
  `CapObject` slices the same day: a RAM-backed `File` cap with
  read/write/stat/truncate/sync/close and 64 KiB per-call inline-payload
  bound (slice 1, `d06dff6b`); a RAM-backed `Directory` cap with subtree
  bring-up + grant path + QEMU smoke (slice 2, `b11ec9e4`); and a
  content-addressed RAM-backed `Store` + name->hash `Namespace` pair (slice
  3, `804a3f41`). Reproduction: `make run-file-server-smoke`,
  `make run-directory-server-smoke`, `make run-store-namespace-smoke`.
  This unblocks
  POSIX adapter Phase P1.4 (dash port) and WASI host adapter Phase W.5
  (filesystem surface), both previously blocked on the cap shape.

### Remote session -- self-served web UI is the default boot

- Commit `5594c9ef` wires the capOS-served remote-session web UI into the
  default operator boot (`cue/defaults/defaults.cue`, scoped loopback
  listener cap, `make run` host-port line). The Rust backend owns
  connection and session state; the browser receives view models and
  redacted transcript rows. Reproduction: `make run`, or the focused
  `make run-default-web-ui`.

## 2026-05-13

### Device Driver Foundation -- provider TX three-outstanding + MSI-X mask + ack

- Provider TX CQ window expanded from two to three outstanding descriptors
  (`d6458381`, `6ee96d29`), descriptor-issue-bound completions
  (`f894ee1a`, `bc3280be`), MSI-X mask/unmask control with atomic rollback
  on failure (`b5af7335`, `3c8dc627`, `ca9beb73`, `be506075`), real
  IRQ-dispatch wake of provider TX waiters (`203461da`), and hardware
  dispatch acknowledgement accounting (`caaa388c`, `bc11c1aa`). Provider
  CQ teardown gained an end-to-end quiesce/retire proof
  (`d8760182`, `dff94930`, `235ed1e8`). Reproduction:
  `make run-ddf-provider-consumer`.

### Scheduler -- SQPOLL producer-wake progress

- Scheduler added the bounded SQPOLL producer-wake increment
  (commit `0dbb5542`) with preserved wake-result state across stop
  (commit `dbf8e0ff`) on the Phase F prerequisite path that the
  2026-05-14 SQPOLL-driven auto-nohz activation builds on.

### Kernel -- endpoint / park-waiter rollback hardening

- IPC rollback paths hardened: endpoint pending-recv rollback
  (`e46b52dc`), preserved endpoint recv rollback capacity
  (`db454b59`), kept endpoint recovery live across revocation
  (`a1ccbda1`), preserved park wake status during retry
  (`d37edf54`), and drained private park waiters after unmap-retry
  (`1e0ce242`). Bounded recovery surface; no new authority.

### Language adapters -- POSIX stdio, WASI env, libcapos C pipe + entropy

- POSIX adapter routed stdio writes to the Console cap (`aa6a56d7`,
  `d442a3b7`) and exposed `posix_spawn` file actions (`b8fb3131`). WASI
  added bounded per-instance environment grants (`5f5028e7`, `987e7814`),
  promoted stdio-compatibility Preview 1 imports (`1a79037b`), and gained
  an unauthorized-import refusal harness (`c803565f`, `756b5ba8`,
  `1b53acd8`). Native libcapos shipped a C pipe smoke (`b6c2d4bb`) and an
  `EntropySource.fill` wrapper (`b1f7a3c1`, `6b3b7425`).

### Remote session -- Paperclips Path B + Tauri scaffolding

- Paperclips launch wiring Path B (worker + gateway + bridge) landed
  (`701522b9`), with host chat RPC facade over DTO (`7cf4cf2c`) and DTO
  schema for Path A (`e159adb8`). A remote-session Tauri wrapper scaffold
  (`5691ec2a`) plus capability policy hardening and preflight
  (`eff47eb3`, `b41ba656`, `ff58cacf`) prepare the desktop wrapper path.

### Build hygiene -- build-provenance compare harness

- New build-provenance comparison `make` target (`07722584`,
  `a34cb441`, `b3ed23cf`, `779f3ce0`) records runner identity in
  provenance (`00272130`) so two runners can be compared offline.

### Docs sweep -- proposal cross-link + last_reviewed refresh

- Substantial documentation refresh across ~40 proposals and architecture
  docs: cross-links sharpened, `last_reviewed` stamps refreshed, and
  proposals updated against shipped state (POSIX P1.1/P1.2/P1.3,
  Scheduler Phase D/E close and Phase F SQPOLL, error-handling against
  current ExceptionType + CapException, networking proposal against
  transitional kernel state, userspace-binaries Parts 4/5, scheduler
  Phase F.5 cross-link). The 29-page research index landed
  (`18fbaf35`). No behavior change.

## 2026-05-12

### Scheduler -- Phase F nohz scaffolding + CpuIsolationLease

- Phase F infrastructure landed across the day: nohz telemetry
  (`aeb0f4d2`), the clockevent/deadline substrate (`268b44c2`),
  `CpuIsolationLease` scaffold (`e9ab9e46`, `97f958a7`), bounded SQPOLL
  ring mode (`6dcbb69a`, `07578bec`, `cdbb45be`), and housekeeping/
  deferred-work placement (`c7580873`). These are the prerequisite chain
  the 05-14 SQPOLL-driven auto-nohz activation depends on.

### Device Driver Foundation -- provider TX completion delivery + IRQ regrant

- Provider TX gained completion-event delivery (`334818af`), hardened
  interrupt delivery (`dfebd411`), serialized wait posting against IRQ
  race (`bbe2fea7`), and reset-disable lifetime hardening (`50c6c8cd`).
  Provider TX interrupt teardown event proof
  (`9205af3e`, `d8760182`), interrupt reset reassignment proof
  (`8aee7d42`), and a disabled Intel QEMU IOMMU scaffold with MMIO status
  diagnostics (`02688941`, `41314553`, `277dbd26`) prepared the 05-14
  IOMMU Slice A1.

### Userspace runtime -- libcapos fail-closed on C-runtime threading

- libcapos now fails closed on C-runtime threading attempts (`57ad4bfa`),
  closing the remediation entry tracked in
  `docs/proposals/libcapos-c-substrate-proposal.md`.

### Remote session -- local UI bridge hardening

- Local UI bridge was hardened (`cab6f791`) with refreshed evidence
  (`21a6a16a`); login auth denial is now treated as a login failure
  rather than a transport error (`58d198f3`, `b8486eac`).

## 2026-05-11

### Device Driver Foundation -- provider/consumer split + DmaPool manager-authoritative

- The selected virtio-net userspace provider path proof landed
  (`9ca39ff8`, `e6fb4c91`): provider-consumer authority smoke (`3d59cb8b`),
  provider shadow descriptor side effect (`db5c4995`, `c91b1477`),
  selected provider metadata gated to the TX queue, MMIO/IRQ smoke
  (`c52064c0`, `d1c6cece`), and DMA accounting extension
  (`40a77ae0`). DmaPool lifecycle became manager-authoritative
  (`96e1107e`): blocks mapped DMABuffer manager-free (`149ef53e`), keeps
  DMABuffer unmap live in the manager (`d6b7a292`), validates cap identity
  before stale side effects (`4f404f44`), and propagates budget checks
  through release paths (`877ed956`, `01c078f5`, `45903e5e`). The provider
  notify-MMIO no-write cap grant landed (`78c627a9`, `d177ffa1`,
  `b8f7b83f`) with stale admission proof (`0ec23fe6`, `a5a722de`,
  `fefd5267`, `3ed4418f`) and submit-path carry (`54b1499f`).

### Scheduler -- one SQ consumer + session-logout hooks + context bind/revoke

- One SQ consumer owner is now enforced (`c427f3d9`, `b503b640`) -- the
  Phase F prerequisite that ring-coupled nohz depends on -- with
  matching scheduling-context ring/SQ owner proof stabilizations
  (`e5ec448c`, `811a4976`). Scheduling contexts can donate over
  endpoints (`d2eab605`, `6343ec84`) with block/settle around donation
  (`93706ecb`, `d202ca31`, `599f4649`), bind/revoke generation
  (`3b6e1bb5`), identity-aliasing fix (`fe4e340b`), notification cells
  (`c0e4470c`), and exit-cleanup budget preservation (`f30a9bb3`,
  `8b00c480`, `3725c87e`, `eaeb1071`). Session-logout cleanup hook
  marks bound contexts stale (`594f1353`), propagates shell exit to
  session logout (`0d9b3d90`, `0e9c8dd1`), proves logout stale
  contexts fail closed (`59dca4e8`), donated logout skip policy
  (`49de54f2`), and blocks stale-snapshot budget refresh (`9d1cd80b`).

### Device Driver Foundation -- device-manager kernel refactor

- The device-manager kernel module was split into focused submodules
  (`99c37592`, `734383f9`, `af539f6c`, `9c0a5183`, `98dddb72`,
  `bfdb78a0`), reducing the proof-stack footprint and exposing shared
  authority admission helpers ahead of Slice A1's per-domain remapping
  work. Process-exit teardown smokes for DMA/MMIO and Interrupt landed
  (`b452f18e`, `746c1742`), and a stage for the DDF IOMMU
  remapping-domain ledger went in (`636edfb2`).

### Remote session -- observable self-served UI proof

- Self-served remote-session web UI gained an observable proof
  (`e4ab7b41`, `0eb68aa8`, `971d8ce8`, `65fe4bf7`, `28db3277`,
  `505b553c`, `f0254b02`), closing the read-side gate before its 05-14
  default-boot promotion.

## 2026-05-10

### Scheduler Phase D closed

- 2026-05-10 19:39 UTC, mainline commit `77caafc0`
  (closeout `1a08ec23`): Phase D is closed. Accepted WFQ slice covers
  `SchedulingPolicyCap` weight/latency-class authority, per-thread
  weighted vruntime and per-enqueue `virtual_finish_ns`, per-CPU WFQ run
  queues, bounded steal/migration invariants, fairness/interactive/
  weight-change smokes, and the controlled Task 6 thread-scale gate.

  Phase D thread-scale benchmark (five runs, KVM, physical-core logical
  CPUs `0,1,2,3`, blocking parent join, 262,144 blocks / 16 MiB,
  `work_rounds=64`):

  | Comparison | capOS Phase D WFQ | Linux pthread | capOS gate |
  | --- | ---: | ---: | ---: |
  | 1->2 work  | `1.809x` | `1.996x` | >= `1.6x` |
  | 1->2 total | `1.774x` | `1.995x` | >= `1.6x` |
  | 1->4 work  | `3.088x` | `3.974x` | diagnostic target >= `2.5x` |
  | 1->4 total | `2.700x` | `3.850x` | diagnostic baseline > `1.538x` |

  The 1->2 work/total rows passed the harness-enforced gate; the 1->4
  rows were manually accepted from recorded diagnostics. Raw artifacts:
  `target/thread-scale/20260510T193200Z/` and
  `target/linux-thread-scale/20260510T194600Z/`. Reproduction in
  `tools/qemu-thread-scale-harness.sh` (via `make run-thread-scale`)
  and the matching `make run-linux-thread-scale-baseline`.

  **Bottleneck analysis.** Linux pthread scaled near-linearly on the
  same physical CPU set, so the workload shape is sound and the
  remaining 1->4 gap is a capOS scheduler/runtime cost. The dominant
  contributors visible in measure-mode and post-thread-scale review are:

  1. **Global `Scheduler` lock contention.** Per-CPU WFQ run queues
     exist, but several scheduler decisions (cross-CPU wake targeting,
     direct-target stale cleanup, queue reservation accounting) still
     funnel through one `Scheduler` mutex. Total-time scaling regresses
     faster than work-window scaling because exit/join/block/schedule
     paths spend disproportionate time inside that critical section.
  2. **Process-wide capability ring under one SQ consumer.** A
     multi-thread process has one ring endpoint owned by one SQ
     consumer at a time. Completions, waker resolution, and direct IPC
     all serialize there, even when scheduler dispatch is per-CPU.
  3. **Temporary four-owner scheduler-CPU assumption.** The selected
     scheduler topology is currently hardcoded to four owner CPUs; the
     boot-time CPU set is not yet discovered, so workloads larger than
     four cores cannot be admitted at all.
  4. **Periodic-tick service tax.** Non-isolated CPUs still pay the
     periodic timer-tick cost on every scheduler tick, even when no
     thread is ready to run; nohz suppression today only fires inside
     the narrow single-runnable window and the SQPOLL-coupled lease.

  **Planned architecture changes that should improve SMP / threading
  scalability.** The roadmap response is concrete:

  - **Scheduler Phase F.5: Full-SMP 16/32-core scalability**
    (`docs/backlog/scheduler-evolution.md`, cross-linked from
    `docs/proposals/smp-proposal.md`). Replaces the four-owner
    assumption with dynamic CPU topology discovery, adds the x2APIC
    backend needed for higher APIC ids, shrinks scheduler shared-state
    serialization so local pick/requeue can avoid the global lock, and
    adds topology-aware placement plus an observable migration policy.
    A 1/2/4/8/16/32-worker hardware benchmark suite against a matching
    native-Linux baseline is the gate.
  - **Ring v2: per-thread capability ring ownership**
    (`docs/proposals/ring-v2-smp-proposal.md`). Completions route by
    `ThreadRef -> RingEndpoint`, removing the single-SQ-consumer
    bottleneck and unblocking concurrent scheduler-owned work on more
    than one CPU per process. Needs TLB shootdown + cross-CPU cleanup
    review.
  - **Generic full-nohz + generic SQPOLL nohz**
    (`docs/architecture/scheduling.md` Phase F follow-ons). Extends the
    bounded SQPOLL-driven activation (2026-05-14, commit `8edd2314`)
    to arbitrary rings and threads, retiring the periodic-tick service
    tax on non-isolated CPUs and enabling realtime islands.
  - **EEVDF policy evaluation** (deferred behind Phase F). Tracked as a
    follow-on dispatcher policy, not a Phase D blocker.
  - **`SchedulingContext` over endpoints** (Phase E, see 2026-05-14
    entry above). Already-landed; lets a server inherit a caller's
    reservation, reducing IPC scheduling round-trips for the same
    workload class.

### Device Driver Foundation -- DDF authority surface broadened

- DDF capability surface broadened in one day:
  `DeviceMmio.map` returns a read-only userspace BAR VMA with the
  `unmap` cleanup paths exercised across release/drop/driver-crash/
  reset-disable; `DeviceMmio.write32` exposes typed admission;
  `DMAPool.allocateBuffer` reaches a three-slot bounce-buffer pool
  with manager-owned generation; `DMABuffer` accounting tracks
  per-slot in-flight descriptor identity with `live_inflight`
  aggregation; and `Interrupt.mask` / `unmask` perform bounded
  manager-mediated route-state control. Typed denials for invalid
  protections (`mmio-map-prot-invalid`) and invalid allocate-buffer
  requests (`dmapool-allocation-request-invalid`) now route through
  the no-result-cap admission path. Reproduction:
  `make run-devicemmio-grant`, `make run-dmapool-grant`,
  `make run-interrupt-grant`, `make run-hardware-grant-cycle`. This
  remains bounded manager accounting and admission proof: no direct
  DMA, doorbells, IOVA exposure, IOMMU programming, or production
  driver consumer.

## 2026-05-09

### Device Driver Foundation -- Interrupt/DMABuffer admission + audit hardening

- The `Interrupt` skeleton gained typed admission across
  `acknowledge`, `wait`, `mask`, and `unmask`
  (`admission-check-only`, `*-not-attempted`, `side-effect-blocked`),
  with the pending-IRQ token validator factored into
  `capos-lib::device_authority`. `DMABuffer.submitDescriptor` /
  `.completeDescriptor` follow the same admission pattern with
  per-slot in-flight accounting and typed `freeBuffer`. The
  manifest-granted `Interrupt` retains its claimed MSI-X source
  across cap releases for sequential grant-source reuse
  (commit `681e48ac`).
- `HardwareAuditLog.snapshot` exposes the volatile snapshot contract
  as typed result metadata (`bounded-volatile-ring-drop-oldest`,
  `volatile-only`, `unsigned`,
  `production-admission-policy-not-implemented`) plus typed truncation
  labels (commit `e4cea6ff`), a `startSequence` cursor for the
  retained ring, and cursor edge-case metadata for the below-oldest /
  past-end cases. Hardware audit smokes assert grant-source acquire/
  release identity for `DeviceMmio`, `Interrupt`, `DmaPool`, and
  `DmaBuffer`; cap-audit assertion sets are now exact-count anchored
  so boot-time `virtio-rng` proof records cannot satisfy the grant
  audit checks.
- Reproduction: `make run-interrupt-grant`, `make run-devicemmio-grant`,
  `make run-dmapool-grant`, `make run-hardware-audit`,
  `make run-hardware-grant-cycle`. Bounded manager accounting and
  read-side audit only; production userspace-driver authority remains
  open.

### Device Driver Foundation -- DMAPool parent-first release ordering

- Commit `29b4dde5`: `make run-dmapool-grant` releases the parent
  `DMAPool` before the result `DMABuffer`. Parent release stages a
  pending detach while the proof buffer is still attached; the
  `DMABuffer` release then frees the proof page and completes the
  staged zero-live pool detach as the single `DmaPool` `cap-op-release`
  audit. `DMABuffer` driver-crash and reset-disable `run-net` proofs
  also complete any pending parent release instead of orphaning it.

## 2026-05-08

### Device Driver Foundation -- DMAPool grant + hardware audit cap

- `KernelCapSource::DmaPool` now grants the bounded single-proof-buffer
  allocation path (commit `f95c6cf8`): `capos-rt` exposes typed
  `DmaPoolClient::allocate_buffer_wait` and `DmaBufferClient::info_wait`,
  and `make run-dmapool-grant` proves the manager-attached buffer
  lifecycle plus the matching `dmapool` / `dmabuffer` audit records. An
  earlier info-only grant variant routed through
  `kernel/src/cap/dmapool_grant_source.rs` and reused the virtio-rng
  `ManagerGrantSource` device handle.
- `KernelCapSource::HardwareAuditLog` exposes a read-only
  `HardwareAuditLog.snapshot` cap backed by a bounded volatile
  drop-oldest ring in `kernel/src/cap/hardware_audit.rs`, so userspace
  observes hardware-cap audit records without parsing COM1 text.
  Reproduction: `make run-hardware-audit`.
- `Interrupt` waiter teardown trigger now routes through the stale-safe
  detach helper used by cap release / driver-crash / reset-disable
  cleanup (commit `aeef8b41`). `make run-net` asserts the
  `interrupt waiter hook proof` line and an exact-one
  `cap-audit: cap=interrupt event=interrupt-waiter` count.
- Hostile-smoke gate hardened: `tools/qemu-net-smoke.sh` anchors the
  remaining proof-line assertions in the S.11.2 hostile-smoke gate with
  exact-count guards + anchored suffix assertions.

### Cloud boot -- GCP imported-image serial boot recorded

- Cloudboot run `1778230874-715a` (`2026-05-08 09:06 UTC`) against
  source `3951e275`: `make cloudboot-test` built the 10 GiB
  GCE-compatible disk tarball, uploaded it to the staging bucket,
  created a temporary GCE image + `e2-small` instance, and observed
  the `capos kernel starting` serial landmark on poll attempt 2.
  Serial evidence shows SeaBIOS booting from Google Persistent Disk
  virtio-scsi (10240 MiB), 2 vCPU / 2 GiB RAM discovery, Google
  RSDT/MADT tables, fail-closed IOMMU policy (no MCFG/DMAR/IVRS),
  masked I/O APIC routing, AP online, manifest load, init start, and
  shell spawn. The harness copied artifacts to
  `target/cloudboot-evidence/run-1778230874-715a/` before deleting the
  temporary instance, image, and staged tarball.

## 2026-05-07

### WASI Host Adapter Phase W.2 -- C and Rust hello-wasi smokes closed

- Commit `7bfcb1d8`: WASI host adapter Phase W.2 closed. Both Rust
  (`wasm32-wasip1`) and C (`wasm32-wasi`) `hello, wasi` payloads run
  inside the wasmi interpreter under the `wasm-host` capOS process and
  print through the host's granted Console cap via the Preview 1
  `fd_write(1, ...)` surface. Closed in four sub-slices: (1) the
  `wasm-host` userspace binary + `system-wasm-host.cue` +
  `make run-wasm-host` empty-module instantiation, carrying a one-time
  userspace ABI bump for wasmi's ~3 MiB BSS; (2) the Preview 1
  stdout-only import resolver in `capos-wasm/src/wasi/preview1.rs` (46
  imports, `args_get`/`environ_get` empty, `clock_time_get` backed by
  `Timer`, `proc_exit` via `capos_rt::syscall::exit`, `fd_write` 4 KiB
  iov-total + 1 KiB per-call ceiling through `Console`; everything else
  returns `ERRNO_NOSYS = 52`); (3) the Rust `demos/wasi-hello-rust/`
  crate with `system-wasi-hello-rust.cue` + the manifest-supplied
  payload reader in `capos-wasm/src/payload.rs`; (4) the C
  `demos/wasi-hello-c/` smoke built directly against system clang-18 +
  wasi-libc (no `libcapos`/POSIX work needed -- the wasm-host
  payload-load path from sub-slice 3 carries the C `.wasm` payload
  unchanged). Reproduction: `make run-wasi-hello-rust`,
  `make run-wasi-hello-c`, and `make run-wasm-host` for the empty-module
  regression. Phase W.3 (per-instance CapSet + LaunchParameters) is the
  next selectable phase.

## 2026-05-03

### System Configuration Slice 3 closed

- 2026-05-03 21:54 UTC, commit `a50f610d`: the System Configuration and
  Operator Extensibility track's Slice 3 closed. Every owned
  focused-proof manifest in the inventory declares its own CUE package
  and imports `capos.local/cue/defaults`; the manifest decoder rejects
  unknown document-root fields with typed `Error::UnknownField` (pinned
  by `system_manifest_rejects_unknown_root_field` and
  `system_manifest_accepts_only_known_root_fields`); and the operator
  overlay worked example covers every defaults-package extension hook
  (MOTD, console password verifier, additional authorized SSH keys,
  additional seed accounts, additional resource profiles, additional
  binaries, additional services), verified by a 1808-byte
  `manifest.bin` delta when the worked-example overlay is dropped at
  repo root and `make manifest` is rerun in package mode. Reproduction:
  `cargo test-config` (348 tests), `make manifest`, `make run`, and
  the per-manifest `make run-*` targets named in the Slice-3 inventory
  table. Residual successor scope: `system-measure.cue` migration is
  owned by `docs/backlog/scheduler-evolution.md`; `system-paperclips.cue`
  and `system-adventure.cue` are demo-owned.

## 2026-05-02

### Thread-Scale Honest Scaling Proof

- 2026-05-02 21:38 UTC, against `main` commit `374f8556`: the formal
  capOS+Linux thread-scale evidence pair was collected on the benchmark
  VM as the gate before Phase D. Both runs pinned to physical-core
  logical CPUs `0,1,2,3` on a 4-core/8-thread `n2-highcpu-8` host with
  KVM, five runs per case, same repaired benchmark shape (blocking
  parent join, 262,144 blocks / 16 MiB, `work_rounds=64`).

  | Comparison | capOS | Linux pthread | capOS gate |
  | --- | ---: | ---: | ---: |
  | 1->2 work  | `1.883x` | `1.988x` | >= `1.6x` |
  | 1->2 total | `1.787x` | `1.987x` | >= `1.6x` |
  | 1->4 work  | `1.566x` | `3.963x` | >= `1.6x` (diagnostic) |
  | 1->4 total | `1.538x` | `3.858x` | >= `1.6x` (diagnostic) |

  The 1->2 gates passed against the then-current single-global-queue
  scheduler. The 1->4 rows are the bottleneck-attribution diagnostic that
  justified Phase D's fair-share enqueue policy: Linux scaled
  near-linearly on the same physical CPU set, so the workload shape was
  sound and the gap was a capOS scheduler bottleneck. Phase D later
  reduced the gap (see 2026-05-10 entry above for the post-Phase D
  result and the **Bottleneck analysis** + planned-architecture-changes
  block).

  Raw artifacts: `target/thread-scale/20260502T213544Z/` and
  `target/linux-thread-scale/20260502T213445Z/`. Reproduction:
  `make run-thread-scale` (with `CAPOS_THREAD_SCALE_RUNS=5` etc.) and
  `make run-linux-thread-scale-baseline`. Host: internal benchmark VM
  in single GCP zone, `n2-highcpu-8`, nested virtualization, kernel
  `Linux 6.17.0-1012-gcp x86_64`, CPU `Intel(R) Xeon(R) CPU @ 2.80GHz`,
  `qemu-system-x86_64 8.2.2`, `rustc 1.97.0-nightly (c935696dd
  2026-04-29)`.

### Measure Mode Repair

- 2026-05-02 20:23 UTC, commit `08c54075`: `make run-measure` is green
  again. Two cumulative regressions: the `thread-lifecycle` measure-mode
  binary started requiring `vm` (VirtualMemory) and `frames`
  (FrameAllocator) caps when the park unmap/reuse smoke landed
  (`a7af0e37`, `765c6c26`) but `system-measure.cue` was never updated;
  the `run_park_process_exit_cleanup` path called
  `capos_rt::syscall::exit(0)` to terminate the entire process, but
  that syscall became per-thread in `214c8e11`, so the parent thread
  exited while the parked child kept the process alive. Repair: add the
  missing cap entries, bump the smoke assertion from `5 caps` to
  `7 caps`, retire the broken park-exit path, and route measure-mode
  exits through the same `exit_last_thread` ThreadControl flow as the
  spawn smoke. Closeout: `make run-measure` exits 0 in 32s with the full
  `measure: ...` segment/scheduler/timer/lock attribution intact; all
  other validation gates passed.

## 2026-05-01

### In-Process Threading Scalability

- 2026-05-01 14:58 UTC, commit `136b72de`: the In-Process Threading
  Scalability milestone reached accepted controlled evidence only after
  the benchmark shape was repaired (the old 1 MiB / spinning-parent
  shape failed to scale even on Linux pthread at four workers).
  Harness defaults are now blocking parent join, 262,144 blocks
  (16 MiB), `work_rounds=64`. Controlled native-Linux evidence on a
  physical CPU set validated the repaired shape (1->2 `1.991x` work /
  `1.990x` total; 1->4 `3.958x` / `3.834x`). Controlled capOS evidence
  on the same CPU set passed both enforced 1->2 gates with
  `1.828x` / `1.687x` work/total. Unsuppressed 1->4 diagnostic recorded
  `3.029x` / `2.386x`; switch-log-suppressed `3.272x` / `2.303x`,
  showing serial scheduler switch logging materially distorts
  four-worker work timing. Four-core capOS scaling was not declared a
  closed claim -- guest-measure evidence showed remaining global
  `Scheduler` lock contention plus exit/join/block/schedule overhead in
  total time. This was the diagnostic stepping-stone that motivated
  Phase D's WFQ run queues and the Phase F.5 architecture work listed
  in the 2026-05-10 entry.
- Same branch tightened caller-aware child publication for the repaired
  blocking-parent benchmark: publication avoids the caller only when
  another active ready scheduler CPU has a strictly lower non-idle
  dispatch load; equal-load ties keep an active-ready caller CPU
  instead of falling through to CPU0.

### Diagnostics and Scheduler Support

- 2026-05-01 07:28 UTC, commit `d8d9dab1`: benchmark attribution added
  guest-measure phase counters, host-summary work/total speedup gates,
  guest PC sampling, benchmark-only userspace symbol maps, resolved
  `user-pc-symbols.log` reports, the Linux pthread baseline, larger
  workload / Amdahl controls, logging-suppression A/B support, and
  first-slice shared-kernel lock counters for frame-allocator and
  ring-dispatch paths.
- 2026-05-01 05:24 UTC, commit `a88e7906`: scheduler support landed as
  incremental slices, not milestone closeout -- bounded per-scheduler-CPU
  runnable queues, queue reservation accounting, bounded idle-to-runnable
  wake targeting, wake/reschedule attribution, stale runnable / direct
  target cleanup proofs, a `SchedulerDispatch` substate separating
  dispatch ownership from shared thread metadata, and per-thread
  runtime/virtual-runtime accounting.

## 2026-04-30

### Multi-Process SMP Concurrency

- 2026-04-30 09:45 UTC, commit `3fb89923`: Multi-Process SMP Concurrency
  closed. Worker elapsed reporting uses scaled user-mode cycle counts;
  prime-counting ranges remain contiguous while balancing upper-range
  cost. Accepted KVM-backed run in
  `target/smp-process-scale/cycle-balanced-default/`: medians
  `smp1=1693`, `smp2=1053`, `smp4=2314`, or `1.608x` 1-to-2 speedup.
  Ordinary `run-smoke` and `run-spawn` under `-smp 2` passed.

## 2026-04-28 / 2026-04-29

### Session-Bound Invocation Context core gates

- 2026-04-29 08:40 UTC: Session-Bound Invocation Context landed its core
  gates: process-session invariant, default endpoint caller-session
  metadata, stale normal endpoint rejection, transfer scopes,
  field-granular disclosure gating, session expiry for broker-issued
  shell bundle caps, guest bundle narrowing, chat membership keyed by
  opaque caller-session references, Aurelian player state keyed by live
  endpoint caller-session metadata, and terminal output liveness checks.
  Terminal/stdio bridge completion and final service-scoped reference
  derivation/rotation remained open.

## 2026-04-25

### SMP Phase C -- multi-CPU scheduling proof

- 2026-04-25 11:47 UTC: SMP Phase C AP scheduler-owner proof closed.
  AP cpu=1 can run scheduler-owned user contexts while the BSP stays in
  kernel idle behind a one-way scheduler-owner latch (review-fix commit
  `d88bca7`). Per-CPU `KernelGsBase` + `swapgs`, PIT-calibrated xAPIC
  LAPIC timer/IPI, resident-mask TLB shootdown (vector 49), and split
  scheduler current-thread tracking landed across the day on the
  `smp-phase-c-*` branches (`swapgs`, `lapic-ipi`, `tlb-shootdown`,
  `scheduler-ownership`). Per-CPU run queues, reschedule IPIs,
  concurrent scheduler-owned work on more than one CPU, and per-thread
  rings (Ring v2) remained Phase C follow-ups.

### Telnet Shell Demo

- 2026-04-25 20:25 UTC, reviewed merge `2834bfc`: Telnet Shell Demo
  closed. Adds `telnet-gateway`, `system-telnet.cue`, `make run-telnet`,
  `make qemu-telnet-harness`, proving QEMU host-local forwarding from
  `127.0.0.1:2323` to guest port 23, password login, `caps`, `session`,
  and clean exit through a socket-backed `TerminalSession`. The child
  shell transcript proves no raw `NetworkManager`, `ProcessSpawner`,
  TCP, or unknown capability interfaces. Scoped gateway authority
  follow-up remains open.

### SMP Phase B -- APs running

- 2026-04-25 06:59 UTC: SMP Phase B closed. AP startup uses Limine
  `MpRequest`/`MpInfo::bootstrap`, stable AP records, AP-owned
  kernel/IST stacks, AP-local GDT/TSS state, capOS kernel PML4 handoff,
  AP-owned kernel RSP handoff, shared IDT, `KernelGsBase`, syscall
  MSRs, SMEP/SMAP state, and a parked interrupt-disabled `hlt` loop.

### SMP Phase A and user-buffer protection

- 2026-04-25 05:36 UTC: SMP Phase A closed. The BSP has a concrete
  `PerCpu` for syscall-stack state and current-thread mirroring;
  kernel-entry stack updates flow through one per-CPU hook.
- 2026-04-25 04:00 UTC: `workplan/user-buffer-validation-protection`
  closed the private process-buffer `validate_user_buffer` TOCTOU
  finding. `AddressSpace` now owns validation plus HHDM-backed user
  copy/read helpers under the process address-space mutex.
- 2026-04-25 03:36 UTC: final review of
  `workplan/futexspace-private-wait-wake` fixed a park-ownership bug
  where a sibling thread could drain a park SQE and park the wrong
  `ThreadRef`. Fix requires `CAP_SQE_THREAD_OWNED` plus the owning
  thread id for `CAP_OP_PARK`.

## 2026-04-24

- 2026-04-24 22:41 UTC: in-process threading design freeze closed.
  Thread/process ownership and park authority contracts frozen; review
  findings fixed before merge.
- 2026-04-24 20:53 UTC: runtime prerequisites for threading and Go
  closed, with follow-up rejecting writable-executable user mappings in
  anonymous `VirtualMemory` / `MemoryObject` paths and QEMU smoke
  coverage.
- 2026-04-24 16:45 UTC: kernel networking smoke closed -- QEMU
  virtio-net path proves modern transport discovery, virtqueue setup,
  descriptor completion, ARP, ICMP echo, smoltcp handoff, static IPv4,
  and host-backed TCP HTTP GET.
- 2026-04-24 13:11 UTC: custom userspace target closed. Userspace
  artifacts build through `targets/x86_64-unknown-capos.json`; kernel
  stays on `x86_64-unknown-none`.
- 2026-04-24 11:25 UTC: boot-manifest parser scope tightened by
  `KernelBootstrapManifest`, which decodes only kernel-owned fields and
  avoids materializing the init-owned service graph. Boot package
  boundary cleanup followed (10:53 UTC).
- 2026-04-24 03:06 UTC: Ring-as-Black-Box closed. QEMU debug-tap builds
  export bounded metadata-only ring records; `tools/ringtap-viewer/`
  renders correlated SQE/CQE evidence offline.
- 2026-04-24 02:16 UTC: shared service harness extraction closed for
  non-speculative duplicated demo-service pieces.
- 2026-04-24 00:34 UTC: dependency policy gate restored by allowing
  `BSD-3-Clause` for the current Argon2 closure with rationale in
  `docs/trusted-build-inputs.md`.

## 2026-04-23

- 2026-04-23 22:05 UTC: Verified Core closed. `make kani-lib` runs the
  bounded local/GitHub Kani model-checking gate; `make kani-lib-full` adds
  the high-memory transfer model-checking gate. These are bounded model
  checks (small input sizes such as <=8 frames and 63 ELF bytes), proving
  the harnessed invariants within those bounds rather than for all inputs.
  The companion Loom check (`cargo test-ring-loom`) exercises a bounded
  concurrency model of the ring protocol, not the shipped
  `kernel/src/cap/ring.rs`.
- 2026-04-23 21:30 EEST: boot-to-shell milestone closed. Default
  `make run` reaches setup/login, volatile credential creation,
  password-authenticated session minting, broker-issued shell bundles,
  redacted auth/session audit records, and an interactive native shell
  REPL over serial. `capos-shell` is init on shell-led manifests;
  anonymous shell starts on boot; `login`/`setup` mint authenticated
  operator bundles.
- 2026-04-23 16:34 UTC: split UART shell session closed. `make run`
  presents login/native shell on terminal UART while kernel/debug
  output goes to `target/qemu-console.log`. The revocable read
  milestone closed in the same window -- `make run-revocable-read`
  proves a parent can revoke a child-local `BootPackage` grant through
  `CapabilityManager`.

## 2026-04-20 To 2026-04-22

- 2026-04-22 23:50 UTC: AP-independent review remediation closed
  issues around endpoint owner cleanup, ProcessSpawner badge
  attenuation, ProcessSpawner heap-OOM paths, queued release semantics,
  pinned CUE toolchain enforcement, stale authority docs, spawn
  hardening stability, NMI IST coverage, MemoryObject replacement for
  raw frame grants, generated capnp ownership, and manifest validation
  modularization.
- 2026-04-21 22:21 EEST: VirtualMemory quota review finding resolved
  with per-address-space ownership tracking, holder quota, bounded
  auto-placement probes, owned-range checks, and QEMU coverage.
- 2026-04-21 18:46 EEST: smoke demos moved into a nested `demos/`
  userspace workspace; `system.cue` packages each demo as a distinct
  release-built binary/service.
- 2026-04-21 16:56 UTC: cross-process `CAP_OP_CALL`/`RECV`/`RETURN`
  flow closed. Allocation-free synchronous ring dispatch (12:28 UTC),
  SMEP/SMAP, `cap_enter` blocking waits with timeout, Endpoint, and
  RECV/RETURN routing (01:15 UTC) closed in the same window.
- 2026-04-20 23:05 EEST: Phase 0 and Phase 1 cleanup closed -- dead-code
  cleanup, ELF validation hardening, deterministic error paths,
  corrupted ring recovery policy, `capos-lib` split, host tests.

## 2026-04-05

- 2026-04-05 16:39 EEST: Stage 4 and Stage 5 direction took shape.
  Capability invocation moved from direct calls toward the
  shared-memory ring and `cap_enter`; preemptive scheduling was
  documented after the PIT/context-switch scheduler landed; stale
  `cap_call` proposal text was replaced with the ring-based model.
- 2026-04-05 17:08 EEST: planning surface matured. The roadmap moved
  out of `README.md`, review findings split into their own log, and
  the project added userspace-binaries, SMP, Go runtime, cloud
  deployment, storage/naming, service architecture, GPU,
  error-handling, and persistence planning.
- 2026-04-05 10:35 EEST: design grounding expanded through prior-art
  research on seL4, Zircon, Plan 9/Inferno, EROS/CapROS/Coyotos,
  Genode, and LLVM target customization. That research fed the
  interface-as-permission decision.
- 2026-04-05 02:17 EEST: manifest/config and init-side planning
  advanced with a no-std manifest config loader, hardening tests, and
  early init-side manifest parsing demos.

## 2026-04-04

- 2026-04-04 21:02 EEST: capOS bootstrapped as a Limine-loaded Rust
  kernel with serial output, then gained the first Cap'n Proto
  capability invocation path and a staged implementation roadmap.
- 2026-04-04 23:12 EEST: Stage 1 through Stage 3 landed in rapid
  succession -- virtual memory with kernel remapping and isolated
  process address spaces; Ring 3 user-space transition through
  GDT/TSS/syscall setup; and process abstraction with ELF loading,
  per-process address spaces/cap tables, static init, and QEMU
  auto-exit proof.
- 2026-04-04 23:57 EEST: the first major design proposals appeared,
  including userspace TCP/IP networking and capability-based service
  architecture. Networking was split into its own proposal after
  review.
