Skip to content

fix: address post-merge code review findings from PR #556#578

Merged
anandgupta42 merged 2 commits intomainfrom
fix/code-review-556-followup
Mar 29, 2026
Merged

fix: address post-merge code review findings from PR #556#578
anandgupta42 merged 2 commits intomainfrom
fix/code-review-556-followup

Conversation

@anandgupta42
Copy link
Copy Markdown
Contributor

@anandgupta42 anandgupta42 commented Mar 29, 2026

What does this PR do?

Addresses 8 findings from Kulvir's post-merge multi-model code review on PR #556 (comment).

Security fixes:

  • MongoDB aggregate now blocks nested $function/$accumulator via JSON.stringify scan (not just top-level stage keys which could be bypassed)
  • Separate $out/$merge write stage blocking with clear error messages

Bug fixes:

  • PlanExitTool now rejects dismissed/undefined dialog (!== "Yes" instead of === "No")
  • Plan revision counter only increments once per user message (prevents double-counting on internal loop iterations)
  • Approval phrase detection uses word-boundary regex + negation phrases ("not approved", "disapprove") to prevent false positives
  • Skip SQL suggestions (sql_execute, sql_analyze) for MongoDB warehouses
  • MCP safeDetail handles string commands with trim() + /\s+/ split

Code quality:

  • Remove dead hasWrite code and BSON serialization dead branch
  • Add text language tag to markdown code fence
  • Use regex instead of hardcoded slice for telemetry block matching in tests

Type of change

  • Bug fix (non-breaking change that fixes an issue)

Issue for this PR

Closes #577

How did you verify your code works?

  • All 13 plan-refinement tests pass
  • Full test suite: 2501 pass, 423 skip, 1 pre-existing fail (unrelated semver issue)
  • TypeScript type check passes (5/5 packages)
  • Marker check: no new violations in changed files
  • Multi-model code review (Claude, GPT 5.2, Gemini 3.1 Pro, Kimi K2.5, MiniMax M2.5, GLM-5) with convergence round

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Enhanced MongoDB pipeline safety by blocking unsafe write operations and operators.
    • Fixed approval/rejection detection for plan refinements with improved case-insensitive matching.
    • SQL-specific suggestions now properly excluded for MongoDB warehouse connections.
  • Improvements

    • Better support for MCP server command configuration formats.
    • Refined plan refinement tracking for more accurate revision counting.
  • Documentation

    • Updated code example formatting in agent modes documentation.

- fix(security): MongoDB aggregate now blocks nested `$function`/`$accumulator`
  via `JSON.stringify` scan (not just top-level stage keys)
- fix(security): block `$out`/`$merge` write stages separately with clear error
- fix(consent): `PlanExitTool` rejects dismissed/undefined dialog (`!== "Yes"`)
- fix(telemetry): plan revision counter only increments once per user message,
  not on internal loop iterations (`planLastUserMsgId` dedup)
- fix(telemetry): approval phrase detection uses word-boundary regex + negation
  phrases to prevent false positives ("not approved", "disapprove")
- fix(ux): skip SQL suggestions (`sql_execute`, `sql_analyze`) for MongoDB
- fix(mcp): `safeDetail` handles string commands with `trim()` + `/\s+/` split
- fix(docs): add `text` language tag to markdown code fence
- fix(test): use regex instead of hardcoded slice for telemetry block matching
- chore: remove dead `hasWrite` code and BSON serialization dead branch
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

📝 Walkthrough

Walkthrough

This PR addresses post-merge code review findings by implementing stricter MongoDB pipeline safety checks for $function and $accumulator operators, fixing plan revision double-counting logic, enhancing approval/rejection phrase detection with word boundaries, inverting plan tool consent validation, conditionally hiding SQL suggestions for MongoDB warehouses, and improving MCP server command string handling.

Changes

Cohort / File(s) Summary
Documentation
docs/docs/data-engineering/agent-modes.md
Updated fenced code block formatting from unspecified to text language specifier in "Example conversation" section.
MongoDB Pipeline Security
packages/drivers/src/mongodb.ts
Added validation to block pipelines containing top-level $out/$merge stages and nested $function/$accumulator operators; simplified serializeValue by removing array special-casing and consolidating to single JSON.stringify path.
OpenCode Tools
packages/opencode/src/altimate/tools/mcp-discover.ts, packages/opencode/src/altimate/tools/post-connect-suggestions.ts
Extended MCP safeDetail() to handle server.command as string in addition to array; filtered SQL-specific suggestions conditionally based on warehouse type (excluded for MongoDB).
Plan Approval & Refinement Logic
packages/opencode/src/session/prompt.ts, packages/opencode/src/tool/plan.ts
Refined plan revision tracking to count only on new user messages; upgraded approval detection to use case-insensitive word-boundary regex to prevent false positives; added "not approve", "disapprove" rejection phrases; inverted consent validation in plan exit/enter tools to reject non-"Yes" responses.
Test Improvements
packages/opencode/test/altimate/plan-refinement.test.ts
Simplified telemetry assertion by using direct regex capture instead of index-based slicing.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #556: Introduces overlapping changes to the same opencode modules (session/prompt.ts, plan tools, post-connect-suggestions, telemetry) and is the primary PR from which these post-merge fixes originate.

Suggested labels

contributor

Suggested reviewers

  • kulvirgit
  • mdesmet

Poem

🐰 A rabbit hops through logic chains,
Fixing counts and approval pains,
MongoDB pipelines now stand tall,
With word-bound words that catch them all! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically references addressing post-merge code review findings from PR #556, which aligns with the main objective of the changeset.
Description check ✅ Passed The PR description comprehensively covers all required template sections with detailed explanations of changes, testing performed, and a complete checklist, exceeding template requirements.
Linked Issues check ✅ Passed All 8 findings from issue #577 are addressed: MongoDB security fixes [#577], PlanExitTool rejection logic [#577], plan revision counter fix [#577], approval detection improvements [#577], SQL suggestions filtering [#577], MCP safeDetail enhancement [#577], dead code removal [#577], and test/documentation improvements [#577].
Out of Scope Changes check ✅ Passed All changes directly address the 8 tracked findings from issue #577 with no unrelated modifications; scope is tightly focused on the post-merge code review items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/code-review-556-followup

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/drivers/src/mongodb.ts (1)

354-364: Minor inconsistency with find truncation detection.

The $limit capping logic differs from the find command (lines 304-305). In find, the limit is always incremented by 1 (queryLimit + 1) to detect truncation. Here, when the user's limit is ≤ effectiveLimit, it's kept as-is without the +1.

Edge case: If a user specifies { $limit: 1000 } and effectiveLimit is also 1000, truncation won't be detected even if more documents exist.

This appears to be pre-existing behavior, but you may want to align with find for consistency:

🔧 Optional fix to align with `find` behavior
          const limitIdx = pipeline.findIndex((stage) => "$limit" in stage)
          if (limitIdx >= 0) {
-           // Cap user-specified $limit against effectiveLimit
            const userLimit = (pipeline[limitIdx] as any).$limit
-           if (typeof userLimit === "number" && userLimit > effectiveLimit) {
-             pipeline[limitIdx] = { $limit: effectiveLimit + 1 }
+           if (typeof userLimit === "number") {
+             // Cap user-specified $limit and add +1 for truncation detection
+             pipeline[limitIdx] = { $limit: Math.min(userLimit, effectiveLimit) + 1 }
            }
          } else {
            pipeline.push({ $limit: effectiveLimit + 1 })
          }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/drivers/src/mongodb.ts` around lines 354 - 364, The $limit handling
in the aggregation pipeline differs from the find path: when a $limit stage
exists and the user's $limit is ≤ effectiveLimit you currently leave it
unchanged, which prevents detection of truncation; update the logic in the block
that examines pipeline, limitIdx and userLimit so that whenever a $limit is
present you set it to (min(userLimit, effectiveLimit) + 1) (i.e., always add +1
for truncation detection), and when no $limit exists continue to push { $limit:
effectiveLimit + 1 }; ensure you still only modify numeric userLimit values and
preserve behavior for non-numeric/missing cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/session/prompt.ts`:
- Line 326: The tracker variable planLastUserMsgId is currently unset and later
updated from the last user message of any kind, causing synthetic/internal user
turns to be counted as new plan revisions; modify the logic that
initializes/updates planLastUserMsgId (the variable declared as
planLastUserMsgId) so that when the plan file is first detected you seed
planLastUserMsgId from the most recent user message that contains a
non-synthetic text part (i.e., skip synthetic user turns created in the
synthetic-user-turn creation block around Lines 571-589), and apply the same fix
to the analogous update logic around Lines 641-646 so only genuine user text
messages move currentUserMsgId/planLastUserMsgId and increment revision_number.

---

Nitpick comments:
In `@packages/drivers/src/mongodb.ts`:
- Around line 354-364: The $limit handling in the aggregation pipeline differs
from the find path: when a $limit stage exists and the user's $limit is ≤
effectiveLimit you currently leave it unchanged, which prevents detection of
truncation; update the logic in the block that examines pipeline, limitIdx and
userLimit so that whenever a $limit is present you set it to (min(userLimit,
effectiveLimit) + 1) (i.e., always add +1 for truncation detection), and when no
$limit exists continue to push { $limit: effectiveLimit + 1 }; ensure you still
only modify numeric userLimit values and preserve behavior for
non-numeric/missing cases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 99efba67-0cff-4668-9824-1c35815f41f9

📥 Commits

Reviewing files that changed from the base of the PR and between 2180ce0 and 930e5b3.

📒 Files selected for processing (7)
  • docs/docs/data-engineering/agent-modes.md
  • packages/drivers/src/mongodb.ts
  • packages/opencode/src/altimate/tools/mcp-discover.ts
  • packages/opencode/src/altimate/tools/post-connect-suggestions.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/tool/plan.ts
  • packages/opencode/test/altimate/plan-refinement.test.ts

// altimate_change start — plan refinement tracking
let planRevisionCount = 0
let planHasWritten = false
let planLastUserMsgId: string | undefined
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This still counts non-feedback turns as plan revisions.

planLastUserMsgId starts unset, so once the plan file is first created the next internal loop will treat the same user prompt as a new revision. It also pulls currentUserMsgId from the last user message of any kind, so the synthetic user turns created on Lines 571-589 can increment the counter again. That makes revision_number telemetry drift and can hit the 5-revision cap early. Seed the tracker when the plan file first appears, and derive it from the last user message with a non-synthetic text part.

Also applies to: 641-646

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/session/prompt.ts` at line 326, The tracker variable
planLastUserMsgId is currently unset and later updated from the last user
message of any kind, causing synthetic/internal user turns to be counted as new
plan revisions; modify the logic that initializes/updates planLastUserMsgId (the
variable declared as planLastUserMsgId) so that when the plan file is first
detected you seed planLastUserMsgId from the most recent user message that
contains a non-synthetic text part (i.e., skip synthetic user turns created in
the synthetic-user-turn creation block around Lines 571-589), and apply the same
fix to the analogous update logic around Lines 641-646 so only genuine user text
messages move currentUserMsgId/planLastUserMsgId and increment revision_number.

@anandgupta42 anandgupta42 merged commit e1c6cae into main Mar 29, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Address post-merge code review findings from PR #556

1 participant