Skip to content

fix(core-app): stabilize Windows search launch diagnostics#258

Merged
TalexDreamSoul merged 23 commits intotalex-touch:masterfrom
liuxinrong00:lxr/dev
May 8, 2026
Merged

fix(core-app): stabilize Windows search launch diagnostics#258
TalexDreamSoul merged 23 commits intotalex-touch:masterfrom
liuxinrong00:lxr/dev

Conversation

@liuxinrong00
Copy link
Copy Markdown
Contributor

@liuxinrong00 liuxinrong00 commented May 5, 2026

Summary

  • Persist main-process diagnostics logs and harden Windows active-app failure logging.
  • Fix Windows app launch metadata, shortcut-first launch, Store/UWP indexing, and AppsFolder/AUMID launch paths.
  • Add Everything backend diagnostics and reduce startup/search indexing contention.
  • Fix Windows titlebar controls/logo spacing and repair corrupted app display names from stale index data.
  • Record Windows search diagnostics and performance findings in docs.

Details

  • WeChat was searchable but could fail to launch because shortcut metadata was discarded; scanner now keeps .lnk, args, cwd, and launcher uses shortcut first before target fallback.
  • Codex / Apple Music from Microsoft Store are indexed via Get-StartApps and launched via AppsFolder AUMID.
  • Corrupted display_name values containing replacement/square glyphs now fall back to the clean name field and are repaired during backfill/full sync.
  • Traditional desktop apps returned by Get-StartApps with absolute-path AppIDs are treated as path launches instead of fake AppsFolder entries.

Verification

  • pnpm -C apps/core-app run typecheck:node
  • pnpm -C apps/core-app exec vitest run src/main/modules/box-tool/addon/apps/display-name-sync-utils.test.ts src/main/modules/box-tool/addon/apps/search-processing-service.test.ts src/main/modules/box-tool/addon/apps/app-provider.test.ts
  • git diff --check

Notes

  • typecheck:web and live dev launch were not rerun in the final encoding-display commit.
  • GitHub CLI was invoked from C:/Program Files/GitHub CLI/gh.exe because the current shell PATH had not refreshed.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed corrupted app display names in search results with fallback rendering
    • Improved Windows active-app detection with better PowerShell output parsing
    • Fixed Windows titlebar and layout spacing issues
    • Enhanced Windows Start Menu app discovery and indexing
  • Chores

    • Added persistent diagnostic logging and backend error tracking for troubleshooting

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Important

Review skipped

Too many files!

This PR contains 284 files, which is 134 over the limit of 150.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd05d9d5-ffed-459f-ad00-116290c20e96

📥 Commits

Reviewing files that changed from the base of the PR and between ab1089a and 36d88a3.

📒 Files selected for processing (284)
  • apps/core-app/package.json
  • apps/core-app/scripts/clipboard-polling-stress.ts
  • apps/core-app/src/main/channel/common.test.ts
  • apps/core-app/src/main/channel/common.ts
  • apps/core-app/src/main/modules/ai/README.md
  • apps/core-app/src/main/modules/ai/intelligence-deepagent-orchestration.test.ts
  • apps/core-app/src/main/modules/ai/intelligence-deepagent-orchestration.ts
  • apps/core-app/src/main/modules/ai/intelligence-module.ts
  • apps/core-app/src/main/modules/ai/intelligence-service.ts
  • apps/core-app/src/main/modules/ai/intelligence-workflow-service.test.ts
  • apps/core-app/src/main/modules/ai/intelligence-workflow-service.ts
  • apps/core-app/src/main/modules/ai/tuff-intelligence-runtime.test.ts
  • apps/core-app/src/main/modules/ai/tuff-intelligence-runtime.ts
  • apps/core-app/src/main/modules/analytics/README.md
  • apps/core-app/src/main/modules/analytics/analytics-module.ts
  • apps/core-app/src/main/modules/analytics/core/analytics-core.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-scanner.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/win.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/win.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/clipboard.transport.test.ts
  • apps/core-app/src/main/modules/clipboard.ts
  • apps/core-app/src/main/modules/division-box/ipc.actor.test.ts
  • apps/core-app/src/main/modules/download/MIGRATION_GUIDE.md
  • apps/core-app/src/main/modules/global-shortcon.ts
  • apps/core-app/src/main/modules/omni-panel/index.test.ts
  • apps/core-app/src/main/modules/permission/permission-store.test.ts
  • apps/core-app/src/main/modules/plugin/install-queue.test.ts
  • apps/core-app/src/main/modules/plugin/plugin-loaders.test.ts
  • apps/core-app/src/main/modules/plugin/plugin-loaders.ts
  • apps/core-app/src/main/modules/plugin/plugin-module.ts
  • apps/core-app/src/main/modules/plugin/plugin-preflight-helper.test.ts
  • apps/core-app/src/main/modules/plugin/plugin.ts
  • apps/core-app/src/main/modules/plugin/runtime/plugin-runtime-repair.test.ts
  • apps/core-app/src/main/modules/plugin/runtime/plugin-runtime-repair.ts
  • apps/core-app/src/main/modules/sync/index.ts
  • apps/core-app/src/main/modules/sync/sync-payload-crypto.test.ts
  • apps/core-app/src/main/modules/sync/sync-payload-crypto.ts
  • apps/core-app/src/main/modules/sync/sync-payload-wire.test.ts
  • apps/core-app/src/main/service/service-center.ts
  • apps/core-app/src/main/utils/perf-monitor.severe-lag.test.ts
  • apps/core-app/src/main/utils/perf-monitor.ts
  • apps/core-app/src/renderer/src/modules/hooks/useSvgContent.ts
  • apps/core-app/src/renderer/src/modules/hooks/useWorkflowEditor.test.ts
  • apps/core-app/src/renderer/src/modules/hooks/useWorkflowEditor.ts
  • apps/core-app/src/renderer/src/modules/lang/index.ts
  • apps/core-app/src/renderer/src/modules/lang/language-preferences.test.ts
  • apps/core-app/src/renderer/src/modules/lang/language-preferences.ts
  • apps/core-app/src/renderer/src/modules/lang/useLanguage.ts
  • apps/core-app/src/renderer/src/modules/storage/account-storage.test.ts
  • apps/core-app/src/renderer/src/modules/storage/app-storage-boundary.test.ts
  • apps/core-app/src/renderer/src/modules/storage/app-storage.ts
  • apps/core-app/src/renderer/src/modules/tuffex/index.ts
  • apps/core-app/src/renderer/src/views/base/intelligence/IntelligenceWorkflowPage.vue
  • apps/core-app/src/renderer/src/views/base/settings/SettingAbout.vue
  • apps/core-app/src/renderer/src/views/base/settings/SettingPermission.vue
  • apps/core-app/src/renderer/src/views/base/settings/setting-everything-state.test.ts
  • apps/core-app/src/shared/update/channel.test.ts
  • apps/nexus/app/app.vue
  • apps/nexus/app/components/content/demos/ScrollBasicDemo.vue
  • apps/nexus/app/components/content/demos/ScrollScrollDemo.vue
  • apps/nexus/app/composables/useLocaleOrchestrator.ts
  • apps/nexus/app/data/search/featureIndex.ts
  • apps/nexus/app/data/tuffSdkItems.ts
  • apps/nexus/app/pages/dashboard/devices.vue
  • apps/nexus/app/pages/device-auth.vue
  • apps/nexus/content/docs/dev/api/box.en.mdc
  • apps/nexus/content/docs/dev/api/box.zh.mdc
  • apps/nexus/content/docs/dev/api/bridge-hooks.en.mdc
  • apps/nexus/content/docs/dev/api/bridge-hooks.zh.mdc
  • apps/nexus/content/docs/dev/api/channel.en.mdc
  • apps/nexus/content/docs/dev/api/channel.zh.mdc
  • apps/nexus/content/docs/dev/api/clipboard.en.mdc
  • apps/nexus/content/docs/dev/api/clipboard.zh.mdc
  • apps/nexus/content/docs/dev/api/feature.en.mdc
  • apps/nexus/content/docs/dev/api/feature.zh.mdc
  • apps/nexus/content/docs/dev/api/index.en.mdc
  • apps/nexus/content/docs/dev/api/index.zh.mdc
  • apps/nexus/content/docs/dev/api/keyboard.en.mdc
  • apps/nexus/content/docs/dev/api/keyboard.zh.mdc
  • apps/nexus/content/docs/dev/api/transport-internals.en.mdc
  • apps/nexus/content/docs/dev/api/transport-internals.zh.mdc
  • apps/nexus/content/docs/dev/api/transport.en.mdc
  • apps/nexus/content/docs/dev/api/transport.zh.mdc
  • apps/nexus/content/docs/dev/architecture/intelligence-system.en.mdc
  • apps/nexus/content/docs/dev/architecture/intelligence-system.zh.mdc
  • apps/nexus/content/docs/dev/architecture/ipc-events-sdk-map.en.mdc
  • apps/nexus/content/docs/dev/architecture/ipc-events-sdk-map.zh.mdc
  • apps/nexus/content/docs/dev/components/agents.en.mdc
  • apps/nexus/content/docs/dev/components/alert.en.mdc
  • apps/nexus/content/docs/dev/components/alert.zh.mdc
  • apps/nexus/content/docs/dev/components/auto-sizer.en.mdc
  • apps/nexus/content/docs/dev/components/avatar.en.mdc
  • apps/nexus/content/docs/dev/components/avatar.zh.mdc
  • apps/nexus/content/docs/dev/components/badge.en.mdc
  • apps/nexus/content/docs/dev/components/badge.zh.mdc
  • apps/nexus/content/docs/dev/components/base-anchor.en.mdc
  • apps/nexus/content/docs/dev/components/base-anchor.zh.mdc
  • apps/nexus/content/docs/dev/components/base-surface.en.mdc
  • apps/nexus/content/docs/dev/components/base-surface.zh.mdc
  • apps/nexus/content/docs/dev/components/blank-slate.en.mdc
  • apps/nexus/content/docs/dev/components/blank-slate.zh.mdc
  • apps/nexus/content/docs/dev/components/breadcrumb.en.mdc
  • apps/nexus/content/docs/dev/components/breadcrumb.zh.mdc
  • apps/nexus/content/docs/dev/components/button.en.mdc
  • apps/nexus/content/docs/dev/components/button.zh.mdc
  • apps/nexus/content/docs/dev/components/card-item.en.mdc
  • apps/nexus/content/docs/dev/components/card.en.mdc
  • apps/nexus/content/docs/dev/components/cascader.en.mdc
  • apps/nexus/content/docs/dev/components/chat-composer.en.mdc
  • apps/nexus/content/docs/dev/components/chat-composer.zh.mdc
  • apps/nexus/content/docs/dev/components/checkbox.en.mdc
  • apps/nexus/content/docs/dev/components/collapse.en.mdc
  • apps/nexus/content/docs/dev/components/collapse.zh.mdc
  • apps/nexus/content/docs/dev/components/container.en.mdc
  • apps/nexus/content/docs/dev/components/container.zh.mdc
  • apps/nexus/content/docs/dev/components/context-menu.en.mdc
  • apps/nexus/content/docs/dev/components/corner-overlay.en.mdc
  • apps/nexus/content/docs/dev/components/data-table.en.mdc
  • apps/nexus/content/docs/dev/components/data-table.zh.mdc
  • apps/nexus/content/docs/dev/components/date-picker.en.mdc
  • apps/nexus/content/docs/dev/components/dialog.en.mdc
  • apps/nexus/content/docs/dev/components/dialog.zh.mdc
  • apps/nexus/content/docs/dev/components/drawer.en.mdc
  • apps/nexus/content/docs/dev/components/drawer.zh.mdc
  • apps/nexus/content/docs/dev/components/dropdown-menu.en.mdc
  • apps/nexus/content/docs/dev/components/edge-fade-mask.en.mdc
  • apps/nexus/content/docs/dev/components/edge-fade-mask.zh.mdc
  • apps/nexus/content/docs/dev/components/empty-state.en.mdc
  • apps/nexus/content/docs/dev/components/empty.en.mdc
  • apps/nexus/content/docs/dev/components/error-state.en.mdc
  • apps/nexus/content/docs/dev/components/error-state.zh.mdc
  • apps/nexus/content/docs/dev/components/flat-button.en.mdc
  • apps/nexus/content/docs/dev/components/flat-button.zh.mdc
  • apps/nexus/content/docs/dev/components/flat-input.en.mdc
  • apps/nexus/content/docs/dev/components/flat-input.zh.mdc
  • apps/nexus/content/docs/dev/components/flat-radio.en.mdc
  • apps/nexus/content/docs/dev/components/flat-select.en.mdc
  • apps/nexus/content/docs/dev/components/flat-select.zh.mdc
  • apps/nexus/content/docs/dev/components/flex.en.mdc
  • apps/nexus/content/docs/dev/components/floating.en.mdc
  • apps/nexus/content/docs/dev/components/floating.zh.mdc
  • apps/nexus/content/docs/dev/components/foundations.zh.mdc
  • apps/nexus/content/docs/dev/components/fusion.en.mdc
  • apps/nexus/content/docs/dev/components/glass-surface.en.mdc
  • apps/nexus/content/docs/dev/components/glow-text.en.mdc
  • apps/nexus/content/docs/dev/components/gradient-border.en.mdc
  • apps/nexus/content/docs/dev/components/gradual-blur.en.mdc
  • apps/nexus/content/docs/dev/components/gradual-blur.zh.mdc
  • apps/nexus/content/docs/dev/components/grid-layout.en.mdc
  • apps/nexus/content/docs/dev/components/grid.en.mdc
  • apps/nexus/content/docs/dev/components/grid.zh.mdc
  • apps/nexus/content/docs/dev/components/group-block.en.mdc
  • apps/nexus/content/docs/dev/components/guide-state.en.mdc
  • apps/nexus/content/docs/dev/components/guide-state.zh.mdc
  • apps/nexus/content/docs/dev/components/icon.en.mdc
  • apps/nexus/content/docs/dev/components/icon.zh.mdc
  • apps/nexus/content/docs/dev/components/image-gallery.en.mdc
  • apps/nexus/content/docs/dev/components/image-gallery.zh.mdc
  • apps/nexus/content/docs/dev/components/image-uploader.en.mdc
  • apps/nexus/content/docs/dev/components/image-uploader.zh.mdc
  • apps/nexus/content/docs/dev/components/input.en.mdc
  • apps/nexus/content/docs/dev/components/input.zh.mdc
  • apps/nexus/content/docs/dev/components/keyframe-stroke-text.en.mdc
  • apps/nexus/content/docs/dev/components/keyframe-stroke-text.zh.mdc
  • apps/nexus/content/docs/dev/components/layout-skeleton.en.mdc
  • apps/nexus/content/docs/dev/components/layout-skeleton.zh.mdc
  • apps/nexus/content/docs/dev/components/loading-overlay.en.mdc
  • apps/nexus/content/docs/dev/components/loading-state.en.mdc
  • apps/nexus/content/docs/dev/components/loading-state.zh.mdc
  • apps/nexus/content/docs/dev/components/markdown-view.en.mdc
  • apps/nexus/content/docs/dev/components/modal.en.mdc
  • apps/nexus/content/docs/dev/components/modal.zh.mdc
  • apps/nexus/content/docs/dev/components/nav-bar.en.mdc
  • apps/nexus/content/docs/dev/components/no-data.en.mdc
  • apps/nexus/content/docs/dev/components/no-data.zh.mdc
  • apps/nexus/content/docs/dev/components/no-selection.en.mdc
  • apps/nexus/content/docs/dev/components/no-selection.zh.mdc
  • apps/nexus/content/docs/dev/components/offline-state.en.mdc
  • apps/nexus/content/docs/dev/components/offline-state.zh.mdc
  • apps/nexus/content/docs/dev/components/outline-border.en.mdc
  • apps/nexus/content/docs/dev/components/pagination.en.mdc
  • apps/nexus/content/docs/dev/components/pagination.zh.mdc
  • apps/nexus/content/docs/dev/components/permission-state.en.mdc
  • apps/nexus/content/docs/dev/components/permission-state.zh.mdc
  • apps/nexus/content/docs/dev/components/picker.en.mdc
  • apps/nexus/content/docs/dev/components/popover.en.mdc
  • apps/nexus/content/docs/dev/components/progress.en.mdc
  • apps/nexus/content/docs/dev/components/progress.zh.mdc
  • apps/nexus/content/docs/dev/components/radio.en.mdc
  • apps/nexus/content/docs/dev/components/radio.zh.mdc
  • apps/nexus/content/docs/dev/components/rating.en.mdc
  • apps/nexus/content/docs/dev/components/rating.zh.mdc
  • apps/nexus/content/docs/dev/components/scroll.en.mdc
  • apps/nexus/content/docs/dev/components/scroll.zh.mdc
  • apps/nexus/content/docs/dev/components/search-empty.en.mdc
  • apps/nexus/content/docs/dev/components/search-empty.zh.mdc
  • apps/nexus/content/docs/dev/components/search-input.en.mdc
  • apps/nexus/content/docs/dev/components/search-select.en.mdc
  • apps/nexus/content/docs/dev/components/segmented-slider.en.mdc
  • apps/nexus/content/docs/dev/components/select.en.mdc
  • apps/nexus/content/docs/dev/components/skeleton.en.mdc
  • apps/nexus/content/docs/dev/components/skeleton.zh.mdc
  • apps/nexus/content/docs/dev/components/slider.en.mdc
  • apps/nexus/content/docs/dev/components/sortable-list.en.mdc
  • apps/nexus/content/docs/dev/components/spinner.en.mdc
  • apps/nexus/content/docs/dev/components/splitter.en.mdc
  • apps/nexus/content/docs/dev/components/stack.en.mdc
  • apps/nexus/content/docs/dev/components/stagger.en.mdc
  • apps/nexus/content/docs/dev/components/stat-card.en.mdc
  • apps/nexus/content/docs/dev/components/status-badge.en.mdc
  • apps/nexus/content/docs/dev/components/status-badge.zh.mdc
  • apps/nexus/content/docs/dev/components/steps.en.mdc
  • apps/nexus/content/docs/dev/components/steps.zh.mdc
  • apps/nexus/content/docs/dev/components/switch.en.mdc
  • apps/nexus/content/docs/dev/components/tab-bar.en.mdc
  • apps/nexus/content/docs/dev/components/tabs.en.mdc
  • apps/nexus/content/docs/dev/components/tabs.zh.mdc
  • apps/nexus/content/docs/dev/components/tag.en.mdc
  • apps/nexus/content/docs/dev/components/tag.zh.mdc
  • apps/nexus/content/docs/dev/components/text-transformer.en.mdc
  • apps/nexus/content/docs/dev/components/timeline.en.mdc
  • apps/nexus/content/docs/dev/components/timeline.zh.mdc
  • apps/nexus/content/docs/dev/components/toast.en.mdc
  • apps/nexus/content/docs/dev/components/toast.zh.mdc
  • apps/nexus/content/docs/dev/components/transition.en.mdc
  • apps/nexus/content/docs/dev/components/tree-select.en.mdc
  • apps/nexus/content/docs/dev/components/tuff-logo-stroke.en.mdc
  • apps/nexus/content/docs/dev/components/tuff-logo-stroke.zh.mdc
  • apps/nexus/content/docs/dev/components/typing-indicator.en.mdc
  • apps/nexus/content/docs/dev/tools/tuffex.en.mdc
  • apps/nexus/content/docs/dev/tools/tuffex.zh.mdc
  • apps/nexus/server/api/admin/release-evidence/releaseEvidence.api.test.ts
  • apps/nexus/server/api/app-auth/__tests__/sign-in-token.post.test.ts
  • apps/nexus/server/api/app-auth/device/abort.post.ts
  • apps/nexus/server/api/app-auth/device/approve.post.ts
  • apps/nexus/server/api/app-auth/device/cancel.post.ts
  • apps/nexus/server/api/app-auth/device/info.get.ts
  • apps/nexus/server/api/app-auth/device/start.post.ts
  • apps/nexus/server/api/app-auth/sign-in-token.post.ts
  • apps/nexus/server/api/auth/[...].ts
  • apps/nexus/server/api/auth/__tests__/sign-in-token-retired.test.ts
  • apps/nexus/server/api/auth/sign-in-token.post.ts
  • apps/nexus/server/api/dashboard/api-keys.post.ts
  • apps/nexus/server/api/devices/audits.get.ts
  • apps/nexus/server/api/devices/revoke.post.ts
  • apps/nexus/server/api/devices/trust.post.ts
  • apps/nexus/server/api/sync/__tests__/sync-routes-410.test.ts
  • apps/nexus/server/api/sync/pull.get.ts
  • apps/nexus/server/api/sync/push.post.ts
  • apps/nexus/server/middleware/__tests__/intelligence-route-compat.test.ts
  • apps/nexus/server/utils/__tests__/auth-api-key-scopes.test.ts
  • apps/nexus/server/utils/__tests__/device-auth-risk.test.ts
  • apps/nexus/server/utils/__tests__/team-context.test.ts
  • apps/nexus/server/utils/apiKeyScopes.ts
  • apps/nexus/server/utils/appAuthToken.ts
  • apps/nexus/server/utils/auth.ts
  • apps/nexus/server/utils/authStore.ts
  • apps/pilot/app/components/admin/AdminSideNav.vue
  • apps/pilot/app/components/pilot/PilotChatWorkspace.vue
  • apps/pilot/app/components/pilot/PilotSessionsPanel.vue
  • apps/pilot/app/components/pilot/PilotSidebarHeader.vue
  • apps/pilot/app/composables/api/base/v1/aigc/completion/index.ts
  • apps/pilot/app/composables/api/base/v1/aigc/completion/legacy-stream-contract.ts
  • apps/pilot/app/composables/api/base/v1/aigc/completion/legacy-stream-input.ts
  • apps/pilot/app/composables/api/base/v1/aigc/completion/legacy-stream-sse.ts
  • apps/pilot/app/composables/api/base/v1/aigc/history/index.ts
  • apps/pilot/app/composables/usePilotChatPage.ts
  • apps/pilot/app/composables/usePilotRoutingAdmin.ts
  • apps/pilot/app/pages/admin/system/model-groups.vue
  • apps/pilot/app/pages/admin/system/route-combos.vue
  • apps/pilot/app/pages/index.vue
  • apps/pilot/nuxt.config.ts
  • apps/pilot/server/utils/__tests__/auth.test.ts
  • apps/pilot/server/utils/__tests__/legacy-completion-stream-contract.test.ts
  • apps/pilot/server/utils/__tests__/legacy-stream-input.test.ts
  • apps/pilot/server/utils/__tests__/pilot-admin-channel-config.test.ts
  • apps/pilot/server/utils/__tests__/pilot-admin-datasource-config.test.ts
  • apps/pilot/server/utils/__tests__/pilot-admin-routing-config.capabilities.test.ts
  • apps/pilot/server/utils/__tests__/pilot-admin-routing-config.test.ts
  • apps/pilot/server/utils/__tests__/pilot-capability-meta.shared.test.ts
  • apps/pilot/server/utils/__tests__/pilot-channel-model-sync.test.ts

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Windows diagnostics, search, and UI improvements for Core App: corrupted app display-name detection with fallback rendering, Windows Store app indexing by absolute path, persistent main-process logging via log4js, enhanced foreground-process detection with structured error logging, Everything backend attempt error tracking, and titlebar/window-controls styling adjustments.

Changes

Display Name Corruption Detection and Search Integration

Layer / File(s) Summary
Data Shape & Utilities
apps/core-app/src/main/modules/box-tool/addon/apps/display-name-sync-utils.ts, display-name-sync-utils.test.ts
Introduces isProbablyCorruptedDisplayName() to detect garbled names via Unicode replacement-character heuristics, and resolveDisplayName() to prefer clean display names with fallback to normalized fallbackName. Updates shouldUpdateDisplayName() to reject updates when names are corrupted.
App Indexing & Normalization
apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts, app-provider.test.ts
App provider now resolves/normalizes display names during indexing, managed-entry listing/sorting, managed upserts, and startup backfill. Adds corruption detection for stored names and propagates corrected name/displayName to keyword syncing. New test verifies startup backfill repairs corrupted displayName values in DB rows.
Search & Recommendation Integration
apps/core-app/src/main/modules/box-tool/addon/apps/search-processing-service.ts, search-processing-service.test.ts
apps/core-app/src/main/modules/box-tool/search-engine/recommendation/recommendation-engine.ts
apps/core-app/src/main/modules/box-tool/search-engine/search-core.ts
Search processing derives per-app displayName via resolveDisplayName() for titles, keywords, and all name-based matching. Field renamed from bundle_id to bundleId for consistency in app meta throughout search deduplication and telemetry. New test asserts fallback to name when displayName contains replacement characters.
Windows Store Path Detection
apps/core-app/src/main/modules/box-tool/addon/apps/win.ts, win.test.ts
listWindowsStoreApps() now detects absolute filesystem paths returned by Get-StartApps and treats them as desktop apps via buildDesktopAppInfo(). New isWindowsAbsolutePath() helper supports classification. Test verifies path-based app detection with correct launchKind/identity.

Logger Persistence Infrastructure

Layer / File(s) Summary
Log4js Integration & Error Serialization
apps/core-app/src/main/utils/logger.ts
Imports log4js and adds writePersistentLog() to write colored-agnostic plainLine and serialized errors. Introduces formatMetaPlain() for non-chalk metadata, serializeError() for stack/JSON/string fallback, and getNativeConsoleMethod() for centralized console selection. Console and error persistence routing refactored from direct level-selection to native-method dispatch plus log4js-backed output.
Module Logger Routing
packages/utils/common/logger/module-logger.ts
ModuleLogger.log() now computes plainOutput and calls writeMainProcessLog() to forward to globalThis.logger/globalThis.errLogger, then emits to console via getConsoleMethod(). Added serializeArg() helper for Error stack/name/message handling and internal LogSink/MainProcessGlobal/NativeConsole types.
Module Enablement
packages/utils/common/logger/logger-manager.ts
file-provider and app-provider modules now enabled by default with log level changed from DEBUG (when disabled) to INFO.

Active App Detection Improvements

Layer / File(s) Summary
Error & Output Normalization
apps/core-app/src/main/modules/system/active-app.ts
Added helpers: getCommandErrorCode(), getCommandErrorMessage(), extractJsonObjectLine() to normalize PowerShell error metadata and extract JSON objects from mixed stdout. Windows active-app script now initializes $processId as uint32 and emits compact UTF-8 JSON. Parsing refactored to extract JSON object from stdout instead of assuming pure JSON after trim. Failure logging emits structured meta with code and message.
Test Coverage
apps/core-app/src/main/modules/system/active-app.test.ts
Two new Windows tests: one verifies parsing succeeds despite PowerShell warning line before JSON; another verifies failure mode calls warn with structured error meta containing code and message.

Everything Provider Backend Diagnostics

Layer / File(s) Summary
Backend Error Tracking
apps/core-app/src/main/modules/box-tool/addon/files/everything-provider.ts, everything-provider.test.ts
Provider maintains backendAttemptErrors: Record<string, string> map keyed by backend/candidate, cleared on each initialization. SDK/CLI load failures record error messages; getStatusSnapshot() now includes backendAttemptErrors in EverythingStatusResponse. Test adds field to MutableEverythingProvider and resets in cleanup.
Event Schema Update
apps/core-app/src/shared/events/everything.ts
EverythingStatusResponse now includes backendAttemptErrors: Record<string, string> field to carry per-backend attempt error details.

Windows UI Layout and Title Bar Styling

Layer / File(s) Summary
Title Bar Styling Updates
apps/core-app/src/main/config/default.ts
MainWindowOption.titleBarOverlay increases height from 35 to 40 and changes symbolColor from 'white' to '#1f2937'. DivisionBoxWindowOption.titleBarOverlay updates symbolColor to '#1f2937'.
CSS Custom Property & Layout Mixin
apps/core-app/src/renderer/src/styles/layout/_layout-shell.scss
Adds --layout-window-controls-width: 0px custom property to .AppLayout-Header within layout-shell-base mixin.
Renderer Component Props & Styling
apps/core-app/src/renderer/src/views/layout/flat/FlatLayout.vue
apps/core-app/src/renderer/src/views/layout/shared/LayoutShell.vue
FlatLayout.vue computes isWindows from process.platform === 'win32' and forwards to LayoutShell via :is-windows prop. LayoutShell.vue applies Windows-specific styling: for both simple and flat variants, sets --layout-window-controls-width: 138px and adds left padding to header child elements; globally adds right padding and ::after width calculation using the custom property for all .is-windows containers with forced border-radius: 0.

Documentation Updates

Layer / File(s) Summary
Changelog & TODO
docs/plan-prd/01-project/CHANGES.md, docs/plan-prd/TODO.md
Adds dated 2026-05-05 changelog entry documenting Windows diagnostics persistence, Store/UWP metadata, app launch logging, startup deferment, and titlebar/display-name fixes. Adds "Windows Search/Launch Stabilization (2026-05-05)" task board with completed items (diagnostics, Store indexing, display-name fallback, contention reduction, Everything errors, UI fixes, active-app improvements) and follow-up test/measurement todos.
Diagnostics Report
docs/plan-prd/report/windows-search-diagnostics-2026-05-05.md
Comprehensive diagnostic report detailing production logging gaps, crash dumps, findings across display-name corruption, startup/search contention, Everything backend errors, and UI issues. Documents all implemented changes: persistent main diagnostics, .lnk/launch metadata handling, Store app indexing via AUMID, corrupted-displayName fallback, search deferment, backend error tracking, UI layout adjustments, and active-app parsing improvements. Includes verification status (typecheck/tests passed; spawn/approval-service blocked) and follow-up measurement instructions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Possibly related PRs

  • talex-touch/tuff#254: Modifies display-name normalization and keyword generation logic in app-provider/search-processing — directly overlaps with corruption-detection and resolved-displayName propagation.
  • talex-touch/tuff#234: Updates Everything status contract and provider payload shape (EverythingStatusResponse) — directly related to backend error tracking additions.
  • talex-touch/tuff#224: Modifies the same app indexing and search code (app-provider.ts, search-processing-service.ts) — changes to related display-name and keyword-sync logic.

Suggested labels

codex, Windows, diagnostics, search, ui-layout, logging


🐰 Windows bugs scattered far and wide,
With corrupted names and paths we hide,
Now logger sings to disk so true,
Title bars shine bright, restyled anew!
Search flows smooth where chaos once grew.

🚥 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 accurately and concisely captures the main focus of the changeset: stabilizing Windows search and launch diagnostics through multiple improvements including persistence logging, Windows app handling, corruption detection, and UI fixes.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Contributor

@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: 5

Caution

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

⚠️ Outside diff range comments (1)
docs/plan-prd/TODO.md (1)

327-336: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Task statistics table is stale after adding the new section.

The new "Windows Search/Launch Stabilization" section adds 8 [x] and 2 [ ] items, but the counts at lines 329–334 still read 139/21/160 from 2026-04-07. If pnpm docs:guard validates these counters, it will fail.

📝 Suggested update
-| 已完成 (`- [x]`) | 139 |
-| 未完成 (`- [ ]`) | 21 |
-| 总计 | 160 |
-| 完成率 | 87% |
+| 已完成 (`- [x]`) | 147 |
+| 未完成 (`- [ ]`) | 23 |
+| 总计 | 170 |
+| 完成率 | 86% |
-> 统计时间: 2026-04-07(按本文件实时 checkbox 计数)。
+> 统计时间: 2026-05-05(按本文件实时 checkbox 计数)。
🤖 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 `@docs/plan-prd/TODO.md` around lines 327 - 336, Update the task statistics
table to reflect the new "Windows Search/Launch Stabilization" section:
increment 已完成 (`- [x]`) by 8 (139 -> 147), 未完成 (`- [ ]`) by 2 (21 -> 23), 总计 by
10 (160 -> 170) and set 完成率 to 86% (147/170); also update the “统计时间” date to the
current snapshot date and ensure the table row labels remain "已完成 (`- [x]`)",
"未完成 (`- [ ]`)", "总计", and "完成率" so pnpm docs:guard validation passes.
🧹 Nitpick comments (3)
apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts (2)

329-352: ⚡ Quick win

Dual bundleId/bundle_id accessor smells like API drift.

AppLaunchMetadata accepts both bundle_id (the snake_case key emitted by search-processing-service.ts) and bundleId (camelCase). onExecute reads launchMeta.bundleId || launchMeta.bundle_id, but buildProcessedAppItem only emits bundle_id. Pick one shape (camelCase to match appUserModelId/launchKind) and drop the alias to prevent future producers from drifting again.

Proposed cleanup
- type AppLaunchMetadata = {
-   path?: string
-   bundle_id?: string
-   bundleId?: string
+ type AppLaunchMetadata = {
+   path?: string
+   bundleId?: string

…and update search-processing-service.ts to emit bundleId consistently.

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts` around
lines 329 - 352, AppLaunchMetadata currently accepts both bundle_id and bundleId
which causes API drift; choose one canonical key (prefer camelCase: bundleId to
match appUserModelId/launchKind), remove bundle_id from the AppLaunchMetadata
type and any fallback logic (e.g. the launchMeta.bundleId ||
launchMeta.bundle_id check in onExecute), and update the producer
buildProcessedAppItem (and search-processing-service.ts) to emit bundleId
consistently so all consumers use AppLaunchMetadata.bundleId only.

1785-1918: 💤 Low value

launchApp flow LGTM, but void launchApp(...) swallows unhandled rejections.

The shortcut-first → direct-path → spawn fallback chain matches the report's intent and includes the AppsFolder/explorer fallback. One small concern: void this.launchApp(...) at the call site (Line 1780) detaches the promise; the inner method already wraps everything in try/catch, but adding a .catch(...) on the floating promise (or marking the call await-able for tests) would prevent any future unhandled-rejection regression if a throw is introduced before the existing try boundary.

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts` around
lines 1785 - 1918, The PR currently calls launchApp with a detached promise
(void this.launchApp(...)) which can swallow future unhandled rejections; update
the call site to either await this.launchApp(...) or append a safe rejection
handler like this.launchApp(...).catch(err => logApp(`launchApp promise
rejected: ${err instanceof Error ? err.message : String(err)}`, LogStyle.error,
{ stack: err instanceof Error ? err.stack : undefined })) so any thrown errors
from launchApp (the method defined as private async launchApp(...)) are
surfaced/logged; no changes needed inside spawnAppFallback other than ensuring
launchApp rejections are handled at the caller.
apps/core-app/src/main/modules/box-tool/addon/apps/win.ts (1)

411-439: 💤 Low value

getAppInfo AppsFolder/URL branches omit displayName.

The Start Menu shortcut and direct-path branches set displayName: appName, but the AppsFolder and URL branches return objects without displayName. Consumers in app-provider.ts derive keywords/title from displayName/name, and downstream _mapDbAppToScannedInfo already tolerates missing values, but for consistency (and to give the AUMID/URL launcher a non-noisy human-readable label) consider populating displayName: appUserModelId/displayName: filePath here too — or document why it's intentionally omitted.

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/win.ts` around lines 411 -
439, The AppsFolder and URL branches in getAppInfo omit displayName; add
displayName: appUserModelId to the APPS_FOLDER_PREFIX branch and displayName:
filePath to the isUrlLaunchId branch so both return objects include a
human-readable label (refer to symbols APPS_FOLDER_PREFIX, appUserModelId,
isUrlLaunchId, filePath and the getAppInfo return object).
🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts`:
- Around line 1199-1209: The function _generateKeywordsForApp currently uses
appInfo.description and appInfo.appUserModelId as sources and can inherit
AUMID-like strings into the description-based matching path; change the logic so
you skip adding description-derived keywords when the description is equal to or
appears to be an AUMID (e.g., contains characters typical of AUMIDs like '.' '!'
'_' or matches a short-manifest-token pattern), keep using appUserModelId only
for validation (don’t treat it as a description), and ensure
INVALID_KEYWORD_REGEX still filters raw tokens; update _generateKeywordsForApp
to detect and ignore AUMID-like descriptions before splitting/adding keywords
(refer to _generateKeywordsForApp, INVALID_KEYWORD_REGEX, and
appInfo.description / appInfo.appUserModelId).

In `@apps/core-app/src/main/modules/box-tool/addon/apps/win.ts`:
- Around line 366-379: The code currently sets description:
toManifestDisplayName(entry.Description) || appUserModelId which uses the raw
AUMID as a fallback and pollutes keyword/indexing; update the apps.push object
(the block that builds each app entry) to remove the fallback so description is
only set from toManifestDisplayName(entry.Description) (i.e., make description
undefined when toManifestDisplayName returns falsy) — this change affects how
_generateKeywordsForApp and processSearchResults receive description and
prevents AUMID strings from being treated as descriptions/keywords.

In `@apps/core-app/src/main/modules/system/active-app.ts`:
- Around line 392-396: When a Windows probe resolves successfully (the awaited
resolveTask yields a truthy result), also reset the warning cooldown so future
failures aren't muted: in the same branch where you set
this.windowsFailureBackoffUntil = 0 (inside the if (result) block after awaiting
resolveTask), also set this.windowsFailureLogCooldownUntil = 0 so the cooldown
is cleared on success.

In `@apps/core-app/src/main/polyfills.ts`:
- Around line 45-49: The override of consoleRef.info currently routes all
messages to globalThis.logger.info which will be suppressed in packaged builds;
restore a native path by always invoking consoleRef._info(message, ...args) so
the original console output is preserved, and then conditionally call
globalThis.logger.info only when appropriate (e.g., when
globalThis.logger.isLevelEnabled('info') or similar) to avoid double-logging;
update the implementation in the consoleRef.info override and keep the saved
original as consoleRef._info for direct use.

In `@docs/plan-prd/TODO.md`:
- Line 364: Update the checklist item in TODO.md to fix product-name casing:
replace "wechat" with "WeChat" and "apple music" with "Apple Music" in the line
that reads "Capture post-fix measurements for `微信`, `wechat`, `codex`, `apple
music`, Everything status and app DB table sizes." — leave the other tokens
(`微信`, `codex`, Everything status, app DB table sizes) unchanged.

---

Outside diff comments:
In `@docs/plan-prd/TODO.md`:
- Around line 327-336: Update the task statistics table to reflect the new
"Windows Search/Launch Stabilization" section: increment 已完成 (`- [x]`) by 8 (139
-> 147), 未完成 (`- [ ]`) by 2 (21 -> 23), 总计 by 10 (160 -> 170) and set 完成率 to 86%
(147/170); also update the “统计时间” date to the current snapshot date and ensure
the table row labels remain "已完成 (`- [x]`)", "未完成 (`- [ ]`)", "总计", and "完成率" so
pnpm docs:guard validation passes.

---

Nitpick comments:
In `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts`:
- Around line 329-352: AppLaunchMetadata currently accepts both bundle_id and
bundleId which causes API drift; choose one canonical key (prefer camelCase:
bundleId to match appUserModelId/launchKind), remove bundle_id from the
AppLaunchMetadata type and any fallback logic (e.g. the launchMeta.bundleId ||
launchMeta.bundle_id check in onExecute), and update the producer
buildProcessedAppItem (and search-processing-service.ts) to emit bundleId
consistently so all consumers use AppLaunchMetadata.bundleId only.
- Around line 1785-1918: The PR currently calls launchApp with a detached
promise (void this.launchApp(...)) which can swallow future unhandled
rejections; update the call site to either await this.launchApp(...) or append a
safe rejection handler like this.launchApp(...).catch(err => logApp(`launchApp
promise rejected: ${err instanceof Error ? err.message : String(err)}`,
LogStyle.error, { stack: err instanceof Error ? err.stack : undefined })) so any
thrown errors from launchApp (the method defined as private async
launchApp(...)) are surfaced/logged; no changes needed inside spawnAppFallback
other than ensuring launchApp rejections are handled at the caller.

In `@apps/core-app/src/main/modules/box-tool/addon/apps/win.ts`:
- Around line 411-439: The AppsFolder and URL branches in getAppInfo omit
displayName; add displayName: appUserModelId to the APPS_FOLDER_PREFIX branch
and displayName: filePath to the isUrlLaunchId branch so both return objects
include a human-readable label (refer to symbols APPS_FOLDER_PREFIX,
appUserModelId, isUrlLaunchId, filePath and the getAppInfo return object).
🪄 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

Run ID: 75c2ff5f-eaa4-4a4a-a320-129be71e3d04

📥 Commits

Reviewing files that changed from the base of the PR and between 69887ae and 52a6fc3.

📒 Files selected for processing (24)
  • apps/core-app/src/main/config/default.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-types.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/display-name-sync-utils.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/display-name-sync-utils.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/search-processing-service.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/search-processing-service.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/win.ts
  • apps/core-app/src/main/modules/box-tool/addon/files/everything-provider.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/files/everything-provider.ts
  • apps/core-app/src/main/modules/system/active-app.test.ts
  • apps/core-app/src/main/modules/system/active-app.ts
  • apps/core-app/src/main/polyfills.ts
  • apps/core-app/src/main/utils/logger.ts
  • apps/core-app/src/renderer/src/styles/layout/_layout-shell.scss
  • apps/core-app/src/renderer/src/views/layout/flat/FlatLayout.vue
  • apps/core-app/src/renderer/src/views/layout/shared/LayoutShell.vue
  • apps/core-app/src/shared/events/everything.ts
  • docs/plan-prd/01-project/CHANGES.md
  • docs/plan-prd/TODO.md
  • docs/plan-prd/report/windows-search-diagnostics-2026-05-05.md
  • packages/utils/common/logger/logger-manager.ts
  • packages/utils/common/logger/module-logger.ts

Comment thread apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts
Comment thread apps/core-app/src/main/modules/box-tool/addon/apps/win.ts Outdated
Comment on lines +392 to +396
try {
const result = await resolveTask
if (result) {
this.windowsFailureBackoffUntil = 0
}
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reset the warning cooldown after a successful Windows probe.

windowsFailureLogCooldownUntil survives successful resolutions, so a fresh failure within the next 10s is still muted even after the resolver has recovered. That makes intermittent Windows issues harder to diagnose. Clear the cooldown alongside windowsFailureBackoffUntil when result is truthy.

Suggested fix
     try {
       const result = await resolveTask
       if (result) {
         this.windowsFailureBackoffUntil = 0
+        this.windowsFailureLogCooldownUntil = 0
       }
       return result
     } finally {
🤖 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 `@apps/core-app/src/main/modules/system/active-app.ts` around lines 392 - 396,
When a Windows probe resolves successfully (the awaited resolveTask yields a
truthy result), also reset the warning cooldown so future failures aren't muted:
in the same branch where you set this.windowsFailureBackoffUntil = 0 (inside the
if (result) block after awaiting resolveTask), also set
this.windowsFailureLogCooldownUntil = 0 so the cooldown is cleared on success.

Comment thread apps/core-app/src/main/polyfills.ts Outdated
Comment on lines +45 to +49
consoleRef._info = consoleRef.info
consoleRef.info = (message?: unknown, ...args: unknown[]) => {
if (args?.length) globalThis.logger.info(message, args)
else globalThis.logger.info(message)
}
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't turn console.info() into a production no-op.

This new override sends every console.info() through globalThis.logger.info(), but Lines 81-83 later raise that logger to "warn" in packaged builds. The result is that info-level startup diagnostics from Electron/dependencies are silently dropped instead of being preserved. Please keep a native consoleRef._info path, or route these messages through a sink whose persistence is not gated by the console verbosity level.

🤖 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 `@apps/core-app/src/main/polyfills.ts` around lines 45 - 49, The override of
consoleRef.info currently routes all messages to globalThis.logger.info which
will be suppressed in packaged builds; restore a native path by always invoking
consoleRef._info(message, ...args) so the original console output is preserved,
and then conditionally call globalThis.logger.info only when appropriate (e.g.,
when globalThis.logger.isLevelEnabled('info') or similar) to avoid
double-logging; update the implementation in the consoleRef.info override and
keep the saved original as consoleRef._info for direct use.

Comment thread docs/plan-prd/TODO.md Outdated
- [x] Record performance and index analysis report: `docs/plan-prd/report/windows-search-diagnostics-2026-05-05.md`.
- [x] Repair corrupted Windows app display names from stale index data: bad `display_name` values containing replacement/square glyphs now fall back to a clean `name` and are corrected during backfill/full sync.
- [ ] Re-run target Vitest, `typecheck:web`, dev launch, and production DB snapshot analysis once approval service / child-process permissions are available.
- [ ] Capture post-fix measurements for `微信`, `wechat`, `codex`, `apple music`, Everything status and app DB table sizes.
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix brand-name casing: wechatWeChat, apple musicApple Music.

These are proper product names; incorrect casing is flagged by the project's LanguageTool linter.

📝 Proposed fix
-- [ ] Capture post-fix measurements for `微信`, `wechat`, `codex`, `apple music`, Everything status and app DB table sizes.
+- [ ] Capture post-fix measurements for `微信`, `WeChat`, `codex`, `Apple Music`, Everything status and app DB table sizes.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~364-~364: The official name of this popular chat service is spelled with a capital “C”.
Context: ...Capture post-fix measurements for 微信, wechat, codex, apple music, Everything st...

(WECHAT)


[uncategorized] ~364-~364: Did you mean the proper noun “Apple Music”?
Context: ...asurements for 微信, wechat, codex, apple music, Everything status and app DB table si...

(APPLE_PRODUCTS)

🤖 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 `@docs/plan-prd/TODO.md` at line 364, Update the checklist item in TODO.md to
fix product-name casing: replace "wechat" with "WeChat" and "apple music" with
"Apple Music" in the line that reads "Capture post-fix measurements for `微信`,
`wechat`, `codex`, `apple music`, Everything status and app DB table sizes." —
leave the other tokens (`微信`, `codex`, Everything status, app DB table sizes)
unchanged.

Copy link
Copy Markdown
Contributor

@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: 6

Caution

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

⚠️ Outside diff range comments (2)
apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts (2)

647-676: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Cleared managed-entry metadata is never removed here.

This update path only re-adds truthy extension rows. If a user clears launchArgs, workingDirectory, description, alternateNames, icon, or similar fields, the old fileExtensions rows survive and the app can keep launching or searching with stale metadata after the edit.

Suggested fix
+      await db
+        .delete(fileExtensions)
+        .where(
+          and(
+            eq(fileExtensions.fileId, existingFile.id),
+            inArray(fileExtensions.key, [
+              'bundleId',
+              'icon',
+              APP_IDENTITY_EXTENSION_KEY,
+              APP_LAUNCH_KIND_EXTENSION_KEY,
+              APP_LAUNCH_TARGET_EXTENSION_KEY,
+              APP_LAUNCH_ARGS_EXTENSION_KEY,
+              APP_WORKING_DIRECTORY_EXTENSION_KEY,
+              APP_DISPLAY_PATH_EXTENSION_KEY,
+              APP_DESCRIPTION_EXTENSION_KEY,
+              APP_ALTERNATE_NAMES_EXTENSION_KEY,
+              APP_ENTRY_SOURCE_EXTENSION_KEY,
+              APP_ENTRY_ENABLED_EXTENSION_KEY
+            ])
+          )
+        )
+
       const nextExtensions = this.buildManagedEntryExtensions(existingFile.id, appInfo, enabled)
       await this.dbUtils.addFileExtensions(nextExtensions)
🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts` around
lines 647 - 676, The update path re-adds only truthy extension rows so cleared
fields leave stale fileExtensions; before calling
this.dbUtils.addFileExtensions(nextExtensions) compute which extension keys are
now cleared by comparing existingExtensions (from existingFile.extensions) to
the new nextExtensions (or by checking falsy values in
buildManagedEntryExtensions output) and call a removal operation to delete those
keys for the file (e.g., add a call like
this.dbUtils.removeFileExtensions(fileId, keysToRemove) or a suitable DB delete
method) so that entries for launchArgs, workingDirectory, description,
alternateNames, icon, etc. that were cleared are deleted; then proceed to add
nextExtensions and update the extensions map used in this.mapManagedEntry.

1345-1363: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

This file still has lint blockers.

These new blocks violate the current ESLint profile (antfu/consistent-chaining, style/arrow-parens, style/operator-linebreak), so the closest quality gate for this file will still fail until they’re normalized.

As per coding guidelines, "Run quality checks (lint/typecheck/test/build) closest to changed code without fixing unrelated failures".

Also applies to: 1609-1616, 1848-1860

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts` around
lines 1345 - 1363, The multi-call query creating insertedFile
(this.dbUtils!.getDb().insert(filesSchema).values(...).onConflictDoUpdate(...).returning())
must be reformatted to satisfy the antfu/consistent-chaining, style/arrow-parens
and style/operator-linebreak rules: break the chain so each method call starts
on its own line (e.g. const [insertedFile] = await this.dbUtils!.getDb()\n 
.insert(filesSchema)\n  .values({ ... })\n  .onConflictDoUpdate({ ... })\n 
.returning(); ensure any arrow functions in nearby changed blocks use consistent
parentheses around params, and place binary operators (if split across lines) at
the end of the previous line rather than the start; re-run the linter to verify
the change.
🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts`:
- Around line 215-216: The two single-line if statements using normalizedNext
and normalizedCurrent violate the antfu/if-newline rule; change both to
block-style if statements (i.e., use braces and put the return on the next line)
for the checks "if (typeof normalizedNext === 'string' &&
normalizedNext.includes('\uFFFD'))" and "if (typeof normalizedCurrent ===
'string' && normalizedCurrent.includes('\uFFFD'))" so each has its own newline
and braces around the return to satisfy ESLint.
- Around line 201-210: The mock is inconsistent: isProbablyCorruptedDisplayName
flags both '\uFFFD' and '\u25A1' as corrupted, but resolveDisplayName (and other
places around resolveDisplayName/normalizeDisplayName) only checks '\uFFFD';
update resolveDisplayName (and any other mock checks e.g., the later check at
the second occurrence noted) to treat '\u25A1' the same way as '\uFFFD' so the
mock consistently detects and falls back for both corruption characters (refer
to isProbablyCorruptedDisplayName and resolveDisplayName to locate the changes).
- Around line 709-713: The arrow function assigned to
privateProvider.fetchExtensionsForFiles uses parentheses around a single
parameter; update the function signature in the fetchExtensionsForFiles mock so
the single parameter is unparenthesized (i.e., change "(files) =>" to "files
=>") while leaving the body intact; reference the
privateProvider.fetchExtensionsForFiles mock and the dbRow usage to locate the
change.

In `@apps/core-app/src/main/modules/box-tool/addon/apps/win.test.ts`:
- Around line 163-166: The if statement inside statMock.mockImplementation uses
a single-line body and triggers antfu/if-newline; update the implementation in
statMock.mockImplementation to put the body on the next line (or use braces) so
the return is on its own line when target === appPath; locate the mock by the
symbol statMock.mockImplementation and the related identifiers
appPath/createFileStat and modify the block to use a newline (or a braced block)
before calling createFileStat().

In
`@apps/core-app/src/main/modules/box-tool/search-engine/recommendation/recommendation-engine.ts`:
- Around line 1719-1722: The current block in recommendation-engine (variable
appMeta and returned cache key using appMeta.bundleId) must fall back to the
legacy meta.app.bundle_id during the cache migration window; update the logic
that builds the cache key (the code that uses appMeta and sourceId) to check
both appMeta.bundleId and appMeta.bundle_id (e.g., use bundleId || bundle_id) so
cached entries written with the old field still resolve to the same key and
de-dupe/pinned filtering remains correct.

In `@apps/core-app/src/main/modules/system/active-app.ts`:
- Around line 60-77: Split single-line if-statements into multi-line blocks with
braces and a newline and remove unnecessary parens from single-parameter arrow
functions: in getCommandErrorCode change the single-line "if (!error || typeof
error !== 'object') return null" into a block with braces and a newline; in
getCommandErrorMessage change "if (error instanceof Error) return error.message"
into a braced multi-line if; and in extractJsonObjectLine replace "(line) =>"
occurrences with "line =>" for map and find callbacks so they follow the
configured arrow-parens rule. Ensure formatting matches project lint rules.

---

Outside diff comments:
In `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts`:
- Around line 647-676: The update path re-adds only truthy extension rows so
cleared fields leave stale fileExtensions; before calling
this.dbUtils.addFileExtensions(nextExtensions) compute which extension keys are
now cleared by comparing existingExtensions (from existingFile.extensions) to
the new nextExtensions (or by checking falsy values in
buildManagedEntryExtensions output) and call a removal operation to delete those
keys for the file (e.g., add a call like
this.dbUtils.removeFileExtensions(fileId, keysToRemove) or a suitable DB delete
method) so that entries for launchArgs, workingDirectory, description,
alternateNames, icon, etc. that were cleared are deleted; then proceed to add
nextExtensions and update the extensions map used in this.mapManagedEntry.
- Around line 1345-1363: The multi-call query creating insertedFile
(this.dbUtils!.getDb().insert(filesSchema).values(...).onConflictDoUpdate(...).returning())
must be reformatted to satisfy the antfu/consistent-chaining, style/arrow-parens
and style/operator-linebreak rules: break the chain so each method call starts
on its own line (e.g. const [insertedFile] = await this.dbUtils!.getDb()\n 
.insert(filesSchema)\n  .values({ ... })\n  .onConflictDoUpdate({ ... })\n 
.returning(); ensure any arrow functions in nearby changed blocks use consistent
parentheses around params, and place binary operators (if split across lines) at
the end of the previous line rather than the start; re-run the linter to verify
the change.
🪄 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

Run ID: 2630d26f-d964-4a75-948a-bbc9e2db4a45

📥 Commits

Reviewing files that changed from the base of the PR and between 52a6fc3 and ab1089a.

📒 Files selected for processing (12)
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/search-processing-service.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/search-processing-service.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/win.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/win.ts
  • apps/core-app/src/main/modules/box-tool/addon/files/everything-provider.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/files/everything-provider.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/recommendation/recommendation-engine.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/search-core.ts
  • apps/core-app/src/main/modules/system/active-app.test.ts
  • apps/core-app/src/main/modules/system/active-app.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/core-app/src/main/modules/box-tool/addon/files/everything-provider.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/core-app/src/main/modules/box-tool/addon/apps/search-processing-service.test.ts
  • apps/core-app/src/main/modules/box-tool/addon/apps/win.ts

Comment on lines +201 to +210
isProbablyCorruptedDisplayName: vi.fn((value: string | null | undefined) => {
return typeof value === 'string' && (value.includes('\uFFFD') || value.includes('\u25A1'))
}),
normalizeDisplayName: vi.fn((value: string | null | undefined) => value ?? null),
resolveDisplayName: vi.fn((displayName: string | null | undefined, fallbackName: string) => {
if (typeof displayName === 'string' && displayName && !displayName.includes('\uFFFD')) {
return displayName
}
return fallbackName
}),
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Corruption mock logic is inconsistent for \u25A1 and can hide backfill regressions.

Line [201]-Line [203] treats both \uFFFD and \u25A1 as corrupted, but Line [206] and Line [215]-Line [216] only check \uFFFD. This makes the mock internally inconsistent and may miss repair/update behavior for \u25A1 inputs.

Suggested fix
  resolveDisplayName: vi.fn((displayName: string | null | undefined, fallbackName: string) => {
-    if (typeof displayName === 'string' && displayName && !displayName.includes('\uFFFD')) {
+    if (
+      typeof displayName === 'string'
+      && displayName
+      && !displayName.includes('\uFFFD')
+      && !displayName.includes('\u25A1')
+    ) {
       return displayName
     }
     return fallbackName
   }),
   shouldUpdateDisplayName: vi.fn(
     (current: string | null | undefined, next: string | null | undefined) => {
       const normalizedCurrent = current ?? null
       const normalizedNext = next ?? null
-      if (typeof normalizedNext === 'string' && normalizedNext.includes('\uFFFD')) return false
-      if (typeof normalizedCurrent === 'string' && normalizedCurrent.includes('\uFFFD')) return true
+      if (
+        typeof normalizedNext === 'string'
+        && (normalizedNext.includes('\uFFFD') || normalizedNext.includes('\u25A1'))
+      ) {
+        return false
+      }
+      if (
+        typeof normalizedCurrent === 'string'
+        && (normalizedCurrent.includes('\uFFFD') || normalizedCurrent.includes('\u25A1'))
+      ) {
+        return true
+      }
       return normalizedCurrent !== normalizedNext
     }
   )

Also applies to: 215-217

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts`
around lines 201 - 210, The mock is inconsistent: isProbablyCorruptedDisplayName
flags both '\uFFFD' and '\u25A1' as corrupted, but resolveDisplayName (and other
places around resolveDisplayName/normalizeDisplayName) only checks '\uFFFD';
update resolveDisplayName (and any other mock checks e.g., the later check at
the second occurrence noted) to treat '\u25A1' the same way as '\uFFFD' so the
mock consistently detects and falls back for both corruption characters (refer
to isProbablyCorruptedDisplayName and resolveDisplayName to locate the changes).

Comment on lines +215 to +216
if (typeof normalizedNext === 'string' && normalizedNext.includes('\uFFFD')) return false
if (typeof normalizedCurrent === 'string' && normalizedCurrent.includes('\uFFFD')) return true
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

ESLint failure: if single-line statements violate antfu/if-newline.

Line [215] and Line [216] are currently written as one-line if statements and match the reported lint error. Please format them with newline/block style to unblock checks.

🧰 Tools
🪛 ESLint

[error] 215-215: Expect newline after if

(antfu/if-newline)


[error] 216-216: Expect newline after if

(antfu/if-newline)

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts`
around lines 215 - 216, The two single-line if statements using normalizedNext
and normalizedCurrent violate the antfu/if-newline rule; change both to
block-style if statements (i.e., use braces and put the return on the next line)
for the checks "if (typeof normalizedNext === 'string' &&
normalizedNext.includes('\uFFFD'))" and "if (typeof normalizedCurrent ===
'string' && normalizedCurrent.includes('\uFFFD'))" so each has its own newline
and braces around the return to satisfy ESLint.

Comment on lines +709 to +713
privateProvider.fetchExtensionsForFiles = vi.fn(async (files: unknown[]) =>
files.map((file) => ({
...(file as typeof dbRow),
extensions: { appIdentity: 'path:d:\\weixin\\weixin.exe' }
}))
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

ESLint failure: arrow function uses disallowed parens for single parameter.

Line [710] wraps a single arrow parameter in parentheses ((files) =>) while style/arrow-parens expects files => for this style rule.

Suggested fix
-    privateProvider.fetchExtensionsForFiles = vi.fn(async (files: unknown[]) =>
+    privateProvider.fetchExtensionsForFiles = vi.fn(async files =>
       files.map((file) => ({
         ...(file as typeof dbRow),
         extensions: { appIdentity: 'path:d:\\weixin\\weixin.exe' }
       }))
     )
📝 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
privateProvider.fetchExtensionsForFiles = vi.fn(async (files: unknown[]) =>
files.map((file) => ({
...(file as typeof dbRow),
extensions: { appIdentity: 'path:d:\\weixin\\weixin.exe' }
}))
privateProvider.fetchExtensionsForFiles = vi.fn(async files =>
files.map((file) => ({
...(file as typeof dbRow),
extensions: { appIdentity: 'path:d:\\weixin\\weixin.exe' }
}))
)
🧰 Tools
🪛 ESLint

[error] 710-710: Unexpected parentheses around single function argument having a body with no curly braces.

(style/arrow-parens)

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/app-provider.test.ts`
around lines 709 - 713, The arrow function assigned to
privateProvider.fetchExtensionsForFiles uses parentheses around a single
parameter; update the function signature in the fetchExtensionsForFiles mock so
the single parameter is unparenthesized (i.e., change "(files) =>" to "files
=>") while leaving the body intact; reference the
privateProvider.fetchExtensionsForFiles mock and the dbRow usage to locate the
change.

Comment on lines +163 to +166
statMock.mockImplementation(async (target: string) => {
if (target === appPath) return createFileStat()
throw new Error(`Unexpected stat path: ${target}`)
})
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix missing newline after if (ESLint antfu/if-newline error).

Line 164 triggers a lint error — the rule requires a newline between the if condition and its body.

🔧 Proposed fix
     statMock.mockImplementation(async (target: string) => {
-      if (target === appPath) return createFileStat()
-      throw new Error(`Unexpected stat path: ${target}`)
+      if (target === appPath)
+        return createFileStat()
+      throw new Error(`Unexpected stat path: ${target}`)
     })
📝 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
statMock.mockImplementation(async (target: string) => {
if (target === appPath) return createFileStat()
throw new Error(`Unexpected stat path: ${target}`)
})
statMock.mockImplementation(async (target: string) => {
if (target === appPath)
return createFileStat()
throw new Error(`Unexpected stat path: ${target}`)
})
🧰 Tools
🪛 ESLint

[error] 164-164: Expect newline after if

(antfu/if-newline)

🤖 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 `@apps/core-app/src/main/modules/box-tool/addon/apps/win.test.ts` around lines
163 - 166, The if statement inside statMock.mockImplementation uses a
single-line body and triggers antfu/if-newline; update the implementation in
statMock.mockImplementation to put the body on the next line (or use braces) so
the return is on its own line when target === appPath; locate the mock by the
symbol statMock.mockImplementation and the related identifiers
appPath/createFileStat and modify the block to use a newline (or a braced block)
before calling createFileStat().

Comment on lines 1719 to 1722
const appMeta = meta?.app
if (appMeta?.bundle_id) {
return `${sourceId}:bundle:${appMeta.bundle_id}`
if (appMeta?.bundleId) {
return `${sourceId}:bundle:${appMeta.bundleId}`
}
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep a legacy bundle_id fallback during the cache migration window.

getCachedRecommendations() can still hydrate items written before this rename. Those cached entries will carry meta.app.bundle_id, and falling back to path here can break de-dupe or pinned filtering for the same app until the recommendation cache expires—especially now that this PR also changes Windows app path semantics.

🤖 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
`@apps/core-app/src/main/modules/box-tool/search-engine/recommendation/recommendation-engine.ts`
around lines 1719 - 1722, The current block in recommendation-engine (variable
appMeta and returned cache key using appMeta.bundleId) must fall back to the
legacy meta.app.bundle_id during the cache migration window; update the logic
that builds the cache key (the code that uses appMeta and sourceId) to check
both appMeta.bundleId and appMeta.bundle_id (e.g., use bundleId || bundle_id) so
cached entries written with the old field still resolve to the same key and
de-dupe/pinned filtering remains correct.

Comment on lines +60 to +77
function getCommandErrorCode(error: unknown): string | null {
if (!error || typeof error !== 'object') return null
const value = (error as { code?: unknown }).code
return typeof value === 'string' ? value : null
}

function getCommandErrorMessage(error: unknown): string {
if (error instanceof Error) return error.message
return String(error)
}

function extractJsonObjectLine(output: string): string {
const lines = output
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean)
return lines.reverse().find((line) => line.startsWith('{') && line.endsWith('}')) || output.trim()
}
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix ESLint violations in the new helper block before merge.

Line 61, Line 67, Line 74, and Line 76 violate configured lint rules (antfu/if-newline, style/arrow-parens), which will fail quality gates.

Suggested patch
 function getCommandErrorCode(error: unknown): string | null {
-  if (!error || typeof error !== 'object') return null
+  if (!error || typeof error !== 'object')
+    return null
   const value = (error as { code?: unknown }).code
   return typeof value === 'string' ? value : null
 }
 
 function getCommandErrorMessage(error: unknown): string {
-  if (error instanceof Error) return error.message
+  if (error instanceof Error)
+    return error.message
   return String(error)
 }
 
 function extractJsonObjectLine(output: string): string {
   const lines = output
     .split(/\r?\n/)
-    .map((line) => line.trim())
+    .map(line => line.trim())
     .filter(Boolean)
-  return lines.reverse().find((line) => line.startsWith('{') && line.endsWith('}')) || output.trim()
+  return lines.reverse().find(line => line.startsWith('{') && line.endsWith('}')) || output.trim()
 }

As per coding guidelines "Run quality checks (lint/typecheck/test/build) closest to changed code without fixing unrelated failures."

📝 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
function getCommandErrorCode(error: unknown): string | null {
if (!error || typeof error !== 'object') return null
const value = (error as { code?: unknown }).code
return typeof value === 'string' ? value : null
}
function getCommandErrorMessage(error: unknown): string {
if (error instanceof Error) return error.message
return String(error)
}
function extractJsonObjectLine(output: string): string {
const lines = output
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean)
return lines.reverse().find((line) => line.startsWith('{') && line.endsWith('}')) || output.trim()
}
function getCommandErrorCode(error: unknown): string | null {
if (!error || typeof error !== 'object')
return null
const value = (error as { code?: unknown }).code
return typeof value === 'string' ? value : null
}
function getCommandErrorMessage(error: unknown): string {
if (error instanceof Error)
return error.message
return String(error)
}
function extractJsonObjectLine(output: string): string {
const lines = output
.split(/\r?\n/)
.map(line => line.trim())
.filter(Boolean)
return lines.reverse().find(line => line.startsWith('{') && line.endsWith('}')) || output.trim()
}
🧰 Tools
🪛 ESLint

[error] 61-61: Expect newline after if

(antfu/if-newline)


[error] 67-67: Expect newline after if

(antfu/if-newline)


[error] 74-74: Unexpected parentheses around single function argument having a body with no curly braces.

(style/arrow-parens)


[error] 76-76: Unexpected parentheses around single function argument having a body with no curly braces.

(style/arrow-parens)

🤖 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 `@apps/core-app/src/main/modules/system/active-app.ts` around lines 60 - 77,
Split single-line if-statements into multi-line blocks with braces and a newline
and remove unnecessary parens from single-parameter arrow functions: in
getCommandErrorCode change the single-line "if (!error || typeof error !==
'object') return null" into a block with braces and a newline; in
getCommandErrorMessage change "if (error instanceof Error) return error.message"
into a braced multi-line if; and in extractJsonObjectLine replace "(line) =>"
occurrences with "line =>" for map and find callbacks so they follow the
configured arrow-parens rule. Ensure formatting matches project lint rules.

@TalexDreamSoul TalexDreamSoul merged commit 7174f1c into talex-touch:master May 8, 2026
9 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.

2 participants