You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constructSelectionPath (client/src/interpreter/interpreter.ts:23) builds each selection key as `${optionPath}-${instancePath}`, where optionPath is the parameter's modelicaPath — i.e. the class where the parameter is declared. When two templates contain an instance at the same relative instancePath whose type is redeclared to different concrete classes, and the toggled parameter is declared in a common base class of those concrete classes, the optionPath (base class) and the instancePath are both identical, so the two templates produce the same key.
DownloadModal.getSequenceData() (client/src/components/modal/DownloadModal.tsx:50) then merges the per-config values under that one key into a single array, and mogrifier evaluates section toggles with any() over it — so a subsection is kept if any selected template uses the feature, and attributed to the wrong template's section in the generated document.
Root cause
The key uses the parameter's declaration site rather than a canonical Modelica path anchored at the concrete template. It should be, e.g.:
mogrifier cannot resolve a toggle to the correct template's value; any() is the only thing it can do with the merged array.
Any sequence template with per-template sections that reference an inherited parameter is affected.
Proposed fix: group by template, keep templates separate
Note
Canonical Modelica paths in the payload are still the correct long-term data model. But that's a major refactoring impacting config store keys, modifier/redeclare resolution, evaluatedValues, record redirection, and the display-option tree.
The proposed fix is scoped to the sequence generation, with minimum refactoring effort.
The declaration-site keys are unambiguous within a single config — inside one config, ctl.have_reqNeeCoo resolves to one value. The collision is created solely by merging configs of different templates into one dict. The interpreter, path construction, value resolution, and redeclare handling are not involved and do not need to change.
Collapse configs of the same template. Keep different templates in separate dicts.
Client — getSequenceData():groupBy(projectConfigs, "templatePath"), run the current per-config merge within each group, and emit:
The top-level Buildings.Templates.ZoneEquipment list (consumed by block-selector toggles) becomes the set of present group keys — same mechanism as today.
Server: passthrough; update SequenceData type in server/src/sequence/index.ts.
mogrifier — scope nested toggles per template block (single walk): when entering a template Heading 3 block kept by its block toggle, resolve the toggle's short IDs to templatePath(s) via mappings.csv ([EQUALS VAV RH] → RH → …VAVBoxReheat; [ANY VAV PFBCV SFBCV] → {…FanParallelConstant, …FanSeriesConstant}, whose group dicts are merged for that block). Evaluate that block's nested toggles against the selected group dict(s). Toggles outside any template block use a global union dict.
mappings.csv: unchanged — keys stay unambiguous within a template group.
Important
The refactoring must cover the case where the sequence document includes a single section covering multiple system types (e.g. parallel and series fan-powered box), which may be configured differently. To handle such a case, we need to implement specific merge logic.
constructSelectionPath(client/src/interpreter/interpreter.ts:23) builds each selection key as`${optionPath}-${instancePath}`, whereoptionPathis the parameter'smodelicaPath— i.e. the class where the parameter is declared. When two templates contain an instance at the same relativeinstancePathwhose type is redeclared to different concrete classes, and the toggled parameter is declared in a common base class of those concrete classes, theoptionPath(base class) and theinstancePathare both identical, so the two templates produce the same key.DownloadModal.getSequenceData()(client/src/components/modal/DownloadModal.tsx:50) then merges the per-config values under that one key into a single array, andmogrifierevaluates section toggles withany()over it — so a subsection is kept if any selected template uses the feature, and attributed to the wrong template's section in the generated document.Root cause
The key uses the parameter's declaration site rather than a canonical Modelica path anchored at the concrete template. It should be, e.g.:
which are distinct and carry the template context, instead of:
which discards it.
Impact
mogrifiercannot resolve a toggle to the correct template's value;any()is the only thing it can do with the merged array.Proposed fix: group by template, keep templates separate
Note
Canonical Modelica paths in the payload are still the correct long-term data model. But that's a major refactoring impacting config store keys, modifier/
redeclareresolution,evaluatedValues, record redirection, and the display-option tree.The proposed fix is scoped to the sequence generation, with minimum refactoring effort.
The declaration-site keys are unambiguous within a single config — inside one config,
ctl.have_reqNeeCooresolves to one value. The collision is created solely by merging configs of different templates into one dict. The interpreter, path construction, value resolution, andredeclarehandling are not involved and do not need to change.Collapse configs of the same template. Keep different templates in separate dicts.
Client —
getSequenceData():groupBy(projectConfigs, "templatePath"), run the current per-config merge within each group, and emit:The top-level
Buildings.Templates.ZoneEquipmentlist (consumed by block-selector toggles) becomes the set of present group keys — same mechanism as today.Server: passthrough; update
SequenceDatatype inserver/src/sequence/index.ts.mogrifier— scope nested toggles per template block (single walk): when entering a templateHeading 3block kept by its block toggle, resolve the toggle's short IDs totemplatePath(s) viamappings.csv([EQUALS VAV RH]→RH→…VAVBoxReheat;[ANY VAV PFBCV SFBCV]→{…FanParallelConstant, …FanSeriesConstant}, whose group dicts are merged for that block). Evaluate that block's nested toggles against the selected group dict(s). Toggles outside any template block use a global union dict.mappings.csv: unchanged — keys stay unambiguous within a template group.Important
The refactoring must cover the case where the sequence document includes a single section covering multiple system types (e.g. parallel and series fan-powered box), which may be configured differently. To handle such a case, we need to implement specific merge logic.