Skip to content

M2.2.5#57

Merged
AashishH15 merged 59 commits into
mainfrom
M2.2.5
Jun 15, 2026
Merged

M2.2.5#57
AashishH15 merged 59 commits into
mainfrom
M2.2.5

Conversation

@fiorittoev

Copy link
Copy Markdown
Collaborator

M2.2.5 — Pending Changeset Correction & Amendment — Commit Plan

Roadmap alignment (Concepts/MindVault_Roadmap_v08.md §M2.2.5):
The debounce gate (≥ 6 messages + 2-minute cooldown) is the right call for general extraction — you don't want to hit the LLM on every message. But it's too blunt to handle corrections well. This milestone layers three complementary approaches (correction detection, changeset amendment, manual trigger) to differentiate MindVault's memory UX and ensure pending changesets remain clean and accurate before the user ever sees them.

M2.2.5 sits directly between the shipped M2.2 (Memory Diff Panel) and M2.3 (Embedding Engine). It does not require embeddings and operates entirely on the existing Jaccard/rule-based pipeline.

What already exists in the repo (grounding):

Asset Location Relevance
Debounced extraction trigger core/src/memory_agent/trigger.rs (should_extract, mark_extraction_complete) GATE LOGIC — evaluates ≥ 6 messages + 2-minute debounce. M2.2.5 Layer 1 must bypass this gate when correction signals are detected.
Extraction pipeline core/src/lib.rs (execute_memory_extraction_pipeline, memory_extract_if_ready) PIPELINE — full end-to-end extraction: loads chat, calls LLM, parses candidates, builds changeset, persists. Layer 1 will invoke this pipeline directly.
Changeset persistence core/src/memory_agent/persistence.rs (persist_changeset, list_pending_changesets, list_changeset_items) DATA PLUMBING — persists new changesets and retrieves pending items. Layer 2 will amend existing items in-place rather than creating new changesets.
Changeset builder core/src/memory_agent/changeset.rs (build_changeset) DEDUP ENGINE — builds PendingChangeset from candidates using Jaccard similarity matching against existing nodes.
Changeset item schema db/migrations/0001_schema_v1.sql L130–143 DURABLE STRUCTURE — changeset_items table with proposed_data, existing_data, similarity, status, and sort_order columns.
Frontend extraction call ui/components/ChatPanel.tsx L580 UI TRIGGER — fire-and-forget extractMemoryIfReady() call after every assistant response. Layer 1 needs a parallel path for correction-triggered extractions.
Memory Agent service layer ui/services/memoryAgent.ts (extractMemory, extractMemoryIfReady) IPC WRAPPERS — TypeScript wrappers for Tauri memory_extract and memory_extract_if_ready commands.
Global proposals badge ui/App.tsx UI BADGE — rendered badge in the global top bar showing the real-time count of pending changeset items.
Diff Panel ui/components/DiffPanel.tsx, DiffPanel/DiffRow.tsx REVIEW UI — displays pending changeset items with side-by-side diffs, inline actions, and history. Layer 2 amended items will need an (amended) badge here.
IPC types core/src/ipc_types.rs + ui/types/generated/ TYPE BRIDGE — TS-binding structs for Changeset, ChangesetItem, ChangesetCommitInput.

Current Status

The Memory Agent (M2.1) and Diff Panel (M2.2) are fully shipped. Background extraction runs on a debounced trigger after ≥ 6 new messages with a 2-minute cooldown. M2.2.5 adds intelligence to handle correction scenarios that the fixed debounce gate misses.

Commit Focus Area Status
1 — Correction Signal Detector (Backend) Lightweight heuristic pattern matcher running on every message [ ] Planned
2 — Correction-Triggered Extraction (Backend) Gate bypass logic, targeted extraction, and IPC plumbing [ ] Planned
3 — Pending Changeset Amendment Engine (Backend) In-place changeset item updates instead of duplicate creation [ ] Planned
4 — Manual "Extract Now" Trigger (Frontend + Backend) Chat toolbar button and force-extraction IPC command [ ] Planned
5 — Diff Panel Amendment Badge & Integration Tests (amended) badge rendering + comprehensive E2E test coverage [ ] Planned

Implementation Plan — Commits (Specific)

Commit 1 — Correction Signal Detector (Backend) (core/src/memory_agent/)

Goal: Build a lightweight, local heuristic that evaluates every incoming user message for correction signals. No LLM calls — pure pattern matching. This is the foundation that Commit 2 uses to decide whether to bypass the debounce gate.

Files to create/modify:

  • Create core/src/memory_agent/correction.rs:
    • Define the correction signal heuristic as a pure function:
      /// Evaluates whether a user message contains correction signals.
      /// Returns `Some(CorrectionSignal)` if detected, `None` otherwise.
      pub fn detect_correction_signal(
          message: &str,
          previous_message: Option<&str>,
          pending_proposed_data: &[String],
      ) -> Option<CorrectionSignal>
    • Define the CorrectionSignal enum:
      #[derive(Debug, Clone, PartialEq)]
      pub enum CorrectionSignal {
          /// Explicit correction phrases: "actually," "wait," "I meant," "not X, Y," etc.
          ExplicitPhrase { phrase: String },
          /// Direct negation of a prior message value
          Negation { negated_fragment: String },
          /// Contradiction of a field in a pending changeset item
          ChangesetContradiction { contradicted_field: String },
      }
    • Implement three detection layers inside detect_correction_signal:
      1. Explicit Phrase Scan: Tokenize the message into lowercase words. Check against a static CORRECTION_PHRASES list:
        const CORRECTION_PHRASES: &[&str] = &[
            "actually", "actually,", "wait,", "wait", "i meant",
            "not that", "correction", "correction:", "to clarify",
            "scratch that", "never mind", "nevermind", "no wait",
            "i was wrong", "let me correct", "that's wrong",
            "that's not right", "i misspoke",
        ];
        Match using a sliding window of 1–3 consecutive word tokens against each phrase. Return CorrectionSignal::ExplicitPhrase on first match.
      2. Direct Negation Scan: If previous_message is provided, check if the current message contains explicit negation patterns targeting a value from the previous message:
        • Pattern: "not <WORD>" or "no, <WORD>" where <WORD> appears in the previous message.
        • Pattern: "it's <VALUE>, not <VALUE>" — detects replacement patterns.
        • Return CorrectionSignal::Negation with the negated fragment.
      3. Pending Changeset Contradiction Scan: Iterate pending_proposed_data (JSON strings). For each, extract the title and summary fields. Check if the current message contradicts any of those values:
        • Heuristic: if the message contains "not <extracted_value>" or "<extracted_value> is wrong", flag it.
        • Return CorrectionSignal::ChangesetContradiction with the contradicted field name.
    • Implement a public convenience wrapper:
      /// Returns `true` if any correction signal is detected in the message.
      pub fn has_correction_signal(
          message: &str,
          previous_message: Option<&str>,
          pending_proposed_data: &[String],
      ) -> bool
  • Modify core/src/memory_agent/mod.rs:
    • Add pub mod correction; and re-export:
      pub use correction::{detect_correction_signal, has_correction_signal, CorrectionSignal};

Verify: cargo test compiles. Unit tests for phrase detection, negation scanning, and contradiction detection all pass (tests included in correction.rs #[cfg(test)] module).


Commit 2 — Correction-Triggered Extraction (Backend) (core/src/memory_agent/trigger.rs, core/src/lib.rs)

Goal: Wire the correction signal detector into the message processing pipeline so that when a correction is detected, the debounce gate is bypassed and a targeted extraction fires immediately.

Files to create/modify:

  • Modify core/src/memory_agent/trigger.rs:
    • Add a new public function that evaluates correction-based extraction readiness:
      /// Evaluates whether a correction signal should bypass the standard debounce gate.
      /// Returns true if a correction was detected AND there are at least 3 messages
      /// in the session (minimum viable context for extraction).
      pub fn should_extract_correction(
          conn: &Connection,
          session_id: &str,
          message: &str,
      ) -> Result<bool, String>
    • Implementation:
      1. Query the latest user message prior to this one (previous_message) from session_messages.
      2. Query all pending changeset_items with status 'pending' and extract their proposed_data column values.
      3. Call correction::has_correction_signal(message, previous_message, &pending_data).
      4. If a signal is detected AND current_message_count >= 3, return true.
      5. Otherwise return false.
    • Re-export in mod.rs:
      pub use trigger::{mark_extraction_complete, should_extract, should_extract_correction};
  • Modify core/src/lib.rs (memory_extract_if_ready function):
    • After the existing should_extract() check (which may return false due to debounce), add a second path:
      // If standard debounce says not ready, check for correction signals
      if !ready {
          let latest_user_msg = fetch_latest_user_message(&conn, session_id)?;
          if let Some(msg_content) = latest_user_msg {
              let correction_ready = memory_agent::trigger::should_extract_correction(
                  &conn, session_id, &msg_content
              )?;
              if correction_ready {
                  ready = true;
              }
          }
      }
    • Add a private helper fetch_latest_user_message(conn, session_id) -> Result<Option<String>, String> that queries the most recent user-role message content from session_messages.
  • Modify ui/ipc.ts (if needed):
    • No changes needed — the existing memoryExtractIfReady IPC command already returns Option<Changeset> which handles both the standard and correction-triggered paths transparently.

Verify: cargo test compiles. When a correction phrase is present in the latest message, memory_extract_if_ready returns a changeset even though the standard debounce gate would have blocked it.


Commit 3 — Pending Changeset Amendment Engine (Backend) (core/src/memory_agent/)

Goal: When a correction-triggered extraction produces new candidates that overlap with items in an existing pending changeset, amend the existing changeset items in-place rather than creating a duplicate changeset. This keeps the Diff Panel clean.

Files to create/modify:

  • Create core/src/memory_agent/amendment.rs:
    • Define the core amendment function:
      /// Attempts to amend an existing pending changeset with new extraction results.
      /// Returns `true` if amendments were made, `false` if a new changeset was created instead.
      pub fn amend_or_create_changeset(
          conn: &Connection,
          candidates: &[CandidateNode],
          session_id: &str,
          model: &str,
      ) -> Result<(String, bool), String>
    • Implementation:
      1. Find existing pending changeset: Query changesets WHERE session_id = ?1 AND status = 'pending' ORDER BY created_at DESC LIMIT 1.
      2. If no pending changeset exists: Fall through to the standard build_changeset → persist_changeset path. Return (new_changeset_id, false).
      3. If a pending changeset exists:
        a. Load all pending changeset_items for that changeset.
        b. For each new candidate, compute Jaccard similarity against each existing pending item's proposed_data (title + summary).
        c. If similarity > 50% (same candidate, corrected values), update the existing changeset_items row in-place:
        UPDATE changeset_items
        SET proposed_data = ?1,
            similarity = ?2,
            reviewed_at = NULL,
            sort_order = sort_order
        WHERE id = ?3;
        Also mark the item as amended by prepending "amended": true into the proposed_data JSON.
        d. If no match is found (genuinely new candidate), insert as a new changeset_items row into the existing changeset and increment changesets.item_count.
        e. Return (existing_changeset_id, true).
    • Add amended_at metadata into the proposed_data JSON payload (ISO timestamp) so the Diff Panel can render the (amended) badge without a schema migration:
      proposed_json["_amended"] = serde_json::json!({
          "at": chrono_now_iso(),
          "reason": format!("{:?}", correction_signal),
      });
  • Modify core/src/lib.rs (execute_memory_extraction_pipeline):
    • Add an optional parameter is_correction: bool (default false).
    • When is_correction == true, call amendment::amend_or_create_changeset() instead of the standard build_changeset → persist_changeset path.
    • Thread the is_correction flag through from memory_extract_if_ready when the correction path was taken.
  • Modify core/src/memory_agent/mod.rs:
    • Add pub mod amendment; and re-export:
      pub use amendment::amend_or_create_changeset;

Verify: cargo test compiles. When a correction-triggered extraction fires and a pending changeset already exists, the existing items are updated in-place rather than duplicated.


Commit 4 — Manual "Extract Now" Trigger (Frontend + Backend) (ui/components/ChatPanel.tsx, core/src/lib.rs)

Goal: Add a small button in the chat input toolbar that lets the user force an extraction on demand, bypassing the debounce gate entirely. This serves as a safety net and escape hatch for edge cases the automatic detector misses.

Files to create/modify:

  • Modify core/src/lib.rs:
    • Add a new Tauri command memory_extract_force:
      #[tauri::command]
      async fn memory_extract_force(
          provider: String,
          endpoint: String,
          model: String,
          state: tauri::State<'_, AppState>,
      ) -> Result<Changeset, String> {
          check_rate_limit("memory_agent")?;
          let db_path = state.db_path.clone();
          let conn = open_connection(&db_path)?;
      
          // Verify minimum message threshold (at least 3 messages)
          let count: i64 = conn.query_row(
              "SELECT COUNT(*) FROM session_messages WHERE session_id = 'default-session';",
              [], |row| row.get(0),
          ).map_err(|err| format!("Failed querying message count: {err}"))?;
          if count < 3 {
              return Err("Need at least 3 messages to extract memory.".to_string());
          }
      
          drop(conn);
      
          // Execute pipeline (always as correction=true to enable amendment)
          let result = execute_memory_extraction_pipeline(
              provider, endpoint, model, db_path.clone(), true
          ).await;
      
          // Mark extraction complete
          let conn = open_connection(&db_path)?;
          memory_agent::trigger::mark_extraction_complete(&conn, count)?;
      
          result
      }
    • Register memory_extract_force in the Tauri command handler list.
  • Modify ui/ipc.ts:
    • Add the IPC wrapper:
      export function memoryExtractForce(
        provider: string,
        endpoint: string,
        model: string
      ): Promise<IpcResponse<Changeset>> {
        return invoke<IpcResponse<Changeset>>("memory_extract_force", {
          provider, endpoint, model,
        });
      }
  • Modify ui/services/memoryAgent.ts:
    • Add the service wrapper:
      /**
       * Forces an immediate memory extraction, bypassing the debounce gate.
       * Used by the manual "Extract Now" chat toolbar button.
       */
      export async function extractMemoryForce(
        provider: string,
        endpoint: string,
        model: string
      ): Promise<Changeset> {
        const result = await unwrapIpcResult(memoryExtractForce(provider, endpoint, model));
        clearNodesCache();
        return result;
      }
  • Modify ui/components/ChatPanel.tsx:
    • Import extractMemoryForce from ../services/memoryAgent.
    • Add state: const [isExtracting, setIsExtracting] = useState(false);
    • Add handler:
      const handleForceExtract = useCallback(async () => {
        if (isExtracting || isSending) return;
        setIsExtracting(true);
        try {
          const { provider, endpoint, model } = await resolveLlmConfig();
          await extractMemoryForce(provider, endpoint, model);
          onRefreshPendingCount?.();
        } catch (err) {
          console.error("Manual extraction failed:", err);
          setStatus(String(err));
        } finally {
          setIsExtracting(false);
        }
      }, [isExtracting, isSending, onRefreshPendingCount]);
    • Render button in the chat input area (next to the send button or in the pills row):
      <button
        className="extract-now-btn"
        onClick={handleForceExtract}
        disabled={isExtracting || isSending}
        title="Extract memories now"
      >
        {isExtracting ? "⏳" : "✨"}
      </button>
  • Modify ui/App.css (or relevant CSS file):
    • Add styling for .extract-now-btn:
      .extract-now-btn {
        background: transparent;
        border: 1px solid rgba(255, 255, 255, 0.15);
        border-radius: 8px;
        padding: 6px 10px;
        cursor: pointer;
        font-size: 14px;
        transition: all 0.2s ease;
        color: rgba(255, 255, 255, 0.7);
      }
      .extract-now-btn:hover:not(:disabled) {
        background: rgba(255, 255, 255, 0.08);
        border-color: rgba(255, 255, 255, 0.25);
        color: rgba(255, 255, 255, 0.95);
      }
      .extract-now-btn:disabled {
        opacity: 0.4;
        cursor: not-allowed;
      }

Verify: Clicking the ✨ button in the chat toolbar triggers an immediate extraction regardless of debounce state. The pending proposals badge updates. The button shows ⏳ while extraction is in progress and disables during active sends.


Commit 5 — Diff Panel Amendment Badge & Integration Tests (ui/components/DiffPanel/, core/tests/)

Goal: Surface amended changeset items with a visible (amended) badge in the Diff Panel so the user knows a correction was self-applied. Write comprehensive integration tests for the entire correction → amendment → display pipeline.

Files to create/modify:

  • Modify ui/components/DiffPanel/DiffRow.tsx:
    • Parse the _amended metadata from item.proposedData:
      const proposedJson = JSON.parse(item.proposedData || "{}");
      const isAmended = proposedJson._amended != null;
      const amendedAt = isAmended ? proposedJson._amended.at : null;
    • Render the (amended) badge next to the item type badge when isAmended is true:
      {isAmended && (
        <span className="diff-amended-badge" title={`Amended at ${amendedAt}`}>
          (amended)
        </span>
      )}
  • Modify ui/style/components/DiffPanel.css:
    • Add styling for .diff-amended-badge:
      .diff-amended-badge {
        display: inline-flex;
        align-items: center;
        font-size: 11px;
        font-weight: 500;
        color: rgba(251, 191, 36, 0.9);
        background: rgba(251, 191, 36, 0.1);
        border: 1px solid rgba(251, 191, 36, 0.2);
        border-radius: 6px;
        padding: 1px 6px;
        margin-left: 6px;
        letter-spacing: 0.02em;
      }
  • Create core/tests/correction_amendment.rs:
    • test_detect_explicit_correction_phrase(): Feed messages containing "actually," "wait," "I meant" — assert CorrectionSignal::ExplicitPhrase is returned.
    • test_detect_negation_of_previous_message(): Feed a previous message "My favorite color is blue" and current message "not blue, it's green" — assert CorrectionSignal::Negation is detected.
    • test_detect_changeset_contradiction(): Create a pending changeset with proposed_data: {"title": "Blue Theme"}, feed message "actually it should be green theme" — assert CorrectionSignal::ChangesetContradiction.
    • test_no_false_positive_on_neutral_message(): Feed neutral messages like "tell me about rust" — assert no correction signal is detected.
    • test_should_extract_correction_bypasses_debounce(): Set up a session with a correction message where should_extract() returns false (debounce active), but should_extract_correction() returns true.
    • test_amend_existing_changeset_in_place(): Create a pending changeset with an item, run amend_or_create_changeset with a corrected candidate. Assert the original changeset_items row was updated in-place, not duplicated. Verify _amended metadata is present in proposed_data.
    • test_amend_creates_new_when_no_pending_exists(): Run amend_or_create_changeset with no prior pending changeset. Assert a new changeset is created normally.
    • test_amend_appends_genuinely_new_candidate(): Create a pending changeset with item A, run amendment with unrelated candidate B. Assert B is inserted as a new row and item_count is incremented.
    • test_force_extract_minimum_message_threshold(): Call memory_extract_force with fewer than 3 messages. Assert it returns an error.

Verify: cargo test --test correction_amendment passes all test suites. Diff Panel renders (amended) badges correctly on items that were updated in-place.


Ordering and Dependencies

The correction signal detector is a pure function with no external dependencies, making it the natural starting point. Commits 2 and 3 build on it sequentially. The manual trigger (Commit 4) is independent of the correction heuristic and can be developed in parallel. The badge and tests (Commit 5) finalize the feature.

Commit 1 (Correction Detector)  ── Commit 2 (Gate Bypass)  ── Commit 3 (Amendment Engine)
                                                                         │
                                                                         └── Commit 5 (Badge + Tests)
                                                                                      │
Commit 4 (Manual Trigger)  ─────────────────────────────────────────────────────────── ┘

What M2.2.5 does NOT include (deferred)

Feature Deferred to
Cosine similarity for amendment matching M2.3 (Upgrades Jaccard to embeddings)
LLM-powered correction detection M2.7a (Streaming + constrained decoding enables structured correction analysis)
Multi-session correction tracking M3.7 (Memory Consolidation Nightly Job)
Correction pattern learning/personalization M2.7b (Per-vault policy model + training loop)
Schema migration for amended_at column Not needed — amendment metadata is embedded inside the existing proposed_data JSON column

Key Files Touched (Summary)

File Action Description
core/src/memory_agent/correction.rs Create Lightweight correction signal detection heuristic (explicit phrases, negation, changeset contradiction).
core/src/memory_agent/amendment.rs Create In-place changeset item amendment engine with _amended JSON metadata injection.
core/src/memory_agent/mod.rs Modify Re-export correction and amendment modules.
core/src/memory_agent/trigger.rs Modify Add should_extract_correction() — correction-aware gate bypass evaluation.
core/src/lib.rs Modify Wire correction path into memory_extract_if_ready, add memory_extract_force command, add fetch_latest_user_message helper.
core/tests/correction_amendment.rs Create E2E integration tests for correction detection, debounce bypass, in-place amendment, and force extraction.
ui/ipc.ts Modify Add memoryExtractForce IPC wrapper.
ui/services/memoryAgent.ts Modify Add extractMemoryForce service wrapper.
ui/components/ChatPanel.tsx Modify Add ✨ "Extract Now" button with loading state in chat input toolbar.
ui/components/DiffPanel/DiffRow.tsx Modify Parse _amended metadata from proposed_data and render (amended) badge.
ui/style/components/DiffPanel.css Modify Add .diff-amended-badge styling (amber glassmorphic pill).
ui/App.css Modify Add .extract-now-btn styling for manual trigger button.

…ections

node not found text if it is a broken connection, instead of showing the link with throw a warning
Built a lightweight, local heuristic that evaluates every incoming user message for correction signals
@fiorittoev fiorittoev requested a review from AashishH15 June 14, 2026 18:24
@fiorittoev fiorittoev self-assigned this Jun 14, 2026
@fiorittoev fiorittoev added bug Something isn't working enhancement New feature or request labels Jun 14, 2026

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline, allowing users to manually force memory extraction and amend existing pending changesets. It adds backend modules for detecting correction signals and managing amendments, along with UI updates like persistent icon rails, a chat history panel, and visual badges for amended items. The review highlights several critical issues in the correction and amendment logic, including comparing plain text against raw JSON strings, querying the wrong previous message in the database, bypassing the contradiction scan during pipeline execution, discarding metadata fields during candidate serialization, and a redundant negation check formatting the same word twice.

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 core/src/memory_agent/correction.rs Outdated
Comment thread core/src/memory_agent/trigger.rs Outdated
Comment thread core/src/lib.rs Outdated
Comment thread core/src/memory_agent/amendment.rs Outdated
Comment thread core/src/memory_agent/correction.rs Outdated
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@fiorittoev fiorittoev linked an issue Jun 15, 2026 that may be closed by this pull request

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline, allowing users to correct previous extractions through explicit phrases, negations, or contradictions. It adds a forced memory extraction command, persistent sidebar icon rails, a decoupled chat panel, and a new WikiLinkBadge component to handle broken node links. Key feedback includes resolving a compilation error on stable Rust by replacing the unstable is_multiple_of method with the modulo operator, fixing a database query in should_extract_correction to correctly fetch the previous message using an offset, wrapping resolveLlmConfig in useCallback to avoid unnecessary re-renders, and optimizing WikiLinkBadge to prevent a flood of redundant getAllNodes() IPC calls on mount.

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 core/src/memory_agent/amendment.rs Outdated
Comment thread core/src/memory_agent/trigger.rs
Comment thread ui/components/ChatPanel.tsx Outdated
Comment thread ui/utils/markdownUtils.tsx Outdated
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline to the backend, allowing the system to detect correction signals in user messages and update pending changesets in-place. It also adds a force-extraction command and corresponding UI controls, introduces persistent icon rails for sidebar navigation, and enhances the WikiLinkBadge component to validate node connections. The reviewer feedback highlights several critical issues, including potential cross-session data contamination due to missing session filters in database queries, a cache-clearing regression in the frontend node service, a potential runtime panic from unsafe UTF-8 string slicing, and non-deterministic database ordering.

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 core/src/lib.rs Outdated
Comment thread core/src/memory_agent/trigger.rs
Comment thread ui/services/nodes.ts
Comment thread core/src/memory_agent/amendment.rs
Comment thread core/src/memory_agent/amendment.rs
Comment thread core/src/memory_agent/amendment.rs Outdated
Comment thread core/src/memory_agent/correction.rs Outdated
Comment thread core/src/memory_agent/correction.rs Outdated
Comment thread core/src/memory_agent/trigger.rs Outdated
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline to detect correction signals in user messages and update pending changesets in-place. It also adds a manual memory extraction command, replaces sidebar toggles with persistent icon rails, and enhances the UI to display amended badges and validate wiki-link node existence. The review feedback focuses on improving the Rust implementation in amendment.rs by simplifying JSON manipulation in stamp_amended using as_object_mut(), replacing manual timestamp decomposition with the chrono crate, and removing a redundant SQL assignment.

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 core/src/memory_agent/amendment.rs
Comment thread core/src/memory_agent/amendment.rs
Comment thread core/src/memory_agent/amendment.rs
Body: Replaced as_object() + new Map allocation + clone-all-entries with a single as_object_mut() + in-place insert
Call site: Removed .map_err(...) error handling, now just stamp_amended(&mut candidate_data, ...)
This eliminates an unnecessary heap allocation, O(n) key/value cloning, and error-handling boilerplate for a condition that can never occur.
…is_leap) with a compact 32-line implementation using Howard Hinnant's civil-date algorithm. Key improvements:

Eliminated is_leap helper — no longer needed; leap year math is handled implicitly by the era-based algorithm
O(1) date calculation — the old code iterated year-by-year from 1970 (loop { year += 1 }) and month-by-month; the new algorithm computes the result directly via integer arithmetic
…DATE query in amendment.rs:255-257. Setting a column to its own value has no effect and just adds noise to the query.
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline to the memory agent, allowing the system to detect correction signals in user messages and update pending changesets in-place. It also adds a manual memory extraction button, persistent icon rails for sidebar navigation, and a WikiLinkBadge component to handle broken node connections. Feedback on these changes highlights a layout issue where the (amended) badge in the diff panel renders on a new line instead of inline, and suggests architectural improvements to avoid duplicate CorrectionSignal detection and to replace the complex custom ISO timestamp generator with the standard chrono crate.

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 ui/components/DiffPanel.tsx
Comment thread core/src/lib.rs Outdated
Comment thread core/src/memory_agent/amendment.rs
Refactored chrono_now_iso: Simplified the function in amendment.rs to utilize chrono::Utc::now(), replacing the custom time decomposition arithmetic.
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline in the backend, along with a manual force-extraction command. On the frontend, it decouples the chat panel, introduces persistent left and right icon rails for switching views, adds a manual extraction button, and implements a WikiLinkBadge to handle broken node connections gracefully. Feedback on these changes highlights a performance issue with ChatPanel's background node fetching when hidden, a potential UI bug when interpolating React.ReactNode directly into string templates within WikiLinkBadge, and a performance concern regarding the O(N * M) complexity of the backend negation scan algorithm.

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 ui/components/ChatPanel.tsx Outdated
Comment thread ui/utils/markdownUtils.tsx
Comment thread core/src/memory_agent/correction.rs
ChatPanel.tsx
 to accept an optional visible?: boolean prop (defaulting to true).
Guarded useEffect: Guarded the node refresh effect in

ChatPanel.tsx
 to skip cache clearing and database querying if visible is false. Added visible to the dependency array.
Propagated State: Passed visible={viewMode === "chat"} from

App.tsx
 to the mounted <ChatPanel> component.
…inkBadge in

markdownUtils.tsx
 that extracts a clean, concatenated string representation from a React.ReactNode (handling strings, numbers, arrays, and recursively traversing nested React elements).
Replaced Interpolations: Substituted ${children} with ${labelText} inside all tooltip titles and modal alert template strings to prevent [object Object] rendering.
Build a HashSet containing the words from the previous_message (ignoring non-alphanumerics and stopwords).
Tokenize the message_lower and iterate to find occurrences of the negation words "not" and "no".
Perform an $O(1)$ lookup in the HashSet for the adjacent subsequent word.
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline, allowing the system to detect correction signals in user messages and update pending changesets in-place. It also adds a manual memory extraction command, replaces the floating sidebar toggles with persistent left and right icon rails, and enhances wikilink rendering with broken link detection. The review feedback highlights a compilation-breaking type mismatch in a test helper where DbState is used instead of AppState, and points out an unnecessary cache clearing call in the chat panel's visibility effect that degrades performance.

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 core/src/lib.rs Outdated
Comment thread ui/components/ChatPanel.tsx
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a correction-based memory extraction pipeline and refactors the UI sidebar layout. On the backend, new modules for detecting correction signals and amending pending changesets in-place have been added, alongside a manual force-extraction command. On the frontend, persistent icon rails have been introduced to switch between panels, and a shared context has been added to validate wiki-link badges. The review feedback highlights opportunities to prevent redundant API fetches by distinguishing between loading and unprovided context states in the wiki-link badge, and to optimize database performance by checking the message count threshold early in the correction trigger evaluation.

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 ui/utils/markdownUtils.tsx
Comment thread ui/utils/markdownUtils.tsx Outdated
Comment thread core/src/memory_agent/trigger.rs Outdated
markdownUtils.tsx:169
 to undefined (representing "no provider present") instead of null.
Refactored useEffect Guard: Updated the guard inside WikiLinkBadge's mount check
trigger.rs:119-165 to query and check message_count as the first operation in should_extract_correction.
Early Exit: If message_count < 3, the function immediately short-circuits and returns Ok(None). This avoids executing the heavier SQLite queries for the previous message, pending changeset items, and any negation/phrase scanning logic.
@AashishH15

Copy link
Copy Markdown
Member

/gemini review --depth=exhaustive --include-dependencies

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a memory correction and amendment pipeline, allowing users to correct previous memory extractions and amend changesets in-place. It also adds a manual force extraction option, refactors the UI to use persistent icon rails with a new chat history panel, and improves WikiLink rendering with broken connection detection. The review feedback highlights critical issues: a potential race condition in amend_or_create_changeset that can be resolved by starting the transaction earlier, a logical bug where correction signals are bypassed if the standard debounce gate is open, and a UI bug in WikiLinkBadge where checking existingNodeIds !== undefined instead of truthiness causes a permanent loading state when the context is null.

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 core/src/memory_agent/amendment.rs
Comment thread core/src/lib.rs
Comment thread ui/utils/markdownUtils.tsx
…SQLite Connection::transaction() at the very beginning of the amend_or_create_changeset function.

Propagated Transaction Reference: Passed &tx (which derefs to &Connection) to find_pending_changeset(&tx, ...) and load_pending_items(&tx, ...).
Simplified Flow: Removed the nested transaction blocks for creating fresh changesets (path 2a) and updating pending changesets (path 2b). All operations (reading the database for a pending changeset, building the changeset, persisting it, or updating matching changeset items) now run inside a single transaction and are fully atomic.
…eve the latest user message and scan it for a CorrectionSignal, regardless of the value returned by should_extract.

Atomic/Isolated Flow: If a CorrectionSignal is detected, ready is set to true and the signal is correctly captured and propagated to the amendment pipeline.
…ail.tsx:277 to pass existingNodeIds directly to the ExistingNodesContext.Provider (removing the legacy ?? null default logic).
@AashishH15 AashishH15 merged commit d15bfe9 into main Jun 15, 2026
7 checks passed
@fiorittoev fiorittoev deleted the M2.2.5 branch June 15, 2026 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Chat - Halted generation when view changed [Bug]: Node Edit Focus View - Non existing node connections show the same as existing connections

2 participants