Skip to content

fix(state): use merge_dicts reducer for scratchpad to prevent key loss on concurrent writes - #209

Merged
plfavreau merged 1 commit into
minitap-ai:mainfrom
citizen204:fix-208-merge-reducers-for-concurrent-branches
Jul 9, 2026
Merged

fix(state): use merge_dicts reducer for scratchpad to prevent key loss on concurrent writes#209
plfavreau merged 1 commit into
minitap-ai:mainfrom
citizen204:fix-208-merge-reducers-for-concurrent-branches

Conversation

@citizen204

@citizen204 citizen204 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

When the executor calls save_note multiple times in the same
executor_tools superstep (i.e. the LLM emits several tool calls at
once), every save_note invocation reads the same base
state.scratchpad and produces a complete merged-copy update:

updated_scratchpad = {**state.scratchpad, key: content}

The previous take_last reducer then keeps only the last update,
silently discarding all keys written by earlier calls in the same
batch. With merge_dicts as the reducer, LangGraph accumulates each
branch's output via {**a, **b}, so every key written by every tool
call in the same superstep survives.

Fixes #208

Changes

  • minitap/mobile_use/graph/state.py: add merge_dicts helper and use
    it as the reducer for scratchpad instead of take_last

Summary by CodeRabbit

  • Bug Fixes
    • Updated how saved app state is combined so new values can be merged into existing stored data instead of replacing it entirely.
    • Improved persistence for the scratchpad, helping preserve previously stored entries while applying updates.

When multiple save_note tool calls run in the same executor_tools
superstep, they all read the same base state and each produce a
full merged-scratchpad update. The previous take_last reducer
discarded all but the last update, silently losing keys written by
earlier tool calls. merge_dicts accumulates every key across all
concurrent updates, preserving all writes.

Fixes minitap-ai#208
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a dictionary merge helper and changes State.scratchpad to merge incoming updates instead of replacing the whole dict.

Changes

Scratchpad merge behavior

Layer / File(s) Summary
Dict merge helper and scratchpad reducer
minitap/mobile_use/graph/state.py
Adds merge_dicts(a, b) to combine two dictionaries with b overriding a, and updates State.scratchpad to use that reducer.

🎯 1 (Trivial) | ⏱️ ~2 minutes

🐇 I hop through notes, one key at a time,
Two paws of updates now mingle in rhyme.
No scratchpad crumbs get lost in the night,
Merge, little burrow, and keep them all right. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the scratchpad reducer change and its purpose.
Linked Issues check ✅ Passed It satisfies the issue's immediate objective by merging concurrent scratchpad updates instead of replacing them.
Out of Scope Changes check ✅ Passed The change stays focused on the scratchpad reducer and does not introduce unrelated scope.

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
minitap/mobile_use/graph/state.py (1)

21-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the redundant docstring on Line 21.

This sentence restates exactly what the implementation already makes obvious; prefer code clarity over explanatory restatement comments.

As per path instructions, "Comments: flag any comment that restates what the code already says."

🤖 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 `@minitap/mobile_use/graph/state.py` at line 21, Remove the redundant docstring
in the state module: the brief description on the merge helper is just restating
what the implementation already makes obvious. Delete the docstring near the
dict-merge logic in state.py and leave the function/class code unchanged so the
intent comes from the code itself.

Source: Path instructions

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

Nitpick comments:
In `@minitap/mobile_use/graph/state.py`:
- Line 21: Remove the redundant docstring in the state module: the brief
description on the merge helper is just restating what the implementation
already makes obvious. Delete the docstring near the dict-merge logic in
state.py and leave the function/class code unchanged so the intent comes from
the code itself.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a3b9d1d8-c220-40d9-bb25-2c8790ed1074

📥 Commits

Reviewing files that changed from the base of the PR and between 47cce16 and 7a57c9b.

📒 Files selected for processing (1)
  • minitap/mobile_use/graph/state.py

@plfavreau plfavreau left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you @citizen204 for your contribution ! Merging your PR.

@plfavreau
plfavreau merged commit f5d513f into minitap-ai:main Jul 9, 2026
6 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.

[BUG] post_cortex_gate fan-out + take_last reducers cause silent state loss between concurrent orchestrator and executor branches

2 participants