New area_breakdown() calc groups top-5 alarm sources by plant area for
a new Areas tab / AreaCard component. Disabled AlarmSimTick so it stops
generating data during dev.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Heatmap -> Journal drill-down (PrimeBAT only):
- clicking an Activations-by-hour/day cell jumps to the Journal filtered to
that recurring day-of-week + hour (new query.filterDow/filterHour session
props; same local-time bucketing as calc.heatmap)
- Journal shows a "Time filter: Thu 12:00-12:59" chip with an X to clear;
filter composes with existing filters and is included in CSV export
- getJournalPage clamps out-of-range pages when a filter shrinks the set
Layout:
- filter bar moved below the tab strip so the tabs no longer shift when the
bar hides on Overview (tab bar y verified pixel-stable across tabs)
- popup titles (AlarmDetail/EventDetail) auto-shrink their font to fit long
source paths on one line without colliding with the state/priority chips
Alarm health -> B (score ~88):
- alarmsim gains a MODE flag: "healthy" (default) generates ~12 activations/hr
with an 80/15/5 priority mix and no chatter/standing/fleeting/floods;
"chaos" restores the original stress profile
- SimHarness gains a SimReset one-shot timer (disabled) that clears all sim
tags; probe P3 reports health-grade ground truth for the 8h window
- Dashboard onStartup now re-anchors relative range presets (4h/8h/24h/7d)
to now on session start - fixes stale Designer-baked startMs/endMs pinning
every new session to an old window
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Data & simulation:
- simulation_tags.json: re-prioritize 10 tags to Medium so all four
priorities appear in live data (backfilled journal history to match)
- SimHarness probe P2: ack-user/includeData ground truth + filtered-bundle
verification against the live journal
Data layer (PrimeControls.calc/alarms):
- filters now drive every metric: queryStatus rows (Active Now/Unacked/
Standing) filtered via calc.apply_status_filters; event_count counts only
filtered instances (per-instance n_events); dropdown options enumerate
unfiltered data so choices never collapse
- build_bundle refactored into _assemble(); when filters are active an
unfiltered mirror is attached as bundle.overview - the Overview tab stays
a plant-wide summary while all other consumers bind filtered sections
- _fetch_journal now honors includeData (required for ackUserName; without
it ack attribution is always None); enabled for journal rows + source
detail so Top Ack Users and the Ack By column populate
FilterBar/Dashboard:
- root-cause fix: bidirectional bindings never wrote dropdown selections
back to session props, so filters silently did nothing; Apply now pulls
values directly from the sibling controls, Clear resets both
- multi-select dropdowns cap at 280px and wrap chips; filter bar row is
auto-height so wrapped chips push tabs down instead of overlapping
- filter bar hidden on the Overview tab (not applicable there)
UI scaling:
- Header: Prime logo added; KpiCard compacted to fit the 71px KPI row
(basis-95% overflow fix, chip hugs text, embeds clipped) - no scrollbars
- Overview timeline: thinned x labels (minDistance 140), labels anchored
below the axis, smaller legend markers
- Bad Actors focus chip shows the full source string with the clear X
- popup repeaters (Daily Activity, ScoreBars) no longer overflow
(useDefaultViewWidth/Height off, taller strip); 5px table cell padding
Tooling/tests:
- lint_project.py: accept propConfig params.* as param declarations
(Designer saves strip null params entries)
- tests: 31 -> 34 (status-filter semantics, overview mirror, filtered
event counts)
- .gitignore: runtime churn (valueStore.idb, local-system-properties,
migration logs, thumbnails, .schemas)
New project: AlarmAnalysis - submission copy of PrimeBAT with client-visible
Prime Controls branding removed (logo, subtitle, project title, shift report
heading); PrimeControls organizational namespaces retained per spec.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Built via parallel Workflow (5 builders + adversarial verifiers), then
live-rendered and fixed in a headless browser against the running gateway.
Tabs (PrimeControls/Tabs/*):
- Overview: priority cards, KPI status row, alarm-rate timeline, insights, top-5
- Analysis: hour x day heatmap, priority donut vs ISA 80/15/5, MTTA/MTTR, floods
- BadActors: chattering/standing/fleeting tables, focus chip, AlarmDetail wiring
- Journal: paginated getJournalPage table, CSV export, EventDetail wiring
Popups (PrimeControls/Popups/*): HealthScore, ShiftReport, AlarmDetail, EventDetail
Chart fixes (verified rendering in-browser):
- Overview timeline: seeded dataSources.rate, switched to static fills, split
flood bins into their own red stacked series (per-point deriveFieldsFromData
fill was crashing render with React.cloneElement null).
- BadActors: removed the dual-axis Pareto XY chart (scaling was unusable);
replaced with a ranked "Top Sources" table (share-of-total progress bar +
cumulative %). Same insight, no axis scaling to break.
Structural / hygiene:
- Relocated Header + FilterBar from Dashboard/ to Shell/ and updated the two
embed paths. A Perspective view cannot resolve sub-views nested inside another
view's folder, so both were rendering as "view does not exist" placeholders.
- Set persistent:false on all view input params. persistent:true caused the
gateway to bake the live bundle (with sim tag paths) into Tabs/Analysis on
render; nulled that baked data and reset the session query range to 0.
lint_project.py: 0 failures / 0 warnings.
Verified in-browser: Overview, BadActors. NOT yet live-verified: Analysis,
Journal, and the four popups (schema-verified only). Header content is next
phase (renders now, but a benign cloneElement console warning remains).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>