Skip to content

Development - #5

Merged
cemililik merged 8 commits into
mainfrom
development
Apr 21, 2026
Merged

Development#5
cemililik merged 8 commits into
mainfrom
development

Conversation

@cemililik

@cemililik cemililik commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

Summary by Sourcery

Demonstrate an end-to-end two-task IPC round-trip on the QEMU virt BSP and mark Phase A as complete, updating docs and audits accordingly.

New Features:

  • Add capability-backed IPC demo between two kernel tasks using a shared endpoint with send/receive capabilities on QEMU virt.
  • Introduce per-task capability tables and IPC endpoint/queue globals in the BSP to support the demo scenario.

Enhancements:

  • Rework BSP task A/B logic to perform an IPC send/receive exchange instead of simple cooperative yield loops, including deterministic task ordering via the scheduler.
  • Extend kernel_entry initialisation to create and publish IPC kernel objects, capability tables, and endpoint capabilities before starting the scheduler.
  • Clarify comments, boot-flow descriptions, and panic/unsafe audit notes around shared kernel state, context switching, and cooperative scheduling.
  • Tidy minor scheduler test code formatting and assembly comments for context_switch_asm.

Documentation:

  • Update unsafe-log entry UNSAFE-2026-0012 to cover aliasing on additional shared IPC-related statics and refine its invariants and rejected alternatives.
  • Advance roadmap and phase-a documentation to record A6 completion, Phase A closure, and the new T-005 task.
  • Add detailed task spec for T-005, a Phase A completion business review, and a baseline performance review capturing image size and structural performance metrics for the IPC demo.
  • Introduce a user-facing guide explaining how to run and interpret the two-task IPC demo on QEMU virt.

Summary by CodeRabbit

  • New Features

    • Two-task IPC demo: end-to-end capability-controlled send/receive round-trip with scheduler-mediated IPC.
  • Documentation

    • Added demo guide with run steps and expected output.
    • Added Phase A completion retrospective, performance baseline, task spec, roadmap updates, and multiple code/security review artifacts.
    • Expanded unsafe-audit notes and security-model clarifications.
  • Style

    • Minor comment/formatting tweaks in code and tests.

cemililik and others added 2 commits April 21, 2026 19:55
Task A sends a capability-gated message to Task B through an endpoint; B
replies; both tasks exit cleanly — proving the Phase A exit bar end-to-end.
7 acceptance criteria; guide, baseline perf review, and business review
required before Done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Task B registers as receiver on a capability-gated endpoint; Task A sends
a message (label=0xAAAA); B receives and replies (label=0xBBBB); A receives
the reply. Full IPC round-trip through ipc_send_and_yield / ipc_recv_and_yield
and two cooperative context switches confirmed on QEMU virt aarch64.

Docs: two-task-demo.md guide; A6 baseline perf review (80 KiB image,
17.5 KiB .bss, 27-instruction context switch); A2–A6 Phase A business
retrospective. UNSAFE-2026-0012 extended to cover IPC statics aliasing.

Phase A complete. 109 host tests passing; QEMU smoke confirmed.

Refs: ADR-0017, ADR-0019, ADR-0020
Audit: UNSAFE-2026-0012

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Apr 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements the A6 two-task IPC demo on QEMU by replacing the previous scheduler smoke-test tasks with a capability-gated send/reply flow, wiring in global IPC state in the BSP, and documenting the milestone closure, unsafe aliasing rationale, and Phase A completion across roadmap, reviews, and guides.

Class diagram for BSP IPC infrastructure and tasks in A6

classDiagram
    class StaticCell_T {
      +UnsafeCell_MaybeUninit_T_0
      +new() StaticCell_T
      +get() *mut MaybeUninit_T
    }

    class Scheduler_QemuVirtCpu {
      +new() Scheduler_QemuVirtCpu
      +add_task(cpu QemuVirtCpu, handle TaskHandle, entry fn, stack_top usize) Result_void
      +start(cpu QemuVirtCpu) -> !
      +yield_now(cpu QemuVirtCpu) Result_void
      +ipc_send_and_yield(cpu QemuVirtCpu, ep_arena EndpointArena, queues IpcQueues, table CapabilityTable, cap CapHandle, msg Message, badge Option_u64) Result_void
      +ipc_recv_and_yield(cpu QemuVirtCpu, ep_arena EndpointArena, queues IpcQueues, table CapabilityTable, cap CapHandle) Result_RecvOutcome
    }

    class QemuVirtCpu {
      +new() QemuVirtCpu
      +context_switch(prev *mut Aarch64TaskContext, next *const Aarch64TaskContext)
    }

    class EndpointArena {
      +default() EndpointArena
      +allocate(ep Endpoint) Result_EndpointHandle
    }

    class Endpoint {
      +new(id u32) Endpoint
    }

    class IpcQueues {
      +new() IpcQueues
    }

    class CapabilityTable {
      +new() CapabilityTable
      +insert_root(cap Capability) Result_CapHandle
    }

    class Capability {
      +new(rights CapRights, object CapObject) Capability
    }

    class CapObject {
    }

    class CapRights {
      <<enumeration>>
      SEND
      RECV
      DUPLICATE
    }

    class CapHandle {
      +index usize
    }

    class Message {
      +label u64
      +params u64[3]
    }

    class RecvOutcome {
      <<enumeration>>
      Received
      WouldBlock
      InvalidCap
    }

    class TaskArena {
      +default() TaskArena
      +create_task(task Task) Result_TaskHandle
    }

    class Task {
      +new(id u32) Task
    }

    class TaskHandle {
      +index usize
    }

    class Pl011Uart {
      +new(base usize) Pl011Uart
      +write_bytes(buf *const u8)
    }

    class KernelEntry {
      +kernel_entry() -> !
    }

    class TaskAEntry {
      +task_a() -> !
    }

    class TaskBEntry {
      +task_b() -> !
    }

    StaticCell_T <|-- StaticCell_Scheduler_QemuVirtCpu
    StaticCell_T <|-- StaticCell_QemuVirtCpu
    StaticCell_T <|-- StaticCell_Pl011Uart
    StaticCell_T <|-- StaticCell_EndpointArena
    StaticCell_T <|-- StaticCell_IpcQueues
    StaticCell_T <|-- StaticCell_CapabilityTable_A
    StaticCell_T <|-- StaticCell_CapabilityTable_B
    StaticCell_T <|-- StaticCell_CapHandle_A
    StaticCell_T <|-- StaticCell_CapHandle_B

    class StaticCell_Scheduler_QemuVirtCpu {
    }
    class StaticCell_QemuVirtCpu {
    }
    class StaticCell_Pl011Uart {
    }
    class StaticCell_EndpointArena {
    }
    class StaticCell_IpcQueues {
    }
    class StaticCell_CapabilityTable_A {
    }
    class StaticCell_CapabilityTable_B {
    }
    class StaticCell_CapHandle_A {
    }
    class StaticCell_CapHandle_B {
    }

    KernelEntry --> Pl011Uart : initialises
    KernelEntry --> QemuVirtCpu : initialises
    KernelEntry --> TaskArena : allocates_tasks
    KernelEntry --> EndpointArena : allocates_endpoint
    KernelEntry --> CapabilityTable : creates_TableA_TableB
    KernelEntry --> IpcQueues : initialises
    KernelEntry --> Scheduler_QemuVirtCpu : configures

    Scheduler_QemuVirtCpu --> QemuVirtCpu : uses_for_context_switch
    Scheduler_QemuVirtCpu --> EndpointArena : uses_for_ipc
    Scheduler_QemuVirtCpu --> IpcQueues : tracks_ipc_state
    Scheduler_QemuVirtCpu --> CapabilityTable : validates_caps

    Capability --> CapRights
    Capability --> CapObject
    CapabilityTable --> Capability : stores
    CapabilityTable --> CapHandle : returns

    EndpointArena --> Endpoint : owns
    TaskArena --> Task : owns
    TaskArena --> TaskHandle : returns

    TaskAEntry --> Scheduler_QemuVirtCpu : calls_ipc_send_and_yield
    TaskAEntry --> Scheduler_QemuVirtCpu : calls_ipc_recv_and_yield
    TaskBEntry --> Scheduler_QemuVirtCpu : calls_ipc_recv_and_yield
    TaskBEntry --> Scheduler_QemuVirtCpu : calls_ipc_send_and_yield
    TaskAEntry --> Pl011Uart : logs
    TaskBEntry --> Pl011Uart : logs
    KernelEntry --> TaskAEntry : registers_entry
    KernelEntry --> TaskBEntry : registers_entry
Loading

File-Level Changes

Change Details Files
Replace cooperative yield-only smoke-test tasks with Task A/B IPC send/reply demo using scheduler IPC bridge and new global kernel IPC state.
  • Extend StaticCell usage to host endpoint arena, IPC queues, per-task capability tables, and endpoint cap handles as global kernel state.
  • Implement Task B as the initial receiver: logs, performs ipc_recv_and_yield on its endpoint cap, logs the received message, sends a reply via ipc_send_and_yield, then explicitly yield_now so Task A can run, and finally spins.
  • Implement Task A as initiator: logs, sends a labeled Message via ipc_send_and_yield using its endpoint cap, then performs ipc_recv_and_yield to collect the reply, logs the reply and a completion banner, then spins.
  • Adjust kernel_entry to allocate Task and Endpoint objects, build per-task CapabilityTables with SEND
RECV
Clarify and extend unsafe-audit documentation for &mut aliasing across cooperative context switches to cover new IPC statics.
  • Retitle UNSAFE-2026-0012 to cover generic &mut aliasing on shared kernel state instead of only Scheduler.
  • Document that A6 extends the pattern to EP_ARENA, IPC_QUEUES, and per-task capability tables, explaining how ipc_recv_and_yield holds &mut references across cpu.context_switch and how other tasks derive their own &mut from the same UnsafeCells.
  • Refine the invariants that justify soundness under the single-core cooperative model and note that TABLE_A and TABLE_B are disjoint, and reiterate the rejected raw-pointer vs Mutex alternatives.
docs/audits/unsafe-log.md
Mark Phase A as complete with A6 two-task IPC demo and add associated planning and task-linking updates.
  • Update the current roadmap pointer to mark Phase A as closed, set the active phase to B, record A6 completion and T-005 as the last completed task, and define the next milestone triggers around Phase B planning and UNSAFE-2026-0012 refactor.
  • Add A6/T-005 section into the Phase A roadmap, including its listing under tasks and explicit linkage from T-004 to T-005.
  • Extend the Phase A tasks index with T-005 and fix the T-004 document to link to the T-005 task file.
docs/roadmap/current.md
docs/roadmap/phases/phase-a.md
docs/analysis/tasks/phase-a/README.md
docs/analysis/tasks/phase-a/T-004-cooperative-scheduler.md
Add business and performance review artifacts plus a detailed task spec for the A6 IPC demo and a user-facing guide for running and understanding it.
  • Introduce a Phase A closure business review summarising A3–A6, accepted ADRs, test counts, exit-bar verification, what went well/poorly, technical debt, and Phase B readiness with initial priorities.
  • Add a baseline performance review capturing image size, RAM footprint, estimated IPC round-trip and context-switch costs, and qualitative boot time commentary for v0.0.1.
  • Create the T-005 task document specifying the A6 user story, acceptance criteria (including expected QEMU trace), scope, approach, DoD, and design notes.
  • Author a guide explaining what the two-task IPC demo proves, how to run it under QEMU, expected logs and execution trace, capability setup, known limitations, and references to relevant ADRs and audits.
docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md
docs/analysis/reviews/performance-optimization-reviews/2026-04-21-A6-baseline.md
docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md
docs/guides/two-task-demo.md
Minor formatting and comment cleanups in CPU context-switch assembly and scheduler tests.
  • Tidy comments and spacing around aarch64 context_switch_asm save/restore instructions for readability without changing semantics.
  • Inline add_task calls on the FakeCpu scheduler test to a more compact style.
bsp-qemu-virt/src/cpu.rs
kernel/src/sched/mod.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Apr 21, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@cemililik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 14 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 17 minutes and 14 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dcc32c05-c224-4891-a29f-534703960812

📥 Commits

Reviewing files that changed from the base of the PR and between 53ddf3e and 29ed53e.

📒 Files selected for processing (7)
  • .gitignore
  • bsp-qemu-virt/src/main.rs
  • docs/analysis/tasks/phase-b/README.md
  • docs/analysis/tasks/phase-b/T-006-raw-pointer-scheduler-api.md
  • docs/architecture/security-model.md
  • docs/roadmap/current.md
  • docs/roadmap/phases/phase-b.md
📝 Walkthrough

Walkthrough

Replaces the prior two-task cooperative scheduler smoke test with an A6 two-task IPC end-to-end demo: kernel entry allocates endpoints and per-task capability tables, registers Task B then Task A, and tasks perform a capability-controlled send/receive round-trip via scheduler IPC bridge calls. Supporting docs, reviews, and unsafe-audit scope were added/updated.

Changes

Cohort / File(s) Summary
BSP & Demo Impl
bsp-qemu-virt/src/cpu.rs, bsp-qemu-virt/src/main.rs
Minor doc formatting in cpu.rs. Replaces A5 smoke test with A6 IPC demo: new globals EP_ARENA, IPC_QUEUES, TABLE_A, TABLE_B; implements task_a (initiator/sender then recv) and task_b (receiver then reply); kernel_entry allocates endpoints/cap tables, inserts root caps, publishes IPC state, registers B before A, and uses expect for task allocation errors.
Docs: Tasks & Guides
docs/analysis/tasks/phase-a/README.md, docs/analysis/tasks/phase-a/T-004-cooperative-scheduler.md, docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md, docs/guides/two-task-demo.md
Adds T-005 task entry and full two-task IPC demo spec/guide; links and formatting updates; run instructions, expected trace, capability discipline, and known Phase A limitations.
Reviews: Business/Perf/Security/Code
docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md, docs/analysis/reviews/performance-optimization-reviews/2026-04-21-A6-baseline.md, docs/analysis/reviews/code-reviews/..., docs/analysis/reviews/security-reviews/...
Adds Phase A completion retrospective, performance baseline artifact (size/footprint metrics; latency not measured), new code-review and security-review artifacts; updates review indexes.
Roadmap & Phase Tracking
docs/roadmap/current.md, docs/roadmap/phases/phase-a.md
Marks Phase A closed (A6), updates active phase/milestone pointers and lists Phase B initial work (timer, raw-pointer API refactor for UNSAFE-2026-0012, MMU).
Unsafe Audit & Architecture
docs/audits/unsafe-log.md, docs/architecture/security-model.md
Expands UNSAFE-2026-0012 aliasing scope to include multi-yield patterns and new globals (SCHED, EP_ARENA, IPC_QUEUES, TABLE_A, TABLE_B); narrows/records cross-table revocation semantics and open ADRs.
Tests / Kernel Reformat
kernel/src/sched/mod.rs
Minor formatting changes in tests (backticks in comments; single-line add_task calls). No logic changes.
Indexes / Review READMEs
docs/analysis/reviews/*/README.md
Inserted dated entries for new business/code/security/perf reviews and removed placeholders.

Sequence Diagram(s)

sequenceDiagram
    participant TaskA as Task A
    participant Sched as Scheduler
    participant TaskB as Task B
    participant IPC as IPC Subsystem

    rect rgba(100, 150, 255, 0.5)
    Note over TaskA,IPC: Capability-controlled IPC round-trip
    end

    TaskA->>IPC: ipc_send_and_yield(message)
    IPC->>Sched: enqueue/send state, suspend Task A
    Sched->>TaskB: resume Task B

    TaskB->>IPC: ipc_recv_and_yield()
    IPC->>TaskB: deliver message label, suspend Task B
    Sched->>TaskA: resume Task A

    TaskA->>IPC: ipc_recv_and_yield() (await reply)
    Sched->>TaskB: resume Task B

    TaskB->>IPC: ipc_send_and_yield(reply)
    IPC->>TaskB: enqueue reply, suspend Task B
    Sched->>TaskA: resume Task A

    TaskA->>TaskA: receive reply, print completion
    rect rgba(200, 200, 200, 0.5)
    Note over Sched: Tasks idle → spin/wfe
    end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Development #3 — Adds IPC primitives (Endpoint/EndpointArena, IpcQueues) and capability semantics used by this demo.
  • Development #4 — Related BSP/HAL and context-switch changes affecting bsp-qemu-virt/src/cpu.rs and scheduler integration.

Poem

🐰 Two tiny hops through kernel air,
Cap rights held with tidy care,
Send, receive, a scheduler beat,
Phase A done — the demo’s sweet! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title "Development" is overly vague and generic, using a non-descriptive term that does not convey meaningful information about the substantial changeset. Use a more specific title that captures the main change, such as "Add two-task IPC demo and mark Phase A complete" or "Implement capability-backed IPC round-trip demo with Phase A closure".
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch development

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

A6 two-task IPC demo — Phase A exit bar met

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Implements end-to-end two-task IPC demo proving Phase A exit bar
• Task B receives capability-gated message from Task A, replies; both exit cleanly
• Adds IPC infrastructure: endpoint arena, queues, capability tables for both tasks
• Replaces yield-loop smoke test with full IPC round-trip using ipc_send_and_yield /
  ipc_recv_and_yield
• Includes comprehensive documentation: guide, baseline performance review, Phase A retrospective
Diagram
flowchart LR
  A["Task A<br/>initiator"] -->|ipc_send_and_yield| EP["Endpoint<br/>capability-gated"]
  EP -->|ipc_recv_and_yield| B["Task B<br/>responder"]
  B -->|ipc_send_and_yield<br/>reply| EP
  EP -->|ipc_recv_and_yield| A
  A -->|clean exit| DONE["Phase A<br/>complete"]
Loading

Grey Divider

File Changes

1. bsp-qemu-virt/src/cpu.rs 📝 Documentation +5/-7

Documentation formatting and comment alignment

bsp-qemu-virt/src/cpu.rs


2. bsp-qemu-virt/src/main.rs ✨ Enhancement +241/-101

Complete IPC demo with capability tables and endpoint setup

bsp-qemu-virt/src/main.rs


3. kernel/src/sched/mod.rs Formatting +2/-6

Minor formatting cleanup in scheduler tests

kernel/src/sched/mod.rs


View more (9)
4. docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md 📝 Documentation +115/-0

Phase A retrospective and Phase B readiness assessment

docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md


5. docs/analysis/reviews/performance-optimization-reviews/2026-04-21-A6-baseline.md 📝 Documentation +106/-0

Baseline performance metrics for v0.0.1 kernel

docs/analysis/reviews/performance-optimization-reviews/2026-04-21-A6-baseline.md


6. docs/analysis/tasks/phase-a/README.md 📝 Documentation +1/-0

Add T-005 two-task IPC demo to task list

docs/analysis/tasks/phase-a/README.md


7. docs/analysis/tasks/phase-a/T-004-cooperative-scheduler.md 📝 Documentation +1/-1

Update reference link to T-005 task

docs/analysis/tasks/phase-a/T-004-cooperative-scheduler.md


8. docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md 📝 Documentation +105/-0

Complete task specification for two-task IPC demo

docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md


9. docs/audits/unsafe-log.md 📝 Documentation +9/-9

Extend UNSAFE-2026-0012 to cover IPC statics aliasing

docs/audits/unsafe-log.md


10. docs/guides/two-task-demo.md 📝 Documentation +97/-0

Comprehensive guide to running and interpreting IPC demo

docs/guides/two-task-demo.md


11. docs/roadmap/current.md 📝 Documentation +7/-7

Update current milestone to Phase A complete

docs/roadmap/current.md


12. docs/roadmap/phases/phase-a.md 📝 Documentation +4/-0

Mark A6 complete and Phase A exit bar met

docs/roadmap/phases/phase-a.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Apr 21, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. unsafe IPC lacks alternatives📘 Rule violation ⛨ Security
Description
New unsafe blocks around ipc_recv_and_yield/ipc_send_and_yield document aliasing invariants
but do not document why safer alternatives were rejected within the unsafe block comment. This
violates the requirement that each new/modified unsafe block itself contains complete
justification and invariants documentation.
Code

bsp-qemu-virt/src/main.rs[R175-197]

+    // SAFETY (aliasing): `assume_init_mut` on SCHED, EP_ARENA, IPC_QUEUES, and
+    // TABLE_B creates `&mut` references that are alive across the cooperative
+    // context switch inside `ipc_recv_and_yield`. When Task A runs during the
+    // suspension, it creates its own `&mut` references to SCHED, EP_ARENA, and
+    // IPC_QUEUES from the same UnsafeCells — technically aliasing mutable
+    // references. This is safe under the single-core cooperative invariant
+    // (no two tasks execute simultaneously) and the same reasoning documented
+    // in UNSAFE-2026-0012: the suspended task's stack frame does not access any
+    // of these references after the context switch returns, and the compiler
+    // cannot observe the aliasing across the assembly context-switch barrier.
+    // SAFETY: see aliasing note above. Audit: UNSAFE-2026-0012.
+    let recv_outcome = unsafe {
+        (*SCHED.0.get())
+            .assume_init_mut()
+            .ipc_recv_and_yield(
+                (*CPU.0.get()).assume_init_ref(),
+                (*EP_ARENA.0.get()).assume_init_mut(),
+                (*IPC_QUEUES.0.get()).assume_init_mut(),
+                (*TABLE_B.0.get()).assume_init_mut(),
+                *(*EP_CAP_B.0.get()).assume_init_ref(),
+            )
+            .expect("task B: ipc_recv failed")
+    };
Evidence
PR Compliance ID 3 requires each new/modified unsafe block to include (a) why unsafe is needed,
(b) invariants, and (c) why safer alternatives were rejected. The new unsafe blocks include
invariants and refer to an audit entry, but the unsafe-site comments do not state rejected
alternatives (e.g., raw-pointer API) within the block documentation.

CLAUDE.md
bsp-qemu-virt/src/main.rs[175-197]
bsp-qemu-virt/src/main.rs[219-234]
bsp-qemu-virt/src/main.rs[272-285]
bsp-qemu-virt/src/main.rs[292-304]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New/modified `unsafe` blocks document invariants but do not document why safer alternatives were rejected within the local `unsafe` justification comment, as required.
## Issue Context
The code currently relies on references to an external audit entry (`UNSAFE-2026-0012`) for rejected-alternatives rationale. The compliance rule requires each `unsafe` block itself to contain the full justification (why unsafe, invariants, and why safer alternatives were rejected).
## Fix Focus Areas
- bsp-qemu-virt/src/main.rs[175-197]
- bsp-qemu-virt/src/main.rs[219-234]
- bsp-qemu-virt/src/main.rs[272-285]
- bsp-qemu-virt/src/main.rs[292-304]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. CapRights::DUPLICATE added to endpoint📘 Rule violation ⛨ Security
Description
The demo endpoint capabilities grant CapRights::DUPLICATE to both tasks, increasing authority
beyond what the send/recv round-trip requires. This risks introducing unnecessary ambient authority
and should be removed or explicitly justified.
Code

bsp-qemu-virt/src/main.rs[R379-383]

+    // Both tasks get SEND | RECV so each can both send and receive on the
+    // same endpoint — Task A sends the initial message and receives the reply;
+    // Task B receives the initial message and sends the reply.
+    let ep_rights = CapRights::SEND | CapRights::RECV | CapRights::DUPLICATE;
+
Evidence
PR Compliance ID 1 prohibits introducing ambient authority or weakening capability enforcement.
Granting DUPLICATE expands what each task can do with the capability (potential further
propagation), which is unnecessary for the stated IPC demo unless explicitly required and justified.

CLAUDE.md
bsp-qemu-virt/src/main.rs[379-383]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Endpoint capabilities for Task A and Task B include `CapRights::DUPLICATE`, which grants additional authority beyond the needs of the A6 send/recv demo.
## Issue Context
The PR adds `let ep_rights = CapRights::SEND | CapRights::RECV | CapRights::DUPLICATE;`. If `DUPLICATE` is not required for the demo, remove it to reduce ambient authority; if it is required, add an explicit justification comment explaining why it is needed for the scenario.
## Fix Focus Areas
- bsp-qemu-virt/src/main.rs[379-383]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. add_task unsafe lacks alternatives 📘 Rule violation ⚙ Maintainability
Description
The modified unsafe block in scheduler tests documents stack alignment but does not document why
safer alternatives were rejected in the local unsafe justification. This fails the requirement for
complete per-unsafe justification on modified unsafe regions.
Code

kernel/src/sched/mod.rs[R635-636]

+            sched.add_task(&cpu, h0, spin_entry(), s0.top()).unwrap();
+            sched.add_task(&cpu, h1, spin_entry(), s1.top()).unwrap();
Evidence
PR Compliance ID 3 applies to modified unsafe blocks as well. The test unsafe block is modified
in this PR, but the nearby safety comment does not include why safer alternatives were rejected, as
required by the checklist item.

CLAUDE.md
kernel/src/sched/mod.rs[635-636]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A modified `unsafe` block in tests lacks the required (c) “rejected alternatives” documentation within the local `unsafe` justification.
## Issue Context
Even in tests, the compliance checklist requires each new/modified `unsafe` block to document why unsafe is needed, invariants, and why safer alternatives were rejected.
## Fix Focus Areas
- kernel/src/sched/mod.rs[635-636]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. UB from aliased &mut🐞 Bug ≡ Correctness
Description
task_a/task_b derive &mut references to shared StaticCell state (scheduler + IPC
arenas/queues) and pass them into ipc_*_and_yield, which context-switches while those mutable
borrows are still live. When the other task runs it derives another &mut to the same statics,
which is undefined behavior under Rust aliasing rules and can theoretically miscompile even without
true parallel execution.
Code

bsp-qemu-virt/src/main.rs[R186-196]

+    let recv_outcome = unsafe {
+        (*SCHED.0.get())
+            .assume_init_mut()
+            .ipc_recv_and_yield(
+                (*CPU.0.get()).assume_init_ref(),
+                (*EP_ARENA.0.get()).assume_init_mut(),
+                (*IPC_QUEUES.0.get()).assume_init_mut(),
+                (*TABLE_B.0.get()).assume_init_mut(),
+                *(*EP_CAP_B.0.get()).assume_init_ref(),
+            )
+            .expect("task B: ipc_recv failed")
Evidence
In the BSP, task_b (and similarly task_a) constructs &mut references to SCHED, EP_ARENA,
IPC_QUEUES, and a capability table via assume_init_mut() and then calls ipc_recv_and_yield. In
the scheduler implementation, ipc_recv_and_yield performs cpu.context_switch(...) and then,
after resuming, uses the same &mut parameters again to call ipc_recv(...) a second time—so those
mutable borrows must remain live across the context switch. Because the other task runs during that
suspension and makes the same assume_init_mut() calls on the same StaticCells, this creates
aliased &mut references, which Rust defines as UB; the project’s own unsafe audit log explicitly
documents this pattern as UB-adjacent and notes it was extended in A6 to cover IPC statics.

bsp-qemu-virt/src/main.rs[164-197]
bsp-qemu-virt/src/main.rs[221-243]
kernel/src/sched/mod.rs[370-423]
docs/audits/unsafe-log.md[146-156]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The BSP IPC demo currently creates aliased `&mut` references to shared global kernel state (`SCHED`, `EP_ARENA`, `IPC_QUEUES`, etc.) that remain live across a cooperative context switch (inside `ipc_recv_and_yield` / `ipc_send_and_yield` / `yield_now`). This is formally undefined behavior in Rust and should be eliminated before relying on optimizations or evolving beyond the current cooperative/single-core assumptions.
### Issue Context
`Scheduler::ipc_recv_and_yield` context-switches and then reuses `ep_arena`/`queues`/`caller_table` after resuming, which forces those mutable borrows to span the context switch. Meanwhile the other task derives its own `&mut` to the same statics.
### Fix Focus Areas
- bsp-qemu-virt/src/main.rs[164-243]
- bsp-qemu-virt/src/main.rs[257-305]
- kernel/src/sched/mod.rs[333-426]
### Implementation direction
Refactor the yield/IPC bridge boundary so no Rust `&mut` to shared state is live across `cpu.context_switch`. Typical solutions here are:
- introduce a raw-pointer based API for the switch-point operations (so callers hold `*mut`/`*const` across the switch and only materialize `&mut` in the active task), or
- redesign ownership so the scheduler owns the IPC state and uses interior mutability / carefully-scoped borrows that do not survive the switch point.
Keep the change minimal and document the new safety invariants in the unsafe log entry for UNSAFE-2026-0012.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In kernel_entry you grant both TABLE_A and TABLE_B capabilities with SEND | RECV | DUPLICATE on the same endpoint even though the demo only needs SEND | RECV, which both weakens the minimal-rights story and diverges from the T-005 acceptance text (separate send/recv caps); consider tightening the rights and/or updating the task doc to match the actual capability layout.
  • The guide claims that core::hint::spin_loop() "compiles to wfe", which is not guaranteed across LLVM versions or optimisation levels; either adjust the wording to describe it as an implementation-defined hint or introduce an explicit wfe helper if you want to rely on that specific instruction.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `kernel_entry` you grant both TABLE_A and TABLE_B capabilities with `SEND | RECV | DUPLICATE` on the same endpoint even though the demo only needs `SEND | RECV`, which both weakens the minimal-rights story and diverges from the T-005 acceptance text (separate send/recv caps); consider tightening the rights and/or updating the task doc to match the actual capability layout.
- The guide claims that `core::hint::spin_loop()` "compiles to `wfe`", which is not guaranteed across LLVM versions or optimisation levels; either adjust the wording to describe it as an implementation-defined hint or introduce an explicit `wfe` helper if you want to rely on that specific instruction.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request completes Milestone A6 by implementing a capability-gated IPC round-trip demo between two tasks on QEMU virt aarch64. It introduces global IPC infrastructure, including endpoint arenas and capability tables, and updates the boot sequence to initialize these components. The PR also adds a performance baseline and a Phase A retrospective. Review feedback highlights opportunities to improve error-handling consistency for scheduler calls and to align the storage of the task arena with the established global pattern for kernel objects.

Comment thread bsp-qemu-virt/src/main.rs Outdated
Comment on lines +240 to +242
let _ = (*SCHED.0.get())
.assume_init_mut()
.yield_now((*CPU.0.get()).assume_init_ref());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The result of yield_now is ignored here using let _ =, whereas all other scheduler and IPC calls in this file use .expect() to handle potential errors. For consistency and to ensure that any unexpected scheduler state (e.g., current being None) is caught during the demo, this call should also be checked.

        (*SCHED.0.get())
            .assume_init_mut()
            .yield_now((*CPU.0.get()).assume_init_ref())
            .expect("task B: yield_now failed");

Comment thread bsp-qemu-virt/src/main.rs
Comment on lines 369 to +371
let mut arena = TaskArena::default();
// Infallible: arena capacity is 16 and we allocate 2 tasks.
let handle_a = create_task(&mut arena, Task::new(0)).ok().unwrap();
let handle_b = create_task(&mut arena, Task::new(1)).ok().unwrap();
let handle_a = create_task(&mut arena, Task::new(0)).expect("create_task A failed");
let handle_b = create_task(&mut arena, Task::new(1)).expect("create_task B failed");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The TaskArena is currently allocated as a local variable on the stack of kernel_entry, which differs from the pattern used for EndpointArena and CapabilityTables (which are stored in global StaticCells). While this works for the current demo because kernel_entry never returns and the scheduler only tracks handles and contexts, it prevents other parts of the kernel from looking up Task objects by their handles. Adhering to the global storage pattern established in ADR-0016 for all kernel object types would improve architectural consistency and support future features like task destruction or status queries.

Comment thread bsp-qemu-virt/src/main.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bsp-qemu-virt/src/main.rs`:
- Around line 212-243: The comment and explicit yield are stale because
ipc_send_and_yield already yields on Enqueued; remove the redundant yield_now
call and its comment in the block that calls ipc_send_and_yield (the unsafe
block invoking SCHED.assume_init_mut().ipc_send_and_yield(...)) and update the
surrounding comment to reflect that ipc_send_and_yield yields to Task A;
alternatively, if you intend the send not to auto-yield, change the scheduler
bridge behavior in kernel/src/sched/mod.rs instead of keeping this extra
yield—do not leave both behaviors in place (references: ipc_send_and_yield,
yield_now, ipc_recv_and_yield, SCHED, CPU, EP_ARENA, IPC_QUEUES, TABLE_B,
EP_CAP_B).
- Around line 379-382: The ep_rights variable grants unnecessary
CapRights::DUPLICATE for the demo endpoint; remove CapRights::DUPLICATE so
ep_rights is only CapRights::SEND | CapRights::RECV because the code never
duplicates or transfers the endpoint (ipc_* calls pass None). Update the binding
that defines ep_rights to drop CapRights::DUPLICATE and ensure any comments
reflect the reduced least-privilege set.
- Around line 175-197: The unsafe block around the ipc_recv_and_yield call
documents aliasing/invariants but misses the required "safer-alternative
rationale"; update the unsafe comment above the block that contains SCHED,
EP_ARENA, IPC_QUEUES, TABLE_B, EP_CAP_B, CPU and the ipc_recv_and_yield call to
include a short justification explaining why safer alternatives were rejected
(e.g., "raw-pointer scheduler APIs deferred to Phase B refactor; current bridge
APIs require &mut"), while keeping the existing aliasing invariant and audit ID
(UNSAFE-2026-0012); apply the same addition to the other unsafe blocks you
flagged (the ones wrapping the same symbols/calls at the later sites).

In `@docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md`:
- Line 115: The relative link "[UNSAFE-2026-0012](../../audits/unsafe-log.md)"
in docs/analysis/reviews/business-reviews/ is incorrect; update that markdown
link target to "../../../audits/unsafe-log.md" so it points to the actual audit
file under docs/audits/ (i.e., replace ../../audits/unsafe-log.md with
../../../audits/unsafe-log.md).
- Around line 49-57: The code block showing the QEMU trace fence is missing a
language tag and triggers MD040; update the fence by adding the "text" language
tag (i.e., change the opening ``` to ```text) around the trace shown (the lines
beginning with "umbrix: hello from kernel_main" through "umbrix: all tasks
complete") so the block is treated as plain text.

In `@docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md`:
- Around line 30-46: Update the acceptance criteria to match the actual
implemented demo: change the deterministic QEMU trace lines to reflect the
current log (including Task B’s waiting line and the exact labels emitted by
kernel_main and tasks), mark checklist items that are implemented as [x], revise
the capability discipline bullet to describe how caps are actually split (Send
for A, Recv index passed to B) and that no raw object access is used, change the
IPC bullet to require use of ipc_send_and_yield / ipc_recv_and_yield (or note
the current implementation if different), and update the clean-exit bullet to
reflect the real shutdown mechanism used by kernel_entry (whether wfe or
spin-loop detection) so the criteria mirror the committed guide/code; apply the
same reconciliation changes to the corresponding checklist blocks at lines noted
(61-65 and 85-87) so all acceptance items match the implementation and completed
items are checked off.
- Around line 33-40: The fenced code block showing the expected trace should
include a language tag to satisfy MD040; update the block in
T-005-two-task-ipc-demo.md so the opening fence is ```text (not just ```), e.g.
change the trace fence containing "umbrix: hello from kernel_main" ... "umbrix:
all tasks complete" to use ```text so the console output is properly tagged.

In `@docs/guides/two-task-demo.md`:
- Around line 57-59: The demo trace incorrectly shows Task B explicitly calling
yield_now before Task A runs; update the narrative so that when B's
ipc_send_and_yield results in the endpoint transitioning to SendPending with
outcome Enqueued, the scheduler bridge yields immediately (so Task A resumes
without B having to call yield_now). Modify the steps involving
ipc_recv_and_yield, ipc_recv, ipc_send_and_yield, and yield_now to state that
Enqueued triggers an automatic yield via the scheduler bridge, matching the
behavior implemented around the Enqueued handling in the scheduler bridge and
the fix referenced in sched/mod.rs and bsp-qemu-virt's main.
- Around line 16-19: The fenced code blocks in docs/guides/two-task-demo.md are
missing language tags (triggering MD040); update each command block (e.g., the
blocks containing "cargo kernel-build", "tools/run-qemu.sh", "tools/run-qemu.sh
--release", and "tools/run-qemu.sh --int-log") to use ```shell and change the
expected console output block showing the umbrix lines (e.g., "umbrix: hello
from kernel_main" through "umbrix: all tasks complete") to use ```text so the
markdown linter passes and the intent of each block is clear.
- Line 82: Clarify the sentence about capability isolation to state that while
tasks may receive EP_ARENA via the scheduler IPC bridge, they never dereference
endpoint objects directly; endpoint resolution must still go through each task's
CapabilityTable and the EndpointArena is only referenced by the scheduler.
Update the line mentioning "No capability escapes its owner's table. The tasks
never access the `EndpointArena` directly." to explicitly mention `EP_ARENA`,
`EndpointArena`, the scheduler IPC bridge, and `CapabilityTable` so readers
understand the scheduler may pass the arena handle but tasks must resolve
endpoints only via their `CapabilityTable`.
- Line 47: The doc incorrectly states that core::hint::spin_loop() "compiles to
`wfe`"; update the sentence to remove the inaccurate instruction reference and
use the suggested clearer wording: replace the claim about `wfe` with "Task A
enters a spin loop; QEMU continues running but produces no further output."
Ensure the symbol core::hint::spin_loop() and the mention of Task A remain for
context but do not assert any specific generated instruction (e.g., remove
references to `wfe` or `ISB SY`).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c2efc9fe-f422-4506-bb7f-396cfc7d9cbe

📥 Commits

Reviewing files that changed from the base of the PR and between cb93322 and cba5b16.

📒 Files selected for processing (12)
  • bsp-qemu-virt/src/cpu.rs
  • bsp-qemu-virt/src/main.rs
  • docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md
  • docs/analysis/reviews/performance-optimization-reviews/2026-04-21-A6-baseline.md
  • docs/analysis/tasks/phase-a/README.md
  • docs/analysis/tasks/phase-a/T-004-cooperative-scheduler.md
  • docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md
  • docs/audits/unsafe-log.md
  • docs/guides/two-task-demo.md
  • docs/roadmap/current.md
  • docs/roadmap/phases/phase-a.md
  • kernel/src/sched/mod.rs

Comment thread bsp-qemu-virt/src/main.rs
Comment thread bsp-qemu-virt/src/main.rs
Comment on lines +212 to 243
// Send reply. Since Task A is in the ready queue (not yet blocked on recv),
// this transitions the endpoint to SendPending and returns Enqueued — no
// auto-yield. An explicit yield_now follows so Task A can collect the reply.
let reply = Message {
label: 0xBBBB,
params: [0; 3],
};
// SAFETY: same aliasing invariants as the ipc_recv_and_yield call above.
// Audit: UNSAFE-2026-0012.
unsafe {
(*SCHED.0.get())
.assume_init_mut()
.ipc_send_and_yield(
(*CPU.0.get()).assume_init_ref(),
(*EP_ARENA.0.get()).assume_init_mut(),
(*IPC_QUEUES.0.get()).assume_init_mut(),
(*TABLE_B.0.get()).assume_init_mut(),
*(*EP_CAP_B.0.get()).assume_init_ref(),
reply,
None,
)
.expect("task B: ipc_send reply failed");

// Yield explicitly so Task A can receive the reply that was just queued
// as SendPending. Without this yield, A's ipc_recv_and_yield would never
// run (cooperative scheduling; B never blocks again after the send).
// yield_now returns Err only when current == None, which cannot happen
// once the scheduler has started.
unsafe {
let _ = (*SCHED.0.get())
.assume_init_mut()
.yield_now((*CPU.0.get()).assume_init_ref());
}
let _ = (*SCHED.0.get())
.assume_init_mut()
.yield_now((*CPU.0.get()).assume_init_ref());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Align the reply-yield flow with ipc_send_and_yield semantics.

ipc_send_and_yield already yields on Enqueued per kernel/src/sched/mod.rs, so the “no auto-yield” comment and explicit yield_now path are stale. With Task A spinning after Line 318, Task B may never resume past the reply send, so the “done; spinning” path is not reached.

Either update the scheduler bridge to match this intended behavior, or remove the extra yield/comment and adjust the demo/docs to reflect that the reply send itself yields to Task A.

Also applies to: 318-322

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bsp-qemu-virt/src/main.rs` around lines 212 - 243, The comment and explicit
yield are stale because ipc_send_and_yield already yields on Enqueued; remove
the redundant yield_now call and its comment in the block that calls
ipc_send_and_yield (the unsafe block invoking
SCHED.assume_init_mut().ipc_send_and_yield(...)) and update the surrounding
comment to reflect that ipc_send_and_yield yields to Task A; alternatively, if
you intend the send not to auto-yield, change the scheduler bridge behavior in
kernel/src/sched/mod.rs instead of keeping this extra yield—do not leave both
behaviors in place (references: ipc_send_and_yield, yield_now,
ipc_recv_and_yield, SCHED, CPU, EP_ARENA, IPC_QUEUES, TABLE_B, EP_CAP_B).

Comment thread bsp-qemu-virt/src/main.rs Outdated
Comment thread docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md Outdated
Comment thread docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md Outdated
Comment thread docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md Outdated
Comment thread docs/guides/two-task-demo.md Outdated
Comment thread docs/guides/two-task-demo.md Outdated
Comment thread docs/guides/two-task-demo.md
Comment thread docs/guides/two-task-demo.md Outdated
cemililik and others added 3 commits April 21, 2026 23:23
Full-project review of all code committed from project inception through
Phase A exit (Phase 1–4c bootstrap + A1–A6 kernel core). Code review
verdict Approve with four non-blocking follow-ups; security review verdict
Changes requested with three Phase-B blockers (UNSAFE-2026-0012 aliasing,
cross-table revocation gap, Scheduler deadlock panic) — none of which
gate the A6 exit bar. Four review-type README indexes updated.

Refs: ADR-0013
Code-Review: docs/analysis/reviews/code-reviews/2026-04-21-umbrix-to-phase-a.md
Security-Review: @cemililik (+ Claude agent)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three narrow doc patches that land the non-code follow-ups from the
2026-04-21 security review (Kova 1):

- security-model.md: qualify "Revocation is transitive" invariant with
  the v1 single-table scope; add open questions for cross-table CDT
  and early IRQ masking in BSP reset vectors.
- two-task-demo.md: note that symmetric SEND|RECV grant on one endpoint
  is demo convenience, not a server topology; cite the ADR-0018 badge
  deferral.
- unsafe-log.md: record that UNSAFE-2026-0008's save set intentionally
  omits TPIDR_EL0/TPIDRRO_EL0 in v1; extend the audit trail with the
  2026-04-21 security-review sign-off.

No code changes; the three Phase-B blockers (UNSAFE-2026-0012 aliasing,
cross-table revocation gap, Scheduler deadlock panic) still require
their own ADR + task and are tracked as Kova 2 work.

Refs: ADR-0013
Security-Review: docs/analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Address inline review findings across code and docs. No behavioural
change; 109 host tests still pass, kernel image still builds clean.

Code:
- bsp-qemu-virt/src/main.rs: tighten ep_rights to CapRights::SEND |
  CapRights::RECV (drop DUPLICATE; the demo never calls cap_copy /
  cap_derive and never transfers the endpoint cap, so DUPLICATE is
  dead weight and the minimal-rights story is clearer without it).
- bsp-qemu-virt/src/main.rs: extend all four UNSAFE-2026-0012 aliasing
  SAFETY blocks with the "Rejected alternatives" rationale required
  by unsafe-policy.md §1 (previously carried in the audit entry only).
- bsp-qemu-virt/src/main.rs: convert `let _ = yield_now(...)` after
  Task B's reply into `.expect(...)` for consistency with the
  surrounding IPC call sites.
- kernel/src/sched/mod.rs: backtick `init_context` in a sched-test
  doc comment (pre-existing doc_markdown lint surfaced by today's
  host-clippy run).

Docs:
- T-005: acceptance criteria refreshed to match the actually-shipped
  demo — trace lines, per-task CapabilityTable with SEND|RECV root
  cap, clean-exit via core::hint::spin_loop (not wfe), all checkboxes
  marked done.
- 2026-04-21-A6-completion: fix stale ../../audits link to ../../../
  audits; add `text` language tag to the QEMU trace fence (MD040).
- two-task-demo.md: add `shell` / `text` language tags on fenced
  blocks (MD040); remove unsubstantiated "compiles to wfe" claim on
  core::hint::spin_loop (LLVM-implementation-defined); clarify that
  tasks hand &mut EP_ARENA to the scheduler but never dereference
  endpoint storage themselves — all authority checks go through each
  task's own CapabilityTable.

Unchanged (verified against current code, findings were stale):
- The IPC round-trip still requires Task B's explicit yield_now after
  the reply — ipc_send_and_yield only auto-yields on Delivered, not
  Enqueued (see sched/mod.rs:349 and the in-code comment).

Refs: ADR-0013
Code-Review: docs/analysis/reviews/code-reviews/2026-04-21-umbrix-to-phase-a.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/architecture/security-model.md (1)

289-289: Consider restructuring this invariant for readability.

This 400+ word single bullet point correctly describes the cross-table revocation limitation and accurately reflects the implementation (confirmed by insert_root creating new roots and cap_revoke traversing only within-table). However, the density makes it difficult to extract the key facts:

  1. The core invariant (revocation is transitive within a table)
  2. The v1 limitation (IPC transfer breaks the parent-child link)
  3. The consequence (sender cannot revoke IPC-transferred capabilities)
  4. The workarounds (transfer a child you keep locally, or accept independent root)
  5. The citation (security review)
📝 Proposed restructure for clarity
-- **Revocation is transitive over a derivation subtree *within a single capability table*.** Revoking a parent invalidates all derived children atomically. In v1, IPC transfer installs the received capability as a new root in the receiver's table (the `ipc_recv` path calls `insert_root`), discarding the cross-table parent-child link — so `cap_revoke` in the sender does not reach copies that have been moved over IPC. Cross-table revocation (a cross-task capability derivation tree) is an open question tracked below; until it is answered, a sender that needs to retain revoke authority over an IPC-transferred right must either (a) refuse to transfer the derived cap and instead transfer a distinct derived child it keeps locally, or (b) accept that the receiver now holds an independent root. Recorded by the [security review of Phase A exit](../analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md).
+- **Revocation is transitive over a derivation subtree *within a single capability table*.** Revoking a parent invalidates all derived children atomically.
+  - **v1 limitation:** IPC transfer installs the received capability as a new root in the receiver's table (via `insert_root`), discarding the cross-table parent-child link. Consequently, `cap_revoke` in the sender does not reach capabilities that have been transferred over IPC.
+  - **Workaround:** A sender that needs to retain revoke authority over an IPC-transferred right must either (a) refuse to transfer the derived capability and instead transfer a distinct derived child while keeping the original, or (b) accept that the receiver now holds an independent root.
+  - Cross-table revocation (a cross-task capability derivation tree) is an open question tracked below. Recorded by the [security review of Phase A exit](../analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/architecture/security-model.md` at line 289, The long dense bullet
should be split into a concise structured invariant and supporting points: state
the core invariant first ("Revocation is transitive over a derivation subtree
within a single capability table"), then explicitly note the v1 limitation that
IPC transfer installs received caps as new roots (ipc_recv calls insert_root),
explain the consequence that cap_revoke traverses only within-table so sender
revocation doesn't affect IPC-transferred copies, list the two workarounds
(refuse transfer and transfer a separate derived child you keep locally, or
accept the independent root), and finally include the citation to the security
review; reorganize the paragraph into these discrete lines or sub-bullets to
improve readability while keeping the same technical facts and the referenced
symbols (insert_root, ipc_recv, cap_revoke).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bsp-qemu-virt/src/main.rs`:
- Around line 244-263: Task B's final console.write_bytes("umbrix: task B --
done; spinning") is effectively unreachable because after
SCHED.assume_init_mut().yield_now(...) hands control back to Task A, A's
ipc_recv_and_yield() does not yield again and enters its spin loop, so B never
runs its epilogue; fix by either removing the unreachable console write in Task
B (the CONSOLE write_bytes call) or make Task A perform one more cooperative
yield (call SCHED.assume_init_mut().yield_now(...) / yield_now via the same API
used elsewhere) just after ipc_recv_and_yield() returns and before A enters its
spin loop so B can run its final epilogue — update the code paths around
ipc_recv_and_yield, the follow-up yield, and the CONSOLE write_bytes in Task B
accordingly.

---

Nitpick comments:
In `@docs/architecture/security-model.md`:
- Line 289: The long dense bullet should be split into a concise structured
invariant and supporting points: state the core invariant first ("Revocation is
transitive over a derivation subtree within a single capability table"), then
explicitly note the v1 limitation that IPC transfer installs received caps as
new roots (ipc_recv calls insert_root), explain the consequence that cap_revoke
traverses only within-table so sender revocation doesn't affect IPC-transferred
copies, list the two workarounds (refuse transfer and transfer a separate
derived child you keep locally, or accept the independent root), and finally
include the citation to the security review; reorganize the paragraph into these
discrete lines or sub-bullets to improve readability while keeping the same
technical facts and the referenced symbols (insert_root, ipc_recv, cap_revoke).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7577c204-76a4-4931-8e19-eae1613ef133

📥 Commits

Reviewing files that changed from the base of the PR and between cba5b16 and 53ddf3e.

📒 Files selected for processing (13)
  • bsp-qemu-virt/src/main.rs
  • docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md
  • docs/analysis/reviews/business-reviews/README.md
  • docs/analysis/reviews/code-reviews/2026-04-21-umbrix-to-phase-a.md
  • docs/analysis/reviews/code-reviews/README.md
  • docs/analysis/reviews/performance-optimization-reviews/README.md
  • docs/analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md
  • docs/analysis/reviews/security-reviews/README.md
  • docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md
  • docs/architecture/security-model.md
  • docs/audits/unsafe-log.md
  • docs/guides/two-task-demo.md
  • kernel/src/sched/mod.rs
✅ Files skipped from review due to trivial changes (7)
  • docs/analysis/reviews/business-reviews/README.md
  • kernel/src/sched/mod.rs
  • docs/analysis/reviews/performance-optimization-reviews/README.md
  • docs/analysis/reviews/code-reviews/README.md
  • docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md
  • docs/guides/two-task-demo.md
  • docs/analysis/reviews/security-reviews/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.md
  • docs/audits/unsafe-log.md

Comment thread bsp-qemu-virt/src/main.rs
cemililik and others added 3 commits April 22, 2026 00:02
Integrate every follow-up from the 2026-04-21 Phase-A code and security
reviews into phase-b.md. No review item remains in an ad-hoc ledger;
each is mapped to a specific B0..B6 milestone, and every decision that
must close during Phase B is 🚩-flagged in its milestone and collected
under the plan's "Open questions" section.

New milestone **B0 — Phase A exit hygiene** prepends the original
EL-drop pipeline and absorbs:

- Security-review blockers #1 / #2 / #3 — UNSAFE-2026-0012 raw-pointer
  refactor, cross-table revocation policy, scheduler deadlock panic →
  idle task + typed error — as ADR-0021 / ADR-0022 / ADR-0023.
- Code-review follow-ups: architecture docs for kernel-objects / IPC /
  scheduler; missing tests (ReceiverTableFull, slot-reuse with pending
  transfer cap, returns-Err replacements for should-panic tests);
  const {assert!(N>0)} type-level invariants on SchedQueue and
  CapabilityTable; debug_assert → typed-error hardening.
- Non-blocking tracking items, placed in their natural milestone:
  generation wrap (B2 flag), fault containment scope (B5 flag →
  Phase E for full supervisor), Capability::Debug redaction (B5 before
  console_write syscall), write_bytes TX timeout (B6 flag), QEMU-smoke
  CI gate (B6 flag), cargo-vet init (B6 flag), TaskArena local → global
  StaticCell migration (bundled with T-006), boot.s early DAIFSet (B1
  BSP checklist), TPIDR_EL0 save-set watch (TLS trigger, no decision
  yet).

ADR numbers shifted: the pre-review 0021..0026 (EL-drop, MMU, AS,
loader, syscall ABI, initial syscalls) become 0024..0029 so the
B0 blockers can claim 0021..0023. Final numbers are assigned when the
ADR is actually written per ADR-0013.

current.md updated: active phase B, active milestone B0, first task to
open is T-006 (raw-pointer scheduler API refactor).

Also: docs/analysis/temp/ added to .gitignore as a local-only transient
workbook directory (follow-up ledgers, drafts, scratch notes that do not
belong in git history).

Refs: ADR-0013
Code-Review: docs/analysis/reviews/code-reviews/2026-04-21-umbrix-to-phase-a.md
Security-Review: docs/analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…note

Two narrow inline-review fixes.

bsp-qemu-virt/src/main.rs: the `console.write_bytes("umbrix: task B --
done; spinning")` call at the tail of task_b is structurally unreachable
in the v1 single-round demo. After Task B's final `yield_now`, Task A's
`ipc_recv_and_yield` picks up the reply from SendPending without
blocking and runs straight to its own spin loop — control never returns
to Task B. The expected QEMU trace (recorded in the A6 business review)
confirms this: the "done; spinning" line has never appeared in output.
Remove the unreachable write; keep `loop { spin_loop() }` because the
`fn() -> !` return type still requires a divergent tail. Expand the
task_b doc comment so future readers do not rediscover the reachability
story.

docs/architecture/security-model.md: the long dense "Revocation is
transitive … within a single capability table" bullet added by commit
`de66d68` packs the core invariant, the v1 scope limit, its
consequence, two workarounds, the cross-table open-question pointer,
and a citation into one paragraph. Reorganise into discrete
sub-bullets so the invariant leads and the supporting details follow.
Technical facts unchanged; referenced symbols (insert_root, ipc_recv,
cap_revoke) preserved.

No behavioural change; 109 host tests still green; QEMU build still
clean.

Refs: ADR-0013
Security-Review: docs/analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Expose the scheduler's IPC bridge (ipc_send_and_yield / ipc_recv_and_yield)
in a form that never holds a live &mut to EP_ARENA / IPC_QUEUES / TABLE_*
across cpu.context_switch — closing UNSAFE-2026-0012 (#1 Phase-B blocker
from the 2026-04-21 security review) before any later milestone adds more
shared state. TaskArena migration to a StaticCell is bundled in the same
task to avoid a second round of BSP static-cell churn.

7 acceptance criteria; ADR-0021 writing is the first step inside the
task. Status In Progress; current.md points at T-006; phase-b/README
and phase-b.md updated.

Refs: ADR-0013
Audit: UNSAFE-2026-0012
Security-Review: docs/analysis/reviews/security-reviews/2026-04-21-umbrix-to-phase-a.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cemililik
cemililik merged commit c83510e into main Apr 21, 2026
2 checks passed
cemililik added a commit that referenced this pull request May 8, 2026
… 2026-05-08 + 2026-05-07 follow-ups

Closes the 12 remaining items flagged by the 2026-05-08 multi-axis
review's §Follow-up backlog (3 Track-2 Majors, 1 Track-3 Major fix
already closed in `59c08e9`, 6 Track-3 / Track-2 Minors, 2 Track-4
Minors, 2 Track-2 Nits) plus the carry-forward 2026-05-07 Track-H
NIT-1.

**Track 2 Majors (forward-flagged → ADR-0027 / phase-b ledger riders):**
- M1 (escape-hatch doc): ADR-0027 §Decision outcome (c) gains a bullet
  documenting `mem::forget` / `ManuallyDrop` / `let _ = ...` as
  deliberate-but-rare escape hatches, mirroring the
  `x86_64::structures::paging::MapperFlush` precedent.
- M2 (MMU-instance binding): ADR-0027 §Decision outcome (c) gains a
  bullet noting `MapperFlush::flush(self, mmu: &impl Mmu)` accepts
  any `Mmu`; multi-`Mmu` deployments (B3+ per-task `AddressSpace`,
  Phase C multi-CPU) will need a stronger token type. Out of scope
  for v1.
- M3 (ADR-0034 placeholder): ADR-0027 §Decision outcome adds an
  "ADR-0034 (kernel-image section permissions) placeholder" block
  alongside ADR-0033, and `phase-b.md` ADR ledger gains rows for
  both ADR-0033 and ADR-0034 with named-but-unallocated discipline.

**Track 3 Minors (governance / wording polish):**
- m1 + m2 (current.md L52): drop "Phase-2" prefix on "§Simulation
  table" (the table walks Steps 0–4, not a "Phase 2"); "Accept will
  be" → "Accept landed as" + actual commit SHA `bb0a6ba`.
- m3 (commit-style.md PR-numbering rider): new §"PR-number references
  in committed artefacts" subsection naming the recurrence (PR #18 +
  PR #20 each had a one-commit PR-number fix-up) and codifying three
  acceptable disciplines (defer banner authoring; reference branch
  slug; or use commit SHA).
- n1 (framing alignment): "first to apply Simulation forward" wording
  in current.md (banner + Active decisions row) and phase-b.md §B2
  status block aligned to the precise "first non-recovery-primitive
  state-machine ADR drafted under §Simulation" phrasing — ADR-0032's
  Propose did land with a table; the prior framing was technically
  defensible only under a narrow reading of "retro-extracted".

**Track 2 Nits (substance riders in ADR-0027):**
- #4 (DSB ISH vs DSB NSH rationale): §Simulation gains a rationale
  paragraph after the table — `ISH` is forward-compatible with the
  eventual SMP boot, sub-microsecond cost on single-core, matches
  Linux aarch64 `arch/arm64/mm/proc.S` for the same reason.
- #5 (TCR_EL1.AS wording tighten): line 59 reworded — `AS = 0`
  selects 8-bit ASID *size*, not "the ASID value is 0" (the value
  is `TTBR0_EL1.ASID = 0` and is what's "globally used in v1").
- #7 (line 17 §-citation precision) + Track-3 n1: "first
  non-recovery-primitive state-machine" framing now precise.
- #8 (memory-management.md L88 page-table descriptor cosmetic):
  ASCII bit-field diagram redrawn to match L2 block-descriptor
  reality (OutputAddress[47:21], not [47:12]); explanatory note
  added for L1-block / L3-page variants.

**Track 4 Minors (perf-harness.sh):**
- #1 (Ctrl-C cleanup trap): new `cleanup_in_flight` shell function +
  `trap '...' EXIT INT TERM` that kills any in-flight QEMU + watchdog
  PIDs tracked in `CURRENT_CMD_PID` / `CURRENT_WATCHDOG_PID` shell
  globals. `run_with_timeout` updates the globals at every call so
  the trap addresses whichever pair is currently in flight; clears
  them at every clean exit so the trap is a no-op outside iterations.
- #2 (p99 small-N reporting hygiene): generated baseline report
  Methodology section gains a "**Note on p99 at small `n`**" paragraph
  explaining that under nearest-rank `p99 == max` for `n < 100` and
  callers should not over-read it as a tail-latency signal until
  `n >= 100`.

**Track 4 Nit #3 (read_stats refactor):** **Already closed by PR #21
review-round commit `ef30b5c`** — the 8 `echo | awk` parses became a
single `while read` loop. Verified at HEAD (`grep -c "while read -r
key val" tools/perf-harness.sh` → 1 hit).

**2026-05-07 Track-H NIT-1 (Pending Amendment closure-path indexing):**
UNSAFE-2026-0019 / 0020 / 0021 each gain a 2026-05-08 "closure-path
indexed" Amendment naming the canonical clearance trigger (B5
Milestone, ADR-0030 entry-point, deadline-arming syscall) explicitly,
so a future reader of `unsafe-log.md` alone has the full picture
without leaving the file. No semantic change; co-locates information
that was previously distributed across `phase-b.md` cross-references.

Verification gates re-run on the integration branch:
- `cargo fmt --all -- --check` clean
- `cargo host-test` 159/159 (25 + 100 + 34)
- `cargo host-clippy` clean (-D warnings)
- `cargo kernel-clippy` clean
- `cargo kernel-build` clean
- `tools/perf-harness.sh --iterations=3` runs end-to-end with the new
  trap + Methodology note + while-read parsing intact

This commit + the prior 2026-05-08 review's recommendations close all
follow-ups identified by both 2026-05-07 and 2026-05-08 multi-axis
reviews. Forward-flagged items (10/12/13 from 2026-05-07) and any
review-round bot input on this integration branch remain the only
open items.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request May 15, 2026
Verified all 5 review findings against current code state; all valid.
Minimal-change fixes: 4 doc-only, 1 visibility narrowing.

**(1) T-019 user-story §Review-history line 134 — unresolved `<TBD>`
placeholders.** The 2026-05-14 implementation-arc row carried two
literal `<TBD>` tokens (the BSP-wiring commit hash and the smoke-
trace HEAD reference) that subsequent review-round commits never
back-filled. Resolved both to `ae31bc8` (the round-3 BSP-wiring
commit). The accompanying narrative (test count, gate names, smoke
line content) was the state at commit `ae31bc8` and stays as the
historical record per the user-story file's append-only convention.

**(2) ADR-0029 §"Build pipeline (B4 / T-019)" + §"Host-side loader
tests" — in-place edit of an Accepted ADR violated append-only
policy.** Commit `196d3fb` (T-019 commit 4) silently rewrote the
placeholder-byte literal from `[0x40, 0x00, 0x80, 0xd2, ...]` (the
Accept-state form) to `[0x40, 0x05, 0x80, 0x52, ...]` (the
documented-intent `mov w0, #42; ret` form). Per CLAUDE.md non-neg
#5 + the ADR README §Format, ADRs are append-only — corrections
land in §Revision notes, not via body rewrites. Fix:
  - Reverted both byte literals (lines 44 + 78) to their Accept-
    state form.
  - Added a new §Revision notes section before §References with a
    2026-05-16 entry recording the byte-encoding correction,
    decoding both literals explicitly (Accept-state bytes →
    `MOVZ x0, #2; RET`; corrected bytes → `MOVZ w0, #42; RET`),
    citing the canonical kernel-source bytes in
    `bsp-qemu-virt/src/main.rs::USERSPACE_IMAGE`, and noting the
    discrepancy was non-load-bearing because the placeholder is
    not executed in B4.

The kernel-source bytes are unchanged (BSP `USERSPACE_IMAGE` is
the production reality and stays at the corrected form).

**(3) `kernel/src/obj/task_loader.rs` test-only `unsafe`
`FakeMmu::create_address_space` call sites — brief SAFETY comments
missing (a)/(b)/(c) discipline.** Four sites use the pattern:
  - `fixture` helper (the canonical one) at line 908
  - `missing_derive_surfaces_via_address_space_creation_failed`
    test body
  - `FailingMapMmu::create_address_space` `unsafe fn` body
  - `fixture_with_failing_mmu` helper

Fix: expanded the `fixture` helper's SAFETY comment with the full
(a) why-unsafe-required / (b) invariants-upheld /
(c) why-safer-alternative-rejected discipline. Cross-referenced
the three peer sites by name with brief "same argument as fixture"
notes, including the `unsafe fn` body which separately documents
the `unsafe_op_in_unsafe_fn` lint requirement.

**(4) `kernel/src/mm/pmm.rs` test `unsafe` blocks for
`core::ptr::write_bytes` and `*returned_ptr.add(off)` — brief SAFETY
comments missing (a)/(b)/(c).** Both blocks (the pre-poison fill +
the per-byte zero-fill assertion) were one-liners covering only
(b). Expanded both to the full (a)/(b)/(c) discipline, naming
`aligned_backing`'s host-allocation contract and the per-byte
loop's in-bounds reasoning.

**(5) `kernel/src/mm/mod.rs::phys_frame_kernel_ptr` — visibility
widened public API unnecessarily.** Helper is only called from
inside the kernel crate (`task_loader::load_image`'s byte-copy
site; verified via `grep -rn phys_frame_kernel_ptr`). Narrowed
`pub` → `pub(crate)` to keep the kernel-internal shim out of the
crate's public API surface; no external (bsp / hal / test-hal)
caller exists.

Tests at HEAD: **260/260** (no test changes; all fixes are
doc/visibility). All gates clean: cargo fmt --check,
cargo host-test, cargo host-clippy -D warnings,
cargo kernel-clippy -D warnings, cargo kernel-build. QEMU smoke
byte-stable — full demo through `tyrne: all tasks complete`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant