Skip to content

Commit f7712d4

Browse files
authored
Merge pull request #50 from HanSur94/claude/reverent-bohr
v2.0: Tag-Based Domain Model — unified Tag foundation
2 parents 2327c2a + 167bb1f commit f7712d4

325 files changed

Lines changed: 48354 additions & 11710 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.planning/PROJECT.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ Users can organize complex dashboards into navigable sections and pop out any wi
4141
### Active
4242

4343
- ✓ Dashboard performance optimization: theme caching, O(1) widget dispatch, single-pass live tick, in-place resize, visibility page switch — v1.0 Performance
44+
- ✓ Tag-based domain model: unified `Tag` foundation, `TagRegistry`, `MonitorTag` derived time-series, `CompositeTag` aggregation — v2.0
45+
- ✓ Events attached to tags with FastSense overlay rendering — v2.0
46+
47+
## Current State
48+
49+
**Shipped:** v2.0 Tag-Based Domain Model (2026-04-17)
50+
51+
The SensorThreshold subsystem has been fully rebooted on a unified `Tag` foundation. Legacy `Sensor`/`Threshold`/`StateChannel`/`CompositeThreshold` classes are deleted. All consumers (FastSenseWidget, dashboard widgets, EventDetection, LiveEventPipeline) operate through the Tag API (`addTag`, `getXY`, `valueAt`). Events bind to tags via `EventBinding` registry and render as toggleable round markers in FastSense.
52+
53+
**Vocabulary:** `SensorTag`, `StateTag`, `MonitorTag`, `CompositeTag`, `TagRegistry`, `EventBinding`. FastSense API: `addTag(t)`.
54+
55+
**Next milestone candidates:**
56+
- Asset hierarchy (Asset tree, templates, tag-to-asset binding, browse rollups)
57+
- Custom event GUI (click-drag region selection in FastSense → label dialog)
58+
- Calc tags / formula evaluator for arbitrary derived tags
59+
- Tri-state / continuous severity MonitorTag output
60+
- WebBridge parity for Tag API features
4461

4562
### Out of Scope
4663

@@ -95,6 +112,11 @@ Users can organize complex dashboards into navigable sections and pop out any wi
95112
| repositionPanels for onResize | In-place panel repositioning vs destroy+recreate; fallback to rerenderWidgets on missing handles | ✓ Good |
96113
| switchPage visibility toggle | Hide/show panels instead of full rerender; pre-allocate all page panels at render() | ✓ Good |
97114
| Single-pass onLiveTick with updateLiveTimeRangeFrom | One activePageWidgets() call, merged mark-dirty+refresh loop | ✓ Good |
115+
| v2.0 reboot under unified `Tag` root (Option 2) | No-users codebase; preserves design wins from 1001-1003 as concepts; cleanest end state vs. interface-shim approach (Option 3) | Pending v2.0 |
116+
| Vocabulary: `Tag` suffix on all primitives (`SensorTag`, `MonitorTag`, ...) | Trendminer-faithful; uniform mental model; `addTag()` API replaces `addSensor()` | Pending v2.0 |
117+
| Single `TagRegistry` (replaces `SensorRegistry` + `ThresholdRegistry`) | One namespace, one search surface; fewer parallel singletons | Pending v2.0 |
118+
| MonitorTag as full time-series signal (not current-state only) | Plottable, persistable, event-detectable; reuses existing infrastructure | Pending v2.0 |
119+
| Defer asset hierarchy (D), custom event GUI (F), calc tags (G) to later milestones | Ambitious tier (A+B+C+E) is shippable on its own; D/F/G are independent additions | Pending v2.0 |
98120

99121
## Evolution
100122

@@ -114,4 +136,4 @@ This document evolves at phase transitions and milestone boundaries.
114136
4. Update Context with current state
115137

116138
---
117-
*Last updated: 2026-04-04 after v1.0 performance optimization milestone*
139+
*Last updated: 2026-04-16 — v2.0 milestone (Tag-Based Domain Model) initialized*

.planning/ROADMAP.md

Lines changed: 215 additions & 1 deletion
Large diffs are not rendered by default.

.planning/STATE.md

Lines changed: 106 additions & 53 deletions
Large diffs are not rendered by default.

.planning/milestones/v2.0-REQUIREMENTS.md

Lines changed: 218 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Milestone v2.0: Tag-Based Domain Model
2+
3+
**Status:** ✅ SHIPPED 2026-04-17
4+
**Phases:** 1004-1011 (8 phases)
5+
**Total Plans:** 27
6+
**Commits:** 119
7+
**Files Changed:** 224 (13,799 insertions, 10,747 deletions — net +3,052 lines)
8+
**Timeline:** 2026-04-16 → 2026-04-17
9+
10+
## Overview
11+
12+
Reboot the SensorThreshold subsystem on a unified `Tag` foundation. Everything is a Tag — `Sensor`/`Threshold`/`StateChannel`/`CompositeThreshold` rewritten as Tag subclasses (`SensorTag`, `StateTag`, `MonitorTag`, `CompositeTag`). New primitives deliver derived time-series health signals. Events bind to tags and overlay in FastSense. Strangler-fig sequencing: parallel hierarchy phases 1004-1008, consumer migration phase 1009, event binding phase 1010, legacy deletion phase 1011.
13+
14+
## Key Accomplishments
15+
16+
1. **Unified Tag foundation**`Tag` abstract base class with `TagRegistry` singleton, two-phase JSON deserializer, label/metadata/criticality support. Proven Octave-safe throw-from-base pattern.
17+
2. **MonitorTag derived signals** — Lazy-by-default 0/1 binary time series from any parent Tag + condition function. Debounce (ISA-18.2 MinDuration), hysteresis (alarm-on/alarm-off), streaming `appendData` for live pipelines, opt-in disk persistence.
18+
3. **CompositeTag aggregation** — 7 modes (AND/OR/MAJORITY/COUNT/WORST/SEVERITY/USER_FN) via vectorized merge-sort streaming. Key-equality cycle detection. 0.125x output-size ratio at 8×100k children (Pitfall 3 gate).
19+
4. **Event↔Tag binding** — Many-to-many `EventBinding` registry replacing denormalized carrier strings. `Event.TagKeys` cell. `Tag.addManualEvent` convenience. FastSense `renderEventLayer_` draws toggleable round markers.
20+
5. **Full consumer migration** — Every widget (FastSenseWidget, MultiStatusWidget, IconCardWidget, EventTimelineWidget, SensorDetailPlot) + EventDetector + LiveEventPipeline migrated to Tag API. 0.3% tick overhead.
21+
6. **Clean legacy deletion** — 8 legacy classes + 13 private helpers + 37 legacy-only test files deleted. Golden integration test rewritten to Tag API with preserved assertion semantics. Net -3,995 lines in libs/.
22+
23+
## Phases
24+
25+
### Phase 1004: Tag Foundation + Golden Test
26+
**Goal**: Establish parallel Tag hierarchy and untouchable regression guard.
27+
**Plans**: 3 (Tag base + MockTag, TagRegistry + two-phase loader, Golden test + budget verification)
28+
**Key deliverables**: Tag.m (6 abstract-by-convention stubs), TagRegistry.m (CRUD + query + loadFromStructs), TestGoldenIntegration.m
29+
**Completed**: 2026-04-16
30+
31+
### Phase 1005: SensorTag + StateTag (data carriers)
32+
**Goal**: Port raw-data half of domain into Tag subclasses with polymorphic FastSense.addTag.
33+
**Plans**: 3 (SensorTag composition wrapper, StateTag ZOH valueAt, FastSense.addTag dispatcher)
34+
**Key deliverables**: SensorTag.m (HAS-A Sensor delegate), StateTag.m (ZOH), FastSense.addTag (getKind dispatch)
35+
**Completed**: 2026-04-16
36+
37+
### Phase 1006: MonitorTag (lazy, in-memory)
38+
**Goal**: First-class derived signal replacing Sensor.resolve() side-effect pipeline.
39+
**Plans**: 3 (Core lazy memoize + observer hook, Debounce + hysteresis + events, Integration + bench)
40+
**Key deliverables**: MonitorTag.m (500 SLOC), SensorTag/StateTag listener hooks, bench: 3.3x faster than legacy
41+
**Completed**: 2026-04-16
42+
43+
### Phase 1007: MonitorTag streaming + persistence
44+
**Goal**: Opt-in performance/persistence levers for live pipelines.
45+
**Plans**: 3 (appendData streaming, Persist + FastSenseDataStore monitors API, Bench)
46+
**Key deliverables**: appendData with boundary-state continuity, storeMonitor/loadMonitor/clearMonitor, bench: 11.1x speedup
47+
**Completed**: 2026-04-16
48+
49+
### Phase 1008: CompositeTag
50+
**Goal**: Aggregate MonitorTags/CompositeTags via merge-sort streaming with 7 aggregation modes.
51+
**Plans**: 3 (Core + addChild + cycle DFS, Merge-sort + ALIGN + 3-deep round-trip, Integration + bench)
52+
**Key deliverables**: CompositeTag.m (vectorized sort merge), valueAt fast-path, bench: 53ms at 8×100k
53+
**Completed**: 2026-04-16
54+
55+
### Phase 1009: Consumer migration (one widget at a time)
56+
**Goal**: Migrate every consumer to Tag API — one widget per commit, green CI each.
57+
**Plans**: 4 (FastSense layer, Dashboard widgets, EventDetection + LEP appendData wire-up, Bench)
58+
**Key deliverables**: 19 production files cleaned, LiveEventPipeline MonitorTargets, bench: 0.3% overhead
59+
**Completed**: 2026-04-17
60+
61+
### Phase 1010: Event ↔ Tag binding + FastSense overlay
62+
**Goal**: Replace denormalized Event carriers with EventBinding registry; render event markers.
63+
**Plans**: 3 (Event.TagKeys + EventBinding, Tag.addManualEvent + renderEventLayer_, Bench)
64+
**Key deliverables**: EventBinding.m singleton, Event.TagKeys/Severity/Category, FastSense renderEventLayer_
65+
**Completed**: 2026-04-17
66+
67+
### Phase 1011: Cleanup — collapse parallel hierarchy + delete legacy
68+
**Goal**: Delete 8 legacy classes, rewrite golden test, ship unified Tag-only domain.
69+
**Plans**: 5 (SensorTag inline + delete classes, Delete tests, Consumer branch removal, Example migration, Golden rewrite + grep audit)
70+
**Key deliverables**: 8 classes deleted, 37 test files deleted, golden rewritten, net -3,995 lines in libs/
71+
**Completed**: 2026-04-17
72+
73+
## Milestone Summary
74+
75+
### Key Decisions
76+
- Strangler-fig sequencing (parallel hierarchy → consumer migration → deletion)
77+
- Composition over inheritance for SensorTag (HAS-A Sensor delegate, later inlined)
78+
- Lazy-by-default MonitorTag (Pitfall 2 discipline)
79+
- Key-equality cycle detection (Octave SIGILL avoidance)
80+
- Vectorized sort-based merge for CompositeTag (pointer-loop too slow)
81+
- Event.TagKeys via EventBinding registry (no handle cross-references)
82+
- Separate renderEventLayer_ (no render-path pollution)
83+
84+
### Tech Debt (from audit)
85+
1. EventDetector.detect(tag, threshold) references deleted Threshold API — dead code
86+
2. DashboardSerializer .m export doesn't handle source.type='tag' — JSON works
87+
3. 93 MATLAB-only test refs to deleted Threshold class in 42 suite files
88+
89+
### Performance Gates (all passed)
90+
- Pitfall 3: CompositeTag 0.125x output ratio, 53ms compute
91+
- Pitfall 9 (Phase 1006): MonitorTag 3.3x faster than legacy Sensor.resolve
92+
- Pitfall 9 (Phase 1007): appendData 11.1x speedup vs full recompute
93+
- Pitfall 9 (Phase 1009): Consumer migration 0.3% tick overhead

0 commit comments

Comments
 (0)