Skip to content

fix: prevent false divergence when disabling second PVM#8

Merged
tomusdrw merged 3 commits intomainfrom
td-fix-pvm-disable-diverge
Apr 15, 2026
Merged

fix: prevent false divergence when disabling second PVM#8
tomusdrw merged 3 commits intomainfrom
td-fix-pvm-disable-diverge

Conversation

@tomusdrw
Copy link
Copy Markdown
Member

Summary

  • Fix rAF race condition in useOrchestratorState where post-flush event handlers fell back to a stale initial closure, reverting already-loaded PVM state to pre-loadProgram defaults
  • Add lastFlushedSnapshots ref so the fallback chain is: pending buffer → last flushed state → initial state
  • Add E2E tests covering the enable→disable flow

Details

When two PVM workers responded to loadProgram across different animation frames, the second pvmStateChanged event would rebuild from new Map(initial) (captured before loadProgram), losing the first PVM's loaded state. This caused false gas divergence (0 vs 10000) immediately after enabling the second PVM.

Test plan

  • 2 new E2E tests for enable/disable divergence scenarios
  • All 257 E2E tests pass
  • All 683 unit tests pass
  • Build + lint pass

🤖 Generated with Claude Code

The rAF-based flush in useOrchestratorState cleared pendingSnapshots
after each flush, causing subsequent pvmStateChanged handlers to fall
back to a stale `initial` closure captured before loadProgram completed.
When two PVM workers responded across different animation frames, the
second event reverted the first PVM's loaded state to pre-load defaults,
producing a false gas/PC divergence.

Add a lastFlushedSnapshots ref that tracks the most recently flushed
snapshot map. Post-flush event handlers now use this as their fallback
base instead of the stale initial state.

Includes E2E tests for the enable→disable flow.

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

netlify bot commented Apr 14, 2026

Deploy Preview for pvm-debugger ready!

Name Link
🔨 Latest commit 94736f9
🔍 Latest deploy log https://app.netlify.com/projects/pvm-debugger/deploys/69df56336a633500088f9219
😎 Deploy Preview https://deploy-preview-8--pvm-debugger.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 14, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e130e7ff-6eef-4d75-a630-c4dd8440bd8c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds end-to-end tests validating correct behavior when disabling a secondary PVM debugger and modifies the orchestrator state hook's snapshot accumulation logic to retain post-flush state across event boundaries.

Changes

Cohort / File(s) Summary
E2E Test Suite
apps/web/e2e/sprint-25-disable-pvm-divergence.spec.ts
New Playwright test suite with helper functions to load programs, open settings, and toggle Ananas PVM. Two test cases validate that divergence indicators remain absent when enabling and disabling a second PVM, both with and without prior execution steps.
State Accumulation Logic
apps/web/src/hooks/useOrchestratorState.ts
Added lastFlushedSnapshots ref to cache the most recent snapshot state after rAF flush. Event handlers now fall back to this cached state instead of the orchestrator's initial state, preventing stale state propagation across rAF boundaries.

Possibly related issues

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly describes the main fix: preventing false divergence when disabling the second PVM, which is the central issue addressed in the changeset.
Description check ✅ Passed The description is well-related to the changeset, explaining the rAF race condition fix, the lastFlushedSnapshots addition, and covering the E2E tests added.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch td-fix-pvm-disable-diverge

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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/web/e2e/sprint-25-disable-pvm-divergence.spec.ts (1)

25-40: Consider adding diagnostic logging in the catch block.

The silent catch block makes it harder to diagnose why Ananas failed to enable if the test returns false. This is a minor ergonomics improvement.

🔧 Proposed improvement for better diagnostics
     try {
       await expect(page.getByTestId("pvm-tab-ananas")).toHaveRole("tab", {
         timeout: 15000,
       });
       return true;
-    } catch {
+    } catch (e) {
+      console.warn("Ananas PVM tab did not appear:", e);
       return false;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/e2e/sprint-25-disable-pvm-divergence.spec.ts` around lines 25 - 40,
The tryEnableAnanas function currently swallows errors in its catch and returns
false with no diagnostics; update the catch block in tryEnableAnanas to log
diagnostic information (e.g., the caught error message and a snapshot of
relevant page state like page.url() or page.locator('body').innerText()) via the
test/logger so you can see why the tab didn't appear before returning false,
while preserving the existing return false behavior; reference the ananasSwitch
locator and pvm-tab-ananas expectation when assembling the log for context.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/web/e2e/sprint-25-disable-pvm-divergence.spec.ts`:
- Around line 25-40: The tryEnableAnanas function currently swallows errors in
its catch and returns false with no diagnostics; update the catch block in
tryEnableAnanas to log diagnostic information (e.g., the caught error message
and a snapshot of relevant page state like page.url() or
page.locator('body').innerText()) via the test/logger so you can see why the tab
didn't appear before returning false, while preserving the existing return false
behavior; reference the ananasSwitch locator and pvm-tab-ananas expectation when
assembling the log for context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a6148e6f-5046-4baf-9395-5bdde37266d8

📥 Commits

Reviewing files that changed from the base of the PR and between a62f89c and e5a53cb.

📒 Files selected for processing (2)
  • apps/web/e2e/sprint-25-disable-pvm-divergence.spec.ts
  • apps/web/src/hooks/useOrchestratorState.ts

tomusdrw and others added 2 commits April 15, 2026 11:05
When enabling/disabling PVMs, loadProgram is async and workers respond
at different times. This creates a brief window where one PVM has loaded
state while the other still has defaults, producing a false divergence
flash. Gate divergence display behind isReloadingRef which is already
true for the duration of loadProgram.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document the stale-closure rAF race fix (lastFlushedSnapshots ref) and
the divergence flash suppression during PVM reload (isReloadingRef gate).
Add the new E2E test file to required files and verification sections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tomusdrw tomusdrw merged commit af91e73 into main Apr 15, 2026
7 checks passed
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