Skip to content

BEMGen Implementation Roadmap

Status: Approved (D-030) · Date: 2026-09-30 · Owner: Cheng Xuan Li

Checkpoint 1: completion of S0–S4 (D-030).

Progress: 2026-10-01 · S0 Foundation complete (tag v0.0.1); next: S1. ADR-001 and ADR-004 ratify the tech stack and tolerances listed in this roadmap: C# 12 rather than the latest language version, no System.Collections.Immutable, minimum Rhino 8.19, relative area tolerance 1e-6, and the verify gate on Windows PowerShell 5.1 (powershell -NoProfile -ExecutionPolicy Bypass -File scripts/verify.ps1).

Progress: 2026-10-01 · S1 Program presets and equivalence engine complete (tag v0.1.0); next: S2. The example presets are illustrative (stair unconditioned), not DOE values; sourced presets remain open point 4 of §7.

Progress: 2026-10-01 · S2 End-to-end pipeline skeleton complete (tag v0.2.0); next: S3. Presets → LinearPlanGenerator → NoSimplification → Stack → neutral Convert2BEM (D-023) runs in Grasshopper with previews; explicit windows (one centered window per outdoor wall from the generator, D-039, D-026) and preset conditioning (stair unconditioned, D-038) appear in every report and preview; 94 core, 17 generator, and 9 integration tests pass on net8.0. Convert2BEM has no validation gate until S3.

Progress: 2026-10-01 · S3 Plan simplifiers and validation complete (tag v0.3.0); next: S4. Plan simplifiers Z1 semantic merge, Z2 perimeter/core (corner rule in ADR-008), and Z3 single zone per floor keep every window in place (D-039) and require full façade coverage (D-041); floor and building validation, with conditioned floor area reported (D-038) and ground, roof, and exposed floor area and building height enforced (D-045, D-046); the Convert2BEM validation gate with a recorded override; 104 core, 17 generator, and 38 integration tests pass on net8.0.

Progress: 2026-10-01 · S4 Floor aggregators complete (tag v0.4.0); Checkpoint 1 reached (S0–S4 complete, D-044); next: S5, S6, and S7. FloorAreaMultiplier (representative storeys at their true elevations, exposed storeys split off as × 1, D-045, D-046) and SingleZoneMerged (windows in place, façade coverage checked, slabs as internal mass) follow ADR-009; every simplifier × aggregator combination of the linear plan validates and converts; 104 core, 17 generator, and 63 integration tests pass on net8.0.

Progress: 2026-10-01 · S4.1 Grasshopper inputs, presets, and icons complete (tag v0.4.1); next: S5, S6, and S7. The Linear Plan Generator takes one preset per space type (Dwelling Unit, Corridor, Stair; LinearPlanPresets, mismatches are PresetSpaceTypeMismatch) from the new default preset components, which replace Example Residential Presets (D-061); generator, simplifier, and aggregator components have a Preview Location input (D-062); every component and parameter has an icon drawn by scripts/make_icons.py (D-063); all seven snapshots unchanged; 120 core, 19 generator, and 63 integration tests pass on net8.0.

Progress: 2026-10-01 · S4.2 Vertical aggregation methods, plan transform, and heat-transfer options complete (tag v0.4.2, local until the owner pushes it, D-075); next: S5, S6, and S7. Every floor aggregator designates floors and ceilings on the assembled stack (D-068) and warns about unsupported storeys (D-074); the aggregators are Stack, StackedFloorZoneMultiplier (formerly FloorAreaMultiplier), SingleZonePerFloorType (one zone per floor entry, behind the former Single Zone Merged component), and SingleZoneBuilding (formerly SingleZoneMerged, D-071), following ADR-013; Transform Plan rotates and moves a plan, and every simplifier and aggregator validates on rotated plans (D-070, D-076); Convert2BEM writes heat transfer between zones only when asked (D-069); existing buildings unchanged, two snapshots renamed with identical content; 136 core, 19 generator, and 163 integration tests pass on net8.0.

Progress: 2026-10-02 · S5 Centred windows on rebuilt walls complete (tag v0.5.0; main, v0.4.2, and v0.5.0 are pushed after the fresh-clone gate, D-080); next: S6 and S7. CentredWindows gives every outdoor wall rebuilt by Semantic Merge, Perimeter Core, Single Zone per Floor, Single Zone per Floor Type, and Single Zone Building one window centred by the generator's rule with the glazed area of the source windows it covers (D-079, ADR-012); glazing per wall, façade, orientation, and building and every validation report unchanged; new error GlazingExceedsWall; six snapshots changed in their window entries only; 142 core, 19 generator, and 187 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.1 Plan generation mechanism and bar typologies complete (tag v0.8.0, local until the owner pushes it, D-084); next: S6 and S8.2. ADR-006 fixes one PlanGenerator subclass per High-Density Housing family, with typed parameter and preset records and design defaults for all nine families; ADR-011 adds GeometryLimits (no window on an outdoor wall shorter than 1 m or for a window narrower or lower than 0.3 m, info WindowOmitted); LinearPlanGenerator checked as HDHM-TYP-009 and kept; new generators and components Stair Bay Bar (001), Stair Pair (008), Gallery Bar (002, gallery not modelled), and Terrace Row (006, one zone per plot and storey, D-085); every bar family validates with every simplifier and aggregator, also rotated and moved; existing snapshots byte-identical, four new; 152 core, 91 generator, and 319 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.2 Non-rectangular typologies without holes complete (tag v0.8.1, local until the owner pushes it, D-084); next: S6 and S8.3. New generators and components Point Plate (007, a square plate whose core has no outdoor wall), Winged Band (003, a comb), and Open Court (004, a U), their wings on the shared stair-bay layout; Semantic Merge unites its groups as tiles, the surface builder tests vertices on edges at their original positions, and unions of tiles keep the tiles' own vertices, which repairs rotated plans released up to v0.8.0 (D-088); Perimeter Core states its width precondition in PlanTooNarrow (D-087); every non-rectangular family validates with every simplifier and aggregator, also rotated and moved; existing snapshots byte-identical, three new; 154 core, 159 generator, and 474 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.3 Enclosed courtyard and footprints with holes complete (tag v0.8.2, local until the owner pushes it, D-084); next: S6 and S9. New generator and component Enclosed Court (005, four wings of stair bays around a court closed on all four sides), the first footprint with a hole; the surface builder requires every footprint edge, court edges included, to be covered by outdoor zone edges; Perimeter Core zones the court façades in their own zones P-Court-<Bin> around a ring core, with its width precondition on every wing (D-087); No Simplification, Semantic Merge, Single Zone per Floor, the four floor aggregators, and validation needed no change; every simplifier and aggregator validates the enclosed court, also rotated and moved; zone solids are outward-oriented and surfaces and windows face out of their zones in Convert2BEM, which repairs every plan released up to v0.8.1 (D-091); existing snapshots byte-identical, one new; 158 core, 181 generator, and 601 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.4 Non-residential programs, office plate and cafeteria complete (tag v0.8.3; main and the tag pushed after the fresh-clone gate, D-098); next: S8.5. The four-source records are pinned (v0.3.1-research, 7538ed3) and paraphrased in syn-typologies.md, and BEMGen documents use the SYN-TYP-* IDs (D-099); the study covers every program type (D-094) in the brief, spec, README, AGENTS.md, and roadmap; ADR-014 adds twelve non-residential space types (Core, Lobby, and Service reused), fifteen illustrative presets in ExampleNonResidentialPresets, their default preset components, and the department zoning of every new family (D-097); ADR-006 specifies all nine new families, the hub-and-arms families with at most four arms (D-100); new generators and components Office Plate (017, the first zone with a hole in a footprint without one, needing no pipeline change) and Cafeteria (016); existing snapshots byte-identical, two new; 193 core, 224 generator, and 704 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.5 Branching plans on a shared hub-and-arms layout complete (tag v0.8.4; main and the tag pushed after the fresh-clone gate, D-098); next: S8.6. HubArmsLayout lays out a square hub with up to four arms (D-100, D-102) for four new generators and components: Radial Lobes (010), Branching Mall (014, one mall zone through every branch), Care Hub (018), and Foyer Halls (019); Perimeter Core keeps the footprint's own vertices, which repairs short façades on rotated plans (ADR-008); existing snapshots byte-identical, four new; 193 core, 360 generator, and 1184 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.6 Operating suite and court clusters complete (tag v0.8.5; main and the tag pushed after the fresh-clone gate, D-098); next: S8.7. Two new generators and components: Operating Suite (015, theatre banks between alternating clean and dirty corridors beside the support rooms) and Court Cluster (011, stair-bay wings around a row of courts, the first footprint with several holes, which every step already handles; D-104); existing snapshots byte-identical, two new; 193 core, 427 generator, and 1385 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.7 Plans per storey and the stepped band complete (tag v0.8.6; main and the tag pushed after the fresh-clone gate, D-098); S8 is complete with 18 plan generators; next: S6. ADR-015 decides plans per storey (D-095, D-106): a MultiStoreyPlanGenerator returns one plan per storey, bottom-up, sharing every rule of PlanGenerator, and every simplifier and floor aggregator takes the storeys unchanged, the terraces designated on the assembled stack (D-068); new generator and component Stepped Band (012, a dwelling band stepping back storey by storey, with a Plan list); existing snapshots byte-identical, one new; 210 core, 463 generator, and 1485 integration tests pass on net8.0.

Progress: 2026-10-02 · S8.8 Storey previews, the any-program preset, and the preset panel complete (tag v0.8.7; pushing waits for the owner, D-108); next: S6. Floors of a storey plan previewed at the storey's height (StoreyElevation, ADR-015), the Any Program Preset parameter (24bc6a12-ad06-4c25-bc9d-4e8318b8744c) accepted on every preset input (ADR-014), and the panel 1 Program Presets (D-109); no GUID changed; existing snapshots byte-identical; 243 core, 518 generator, and 1518 integration tests pass on net8.0.

Progress: 2026-10-02 · S6 Convert2IDF complete (version 0.9.0, D-113; tagging and pushing wait for the owner); next: S9. An envelope preset shared by Convert2BEM and Convert2IDF, Lod.Export with the IDF writer (EnergyPlus 25.2, ADR-010), the Envelope Preset and Convert2IDF components, scripts/rhino-smoke/ and scripts/idd-check/; every converted IDF of the tests and of the Rhino run passes the IDD check; existing snapshots and icons byte-identical; 294 core, 518 generator, 475 export, and 1518 integration tests pass on net8.0.

Progress: 2026-10-02 · Process (D-111): from S6 on, stages are planned in a short design note, built once test-first on feature branches (independent parts in parallel), reviewed by a second agent, checked headless in Rhino from scripts/rhino-smoke/, and recorded in one decision-log entry; the execution handoff, its .handoff/ archive and tools, and the reference-and-replay method are retired.

Progress: 2026-10-03 · Zero-width artefacts fixed (D-114; no version change, the controller decides on a tag); next: S9. Floors and ceilings between storeys are clipped from conformed footprints (PolygonOps.Conform, ADR-002), so rotated and moved plans carry no slivers, spikes, or excursions (a sweep of 14,400 buildings: 1,249 with artefacts before, none after); Convert2IDF's sliver handling stays as a guard; rotated setback stacks are no longer split by rounding slivers under Stacked Floor Zone Multiplier; snapshots unchanged; 346 core, 518 generator, 635 export, and 1573 integration tests pass on net8.0.

Progress: 2026-10-03 · S9 Release complete (version 1.0.0, D-116; the tag v1.0.0 is set at the fresh-clone gate and pushing waits for the owner). A local MkDocs docs site (user part and developer part, served on localhost, never published), the component reference generated from the plugin's metadata with icons and screenshots, 19 example definitions built by the headless harness (one per plan generator and the end-to-end example), the sync-docs project skill, a local Yak build (scripts/package-yak.ps1), and the MIT license. The headless check found a Grasshopper freeze: BEMGen's Goo types lacked a public parameterless constructor, so a wire of the wrong type, the "Data conversion failed" message, or component help opened Grasshopper's modal assert dialog in every version up to v0.9.1; fixed, and the smoke check now asserts expected errors. scripts/verify.ps1 and mkdocs build --strict pass; all 12 rhino-smoke specs pass and all 19 examples reopen and solve; 346 core, 518 generator, 635 export, and 1573 integration tests pass on net8.0. Open for a person: the examples on screen, the Yak install, the toolbar icons, and a first EnergyPlus run (D-112). Next: the first EnergyPlus run and sourced presets (D-112, D-023).

Progress: 2026-10-03 · The docs site move, BEMGen side, complete (version 1.0.1, D-117 to D-119; tag v1.0.1). The MkDocs site left this repository for the public energy-atlas/BEMGen-docs; scripts/docs-export/ writes what the site takes from BEMGen, scripts/package-release.ps1 builds each version's release files for that repository's GitHub Releases (D-118), and decision numbers left every user-visible string. Step C, the import and release there, belongs to the docs repository.

Progress: 2026-10-05 · Enum inputs complete (version 1.0.2, D-120, D-121; tag v1.0.2, released with a docs export). Five inputs that took an enum name as typed text list its values in the right-click menu, and Extract parameter on them places a dropdown; 13 rhino-smoke specs pass, and 346 core, 518 generator, 635 export, and 1573 integration tests pass on net8.0.

Progress: 2026-10-06 · Conditioned Merge and joined pieces built on feature/conditioned-merge and reviewed (D-123); not merged: the merge, version, and tag are the owner's. A new plan simplifier merges conditioned and unconditioned zones separately (Z1c) and keeps conditioned floor area exactly; Semantic Merge and Conditioned Merge take Join Pieces, one zone per connected piece (default) or one per class made of its pieces. scripts/verify.ps1 passes (412 core, 518 generator, 2620 integration, 1024 export tests) and all 14 rhino-smoke specs pass. Open for a person: the merge checklist.

Progress: 2026-10-07 · Program mix and building-level infiltration built on feature/program-mix and reviewed (D-124, ADR-017); not merged: the merge, version, and tag are the owner's. Mix Programs mixes presets by floor-area share as a zone merge would (absolute loads raw, setpoints over the conditioned inputs); infiltration leaves programs and becomes an Envelope Preset input written per zone in EnergyPlus's own method. scripts/verify.ps1 passes (417 core, 518 generator, 1624 integration, 705 export tests), all 14 rhino-smoke specs pass, and the IDD check of 579 files finds 0 problems. Open for a person: the program-mix checklist.

Progress: 2026-10-07 · The program mix (D-124) rebased onto Conditioned Merge (D-123) on feature/program-mix, for release 1.1.0; not merged: the merge and tag are the owner's. Zones of several pieces take the envelope's infiltration over the outdoor surfaces of every piece; the merge modes run through the infiltration and program-mix matrices; the four Conditioned Merge snapshots change only by infiltration (three floor snapshots lose their infiltration load lines, and the stair-bay bar's IDF snapshot gains the header line and the envelope's schedule); the IDD-check files of the joined merge modes are written under plain file names (a colon had hidden 288 of them in alternate data streams). scripts/verify.ps1 passes (484 core, 518 generator, 2695 integration, 1148 export tests) and the IDD check of 1016 files finds 0 problems. Open: the rebuilt examples and the headless Rhino run of all specs.

Progress: 2026-10-07 · Version 1.1.0 (D-125): Conditioned Merge and joined pieces (D-123) and the program mix with building-level infiltration (D-124, ADR-017) integrated into one linear history and released as v1.1.0; the owner approved the merge, the tag, the push, and the release on 2026-10-07. scripts/verify.ps1 passes (484 core, 518 generator, 2695 integration, 1148 export tests) and the IDD check of 1016 files finds 0 problems; the headless Rhino check of every spec and the example rebuild are recorded in D-125. Open for a person: the Conditioned Merge and program-mix checklists in the smoke test. The S10 atlas presets (D-122) are not in this release; they wait on feature/archetype-data. Next: the first EnergyPlus run and sourced presets (D-112, D-023).

Progress: 2026-10-07 · The program JSON stage built on feature/program-json, reviewed, and smoke-checked (D-126, ADR-018), for version 1.2.0; not merged: the merge, the tag, the push, the docs export, and the release are the owner's. The S10 atlas stage is retired: its fetch components (D-122, ADR-016) were never merged, and the branch is kept only as the local tag archive/archetype-data. In its place the new component Program JSON turns the text of an Energy Archetype Atlas program JSON 2.0.0 into a program preset (Lod.ProgramJson, strict parsing, a bundled JSON Schema library, expansion of rule-based schedules on a calendar of Year and Holidays, overrides, provenance), and BEMGen's program model grew to hold what the contract describes: loads per dwelling unit (merged by dwelling count), end uses, heat fractions, the occupants' activity and fractions, heating and cooling as separate sides, hot-water temperatures, and a calendar. Existing definitions open unchanged, the IDF writer takes these values from the program with its old fixed values as defaults, and 28 text snapshots gained lines and 6 IDF snapshots a header line and the run-period year 2007. scripts/verify.ps1 passed (614 core, 518 generator, 160 program JSON, 2698 integration, 1219 export tests, after the review fixes and a fix of concurrent schema evaluation), the IDD check of 1073 files finds 0 problems, and all 16 rhino-smoke specs pass with the 20 examples reopening and solving. Open for a person: the canvas look of program-json-office.gh and the icon, a 1.1.0 definition opened in the editor, and the install from the .yak. Next: the first EnergyPlus run (D-112).

Progress: 2026-10-09 · Version 1.2.0 (D-127): the program JSON stage (D-126, ADR-018) fast-forwarded into main and released as v1.2.0, at the owner's request of 2026-10-09. scripts/verify.ps1 passes with the counts above, the 20 example definitions were rebuilt with the 1.2.0 plugin and all reopen and solve with Validate True, and a clean clone passes the fresh-clone gate. The release files and a docs export of v1.2.0 go to the docs repository (D-118). Next: the first EnergyPlus run and sourced envelope values (D-112, D-023).

Progress: 2026-10-11 · The simulation-ready IDF stage is built on feature/idf-out (D-130, ADR-019), for version 1.3.0, not merged: the merge, the tag, the push, the docs export, and the release are the owner's. - Convert2IDF targets EnergyPlus 26.2, takes a weather file, and writes the research outputs of the new experiment outputs (from the owner's specification), a case record, and ground temperatures "indoor minus 2 °C". - Non-convex outdoor surfaces are split into convex pieces, and the storeys a floor multiplier leaves out cast shadows in both converters. - The new library Lod.Simulation runs EnergyPlus outside the pipeline, reads its outputs, and computes the experiment metrics, with opt-in end-to-end tests and the check tool scripts/eplus-check.

Checks: - scripts/verify.ps1 passes (629 core, 518 generator, 160 program JSON, 1382 export, 2726 integration, 136 simulation tests). - 110 EnergyPlus cases pass the end-to-end set, and all 1080 export IDFs pass eplus-check and the 26.2 IDD check. - All 16 rhino-smoke specs pass.

The tag v1.3.0 is set locally on the owner's request; the merge and the push wait for the owner's review. Next: the owner's merge and release of 1.3.0, and sourced envelope values (D-023).

Progress: 2026-10-12 · Version 1.3.0 (D-131): the simulation-ready IDF stage (D-130, ADR-019) fast-forwarded into main and released as v1.3.0 at the owner's request. The 20 example definitions were rebuilt with the 1.3.0 plugin and all reopen and solve with Validate True; a clean clone of main passes the fresh-clone gate. The release files and a docs export of v1.3.0 go to the docs repository (D-118). Next: simulation experiments with the runner and the experiment metrics, and sourced envelope values (D-023).

Progress: 2026-10-12 · The batch runner (D-132) is built on feature/idf-batch-runner; it is not merged and not released. scripts/IdfBatchRunner runs batches of Convert2IDF files: - each case's reference is found from the case records, references run first, and no case runs without a reference; - each run's folder gets a central DuckDB database of the useful results with the hourly loads by fuel and by end use, a full batch database with 17 hourly series per case, and a folder per case; - merge combines runs, and --resume continues one.

Lod.Simulation gains the end-use-by-fuel catalogue, the closure check, the run period's timestamps, and the batch plan. scripts/verify.ps1 passes (629 core, 518 generator, 160 program JSON, 1382 export, 2726 integration, 176 simulation, and 41 batch-runner tests; the 6 opt-in EnergyPlus tests skipped; 0 warnings). The tool ran 80 real cases of the 1.3.0 end-to-end set at 361 kB per case in the central database. Next: the owner's review and merge, then simulation experiments with the tool.

Progress: 2026-10-12 · Test suites (D-133 to D-135, ADR-020) are built on feature/test-suite-generator, on top of the unmerged batch runner. Neither branch is merged. - "Case" is now "site" everywhere current. - scripts/TestSuiteGenerator writes a suite's IDFs and tables from a YAML spec. - The batch runner's --suite runs the declared test cases, and joins every site's metrics to its generation parameters in site_results.

scripts/verify.ps1 passes, and a generated suite ran on EnergyPlus 26.2. Next: the owner's review and merge of both branches, then the first study suites.

Progress: 2026-10-12 · The batch runner and test suites are merged into main by fast-forward (D-136), without a release: still version 1.3.0, with no tag and no push. scripts/verify.ps1 passed on the merged commit. Work continues on feature/test-suite-generator. Next: a pilot suite on real program JSON and a few climate zones, and the deferred designs (schedule generator, constructions, buildings whose floors differ).

Progress: 2026-10-15 · The construction JSON stage closes on the unified path (D-137 to D-139, ADR-021, design note) on feature/construction-json, not merged, with no release. Parts A to D are built, reviewed, and verified: the pinned atlas packet; typed layers and glazing; Lod.ConstructionJson, construction sets, and the mass ledger; Construction JSON and Convert2IDF's Construction input. scripts/verify.ps1 passed, all 17 headless Rhino specs passed, the 168 construction IDFs have no IDD problem and ran in EnergyPlus 26.2, and the fresh-clone gate passed at 8fffa3e (a clone of the branch into D:\BEMGen-gate\construction-json, scripts/verify.ps1 with every test project, the packet manifest hash intact). Next: Part E, the detailed documents, and the merge at the owner's direction.

Progress: 2026-10-15 · C2 and E1 of the construction JSON stage (D-140, D-141, ADR-022) on feature/construction-json, not merged. Packet v2 is pinned. Fill From Example is opt-in. A house's attic ceiling is its roof. Detailed documents are read, not assigned. scripts/verify.ps1 passed, all 17 headless Rhino specs passed, and the C2 IDFs passed the IDD check and EnergyPlus 26.2. The fresh-clone gate passed at 6e36c02 (a clone of the branch, scripts/verify.ps1 with every test project, the packet v2 manifest hash intact). Next: E2, its design note first, and the merge at the owner's direction.

Progress: 2026-10-16 · D-142 and D-143 on feature/construction-json (not merged, no release; design note, build log "D-142 and packet v3"). Construction JSON converts only unified building-scope sets and refuses single-dwelling ones; the residential rules of D-140 and E2 are gone, and detailed documents are evidence only. Packet v3 (seven pairs, with the midrise apartment) is pinned. A removed slab is written as a half slice per exposed face, so the IDF holds its capacity once. The solar multiplier was checked in EnergyPlus 26.2 (ratio 0.8276). Deferred by the owner: Program JSON v3, the test-suite generator's construction input, and Convert2BEM with construction sets. The review by a second agent found nothing blocking; its three low findings are fixed or recorded. scripts/verify.ps1 passed, all 17 headless Rhino specs passed (construction-json: 7 scenarios, 19 checks), and the fresh-clone gate passed at 80016e3 (a clone of the branch into D:\BEMGen-gate\d143, scripts/verify.ps1 with every test project, the packet v3 manifest hash intact). Next: the merge at the owner's direction.

Progress: 2026-10-16 · Version 1.4.0 (D-144): the construction JSON stage (D-137 to D-143, ADR-021) fast-forwarded into main and released as v1.4.0 at the owner's request, after the owner's check in Rhino. The 20 example definitions were rebuilt with the 1.4.0 plugin and all reopen and solve with Validate True; a clean clone of main passes the fresh-clone gate. The release files and a docs export of v1.4.0 go to the docs repository (D-118). Next: simulation experiments with the runner and the experiment metrics, and sourced envelope values (D-023).

Progress: 2026-10-18 · The construction foundation v7 stage (D-145, D-146, ADR-023, design note) is built, reviewed by a second agent, and verified on claude/bemgen-construction-v7-update-bd63b1; it is not merged, tagged, pushed, or released. Packet v7 replaces v3; foundations are instantiated from declared geometry (the handover's R1 to R6, K1 to K6, and I1 to I6 pass on both representations); Convert2IDF writes a v7 set's own F-factor or layered ground floors, with the weather file's ground temperatures for F-factor and 18 °C for layered ground, while Kiva and the C-factor wall are written only outside the pipeline. scripts/verify.ps1 passed, all 17 headless Rhino specs passed, the IDFs have no IDD problem, and EnergyPlus 26.2 passed every case except the small data centre with Example windows (6 severe errors). Next: the owner's reading, then the merge at the owner's direction; the open items are in ADR-023.

Progress: 2026-10-19 · The v7 stage is fast-forwarded into main (D-150), with its follow-ups: - D-147, a Convert2IDF warning when Example windows meet a ground floor that absorbs no solar; - D-148 and D-149: turned court plans run in EnergyPlus, and core ground floors now expose exactly 0; - the shared assignment-selection rule.

scripts/verify.ps1, the opt-in EnergyPlus suites, and all 17 headless Rhino specs passed. Not pushed, tagged, or released.

Progress: 2026-10-19 · The suite constructions and ground stage (D-151, design note) is built, reviewed by a second agent, and verified on feature/test-suite-generator; it is not merged into main. - Test suites take unified construction JSON sets, paired only with weather files of their climate zone. - The research outputs gain the hourly building-level ground heat transfer (experiment outputs §9). - A pilot suite of two F-factor sets ran on EnergyPlus 26.2 with the owner's 3B weather file, every site succeeding.

Next: Program JSON 3.0.0, with its own note.

Progress: 2026-10-22 · After a first mock test suite (1,024 sites, results outside the repository), D-151 is fast-forwarded into main (not pushed) and the batch runner's results are redesigned on feature/runner-site-status (D-152, D-153), not merged. - Progress lines as each site finishes; sites start in plan order. - A status row for every site in central.duckdb. - Central schema version 5 without hourly rows; an hourly Parquet file per site; raw/ and failure/ folders; incremental resume. - The mock suite ran in 8 min 24 s with a 3.6 MB central database.

Progress: 2026-10-22 to 2026-10-25 · The runner stages are merged into main and pushed (D-154); merged branches and worktrees are cleaned up, and the program JSON popup branches are kept unmerged on origin (D-155).

Progress: 2026-10-26 · The paired evaluation metrics (D-156, D-157, design note) are built, reviewed twice by a second agent, verified, and fast-forwarded into main (D-158), not pushed or released. - Experiment outputs §10: the ideal sensible heating and cooling summed over the zones (EnergyPlus already multiplies them by the zone multiplier), their annual, peak, P99/P95/P90 and exceedance, CV(RMSE), NMBE (reference minus site), load-duration-curve NRMSE over the full curve and the top 1, 5, 10 %, and KS against the reference; the conditioned temperature's MBE and RMSE over all hours; the cost with processor time and committed memory; a near-zero guard in ToleranceSettings. - The batch runner: central schema version 7 with metric_definitions, 20 hourly series, and an optional serial timing pass (site_timing). - scripts/verify.ps1, the opt-in EnergyPlus suites, and all 17 headless Rhino specs passed.

Progress: 2026-10-25 · DOE reference geometry generators (design note, ADR-025) on feature/doe-geom, not merged into main. Stage P0a (D-160, D-161) merged: 15 layout records and answer keys extracted from the DOE reference buildings and the openstudio-standards detailed offices, GridPlanLayout with the S3 variation rule, sourced program keys, and the comparison harness; T1–T3 pass for every record except the hospital ground storey (P5).

Progress: 2026-10-25 · DOE geometry stage P0b (D-162) merged into feature/doe-geom: WWR per orientation and skylight ratio on program presets, the S6 glazing reference height, skylights through every simplifier, aggregator, Convert2IDF and Convert2BEM, and T4 on the source's true outdoor walls; all 15 records pass T2 and T4, with the gap and P5 quantities excluded by reason.

Progress: 2026-10-26 · DOE geometry stage P5a (D-163, ADR-026) merged into feature/doe-geom: zone multipliers on planned zones, one plate with a copy space, the SelfAdjacent boundary through validation and both converters, equal-multiplier merging, and T4 through the generators' path with per-key glazing; the hospital and large hotel pass T1–T4.

Progress: 2026-10-26 · DOE geometry stage P1 (D-164) merged into feature/doe-geom: the ring offices (small, medium, large) with the ×10 middle floor as a storey multiplier, the DOE Program Map and the DOE generator component base, and S3 amended to slack shares (note §2 and ADR-025 amended, the O3 wording corrected).

Progress: 2026-10-26 · DOE geometry stage P3 (D-165) merged into feature/doe-geom: the school generator (primary and secondary) with its wing count, the spine stretched by slack so every wing keeps its links, and two components.

Progress: 2026-10-26 · DOE geometry stages P5b (D-166) and P6 (D-167) merged into feature/doe-geom: the tower hotel (×4 floor, ×19 rooms) and the hospital (17 multiplied rooms on one plate with a copy space) with their components, and the outpatient (59/41/26 zones) with its component; the full Rhino smoke check passes 22 specs.

Progress: 2026-10-26 · DOE geometry stage P2 (D-168) merged into feature/doe-geom: the restaurants, strip mall, stand-alone retail, supermarket and warehouse generators with six components; the full Rhino smoke check passes 23 specs.

Progress: 2026-10-26 · DOE geometry stage P4 (D-169) merged into feature/doe-geom: the corridor hotel generator of the small hotel with one flexible interval per guest-room bay and its component. Every build stage is merged; the full Rhino smoke check passes 24 specs. Next: the close-out C.

Progress: 2026-10-26 · DOE geometry stage C (D-170) merged into feature/doe-geom: icons for the 15 DOE generator components, DOE Program Map and its parameter; the sync-docs pass; the design note Done pending the owner's reading. scripts/verify.ps1 passes and the full Rhino smoke check passes 24 specs. Every DOE stage is built, not merged into main, pushed, or released; what remains is the owner's reading (D-160 to D-170), the atlas inputs A1 to A3, and the items for a person in Rhino 8.

Progress: 2026-10-26 · DOE geometry stage P7 (D-171) merged into feature/doe-geom: fifteen DOE … Programs presets in 1 Program Presets, one ready program map per DOE generator (illustrative example loads, the source's glazing per key, shipped in the layout records); scripts/verify.ps1 passes and the full Rhino smoke check passes 25 specs.

Progress: 2026-10-29 · Version 1.5.0 prepared on release/v1.5.0 from main at 54f990d (D-175): the construction foundation v7, suite, runner, and evaluation-metric stages (D-145 to D-159), the DOE reference geometry generators (D-160 to D-171, PR #1), and the atlas release 2.0.0 contracts with no daylight dimming in IDF runs (D-172 to D-174, PR #2); the 20 examples rebuilt, the full Rhino smoke check passes 25 specs, and the fresh-clone gate passes. Next: the geometric LOD study.

Progress: 2026-10-29 · The owner approved PR #1 (D-176): the DOE geometry decisions D-160 to D-171, ADR-025, ADR-026, the DOE design note, and the DOE architecture pages are Accepted.

Progress: 2026-10-29 · The research integration branch (D-177 to D-183, ADR-028 to ADR-031) merged into main (D-184), renumbered after main's D-172 to D-176 and ADR-027; not released.

Progress: 2026-10-29 · Stage B2, Schedule Draw (design note, D-194 to D-196, ADR-033): the atlas generator atlas_schedules 3.0.0 as an external command, Schedule Draw in 1 Program, and the test-suite spec's schedules: section; not released. The Rhino check of the new component is open.

Progress: 2026-10-29 · Stage B3, version 1.6.0 prepared on release/v1.6.0 from main at 5883da6 (D-197): Schedule Draw with the released generator atlas-schedules 3.0.0 and Program JSON reading atlas release 2.1.0 (D-198), DOE Reference Program and the research contracts (D-177 to D-184), the LOD study tooling and the IDF writer's coplanar merge (D-185 to D-192); the 21 examples rebuilt (the new schedule-draw.gh), the full Rhino smoke check and the fresh-clone gate pass. The person-in-Rhino checklist is open.

Progress: 2026-10-30 · Version 1.7.0 prepared on release/v1.7.0 from main at 38ff521 (D-204, design note): atlas release 2.2.0 and the generator 4.0.0 pinned (D-205, ADR-035): the embedded program JSON 5.4.0 schema with its release pattern, Schedule Draw on request and bundle schema 4.0.0 with release program IDs, the export's view, and the release's generation.json, the recorded draws recorded again; the 21 examples rebuilt, the full Rhino smoke check and the fresh-clone gate pass. The person-in-Rhino checklist is open.

Progress: 2026-10-30 · Phase 1 of the atlas program picker note (D-207): the JSON editor window of D-128 merged into main, its nine conflicts resolved, its tests moved to program JSON 5.4.0, and its check given the component's Climate Zone and Context. The program checksum is now that of the text with LF line endings, which changes the recorded checksums of the release 2.x fixtures (written with CR LF) but no fixture. Not released: 1.8.0 follows phase 3.

Progress: 2026-10-30 · Phase 2 of the atlas program picker note (D-208): Get from Atlas… on Program JSON takes the program of the page the user opens on the atlas site, downloaded and checked against the site's index and the store file's name (Lod.ProgramJson.Site); the clipboard of D-129 is gone, and the solve still reads no file or network. Not released: 1.8.0 follows phase 3.

Progress: 2026-10-30 · Phase 3b of the atlas program picker note (D-209, ADR-036): Get from Atlas… on the fifteen DOE Programs components takes every key's program of one of five atlas families from the prototype's one folder, stored in the component and imported offline with Program JSON's import, with the DOE reference glazing, the inputs Climate Zone, Year, Holidays, Context, and the output JSON; keys without a program are refused by name. Schedule Draw's strip takes the program's folder's generation.json from the site. For 1.8.0 (D-210).

Progress: 2026-10-30 · Version 1.8.0 (D-210): the atlas program picker's three phases (D-207 to D-209), with the examples rebuilt (22, the new doe-atlas-map.gh with a stored atlas map) and the release files on the docs repository.

Progress: 2026-11-01 · Stage LOD1 of the 2026-10-31 review's fix programme (tooling fixes, D-219 to D-223): the LOD study's R6 tables from durable sources with the lost repeat check archived, recommendations bounded by the reference's zone count with every planned zoning listed (schema 1.2.0), the both-on twin kept, cost medians by prototype, the lod-study tests in scripts/verify.ps1, LF output, a pinned EnergyPlus; the R4 small-hotel rerun after BG1 follows (D-224).

Progress: 2026-11-01 · Stage BG3 of the 2026-10-31 review's fix programme (code-rule daylighting, D-233 to D-235, ADR-037): Convert2IDF's appended Daylighting input (off by default, the LOD study's setting) writes the programs' daylighting controls at the reference points the 90.1 code rule of openstudio-standards places on each zone's own windows and skylights; the test-suite spec's settings.daylighting; the partial-control warning expected only for IDFs with controls; occupancy sensors and time switches checked in the PNNL models (an occupancy-driven lighting cap left to the atlas); the prototype fractions compared on four DOE prototypes.

Progress: 2026-11-01 · Stage BG2 of the 2026-10-31 review's fix programme (atlas pickers, D-225 to D-229): site downloads at most four at a time with one retry of a 429 or 5xx and a rate-limit message (D-225); the program and construction checksums of the atlas's canonical JSON, with the store file of an atlas pick in Source (D-226); the site index schema 1.0.0 with its mix compositions and construction sets (D-227); Get from Atlas… on Mix Programs (D-228) and on Construction JSON, the residential source-model documents refused (D-229).

Progress: 2026-11-01 · Stage REL-B of the 2026-10-31 review's fix programme (REL-B, D-239 to D-245, ADR-038): BEMGen reads atlas release 2.3.0 (program JSON 6.0.0, unified 4.0.0, detailed 5.0.0; the fixtures and the recorded sites from release 2.3.0), refuses stored texts of earlier releases naming their 2.3.0 IDs through the atlas's ID map, offers the six IECC families on the DOE Programs components (F1), draws with atlas-schedules 4.1.0 (the DOE offices and IECC programs drawable), and imports the 152 DOE Ref unified documents of A2; version 1.9.0. Rhino not run: the examples' rebuild, the smoke check, and the docs export are for a person.

Progress: 2026-11-01 · Stage REL-B2 of the 2026-10-31 review's fix programme, round 2 (REL-B2, D-253 to D-260, ADR-040): BEMGen reads atlas release 2.4.0 (program JSON 6.1.0; constructions unchanged; the fixtures and the recorded sites from release 2.4.0), refuses stored texts of releases 2.0.0 to 2.3.0 naming their 2.4.0 IDs through both ID maps, draws with atlas-schedules 4.1.1, and writes the PNNL unoccupied lighting cap as an EMS program per zone when Convert2IDF's Lighting Cap is on (off by default, the owner's G4); version 1.10.0 (D-260).

Revisions: v1 (2026-09-30) initial draft · v2 (2026-09-30) pipeline-first restructure after D-015 to D-024: Grasshopper objects instead of JSON, the D-018 pipeline vocabulary, ClimateStudio output without simulation, precedent study moved after the pipeline works · v3 (2026-10-01) plan review: conditioning from presets (D-038), explicit windows and a separate window-transformation stage S5 with later stages renumbered (D-039), multiplier without multiplied ground or roof (D-040), enforced façade coverage (D-041); facts established while writing the S0–S4 plans · v4 (2026-10-01) plan review: representative storeys at their true elevations (D-045), exposed storeys of multiplied floor types split off automatically so floor types may differ in footprint (D-046, supersedes D-040), loads aggregated per load type and basis (D-047) · v5 (2026-10-01) Checkpoint 1 review: revision stage S4.1 before S5 (D-061 to D-064) · v6 (2026-10-01) S4.1 review: revision stage S4.2 before S5 (D-068 to D-077) · v7 (2026-10-01) windows of merged zones: one centred window per rebuilt wall with the wall's glazed area, window levels W1–W5 dropped, S5 renamed "Centred windows on rebuilt walls" (D-079, ADR-012) · v8 (2026-10-02) precedent source High-Density Housing, studied in a separate repository, replaces the S7 research (D-082); one plan generator per typology family (D-083); S8 split into S8.1–S8.3 (D-084) · v9 (2026-10-02) four-source precedent set SYN-TYP-001–019 (D-093), non-residential programs in scope (D-094), plans per storey (D-095), 013 set aside (D-096), department zoning (D-097), sub-stages S8.4–S8.7 before S6 (D-098).

For agentic workers: this is a stage-level roadmap, not an executable task list. Before starting a stage, write its detailed test-first plan as docs/plans/YYYY-MM-DD-sN-<stage-name>.md (bite-sized tasks, exact files, test code, commands), using superpowers:writing-plans, then execute it with superpowers:subagent-driven-development or superpowers:executing-plans.

Goal: A Rhino 8 Grasshopper plugin that generates detailed plans of residential and non-residential building typologies (D-094) from program presets, simplifies them into lower-LoD buildings that satisfy prescribed conservation invariants, checks those invariants numerically, and outputs Grasshopper objects ready for visualization and for a ClimateStudio definition.

Architecture: All logic lives in plain C# libraries (Lod.Core, Lod.Generators, later Lod.Export) and is tested with dotnet test without Rhino. Lod.Grasshopper wraps the pipeline types in Goo, exposes one component per pipeline step, previews every object, and hosts Convert2BEM. The pipeline (D-018):

program presets (x, y, ...)
  → PlanGenerator (LinearPlanGenerator, ...)        → IGeneratedPlan      Z0: one zone per dwelling unit or department, explicit windows
  → PlanTransform (optional, D-070)                 → IGeneratedPlan      rotation about z, translation in x and y
  → IPlanSimplifier                                  → IFloor              one centred window per rebuilt wall (D-079)
       NoSimplification | SemanticMerge | ConditionedMerge | PerimeterCore | SingleZonePerFloor
  → IFloorAggregator (IFloor[])                      → IGeneratedBuilding
       Stack | StackedFloorZoneMultiplier | SingleZonePerFloorType | SingleZoneBuilding (whole building = 1 zone)
  → Convert2BEM                                      → ClimateStudio-ready Grasshopper inputs
  → Convert2IDF (S6)                                 → EnergyPlus-ready IDF

Tech stack (ratified in ADR-001 during S0): C# 12, .NET SDK ≥ 8, netstandard2.0 core libraries, Rhino 8 RhinoCommon + Grasshopper NuGet packages ≥ 8.19 (plugin targets net7.0 only, one BEMGen.gha for Rhino 8's default .NET Core runtime; D-053), Clipper2 for polygon operations, xUnit on net8.0 only. No System.Collections.Immutable (Rhino 8 ships a conflicting copy).

Progress: 2026-10-28 · The first reference-program backend stage, D-177/ADR-028, provides authenticated MidriseApartment programs for two DOE releases, an opt-in floor research writer gate, and separate thermal/purchased/COP/cost reporting. It remains on feature/reference-program-contract, not merged or released; version stays 1.4.0. Existing components and example defaults are unchanged. No new annual simulations establish reference energy accuracy.

Global constraints

The subsequent 2026-10-28 adapter continuation (D-178/ADR-029) exposes explicit source-program selection and the floor research opt-in in Grasshopper, preserving existing GUIDs/defaults. Combined verification: 7,907 passed, 18 explicit engine/weather skips. An isolated direct-instance native check passed 62 checks, including the actual sourced-program-to-IDF caller; normal registration/archive restoration remain open after a duplicate-library startup diagnosis. The office/courtyard work remains a source-linked contract plan and local geometry data, with no new generators or annual simulations.

  • Rhino 8 (8.19 or later) only (D-003). BEMGen is a Grasshopper plugin; stages exchange Grasshopper objects, not JSON (D-017).
  • Lod.Core, Lod.Generators, Lod.Export have no RhinoCommon/Grasshopper reference; their tests run without Rhino.
  • Nullable reference types enabled; warnings as errors in all projects.
  • Generation is deterministic; randomness only via an explicit seed stored in metadata.
  • Numerical tolerances live only in ToleranceSettings.
  • Z0 has at most one zone per dwelling unit and storey; rooms are never modelled (D-009, D-085). A non-residential floor has one zone per department, a contiguous group of rooms of one program (D-097, ADR-014).
  • Walls carry explicit windows (position, sill, width, height; any number per wall). The first generator places one centered window per outdoor wall sized from the preset's WWR (D-026); wherever zones are merged and walls rebuilt, every outdoor wall carries one centred window, shaped by the same rule, with the glazed area of the source windows it covers, so glazing is conserved per wall, façade, orientation, and building; steps that do not rebuild walls keep their input's windows (D-079, ADR-012). There are no window levels W1–W5.
  • Conditioning comes from the program preset; unconditioned zones have no setpoints. A simplified zone is conditioned if any source contributing floor area is; its setpoints are floor-area weighted over the conditioned sources, a prescribed control rule, not a conservation invariant (D-038).
  • Air-change-based loads are volume weighted (D-019).
  • Façade coverage is enforced: target façades must cover every source façade over its full length (D-041).
  • Floor multipliers never multiply exposure: storeys with exposed floors or ceilings (ground, roof, setbacks, overhangs) are split off as ×1 storeys automatically, so floor types may differ in footprint; representative storeys sit at their true elevations (D-045, D-046).
  • A program may express a load type in several bases (e.g. ventilation per person plus per area); each (type, basis) component is aggregated and conserved on its own (D-047).
  • Validation failures block conversion unless an override is explicitly recorded.
  • No simulation inside the pipeline (D-016). No CI/CD (D-005); scripts/verify.ps1 must pass locally before merging to main.
  • Commits: type(scope): summary, no tool attribution (D-001, D-002). Chat decisions go to docs/decisions/decision-log.md (D-007).

1. Stage overview

Stage Name Depends on Tag
S0 Foundation — v0.0.1
S1 Program presets and equivalence engine S0 v0.1.0
S2 End-to-end pipeline skeleton S1 v0.2.0
S3 Plan simplifiers and validation S2 v0.3.0
S4 Floor aggregators S3 v0.4.0
S4.1 Grasshopper inputs, presets, and icons (revision, D-064) S4 v0.4.1
S4.2 Vertical aggregation methods, plan transform, and heat-transfer options (revision, D-073) S4.1 v0.4.2
S5 Centred windows on rebuilt walls S4.2 v0.5.0
S6 Convert2IDF S8.8 (D-098, D-108) v0.9.0
S7 Precedent study — replaced by the external study of D-082 — —
S8.1 Plan generation mechanism and bar typologies (ADR-006, ADR-011; families 009 check, 001, 008, 002, 006) S5 v0.8.0
S8.2 Non-rectangular typologies without holes (families 007, 003, 004) S8.1 v0.8.1
S8.3 Enclosed courtyard (family 005), footprints with holes in every simplifier and aggregator S8.2 v0.8.2
S8.4 Non-residential programs, office plate and cafeteria (pinned four-source records, scope alignment, ADR-014; families 017, 016) S8.3 v0.8.3
S8.5 Branching plans on a shared hub-and-arms layout (families 010, 014, 018, 019) S8.4 v0.8.4
S8.6 Operating suite and linked court clusters (families 015, 011) S8.5 v0.8.5
S8.7 Plans that differ by storey (D-095, with an ADR) and stepped bands with terraces (family 012) S8.6 v0.8.6
S8.8 Storey previews, any-program preset, and the preset panel (revision stage, D-108) S8.7 v0.8.7
S9 Release: docs site, examples, Yak package (D-115) S6, S8.8 v1.0.0
— Conditioned Merge and joined pieces for both merge simplifiers (revision, D-123) S9 v1.1.0
Mix Program mix and building-level infiltration (revision stage, D-124, ADR-017) S9 v1.1.0
S10 (retired) Atlas fetch components (D-122, ADR-016): never merged, retired by D-126; archived as the tag archive/archetype-data — —
Program JSON Program presets from program JSON 2.0.0 and the extended program model (revision stage, D-126, ADR-018) S9 v1.2.0
JSON editor A JSON editor window on Program JSON and the LF checksum (revision, D-128) Program JSON merged into main (D-207), v1.8.0 (D-210)
S0 ── S1 ── S2 ── S3 ── S4 ── S4.1 ── S4.2 ── S5 Windows ── S8.1 ── S8.2 ── S8.3 ── S8.4 ── S8.5 ── S8.6 ── S8.7 ── S8.8 ── S6 Convert2IDF ── S9 Release
            (S7 precedents: done outside this repository, D-082)

The pipeline is complete for the linear plan at the end of S4 (D-015); only then do the centred-window rule (S5), precedents, and new typologies begin. The revision stage S4.1 (D-061 to D-064) changes the Grasshopper inputs after the Checkpoint 1 review (one preset input per space type with default preset components, a Preview Location input, icons) and runs before S5. The revision stage S4.2 (D-068 to D-077) follows it, also before S5: floors and ceilings designated on the assembled stack, four floor aggregation methods, Transform Plan, and heat transfer between zones as an export option. S6 depends on S4.2 for that option (D-077) and follows S8.7 (D-098) and the revision stage S8.8 (D-108). The precedent research of S7 was done in a separate repository (D-082); S8 builds one plan generator per typology family in three sub-stages (D-083, D-084); the four-source precedent set (D-093) adds nine families of every program type (D-094), built in S8.4–S8.7 before S6 (D-098). Simulation, batch experiments, and error analysis are outside this repository (D-016).

Detailed stage plans

Test-first plans for S0–S4, written on 2026-10-01 from code that was built (warnings as errors) and tested on net8.0 and net48 stage by stage before the plans were written; net48 was dropped after S0's smoke test (D-053), so the counts below are for net8.0:

Stage Plan Tests at stage end (net8.0)
S0 2026-10-01-s0-foundation.md 1 core
S1 2026-10-01-s1-presets-equivalence.md 65 core
S2 2026-10-01-s2-pipeline-skeleton.md 94 core, 17 generators, 9 integration
S3 2026-10-01-s3-plan-simplifiers.md 104 core, 17 generators, 38 integration
S4 2026-10-01-s4-floor-aggregators.md 104 core, 17 generators, 63 integration
S4.1 2026-10-01-s4.1-presets-preview-icons.md 120 core, 19 generators, 63 integration
S4.2 2026-10-01-s4.2-aggregation-transform-heat-transfer.md 136 core, 19 generators, 163 integration
S5 2026-10-01-s5-centred-windows.md 142 core, 19 generators, 187 integration
S8.1 2026-10-02-s8.1-bar-typologies.md 152 core, 91 generators, 319 integration
S8.2 2026-10-02-s8.2-non-rectangular-typologies.md 154 core, 159 generators, 474 integration
S8.3 2026-10-02-s8.3-enclosed-courtyard.md 158 core, 181 generators, 601 integration
S8.4 2026-10-02-s8.4-non-residential-programs.md 193 core, 224 generators, 704 integration
S8.5 2026-10-02-s8.5-hub-and-arms-typologies.md 193 core, 360 generators, 1184 integration
S8.6 2026-10-02-s8.6-operating-suite-court-cluster.md 193 core, 427 generators, 1385 integration
S8.7 2026-10-02-s8.7-per-storey-plans-stepped-band.md 210 core, 463 generators, 1485 integration
S8.8 2026-10-02-s8.8-previews-any-preset-panel.md 243 core, 518 generators, 1518 integration
S6 2026-10-02-s6-convert2idf.md (design note, D-111) 294 core, 518 generators, 475 export, 1518 integration
S9 2026-10-03-s9-release.md (design note, D-111) 346 core, 518 generators, 635 export, 1573 integration
Docs move 2026-10-03-docs-site-move.md (D-117 to D-119), version 1.0.1 unchanged; developer-page export: 8 unit tests
Enum inputs 2026-10-04-dropdown-enums.md (design note, D-111, D-120), version 1.0.2 (D-121) unchanged: 346 core, 518 generators, 635 export, 1573 integration
Conditioned Merge 2026-10-06-conditioned-merge.md (design note, D-111, D-123), released in version 1.1.0 (D-125) 412 core, 518 generators, 1024 export, 2620 integration
Mix 2026-10-06-program-mix.md (design note, D-111, D-124), released in version 1.1.0 (D-125) 417 core, 518 generators, 705 export, 1624 integration
1.1.0 The two stages integrated in one linear history (D-125), no design note 484 core, 518 generators, 1148 export, 2695 integration
Program JSON 2026-10-07-program-json.md (design note, D-111, D-126), released in version 1.2.0 (D-127) 614 core, 518 generators, 160 program JSON, 1219 export, 2698 integration
JSON editor 2026-10-09-program-popup-window.md (design note, D-111, D-128), merged into main (D-207) on the branch: 614 core, 518 generators, 173 program JSON, 1219 export, 2698 integration; on main after D-207: 346 program JSON

Where a stage plan and this roadmap differ, the stage plan and its ADRs are authoritative; each plan lists its deviations under "Notes for the reviewer".


2. Target repository layout

Created incrementally; each stage adds only what it needs.

BEMGen.sln
global.json                        SDK ≥ 8
Directory.Build.props              LangVersion 12, Nullable, TreatWarningsAsErrors, code style in build, polyfill link, version
Directory.Packages.props           central NuGet versions
scripts/verify.ps1                 local build + test gate (replaces CI)
src/
  Shared/          IsExternalInit polyfill for netstandard2.0
  Lod.Core/
    Common/        ToleranceSettings, GeometryLimits, Result<T>, Diagnostic, DiagnosticCodes, ZoneId, BuildInfo
    Schedules/     ScheduleKind, Schedule
    Loads/         LoadType, LoadBasis, LoadDefinition
    Programs/      SpaceType, Thermostat, ZoneProgram, ProgramPreset, PresetValues, ExampleResidentialPresets
    Aggregation/   IEquivalentPropertyAggregator, EquivalentPropertyAggregator, SourceZoneContribution, ZoneMeasures, AggregationRecord
    Geometry/      Point2, Polygon2 (outer ring + holes), PolygonOps (Clipper2), Orientation, Window, PlanMotion
    Model/         surfaces, zones, provenance, IGeneratedPlan, IFloor, IGeneratedBuilding, TextReport
    Layout/        LayoutSurfaceBuilder, LayoutMeasures
    Plans/         PlanGenerator (abstract), PlanParameters, PlanTransform
    Simplification/ IPlanSimplifier, NoSimplification, OverlapMapper, TransferMatrix, FacadeAttribution, WindowRehosting, CentredWindows, SemanticMerge, ConditionedMerge, PerimeterCore, SingleZonePerFloor
    Buildings/     IFloorAggregator, Storeys, Stack, StackedFloorZoneMultiplier, SingleZonePerFloorType, SingleZoneBuilding
    Validation/    Totals, FloorValidator, BuildingValidator, ValidationReport
    Conversion/    HeatTransferOptions (export options shared by the converters)
  Lod.Generators/
    Linear/        LinearPlanGenerator, LinearPlanParameters      (HDHM-TYP-009)
    StairBayBar/ StairPair/ GalleryBar/ TerraceRow/                (S8.1: 001, 008, 002, 006)
    PointPlate/ WingedBand/ OpenCourt/                             (S8.2: 007, 003, 004)
    EnclosedCourt/                                                 (S8.3: 005)
    OfficePlate/ Cafeteria/                                        (S8.4: SYN-TYP-017, 016)
    HubArms/ RadialLobes/ BranchingMall/ CareHub/ FoyerHalls/      (S8.5: 010, 014, 018, 019)
    OperatingSuite/ CourtCluster/                                  (S8.6: 015, 011)
    SteppedBand/                                                   (S8.7: 012)
  Lod.Export/
    Idf/           Convert2IDF                         (S6)
  Lod.Grasshopper/
    Goo/           ScheduleGoo, LoadGoo, ProgramPresetGoo, PlanGoo, FloorGoo, BuildingGoo (with preview)
    Parameters/    matching Grasshopper params
    Components/    one component per pipeline step, plus inspect/validate
    Convert/       Rhino geometry conversion
tests/
  Shared/ Lod.Core.Tests/ Lod.Generators.Tests/ Lod.Integration.Tests/ (Lod.Export.Tests/ in S6)
docs/
  decisions/ plans/ research/ architecture/ development/
examples/
  grasshopper/    example definitions (.gh), saved from Rhino 8 by a person

3. Branching, merging, and release workflow

Per D-004 and D-005.

  • Branches: <type>/<scope>-<short-description> from main, e.g. feature/programs-presets, feature/simplifiers-perimeter-core, build/solution-skeleton. One logical change per branch, a few days at most. A stage is several branches, never one long-lived stage branch.
  • Before merging: rebase on origin/main, then run scripts/verify.ps1 (restore, build with warnings as errors, run all tests).
  • Merging (rebase merge, self-merge allowed):
git fetch origin
git rebase origin/main
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/verify.ps1
git switch main
git pull --ff-only
git merge --ff-only feature/programs-presets
git push origin main
git branch -d feature/programs-presets

Opening a GitHub PR and using Rebase and merge is equally valid and leaves a visible record for collaborators. - GitHub settings (no CI involved): protect main against force pushes and deletion; require linear history; enable "Rebase and merge" only. - Tags: annotated v0.N.0 when a stage's exit criteria are met; v1.0.0 after S9; the revisions since are patch or minor versions (v1.0.1, v1.0.2, v1.1.0, D-125; v1.2.0, D-127). - Reproducibility: every IGeneratedBuilding carries a provenance record (generator parameters and presets, simplifier, floor aggregator, plugin version with commit SHA). Tagged history is never rewritten. - Stage method (D-111): a short design note in docs/plans/ before the build (scope, decisions, acceptance criteria, task list, no copied code); one test-first build on feature branches in a worktree, independent parts in parallel worktrees; a review of the diff by a second agent before each merge; scripts/verify.ps1 before each merge; the headless Rhino check scripts/rhino-smoke/ once per stage on the merge candidate; a fresh clone of the tag passing scripts/verify.ps1; pushes only with the owner's approval. - Stage bookkeeping: at each stage end, one decision-log entry (choices and completion), the README status, a dated progress line at the top of this roadmap, and a row in the detailed-plans table; AGENTS.md "Project state" only when its summary changes (D-111).


4. Stages

S0 — Foundation

Goal: a building, testable solution with a plugin that loads in Rhino 8, plus the decisions every later stage relies on.

Work slices (one branch each):

  1. docs/decisions-foundation-adrs — ADRs, each listing options, decision, and consequences:
  2. ADR-001 Toolchain: C# 12 and SDK ≥ 8; core libraries netstandard2.0 with a shared IsExternalInit polyfill; plugin net7.0 only against RhinoCommon/Grasshopper 8.19.25132.1001 (the first packages with net7.0 builds), loaded by Rhino 8's default .NET Core runtime (D-053); tests net8.0 only; xUnit; central package management; no System.Collections.Immutable; component GUID policy.
  3. ADR-002 Geometry: 2.5D. Plans are planar polygons with holes; zones are prisms of floor polygon × floor-to-floor height; walls are vertical rectangles carrying explicit windows (position along the wall, sill, width, height; D-039); floors and ceilings are polygons. Clipper2 (PathsD) handles intersection, union, and difference. Rhino conversion only in Lod.Grasshopper.
  4. ADR-003 Schedules: immutable 8760-value hourly arrays (non-leap year); ScheduleKind.Fraction (0–1) vs ScheduleKind.Temperature (°C).
  5. ADR-004 Tolerances: one ToleranceSettings: distance 1e-6 m, relative area 1e-6 (Clipper2 snaps to a 1e-6 m grid), relative load 1e-9, absolute schedule 1e-9, angle 1e-6 rad.
  6. ADR-005 Conditioning and setpoint aggregation (D-038): conditioning from presets; "any conditioned wins"; setpoints floor-area weighted over conditioned sources; exposed-area weighting rejected (reasons in D-027). Updates the research brief §7.
  7. Research brief §10 update: explicit windows; the first generator's centered-window rule; simplifiers keep windows in place (W0); window transformations are S5 (D-039).
  8. ADR-007 Load-basis aggregation: one magnitude rule for all bases (area, per person, absolute, exterior wall area, air changes — volume weighted, D-019); each (type, basis) component aggregated on its own, so mixed bases are not an error (D-047); schedules weighted by transferred magnitude. Updates the research brief §9. (ADR-006, the plan generation mechanism, was written in S8.1; D-082, D-084.)
  9. build/solution-skeleton — BEMGen.sln, global.json, Directory.Build.props, Directory.Packages.props, Lod.Core with its test project and one smoke test, scripts/verify.ps1, AGENTS.md "Commands" and "Project state" updated. Further projects are created by the stage that first needs them.
  10. feature/grasshopper-plugin-shell — Lod.Grasshopper plugin with assembly info and one BEMGen Info component (version, commit SHA); docs/development/grasshopper-smoke-test.md (how to load the plugin in Rhino 8 and what to check).

Exit criteria: scripts/verify.ps1 passes on a clean clone; the plugin loads in Rhino 8 and BEMGen Info shows the version; ADR-001 to ADR-005 and ADR-007 accepted.

S1 — Program presets and equivalence engine

Goal: the aggregation rules before any geometry exists: conservation of loads, scheduled loads, occupancy, and air volume flow proven by tests. Setpoint aggregation is a prescribed control rule, tested against its definition, not a conservation invariant.

Work slices:

  1. feature/core-common — ToleranceSettings, Result<T>, Diagnostic and DiagnosticCodes, ZoneId.
  2. feature/schedules-model — Schedule (immutable, validated length and kind), AggregationRecord.
  3. feature/loads-model — LoadType (Occupancy, Lighting, ElectricEquipment, GasEquipment, DomesticHotWater, Ventilation, Infiltration), LoadBasis (PerFloorArea, PerPerson, Absolute, PerExteriorWallArea, AirChangesPerHour), LoadDefinition.
  4. feature/programs-presets — SpaceType, Thermostat, ZoneProgram (conditioned with a thermostat, or unconditioned), ProgramPreset (space type, program, WWR), ProgramPresetSet, and ExampleResidentialPresets: illustrative round numbers for testing, with the stair unconditioned — NOT DOE prototype values. Sourcing DOE mid-rise apartment values is an open research input (§7). docs/research/program-presets.md documents both.
  5. feature/aggregation-engine — IEquivalentPropertyAggregator implementing ADR-005 and ADR-007. Every result records source IDs, method, and weights. Zero magnitude gives value 0 and a constant-zero schedule with a diagnostic.

Tests: validation of every type; seeded property tests for installed and hourly scheduled magnitude, occupancy, and air volume flow; single source returns itself (loads and setpoints); source order does not change the result; conditioning rules (unconditioned sources do not weigh setpoints, all-unconditioned gives an unconditioned target, façade-only sources do not condition a target); zero-load, zero-weight, invalid-measure edge cases.

Exit criteria: all tests pass; public types have XML docs; docs/architecture/domain-model.md written.

S2 — End-to-end pipeline skeleton

Goal: the whole pipeline runs in Grasshopper for the simplest case: presets → linear plan → no simplification → stacked floors → Convert2BEM, previewed at every step.

Work slices:

  1. feature/geometry-ops — Polygon2, PolygonOps over Clipper2, orientation bins (N/E/S/W), explicit Window (plus the centered placement rule).
  2. feature/plans-model — pipeline model types (surfaces with explicit windows, zones, provenance, plan/floor/building interfaces) and the layout surface builder.
  3. feature/generators-linear-plan — PlanGenerator base and LinearPlanGenerator: rectangular footprint, west stair, double-loaded corridor, one zone per dwelling unit (D-009); one centered window per outdoor wall from each zone's preset WWR (D-039, D-026); deterministic. Refined in S8 from the precedent study.
  4. feature/pipeline-no-simplification-stack — IPlanSimplifier, NoSimplification, IFloorAggregator, and Stack (ground at the bottom, roof at the top, interzone between storeys by polygon overlap).
  5. feature/grasshopper-pipeline-components — Goo and params; components Schedule, Load, Program Preset (with Conditioned), Example Residential Presets, Linear Plan Generator, No Simplification, Stack Floors, Inspect; preview on every object.
  6. feature/convert-bem-neutral — Convert2BEM (provisional, D-023): per zone Breps, name, space type, multiplier, conditioned flag, loads, schedules, setpoints, surfaces with boundaries, explicit windows, internal mass, as data trees. Documented in docs/architecture/convert2bem.md.

Tests: zones tile the plan; every outdoor wall of the rectangular generator has one centered window with area = WWR × wall area (valid only for this generator; see ADR-011 in S8); determinism; stacked boundary conditions; integration test presets → generator → NoSimplification → Stack; snapshots.

Manual check: the smoke-test checklist in Rhino 8, plus examples/grasshopper/pipeline-skeleton.gh saved by a person.

Exit criteria: the example definition runs from presets to Convert2BEM outputs, all previews show, and all tests pass.

S3 — Plan simplifiers and validation

Goal: the zoning LoDs, each proven to satisfy the prescribed conservation invariants. Zoning, heat transfer, controls, and window placement are deliberately approximated where the LoD says so; those differences are what the study measures.

Work slices:

  1. feature/mapping-overlap — OverlapMapper, TransferMatrix (fractions normalised per source), FacadeAttribution with coverage gaps (D-041), WindowRehosting (D-039).
  2. docs/decisions-perimeter-corner-rule — ADR-008 perimeter/core corners (bisector trapezoids).
  3. feature/simplifiers — shared pipeline (propose zones → surfaces → mapping → façade coverage check → window re-hosting → aggregation; partitions between merged sources disappear, D-034); SemanticMerge (Z1, by space type and adjacency), PerimeterCore (Z2), SingleZonePerFloor (Z3).
  4. feature/validation-invariants — floor and building validation: floor area, volume, exterior wall area, glazing total and per orientation, installed and hourly scheduled magnitude per load type, façade coverage, no overlap, source coverage, traceability (enforced); conditioned floor area (reported, D-038). Convert2BEM refuses invalid input unless an override is recorded.
  5. feature/grasshopper-simplifier-components — Semantic Merge, Perimeter Core, Single Zone per Floor, Map Source to Target, Validate; the validation gate in Convert2BEM.

Tests: mapping and façade attribution (including partial coverage); window re-hosting (positions kept, windows across two walls rejected); every simplifier passes every invariant for seeded random plans; validation catches a changed program and an uncovered façade; conditioned area reported when the unconditioned stair is merged; snapshots per simplifier.

Exit criteria: linear plan at Z0–Z3 validated, previewed, and converted.

S4 — Floor aggregators

Goal: the vertical LoDs; after this stage the pipeline is complete for the linear plan (Checkpoint 1).

Work slices:

  1. docs/decisions-vertical-aggregation — ADR-009 Vertical aggregation geometry. Gate: accepted before any S4 code. Records D-031 (slabs become internal mass in SingleZoneMerged), D-032 (floor types with multipliers), D-034 (partitions discarded), D-045 (representative storeys at their true elevations), and D-046 (exposed storeys split off as ×1, overlap between storeys adiabatic, floor types may differ in footprint).
  2. feature/aggregators — FloorAreaMultiplier (representative storey nearest the middle of the storeys it stands for; exposed storeys split off as ×1; overlap adiabatic, uncovered parts exposed) and SingleZoneMerged (one zone, one part per storey, walls rebuilt with windows kept in place and façade coverage checked, slabs as internal mass).
  3. feature/grasshopper-aggregator-components — Floor Area Multiplier, Single Zone Merged.

Tests: each aggregator conserves floor area, volume, exterior wall area, glazing, installed and hourly magnitudes, ground, roof, and exposed floor area, and building height against the fully stacked reference; exposed storeys of multiplied types are split off; setbacks and overhangs validate; every simplifier × aggregator combination validates; snapshots.

Exit criteria: every simplifier × aggregator combination for the linear plan validates and converts; docs/architecture/pipeline.md describes the complete pipeline; a full example definition is saved.

S5 — Centred windows on rebuilt walls

Goal: wherever zones are merged and walls are rebuilt (Semantic Merge, Perimeter Core, Single Zone per Floor, Single Zone per Floor Type, Single Zone Building), every outdoor wall of a target zone carries exactly one window, centred on it and shaped by the generator's rule (D-026), whose area is the total glazed area of the source windows that wall covers (D-079). Window level of detail is not a separate axis: the window levels W1–W5 are dropped. Steps that do not rebuild walls (No Simplification, Stack Floors, Stacked Floor Zone Multiplier) keep their input's windows.

Gate: ADR-012 Centred windows on rebuilt walls, accepted before any S5 code. It records the rule, where it applies, what is conserved (glazed area per wall, and so per façade, orientation, and building; not window positions), and the guards that hold by construction but still fail loudly: a source window not contained by one target wall (WindowNotHosted), a target wall whose glazed area is not smaller than its area (GlazingExceedsWall), never a cap or a silent move.

Work slices: ADR-012 and the research brief §10; CentredWindows in Lod.Core (attribution by WindowRehosting, shape by Window.Centered) used by the shared simplifier pipeline and by SingleZoneMerge; Grasshopper descriptions; documentation. No new components; GUIDs unchanged.

Tests: per target wall, one centred window whose area is the sum of the covered source windows, none on a wall without glazing; the guards; glazing per orientation unchanged; on the canonical and on rotated and moved plans; snapshots of merged zones change in window geometry only.

S6 — Convert2IDF

Goal: an EnergyPlus-ready IDF from IGeneratedBuilding (D-020).

Scope and plan: EnergyPlus 25.x, an envelope preset shared with Convert2BEM, ideal loads, and no simulation runs yet (D-112); realised as ADR-010 sets out and built from the S6 design note (D-111).

Work slices: ADR-010 for the scope (EnergyPlus version, ideal-loads HVAC, constructions and materials source, schedule representation, internal mass and zone multipliers, unconditioned zones); feature/convert-idf in Lod.Export as a pure C# text writer; a Convert2IDF component that writes the file, with the inputs EnableInternalWallHeatTransfer and EnableFloorHeatTransfer (both default False) from its first version, using the shared HeatTransferOptions and ExportedBoundary from S4.2 (D-069, D-077).

Tests: snapshot IDFs for each simplifier × aggregator combination of the canonical linear plan; object counts and references consistent. Running EnergyPlus is not required.

First slice (D-111): move the headless Rhino check from the controller's scratch folder into scripts/rhino-smoke/ (the harness, a run script that builds the plugin and starts Rhino 8 headless, and one spec per family or feature, with results written outside the repository), so every later stage runs it from the repository.

S7 — Precedent study (replaced, D-082)

S7 is not run in this repository. The precedent research was carried out in the separate repository typology-synthesizer on High-Density Housing (DETAIL) instead of Floor Plan Manual Housing (D-082, superseding D-011): nine typology families with topological rules, paraphrased in docs/research/precedents/hdhm-typologies.md. Its third slice, ADR-006, is written in S8.1. The original plan is kept below for reference.

Goal (original): base the generators on documented housing-design knowledge (D-011, D-015).

Source: Heckmann & Schneider, Floor Plan Manual Housing (heckmann-fpm). Further sources are decided later. Copies stay outside the repository; only paraphrases, page references, and short attributed quotes are committed.

Work slices:

  1. docs/research-precedent-index — docs/research/precedents/README.md (bibliography) and docs/research/precedents/heckmann-fpm.md: chapters and pages read; a rules table (rule, value/range, typology, page, confidence); figures referenced by page, never reproduced.
  2. docs/research-floor-plan-synthesis — docs/research/floor-plan-generation.md: typology taxonomy by access system; comparison of generation mechanisms; parameter catalogue; validity rules; per-typology algorithm with diagrams; window placement rules for detailed plans. Unit-internal layout is used only to size units, never to generate rooms (D-009).
  3. docs/decisions-generation-mechanism — ADR-006 Plan generation mechanism, with parameter record signatures for linear, point, and courtyard plans.

Exit criteria (original): the synthesis is reviewed and ADR-006 accepted.

S8 — Typologies (S8.1–S8.7, D-083, D-084, D-098)

Goal: one plan generator per High-Density Housing family HDHM-TYP-001 to HDHM-TYP-009 (D-083, S8.1–S8.3), and from S8.4 one per family of the four-source set SYN-TYP-010 to SYN-TYP-019 except 013 (D-093, D-096, D-098), each a PlanGenerator subclass with typed parameter and preset records (ADR-006), and a Grasshopper component per generator in panel 2 Generate. Dimensions and counts are design defaults recorded in ADR-006; the gallery of 002 is not modelled. Each sub-stage follows the S5 method (D-080): verified reference, headless Rhino check, plan, per-task execution, local merge and tag; nothing is pushed during the run.

Gate: ADR-006 and ADR-011 accepted before any S8 code. ADR-011 defines the minimum wall and window geometry (GeometryLimits): a generator's outdoor wall shorter than 1 m, or a window narrower or lower than 0.3 m, gets no window and the info WindowOmitted, never invalid geometry; rebuilt walls keep the centred-window rule of ADR-012; a window that would straddle target walls stays the error WindowNotHosted.

  • S8.1 Plan generation mechanism and bar typologies (v0.8.0). The precedent page, ADR-006 (all nine families specified), ADR-011 and its limits in the generator base; LinearPlanGenerator checked as HDHM-TYP-009 and kept; new generators Stair Bay Bar (001), Stair Pair (008, one bay of 001's layout), Gallery Bar (002, gallery omitted), and Terrace Row (006, one dwelling zone per plot and storey).
  • S8.2 Non-rectangular typologies without holes (v0.8.1). Point Plate (007), Winged Band (003), Open Court (004); short façade fragments under ADR-011. Their rotated plans showed that Semantic Merge and the unions of tiles must unite zones exactly; the fixes also repair rotated linear and bar plans released up to v0.8.0 (D-088). Perimeter Core states its precondition, that every part of a footprint be wider than twice the perimeter depth (D-087).
  • S8.3 Enclosed courtyard (v0.8.2). Enclosed Court (005): footprints with holes supported by every plan simplifier (perimeter/core included) and floor aggregator. The court is outside the building: its edges are outdoor walls, and the surface builder requires every footprint edge, court edges included, to be covered by outdoor zone edges; Perimeter Core zones the court façades separately (P-Court-<Bin>), and its width precondition applies to the wings between the outer and the court façades (D-087). The headless Rhino check of the reference found the Convert2BEM zone solids inward-oriented and the floors facing up on every plan released up to v0.8.1; S8.3 applies the orientation rule of D-091.
  • S8.4 Non-residential programs, office plate and cafeteria (v0.8.3). The four-source records pinned (D-093, syn-typologies.md); the scope of D-094 in the research brief, spec, README, AGENTS.md, and this roadmap; ADR-014 (the non-residential space types, one typed illustrative preset each, and the departments of every new family, D-097); ADR-006 extended to all nine new families; the default preset components of the new space types; Office Plate (SYN-TYP-017, a core inside one ring-shaped work-area zone) and Cafeteria (SYN-TYP-016, a kitchen and servery edge beside the dining field).
  • S8.5 Branching plans (v0.8.4). A shared hub-and-arms layout for Radial Lobes (010), Branching Mall (014), Care Hub (018), and Foyer Halls (019).
  • S8.6 Operating suite and court clusters (v0.8.5). Operating Suite (015, separate clean and dirty corridors) and Court Cluster (011, a footprint with several courts).
  • S8.7 Plans per storey (v0.8.6). A plan generator that returns one plan per storey (D-095, with its ADR: the interface, how the four floor aggregators treat storeys that differ, and how a terrace is designated) and Stepped Band (012).

Tests (every sub-stage): per generator, zones tile the footprint, every outdoor wall above the ADR-011 minimum has one centred window sized by its preset, zone IDs, determinism, invalid parameters, and a canonical snapshot; every generator × simplifier × aggregator combination validates, also on a plan rotated and moved by Transform Plan.

S9 — Release (D-115)

Status: Done (D-116), version 1.0.0.

Scope: a local MkDocs docs site with a user part (getting started, concepts, workflow guide, one end-to-end example, typologies, a component reference generated from the plugin with icons and screenshots) clearly separated from a developer part (architecture, ADRs, decision log, assembled from docs/ at build time); a sync-docs project skill; one example .gh definition per typology built by the headless harness; a local Yak package build; an MIT license; version 1.0.0. The Grasshopper polish first planned here was done in S4.1, S8.8, and along the way. Built from the S9 design note (D-111).

Exit criteria: a new user can follow the site from presets to Convert2BEM and Convert2IDF for each typology; mkdocs build --strict passes; the examples open and solve; the Yak package builds; v1.0.0 tagged.


5. Cross-cutting practices

  • Test-first for everything in Lod.Core, Lod.Generators, and Lod.Export. Components stay thin enough that the manual smoke test covers them.
  • Snapshots are small, human-readable text; changing one requires a commit that explains why the output changed.
  • Research rules (aggregation, setpoints, conditioning, window rules) change only together with docs/research/ and a decision-log entry.
  • .gh example files are built, saved, and reopened by the headless harness (D-115); a person opens them in Rhino 8 to check the canvas and the viewport.
  • Agents follow AGENTS.md; a stage's design note names the parts built in parallel and the files each touches, so parallel worktrees do not collide (D-111).

6. Risks

Risk Impact Mitigation
ClimateStudio's real input format differs from the neutral Convert2BEM output Rework of the converter Converter isolated behind IGeneratedBuilding; neutral output documented; revisit D-023 as soon as a reference definition exists
netstandard2.0 limits modern C# features Friction in core code Polyfills (IsExternalInit); multi-target later if needed (ADR-001)
Polygon precision in overlaps Spurious conservation failures Clipper2 PathsD with fixed precision; tolerances in ToleranceSettings; tests at realistic building scales
Rounding on the clipping grid on rotated plans A very small zone of a rotated plan can fail validation (for example SourceCoverage) although its quantities are conserved Tolerances stay central and are never widened (ADR-004); zones are united as tiles that keep their sources' vertices, and vertices on edges are tested at their original positions (S8.2, D-088); every family's defaults validate at the tested placements; a remaining failure is reported, not repaired, and needs its own decision (D-090: zones about 1 m wide)
No CI Broken main scripts/verify.ps1 before every merge; linear history makes bisecting easy
Grasshopper code cannot be unit tested without Rhino Component regressions Thin components; smoke-test checklist per stage
Future zoning strategies split a source window between target walls Simplification fails with WindowNotHosted Deliberate: no silent moves; ADR-011 (S8.1) keeps WindowNotHosted as an error: a strategy must cut façades at source wall ends; the centred-window rule (S5, D-079) needs every source window on one target wall
Illustrative presets mistaken for sourced values Results not representative Presets are named Example…, labelled in code and docs; sourced presets are an open research input (§7)
Copyrighted reference books Licence Copies never committed; paraphrase with page references only

7. Open points

Resolved: the plan generation mechanism (ADR-006) and minimum wall and window geometry (ADR-011), S8.1; the window parameter is WWR (D-026); conditioning from presets with "any conditioned wins" (D-038); explicit windows (D-039); one centred window per rebuilt wall with the wall's glazed area, no window-LoD stage (D-079, ADR-012); façade coverage enforced (D-041); representative storeys at true elevations and automatic split of exposed storeys (D-045, D-046, superseding D-040); loads per type and basis (D-047).

Deferred, with gates in the stage that needs them:

  1. ADR-009 vertical aggregation geometry — before S4.
  2. ADR-012 centred windows on rebuilt walls — before S5 (D-079).
  3. ADR-011 minimum wall and window geometry — before S8 (written in S8.1).
  4. Sourced program presets (DOE mid-rise apartment loads, schedules, and conditioning, with citations) — a research input from the researcher; the example presets stay illustrative until then. Check that every sourced load maps onto a LoadBasis (D-047 allows several bases per load type, but a basis the model lacks, e.g. flow per total exterior surface area including roofs, needs a decision first).

The 2026-10-28 stage-three continuation (D-179/ADR-030) strengthens the opt-in floor research gate with normalized spatial program signatures and configured hourly heat partitions and adds generic explicit source/derived air/boundary ledgers. These APIs and conceptual fixtures do not establish populated authenticated DOE ledgers, exact composition or vertical equivalence. Production behavior and tolerances remain unchanged; no annual simulations or publication.