Commit Graph
6 Commits
Author SHA1 Message Date
ZacharyZhang-NY 487f2456ff refactor(badges): derive from snapshot; delete getSidebarBadges IPC chain
Badges were fetched via a dedicated IPC that aggregated counts on the
server, while the same data lived in ProfileSnapshot on the client.
Two paths to the same answer drift whenever one side mutates between
refreshes — the visible symptom being "badge = 1 unread" with an empty
inbox after a message gets marked read in another screen.

Delete the whole server path. Sidebar badges are now derived on the
client from the snapshot via `deriveSidebarBadges(snapshot, companyId)`
in `src/shared/sidebar-badges.ts`. One source of truth; drift is
physically impossible.

Deletions:
- database/company-settings.ts::getSidebarBadges (120-line SQL aggregation)
- database-base.ts::getSidebarBadges pass-through
- ipc-core-read-handlers.ts: handler
- preload/index.ts: bridge binding
- shared/contracts/channels.ts: channel name
- shared/contracts/desktop-api/companies.ts: API signature
- shared/contracts/schemas-badges.ts::sidebarBadgesSchema Zod schema
- renderer/state/slices/company.ts: `badges` field, `setBadges`,
  `refreshBadges`
- useDataLoader: both getSidebarBadges call sites
- useCompanyController: badge reset on company switch
- useDesktopEvents: refreshBadges call on granular patches
- tests/unit/store.test.ts: refreshBadges test (deleted code)

The snapshot's agentMessages already carries board-reader read state
via boardReadReceiptMap (`snapshot.ts:39-47` has always LEFT JOIN'd
agent_message_reads with agent_id = BOARD_READER_ID). So derivation
needs no schema change — the infrastructure was in place, just unused.

fix(communication/MessageList): render orphaned-reply messages at the
top level

The thread-flattening used `filteredMessages.filter(m => !m.parentMessageId)`
to pick top-level messages. When an agent replies to a company/incident
post with a DM (the CEO prompt explicitly instructs this in
wake-reasons/en.ts:119), the DM lands in the direct channel with
parentMessageId pointing to a message that lives in another channel.
That parent is not in `filteredMessages` for the direct channel, so the
reply had no parent to nest under AND was excluded from top-level. The
channel rendered as a blank pane even though exactly one message
matched — the "clicked Dr. X ↔ Dr. Y, got empty" symptom.

Fix: a message is top-level when it either has no parent OR its parent
is outside the current filtered view. Replies with in-view parents
still nest normally.
2026-04-18 21:38:34 -04:00
ZacharyZhang-NY fd6471988a refactor(app): remove Console feature entirely
Per user request: the "显示控制台 / Show console" button in the top-right
header and the bottom drawer it opened are no longer needed — the Runs
section already renders the same log tail in-page via RunDetail, so the
drawer was a duplicate surface. Deleted the entire feature instead of
leaving a hidden toggle that attracts bugs.

Removed files:
- src/renderer/views/ConsoleView.tsx (126 LOC)

Removed renderer integration points:
- App.tsx: header "Show/Hide console" button, ConsoleView render,
  setConsoleOpen(true) call after startRun, TerminalWindow icon import
- views/sections/ExecutionSections.tsx: onOpenConsole callback,
  setConsoleOpen subscription
- components/runs/RunCenter.tsx: onOpenConsole prop (removed from
  forwarding chain)
- components/runs/RunDetail.tsx: onOpenConsole prop + the Lightning
  "Open console" ActionButton. The cancel-run button remains as the
  sole Panel action now that the console entry point is gone.
- hooks/useUIController.ts: consoleOpen / setConsoleOpen subscription
- hooks/useDesktopEvents.ts: "toggle-console" shortcut dispatcher
- state/slices/navigation.ts: consoleOpen field, setConsoleOpen,
  toggleConsole actions, and the two auto-open-on-navigate triggers
  that used to flip the drawer when jumping to a run

Removed main-process integration:
- main/desktop-shell-menu.ts: "Toggle Console" menu item + CmdOrCtrl+`
  accelerator
- main/desktop-shell-window.ts: onShortcut union type narrowed
- shared/types/events.ts: ShortcutEvent action union narrowed

Removed i18n keys (zh + en):
- app.hideConsole / app.showConsole
- console.title / console.noRuns / console.close
- common.openLog / common.noRunSelected / common.waitingForLog
- runs.openConsole

Log capture itself (logBufferRef in useCompanyController + run-log
events) is unchanged — the Runs section still displays it. Nothing
was moved to a "disabled but present" state; the feature is out of
the tree entirely. Typecheck and lint pass.
2026-04-17 20:32:34 -04:00
ZacharyZhang-NY 5547c29491 update 2026-04-17 14:03:56 -04:00
ZacharyZhang-NY 2ec77677cb fix(renderer): classify DesktopEvent types to stop full-refresh fallthrough (D-05)
All 14+ non-specially-handled events were pushing into the batcher with
entityKeyFromEvent returning null, which set hasDomainChanged = true and
triggered a full snapshot refresh on every agent-message, run-status, and
heartbeat-status -- defeating the granular patch machinery.

Per-type classification:
- run-status         -> granular run-updated (patchRun by runId)
- heartbeat-status   -> granular agent-updated (patchAgent by agentId)
- agent-message      -> granular task-updated (patchTask refetches comments)
- new-message, thread-wait-state-updated, domain-changed
                     -> full refresh, coalesced via 500ms batcher window
- automation-fired, recovery-needed
                     -> snapshot-irrelevant, skipped at event source

Widen batcher window from 50ms to 500ms so bursts coalesce into one reload.
Granular batches still flush at the same window cadence.
2026-04-16 21:58:32 -04:00
ZacharyZhang-NY 0119872db6 fix(renderer): use snapshot.currentCompanyId as single source of truth (D-03)
CompanySlice's standalone currentCompanyId field + setCurrentCompanyId action
were never written by any caller, so useDesktopEvents.ts read null and fell
through to full refresh for every entity event -- the granular patch
machinery was dead code.

- Remove currentCompanyId field + setCurrentCompanyId from CompanySlice
- refreshBadges reads from snapshot.currentCompanyId
- useDesktopEvents reads companyId from snapshot.currentCompanyId
- Update store unit test to seed snapshot instead of calling removed action
2026-04-16 21:56:40 -04:00
ZacharyZhang-NY 67c757f481 update 2026-04-04 12:03:50 -04:00