fw-emu: per-frame heap reporting + pin the output-overshoot degradation contract - #280
Draft
Yona-Appletree wants to merge 2 commits into
Draft
fw-emu: per-frame heap reporting + pin the output-overshoot degradation contract#280Yona-Appletree wants to merge 2 commits into
Yona-Appletree wants to merge 2 commits into
Conversation
Yona-Appletree
added a commit
that referenced
this pull request
Aug 2, 2026
…ator firmware fw-emu is the real firmware image: same engine, same server, and what answers hardware questions without hardware (PR #280). Keeping panic-recovery here while fw-esp32c6 dropped it would make it test a configuration that ships nowhere -- the exact drift ADR 2026-07-23 existed to prevent. The guest panic handler collapses to what it always did after unwinding gave up: stage the breadcrumb, finalize, report to the host. memory.ld now discards .eh_frame and .gcc_except_table explicitly rather than retaining them in ROM. Three tests rewritten, not two. `FAULT_RECOVERED_PANIC` is renamed `FAULT_FRAMED_PANIC` -- nothing recovers a panic in-process any more, but the fault still routes through `catch_node_panic_framed`, which is what proves a red-gated path is denied UP FRONT without running the body. - repeat_panics_gate_then_power_on_clears (was recovered_panics_gate_...): reboot-shaped. Each offense now costs a boot. The escalation is observable because `Recovery::init` demotes reds BEFORE recording the prior crash, so a repeat offender lands straight back on red for the next run. - escalation_gates_the_parent_and_clean_runs_return_to_green: same treatment; two distinct children still escalate to the parent. - fuel_exhausted_shader_gates_without_reboot -> fuel_exhausted_shader_errors_without_reboot_or_blame. NOT identified in the plan. Its premise was that a repeat fuel offense red-gates the node, which worked only because the fuel trap PANICKED under panic-recovery and a caught panic is what records blame. With typed errors nothing latches: a hung shader now reports every frame instead of being disabled. The test asserts the ledger stays GREEN across three offenses, so restoring blame for fuel traps will fail it deliberately. just test-recovery-emu: 7/7 green. Plan: 2026-08-02-1314-rv32-unwinding-teardown Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The ESP32 firmwares all expose `esp32_memory_stats` from `esp_alloc::HEAP`; the emulator had no equivalent, so a test could only infer heap behaviour. `allocator::heap_stats()` returns the same (used, free) pair from the guest's linked-list heap, and fw-emu's `heap_report` feature logs it once per frame. Off by default — it is a log line per frame, for tests that need to tell a bounded transient from a leak. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Runs the real firmware image with two projects that differ only in output count: four outputs on the virtual board's four timing channels, and five on the same four. The fifth endpoint is valid but can never open — the shape the C6 report hit with two outputs on a one-channel manifest, reproduced without editing a manifest. Measures what that costs per frame: open attempts, caught panics, and heap used. The unopenable sink is asked twice (once, plus the designed retry after the successful opens bump the hardware generation), then parks; the heap is flat over 40 frames and nothing panics. Guards the contract in docs/defects/2026-08-02-c6-project-outgrows-board-\ outputs-oom-storm.md: one endpoint that cannot open must cost the board a sink, not its boot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Yona-Appletree
force-pushed
the
claude/great-keller-6cc73b
branch
from
August 3, 2026 03:00
6f26811 to
a3cf3f8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebased onto current main (2026-08-02 evening). Most of what this PR originally carried is now redundant — this is the residue that isn't.
What happened to the original PR
It was filed as an investigation of
docs/defects/2026-08-02-c6-project-outgrows-board-outputs-oom-storm.md, and concluded the defect was mis-attributed: a project declaring more outputs than the board offers degrades cleanly, with a flat heap and no retry, so the OOM storm came from somewhere else (soft-limit-bench, 227 KB resident on a 300 KB heap).Since then, two things landed on main independently:
2026-08-02-rv32-firmwares-are-abort-tier) killed the storm shape outright — there is no catcher any more, so there is no 53rd panic because there is no 2nd. It also explained the ledger-blamed stack-overflow crashes: unwinding one panic needed ~41 KB of stack on a chip with ~34 KB.So the conclusion has been absorbed. The doc commit has been dropped — main's version is better and says the same thing.
What's left, and why it's still worth landing
Two commits, +348 lines, no production behaviour change:
fw-emu/heap_report(off by default) andlp_riscv_emu_guest::allocator::heap_stats()— the emulator's equivalent of the ESP32s'esp32_memory_stats, logging[heap] used=N free=Monce per frame. Nothing on main duplicates this. It is directly useful for the question that is still open — heap headroom when auto-loading an oversized project — which main's own amendment says should now be much easier to reproduce.output_overshoot_emu.rs— pins the degradation contract, which outlived the storm it was written for. The abort tier makes a panic storm unreachable, but an endpoint that cannot open must still cost the board one sink rather than its boot, and must not ratchet the heap.Re-verified against today's main
The unopenable sink is asked twice — once on its first flush, then once more because the successful opens in that same flush bump the hardware generation, the designed one-retry-per-ownership-change — then parks. Same numbers as before the teardown, which is the point.
Reasonable to close instead if the appetite for extra test surface is low; the analysis is already safe in the defect doc on main. The instrumentation is the part that would have to be rebuilt later.
🤖 Generated with Claude Code