Skip to content

Development#7

Merged
cemililik merged 10 commits into
mainfrom
development
Apr 22, 2026
Merged

Development#7
cemililik merged 10 commits into
mainfrom
development

Conversation

@cemililik
Copy link
Copy Markdown
Collaborator

No description provided.

cemililik and others added 7 commits April 22, 2026 23:41
The Umbrix name turned out to be registered elsewhere. Renamed
project-wide to Tyrne — a clean invented name with no prior hits — so
the high-security positioning is not diluted by a trademark conflict.

Sweep applied to every tracked text file:
  UmbrixOS → TyrneOS    (compound, 58 occurrences)
  Umbrix   → Tyrne      (proper,   228 occurrences)
  umbrix   → tyrne      (lower,    262 occurrences)

Scope:
- Source: all Rust crates renamed (umbrix-kernel → tyrne-kernel,
  umbrix-hal → tyrne-hal, umbrix-bsp-qemu-virt → tyrne-bsp-qemu-virt,
  umbrix-test-hal → tyrne-test-hal); boot binary is now
  target/aarch64-unknown-none/debug/tyrne-bsp-qemu-virt.
- Docs: 22 ADRs, architecture docs, standards, guides, audit log,
  roadmap, task files, reviews, templates. Doc-comment URL paths
  point at github.com/cemililik/TyrneOS/...; the GitHub repo rename
  is out of scope for this commit (broken links in old commit-history
  comments are expected).
- Project-facing text: README, CLAUDE.md, AGENTS.md, CONTRIBUTING.md,
  SECURITY.md, NOTICE, LICENSE header.
- Tooling: .cargo/config.toml runner path, build scripts, skill
  library references.

Not changed (intentional):
- Git history / commit messages — stay as written. Historical
  references to Umbrix remain; these are the record.
- Working directory `/Users/dev/Documents/Projects/OS-Project` — the
  folder predates the project and the user prefers it unchanged.

Verification:
- cargo clean && cargo build — clean
- 77 kernel + 34 test-hal = 111 host tests green
- cargo fmt / host-clippy / kernel-clippy — clean
- cargo kernel-build — clean
- QEMU smoke — boot trace intact, now prefixed "tyrne:" instead of
  "umbrix:" across all five lines.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Retrospective pass R1 (manual cargo-geiger equivalent via grep): verify
that every UNSAFE-2026-NNNN entry has at least one source reference, and
that every unsafe block/fn/impl in production code cites an audit entry
per unsafe-policy §1.

Inventory:
- 14 audit entries (0001-0014); 13 Active + 1 Removed (0012, retired by
  f9b72f8 per T-006).
- Every audit tag has source references (no orphans).
- UNSAFE-2026-0012 retains 7 source references despite being Removed —
  all in rejected-alternatives comments (intentional historical context,
  no active unsafe block claims coverage under it).

One real gap found and closed:

- TaskStack::top in bsp-qemu-virt/src/main.rs had a SAFETY comment but
  no audit-tag citation. Its inner unsafe block dereferences the
  UnsafeCell interior and computes a one-past-end pointer — operations
  that fall under the TaskStack sharing pattern UNSAFE-2026-0011 was
  introduced for, but the entry's text was scoped to the Sync marker
  only. Extended 0011's Location/Operation/Invariants/Rejected-
  alternatives sections to cover top() explicitly; added the audit
  citation + rejected-alternatives rationale to the per-block SAFETY
  comment (now policy §1 compliant).

Verification: 77 kernel + 34 test-hal = 111 host tests green;
cargo kernel-build / kernel-clippy / host-clippy all clean.

Refs: unsafe-policy §1, §3
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First recorded coverage measurement for Tyrne. Overall (workspace
excluding the bare-metal BSP): 94.41 % regions, 90.37 % functions,
92.85 % lines. 111 host tests across kernel + test-hal exercise this.

Key findings routed to T-011's missing-tests bundle:

1. ipc_send_and_yield has zero direct tests. Three host tests needed
   (Delivered + unblock, Enqueued without yield, Err propagation) —
   this was already noted as a T-007 deferred follow-up; coverage
   data now confirms and quantifies the gap.
2. start() body (lines 426-473) is uncovered because it diverges;
   recommend splitting the prelude into a testable start_prelude()
   helper.
3. cap/table.rs has 40 uncovered error-return branches; a small
   targeted sweep (≤ 5 tests) covers most.
4. hal/src/mmu.rs at 40 % is expected (trait declarations only, no
   production impl until B2).

Explicit non-recommendation: do NOT chase 100 %. The current baseline
is strong; the named gaps are where real value sits.

BSP excluded: tyrne-bsp-qemu-virt is no_std + no_main, its panic
handler conflicts with std when built for host coverage. Covering it
needs QEMU-side instrumentation — routed to T-009.

Files added:
- docs/analysis/reports/2026-04-23-coverage-baseline.md — human report
- .gitignore — raw lcov/profraw dumps excluded

Raw lcov output lives at docs/analysis/reports/lcov-2026-04-23.info
(git-ignored; regenerate on demand).

Refs: T-011 (will route T-011 scope additions when opened)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First `cargo +nightly miri test` run against the full workspace. This
is the dynamic validation of ADR-0021's claim that no `&mut` reference
to shared kernel state is live across `cpu.context_switch`.

Result: 77 kernel + 34 test-hal = 111 host tests all pass under Miri's
Stacked Borrows checker. ADR-0021's aliasing story is now
dynamic-test-validated, not only paper-reviewed.

Pre-fix find (closed in this commit):

The first Miri run caught one real Stacked Borrows violation — inside
the T-007 test helper `ResetQueuesCpu`, not in production code. The
helper cached a raw pointer via `core::ptr::from_mut(&mut queues)`
and the test body later re-derived a second `&mut queues` to pass
into the bridge. Per Stacked Borrows, the second `&mut` borrow pops
the stack and invalidates the tag on the cached pointer; when
`context_switch` then dereferenced the helper's pointer, the tag
was already dead.

Fix: derive each `*mut` pointer exactly once at the top of the test
and reuse the value. This is the same discipline ADR-0021 enforces
on the production side — a reminder from the T-006 retro's "trace
the call graph" lesson that test helpers need the same aliasing
discipline as production code whenever they cache a pointer.

Notable non-finding: the production bridge — every momentary
`&mut *sched`, the split-borrow on `(*sched).contexts[i]` vs `[j]`,
the per-phase re-acquisition in `ipc_recv_and_yield` — is Miri-clean
on first try. T-006/T-007's paper argument holds under the Stacked
Borrows runtime.

Limitations (captured in the report): BSP is not tested under Miri
(no_std + no_main host-build issue, same as llvm-cov); Miri does not
observe optimizer rewrites and is not preemption-aware. Tree Borrows
may surface more patterns when we adopt it.

Recommendation: add `cargo +nightly miri test` to the CI matrix
(T-R6 / future K3-7) — Miri regression is a hard stop.

Files:
- docs/analysis/reports/2026-04-23-miri-validation.md — report
- kernel/src/sched/mod.rs — test-helper pointer-derivation fix

Refs: ADR-0021, UNSAFE-2026-0014
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Glossary pass after Phase A and B0's T-006/T-007 landed. Added 12
entries for terms that now appear throughout the code and docs but
were missing from docs/glossary.md:

- Arena, Generation tag — ADR-0016 kernel-object storage
- CDT (Capability Derivation Tree) — ADR-0014 / ADR-0023 (pending)
- Capability rights (CapRights), Capability transfer — ADR-0014 / ADR-0017
- Cooperative scheduling, Ready queue — ADR-0019
- Rendezvous IPC, Notification — ADR-0017
- Handle (typed) — disambiguates from CapHandle
- Stacked Borrows, Miri, StaticCell, UnsafeCell — the Rust-aliasing
  vocabulary we now use actively after T-006 (ADR-0021) and the
  R3 miri validation pass (commit ff2aea1)

Dropped the stale "Umbra (Latin)" entry: it was the etymology of the
original Umbrix name. Per the 2026-04-22 rename (commit 5d7cc87), Tyrne
is a clean-slate invented name with no shadow/perimeter motif — the
entry was misleading and is removed.

Also fixed a minor currency issue in the Trust boundary entry
("[architecture/security-model.md] (planned)" → plain link; that doc
exists as of commit de66d68).

Entry count: 24 → 35.
No code changes. No tests affected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
R2 coverage baseline and R3 miri validation both produced gap lists
for T-011. This commit opens T-011 with scope expanded to bundle:

(a) Phase A code-review §Test coverage items (ReceiverTableFull
    assertion with cap retention; slot-reuse with pending transfer cap).
(b) T-007's deferred follow-up (ipc_send_and_yield three-case
    coverage — Delivered+unblock, Enqueued no-yield, Err propagation
    — with the same state-restore assertion T-007 applied to
    ipc_recv_and_yield).
(c) R2 coverage baseline routings:
    - sched::start() body uncovered → extract start_prelude helper,
      test directly (small refactor, no behaviour change).
    - cap/table.rs 40 uncovered error-return branches → five targeted
      tests covering the most-reached paths.
(d) R2 + R3 re-runs post-landing: sched/mod.rs regions ≥ 90 %,
    workspace regions ≥ 96 %, miri clean.

Status: Draft. Will move to In Progress only after T-006 and T-007
are promoted to Done, since T-011 writes tests against the final
shape of code those two tasks settled.

No code changes in this commit; only the task file + phase-b task
index + phase-b.md roadmap-row update.

Refs: ADR-0017, ADR-0019, ADR-0021, ADR-0022, T-007
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First external CI gate for Tyrne. Mirrors the local workflow every
contributor runs before opening a PR:

Jobs (all ubuntu-latest, Cargo-cached):

1. lint-and-host-test (stable, ~2 min) — cargo fmt --check,
   cargo host-clippy, cargo host-test. Fast lane.
2. kernel-build (stable + aarch64-unknown-none, ~1 min) — cargo
   kernel-build and cargo kernel-clippy. Ensures the bare-metal
   BSP keeps compiling.
3. miri (nightly, ~10–15 min) — cargo +nightly miri test
   --workspace --exclude tyrne-bsp-qemu-virt. A Stacked Borrows
   regression is a hard stop per ADR-0021 / UNSAFE-2026-0014;
   this job is a direct gate on the R3 validation holding.
4. coverage (nightly + cargo-llvm-cov, ~3–5 min) — informational
   only today (continue-on-error: true). After T-011 lands and
   the workspace settles around its post-gap-fill shape, flip
   to enforce a floor.

Triggers: every push and PR targeting main or development.
Concurrent runs on the same branch cancel each other so only
the latest commit's verdict matters.

tyrne-bsp-qemu-virt is excluded from miri and coverage for the
same reason llvm-cov found locally: no_std + no_main + panic
handler conflicts with std when built for the host target.
BSP-side CI gating needs QEMU automation and is a T-009
follow-up.

Files:
- .github/workflows/ci.yml — pipeline definition.
- docs/guides/ci.md — operator guide: what runs, when, how to
  mirror locally, how to add a new check, when coverage
  starts gating, nightly pin procedure.
- docs/guides/README.md — index updated.

This closes R6 in the 2026-04-23 retrospective pass:
  R1 audit cross-check (c25f8c8)
  R2 coverage baseline (453ab1e)
  R3 miri validation (ff2aea1)
  R4 glossary refresh (25a63fb)
  R5 T-011 open (bf882ca)
  R6 CI skeleton (this commit)

The T-006 mini-retro's "yatayı kalınlaştır" / widen-the-horizontal
recommendation — first external review gate — is now a real
running pipeline. First push that lands on GitHub will exercise it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Sorry @cemililik, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@cemililik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 29 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 10 minutes and 29 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: 0125c644-8c9c-4c75-a5b3-6bae329dc765

📥 Commits

Reviewing files that changed from the base of the PR and between 5502d4e and 330e998.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (132)
  • .cargo/config.toml
  • .claude/skills/README.md
  • .claude/skills/add-bsp/SKILL.md
  • .claude/skills/add-dependency/SKILL.md
  • .claude/skills/justify-unsafe/SKILL.md
  • .claude/skills/perform-code-review/SKILL.md
  • .claude/skills/propose-standard-change/SKILL.md
  • .claude/skills/write-adr/SKILL.md
  • .claude/skills/write-architecture-doc/SKILL.md
  • .github/workflows/ci.yml
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • CONTRIBUTING.md
  • Cargo.toml
  • LICENSE
  • NOTICE
  • README.md
  • SECURITY.md
  • bsp-qemu-virt/Cargo.toml
  • bsp-qemu-virt/build.rs
  • bsp-qemu-virt/linker.ld
  • bsp-qemu-virt/src/console.rs
  • bsp-qemu-virt/src/cpu.rs
  • bsp-qemu-virt/src/main.rs
  • clippy.toml
  • docs/README.md
  • docs/analysis/reports/2026-04-23-coverage-baseline.md
  • docs/analysis/reports/2026-04-23-miri-validation.md
  • docs/analysis/reviews/README.md
  • docs/analysis/reviews/business-reviews/2026-04-21-A6-completion.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/2026-04-21-A6-baseline.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-001-capability-table-foundation.md
  • docs/analysis/tasks/phase-a/T-002-kernel-object-storage.md
  • docs/analysis/tasks/phase-a/T-003-ipc-primitives.md
  • docs/analysis/tasks/phase-a/T-004-cooperative-scheduler.md
  • docs/analysis/tasks/phase-a/T-005-two-task-ipc-demo.md
  • docs/analysis/tasks/phase-b/README.md
  • docs/analysis/tasks/phase-b/T-006-raw-pointer-scheduler-api.md
  • docs/analysis/tasks/phase-b/T-007-idle-task-typed-deadlock.md
  • docs/analysis/tasks/phase-b/T-011-missing-tests-bundle.md
  • docs/analysis/tasks/phase-j/README.md
  • docs/architecture/README.md
  • docs/architecture/boot.md
  • docs/architecture/hal.md
  • docs/architecture/overview.md
  • docs/architecture/security-model.md
  • docs/audits/unsafe-log.md
  • docs/decisions/0001-microkernel-architecture.md
  • docs/decisions/0002-implementation-language-rust.md
  • docs/decisions/0003-license-apache-2.md
  • docs/decisions/0004-target-platforms.md
  • docs/decisions/0005-documentation-language-english.md
  • docs/decisions/0006-workspace-layout.md
  • docs/decisions/0007-console-trait.md
  • docs/decisions/0009-mmu-trait.md
  • docs/decisions/0012-boot-flow-qemu-virt.md
  • docs/decisions/0013-roadmap-and-planning.md
  • docs/decisions/0014-capability-representation.md
  • docs/decisions/0015-ai-integration-stance.md
  • docs/decisions/0016-kernel-object-storage.md
  • docs/decisions/0017-ipc-primitive-set.md
  • docs/decisions/0018-badge-scheme-and-reply-recv-deferral.md
  • docs/decisions/0019-scheduler-shape.md
  • docs/decisions/0020-cpu-trait-v2-context-switch.md
  • docs/decisions/0021-raw-pointer-scheduler-ipc-bridge.md
  • docs/decisions/0022-idle-task-and-typed-scheduler-deadlock.md
  • docs/decisions/README.md
  • docs/glossary.md
  • docs/guides/README.md
  • docs/guides/ci.md
  • docs/guides/run-under-qemu.md
  • docs/guides/two-task-demo.md
  • docs/roadmap/README.md
  • docs/roadmap/current.md
  • docs/roadmap/phases/README.md
  • docs/roadmap/phases/phase-a.md
  • docs/roadmap/phases/phase-b.md
  • docs/roadmap/phases/phase-c.md
  • docs/roadmap/phases/phase-d.md
  • docs/roadmap/phases/phase-e.md
  • docs/roadmap/phases/phase-f.md
  • docs/roadmap/phases/phase-g.md
  • docs/roadmap/phases/phase-h.md
  • docs/roadmap/phases/phase-i.md
  • docs/roadmap/phases/phase-j.md
  • docs/standards/README.md
  • docs/standards/architectural-principles.md
  • docs/standards/code-style.md
  • docs/standards/commit-style.md
  • docs/standards/documentation-style.md
  • docs/standards/error-handling.md
  • docs/standards/infrastructure.md
  • docs/standards/localization.md
  • docs/standards/logging-and-observability.md
  • docs/standards/release.md
  • docs/standards/testing.md
  • docs/standards/unsafe-policy.md
  • hal/Cargo.toml
  • hal/src/console.rs
  • hal/src/context_switch.rs
  • hal/src/cpu.rs
  • hal/src/irq_controller.rs
  • hal/src/lib.rs
  • hal/src/mmu.rs
  • hal/src/timer.rs
  • kernel/Cargo.toml
  • kernel/src/cap/mod.rs
  • kernel/src/cap/rights.rs
  • kernel/src/cap/table.rs
  • kernel/src/ipc/mod.rs
  • kernel/src/lib.rs
  • kernel/src/obj/arena.rs
  • kernel/src/obj/endpoint.rs
  • kernel/src/obj/mod.rs
  • kernel/src/obj/notification.rs
  • kernel/src/obj/task.rs
  • kernel/src/sched/mod.rs
  • rust-toolchain.toml
  • rustfmt.toml
  • test-hal/Cargo.toml
  • test-hal/src/console.rs
  • test-hal/src/cpu.rs
  • test-hal/src/irq_controller.rs
  • test-hal/src/lib.rs
  • test-hal/src/mmu.rs
  • test-hal/src/timer.rs
  • tools/run-qemu.sh
✨ 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.

CI (R6 fast lane) caught three rustfmt diffs in the T-007 / T-011
test-module helpers:

- setup_single_task_with_recv_cap call site reflowed to one-arg-
  per-line block form.
- ipc_recv_and_yield two-test call sites collapsed into single-line
  form now that each argument is a short identifier.
- matches! arm in the assert! collapsed to single-line form.

Formatting only; no behaviour change. 77 kernel + 34 test-hal = 111
host tests remain green; miri remains clean.

This is the first real gate the just-landed CI pipeline has produced
— exactly the kind of mechanical mismatch that auto-fmt should catch
before review rather than clogging review attention. Worth noting:
had the pipeline existed before T-007 landed, this diff would have
surfaced on that PR, not two commits later.

Refs: R6 CI pipeline (479e81e)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

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

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 executes a project-wide rebranding from 'Umbrix' to 'Tyrne,' updating all documentation, crate names, and source code references. It also establishes a baseline for host-test coverage and Miri validation, introduces a new task for test hygiene, and adds a guide for the CI pipeline. The review identified a technical inconsistency in the TaskStack::top implementation where a mutable reference was being implicitly materialized despite safety comments claiming otherwise; a suggestion was provided to use direct pointer casting to strictly adhere to the project's aliasing discipline.

Comment thread bsp-qemu-virt/src/main.rs Outdated
Comment on lines 149 to 160
// SAFETY: `self.0.get()` returns `*mut [u8; 4096]` from the
// UnsafeCell; dereferencing it is sound because the caller's
// `# Safety` contract says the TaskStack outlives every task using
// it, and single-core cooperative scheduling ensures no
// concurrent access to the same stack. `add(4096)` is the
// one-past-end sentinel — pointer arithmetic, not a dereference
// beyond the allocation. Rejected alternatives: safe slice
// indexing (`&self.0[4096..]`) cannot produce a one-past-end raw
// pointer without materialising a `&mut [u8]`, which would
// violate ADR-0021 by carrying a live `&mut` into task setup.
// Audit: UNSAFE-2026-0011.
unsafe { (*self.0.get()).as_mut_ptr().add(4096) }
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 implementation of top() currently materializes a &mut [u8; 4096] reference through the call to as_mut_ptr(). This contradicts the SAFETY comment's claim that it avoids materializing a &mut [u8] to comply with ADR-0021's aliasing discipline.

Using cast().add() instead of (*ptr).as_mut_ptr().add() avoids the implicit dereference and borrow, truly satisfying the stated safety invariant.

Suggested change
// SAFETY: `self.0.get()` returns `*mut [u8; 4096]` from the
// UnsafeCell; dereferencing it is sound because the caller's
// `# Safety` contract says the TaskStack outlives every task using
// it, and single-core cooperative scheduling ensures no
// concurrent access to the same stack. `add(4096)` is the
// one-past-end sentinel — pointer arithmetic, not a dereference
// beyond the allocation. Rejected alternatives: safe slice
// indexing (`&self.0[4096..]`) cannot produce a one-past-end raw
// pointer without materialising a `&mut [u8]`, which would
// violate ADR-0021 by carrying a live `&mut` into task setup.
// Audit: UNSAFE-2026-0011.
unsafe { (*self.0.get()).as_mut_ptr().add(4096) }
// SAFETY: self.0.get() returns *mut [u8; 4096] from the
// UnsafeCell; obtaining a raw pointer to the interior is sound
// because the caller's # Safety contract says the TaskStack
// outlives every task using it, and single-core cooperative
// scheduling ensures no concurrent access to the same stack.
// add(4096) is the one-past-end sentinel — pointer arithmetic,
// not a dereference beyond the allocation. Rejected alternatives:
// safe slice indexing (&self.0[4096..]) or as_mut_ptr()
// cannot produce a one-past-end raw pointer without materialising
// a &mut [u8], which would violate ADR-0021.
// Audit: UNSAFE-2026-0011.
unsafe { self.0.get().cast::<u8>().add(4096) }

cemililik and others added 2 commits April 23, 2026 01:26
Second-read of the six-commit 2026-04-23 retrospective arc
(c25f8c8…5ba0d44) surfaced one real policy violation and several
worth-fixing-now clarifications. Two of the reviewer's "Yüksek"
items were false alarms on verification and needed no change.

Accepted findings:

1. unsafe-policy §3 append-only violation. R1's commit c25f8c8
   edited UNSAFE-2026-0011's original body in place to extend it to
   TaskStack::top, which the log's own "Entries are append-only"
   rule forbids. Fix:
   - Reverted UNSAFE-2026-0011's original body to its pre-R1 shape.
   - Appended a dated "Amendment (2026-04-23, commit TBD):" block
     with the top() location / operation / invariants / rejected
     alternatives — the same content R1 moved, now clearly tagged
     as a post-hoc extension rather than a rewrite.
   - Formalised the pattern in unsafe-log.md's header + unsafe-
     policy.md §3: status-change and dated Amendment blocks are
     the two permitted post-hoc update forms; in-place body edits
     remain a policy violation reviewers must reject.
   - Condensed the in-code SAFETY comment on TaskStack::top to
     reference the Amendment rather than duplicating its rationale,
     closing a drift surface the verbose form would have opened.

2. CI: cargo-llvm-cov reinstall every run. The coverage job did
   not cache ~/.cargo/bin, so `cargo install --locked
   cargo-llvm-cov` rebuilt the binary on every push (~1–2 min).
   Added ~/.cargo/bin to every job's cache paths and made the
   install step idempotent-by-comment.

3. CI: rolling nightly flake risk. Miri and coverage jobs pulled
   floating `nightly`, so a public-channel regression would break
   master with no diff to blame. Introduced NIGHTLY_PIN env var
   (`nightly-2026-01-15`) at the workflow top; both jobs use it.
   Cache keys include the pin so a bump invalidates the cache
   cleanly. docs/guides/ci.md "Nightly pinning" section rewritten
   with a concrete bump procedure.

4. docs/guides/ci.md: `continue-on-error: true` interacts
   surprisingly with branch-protection (GitHub renders neutral as
   non-passing, blocking merges when the job is required). Added
   a "Branch protection and continue-on-error" section spelling
   out which jobs to add to required-checks today (lint-and-
   host-test, kernel-build, miri) and which to leave out
   (coverage, until it flips to enforcing post-T-011).

5. T-011 AC #2 debug_assert mechanic. The original wording
   ("confirms the assertion's dev-mode behaviour") was
   underspecified; a test that triggers a debug_assert! panics,
   which needs explicit `#[should_panic]` + `#[cfg(debug_assertions)]`
   scaffolding. Replaced AC #2 with a paired-test spec: one
   should-panic test for the cap-drop case, one must-not-panic
   test for the no-cap case, both exercising
   `reset_if_stale_generation` by name. Protects the assert from
   rotting into either a blanket panic or a no-op.

6. T-011 references to T-009 softened. T-009 has a reserved
   slot in phase-b.md but no task file; references to it in
   T-011's Out-of-scope section now link to phase-b.md and note
   the "not yet opened" state explicitly.

Rejected findings (verified, no change needed):

- "`reset_if_stale_generation` doesn't exist, it's still
  `sync_generation`." It exists at ipc/mod.rs:211; the rename
  landed in 7eaa10a.
- "`debug_assert!` wasn't added by 7eaa10a." It was; it's at
  ipc/mod.rs:215 (`git show 7eaa10a -- kernel/src/ipc/mod.rs`
  confirms).
- "BSP source still has 'umbrix:' strings." `git ls-files | xargs
  grep -ni umbrix` returns empty; the rename in 5d7cc87 was
  complete. `cargo pkgid -p tyrne-bsp-qemu-virt` succeeds, so the
  CI `--exclude` argument is correct.

Verification: 77 kernel + 34 test-hal = 111 host tests green;
cargo fmt / host-clippy / kernel-clippy / kernel-build clean; YAML
workflow parses cleanly.

Refs: unsafe-policy §3, ADR-0021, R6 CI pipeline
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Amendment block landed in d25a185 with "commit TBD" because the
SHA is not known until commit time (chicken-and-egg). This follow-up
replaces the placeholder with the actual SHA.

Per the newly formalised policy (unsafe-policy.md §3, landed in
d25a185 itself), this edit is permitted: the Amendment block's SHA
slot is part of the block's required header, equivalent to filling
in a dated form field. The Amendment's *content* (location,
operation, invariants, rejected alternatives) is not touched.

When future Amendments land, prefer writing the correct SHA on
first landing by using `git commit --amend` after the commit goes
in, or accept "TBD" and back-fill in a one-character follow-up like
this one. Both patterns preserve the append-only story.

Refs: unsafe-policy §3
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cemililik cemililik merged commit 061afc2 into main Apr 22, 2026
10 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 29, 2026
…0036 (B5 review finding)

The B5 syscall-boundary security review (this PR) re-surfaced the one finding
actionable outside a phase gate: security-model.md §threat-model #7 + §Open
questions still described QEMU `virt` as "launched with SMMUv3 and used in CI to
catch driver misbehaviour" — a live contradiction with Accepted ADR-0036 (QEMU
`virt` is GICv2 / no-IOMMU in v1; SMMUv3 is exposed only under an explicit
`iommu=smmuv3` launch Tyrne does not use). It was N/A as a v1 *defect* (no
bus-master driver exists, so the DMA boundary is inactive) but a stale doc claim,
forward-flagged since the 2026-05-28 B4 closure.

Reconciled conservatively: both sentences now state the v1 GICv2/no-IOMMU reality,
point at ADR-0036, and reframe the SMMU-in-CI gate as a future IOMMU-equipped-target
(Jetson Orin) item — preserving the model's IOMMU intent, correcting only the
stale QEMU-`virt`-has-SMMUv3 claim. The review doc's §8 + forward-flags are updated
to mark this RECONCILED (no longer carried forward). All other review forward-flags
are correctly phase-deferred (B6 carry-forward gates / Phase-E fault containment /
preemption-time ipc_send hardening / B5+ cap_map rights ADR) — no action now.

Refs: ADR-0013, ADR-0036
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request May 29, 2026
…estone B5) (#35)

* docs(analysis): security-review B5-syscall-boundary

Standalone consolidated security pass over the B5 syscall boundary (T-020 IpcError
split + Capability/CapObject Debug redaction K3-9; T-021 EL0→EL1 SVC dispatch),
merged via PR #34 (f98e1af). Performed with a fresh 8-axis checklist after the
PR's three code-review rounds + the adversarial multi-agent pass.

Verdict: **Approve.** All eight applicable axes pass (cryptography N/A). The
dispatcher is panic-free on every register-supplied input; every object-naming
syscall is capability-gated before any effect (console_write on the new
debug-console cap, closing the ambient-authority slip caught before ADR Accept);
copy-from/to-user never dereferences an unvalidated user pointer, with the
soundness basis honestly recorded as the user/kernel disjointness invariant
(an empirical Miri probe disproved an earlier "overlap-tolerant" over-claim —
overlap is UB regardless of the copy primitive via the &mut/& borrow exclusivity);
T-020's Debug redaction closes the K3-9 secrets-leak path exactly where B5 first
creates a userspace-reachable log channel. Both new unsafe entries
(UNSAFE-2026-0029 trampoline asm, UNSAFE-2026-0030 copy-user) are policy-conformant;
0029 carries the required second-reviewer sign-off. Gates: host-test 240,
test --release green, miri --workspace clean (0 UB), QEMU +0x200 proxy round-trip
byte-stable with no new fault class.

B5 builds the boundary mechanism but the real EL0 +0x400 transition is B6; three
B6 carry-forward gates (per-task console_write window + per-page translation;
SP_EL1 init; SYSCALL_STUB_TABLE → current-task table) are tracked in phase-b.md
§B6. This pass can serve as the security leg of the eventual B5 closure trio
(business + performance legs deferred — "security review first").

Refs: ADR-0013, ADR-0030, ADR-0031, ADR-0014
Security-Review: @cemililik (+ Claude Opus 4.8 agent)
Audit: UNSAFE-2026-0029, UNSAFE-2026-0030
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(analysis): reconcile security-model.md SMMUv3-CI claim with ADR-0036 (B5 review finding)

The B5 syscall-boundary security review (this PR) re-surfaced the one finding
actionable outside a phase gate: security-model.md §threat-model #7 + §Open
questions still described QEMU `virt` as "launched with SMMUv3 and used in CI to
catch driver misbehaviour" — a live contradiction with Accepted ADR-0036 (QEMU
`virt` is GICv2 / no-IOMMU in v1; SMMUv3 is exposed only under an explicit
`iommu=smmuv3` launch Tyrne does not use). It was N/A as a v1 *defect* (no
bus-master driver exists, so the DMA boundary is inactive) but a stale doc claim,
forward-flagged since the 2026-05-28 B4 closure.

Reconciled conservatively: both sentences now state the v1 GICv2/no-IOMMU reality,
point at ADR-0036, and reframe the SMMU-in-CI gate as a future IOMMU-equipped-target
(Jetson Orin) item — preserving the model's IOMMU intent, correcting only the
stale QEMU-`virt`-has-SMMUv3 claim. The review doc's §8 + forward-flags are updated
to mark this RECONCILED (no longer carried forward). All other review forward-flags
are correctly phase-deferred (B6 carry-forward gates / Phase-E fault containment /
preemption-time ipc_send hardening / B5+ cap_map rights ADR) — no action now.

Refs: ADR-0013, ADR-0036
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(analysis): performance-review B5-closure

B5 closure performance baseline — the performance leg of the B5 syscall-boundary
closure trio. Re-baseline of kernel footprint + boot-to-end timing after T-020 +
T-021 (PR #34, f98e1af) versus the 2026-05-28 B4 closure baseline.

Footprint (release): .text 34,648 (+1,524) / .rodata 4,856 (+296) / .bss 50,592
(+2,272) = ~88.0 KiB (+4.76 %) — the smallest non-refactor .text growth in Phase
B (the syscall boundary is a thin validator/dispatch layer). Tests 339 (43 hal +
240 kernel + 53 test-hal + 3 doc; +53 kernel), miri clean (0 UB, run locally).
Release harness band p10/p50/p90 = 17.645 / 20.300 / 24.706 ms.

Verdict: baseline, no proposal. The cycle's decisive measurement was a same-host
back-to-back control (the B4 binary 3ab029f rebuilt + re-measured this session):
it proves the ~+2.9 ms p10/p50 delta vs B4 is REAL B5 code (the boot SVC-smoke —
2 exception round-trips + cold TCG translation), not host jitter, correcting an
initial mis-read of the noisier raw band. One-time-at-boot, ~us on real hardware.
The control also shows the QEMU-TCG harness is nearing its resolving floor for
small milestones (per-milestone signal ~ session jitter). Adds the harness report
docs/analysis/reports/perf-baseline-2026-05-29-B5-closure.md and the README index
row.

Refs: ADR-0013, ADR-0030, ADR-0031
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(roadmap): business-review B5-closure

B5 closure retrospective — the business leg of the B5 syscall-boundary closure
trio — plus the roadmap forward motion it drives. Formally closes Milestone B5
(Syscall boundary): T-020 (IpcError taxonomy split + Capability/CapObject Debug
redaction) + T-021 (EL0 to EL1 SVC dispatch) merged via PR #34 (f98e1af);
ADR-0030 + ADR-0031 Accepted.

What landed (canonical metrics, reproduced live at afeed10): 339 host tests
(+53 kernel) incl. local miri 0 UB; release ELF ~88.0 KiB (+4.76 % vs B4);
release smoke clean to "all tasks complete" (the release trace itself proves the
console_write debug-gate — status=0x1 in release); the debug smoke shows the full
console_write SVC round-trip (status=0x0, bytes=63); -d = 712/776 PL011 + 2
expected SVC exceptions (EL1 to EL1, ESR 0x15, clean ERET), zero new fault class;
audit log 30 entries (29 Active) — UNSAFE-2026-0029/0030.

What we learned: the pure-Rust (T-020) / hardware-boundary (T-021) split per
CLAUDE.md section 6 let the most security-sensitive milestone land safely in one
calendar day without skipping rigor; an adversarial pass + Miri corrected a real
copy-user soundness over-claim (disjointness, not the copy primitive, is the
basis); a same-host perf control corrected a host-jitter mis-attribution; ABI
front-loading kept the syscall numbers a decision, not an accident.

Side-effects: current.md banner + Pathfinder flipped to B5-closed / B6-next;
phase-b.md section B5 status -> Closed; test-count drift (236/240 mid-arc -> live
339) reconciled; business-reviews README index row added. Next: B6 (first
userspace "hello") — the deferred task_create_from_image bridge + the 3 T-021
carry-forward gates + the ADR-0033 high-half opening; B6's review is the Phase B
retrospective.

Refs: ADR-0013, ADR-0030, ADR-0031, ADR-0017, ADR-0033
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(roadmap): pre-B6 prep — reconcile B5-done status + B6 opening sequence

Pre-B6 documentation preparation on the B5-closure branch (rides in PR #35),
done before B6 development starts on its own branch off main. Docs-only.

(1) B5-done status reconcile (drift sweep). With B5 closed, several live docs
still treated the syscall boundary as future/next:
- CLAUDE.md: "the syscall ABI and first userspace task are next" -> the syscall
  boundary is done; the first EL0 task is next.
- README.md status table: "Syscall ABI + EL0 entry | Next - Phase B5" -> split
  into "Syscall ABI + dispatcher = Done (B5)" + "First userspace hello (EL0) =
  Next (B6)".
- phase-b ADR ledger: ADR-0030 / ADR-0031 marked Accepted 2026-05-29; ADR-0033 /
  ADR-0034 triggers corrected from B5/B5+ to B6 (B5 closed via the SVC proxy
  without surfacing the per-task TTBR0 swap, so the trigger is now B6).
- architecture docs (task-loader / memory-management / boot): "ADR-0033 gated on
  B5 surfacing per-task TTBR0 swap" -> B6, and "until B5 adds a per-task context
  surface" -> B6 — these would have misled a B6 dev about which milestone owns
  the EL0 context + high-half work.

(2) B6 opening sequence & prerequisites — the careful B6 plan, made durable in
phase-b.md section B6. States the gating prerequisite (the kernel must stay
reachable from every task's active translation, else an EL0 SVC vector fetch
translation-faults), the ADRs that open B6 (ADR-0033 kernel-in-every-AS + the
EL0-task-context decision + optional ADR-0034), and the dependency-ordered task
sequence: ADR-0033 impl -> EL0 context -> task_create_from_image -> the 3 T-021
carry-forward gates -> tyrne-user + userland/hello -> wire-up + EL0 round-trip
smoke -> Phase B retrospective. Decisions remain open for their ADRs; this fixes
only the order + rationale.

All links resolve; docs-only, no kernel changes.

Refs: ADR-0013, ADR-0027, ADR-0030, ADR-0031, ADR-0033
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: PR #35 review-round — fix assert quote, ADR-0033 link, ADR-0034 table pipe

Three review findings on the B5 closure docs, each verified against the source:

- abi.rs assert quote (security review section 1): the doc quoted
  assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX)) but the actual
  abi.rs:42 uses `as u64` casts — (((u32::MAX as u64) << 16) | (u16::MAX as u64))
  (without them the shift overflows in u32 arithmetic). Quote corrected to match.

- ADR-0033 link (security review section 8): the label said "ADR-0033" but the
  link targeted 0027-kernel-virtual-memory-layout.md (a mismatch). ADR-0033
  (high-half migration) is genuinely the right concept — 0027 only reserves the
  slot — so rather than relabel to ADR-0027 (which would misattribute high-half
  to 0027), ADR-0033 is now plain text (matching the unlinked ADR-0034 in the
  same sentence) with a correctly-labeled "reserved in ADR-0027" cross-reference.

- ADR-0034 ledger row (phase-b.md): the inline code USER|EXECUTE (introduced in
  the pre-B6 prep commit) had an unescaped pipe, splitting the table row into
  five columns; escaped to USER\|EXECUTE. All 14 ledger rows now have 4 columns.

Validated: assert quote matches abi.rs:42 verbatim; all links resolve; every
ADR-ledger row is well-formed (5 delimiters = 4 columns). Docs-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (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