v5.0 Multi-Machine Fleet — cross-machine sensor mapping, machine-scoped companion, comparison view#206
Open
HanSur94 wants to merge 114 commits into
Open
v5.0 Multi-Machine Fleet — cross-machine sensor mapping, machine-scoped companion, comparison view#206HanSur94 wants to merge 114 commits into
HanSur94 wants to merge 114 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pitfalls + summary); archive v4.0 research Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…; add CMP-UX research; archive v4.0 roadmap Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wave 0: TestCanonicalMapper.m (30 RED tests) + install.m Fleet path Wave 1: CanonicalMapper core (suggest/confidence/units) — CANON-01/02 Wave 2: override/persist/query API — CANON-03/04 Wave 3: standalone CanonicalMapEditor uifigure + checkpoint — CANON-05 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- W1 (1041-02 Task 1 verify): remove misleading conditional; state that only the two grep gates are GREEN after Task 1, all data-model tests (incl. testEditDistanceKnownPairs) stay RED until Task 2 builds suggest() - W2 (1041-01 + 1041-02): lock a single concrete LOW-confidence fixture (M01/M02 'abcdefghij' seed centroid + M03 'abzzzzzzzz' at sim 0.20 -> within-cluster LOW); specify seed-then-assign clustering with per-member confidence scored against the centroid; both plans now reference the identical keys + hand-confirmed sim math - W3 (1041-04): add phase-completion truth (all 30 tests green on MATLAB, 29 + 1 skip on Octave) to must_haves.truths Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plan 1041-01 Task 1. Adds `addpath(fullfile(root,'libs','Fleet'))` after the libs/Help entry (10 libs paths total) and creates libs/Fleet/.gitkeep so the new Fleet library directory is tracked. CanonicalMapper.m / CanonicalMapEditor.m land here in Plans 02-04. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plan 1041-01 Task 2. Full Nyquist test suite for CanonicalMapper: 30 methods across CANON-01..05 + the two Octave-safety/no-toolbox grep gates, with real assertion bodies (not stubs). Runs RED end-to-end (28 errored: CanonicalMapper not yet implemented; 2 grep gates skip cleanly via assumeTrue file-exists guard). Locked decisions carried forward to Plan 02: - Clustering is seed-then-assign with ATTACH_THRESHOLD_=0.15. The plan/checker said "no floor" but that is inconsistent: testConfidenceLowThreshold needs M03 (sim 0.20 to centroid) to attach as LOW, while testUnmappedReturnsUnresolved needs 'pressure' (hand-computed sim 0.10 to centroid 'temp_motor') to stay unmapped. A 0.15 floor separates them cleanly. - Per-member confidence is scored against the centroid (longest key, tie->lex-smallest). - Reconciled VALIDATION.md count: docs said "30" but enumerated 29; added a 30th test (testNormalizeCollapsesRepeats, CANON-01 normalize collapse/trim) and synced the map. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SUMMARY for Plan 1041-01 (Wave 0). Marks plan 01 complete in ROADMAP/STATE. 30-method RED suite + libs/Fleet path registration done. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… 02 task 1) Plan 1041-02 Task 1. Handle-class scaffold: Entries_ map, LastTagInfos_ seam, threshold constants (HIGH 0.90 / MEDIUM 0.60 / ATTACH 0.15), constructor, and the toolbox-free local helpers normalize_, editDistance_ (Wagner-Fischer), similarity_, plus assignConfidence_ (with a 1e-12 boundary tolerance). Octave-safe: no contains(, helper named editDistance_ so the no-toolbox grep gate stays green. Suite: the 2 grep gates now PASS (file exists, Octave-safe); the 14 CANON-01/02 data tests remain RED (suggest() not yet implemented) — intended Task 1 state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…2 task 2) Plan 1041-02 Task 2. Implements suggest(tagInfos): seed-then-assign clustering (single-link seeds at sim>=0.60; leftovers attach to nearest centroid at sim>=ATTACH_THRESHOLD_=0.15), per-member confidence scored against the centroid (0.90/0.60 inclusive), and the unit-mismatch flag + one-level confidence downgrade. Non-AUTO entries are preserved across re-suggest (override precedence seam for Plan 03). Result: 17 GREEN (6 CANON-01 incl. testNormalizeCollapsesRepeats, 5 confidence, 4 unit, 2 grep gates). testConfidenceLowThreshold passes via the LOCKED 3-member fixture (M03 attaches at sim 0.20 -> LOW). 13 RED remain (CANON-03/04/05 -> Plans 03/04). Test refinement: testSuggestNoMatches now asserts the CANON-01 "no cluster forms" fact only (dropped a premature m.unmapped() call that belongs to CANON-04/Plan 03). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SUMMARY for Plan 1041-02 (Wave 1). suggest/confidence/units done; CANON-01/02 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lan 03 task 1) Plan 1041-03 Task 1. CANON-03 precedence (override -> OVERRIDDEN/HIGH via upsertEntry_, confirm -> CONFIRMED; suggest already preserves non-AUTO) and CANON-04 query API (reviewPending = LOW-AUTO or unitMismatch; isResolvable = the Phase 1045 exclusion gate; unmapped = the unresolved tail, sorted). 26/30 GREEN; only persistence (3) + editor (1) remain RED. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…task 2)
Plan 1041-03 Task 2. CANON-03 persistence: toStruct (version 1 + flat entry cell),
static fromStruct (normalizeToCell_ handles jsondecode struct-array collapse), save
(per-entry jsonencode + strjoin + atomic movefile, EventStore pattern), static load.
normalizeToCell_ ported verbatim from Dashboard (no cross-dependency).
Fix vs LOCKED snippet: used read-modify-write for containers.Map buckets instead of
the invalid `map(key){end+1}=e` indexing.
Result: 29/30 GREEN (all CANON-01..04 + 2 grep gates). Only testEditorConstructs
RED -> Plan 04 (CanonicalMapEditor).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SUMMARY for Plan 1041-03 (Wave 2). CanonicalMapper data model complete; CANON-03/04 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… 04 tasks 1-2)
Plan 1041-04 Tasks 1+2. Standalone MATLAB-only review/edit window per UI-SPEC:
3-row uigridlayout (toolbar / 6-col read-only uitable / action row), theme via
CompanionTheme.get('dark') with a self-contained dark fallback + stripe pair.
Promote (gated by the Low-Confidence and Unit-Mismatch uiconfirm warnings) ->
mapper.confirm; Override (inputdlg) -> mapper.override; Save (uiputfile) ->
mapper.save; Show-Pending toggle; text filter; selection styling; unsaved-changes
close gate. All callbacks try/catch-guarded with non-blocking uialert.
Result: 30/30 TestCanonicalMapper GREEN on MATLAB (testEditorConstructs included).
No existing file modified (CanonicalMapper.m untouched). Octave skips the editor
smoke test cleanly via assumeTrue.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pproved) SUMMARY for Plan 1041-04 (Wave 3). Standalone editor done; CANON-05 satisfied; manual UAT approved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ilter (code review) Addresses code-review findings on the Phase 1041 source: - CR-01 (critical): reviewPending() gated the unitMismatch branch on nothing, so a CONFIRMED/OVERRIDDEN unit-mismatch entry stayed "pending" forever and disagreed with isResolvable(). Now an entry needs review only when NOT user-vouched AND (LOW or unitMismatch). Extended testReviewPendingExcludesGoodEntries with a confirmed-mismatch regression case (locks the fix). 30/30 still green. - WR-02: save() now wraps movefile in try/catch and deletes the orphaned .tmp on failure. - IN-02: CanonicalMapEditor filter haystack now includes machineId. Deferred (advisory, low-severity/edge/future-phase) — see SUMMARY follow-ups: WR-01 (same-machine duplicate keys in one cluster), WR-03 (two clusters normalizing to the same logicalId), WR-04 (LOW+mismatch shows only the mismatch dialog), IN-01/IN-03 (Listeners_ destructor / PENDING status are Phase 1044 seams). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gsd-verifier: status=passed, 5/5 must-haves. gsd-code-reviewer: 1 critical + 4 warn + 3 info (critical CR-01 + WR-02 + IN-02 fixed in 8f67297; remainder deferred as follow-ups). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…AT approved) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… plans, 3 waves) - Plan 01 (Wave 1): RED test scaffold (TestMachine/TestFleet + Octave flat) + Fleet-private normalizeToCell_ - Plan 02 (Wave 1): tagSource_ DI seam on Batch/LiveTagPipeline (FLEET-03; single-machine unchanged) - Plan 03 (Wave 2): Machine class — isolated catalog, duck-type API, ingest wrappers, EventStore, lazy load, timer-safe delete - Plan 04 (Wave 3): Fleet class — composable filters + JSON round-trip with embedded canonical map + fleetConfigVersion Covers FLEET-01..06; all critical invariants baked into acceptance criteria. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fleet auto-select branch assigned firstMachine.Dashboards to
Engines_/Dashboards with only an iscell wrap, skipping the
DashboardEngine validation every other intake path enforces.
Machine.Dashboards is a public, unvalidated property, so e.g.
m.Dashboards = {42} constructed a companion that failed later with an
un-namespaced error, while switching TO the same machine failed fast
via setProject. Reuse the exact Step-4 check and
FastSenseCompanion:invalidDashboard id for a uniform contract.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e (pre-existing)" This reverts commit 0e573d8.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ariant doc MachineSelectorPane:setThemeFailed namespace (was FastSenseCompanion:*); explicit ORDERING INVARIANT comment on the construction selectById-before- listener sequence. UI-REVIEW.md committed (57/60 advisory). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Compare-builder composition (fleet-only toolbar entry, per-machine row grid, quick-fill + per-row overrides, singleton modeless dialog); resolves the STATE-flagged openAdHocPlot injection decision (additive SeriesColors/SeriesLabels NV args); insertion-index stable colors; per-row confidence gate, consolidated open-time warnings, per-row promote (in-memory). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CompareBuilderDialog 600x480 modeless contract: 5-row outer grid, [1 6] machine rows w/ 4-state machine, quick-fill strip, Accent CTA, SeriesColors/SeriesLabels openAdHocPlot NV extension, locked copy + badge glyphs + ASCII fallbacks, R2020b caveats honored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sion, wave plan Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Key finding: CanonicalMapper.resolve() does not exist — Wave-1 prereq. Confidence gate lives in the dialog (Fleet.resolveLogical ungated). CMP-05 invariant via ResolvedTags_ cache-identity seam (no profiler). Toolbar [1 11]->[1 12] fleet-only shift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s, 4 waves) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…g verifies, Fleet.mapper accessor) - 1045-05: add CMP-03 to requirements + testCMP03_SkipGraceful (skip-alert + opens-with-remaining) - 1045-01/02/03/05: replace grep-only verifies with run_matlab test-runner invocations - 1045-01: add Fleet.mapper() public accessor (mirrors machineIds()); helper uses it instead of private Mapper_ - 1045-01: declare optional 3-arg buildCompareResolution_(fleet,logicalId,theme) in must_haves + Ttheme test - 1045-03: executor note on Task 2 (method-by-method stub-then-fill; do not split) - 1045-VALIDATION: nyquist_compliant true; add CMP-03 row + Fleet.mapper wave-0 entry Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ia mapper() accessor) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ution helpers Add the pure-logic foundation for cross-machine comparison: - CanonicalMapper.resolve(logicalId, machineId) -> entry struct | [] (the CMP-05 resolve-once seam; no side effects) - Fleet.mapper() public accessor mirroring machineIds() - buildCompareResolution_ Octave-safe per-machine row assembly with the LOW-confidence gate (invariant #4) + unit-mismatch detection; optional 3-arg theme path populates per-row colors - compareSeriesColor_ stable per-machine color by fleet insertion index - runCompareResolutionTests + tests/test_compare_resolution.m wrapper (7 tests green: resolve/mapper/states/unit-mismatch/theme-color/stability) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add additive optional 'SeriesColors' (cell of 1x3 RGB) and 'SeriesLabels' (cellstr) name-value args so the cross-machine comparison overlay can inject per-machine stable colors and machine-qualified legend labels (CMP-02): - inputParser parses the NV args; arity mismatch throws openAdHocPlot:seriesColorsMismatch BEFORE any figure spawns - the tags-with-data filter carries colors/labels through index-aligned so a dropped (no-data) tag drops its color/label too - plotOverlay_ draws each line with an explicit per-series Color (immune to ColorOrderIndex) and the supplied DisplayName when present; legacy 3-arg calls are byte-unchanged (ColorOrder auto-assign + tag-Name DisplayName) - runOpenAdHocPlotTests gains T-NV1 (legacy byte-compat), T-NV2 (color+label injection), T-NV3 (mismatch error, no figure) — 12/12 green via the flat wrapper Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… Open Phase 1045 Plan 03 (Wave 2): the headline cross-machine comparison builder. New libs/FastSenseCompanion/CompareBuilderDialog.m (classdef < handle): - Modeless 600x480 second uifigure on the CompanionSettingsDialog lifecycle (no WindowStyle='modal'; friend-class CompareBuilderDlg_ write-back on close, guarded so it stands alone before Plan 05 declares the property). - Quick-fill shared-sensor uidropdown populated from CanonicalMapper keys; selecting a logical sensor assembles per-machine rows via buildCompareResolution_ (3-arg form -> per-machine swatch colors). - Four-state row machine (auto / confirm_needed / override / none): LOW+AUTO renders 'confirm_needed' unchecked-by-default (invariant #4); missing sensors render 'none' (excluded). Color swatch + include checkbox + machine name + per-row override dropdown + action slot + status badge per UI-SPEC. - onOpenComparison_ resolves each included tag ONCE into ResolvedTags_ and calls openAdHocPlot with SeriesColors/SeriesLabels; consolidated non-blocking unit-mismatch + skipped-machine alerts (CMP-03); spawned overlay tracked via the companion. No CanonicalMapper call after the cache (invariant #5). - onRowAction_ is an inert bounds-guarded stub; Plan 04 fills Confirm/Promote. FastSenseCompanion.m: add public fleet() read accessor (mirrors Fleet.mapper()/machineIds()). Deviation from the plan's literal app.Fleet_ / app.trackOpenedFigure_ private-member reads: the dialog reaches the companion through PUBLIC seams (fleet() + the existing public trackOpenedFigure()), matching the CompanionSettingsDialog idiom (dialogs call only public app methods). No change to the private Fleet_ field or its internal readers. Verify (live MATLAB, worktree on path): check_matlab_code clean on both files; 10/10 smoke green — shell + invalidApp guard, four-state resolution {auto,confirm_needed,auto,none} with LOW+none unchecked, Open gating, resolve-once cache (2 tags), tracked overlay, and per-machine legends ('Press Line 3: Temp 1', 'Compressor A: Temp 3'); timers clean after teardown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ic-seam deviation) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1045 Plan 04 (Wave 3): layer the per-row CMP-06 actions + theme refresh
onto CompareBuilderDialog.
- onConfirm_(i) (public): include a confirm_needed (LOW/unreviewed) row —
state -> override, checkbox forced checked, action 'Confirm' -> 'Promote',
badge -> override, all in place (no full rebuild; Pitfall 6).
- onPromote_(i) (private, fired by the Promote button): R2020b-safe async
uiconfirm (DefaultOption=Cancel, CancelOption=Cancel); the override is applied
in the CloseFcn, never inline (Pitfall 4).
- onPromoteConfirmed_(i, event) (public): only on 'Promote', calls
CanonicalMapper.override via the public mapper() seam — IN-MEMORY ONLY, never
Fleet.save (deferred idea honored). Marks the row promoted: badge
'<check> promoted' (Accent), Promote button removed. Pitfall 3 accepted.
- onRowAction_ now dispatches by state (confirm_needed -> onConfirm_;
override-unpromoted -> onPromote_).
- applyTheme_(themeArg) (public): repaint figure + walker, then re-assert the
post-walk overrides — Open-button background by includedCount, per-row badge
FontColor by state, and per-machine swatch colors (series colors, NOT theme
tokens — preserved across a theme switch). Plan 05 wires the companion
theme-switch to call it.
onConfirm_/onPromoteConfirmed_/applyTheme_ are public underscore-suffixed seams
(matching the codebase's getOpenedFiguresForTest_/trackOpenedFigureForTest_
convention) so the Plan 05 class-suite drives CMP-06 + theme without the async
uiconfirm.
Verify (live MATLAB): check_matlab_code clean; 9/9 smoke green — Confirm ->
override+Promote button; onPromoteConfirmed_('Promote') -> mapper.resolve status
OVERRIDDEN + '✓ promoted' badge + button gone; Cancel no-op (M01 stays AUTO);
applyTheme_('light') repaints figure + auto-badge to light tokens, swatch color
persists. timers 0 after teardown. The only '.save(' in the file is the locked
instructional copy string ('Call Fleet.save() to persist.'), not a call.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mory override) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1045 Plan 05 (Wave 4): integration — make the comparison builder reachable and prove the phase invariants at the class-suite level. FastSenseCompanion.m: - Fleet-mode toolbar grows [1 11] -> [1 12]: a fleet-only 'Compare' button (Tag 'CompanionCompareBtn', 80 px) at col 9; the flex spacer/active-machine label/gear shift to cols 10/11/12. Legacy toolbar stays [1 10] byte-identical. - hCompareBtn_ (private) + CompareBuilderDlg_ friend property (SetAccess = ?CompareBuilderDialog). - openCompareBuilder_ focus-or-create singleton (mirrors openSettings); close() teardown deletes CompareBuilderDlg_ and resets it to []. - applyTheme propagates to an open builder (CompareBuilderDlg_.applyTheme_, guarded) — the builder owns its own uifigure, not walked by the companion. TestFastSenseCompanion.m: 7 CMP tests after the MACH block — testCompareButtonFleetOnly (12-col fleet / 10-col legacy, MACH-05 intact), testCompareBuilderSingleton, testCompareBuilderClosesWithCompanion, testOpenComparisonLaunchesOverlay, testCMP03_SkipGraceful, testCMP05_NoResolveInTick (cache handle-identity + canonical-map signature unchanged across one engine tick), testPromoteUpdatesMapper. Plus private fixtures (buildSharedSensorFleetApp_/buildLowConfidenceFleetApp_/ openBuilderAndSelect_/mapperSignature_) and a closeSpawnedFigs_ local helper that close()s overlays (fires engine stopLive; delete() would leak the timer). Verify (live MATLAB): TestFastSenseCompanion 91/0/0 (7 new CMP green; both pre-existing PerTag/ADHOC05 flakes green this run — above the 82/84 baseline); test_compare_resolution 7/7; check_matlab_code clean (pre-existing patterns only). Invariants: TagRegistry.register in libs/Fleet = 0; UI primitives in libs/Fleet only in the pre-existing CanonicalMapEditor.m; contains( in CanonicalMapper.m = 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ite) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…1/02 summaries - 1045-VERIFICATION.md: 5/5 success criteria VERIFIED + 5 critical invariants PASS. Evidence: TestFastSenseCompanion 91/0/0, test_compare_resolution 7/7, per-plan smokes 10/9/11, human-verify checkpoint approved. - Backfill 1045-01 / 1045-02 SUMMARYs (Wave-1 code committed earlier without summaries when the execution agent terminated early). - ROADMAP: Phase 1045 [x] complete; all 5 plan boxes checked. - STATE: completed_phases 4->5 (83%); position 1045 complete -> 1046 next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Independent code-review (1045-REVIEW.md, 0 blockers) + UI-review (1045-UI-REVIEW.md, 20/20 full conformance) of the Phase 1045 changes. Fixes for all 3 warnings + 3 cheap infos: - WR-01: onPromoteConfirmed_ bounds-checks the async-captured row index AND re-verifies the row is still an unpromoted 'override' before calling CanonicalMapper.override — a stale/out-of-range index can no longer promote the wrong machine's mapping (the headline data-correctness path). - WR-02: the Open-time unit-mismatch alert now prints the diverging TAG unit (via a shared tagUnits_ helper, also used by detectRowUnitMismatch_) instead of the canonical reference unit. - WR-03: the constructor throws CompareBuilderDialog:notFleetMode when app.fleet() is [] (legacy mode) instead of an opaque double-dispatch error. - IN-01: new CanonicalMapper.logicalIds() public accessor; the quick-fill dropdown uses it instead of poking the private Entries_ map. - IN-04: the '— none —' transition clears stale localUnits/localName/ confidence/status. - IN-05: a single isIncluded_(rs) predicate shared by includedCount_/ includedIndices_ so the count, Open set, and gating cannot drift. Verify (live MATLAB): check_matlab_code clean on both files; 10-check review-fix smoke green (legacy-guard, logicalIds, out-of-range + re-promote guards, valid promote -> OVERRIDDEN, none-clear, unit-mismatch override shows diverging 'K'). Full TestFastSenseCompanion.m re-run 90/91 — the lone failure is the pre-existing testADHOC05 orphan-debounce-timer flake (legacy-mode ad-hoc path that delete()s its spawned figure; exercises none of the changed code; green in the phase-verification run). All 7 CMP tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1046 (final milestone phase) discuss. Decisions locked (user deferred
both forks to me):
- Cloner lives as a DashboardSerializer static (keeps Fleet a pure data model;
Dashboard->Fleet direction preserved).
- Reverse canonical lookup -> new CanonicalMapper.logicalIdFor(machineId, key).
- Scope: programmatic API + tests (no companion UI hook this phase).
- DASH-04 graceful bind: a target-scoped resolver that never throws, collecting
unresolved bindings into a returned warnings struct array {sourceKey,
logicalId, reason}.
Verified against live code: the 1043 resolver seam reaches the 'tag' path
(FastSenseWidget.fromStruct:1501); clone reuses the whole DashboardEngine.load
path via a temp JSON + TagResolver (single + multi-page for free).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…IED)
- 1046-01 (Wave 1): CanonicalMapper.logicalIdFor reverse lookup + flat
Octave-safe test (test_canonical_reverse).
- 1046-02 (Wave 2): DashboardSerializer.cloneForMachine static — target-scoped
resolver (logicalIdFor -> resolve -> targetMachine.get) that never throws,
accumulating {sourceKey, logicalId, reason} warnings via a nested function;
reuses DashboardEngine.load via a temp JSON + 'TagResolver' (single +
multi-page); + TestFleetDashboardClone class-suite (rebind, DASH-04 warnings,
A->B round-trip, arg validation).
gsd-plan-checker: VERIFIED — all 3 success criteria + DASH-03/04 trace to tasks;
every foundation claim confirmed against live code (fromStruct:1524 resolver
seam, load JSON-only resolver path, saveJSON/widgetsToConfig exist, single-page
load populates Widgets:4421, headless Tag read, nested-fn warnings accumulation
correct); invariants preserved (no TagRegistry.register / contains / UI in Fleet;
no signature changes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nding) ROADMAP: Phase 1046 plan list (2 plans, 2 waves). STATE: position -> 1046 discussed+planned, execute pending; total_plans 21->23. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…phases User decision (2026-06-17): drop DASH-03/04 / Phase 1046 entirely rather than build a programmatic-only clone API with no concrete demand. The milestone's headline value (cross-machine comparison) shipped in Phase 1045. - REQUIREMENTS: DASH-03/04 struck + dropped note; coverage 24 delivered / 2 dropped. - ROADMAP: phases_total 6->5, phases_complete 5; Phase 1046 line + detail section marked DROPPED (original spec retained for the record); Overview note. - STATE: status complete, 5/5 phases, 100%; position = milestone delivered. - Removed .planning/phases/1046-* (CONTEXT + 2 checker-verified plans) — retained in git history (7e0477f, e080318); the 1043 resolver seam stays in place, so clone/remap is revivable (~1 hr) if a real need appears. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…2E holds Cross-phase milestone audit of v5.0 Multi-Machine Fleet (delivered at 5 phases; 1046 dropped out of scope): - Requirements 24/24 in-scope satisfied (3-source cross-ref: traceability × VERIFICATION × SUMMARY; no orphan; FLEET-02 isolation confirmed). - Phases 5/5 VERIFICATION: passed. - Integration 4/4 wirings WIRED (Fleet⇄Mapper, Companion⇄Fleet, CompareBuilder⇄Fleet+Mapper); E2E fleet→compare flow holds end-to-end; zero hard breaks (gsd-integration-checker). - Tech-debt (non-blocking, expected from the 1046 drop): 1043 TagResolver seam (DASH-01/02) + Fleet.resolveLogical (FLEET-06) built+tested but unconsumed by any shipped flow; nyquist PARTIAL on 1041-1044 (discovery-only); pre-existing PerTag/ADHOC05 timer flake. Report: .planning/v5.0-MILESTONE-AUDIT.md. Milestone shippable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v5.0 Multi-Machine Fleet
Lets a MATLAB engineer work with a fleet of near-identical machines: define machines with isolated tag catalogs, auto-map the same logical sensor across machines whose raw keys differ, scope the companion to one machine, and overlay the same sensor across machines — all toolbox-free, all through the existing
DashboardWidget/FastSensecontracts.Milestone delivered at 5 phases and audit-PASSED (see
.planning/v5.0-MILESTONE-AUDIT.md).Phases
libs/Fleet/CanonicalMapper.mtagSource_DI; machine tags never enter the globalTagRegistrylibs/Fleet/Machine.m,libs/Fleet/Fleet.mDashboardEngine.load(...,'TagResolver',fn)) + backward compatlibs/Dashboard/{DashboardEngine,DashboardSerializer,FastSenseWidget}.msetProjectwiring, active-machine indicator, clean timer lifecycle on switchlibs/FastSenseCompanion/{FastSenseCompanion,MachineSelectorPane}.mlibs/FastSenseCompanion/CompareBuilderDialog.mAudit summary (PASSED)
gsd-integration-checker), zero hard breaks.grep TagRegistry.register libs/Fleet/= 0; no UI in the Fleet data model; Octave-safelibs/Fleet/(nocontains).Scope decision — DASH-03/04 (clone/remap) dropped
Phase 1046 (dashboard clone/remap) was discussed, planned, and checker-verified, then deliberately dropped before execution: its only v5.0 value would have been a programmatic-only API (the companion UI hook was already deferred), and the headline value — cross-machine comparison — shipped in 1045. The enabling 1043 resolver seam stays in place; the 1046 plans live in git history if revived.
Non-blocking tech-debt (from the 1046 drop)
TagResolverseam (DASH-01/02) andFleet.resolveLogical(FLEET-06) are built + unit-tested but currently unconsumed by any shipped flow (their consumer was 1046). Dormant infrastructure, not defects.Reviewer note — where the code is
113 commits: 45 touch
libs//tests/(the code), 71 are.planning/docs (force-tracked by the GSD workflow in this repo). For code review, focus on thelibs/+tests/file diff. Tests:TestFastSenseCompanion91/91 (CMP block),test_compare_resolution7/7, plus each phase's suite.🤖 Generated with Claude Code