Skip to content

Latest commit

 

History

History
158 lines (107 loc) · 24.4 KB

File metadata and controls

158 lines (107 loc) · 24.4 KB

Business review 2026-05-07 — B1 closure retrospective (post-T-014)

  • Trigger: milestone-completion. Phase B / Milestone B1 ("Drop to EL1 + exception infrastructure") truly closed via T-014's PR #15 merge into main on 2026-05-07. Replaces the 2026-04-28-B1-closure.md trio's load-bearing role: that trio approved B1 implementation-complete based on host-test + miri + paper-review evidence, but the maintainer-side QEMU smoke (still Pending QEMU smoke verification on UNSAFE-2026-0019/0020/0021 at the time) had not run. When the maintainer ran it on 2026-05-06, the smoke surfaced an idle-dispatch regression that B1's "Done" claim could not survive. T-014 fixed the regression; this retrospective records what B1 actually was once smoke-verified end-to-end.
  • Scope: the B1-reopen → T-014 → comprehensive-review → α/β/γ-doc-polish arc. The 2026-04-28 implementation arc (T-013 + T-012) is covered by its own retrospective and is preserved unchanged as historical record.
  • Period: 2026-04-28 (PR #10 merge — original B1 implementation-complete) → 2026-05-07 (today; PR #15 merged; T-014 verified; B1 truly closed).
  • Participants: @cemililik (+ Claude Opus 4.7 agent as scribe; ten parallel multi-agent comprehensive code-review run on 2026-05-06; bot-driven review-rounds on PRs #12 / #13 / #14 / #15 from coderabbitai-bot, gemini-code-assist-bot, sourcery-ai-bot).

Canonical source for B1 closure metrics. This artefact + the security review + the performance baseline are the source of truth for B1's closing numbers (test counts, ELF section sizes, smoke trace, audit-log Amendments). Every other location that mentions B1 metrics (current.md, phase-b.md, T-014 review-history) is a summary at its layer of abstraction and should be read alongside this trio rather than as an independent record. When the metrics drift, the trio is what gets corrected first; downstream summaries follow. Per sourcery-ai PR #16 review feedback.


What landed

Tasks promoted to Done

Task Promoted Description
T-014 2026-05-07 (PR #15 merge) Idle dispatch via separate fallback slot per ADR-0026. Refactored Scheduler<C> to add idle: Option<TaskHandle> field + register_idle raw-pointer free function; updated the three dispatch sites (start_prelude, yield_now, ipc_recv_and_yield) to consult idle only when s.ready.dequeue() returns None; switched bsp-qemu-virt::kernel_entry from add_task(idle_entry, ...) to register_idle(...). Three new host tests including the regression guard (unblock_after_yield_dispatches_unblocked_receiver_not_idle). Audit: UNSAFE-2026-0014 gained the register_idle Amendment; UNSAFE-2026-0019/0020 gained post-T-014 smoke Amendments confirming setup-site sustained-execution under DAIF.I unmasked.

T-013 / T-012 remain Done (promoted by the 2026-04-28 trio); their work was inherited unchanged through B1-reopen.

ADRs

ADR Action Notes
ADR-0026 — Idle dispatch via separate fallback slot Accepted 2026-05-06 (Proposed → Accepted same-day after careful re-read per ADR-0025 §Revision notes) Supersedes ADR-0022's idle-task-location axis only (Option A → Option B); ADR-0022's typed-error axis (Option G — SchedError::Deadlock + IpcError::PendingAfterResume + start's panic kept) stands. Repurposes the previously reserved-but-unused ADR-0026 slot (originally penciled for T-012 vector-table design which T-012 absorbed without writing it). The ADR includes a queue-state simulation table that ADR-0022 lacked — the discipline gap is the single most important lesson from this arc (see What we learned below).
ADR-0022 Status flipped to Superseded by 0026 (idle-task-location axis only; typed-error axis stands) Body preserved unmodified per ADR-0025 §Rule 2 (append-only); a top-of-body callout points forward to ADR-0026 with the partial-supersession scope.

Pull requests merged into main

PR Title Scope
#12 B1 smoke regression: ADR-0026 supersedes ADR-0022 Option A; T-014 fixes idle dispatch Phase 1 + 2 + 3 of the smoke-regression fix arc: mini-retro, ADR-0026, T-014 implementation, post-T-014 audit Amendments. Includes 1 review-fix sweep commit (8/10 findings applied).
#13 Doc-fix sweep — close 7 Track-E blockers + non-blocker doc drift (comprehensive review follow-up) α PR. 13 doc files. Closes the 7 Track-E doc-drift blockers (GIC v2/v3, scheduler idle path, hal Timer status, security-model DAIF question, glossary ADR-0023 dead link) + non-blocker root-doc / standards / guides / infra cluster. Includes 1 review-fix sweep (7/8 findings applied; 1 corrected interpretation).
#14 Doc-fix sweep — repo-wide TyrneOS → Tyrne URL rename + Yüksek → High localization β PR. 31 files (+72/-72). Bulk mechanical sweep. Closes Track J §J-NB1 + §J-NB2. Includes 1 review-fix sweep closing 2/3 findings (third was an architectural suggestion deferred).
#15 Code-side polish — close kernel/HAL/BSP non-blockers from comprehensive review γ PR. 11 source files. Closes Track A/B/F/G/I non-blocker tightening (const-block migration, SchedQueue<0> assert, ContextSwitch +Send+Sync, Aarch64TaskContext size guard, irq_entry _frame doc, vectors.s cross-ref, kernel_entry "no defensive loop" rationale, 3 obj-test lint-allow alignment, cap_revoke size-proof comment). Includes 1 review-fix sweep closing 4/4 findings (3 line-ref drops + process-metadata trim).

Audit-log surface

  • UNSAFE-2026-0012: Removed (commit f9b72f8 from B0 era; verified clean by Track C).
  • UNSAFE-2026-0014: third Amendment added 2026-05-06 (T-014 / ADR-0026): names register_idle as the new sanctioned site for the same momentary-&mut Scheduler<C> pattern. Discipline now extends across add_task, start_prelude, register_idle, the three IPC bridge functions, and the placeholder irq_entry site.
  • UNSAFE-2026-0019 / 0020: gained 2026-05-06 partial-verification Amendments (initial smoke run reached the setup sites — GIC init, MSR VBAR_EL1, MSR DAIFClr); then 2026-05-06 post-T-014 smoke Amendments reaffirming the setup-site verification under sustained execution (~6.3 ms boot-to-end with DAIF.I unmasked; -d int,unimp,guest_errors empty). The IRQ-take + dispatch path itself remains unverified because v1's demo never arms a deadline; Pending QEMU smoke verification status note persists.
  • UNSAFE-2026-0021: gained 2026-05-06 no-verification Amendment (timer-write site is unreachable in the v1 demo; clearance gates on a future preemption-using task that arms a real deadline).

Test counts at B1 closure

Crate Tests Δ from 2026-04-28
tyrne-kernel (host) 93 +3 (T-014's three new tests: register_idle_stores_handle_in_idle_slot_and_not_in_ready_queue, dispatcher_picks_idle_only_when_ready_queue_empty, unblock_after_yield_dispatches_unblocked_receiver_not_idle)
tyrne-hal (host) 25 unchanged
tyrne-test-hal (host) 34 unchanged
Total 152 / 152 +3

cargo +nightly miri test clean across all 152 tests (~20 s wall-clock). cargo fmt --check, cargo host-clippy -D warnings, cargo kernel-clippy -D warnings, cargo kernel-build all clean. QEMU smoke at HEAD e9fa019 reproduces the full demo trace through tyrne: all tasks complete (boot-to-end ~5.8–6.3 ms across runs; -d int,unimp,guest_errors empty for the entire run).

Documentation surface

  • docs/architecture/scheduler.md — body lines 11 + 73 rewritten: idle now described per ADR-0026 as a fallback slot consulted when the ready queue is empty, not as a FIFO resident; commit-hash b4ed68c references replaced with stable T-012 (Done 2026-04-28) citations. Revision notes section (added in earlier ADR-0026 work) records the supersession.
  • docs/architecture/hal.md — Mermaid box + BSP table corrected GICv3 → GICv2 (×2 sites); Timer subsection rewritten (unimplemented!() → real bodies per ADR-0010 §Revision notes).
  • docs/architecture/overview.md — BSP table GICv3 → GICv2 with one-line clarifier; "(planned)" parenthetical on HAL trait surface → "Accepted".
  • docs/architecture/security-model.md — DAIF Open question closed with citations to T-013 / ADR-0024 / UNSAFE-2026-0017.
  • docs/glossary.md — ADR-0023 dead-link replaced with prose ("see ADR-0023 (accept-deferred per Phase B0 closure)").
  • docs/decisions/template.md — Status enum comment block now lists all five recognised values (Proposed / Accepted / Deferred / Deprecated / Superseded by NNNN).
  • docs/decisions/README.md — index gained the deferred ADR-0023 row + Accepted ADR-0026 row + Superseded-by-0026 status flip on ADR-0022.
  • docs/standards/README.mdbsp-boot-checklist.md index row added.
  • docs/standards/infrastructure.md — CI required-gates marked conditional (cargo audit / cargo vet check / QEMU-smoke); §Configuration files split into Present / Planned with a code-style.md §Lints back-pointer; one-line miri-component note.
  • docs/guides/two-task-demo.md — expected-output table gained the post-T-009 tyrne: timer ready (...) and tyrne: boot-to-end elapsed = ... lines; trace prose now describes the idle fallback slot and the cooperative-spin tail accurately.
  • Root docs (README.md, CONTRIBUTING.md, SECURITY.md) refreshed for post-B1 reality (4 crates exist; kernel boots; security-model is Accepted).
  • YüksekHigh in 5 documents (T-009 user-story, B0 closure ×2, security-reviews/README, unsafe-log) per Track J §J-NB2 + ADR-0005 + localization.md.
  • 26 source/manifest files swept from cemililik/TyrneOScemililik/Tyrne per Track J §J-NB1.
  • docs/architecture/scheduler.md §Revision notes records the ADR-0026 supersession and the post-T-014 dispatch shape.

Comprehensive code review (2026-05-06)

A full-tree multi-agent review at HEAD 214052d (10 parallel tracks + pre-flight + merge agent), commissioned by the maintainer pre-smoke:

  • Verdict: Request changes — Track E (docs) returned 7 blocker-class doc-drift items; Tracks A / C / D / F / G / H / I returned Approve / Iterate; Tracks B / J returned Comment.
  • All 7 Track-E blockers + the non-blocker cluster were closed by PRs #13 (α) + #14 (β) + #15 (γ).
  • The review's plan + ten sub-artefacts + merged artefact are preserved in docs/analysis/reviews/code-reviews/2026-05-06-full-tree/ and docs/analysis/reviews/code-reviews/2026-05-06-full-tree-comprehensive.md. Track J §J-NB1's "64 stale TyrneOS URLs" and §J-NB2's "Yüksek term" are now closed by β; Track E's 7 blockers + 8 non-blockers are closed by α; Tracks A / B / F / G / I non-blockers are closed by γ. Tracks C / D / H non-blockers remain open (deferred to specific tasks per the verdict §Out-of-scope list).

What changed in the plan

  • B1's "implementation complete 2026-04-28" claim was rolled back, then refilled with verified-end-to-end content. The 2026-04-28 retro stands as the historical record of "what we believed at PR #10 merge"; this 2026-05-07 retro records "what is true post-T-014". The 2026-04-28 audit-log entries (UNSAFE-2026-0019 / 0020 / 0021) retain their Pending QEMU smoke verification status notes; their partial clearance happened today (setup sites under sustained execution); full clearance is gated on the first deadline-arming task.
  • ADR-0026 was Accepted, repurposing a reserved-but-unused slot. ADR-0026 was originally pencilled for T-012's vector-table design (which T-012 absorbed without writing the ADR). The slot is now spent on the idle-dispatch supersession of ADR-0022. phase-b.md's ADR ledger row 246 updated to reflect the repurpose.
  • B2 prep (ADR-0027) was paused and is now reactivated. The 2026-04-28 retro's Pathfinder output authorised parallel ADR-0027 drafting alongside the maintainer-side smoke. When smoke surfaced the regression, ADR-0027 drafting was paused; with B1 truly closed today, ADR-0027 (kernel virtual memory layout) becomes the next implementation thread.
  • ADR-0023 (cross-table CDT) gained a deferred-row in the index — previously the README index jumped 0022 → 0024 with no row, even though phase-b.md's ADR ledger listed it as Deferred. Both indices now agree.
  • Standards: infrastructure.md §CI-required-gates marked three gates as conditional (cargo audit / cargo vet check waiting on first extern dep; QEMU smoke waiting on a CI job). The original framing presented them as merge-blockers regardless; now they're documented as conditional. This is a process-correction without changing the policy.
  • No B-phase milestone re-shuffling. B2 (MMU activation) remains the next milestone; sub-breakdown unchanged.

What we learned

Smoke is the project's only end-to-end liveness oracle, and B0/B1 had been treating it as a checkbox

The 2026-04-28 retro's Adjustments listed maintainer-side QEMU smoke as a pre-closure work-item; PR #10 merged with that workitem still open. Same pattern at B0 closure (PR #9). For 8 days the audit log carried Pending QEMU smoke verification notes whose meaning was structurally not "we ran the smoke and it passed" but "we will eventually run the smoke". When the smoke finally ran on 2026-05-06, it instantly surfaced a regression that 149 host tests + 149 miri tests had silently passed.

The asymmetry is the lesson: 152 host tests + 152 miri tests + paper-review approval can pass a kernel that hangs at runtime in 6 seconds of QEMU. Host tests use tyrne-test-hal::FakeCpu's wait_for_interrupt which is a count += 1 no-op; miri is a memory-safety checker, not a liveness checker; paper-review (including the comprehensive review's Track A correctness pass) caught zero of the conditions. The smoke is the only oracle that exercises the full dispatch chain under realistic IRQ-source-absence conditions.

The 2026-04-28 trio's Adjustments item ("smoke runs on the maintainer's clock") was structurally insufficient as a closure gate. This retrospective reverses that framing: B1's milestone-level Done is now defined as "smoke trace pasted into the closure retrospective". The 2026-04-28 trio's audit-log clearance approach (Pending notes that "self-clear" via append-only Amendment) is fine for the audit log, but not as a milestone closure gate. Codification of "no closure-trio without recorded smoke" is the natural Adjustment for this retro to track.

ADR analysis is uncomfortable to simulate, and skipping the simulation is the most consistent failure mode of the project's ADR work

ADR-0022 §Decision outcome chose Option A (idle as a regular ready-queue resident) over Option B (idle in a dedicated Option<TaskHandle> slot). The reasoning:

"when idle yields to itself (only task ready), yield_now's existing 'only one ready task' early-return path handles the case without a context switch"

That reasoning is correct only when idle is the sole Ready task. The cooperative IPC demo's flow puts task_b-just-unblocked + task_a-just-yielded + idle-perpetually-ready into the FIFO simultaneously; round-robin then picks idle ahead of task_b. Idle's WFI waits for an IRQ that v1 never arms; the kernel hangs.

The bug is exactly what a four-row table of (queue-state-pre, action, queue-state-post) walked through unblock_receiver_on + yield_now would have surfaced before the ADR Accept. ADR-0022 didn't write that table; ADR-0026 §Decision outcome does, as the central evidence for why Option B is the correct shape. The same critique fits every multi-step state-machine ADR the project has shipped: ADR-0014 cap-derivation tree (had its bug-discoveries via riders post-Accept rather than via simulation pre-Accept), ADR-0017 IPC primitive set (same), ADR-0019 scheduler shape (same), ADR-0022 idle-location (this one).

Adjustment: extend the write-adr skill with a Simulation check item. For every multi-step state-machine ADR (capability flows, IPC handshakes, scheduler dispatch, exception entry, etc.), the body must include a 3-5 row table walking the worst-case interaction through. The simulation table is a structural discipline on the body, not a stylistic suggestion. B2 prep adopts this for ADR-0027 onwards.

The third new test (unblock_after_yield_dispatches_unblocked_receiver_not_idle) is the empirical form of ADR-0026's simulation table

T-014 added three new host tests, but the third one is the generalisable pattern: it walks the queue-state machine through the failing demo step and asserts the post-fix dispatcher routes correctly. This is a useful pattern — pairing an ADR's simulation table with a host test that mechanically replays it. Worth codifying when the next multi-step state-machine ADR comes up; for now, the pattern is a lone data point.

The comprehensive multi-agent review's blind spot was "did you actually run the program?"

Ten parallel agents ran on 2026-05-06; four of them (A kernel correctness, C security, F tests, G BSP) each had a clean shot at the demo flow. None caught the regression. Track F's §F-1 ("QEMU smoke is maintainer-only") was correctly identified but classified Non-blocking. The find was correct; the severity classification was not.

For any future full-tree review, add a Track K — Live execution whose explicit job is "boot the kernel under QEMU and trace one demo flow end-to-end". This is essentially Track F's §F-1 promoted to a track in its own right. Codification deferred until the post-fix B1 closure retro proves the structure works (this retro is that proof). Adjustment item below.

The audit-log "Pending QEMU smoke verification" pattern is load-bearing and was working as designed

UNSAFE-2026-0019 / 0020 / 0021 each carried a Pending QEMU smoke verification status note from 2026-04-28 onward. Today's smoke could not lift those notes blanket-style because the kernel hangs before any of those unsafe sites' contracts get fully exercised in production sequence (the timer's arm_deadline is never called by the demo, so UNSAFE-2026-0021's MMIO write site never fires; the GIC-CPU-interface IRQ path covered by UNSAFE-2026-0019 / 0020 is initialised but never traverses an actual interrupt). The Pending notation correctly reflected the verification gap.

The audit log's calibration is what the closure retros lost when they treated the maintainer-side workitems as "near-done formalities". The audit-log discipline is real and worth preserving as the discipline-of-record for individual unsafe claims; the closure-trio discipline needs strengthening separately.

Bot-driven review-rounds are a useful productivity multiplier when their suggestions are interpretable as structured findings, less so when they're stylistic preferences

PRs #12 / #13 / #14 / #15 each went through bot-driven review-rounds (coderabbitai, gemini-code-assist, sourcery-ai). Aggregate stats:

PR Total bot findings Applied Skipped Reason for skip
#12 10 8 2 Style nits — or().expect() simplifications losing case-comment documentation
#13 8 7 1 "Yield_now in spin tail" suggestion didn't match the actual source code
#14 3 2 1 "Switch to repo-relative paths" — architectural change, separate concern
#15 4 4 0 All applied (3 line-ref drops + 1 metadata trim)

The signal: bots are reliable on factual / mechanical findings (broken table rows, missing language tags on fenced code blocks, hardcoded line numbers, "extern dep" abbreviation drift, cd TyrneOS vs cd Tyrne). They're less reliable on architectural suggestions (gemini's start_prelude .or().expect() simplification ignored the case-comment value; sourcery's repo-relative-paths suggestion is sensible but a separate project). Discipline: read each suggestion, classify as factual-mechanical (apply) vs preference (case-by-case), reject silently when it loses context.

This is a soft adjustment for the maintainer's ongoing PR workflow rather than a process item — but worth recording as a stable observation about the cost / value of bot-driven review.

Adjustments

  • Codify "no closure-trio without recorded smoke" as a B-phase milestone-closure rule. The strict rule: a closure trio (business + security + perf) cannot promote a milestone past In Review to Done without a smoke trace pasted verbatim into the business retrospective. Trigger: amend infrastructure.md §Continuous integration and / or the conduct-review skill's master plan for business reviews.
  • Extend write-adr skill with a Simulation check. For every multi-step state-machine ADR, the body must include a 3-5 row queue-state / handshake-state / dispatch-state simulation table. Trigger: drafted alongside ADR-0027 (B2 prep) so the rule lands with its first user.
  • Add Track K — Live execution to the comprehensive-review template. Promote Track F §F-1 to a standalone live-execution track that boots the kernel under QEMU and traces one demo flow end-to-end. Trigger: when the next full-tree review is commissioned (no scheduled trigger; maintainer-initiated).
  • B2 prep — ADR-0027 (kernel virtual memory layout) drafting. Reactivated post-B1-closure; design-first applies (docs/architecture/memory-management.md lands alongside or before the implementation, mirroring T-008's scheduler.md/ipc.md and T-012's exceptions.md precedents). The ADR's Dependency chain section opens the implementation task (T-015, next free slot) per ADR-0025 §Rule 1.
  • δ — write ADR-0023 placeholder file with Status: Deferred body. decisions/README.md's deferred-row was added in α; per ADR-0025 §Rule 1, every Deferred ADR should still have a file with a body that explains the deferral conditions. This task provides the body. Trigger: opens any time before B2 prep needs to cross-reference the Deferred state from a real task.
  • δ — endpoint rollback / ipc_cancel_recv ADR. Track A non-blocker noted that ipc_recv_and_yield's Deadlock path restores scheduler state but does not reverse the endpoint's Idle → RecvWaiting transition. Benign in v1 (Deadlock is structurally unreachable), but worth a small ADR before B2 lands the first userspace-driven destroy path. Trigger: drafted alongside or before B2's first ADR-0028 (address-space data structure).
  • Track J §J-OBS1 — lift #![deny(clippy::todo)] from kernel/src/lib.rs to [workspace.lints.clippy]. Minor discipline-locking; pick up alongside the next workspace Cargo.toml change (next ADR-0027 or the B2 first impl task).

Next

  • Active phase: B (unchanged).
  • Active milestone: B2 (MMU activation, kernel-half mapping).
  • Active task: none — B1 closed today; B2 prep / ADR-0027 drafting opens next. Per ADR-0025 §Rule 1, the implementation task (T-015 or whichever number lands first) opens in the same commit as ADR-0027's Dependency chain section.
  • Next review trigger: B2 closure trio. Produced when the MMU activation arc reaches In Review (i.e. the implementation task lands). Possible interim triggers: a mini-retro if ADR-0027's drafting surfaces a learning worth capturing mid-arc; a maintainer-initiated review if a non-trivial Track-C/D follow-up gets picked up before B2 implementation starts.