Skip to content

Close Phase 1's four real gaps, and give the RSP its memory (T-21-001) - #35

Merged
doublegate merged 11 commits into
mainfrom
feat/rsp-scalar-sp-interface
Jul 21, 2026
Merged

Close Phase 1's four real gaps, and give the RSP its memory (T-21-001)#35
doublegate merged 11 commits into
mainfrom
feat/rsp-scalar-sp-interface

Conversation

@doublegate

Copy link
Copy Markdown
Owner

Motivation

Two things, in this order: close Phase 1 honestly, then lay the first stone of Phase 2.

Phase 1 was tagged v0.2.0 with 42 acceptance criteria still unticked. An audit of all 42 against the source — not against the docs, which is the point — found that most were genuinely done and never recorded, but four were real gaps sitting behind a green oracle. All four are fixed here.

The four Phase 1 gaps

1. The timer interrupt could be lost outright. timer_edge asked whether Count == Compare at the instant it was polled, and it is polled only from DC — which advance_at skips for the entire duration of a stall. Count is derived from the master clock and keeps advancing regardless, so a 69-PCycle multiply interlock (UM Table 3-12) steps clean over the single cycle the equality holds. Not a late interrupt — a lost one: IP7 never latched, and software waiting on the timer would hang forever.

Now detected as a crossing of the half-open interval (last_count, now], in wrapping arithmetic. MTC0 to Count or Compare re-bases that interval, because both writes move an endpoint underneath the detector and would otherwise manufacture an edge the hardware never produces.

2. The XTLB refill vector was never selected. VectorKind::XtlbRefill existed and its unit tests exercised the enum directly, but no live path produced it — every refill took the 32-bit vector at 0x000. The two vectors share an ExcCode, so the entry point is the only thing telling the handler which page-table walk to run (XContext vs Context). n64-systemtest installs a real handler at 0x8000_0080.

3. The FPU rates were documented and never charged. fp_arith charged nothing, so DIV.D retired as fast as MOV.S. Rather than implement only the four rows this repo had already quoted — which would have meant inventing the rest — UM Table 7-14 was extracted with mutool draw -F txt and transcribed whole, including the three rows that vary by source format (CVT.S is 2 from double but 5 from fixed point).

4. NMI was unimplemented. No signal, no variant, no path bypassing the interrupt masks.

Phase 2 groundwork (T-21-001)

DMEM and IMEM lived twice: as Bus::spmem, which is what the CPU actually read, and as Rsp::dmem/imem, which nothing touched. Harmless only while the RSP was a stub. The RSP now owns both banks.

The behavioural half is the RCP's size-blind bus. Every device in 0x0400_0000-0x04FF_FFFF ignores the access size and the low two address bits, latching the whole 32-bit word the VR4300 placed on SysAD. n64-systemtest states the rule in its own header comment: "SH/SB are broken: they overwrite the whole 32 bit… SD is broken: it only writes the upper 32 bit".

Since RDRAM does honour byte enables (the RI forwards the size to the RDRAM devices), correct narrowing is a property of the target, not the instruction — so Bus::write_sized carries the width and the untruncated register and lets the target decide.

Results

before after
n64-systemtest, suite-wide 413 409
n64-systemtest, Phase 1 categories 0 0
Golden log vs ares 0-diff 0-diff
Workspace tests 386 403

spmem: SB, SH, SD and SW (out of bounds) now pass.

What is deliberately not done

  • The early exit on trivial FPU operands (UM §7.5.6) — charged the full rate instead, so the model is slower than hardware there and never faster. Ledger C-29.
  • Interlock::Cp0i stays named but never raised; its trigger overlaps the exception flush, so charging it would invent a cycle. Its doc said "fires when…" in the present tense — corrected.
  • Four checkboxes stay unticked, now naming their owner (Phase 3 for SysAD phasing, Phase 7 for M and the cache-miss costs) instead of trailing off at "Sprint 2".
  • PI/SI external buses share the size-blindness on hardware and are left out — the PI models its own quirks separately, and folding them together without cart tests would be a change made blind. Phase 5.

Verification

Each fix was mutation-checked: the guard removed, the test confirmed red, the guard restored via a file copy. Two tests were rewritten after the check showed they passed either way — the Compare re-base test needed an unpolled gap before the write, or the detector's interval is already empty and the test proves nothing.

Gates run locally on the final commit: cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace, RUSTDOCFLAGS="-D warnings" cargo doc, the no_std build, pre-commit run markdownlint --all-files, plus both #[ignore]d oracles.

🤖 Generated with Claude Code

doublegate and others added 6 commits July 21, 2026 04:35
…bus (T-21-001)

DMEM and IMEM lived twice: as `Bus::spmem`, which is what the CPU actually
read, and as `Rsp::dmem`/`Rsp::imem`, which nothing touched. That was harmless
only while the RSP was a stub -- the moment it executes, the CPU and the RSP
would address two different memories that happened to start out equal. The RSP
now owns both banks and the Bus reaches them through `Rsp::mem_read`/`mem_write`.

The behavioural half is the RCP's **size-blind** write path. Everything on the
RCP's internal bus (`0x0400_0000-0x04FF_FFFF`) ignores the access size and the
low two address bits, latching the whole 32-bit word the VR4300 placed on SysAD
(N64brew *Memory map* SS Physical Memory Map accesses). The VR4300 has already
shifted the source register into the addressed byte lane, so a narrow store
writes that shifted register -- which is why the effect looks like zero-fill
rather than a partial update. n64-systemtest states the rule outright in its own
header comment (`src/tests/sp_memory/mod.rs`): SH/SB overwrite the whole 32 bits,
SD writes only the upper word and touches four bytes.

The CPU cannot narrow the value itself, because whether narrowing is correct is
a property of the target, not of the instruction: RDRAM honours the byte enables
because the RI forwards the low address bits and the access size to the RDRAM
devices. So `Bus::write_sized` carries the width and the *untruncated* register
to the bus and lets the implementor decide. The default narrows, as the in-crate
test buses need; `rustyn64-core` overrides it.

The SP memory window also repeats its 8 KiB up to `0x0404_0000` rather than
ending at `0x0400_2000`, which is why the folding is the behaviour rather than a
bounds-check standing in for one.

The PI and SI external buses share the size-blindness on hardware and are
deliberately left out: the PI models its own bus quirks separately, and folding
both into one rule without the cart tests to check it against would be a change
made blind. Phase 5.

n64-systemtest: `spmem: SB`, `SH`, `SD` and `SW (out of bounds)` now pass.
Each new test was mutation-checked -- reverting the size-blind path turns
exactly the three store tests red and leaves the RDRAM and window tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A stall could swallow the timer interrupt entirely. `timer_edge` asked whether
`Count == Compare` at the instant it was polled, and it is polled only from
`DC` -- which `advance_at` skips for the whole duration of a stall. `Count` is
derived from the master clock and keeps advancing regardless, so a 69-PCycle
multiply interlock (UM Table 3-12) steps clean over the single cycle for which
the equality holds. `IP7` then never latches at all: not a late interrupt, a
lost one, with software waiting on the timer hanging forever.

The fix asks whether `Compare` lies in the half-open interval
`(last_count, now]`, in wrapping arithmetic so a counter wrap is just another
interval. Excluding `last_count` preserves the existing edge semantics -- sitting
*on* `Compare` is not a transition into it, which is what keeps the power-on
`Count == Compare == 0` from latching `IP7` before an instruction retires.

Making the interval the question also makes the poll cadence irrelevant, which
is why no poll was added to the stall path: an earlier version latched `IP7`
during the stall as well, and that turned out to be unobservable -- no guest
instruction can read `Cause` while the pipeline is held -- so it was dropped
rather than kept as inert code.

`MTC0` to `Count` or `Compare` now re-bases the interval. Both writes move an
endpoint underneath the detector: a `Count` write that jumps *over* `Compare`
would read as a crossing, and a `Compare` placed behind `Count` as one that
already happened. Neither fires on hardware.

Found by the Phase 1 checkbox audit (sprint-2 line 138), which was recorded as
an unmet acceptance criterion with no deferral note rather than as a known bug.

Oracles: golden-log 0-diff holds; n64-systemtest Phase 1 categories still 0.
All three new tests were mutation-checked -- removing the re-base turns both
write tests red, and the stall test was red before the interval fix. The
`Compare` test deliberately leaves an unpolled gap before the write; without it
the detector's interval is already empty and the test passes either way.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssing

`VectorKind::XtlbRefill` existed, `vector()` mapped it to offset 0x080, and its
unit tests exercised the enum directly -- but no live code path ever produced it.
Every TLB refill took the 32-bit vector at 0x000, whatever the addressing width.

The two vectors carry the same `ExcCode`, so the entry point is the only thing
that tells the handler which page-table walk to run: the 64-bit handler reads
`XContext`, the 32-bit one `Context`. Sending a 64-bit miss to 0x000 runs the
32-bit walker over a 64-bit address. n64-systemtest installs a distinct handler
at 0x8000_0080, so this is a real entry point, not a theoretical one.

`Exception::TlbRefill` now carries the addressing width of the faulting access.
It has to be captured there rather than re-derived at dispatch: dispatch has
already set `EXL`, which forces `access_mode` to report Kernel, so a late
re-derivation would answer for the handler's mode instead of the access's.

Two tests, deliberately at different levels. The mapping test is satisfied just
as well by a `wide` flag that is never true in practice, which is the
decoded-but-no-op hazard `docs/engineering-lessons.md` describes; the pipeline
test therefore drives a real miss and differs from the existing 32-bit case in
`Status.KX` alone, so the two landing on different vectors is attributable to
nothing else. Both go red when the selection arm is removed.

Found by the Phase 1 checkbox audit (sprint-2 line 174). Not currently visible to
n64-systemtest -- its three handlers behave alike, so the suite does not
discriminate on entry point -- which is why the gap survived a green oracle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 1's cycle-cost criterion asks for "FPU rates with the latency = rate + 1
rule". The rule was written down in `docs/cpu.md` and never implemented:
`fp_arith` charged nothing, so every COP1 operation from `MOV.S` to `DIV.D`
retired in a single cycle.

The rates come from the manual itself rather than from the four rows this repo
had already quoted. Charging only those four would have meant inventing the
rest, so Table 7-14 was extracted with `mutool draw -F txt` (the project's
documented method for this PDF -- `pdftotext` fails on it) and transcribed whole,
including the three rows that vary by *source* format: `CVT.S` is 2 from double
but 5 from a fixed-point format, and `CVT.D` is 1 from single. A uniform
per-instruction table gets exactly those wrong.

The manual's "+1 for a dependent consumer" is deliberately not added anywhere.
The stall holds every stage, so a consumer spends its own cycle once the stall
drains and arrives at rate + 1 without a second rule -- adding it explicitly
would double-count.

A rate of 1 charges nothing. One cycle is what an ordinary instruction already
takes, so `ABS`, `MOV`, `NEG`, `C.cond` and `CVT.D.S` are free; the test asserts
that asymmetry directly, because a blanket stall on every COP1 op would satisfy
a `MUL.D`-only test.

Two test levels, for the reason `docs/engineering-lessons.md` gives: the table
test asserts the numbers, and a table nothing calls is inert, so the pipeline
test drives real instructions and reads the interlock back. Removing the charge
turns the second red and leaves the first green.

Not implemented, and recorded rather than glossed: the early exit on trivial
operands (UM SS7.5.6, table note 2). Those operands are charged the full rate,
so the model runs slower than hardware there and never faster -- a bounded,
one-directional error. Accuracy ledger C-29, which also records that both
oracles are insensitive to these stalls, so the rates are currently unfalsified
rather than verified.

Oracles: golden-log 0-diff holds over 50,027 records; n64-systemtest Phase 1
categories still 0, suite-wide still 409.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The last unimplemented Phase 1 exception. There was no NMI anywhere in the tree:
no signal, no variant, and no path that bypassed the interrupt masks.

NMI is deliberately kept out of `dispatch`, because almost none of that function
applies to it. It writes `ErrorEPC` rather than `EPC`, sets `ERL` rather than
`EXL`, and writes **no `Cause` at all** -- "the contents of all registers are
preserved except for" `ErrorEPC` and four `Status` bits (`ERL`/`SR`/`BEV` set,
`TS` cleared). Routing it through the general path would have overwritten
`Cause.ExcCode` with a code NMI does not have. It still rides in the `Exception`
enum so it can reuse the pipeline-flush machinery, and `dispatch` intercepts it
before any of the six epilogue steps run.

It ignores `IE`, `EXL` and `ERL` entirely. The one condition it respects is the
instruction boundary -- "unlike Cold Reset and Soft Reset, but like other
exceptions, NMI is taken only at instruction boundaries" -- which is the same
run-cycle gate every interrupt already passes.

The test asserts the bypass against a `Status` with `IE` clear and both `EXL`
and `ERL` set, and a second test shows an ordinary timer interrupt is refused in
that exact state. Without the control, "the NMI was taken" would be equally
consistent with the masks simply not working.

Nothing calls `signal_nmi` yet, and that is stated rather than glossed: on
hardware the source is the console's reset button, which arrives as PRENMI then
NMI, and the frontend owns that button (Phase 6). The exception is Phase 1 work
and belongs with the rest of the exception model; the wire from the button is a
separate, later concern.

Bit positions are from UM Fig. 6-6 (the Self-Diagnostic Status Field) rather
than from memory: BEV 22, TS 21, SR 20.

Oracles: golden-log 0-diff holds; n64-systemtest Phase 1 categories still 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ctually does

Phase 1 was tagged v0.2.0 with 42 acceptance criteria still unticked. That is
not a formatting oversight: an audit of all 42 against the source found four
real gaps hiding behind a green oracle, each now fixed on this branch (the
Count/Compare crossing, the XTLB refill vector, the FPU rates, NMI). The rest
were genuinely done and simply never recorded.

Ticked only with evidence. One box claimed a test "where a multi-cycle stall
separates a branch from its delay slot and Cause.BD / EPC still come out right";
the existing test pinned flag *propagation* only, which is a different claim --
a flag can travel correctly and still be read from the wrong latch at dispatch,
the reverse-cascade hazard this project has hit twice. That test is now written,
and it passed on the first honest run: the implementation was right, my first
draft of the test was not (it flagged the instruction that never faults).

Four boxes stay unticked, and now say who owns them rather than trailing off at
"Sprint 2":

  - Stepping the RCP between SysAD phases -> Phase 3, the first phase with a
    second engine contending for the bus and so the first that can observe the
    difference.
  - `M` (memory access time) -> Phase 7, still unmeasured, still no invented
    value.
  - Cache-miss costs -> Phase 7. This deferral's premise is gone (the caches are
    modelled now), but the cost is blocked on `M`, so it moves with C-1 rather
    than being quietly ticked.
  - The suite-wide criterion that the above be explicitly deferred *with*
    reasons -- which is what this commit makes true.

Also corrected three stale claims that survived because nothing fails when a
document is wrong:

  - `Interlock::Cp0i`'s doc said it "fires when ...", present tense, while
    nothing raises it. Its trigger overlaps the exception flush, so charging it
    would invent a cycle; the variant stays because `Interlock` enumerates the
    documented taxonomy, but the doc now says it is never raised.
  - The ledger's Status section still described Sprint 1. Its replacement keeps
    the uncomfortable part: after a whole phase, nothing here has been
    *measured* -- every resolution so far was by citation.
  - Ledger U-5 and U-8 were resolved long ago and still listed Sprint 2 as
    owner. Marked resolved with forward references rather than rewritten, per
    this file's append-mostly rule.

Oracles unchanged: golden-log 0-diff, Phase 1 categories 0, 403 workspace tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added non-maskable interrupt handling with dedicated reset-vector dispatch.
    • Improved 32-bit vs 64-bit TLB refill vector selection.
    • Added documented COP1/FPU multi-cycle timing and interlock stall modelling.
    • Enhanced RSP DMEM/IMEM byte-access with correct mirrored, repeating CPU-visible memory windows.
  • Bug Fixes
    • Fixed timer interrupt edge detection to trigger on proper compare crossings and re-base correctly after software updates.
  • Documentation
    • Updated CPU, RSP, and accuracy/timing documentation to match the corrected interrupt, exception, memory, and FPU behaviours.

Walkthrough

The PR moves SPMEM ownership into Rsp, adds size-aware CPU bus writes, corrects timer edge detection, implements NMI and 64-bit TLB refill dispatch, adds COP1 pipeline stall timing, and updates tests, documentation, and Phase 1 records.

Changes

RSP memory and bus integration

Layer / File(s) Summary
RSP memory ownership and bus access
crates/rustyn64-rsp/src/lib.rs, crates/rustyn64-core/src/bus.rs, crates/rustyn64-cpu/src/lib.rs, crates/rustyn64-test-harness/src/rom.rs, docs/rsp.md
RSP owns folded DMEM/IMEM access. Bus DMA, CPU SPMEM access, and RCP size-blind writes use the new paths, with corresponding tests and documentation updated.

CPU timing and exception control

Layer / File(s) Summary
Timer and COP1 timing
crates/rustyn64-cpu/src/cop0.rs, crates/rustyn64-cpu/src/fpu.rs, crates/rustyn64-cpu/src/pipeline.rs, docs/cpu.md
Timer crossings use wrapping half-open intervals, writes to Count or Compare re-base detection, and COP1 delay rates produce Mci stalls.
NMI, TLB vectors, and pipeline control
crates/rustyn64-cpu/src/exception.rs, crates/rustyn64-cpu/src/pipeline.rs, docs/cpu.md
NMI is latched and dispatched through the reset vector, while TLB refill exceptions carry addressing width and select the XTLB vector for 64-bit accesses.
Accuracy and project-status records
docs/accuracy-ledger.md, to-dos/**, to-dos/ROADMAP.md, docs/engineering-lessons.md
Records describe the bus and COP1 timing rules, update Phase 1 completion checklists, record deferred measurements, and replace outdated ADR references.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ExternalSignal
  participant Pipeline
  participant COP0
  participant ExceptionDispatch
  ExternalSignal->>Pipeline: signal_nmi()
  Pipeline->>COP0: sample pending NMI at instruction boundary
  Pipeline->>ExceptionDispatch: dispatch Exception::Nmi
  ExceptionDispatch->>COP0: update ErrorEPC and Status
  ExceptionDispatch-->>Pipeline: reset-vector dispatch
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 8 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title describes the work, but it does not follow the required Conventional Commits format. Rewrite it as feat(scope): subject with imperative mood and keep it under 72 characters.
Changelog Entry For User-Visible Changes ⚠️ Warning FAIL: the PR adds user-visible fixes in cop0.rs/pipeline.rs/bus.rs, but CHANGELOG.md is unchanged in the PR range, so no [Unreleased] entry was added. Add a short [Unreleased] bullet for the timer/NMI/FPU/RSP-visible fixes, or split out pure refactors if you want to keep CHANGELOG untouched.
✅ Passed checks (8 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the timer, NMI, FPU, and RSP changes in the patch.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Oracle Number Is Stated ✅ Passed PASS — docs/STATUS.md gives the oracle figure (413 suite-wide, 0 Phase 1), and the PR records the measured 413→409 effect.
Docs-As-Spec Sync ✅ Passed CPU and RSP behaviour changes are paired with docs/cpu.md and docs/rsp.md updates; the core-bus semantics are documented there too.
Measured, Never Tuned ✅ Passed All new constants/timings are source-backed: FPU rates cite UM Table 7-14/C-29; EPILOGUE_STALL, SR/TS, and SP mirroring cite UM figures/pages plus C-28/C-30.
Unsafe Stays Out Of The Chip Crates ✅ Passed Diff scan found no added unsafe or removed #![forbid(unsafe_code)]; core/cpu/rsp retain the forbid guard, and frontend has no unsafe syntax.

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

@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 Phase 1 of the emulator by implementing size-blind write paths for the RCP's internal bus, accurate timer edge crossing detection to prevent missed interrupts during stalls, Non-Maskable Interrupt (NMI) support, and XTLB refill vector selection for 64-bit addressing. It also models FPU pipeline stalls based on UM Table 7-14 and updates the RSP to own DMEM and IMEM directly. Feedback on these changes highlights a potential underflow panic in the size-blind shift calculation on the bus, and an issue where calling stall_for with zero cycles still triggers a one-cycle pipeline stall.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/rustyn64-core/src/bus.rs Outdated
Comment thread crates/rustyn64-cpu/src/pipeline.rs
doublegate and others added 2 commits July 21, 2026 05:14
`Pipeline::access_mode` is private, so the rustdoc gate rejects a link to it
from a public item. Plain code span instead, which is what `docs/` already
prescribes for links that cannot resolve in a default doc build.

Caught by CI rather than locally: the rustdoc gate was run earlier in this
branch's work and not again after the XTLB commit added the reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adopted from a Gemini Code Assist review comment on #35. Within the CPU the
invariant holds -- MIPS requires natural alignment and `AddressError` is raised
before a misaligned store reaches the bus, so `width + (addr & 3) <= 4` -- but
`write_sized` is a public trait method and this PR's own tests call it directly.

The failure mode is worse than the debug panic the comment named: in release the
subtraction wraps, `8 * huge` overflows again, and the shift is masked, so it
would silently write the wrong byte lane instead of failing loudly.

Co-Authored-By: Claude Opus 4.8 <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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/rustyn64-cpu/src/pipeline.rs (2)

639-650: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Comment describes an effect the branch doesn't produce.

"Latching IP7 here does not accept the interrupt... it only records in Cause" — but this branch only calls self.cop0.set_now(count_now) before returning; nothing here calls set_ip/timer_edge. The actual latch happens later, the next time dc_stage runs after the stall drains (which is correct, since the crossing-based timer_edge tolerates the gap). Worth rewording so the comment doesn't read as describing code that isn't in this branch — path instructions call this exact pattern out as costly for this repo ("this project has been bitten by that four times").

As per path instructions: "A comment that asserts what the code does but disagrees with it. Treat comment and code as INDEPENDENT claims; this project has been bitten by that four times and no test failed any of them."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-cpu/src/pipeline.rs` around lines 639 - 650, The stall-branch
comment incorrectly claims that it latches IP7 and updates Cause, while this
branch only advances the clock through self.cop0.set_now(count_now) before
returning. Rewrite the comment to describe only that timer progression continues
during the stall and that timer-edge handling occurs when dc_stage resumes,
without claiming interrupt latching here.

Source: Path instructions


709-735: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Cascade order inverts the documented WB > DC > EX > RF stall priority for the new FPU stall.

stall_for (line 517) overwrites self.stall unconditionally with no priority check, and advance_at runs stages WB → DC → EX → RF → IC. That means whichever stage calls stall_for last in a cycle wins the arbitration in practice — IC > RF > EX > DC > WB — which is the exact inverse of the priority docs/cpu.md documents for this same rule ("Priority runs WB > DC > EX > RF (UM §4.7.4): a later stage's exception or stall request always outranks an earlier stage's").

Before this PR wb_stage never called stall_for, so the collision was unreachable. Now it does (line 734, the new Mci stall for multi-cycle FPU ops), so an FPU instruction retiring in WB and an integer MULT/DIV two instructions younger reaching EX in the same cycle will have the FPU's stall duration silently replaced by the integer op's — the new test (the_documented_fpu_rates_are_charged_as_stalls) only exercises the FPU stall in isolation and does not catch this.

Needs a priority-aware arbitration (e.g. tag Stall with the requesting stage and only overwrite when the new request's stage priority is >= the current one's), covering the pre-existing DC/EX/RF/IC collisions too rather than just the new WB one.

Also applies to: 517-522, 652-656, 1912-1914, 1980-1980, 2131-2131

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-cpu/src/pipeline.rs` around lines 709 - 735, Make stall
arbitration priority-aware across stall_for and every existing caller: associate
each request with its originating pipeline stage and replace the current stall
only when the new request has equal or higher documented priority (WB > DC > EX
> RF, with IC handled consistently). Update the WB FPU request in wb_stage and
the existing DC/EX/RF/IC callers without changing their stall durations or
exception behavior, ensuring lower-priority later calls cannot overwrite
higher-priority stalls.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/rustyn64-core/src/bus.rs`:
- Around line 650-679: Update write_sized to reject unsupported widths before
the is_rcp_internal branch, returning immediately unless width is 1, 2, 4, or 8.
Preserve the existing handling for supported widths and prevent internal-address
writes and shift calculations for width 0, 3, or values above 8.

In `@docs/rsp.md`:
- Around line 59-64: Add authoritative provenance for the repeated SPMEM window:
create or update a measured entry in docs/accuracy-ledger.md naming the exact
n64-systemtest test and marking the behavior measured, then cite that ledger
entry from docs/rsp.md. Update the implementation documentation near the SPMEM
handling in crates/rustyn64-rsp/src/lib.rs and the SPMEM_WINDOW_END definition
in crates/rustyn64-core/src/bus.rs to reference the same ledger entry; apply
these changes at docs/rsp.md:59-64, crates/rustyn64-rsp/src/lib.rs:98-106, and
crates/rustyn64-core/src/bus.rs:281-285.

In `@to-dos/phase-1-cpu-golden-log/overview.md`:
- Around line 20-21: Align the Phase 1 status statements in the overview so COP1
is consistently represented: remove the completed COP1 claim if Sprint 3 remains
a stub, and update the Phase 1 oracle gate criteria to explicitly include COP1
alongside CPU, COP0, and TLB. Ensure the related statements in the referenced
section use the same completion status.

In `@to-dos/phase-1-cpu-golden-log/sprint-2-cop0-tlb-exceptions.md`:
- Around line 265-267: Uncheck the result-count reading criterion in the harness
checklist until the output channel is identified, the reader is implemented, and
execution evidence is documented. Preserve the note requiring selection among
isviewer.rs, sc64.rs, and FramebufferConsole without assuming which channel is
active.
- Around line 206-209: Update the earlier acceptance text and ledger reference
in this ticket to describe the actual cache model consistently, removing the
stale claim that cache contents are not modelled. Keep the subsequent statement
that the unmeasured M parameter remains the blocker and that the work moves to
Phase 7.

In `@to-dos/ROADMAP.md`:
- Around line 21-24: Resolve the v0.2.0 status inconsistency in the roadmap:
align the release entry with the later statement that no tag has been cut by
marking v0.2.0 as planned and unreleased, unless an existing tag can be
verified, in which case update the later status to reference it.

---

Outside diff comments:
In `@crates/rustyn64-cpu/src/pipeline.rs`:
- Around line 639-650: The stall-branch comment incorrectly claims that it
latches IP7 and updates Cause, while this branch only advances the clock through
self.cop0.set_now(count_now) before returning. Rewrite the comment to describe
only that timer progression continues during the stall and that timer-edge
handling occurs when dc_stage resumes, without claiming interrupt latching here.
- Around line 709-735: Make stall arbitration priority-aware across stall_for
and every existing caller: associate each request with its originating pipeline
stage and replace the current stall only when the new request has equal or
higher documented priority (WB > DC > EX > RF, with IC handled consistently).
Update the WB FPU request in wb_stage and the existing DC/EX/RF/IC callers
without changing their stall durations or exception behavior, ensuring
lower-priority later calls cannot overwrite higher-priority stalls.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f052af61-821d-434f-8249-3237609141ff

📥 Commits

Reviewing files that changed from the base of the PR and between 19563f6 and 861258b.

📒 Files selected for processing (17)
  • crates/rustyn64-core/src/bus.rs
  • crates/rustyn64-cpu/src/cop0.rs
  • crates/rustyn64-cpu/src/exception.rs
  • crates/rustyn64-cpu/src/fpu.rs
  • crates/rustyn64-cpu/src/lib.rs
  • crates/rustyn64-cpu/src/pipeline.rs
  • crates/rustyn64-rsp/src/lib.rs
  • crates/rustyn64-test-harness/src/rom.rs
  • docs/accuracy-ledger.md
  • docs/cpu.md
  • docs/engineering-lessons.md
  • docs/rsp.md
  • to-dos/ROADMAP.md
  • to-dos/phase-1-cpu-golden-log/overview.md
  • to-dos/phase-1-cpu-golden-log/sprint-1-integer-core.md
  • to-dos/phase-1-cpu-golden-log/sprint-2-cop0-tlb-exceptions.md
  • to-dos/phase-2-rsp-lle/sprint-1-scalar-sp.md

Comment thread crates/rustyn64-core/src/bus.rs
Comment thread docs/rsp.md
Comment thread to-dos/phase-1-cpu-golden-log/overview.md
Comment thread to-dos/phase-1-cpu-golden-log/sprint-2-cop0-tlb-exceptions.md
Comment thread to-dos/phase-1-cpu-golden-log/sprint-2-cop0-tlb-exceptions.md Outdated
Comment thread to-dos/ROADMAP.md

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/rustyn64-cpu/src/pipeline.rs (1)

532-534: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document Pipeline::signal_nmi.

This new public method lacks rustdoc and will fail the documentation gate. As per coding guidelines, “New public Rust items must have rustdoc documentation.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-cpu/src/pipeline.rs` around lines 532 - 534, Add rustdoc
documentation directly above the public Pipeline::signal_nmi method, briefly
describing that it signals the non-maskable interrupt and marks an NMI as
pending. Keep the method’s behavior unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/rustyn64-cpu/src/pipeline.rs`:
- Around line 532-534: Add rustdoc documentation directly above the public
Pipeline::signal_nmi method, briefly describing that it signals the non-maskable
interrupt and marks an NMI as pending. Keep the method’s behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 34b8813d-52ca-4b80-9b5a-5d343f44a51d

📥 Commits

Reviewing files that changed from the base of the PR and between 861258b and 3bfb95a.

📒 Files selected for processing (2)
  • crates/rustyn64-core/src/bus.rs
  • crates/rustyn64-cpu/src/pipeline.rs

Six comments, all adopted -- four of them documentation inconsistencies this
branch either introduced or left standing, which is the class of error nothing
in CI can catch.

**Unsupported widths now behave the same on both paths.** The non-RCP branch
fell through to `_ => {}`, while the internal-bus arm matched `w => ...` and
would have *stored* for a width of 3, 0 or 9. Nothing reaches it -- `StoreKind`
yields only 1/2/4/8 -- but "unreachable" is a property of the current caller and
this is a public trait method, so the two paths now share one contract.

**The SPMEM mirroring gets real provenance (ledger C-30).** It was resting on a
code comment that named a test, which is not a source. The wiki documents the
two 4 KiB ranges and stops; the mirroring rests entirely on the oracle, in two
independent forms -- n64-systemtest's own source comment and the
`sp_memory: SW (out of bounds)` test that executes the claim. Recorded because
masking an address is the natural implementation of both "it mirrors" and "we
skipped the bounds check", and those are different claims about hardware.

**Phase 1's oracle criterion omitted COP1**, in both `overview.md` and
`ROADMAP.md`. VERSION-PLAN 0.2.0 is authoritative and names all four
categories; AGENTS.md already records that `docs/STATUS.md` once carried the
same three-category conflation. Fixed in both files. The sprint statuses were
stale too: Sprint 2 said "planned" and Sprint 3 "stub" while both are complete,
and Sprint 3 is now marked complete with a note that it never got a plan file --
it ran against the ledger and the two oracles rather than a ticket list.

**The zero-depth cache box is annotated, not rewritten.** It is marked
SUPERSEDED by T-11-003/D-6 the way the ledger marks D-5 itself, because
rewriting a completed sprint's acceptance record erases reasoning that was sound
while it held. The annotation keeps the useful part: the boundary that box
predicted (Phase 5 DMA coherency) came due earlier, at n64-systemtest's cache
groups, which observe staleness with no DMA at all.

**The result-count box was stale in its text, not in its tick.** It still said
the output channel was undetermined. Resolved: both ISViewer and EMUX `xlog`,
EMUX preferred -- the suite picks its console at runtime from what the emulator
advertises, so a single hardcoded choice would have been a guess either way.

**The v1.0.0 milestone still claimed no tag had ever been cut.** Two are.

Co-Authored-By: Claude Opus 4.8 <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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
to-dos/phase-1-cpu-golden-log/overview.md (1)

39-40: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Synchronise the determinism criterion with docs/STATUS.md.

This checkbox now says the ADR 0004 gap is closed, while its own text says docs/STATUS.md still records it as unexercised. Update the authoritative status record with the test evidence in this change, or leave the criterion deferred.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@to-dos/phase-1-cpu-golden-log/overview.md` around lines 39 - 40, Synchronize
the determinism criterion with the authoritative status record: either update
docs/STATUS.md to document the ADR 0004 regression-test evidence and mark the
gap exercised, or revert the checklist item to its deferred state so it no
longer claims closure.

Sources: Path instructions, Learnings

crates/rustyn64-core/src/bus.rs (1)

1194-1282: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a regression test for unsupported store widths.

The new guard at Line [658] restores the public write_sized no-op contract, but the shown tests cover only supported widths. Add cases for widths 0, 3, and 16 against an internal address and assert that memory and register state remain unchanged.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-core/src/bus.rs` around lines 1194 - 1282, Add a regression
test alongside the existing Bus store tests that calls write_sized with
unsupported widths 0, 3, and 16 at an internal address. Initialize
representative memory and register state, perform each store, then assert both
memory and register values remain unchanged, preserving the public no-op
contract.
docs/rsp.md (1)

50-72: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Record the measured oracle effect.

This behaviour section cites C-30 and C-28 but does not state the measured change in n64-systemtest’s failing-assertion count, or explicitly say that it was not measured. Add that result to this specification or the referenced ledger entry.

As per coding guidelines, emulation-behaviour changes must state the measured failure-count effect or explicitly state that it was not measured.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/rsp.md` around lines 50 - 72, Update the RSP memory behavior
documentation around the C-30 and C-28 references, or the referenced accuracy
ledger entries, to record the measured change in n64-systemtest
failing-assertion count caused by this behavior. If no measurement exists,
explicitly state that the failure-count effect was not measured.

Source: Coding guidelines

crates/rustyn64-rsp/src/lib.rs (1)

129-138: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Drop const from mem_write
bank[off & 0xFFF] = val; relies on const IndexMut/DerefMut, which is not stable on Rust 1.97. This const fn blocks the pinned thumbv7em-none-eabihf build.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-rsp/src/lib.rs` around lines 129 - 138, Remove the const
qualifier from Rsp::mem_write while preserving its existing address folding,
bank selection, and byte-write behavior. Keep the method signature and
implementation otherwise unchanged so it no longer requires unstable const
mutable indexing.

Sources: Coding guidelines, MCP tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/accuracy-ledger.md`:
- Around line 1242-1244: Revise the upper-bound statement in the accuracy ledger
to avoid attributing the 0x0404_0000/SP-register boundary to the cited test.
Separate the measured evidence from the bus-map/manual source, or add a test
that explicitly probes the boundary before describing it as test-asserted.

In `@to-dos/phase-1-cpu-golden-log/overview.md`:
- Around line 81-86: Update the Sprint 3 completion record in the overview
document to mark the stale golden-trace producer risk as superseded, and
reference the actual oracle and verification run supporting the 0-diff over
50,027 retired records. Ensure the document no longer states that the producer
is missing or the 0-diff gate cannot be met.

---

Outside diff comments:
In `@crates/rustyn64-core/src/bus.rs`:
- Around line 1194-1282: Add a regression test alongside the existing Bus store
tests that calls write_sized with unsupported widths 0, 3, and 16 at an internal
address. Initialize representative memory and register state, perform each
store, then assert both memory and register values remain unchanged, preserving
the public no-op contract.

In `@crates/rustyn64-rsp/src/lib.rs`:
- Around line 129-138: Remove the const qualifier from Rsp::mem_write while
preserving its existing address folding, bank selection, and byte-write
behavior. Keep the method signature and implementation otherwise unchanged so it
no longer requires unstable const mutable indexing.

In `@docs/rsp.md`:
- Around line 50-72: Update the RSP memory behavior documentation around the
C-30 and C-28 references, or the referenced accuracy ledger entries, to record
the measured change in n64-systemtest failing-assertion count caused by this
behavior. If no measurement exists, explicitly state that the failure-count
effect was not measured.

In `@to-dos/phase-1-cpu-golden-log/overview.md`:
- Around line 39-40: Synchronize the determinism criterion with the
authoritative status record: either update docs/STATUS.md to document the ADR
0004 regression-test evidence and mark the gap exercised, or revert the
checklist item to its deferred state so it no longer claims closure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 46db6a4d-d2ec-439d-96db-b85ed04727ca

📥 Commits

Reviewing files that changed from the base of the PR and between 3bfb95a and bc116a6.

📒 Files selected for processing (7)
  • crates/rustyn64-core/src/bus.rs
  • crates/rustyn64-rsp/src/lib.rs
  • docs/accuracy-ledger.md
  • docs/rsp.md
  • to-dos/ROADMAP.md
  • to-dos/phase-1-cpu-golden-log/overview.md
  • to-dos/phase-1-cpu-golden-log/sprint-2-cop0-tlb-exceptions.md

Comment thread docs/accuracy-ledger.md Outdated
Comment thread to-dos/phase-1-cpu-golden-log/overview.md
Two CodeRabbit findings on prose added earlier in this PR.

Ledger C-30 cited `spmem: SW (out of bounds)` for both halves of the claim,
but that test proves only that the window repeats with an 8 KiB period. It
never probes `0x0404_0000`. The upper bound comes from the address map -- the
SP registers start there, so the window ends where the next device begins --
which is a different kind of evidence, and conflating the two is exactly what
this ledger exists to prevent. The entry now says the last repetition before
that address has never been tested, and names the boundary test that would
close it.

The Phase 1 overview marked Sprint 3 complete while still listing "the golden
trace does not exist yet" as an open risk, and repeating that claim under
Dependencies. Both now record the resolution. The risk is struck rather than
deleted: its predicted mitigation is what actually happened, which makes it a
rare case of a risk register earning its keep.

Co-Authored-By: Claude Opus 4.8 <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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/accuracy-ledger.md`:
- Around line 1242-1250: Update the preceding “Basis” statement for this
bounded-window entry to distinguish the oracle-supported repetition and period
from the address-map-supported upper bound at 0x0404_0000. Preserve the explicit
separation between sourced, measured, and inferred behavior, and do not
attribute the boundary claim solely to the oracle.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a66e1c95-3b7a-4b96-8698-3706a4fee1ef

📥 Commits

Reviewing files that changed from the base of the PR and between bc116a6 and 85e14e1.

📒 Files selected for processing (2)
  • docs/accuracy-ledger.md
  • to-dos/phase-1-cpu-golden-log/overview.md

Comment thread docs/accuracy-ledger.md
The Bounded paragraph was fixed to separate the two sources; the basis heading
above it still said "the oracle, and only the oracle", so the entry
contradicted itself one paragraph later. In this file that half-fix is worse
than the original overstatement, because the heading is what gets skimmed.

Co-Authored-By: Claude Opus 4.8 <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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
docs/accuracy-ledger.md (3)

1222-1252: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Run the pinned markdownlint hook locally before merge. This repo pins markdownlint in .pre-commit-config.yaml, and CI does not run it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/accuracy-ledger.md` around lines 1222 - 1252, Run the repository’s
pinned markdownlint hook locally against the updated documentation before
merging, using the configuration and tool version specified in
.pre-commit-config.yaml; resolve any reported issues in the C-30 entry while
preserving its content.

Sources: Path instructions, Learnings


1231-1236: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not call same-suite evidence independent
docs/accuracy-ledger.md C-30 overstates provenance under the honesty rule: the n64-systemtest source comment and spmem: SW (out of bounds) test are different evidence forms, but they are not independent references. Rephrase that line or add a separate primary source if you want to claim independence.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/accuracy-ledger.md` around lines 1231 - 1236, Revise the C-30 provenance
wording around the n64-systemtest evidence to avoid calling its source comment
and `spmem: SW (out of bounds)` test independent references. Describe them as
two evidence forms from the same suite, or add a genuinely separate primary
source before retaining any independence claim.

Sources: Path instructions, Learnings


1248-1250: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cite the exact SP register-map location for the 0x0404_0000 boundary. N64brew *RSP Interface* is too broad here; point the ledger at the specific section or table row used for the register boundary claim.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/accuracy-ledger.md` around lines 1248 - 1250, Update the boundary
explanation near the `0x0404_0000` claim to cite the exact N64brew RSP Interface
section or table row that identifies the SP register-map start. Replace the
broad `N64brew *RSP Interface*` reference while preserving the distinction
between the map-derived boundary and the untested behavior.

Sources: Path instructions, Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@docs/accuracy-ledger.md`:
- Around line 1222-1252: Run the repository’s pinned markdownlint hook locally
against the updated documentation before merging, using the configuration and
tool version specified in .pre-commit-config.yaml; resolve any reported issues
in the C-30 entry while preserving its content.
- Around line 1231-1236: Revise the C-30 provenance wording around the
n64-systemtest evidence to avoid calling its source comment and `spmem: SW (out
of bounds)` test independent references. Describe them as two evidence forms
from the same suite, or add a genuinely separate primary source before retaining
any independence claim.
- Around line 1248-1250: Update the boundary explanation near the `0x0404_0000`
claim to cite the exact N64brew RSP Interface section or table row that
identifies the SP register-map start. Replace the broad `N64brew *RSP
Interface*` reference while preserving the distinction between the map-derived
boundary and the untested behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0263da37-46f3-4454-abc0-43ffda598119

📥 Commits

Reviewing files that changed from the base of the PR and between 85e14e1 and 6b060fb.

📒 Files selected for processing (1)
  • docs/accuracy-ledger.md

@doublegate
doublegate merged commit ea62e64 into main Jul 21, 2026
9 checks passed
@doublegate
doublegate deleted the feat/rsp-scalar-sp-interface branch July 21, 2026 14:10
doublegate added a commit that referenced this pull request Jul 22, 2026
chore(release): v0.3.0 "Microcode" — the LLE RSP (Phase 2 close) (#54)

Phase 2 close. Bumps the workspace + all crates 0.2.0 -> 0.3.0, renames the
CHANGELOG [Unreleased] section to [0.3.0] "Microcode" (2026-07-22) with the full
Phase 2 summary (PRs #35-#53), and brings README, docs/STATUS.md, VERSION-PLAN,
and AGENTS.md into line with both phases complete. Docs + version only, no
behavior change.

Review: Antigravity clean (one nitpick, declined); CodeRabbit's two findings
adjudicated (softened premature "tagged" claims; the changelog-provenance point
declined and CodeRabbit concurred that the provenance lives in the specs).

Co-Authored-By: Claude Opus 4.8 <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