Skip to content

Phase 1040: Companion Notification Center — acknowledgeable inbox in the Event Viewer#180

Merged
HanSur94 merged 20 commits into
mainfrom
claude/sad-dubinsky-806c5e
Jun 2, 2026
Merged

Phase 1040: Companion Notification Center — acknowledgeable inbox in the Event Viewer#180
HanSur94 merged 20 commits into
mainfrom
claude/sad-dubinsky-806c5e

Conversation

@HanSur94
Copy link
Copy Markdown
Owner

@HanSur94 HanSur94 commented Jun 2, 2026

Summary

Adds an acknowledgeable notification inbox over the existing EventStore, surfaced in the Event Viewer as a horizontally-resizable right panel, with a toolbar bell on FastSenseCompanion (unacked count + highest-severity color) that opens the viewer. Dismiss == shared, ISA-18.2-audited EventStore.acknowledgeEvent. No new timer (piggybacks the existing live/redraw ticks).

Placement note: the inbox was originally built as a 4th column in the main companion; during the human-verify checkpoint the placement was redirected into the Event Viewer (resizable right panel). The 4th-column integration was cleanly reverted; the bell remains as an indicator that opens the viewer.

What's included

  • NotificationCenterPane (new, host-agnostic): unacked filter → newest-first → diff-by-Id → render; per-item Ack / Ack-with-comment / Acknowledge-all (unknownEventId race = no-op); stale-on-read guard; empty state; detach/re-dock; 7 pure static helpers.
  • CompanionEventViewer: [1 4] root grid hosting the pane (col 4) with a draggable col-3 divider driving a public NotifPaneWidth setter; chained WindowButton{Down,Motion,Up}Fcn preserves the Gantt crosshair (mirrors TimeRangeSelector); refresh off the redraw/auto-tick; pop-out window + close teardown.
  • FastSenseCompanion: toolbar bell at col 8 (gear → col 10), disabled with no EventStore, badge updated on construction / onLiveTick_ / applyTheme; bell click opens the Event Viewer.
  • StubEventStore test double.

Tests

  • tests/test_notification_center_pane.m (flat) — 18/18
  • tests/suite/TestNotificationCenterPane.m — 12/12
  • tests/suite/TestCompanionEventViewer.m — 57/57 (incl. 4 new notif tests + updated [1 4] layout test)
  • tests/suite/TestFastSenseCompanion.m — all bell/integration tests pass
  • MISS_HIT (mh_style/mh_lint) clean on all touched files; Code Analyzer clean on new code
  • Human-verified on the industrial-plant demo (placement, divider-drag resize, ack flow, bell-opens-viewer)

Known pre-existing CI caveat (NOT from this phase)

TestFastSenseCompanion/testADHOC05_noOrphanTimersAfterPlotAndClose and testPerTagModeSpawnsNFigures fail verifyEmpty(timerfindall...) — 2 lingering singleShot DashboardEngine render timers under headless MATLAB R2025b. Confirmed identical on the pre-1040 (bell-less) FastSenseCompanion.m, so they are not caused by this phase.

🤖 Generated with Claude Code

HanSur94 and others added 20 commits June 2, 2026 09:18
4 plans across 4 waves (test foundation -> pane -> Companion integration -> tests+verify).
Derives must_haves from the phase goal + 1040-CONTEXT.md locked decisions (no REQ-IDs mapped).
Populates the VALIDATION.md per-task map and updates the ROADMAP phase block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Straggler planning artifacts not captured by the researcher/planner
auto-commits: phase CONTEXT (approved in-session design), the approved
UI-SPEC design contract, and the STATE.md roadmap-evolution note for
Phase 1040 (Companion Notification Center).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fake EventStore handle for NotificationCenterPane tests
- getEvents / numEvents / acknowledgeEvent mirror the real store
- ThrowOnGet_ / ThrowOnAck_ switches drive stale + ack-race paths
- acknowledgeEvent records ids and mutates the matching Event AckedAt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- classdef shell mirroring EventsLogPane (events block, property block)
- 7 pure helpers: filterUnacked_ (empty/NaN AckedAt), sortNewestFirst_,
  maxSeverity_, idsOf_, diffIds_ (order-insensitive), badgeText_, badgeColor_
- No UI yet — attach/refresh/ack lifecycle lands in Plan 02
- Code Analyzer + MISS_HIT clean

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 18 headless assertions: StubEventStore round-trip + ack-race throw,
  filterUnacked_ (incl. NaN-as-unacked), sortNewestFirst_, maxSeverity_,
  idsOf_, order-insensitive diffIds_, badgeText_, badgeColor_ theme mapping
- Uses the real 6-arg Event constructor (planning docs' 4-arg form does not
  construct — direction is required + validated)
- All 18 tests pass; MISS_HIT clean; no UI primitives instantiated

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- StubEventStore + NotificationCenterPane pure-logic core + flat test (18/18 green)
- SUMMARY records the Event 6-arg constructor correction (carries to Plans 02/04)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…fresh/ack)

- attach/detach/applyTheme: [3 1] root (header [1 6] + bulk button + inbox
  uitable), filter selection preserved across detach/reattach
- refresh(eventStore): unacked filter -> diff-by-Id -> newest-first -> render,
  capped at 200; read error keeps last-good + (stale) marker, never uialert
- per-item Ack / Ack-with-comment / "Acknowledge all visible"; EventStore:
  unknownEventId race -> silent no-op; post-ack save() (non-fatal on failure)
- empty-state 'No unacknowledged events'; LIVE tag on open events; no drawnow
- Rule 3 fix: uitable property is CellSelectionCallback, not the planning docs'
  CellSelectionChangedFcn (matches EventViewer.m)
- row-click -> Event Viewer is guarded best-effort (openEventViewer_ is private
  on FastSenseCompanion today)
- Code Analyzer + MISS_HIT clean; attach/detach smoke passes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- lifecycle, detach/reattach state preservation, unacked filter + newest-first,
  diff-no-flicker, ack->removal, ack-race no-op, stale-on-read-error, severity
  filter, empty state, applyTheme, DetachRequested
- adds Hidden test seams to NotificationCenterPane (lastGoodCount_,
  lastIdsSnapshot_, lastUpdatedText_, numVisibleRows_, setSeverityFilterForTest_,
  ackForTest_, tableDataForTest_) per the Phase 1028 pattern
- StubEventStore gains getEventStore()->self + no-op save() so it doubles as
  the Companion's store resolver in ack tests
- 12/12 green; Plan 01 flat test still 18/18; MISS_HIT clean

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Full NotificationCenterPane inbox + 12-test suite (all green)
- SUMMARY records the CellSelectionCallback fix + best-effort row->viewer

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ell + 4th column)

- root grid [3 3]->[3 4] (col 4 hidden at 0); toolbar [1 9]->[1 10]; bell at
  col 8 (gear shifted 9->10); hNotifPanel_ at Row 2 Col 4
- bell disabled with no EventStore (mirrors hEventsBtn_), bellGlyph_ ASCII
  fallback for headless/Windows
- NotifPane_ instantiated + attached (Visible=off, width 0); DetachRequested
  listener registered in build + setProject; close() teardown
- toggleNotificationCenter_ (public) shows/hides col 4 with one drawnow;
  setNotifDetached_ pops out to a 420x600 uifigure + re-inlines; updateBellBadge_
  reflects unacked count + max-severity color (read-error tolerant)
- applyTheme propagates to the pane + recolors the badge
- Hidden seams: getRootColumnWidthForTest_, onLiveTickForTest_, notifPaneForTest_
- no NEW Code Analyzer issues (15 pre-existing, confirmed against HEAD); MISS_HIT
  clean; Task 1 + Task 2 smokes pass

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- inserted after EventsLogPane.setLastUpdated, before the cluster block
- guarded (only when pane attached) + own try/catch so it never crashes the
  live timer; no drawnow added here (pane.refresh stays flicker-free)
- no new timer — piggybacks the existing LiveTimer_/onLiveTick_ loop
- Task 3 smoke: appending a sev-3 then sev-2 event and ticking moves the badge 1 -> 2

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Bell + collapsible 4th column + onLiveTick_ refresh wired into FastSenseCompanion
- SUMMARY records the public-toggle fix + confirmation that the 2 orphan-timer
  test failures are pre-existing/environmental (identical on pre-1040 code)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… tests

- testToolbarGearMovedToColumn8 now asserts col 10 (name preserved per 260526-tcf);
  testToolbarHasWikiButton stays col 7
- 9 new tests: bell at col 8, 4-col grid, toggle 320<->0, enable/disable by store,
  badge count + decrement on ack, sev-3 StatusAlarmColor badge, onLiveTick refresh,
  detach -> 'Notification Center — FastSenseCompanion' window + close teardown
- onLiveTickForTest_ now forces a tick (save/restore IsLive) so badge tests are
  deterministic without starting a real timer
- 11/11 (9 new + 2 toolbar) green in a clean session; MISS_HIT clean; no new
  Code Analyzer issues

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…izable right panel)

Per user feedback at the human-verify checkpoint: the acknowledgeable inbox
belongs in the Event Viewer, not as a 4th column in the main companion.

FastSenseCompanion (revert Plan 03's 4th-column integration, keep the bell):
- root grid back to [3 3]; toolbar/log panel spans back to [1 3]
- removed hNotifPanel_/NotifPane_/hDetachedNotifFig_, toggleNotificationCenter_,
  setNotifDetached_, the onLiveTick pane refresh, and the column test seams
- bell stays at toolbar col 8 (gear col 10) as an unacked-count + severity
  indicator; its click now opens the Event Viewer (openEventViewer_)
- updateBellBadge_ still runs on construction, onLiveTick_, and applyTheme

CompanionEventViewer (host the pane + draggable horizontal resize):
- root grid [1 2] -> [1 4]: catalog | content | divider | notification panel
- NotificationCenterPane attached in col 4 (setCompanion -> the companion so
  acks resolve the store); refreshed off the viewer's redraw/auto-tick
- public NotifPaneWidth setter resizes col 4; a thin col-3 divider drags it via
  chained WindowButton{Down,Motion,Up}Fcn (preserves the Gantt crosshair, mirrors
  TimeRangeSelector's save/restore pattern)
- DetachRequested pops the pane to its own window + re-inlines; close() teardown
- test seams: notifPaneForTest_, rootColumnWidthForTest_

MISS_HIT clean; only new Code Analyzer warning mirrors the accepted LeftPaneWidth
setter pattern. Integration smoke passes (bell opens viewer, pane lists events,
NotifPaneWidth resizes the column).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TestFastSenseCompanion (companion side — bell only):
- replaced testRootGridHasFourColumns + testBellTogglesFourthColumn with
  testBellOpensEventViewer (bell click -> getEventViewerForTest_ non-empty)
- dropped the removed toggleNotificationCenter_ calls from the badge tests
- testOnLiveTickRefreshesNotifPane -> testOnLiveTickUpdatesBellBadge
- moved the detach test to the viewer suite; kept bell col 8 / enable-disable /
  badge count + severity color

TestCompanionEventViewer (viewer side — hosted inbox):
- testNotifPaneHostedInViewer (pane attached + lists 4 unacked)
- testNotifRootGridHasFourColumns (catalog|content|divider|inbox; inbox 320px)
- testNotifPaneWidthResizesColumn (setter resizes col 4; <120 rejected)
- testNotifPaneDetachReinline ('Notification Center — Event Viewer' window)

13/13 (9 companion + 4 viewer) green in a clean session; MISS_HIT clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… column

testRootLayoutIs1x2WithLeftAndRightColumns -> testRootLayoutIs1x4WithNotificationColumn:
asserts the [catalog | content | divider | inbox] grid (4 cols; left 260, inbox 320).
Full TestCompanionEventViewer green (57/57).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r pivot)

- toolbar assertions updated; notification tests retargeted to the Event Viewer
- SUMMARY documents the human-verify pivot (inbox -> Event Viewer resizable panel)
- human-approved; phase suites green (2 pre-existing env flakes only)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- VERIFICATION.md: goal achieved (acknowledgeable inbox + bell), placement pivoted
  to the Event Viewer per user; human-approved; phase suites green
- ROADMAP/STATE marked complete (1040 is the last phase in the milestone line)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Current State notes the Companion notification center (Event Viewer right panel + bell)
- footer bumped to 2026-06-02

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@HanSur94 HanSur94 merged commit 2a191c0 into main Jun 2, 2026
12 checks passed
@HanSur94 HanSur94 deleted the claude/sad-dubinsky-806c5e branch June 2, 2026 14:05
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

HanSur94 added a commit that referenced this pull request Jun 2, 2026
PR #180 (Phase 1040: Companion Notification Center) added a notification
bell to the FastSenseCompanion toolbar, growing it from a 1x9 to a 1x10
grid: the bell was inserted at col 8, pushing the flex spacer 8->9 and the
gear 9->10 (all documented in FastSenseCompanion.m). #180 updated
TestFastSenseCompanion and TestCompanionEventViewer but missed
TestFastSenseCompanionPlantLogToolbar, whose findToolbarGrid_ still matched
a 9-column grid and whose assertions still expected the gear at col 9. The
grid was never found (verifyNotEmpty failed) and the gear-column check
failed, turning MATLAB Tests (E-I) red on main and on every PR that merges
with main.

Updates the test to the shipped 1x10 layout
{110,110,110,130,70,90,70,70,'1x',36}: col 8 = bell (70), col 9 = flex
spacer, col 10 = gear (36).

Test-only change matching the intentional, self-consistent implementation.
Verified 11/11 pass in MATLAB R2020b+ (the two previously-failing methods
testToolbarGridIs1x5 + testSettingsButtonMovedToCol5 now green); mlint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
HanSur94 added a commit that referenced this pull request Jun 2, 2026
Octave Tests: make NotificationCenterPane.m Octave-loadable (drop logical type-constraint, Event.empty -> [], replace object-array comma-list/arrayfun with explicit loops). MATLAB Tests (E-I): update TestFastSenseCompanionPlantLogToolbar to the shipped 1x10 toolbar layout after the Phase 1040 bell. Test-only + compat; verified 18/18 in Octave+MATLAB and 11/11 toolbar in MATLAB.
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