|
| 1 | +# Scenario Workflow Translation Plan |
| 2 | + |
| 3 | +This document is the guiding plan for adding BuildingSync scenario workflow translation to BOSS. It is intended to be merged first, then used as the source of truth for a sequence of focused implementation PRs. |
| 4 | + |
| 5 | +## Goal |
| 6 | + |
| 7 | +Add first-class support for translating BuildingSync `PackageOfMeasures` scenarios into OpenStudio workflows and running those workflows alongside the baseline workflow generated by BOSS today. |
| 8 | + |
| 9 | +The first functional release will: |
| 10 | + |
| 11 | +- Discover BuildingSync package scenarios from `Reports/Report/Scenarios/Scenario/ScenarioType/PackageOfMeasures`. |
| 12 | +- Resolve each package's `MeasureID` references against `Facilities/Facility/Measures/Measure`. |
| 13 | +- Map supported BuildingSync measures to OpenStudio measure steps through a BOSS-owned JSON mapping file. |
| 14 | +- Write the existing baseline workflow plus one scenario workflow for each package scenario with at least one mapped measure. |
| 15 | +- Run baseline and scenario workflows through `OpenStudio::Extension::Runner`. |
| 16 | +- Warn and skip unmapped measures without failing the whole translation. |
| 17 | + |
| 18 | +## Non-Goals |
| 19 | + |
| 20 | +The first release will not: |
| 21 | + |
| 22 | +- Write simulated OpenStudio results back into BuildingSync `ResourceUses`, `AllResourceTotals`, or final XML. |
| 23 | +- Add full multi-facility or multi-site selection beyond the current BOSS assumptions. |
| 24 | +- Dynamically introspect every OpenStudio measure argument. |
| 25 | +- Treat reported BuildingSync savings or costs as simulation inputs unless a mapping explicitly defines that behavior. |
| 26 | +- Add user-supplied mapping files as a required feature. |
| 27 | + |
| 28 | +## Current BOSS Anchors |
| 29 | + |
| 30 | +- Baseline OSW writing starts in `BOSS::Boss.write_baseline_osw` in `lib/BOSS/boss.rb`. |
| 31 | +- Baseline execution starts in `BOSS::Boss.run_baseline_osw` in `lib/BOSS/boss.rb`. |
| 32 | +- BuildingSync XML parsing is centralized in `BOSS::BuildingSyncReader` in `lib/BOSS/buildingsync_reader/buildingsync_reader.rb`. |
| 33 | +- Baseline OpenStudio steps are assembled in `lib/BOSS/osw_arg_populator.rb`. |
| 34 | +- The CLI is Thor-based in `lib/boss_cli.rb`. |
| 35 | +- Existing baseline integration coverage is in `spec/tests/integration/write_and_run_osws_spec.rb`. |
| 36 | + |
| 37 | +## BuildingSync Data Model |
| 38 | + |
| 39 | +Scenario translation should use the first facility supported by BOSS today. |
| 40 | + |
| 41 | +Scenario source: |
| 42 | + |
| 43 | +```text |
| 44 | +BuildingSync/Facilities/Facility/Reports/Report/Scenarios/Scenario |
| 45 | +``` |
| 46 | + |
| 47 | +Package source inside a scenario: |
| 48 | + |
| 49 | +```text |
| 50 | +Scenario/ScenarioType/PackageOfMeasures |
| 51 | +``` |
| 52 | + |
| 53 | +Measure source: |
| 54 | + |
| 55 | +```text |
| 56 | +BuildingSync/Facilities/Facility/Measures/Measure |
| 57 | +``` |
| 58 | + |
| 59 | +Each package scenario should capture at least: |
| 60 | + |
| 61 | +- Scenario ID |
| 62 | +- Scenario name |
| 63 | +- Temporal status |
| 64 | +- Source report ID |
| 65 | +- Package ID |
| 66 | +- Reference case ID, when present |
| 67 | +- Package `MeasureID` IDrefs |
| 68 | +- Linked premises IDrefs, when present |
| 69 | + |
| 70 | +Each measure should capture at least: |
| 71 | + |
| 72 | +- Measure ID |
| 73 | +- `SystemCategoryAffected` |
| 74 | +- Technology category element name |
| 75 | +- `MeasureName` |
| 76 | +- `CustomMeasureName` |
| 77 | +- Linked premises IDrefs |
| 78 | +- Useful cost and savings metadata |
| 79 | +- Implementation status |
| 80 | + |
| 81 | +## Workflow Output Layout |
| 82 | + |
| 83 | +The existing baseline workflow output must remain unchanged: |
| 84 | + |
| 85 | +```text |
| 86 | +<output_path>/baseline/in.osw |
| 87 | +``` |
| 88 | + |
| 89 | +Scenario workflows should be written under a dedicated scenario directory: |
| 90 | + |
| 91 | +```text |
| 92 | +<output_path>/scenarios/<scenario_id>/in.osw |
| 93 | +``` |
| 94 | + |
| 95 | +Scenario workflows should deep-copy the baseline-generation workflow and append mapped retrofit measure steps. This makes every scenario OSW independently runnable and keeps scenario runs parallel-friendly. |
| 96 | + |
| 97 | +## Mapping Policy |
| 98 | + |
| 99 | +Mappings live in a new BOSS-owned JSON file, planned as: |
| 100 | + |
| 101 | +```text |
| 102 | +lib/BOSS/scenario_measure_map.json |
| 103 | +``` |
| 104 | + |
| 105 | +The mapper should prefer this lookup order: |
| 106 | + |
| 107 | +1. `SystemCategoryAffected` plus `MeasureName` |
| 108 | +2. Technology category element plus `MeasureName`, when `SystemCategoryAffected` is absent or unusable |
| 109 | + |
| 110 | +Initial mappings may use the legacy BuildingSync-gem `workflow_maker.json` as background information, but every included measure directory and argument must be verified against BOSS's current OpenStudio measure dependencies before merge. |
| 111 | + |
| 112 | +Conditional arguments should be data-driven. The first supported conditions should come from reader-derived context such as standards building type and principal HVAC/system type. Avoid per-measure Ruby `if`/`elsif` chains. |
| 113 | + |
| 114 | +## Warning Policy |
| 115 | + |
| 116 | +The implementation should return structured warnings and log them consistently. These conditions are warnings, not fatal translation errors: |
| 117 | + |
| 118 | +- Package has no `MeasureIDs`. |
| 119 | +- Package references an unknown measure ID. |
| 120 | +- Measure is missing `SystemCategoryAffected`. |
| 121 | +- Measure is missing a usable technology category. |
| 122 | +- Measure is missing `MeasureName`. |
| 123 | +- Measure category/name cannot be mapped to OpenStudio steps. |
| 124 | + |
| 125 | +If a scenario has at least one mapped measure, write its OSW and include warnings for skipped measures. If a scenario has zero mapped measures, skip that scenario OSW and report the reason clearly. |
| 126 | + |
| 127 | +## PR Sequence |
| 128 | + |
| 129 | +Each PR should be independently reviewable and should not implement later PR scope early unless it is necessary to keep the current PR coherent. |
| 130 | + |
| 131 | +| PR | Title | Scope | Depends On | Green Light | Red Light | |
| 132 | +| --- | --- | --- | --- | --- | --- | |
| 133 | +| 1 | Guiding plan doc | Add this repository plan document. | None | The doc directs PRs 2-18, names acceptance gates, and keeps first-release scope clear. | The doc leaves scenario selection, mapping ownership, warning behavior, or result writeback scope ambiguous. | |
| 134 | +| 2 | Scenario data model and discovery | Add reader-returned structures for first-facility report-level package scenarios. Extract scenario ID, name, temporal status, report ID, package ID, reference case ID, measure IDrefs, and linked premises. | PR 1 | Unit tests prove `building_151.xml` discovers baseline plus all package scenarios and existing reader behavior remains unchanged. | Parser assumes a hardcoded namespace, reads the wrong scenario path, or breaks existing reader tests. | |
| 135 | +| 3 | Facility measure index | Index facility measures by ID and extract category/name metadata plus linked premises, cost/savings fields, and implementation status. | PR 2 | Tests resolve package `MeasureID` references in `building_151.xml` to parsed measure metadata. | Unresolved refs are silently dropped or measures without `TechnologyCategories` crash parsing. | |
| 136 | +| 4 | Parser warning contract | Add structured warnings for missing IDs, unresolved refs, empty packages, missing names, missing categories, and packages with no usable measures. | PR 3 | Tests cover warning cases using `BuildingEQ-1.0.0.xml`, `Golden Test File.xml`, and no-measure fixtures. | Warnings only print to stdout or malformed package data aborts all discovery. | |
| 137 | +| 5 | Initial mapping JSON | Add `lib/BOSS/scenario_measure_map.json` with verified mappings for an initial supported set from `building_151.xml`. | PR 1 | Mapping JSON is valid, and every included entry has source category/name, target `measure_dir_name`, and arguments. | Legacy mappings are copied blindly without checking current OpenStudio measure dirs/args. | |
| 138 | +| 6 | Basic `ScenarioMeasureMapper` | Load JSON, normalize lookup keys, and map one parsed BuildingSync measure to OpenStudio step specs using `SystemCategoryAffected` plus `MeasureName`. | PRs 3, 5 | Mapper unit tests return expected steps and structured unmapped warnings. | Mapper mutates reader data, raises on unmapped measures, or hardcodes rules outside JSON. | |
| 139 | +| 7 | Technology category fallback | Add fallback lookup by technology category plus `MeasureName`. | PR 6 | Tests show fallback mapping works when `SystemCategoryAffected` is absent, while normal lookup priority is preserved. | Fallback changes normal category/name lookup behavior. | |
| 140 | +| 8 | Conditional mapping rules | Add data-driven conditional argument support for building type and principal HVAC/system context. | PR 6 | Tests prove conditions include and exclude arguments predictably. | Implementation becomes a per-measure Ruby condition chain. | |
| 141 | +| 9 | Structured mapping results | Return mapped steps, skipped measure IDs, warnings, and scenario-level write/skip status. | PRs 6-8 | Scenarios with mapped measures are writable; zero-mapped scenarios are skipped with clear warnings. | Callers must infer status from logs or empty arrays. | |
| 142 | +| 10 | Baseline OSW builder refactor | Refactor baseline writing into an internal baseline OSW builder while preserving public behavior. | PR 1 | Existing baseline integration tests pass and generated baseline OSW steps are unchanged. | Existing API, CLI, or baseline output changes unexpectedly. | |
| 143 | +| 11 | Scenario OSW writer API | Add an API that writes baseline plus scenario OSWs for package scenarios with at least one mapped measure. | PRs 9, 10 | Generation tests show expected directories and skipped-scenario reporting. | API writes OSWs for zero-mapped scenarios or disturbs baseline output. | |
| 144 | +| 12 | Scenario workflow step assembly | Deep-copy baseline OSW and append mapped retrofit steps in deterministic order. | PR 11 | OSW tests assert baseline steps plus expected mapped measure steps and arguments. | Scenario workflows omit baseline creation steps, mutate baseline OSW, or use nondeterministic step order. | |
| 145 | +| 13 | Generic OSW step helpers | Centralize mapped step appending and `OpenStudio::Extension.set_measure_argument` use. | PR 12 | Tests prove boolean, numeric, and string arguments serialize correctly. | Baseline populator methods are broadly rewritten or baseline JSON changes unintentionally. | |
| 146 | +| 14 | Generalized runner | Run `baseline/in.osw` and `scenarios/**/in.osw`; keep `run_baseline_osw` intact. | PR 11 | Tests or smoke run show the correct OSW list and baseline-only compatibility. | Runner includes skipped or missing OSWs, or removes baseline-only behavior. | |
| 147 | +| 15 | CLI command | Add a Thor command for baseline plus all package scenarios using existing output, weather, standard, and run options. | PRs 11, 14 | CLI help documents the command, write-only mode produces OSWs, and run mode invokes the generalized runner. | Existing `write_baseline_osw` or `run_osw` behavior changes unexpectedly. | |
| 148 | +| 16 | User documentation | Update README or user docs with scenario path, output layout, mapping policy, warning behavior, and CLI examples. | PR 15 | Docs match implemented command names/options and include one known fixture example. | Docs promise result writeback or unsupported mapping coverage. | |
| 149 | +| 17 | Mapper unit test expansion | Add focused tests for mapped, conditional, fallback, and unmapped cases. | PRs 5-9 | Mapper behavior is covered without relying only on slow integration tests. | Important mapper paths only have integration coverage. | |
| 150 | +| 18 | Scenario generation and integration coverage | Add OSW generation tests and focused write/run integration for a small known-translatable scenario subset. | PRs 11-15, 17 | Focused commands pass; supported scenario `out.osw` files show `completed_status: Success`. | Tests run every package scenario by default, are too slow for CI, or hide failures behind broad skips. | |
| 151 | + |
| 152 | +## Verification Commands |
| 153 | + |
| 154 | +Use the narrowest command that verifies the current PR. Broader commands should be run before merging larger integration PRs. |
| 155 | + |
| 156 | +```bash |
| 157 | +bundle exec rspec spec/tests/unit/buildingsync_reader_spec.rb |
| 158 | +bundle exec rspec spec/tests/unit/scenario_measure_mapper_spec.rb |
| 159 | +bundle exec rspec spec/tests/integration/write_and_run_osws_spec.rb |
| 160 | +bundle exec rake |
| 161 | +``` |
| 162 | + |
| 163 | +After the CLI PR, manually smoke-test the new command against these fixtures: |
| 164 | + |
| 165 | +- `spec/files/v2.7.0/building_151.xml` for package scenarios with known translatable measures. |
| 166 | +- `spec/files/v2.7.0/BuildingEQ-1.0.0.xml` for unmapped warning behavior. |
| 167 | +- `spec/files/v2.7.0/Golden Test File.xml` for package/reference edge cases. |
| 168 | + |
| 169 | +## Planned Files |
| 170 | + |
| 171 | +New files expected during the PR sequence: |
| 172 | + |
| 173 | +- `docs/scenario_workflow_translation_plan.md` |
| 174 | +- `lib/BOSS/scenario_measure_mapper.rb` |
| 175 | +- `lib/BOSS/scenario_measure_map.json` |
| 176 | +- `spec/tests/unit/scenario_measure_mapper_spec.rb` |
| 177 | + |
| 178 | +Existing files likely to change in later PRs: |
| 179 | + |
| 180 | +- `lib/BOSS/boss.rb` |
| 181 | +- `lib/BOSS/osw_arg_populator.rb` |
| 182 | +- `lib/BOSS/buildingsync_reader/buildingsync_reader.rb` |
| 183 | +- `lib/BOSS/constants.rb` |
| 184 | +- `lib/boss_cli.rb` |
| 185 | +- `spec/tests/unit/buildingsync_reader_spec.rb` |
| 186 | +- `spec/tests/integration/write_and_run_osws_spec.rb` |
| 187 | +- `README.md` |
| 188 | + |
| 189 | +## How Future Sessions Should Resume |
| 190 | + |
| 191 | +At the start of any future implementation session: |
| 192 | + |
| 193 | +1. Read this document first. |
| 194 | +2. Check the git state and recent commits to determine which PR steps have already landed. |
| 195 | +3. Start with the first PR in the sequence whose green-light criteria are not yet satisfied. |
| 196 | +4. Keep the change scoped to that PR unless a small supporting edit is necessary to make the PR coherent. |
| 197 | +5. Use the green-light criteria as the definition of done and the red-light criteria as merge blockers. |
| 198 | +6. Run the narrowest verification command that proves the current PR, then run broader compatibility checks before larger integration PRs. |
| 199 | +7. If implementation reveals a better order or a changed decision, update this plan in the same PR so later sessions inherit the new truth. |
| 200 | + |
| 201 | +## Review Checklist |
| 202 | + |
| 203 | +Before merging any implementation PR, confirm: |
| 204 | + |
| 205 | +- The PR implements only its planned scope or explicitly explains why a small dependency is included. |
| 206 | +- Existing baseline behavior remains compatible unless the PR explicitly updates it. |
| 207 | +- New behavior has focused tests or a documented manual verification path. |
| 208 | +- Warnings are structured and visible to callers. |
| 209 | +- Unmapped BuildingSync measures do not crash the whole translation. |
| 210 | +- The plan document remains accurate; update it in the same PR if a later implementation decision changes the roadmap. |
0 commit comments