Skip to content

fix(ui): make alert confirmations reliable - #2072

Merged
yyhhyyyyyy merged 13 commits into
devfrom
fix/alert-dialog-confirmation-contract
Jul 31, 2026
Merged

fix(ui): make alert confirmations reliable#2072
yyhhyyyyyy merged 13 commits into
devfrom
fix/alert-dialog-confirmation-contract

Conversation

@yyhhyyyyyy

@yyhhyyyyyy yyhhyyyyyy commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Enforce click-before-close semantics for the shared AlertDialogAction and AlertDialogCancel wrappers.
  • Add AlertDialogAsyncAction for operations that must retain pending, failure, and retry state.
  • Migrate destructive async flows, including Memory deletion, data reset, sandbox cleanup, OCR cache cleanup, provider rate-limit disable, Skill overwrite, directive deletion, persona rollback, and built-in knowledge removal.
  • Replace ambiguous Memory boolean results with structured applied | rejected results and reason-specific feedback.
  • Add source guards and real Reka primitive tests to prevent lifecycle workarounds and false-positive button stubs.

Root Cause

Reka's DialogClose bubbling handler ran before consumer @click handlers. Controlled dialogs therefore emitted update:open=false first, allowing open-change handlers to clear the confirmation target before the business operation ran.

Async operations had a related ownership problem: the dialog could close before pending or failure state settled, hiding errors and removing retry context.

UI Behavior

BEFORE

Memory delete / Skill overwrite
  click
    └─> DialogClose emits open=false
          └─> target or callback is cleared
                └─> business handler sees empty state
                      └─> operation becomes a no-op

Async destructive action
  click
    └─> dialog closes immediately
          └─> pending and failure UI is unmounted

AFTER

Synchronous confirmation
  click
    └─> business handler runs exactly once
          └─> DialogClose closes the dialog

Asynchronous confirmation
  click
    └─> snapshot target
          └─> pending
                ├─> success ──> explicit close
                └─> failure ──> dialog stays open ──> retry

Summary by CodeRabbit

  • New Features

    • Added reliable asynchronous confirmation dialogs with loading states, retries, cancellation, and clearer error feedback.
    • Memory actions now provide specific success and rejection outcomes.
    • Added automatic refresh and reconciliation when memory data changes during an action.
    • Added localized memory-operation feedback across supported languages.
  • Documentation

    • Added architecture documentation covering confirmation behavior and acceptance criteria.
  • Quality Improvements

    • Added automated validation and expanded coverage for confirmation dialogs and memory operations.

@dosubot

dosubot Bot commented Jul 31, 2026

Copy link
Copy Markdown

📄 Knowledge review

Dosu skipped reviewing this PR because your organization has used its 200 included credits for the month. Your usage will reset on 2026-08-01. To have Dosu review this PR before then, ask your organization admin to upgrade to a pro account.


Leave Feedback Ask Dosu about deepchat Add Dosu to your team

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea3ed302-ede6-46db-a456-857fb3e9077d

📥 Commits

Reviewing files that changed from the base of the PR and between a9bfd81 and 7e253f9.

📒 Files selected for processing (18)
  • scripts/alert-dialog-contract-guard.mjs
  • src/main/memory/index.ts
  • src/main/memory/routes.ts
  • src/main/memory/services/directiveService.ts
  • src/renderer/api/MemoryClient.ts
  • src/renderer/settings/components/MemoryDirectivesPanel.vue
  • src/renderer/settings/components/MemoryInboxBar.vue
  • src/renderer/src/i18n/pl-PL/settings.json
  • src/shared/contracts/routes/memory.routes.ts
  • test/main/memory/directiveService.test.ts
  • test/main/routes/dispatcher.test.ts
  • test/main/routes/memoryDto.test.ts
  • test/main/scripts/alertDialogContractGuard.test.ts
  • test/renderer/api/clients.test.ts
  • test/renderer/components/MemoryDirectivesPanel.test.ts
  • test/renderer/components/MemoryInboxBar.test.ts
  • test/renderer/components/SkillInstallTargetScope.test.ts
  • test/renderer/settings/useMemoryInlineFeedback.test.ts

📝 Walkthrough

Walkthrough

This PR standardizes alert-dialog confirmation behavior, adds asynchronous confirmation actions, replaces boolean memory mutations with structured results, updates feedback and reconciliation handling, adds localized messages, and expands static and runtime test coverage.

Changes

Alert confirmation contract

Layer / File(s) Summary
Shared dialog primitives and enforcement
src/shadcn/components/ui/alert-dialog/*, scripts/alert-dialog-contract-guard.mjs, package.json
Adds typed click forwarding, AlertDialogAsyncAction, controlled close behavior, and lint enforcement for unsafe handlers and modifiers.
Confirmation workflows
src/renderer/settings/components/*, src/renderer/settings/components/skills/*
Migrates destructive operations to explicit request states, pending controls, retry handling, feedback, and stale-request protection.
Confirmation validation
test/renderer/components/*, test/main/scripts/alertDialogContractGuard.test.ts
Covers event ordering, async persistence, disabled controls, retries, stale responses, and guard diagnostics.

Memory command result migration

Layer / File(s) Summary
Structured command contracts
src/shared/contracts/routes/memory.routes.ts, src/main/memory/domain/commandResult.ts
Replaces boolean mutation results with applied or rejected results containing standardized reasons.
Service, route, and client propagation
src/main/memory/*, src/renderer/api/MemoryClient.ts, src/main/tool/*, src/renderer/stores/ui/memoryActivity.ts
Propagates structured results through memory services, routes, clients, tool ports, and activity state.
Feedback and reconciliation
src/renderer/settings/lib/*, src/renderer/settings/components/Memory*.vue, src/renderer/src/i18n/*/settings.json
Maps rejection reasons to localized feedback and reconciles stale or missing local projections.
Memory and route validation
test/main/memory/*, test/main/routes/*, test/main/tool/*, test/renderer/api/clients.test.ts, test/renderer/stores/memoryActivityStore.test.ts
Validates applied results, rejection reasons, lifecycle behavior, route schemas, sanitized tool output, and recovery paths.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ConfirmationDialog
  participant MemoryClient
  participant MemoryRouteService
  participant MemoryService
  participant FeedbackController

  User->>ConfirmationDialog: confirm destructive action
  ConfirmationDialog->>MemoryClient: invoke memory command
  MemoryClient->>MemoryRouteService: send command
  MemoryRouteService->>MemoryService: execute mutation
  MemoryService-->>MemoryRouteService: applied or rejected result
  MemoryRouteService-->>MemoryClient: MemoryCommandResult
  MemoryClient-->>FeedbackController: return command result
  FeedbackController-->>ConfirmationDialog: show feedback or reconcile state
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 clearly summarizes the primary change: improving reliability for alert-dialog confirmations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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/alert-dialog-confirmation-contract

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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/memory/routes.ts (1)

524-546: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Gate deleteMemory to DeepChat agents like archiveUserMemory.

deleteMemory accepts any agent for which canManageClaimMemory(agentId) succeeds, which does not check agentType or memoryEnabled. A DeepChat route dependency with this guard makes the mutation behavior consistent with archive, or this should be removed from the DeepChat route behind a service-level gate.

🤖 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 `@src/main/memory/routes.ts` around lines 524 - 546, Update the
memoryDeleteRoute handler to apply the same DeepChat agent guard used by
memoryArchiveRoute before calling memoryService.deleteMemory: check
deps.getAgentType(input.agentId), return the existing rejected/unavailable
response for non-DeepChat agents, and only perform deletion for eligible agents.
🧹 Nitpick comments (5)
test/renderer/components/SkillInstallTargetScope.test.ts (1)

343-358: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer observable signals over the internal conflictRequest shape.

The assertions on conflictRequest.status read component internals. The observable behavior is already covered by installing, by the rendered conflict dialog, and by the emitted update:open. If you keep the internal assertions, a later rename of the state machine breaks this test without a behavior change. Consider asserting that the conflict dialog is not rendered and that the install stays pending instead.

As per coding guidelines: "Keep committed tests lean and focused on project reliability, stability, and observable contracts; remove temporary checks that only test implementation internals before handoff."

🤖 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 `@test/renderer/components/SkillInstallTargetScope.test.ts` around lines 343 -
358, Remove the internal conflictRequest.status assertions from this test and
rely on observable behavior instead: retain the installing assertion for the
pending state, assert the rendered conflict dialog’s visibility as appropriate,
and keep the emitted update:open assertion after overwrite.resolve completes.
Use the existing dialog selector or component reference rather than inspecting
conflictRequest.

Source: Coding guidelines

test/renderer/settings/useMemoryInlineFeedback.test.ts (1)

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

Make the rejection-reason coverage exhaustive at compile time.

The reason list is typed as MemoryCommandRejectionReason[]. If a new rejection reason joins the union, this test still compiles and still passes, so the new reason gets no reconciliation coverage. Key the expectation by a full record so TypeScript reports a missing reason.

♻️ Proposed exhaustive expectation
-    const reasons: MemoryCommandRejectionReason[] = [
-      'unavailable',
-      'not-found',
-      'invalid-state',
-      'conflict',
-      'stale',
-      'anchored'
-    ]
-
-    expect(
-      Object.fromEntries(
-        reasons.map((reason) => [reason, shouldReconcileMemoryCommandRejection(reason)])
-      )
-    ).toEqual({
-      unavailable: false,
-      'not-found': true,
-      'invalid-state': true,
-      conflict: false,
-      stale: true,
-      anchored: false
-    })
+    const expected: Record<MemoryCommandRejectionReason, boolean> = {
+      unavailable: false,
+      'not-found': true,
+      'invalid-state': true,
+      conflict: false,
+      stale: true,
+      anchored: false
+    }
+
+    for (const reason of Object.keys(expected) as MemoryCommandRejectionReason[]) {
+      expect(shouldReconcileMemoryCommandRejection(reason)).toBe(expected[reason])
+    }
🤖 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 `@test/renderer/settings/useMemoryInlineFeedback.test.ts` around lines 42 - 64,
Update the expectation in the test around shouldReconcileMemoryCommandRejection
to use a fully keyed Record<MemoryCommandRejectionReason, boolean> rather than
deriving keys from the manually maintained reasons array. Ensure every union
member is explicitly represented so adding a new rejection reason causes a
compile-time failure until its reconciliation behavior is covered.
src/renderer/settings/components/MemoryListView.vue (1)

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

Extract the duplicated confirmation request state machine. Three panels declare the same idle | confirming | pending union, the same shallowRef state, the same open computed, and the same stale-request identity comparison. The guard is correct only because shallowRef does not wrap the request object in a proxy, so this rule belongs in one place.

  • src/renderer/settings/components/MemoryListView.vue#L308-L321: move DeleteRequest, deleteRequest, and deleteDialogOpen into a shared helper under src/renderer/settings/lib/ and consume it here.
  • src/renderer/settings/components/MemoryDirectivesPanel.vue#L346-L350: replace DirectiveDeleteRequest and deleteRequest with the shared helper, parameterized by the target type.
  • src/renderer/settings/components/MemoryPersonaPanel.vue#L171-L175: replace RollbackRequest and rollbackRequest with the shared helper.
🤖 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 `@src/renderer/settings/components/MemoryListView.vue` around lines 308 - 321,
Extract the duplicated idle/confirming/pending request state, shallowRef
storage, open computed, and stale-request identity logic into a shared helper
under src/renderer/settings/lib/, parameterized by target type. Update
src/renderer/settings/components/MemoryListView.vue lines 308-321 to consume it
for deleteRequest/deleteDialogOpen,
src/renderer/settings/components/MemoryDirectivesPanel.vue lines 346-350 to
replace DirectiveDeleteRequest/deleteRequest, and
src/renderer/settings/components/MemoryPersonaPanel.vue lines 171-175 to replace
RollbackRequest/rollbackRequest; preserve shallowRef semantics and existing
request behavior at all sites.
test/renderer/components/MemoryDiagnosticsPanel.test.ts (1)

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

Cover the async alert action with the real primitive in three test files. All three files stub AlertDialogAsyncAction with a plain button, so the click-before-close contract added by this PR is asserted only against component state. test/renderer/components/MemoryInlinePanel.test.ts and test/renderer/components/MemoryListView.test.ts already add a realAlertDialog mode.

  • test/renderer/components/MemoryDiagnosticsPanel.test.ts#L24-L44: add a realAlertDialog setup option and one clear-all test that mounts the real alert-dialog components.
  • test/renderer/components/MemoryDirectivesPanel.test.ts#L26-L35: add the same option and one real-primitive test for the directive delete flow.
  • test/renderer/components/MemoryPersonaPanel.test.ts#L16-L25: add the same option and one real-primitive test for the rollback flow.
🤖 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 `@test/renderer/components/MemoryDiagnosticsPanel.test.ts` around lines 24 -
44, Update the test setup in
test/renderer/components/MemoryDiagnosticsPanel.test.ts (lines 24-44),
test/renderer/components/MemoryDirectivesPanel.test.ts (lines 26-35), and
test/renderer/components/MemoryPersonaPanel.test.ts (lines 16-25) to support a
realAlertDialog option that uses the real AlertDialogAsyncAction primitive
instead of the ButtonStub. Add one test in each file covering the clear-all,
directive-delete, and persona-rollback flows respectively, mounting with
realAlertDialog enabled and asserting the action does not close before the async
operation completes.
src/renderer/src/stores/ui/memoryActivity.ts (1)

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

Extract duplicated restore-handling logic in amend.

The restore-outcome handling at lines 634-640 (normal failure path) and lines 646-652 (exception-recovery path) is identical: both check restoreResult.action === 'applied', then apply the same markMemoryStatusInViews and setChipItemError calls. Extract this into a single helper function to prevent the two paths from drifting apart on a future change.

♻️ Proposed refactor to remove the duplication
+  function applyRestoreOutcome(memoryId: string, restoreResult: MemoryCommandResult): void {
+    if (restoreResult.action === 'applied') {
+      markMemoryStatusInViews(memoryId, 'pending_embedding')
+      setChipItemError(memoryId, 'amend_failed_retry')
+    } else {
+      setChipItemError(memoryId, 'amend_restore_failed')
+    }
+  }
+
   async function amend(memoryId: string, content: string): Promise<MemoryAddResult | null> {
     ...
       const restoreResult = await memoryClient.restore(agentId, memoryId)
-      if (restoreResult.action === 'applied') {
-        markMemoryStatusInViews(memoryId, 'pending_embedding')
-        setChipItemError(memoryId, 'amend_failed_retry')
-      } else {
-        setChipItemError(memoryId, 'amend_restore_failed')
-      }
+      applyRestoreOutcome(memoryId, restoreResult)
       return null
     } catch (error) {
       console.warn('[MemoryActivity] failed to amend memory', error)
       if (archived) {
         try {
           const restoreResult = await memoryClient.restore(agentId, memoryId)
-          if (restoreResult.action === 'applied') {
-            markMemoryStatusInViews(memoryId, 'pending_embedding')
-            setChipItemError(memoryId, 'amend_failed_retry')
-          } else {
-            setChipItemError(memoryId, 'amend_restore_failed')
-          }
+          applyRestoreOutcome(memoryId, restoreResult)
         } catch (restoreError) {
🤖 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 `@src/renderer/src/stores/ui/memoryActivity.ts` around lines 634 - 663, Extract
the duplicated restore-result handling from amend into a single local helper,
preserving the existing restoreResult.action === 'applied' branching and its
markMemoryStatusInViews/setChipItemError calls. Invoke that helper in both the
normal restore path and the exception-recovery path, leaving restore-error
logging and handling unchanged.
🤖 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.

Inline comments:
In `@scripts/alert-dialog-contract-guard.mjs`:
- Around line 217-239: Update the alert-dialog contract guard’s binding
detection around CLICK_HANDLER and BOUND_CLICK_HANDLER to also identify dynamic
@[] and v-on:[] event bindings on AlertDialogAction and AlertDialogCancel,
rejecting them with the existing violation mechanism when the dynamic event
could resolve to click. Add a focused regression test covering a dynamic
event-name binding bypass.

In `@src/renderer/settings/components/MemoryInboxBar.vue`:
- Around line 422-423: Update the MemoryClient directive action to return the
full structured command result instead of only result.directive, then update
MemoryInboxBar to apply the existing rejection handling and localized feedback
to both directive actions, including not-found, invalid-state, and stale
reasons. Preserve capacity handling and reconciliation behavior consistently
across approveDirective and the other directive action.

In `@src/renderer/src/i18n/pl-PL/settings.json`:
- Line 263: Update the “anchored” translation in the Polish settings locale to
use the established “Odkotwicz” unanchor term, matching the existing unanchor
label while preserving the rest of the message.

In `@src/shadcn/components/ui/alert-dialog/index.ts`:
- Line 3: Update the AlertDialogAsyncAction export in the module’s index file to
use single quotes instead of double quotes, preserving the existing no-semicolon
formatting and export behavior.

---

Outside diff comments:
In `@src/main/memory/routes.ts`:
- Around line 524-546: Update the memoryDeleteRoute handler to apply the same
DeepChat agent guard used by memoryArchiveRoute before calling
memoryService.deleteMemory: check deps.getAgentType(input.agentId), return the
existing rejected/unavailable response for non-DeepChat agents, and only perform
deletion for eligible agents.

---

Nitpick comments:
In `@src/renderer/settings/components/MemoryListView.vue`:
- Around line 308-321: Extract the duplicated idle/confirming/pending request
state, shallowRef storage, open computed, and stale-request identity logic into
a shared helper under src/renderer/settings/lib/, parameterized by target type.
Update src/renderer/settings/components/MemoryListView.vue lines 308-321 to
consume it for deleteRequest/deleteDialogOpen,
src/renderer/settings/components/MemoryDirectivesPanel.vue lines 346-350 to
replace DirectiveDeleteRequest/deleteRequest, and
src/renderer/settings/components/MemoryPersonaPanel.vue lines 171-175 to replace
RollbackRequest/rollbackRequest; preserve shallowRef semantics and existing
request behavior at all sites.

In `@src/renderer/src/stores/ui/memoryActivity.ts`:
- Around line 634-663: Extract the duplicated restore-result handling from amend
into a single local helper, preserving the existing restoreResult.action ===
'applied' branching and its markMemoryStatusInViews/setChipItemError calls.
Invoke that helper in both the normal restore path and the exception-recovery
path, leaving restore-error logging and handling unchanged.

In `@test/renderer/components/MemoryDiagnosticsPanel.test.ts`:
- Around line 24-44: Update the test setup in
test/renderer/components/MemoryDiagnosticsPanel.test.ts (lines 24-44),
test/renderer/components/MemoryDirectivesPanel.test.ts (lines 26-35), and
test/renderer/components/MemoryPersonaPanel.test.ts (lines 16-25) to support a
realAlertDialog option that uses the real AlertDialogAsyncAction primitive
instead of the ButtonStub. Add one test in each file covering the clear-all,
directive-delete, and persona-rollback flows respectively, mounting with
realAlertDialog enabled and asserting the action does not close before the async
operation completes.

In `@test/renderer/components/SkillInstallTargetScope.test.ts`:
- Around line 343-358: Remove the internal conflictRequest.status assertions
from this test and rely on observable behavior instead: retain the installing
assertion for the pending state, assert the rendered conflict dialog’s
visibility as appropriate, and keep the emitted update:open assertion after
overwrite.resolve completes. Use the existing dialog selector or component
reference rather than inspecting conflictRequest.

In `@test/renderer/settings/useMemoryInlineFeedback.test.ts`:
- Around line 42-64: Update the expectation in the test around
shouldReconcileMemoryCommandRejection to use a fully keyed
Record<MemoryCommandRejectionReason, boolean> rather than deriving keys from the
manually maintained reasons array. Ensure every union member is explicitly
represented so adding a new rejection reason causes a compile-time failure until
its reconciliation behavior is covered.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b24b8480-edd2-4ac6-afa1-72d89961920b

📥 Commits

Reviewing files that changed from the base of the PR and between 6ccb375 and 6762e4c.

📒 Files selected for processing (87)
  • docs/architecture/alert-dialog-confirmation-contract/plan.md
  • docs/architecture/alert-dialog-confirmation-contract/spec.md
  • docs/architecture/alert-dialog-confirmation-contract/tasks.md
  • package.json
  • scripts/alert-dialog-contract-guard.mjs
  • src/main/memory/domain/commandResult.ts
  • src/main/memory/index.ts
  • src/main/memory/routes.ts
  • src/main/memory/services/conflictService.ts
  • src/main/memory/services/directiveService.ts
  • src/main/memory/services/managementService.ts
  • src/main/memory/services/personaService.ts
  • src/main/tool/agentTools/agentMemoryTools.ts
  • src/main/tool/runtimePorts.ts
  • src/renderer/api/MemoryClient.ts
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/MemoryDiagnosticsPanel.vue
  • src/renderer/settings/components/MemoryDirectivesPanel.vue
  • src/renderer/settings/components/MemoryInboxBar.vue
  • src/renderer/settings/components/MemoryInlinePanel.vue
  • src/renderer/settings/components/MemoryListView.vue
  • src/renderer/settings/components/MemoryPersonaPanel.vue
  • src/renderer/settings/components/OcrSettings.vue
  • src/renderer/settings/components/ProviderRateLimitConfig.vue
  • src/renderer/settings/components/skills/SkillInstallDialog.vue
  • src/renderer/settings/lib/useKnowledgeConfigOperation.ts
  • src/renderer/settings/lib/useMemoryInlineFeedback.ts
  • src/renderer/src/features/chat-page/ChatPage.vue
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/de-DE/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/es-ES/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/id-ID/settings.json
  • src/renderer/src/i18n/it-IT/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ms-MY/settings.json
  • src/renderer/src/i18n/pl-PL/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/tr-TR/settings.json
  • src/renderer/src/i18n/vi-VN/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/stores/ui/memoryActivity.ts
  • src/shadcn/components/ui/alert-dialog/AlertDialogAction.vue
  • src/shadcn/components/ui/alert-dialog/AlertDialogAsyncAction.vue
  • src/shadcn/components/ui/alert-dialog/AlertDialogCancel.vue
  • src/shadcn/components/ui/alert-dialog/index.ts
  • src/shared/contracts/routes/memory.routes.ts
  • test/main/memory/conflictService.test.ts
  • test/main/memory/directiveService.test.ts
  • test/main/memory/embeddingPipeline.test.ts
  • test/main/memory/lifecycleRegression.test.ts
  • test/main/memory/maintenanceService.test.ts
  • test/main/memory/managementService.test.ts
  • test/main/memory/memory-persona-eval.test.ts
  • test/main/memory/memoryAdd.test.ts
  • test/main/memory/memoryBehavior.eval.test.ts
  • test/main/memory/memoryUpdate.test.ts
  • test/main/memory/personaService.test.ts
  • test/main/memory/workingMemoryService.test.ts
  • test/main/routes/dispatcher.test.ts
  • test/main/routes/memoryDto.test.ts
  • test/main/scripts/alertDialogContractGuard.test.ts
  • test/main/tool/agentTools/agentMemoryTools.test.ts
  • test/main/tool/agentTools/agentToolDependencies.ts
  • test/renderer/api/clients.test.ts
  • test/renderer/components/AlertDialogContract.test.ts
  • test/renderer/components/BuiltinKnowledgeSettings.test.ts
  • test/renderer/components/DataSettings.test.ts
  • test/renderer/components/MemoryDiagnosticsPanel.test.ts
  • test/renderer/components/MemoryDirectivesPanel.test.ts
  • test/renderer/components/MemoryInboxBar.test.ts
  • test/renderer/components/MemoryInlinePanel.test.ts
  • test/renderer/components/MemoryListView.test.ts
  • test/renderer/components/MemoryPersonaPanel.test.ts
  • test/renderer/components/OcrSettings.test.ts
  • test/renderer/components/ProviderRateLimitConfig.test.ts
  • test/renderer/components/SkillInstallTargetScope.test.ts
  • test/renderer/settings/useMemoryInlineFeedback.test.ts
  • test/renderer/stores/memoryActivityStore.test.ts

Comment thread scripts/alert-dialog-contract-guard.mjs
Comment on lines +422 to +423
shouldReload =
result.reason !== 'capacity' && shouldReconcileMemoryCommandRejection(result.reason)

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Propagate structured rejection results to directive rejection.

This branch handles structured rejection only for approveDirective. src/renderer/api/MemoryClient.ts Lines 321-327 still returns result.directive, and src/renderer/settings/components/MemoryInboxBar.vue Lines 451-455 treats null as generic failure. A not-found, invalid-state, or stale rejection therefore loses localized feedback and skips reconciliation. Return the full command result and apply the same rejection handling to both directive actions.

🤖 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 `@src/renderer/settings/components/MemoryInboxBar.vue` around lines 422 - 423,
Update the MemoryClient directive action to return the full structured command
result instead of only result.directive, then update MemoryInboxBar to apply the
existing rejection handling and localized feedback to both directive actions,
including not-found, invalid-state, and stale reasons. Preserve capacity
handling and reconciliation behavior consistently across approveDirective and
the other directive action.

Comment thread src/renderer/src/i18n/pl-PL/settings.json Outdated
@@ -1,5 +1,6 @@
export { default as AlertDialog } from "./AlertDialog.vue"
export { default as AlertDialogAction } from "./AlertDialogAction.vue"
export { default as AlertDialogAsyncAction } from "./AlertDialogAsyncAction.vue"

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use Oxfmt single quotes.

Line 3 uses double quotes. Format this export with single quotes.

As per coding guidelines, **/*.{ts,tsx,vue} must use “single quotes, no semicolons, and a 100-column width.”

Proposed fix
-export { default as AlertDialogAsyncAction } from "./AlertDialogAsyncAction.vue"
+export { default as AlertDialogAsyncAction } from './AlertDialogAsyncAction.vue'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export { default as AlertDialogAsyncAction } from "./AlertDialogAsyncAction.vue"
export { default as AlertDialogAsyncAction } from './AlertDialogAsyncAction.vue'
🤖 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 `@src/shadcn/components/ui/alert-dialog/index.ts` at line 3, Update the
AlertDialogAsyncAction export in the module’s index file to use single quotes
instead of double quotes, preserving the existing no-semicolon formatting and
export behavior.

Source: Coding guidelines

@yyhhyyyyyy
yyhhyyyyyy merged commit 7eccee6 into dev Jul 31, 2026
11 checks passed
@zhangmo8
zhangmo8 deleted the fix/alert-dialog-confirmation-contract branch July 31, 2026 10:22
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