{
  "contract_version": "0.2.1",
  "csv_format_version": "unversioned-current",
  "merge_precedence": "General precedence is CSV columns > extra_json > defaults profile. Some sections use handler-specific merge rules.",
  "terminology": {
    "dwelling_calculation_input_json": "The merged JSON HEM:FHS runs on after CSV conversion—sometimes called the dwelling model input or batch JSON in older docs.",
    "geometry_to_model_conversion": "CSV + defaults_template (and overlays) → dwelling_calculation_input_json; includes phrases like “CSV merge” or “geometry import”.",
    "populating_the_csv": "Filling cells in the CSV.",
    "section_accepted_rows_ignored_for_model": "Section header is accepted but rows are not merged into the dwelling model."
  },
  "versioning": {
    "recent_contract_updates": "0.2.1: Documented Water Pipework primary vs distribution, multi-segment primary_pipework, tank-shaped HWS clone behaviour, and MVHR ductwork multi-row append; clarified extra_json for WaterPipework rows.",
    "contract_version_semantics": "Semantic version of this JSON document (inventory, notes, documented merge semantics). Integrators should pin tooling and validators to it.",
    "csv_format_version_semantics": "The CSV row/column layout does not yet use its own semver; unversioned-current means behaviour follows this contract_version and the engine release you run against.",
    "recommended_future_csv_marker": "Once stable, add an optional Metadata row such as ContractVersion,0.2.0 so files self-identify; until then there is no automatic parser gate on layout mismatch.",
    "breaking_changes": "Bump contract_version when documented column or section semantics change in ways validators should catch. Undocumented code-only changes are drift\u2014report discrepancies."
  },
  "error_codes": {
    "implementation_sources": {
      "geometry_csv_parser": "CSV parsing stage (subsystem label PARSER_* errors).",
      "geometry_to_model_builder": "Geometry-to-dwelling conversion (subsystem label BUILDER_* errors)."
    },
    "numeric_codes_not_globally_unique": "The same numeric label (for example E001) can mean different failures in the CSV parsing stage (PARSER_*) versus conversion (BUILDER_*); always use subsystem prefix plus message text.",
    "builder_codes_recycled_within_file": "The conversion step reuses several numeric codes (notably E027\u2013E033, E038\u2013E040) for unrelated failures\u2014rely on the full error message, not the code alone.",
    "geometry_csv_parser": {
      "E001": {
        "meaning": "Unknown section name (not in parser allowed list)."
      },
      "E002": {
        "meaning": "Duplicate section header in the same file."
      },
      "E003": {
        "meaning": "Data row appears before the first section header."
      },
      "E004": {
        "meaning": "Row has more columns than the section header with non-empty trailing cells (data would be truncated)."
      },
      "E006": {
        "meaning": "Required column missing for this section (does not satisfy parser-required headers for the section)."
      },
      "E007": {
        "meaning": "Duplicate Name within the same section."
      },
      "E008": {
        "meaning": "Zone column references a zone name that is not defined on any prior Zone row (forward reference)."
      },
      "E009": {
        "meaning": "Ventilation Systems row with Type MechanicalVentilation has vent_type outside the allowed enum."
      }
    },
    "geometry_to_model_builder": {
      "E001": {
        "meaning": "Schema JSON file path does not exist."
      },
      "E002": {
        "meaning": "Failed to read schema file from disk."
      },
      "E003": {
        "meaning": "Schema file is not valid JSON."
      },
      "E004": {
        "meaning": "Defaults JSON file path does not exist."
      },
      "E005": {
        "meaning": "Failed to read defaults file from disk."
      },
      "E006": {
        "meaning": "Defaults file is not valid JSON."
      },
      "E007": {
        "meaning": "Zone section row missing required Name."
      },
      "E008": {
        "meaning": "Fabric element row (Exposed/Window/Ground/Non-Exposed) missing Name."
      },
      "E009": {
        "meaning": "Fabric element row missing Zone."
      },
      "E010": {
        "meaning": "Fabric element row missing Type."
      },
      "E011": {
        "meaning": "Fabric element references a zone not present in merged Zone map."
      },
      "E012": {
        "meaning": "Thermal Bridging Elements row missing Name."
      },
      "E013": {
        "meaning": "Thermal Bridging Elements row missing Zone."
      },
      "E014": {
        "meaning": "Thermal Bridging Elements row missing Type."
      },
      "E015": {
        "meaning": "Thermal bridging references an undefined zone."
      },
      "E016": {
        "meaning": "Lighting row missing Zone."
      },
      "E017": {
        "meaning": "Lighting references an undefined zone."
      },
      "E018": {
        "meaning": "Appliances row missing appliancekey."
      },
      "E019": {
        "meaning": "Hot Water Outlets row missing Name."
      },
      "E020": {
        "meaning": "Hot Water Outlets row missing subcategory, or Ventilation Systems row missing Name (code reused)."
      },
      "E021": {
        "meaning": "Hot Water Outlets row missing Type, or Ventilation Systems row missing Type, or related ventilation merge validation (code reused\u2014read message)."
      },
      "E023": {
        "meaning": "Combustion Appliances row missing Name."
      },
      "E024": {
        "meaning": "Wet Emitters row missing Zone."
      },
      "E025": {
        "meaning": "Wet Emitters row missing subcategory, or JSON Schema compilation failure (code reused\u2014read message)."
      },
      "E026": {
        "meaning": "Merge/build structural errors not covered by per-row codes (e.g. merged root not an object, invalid SpaceHeatSystem FanCoil n_units). Read message."
      },
      "E027": {
        "meaning": "Generic missing-field or missing-default-fragment error used in many branches (read message)."
      },
      "E028": {
        "meaning": "Unknown thermal bridge Type, or no zones in CSV when consolidation requires them (code reused\u2014read message)."
      },
      "E029": {
        "meaning": "Window Shading missing Zone, or JSON shape not an object when expected (code reused\u2014read message)."
      },
      "E030": {
        "meaning": "Window Shading missing linked_window, or OnSiteGeneration not an object (code reused\u2014read message)."
      },
      "E031": {
        "meaning": "Window shading references undefined zone, or Lighting/count validation, or On-Site Generation missing Name, or zone rename failure (code reused\u2014read message)."
      },
      "E032": {
        "meaning": "Linked window not found in zone, or invalid numeric parse in leaks path, or On-Site Generation missing generation_type (code reused\u2014read message)."
      },
      "E033": {
        "meaning": "Invalid numeric conversion for leaks metadata, or unsupported On-Site Generation generation_type (code reused\u2014read message)."
      },
      "E034": {
        "meaning": "Expected JSON object at merge root or branch (code reused\u2014read message)."
      },
      "E035": {
        "meaning": "Systems row missing Type/system_type/subcategory discriminator."
      },
      "E036": {
        "meaning": "EnergySupply exists but is not a JSON object."
      },
      "E037": {
        "meaning": "Named EnergySupply entry is not a JSON object."
      },
      "E038": {
        "meaning": "EnergySupply aggregate not an object, or SpaceHeatSystem row missing Name (code reused\u2014read message)."
      },
      "E039": {
        "meaning": "SpaceHeatSystem container is not a JSON object."
      },
      "E040": {
        "meaning": "MechanicalVentilation missing required schema field, ductwork on non-MVHR, or Systems element missing Name (code reused\u2014read message)."
      },
      "E041": {
        "meaning": "HeatSourceWet merge target is not a JSON object."
      },
      "E042": {
        "meaning": "HotWaterSource merge target is not a JSON object, or intermediate JSON not an object (code reused\u2014read message)."
      },
      "E043": {
        "meaning": "SpaceCoolSystem merge target is not a JSON object."
      },
      "E044": {
        "meaning": "Wet Emitters in FHS mode require an explicit HeatSourceWet Systems row."
      },
      "E045": {
        "meaning": "Defaults template missing WetDistribution SpaceHeatSystem template when Wet Emitters need it."
      },
      "E046": {
        "meaning": "Merged JSON failed JSON Schema validation against input_fhs.schema.json (post-merge). Each row lists jsonschema message and instance path; read message."
      },
      "E999": {
        "meaning": "Filesystem or serialization failure writing batch outputs (not a CSV shape error)."
      }
    }
  },
  "section_requirements_summary": {
    "parser_recognized_section_headers": [
      "Metadata",
      "Exposed Elements",
      "Window Elements",
      "Ground Elements",
      "Non-Exposed Elements",
      "Thermal Bridging Elements",
      "Zone",
      "Window Shading",
      "Lighting",
      "Ventilation Systems",
      "Combustion Appliances",
      "Water Pipework",
      "Wet Emitters",
      "Appliances",
      "Hot Water Outlets",
      "Context Shading",
      "On-Site Generation",
      "Systems",
      "Test Section"
    ],
    "sections_documented_in_csv_contract": "Every importer section title except Test Section is documented under csv_contract.sections; Test Section is test-only.",
    "minimal_integrator_csv": "Include Metadata as needed, at least one Zone row with Name, and the fabric/system sections your dwelling needs. Skip sections only if your defaults_template already supplies a complete dwelling_calculation_input_json for your workflow\u2014otherwise conversion fails or the model is incomplete.",
    "parser_required_column_headers": "Non-empty rows must include every header that section requires (see that section’s authoring_requirements in this contract)."
  },
  "systems_dispatch": {
    "plain_language": [
      "Read Type, then if empty read system_type, then if empty read subcategory\u2014the first non-empty value routes the Systems row.",
      "Contract row_kinds map Type values to payload_contract and target_path for nested FHS fragments.",
      "For PCDB-style inner payloads chosen by subcategory, the outer row must still route as System; otherwise the row may be skipped without a parser error.",
      "ElectricBattery nests under EnergySupply.<extra_json.EnergySupply or mains elec>.ElectricBattery."
    ],
    "mermaid_flowchart": "flowchart TD\n  R[System CSV row] --> D{First non-empty among Type, system_type, subcategory}\n  D -->|ElectricBattery| EB[Merge into EnergySupply named in extra_json]\n  D -->|SpaceHeatSystem / WetDistribution| SHS[SpaceHeatSystem wet distribution branch]\n  D -->|HeatSourceWet / HotWaterSource / \u2026| WK[Use row_kinds + fields_by_type from contract]\n  D -->|unknown / unroutable| SK[May be skipped silently depending on branch]"
  },
  "notes": {
    "csv_format_version": "csv_format_version stays unversioned until an optional in-file marker is implemented; there is no automatic parser gate on mismatch.",
    "test_section": "Parser accepts header 'Test Section' for harness use; conversion ignores it. It is not documented under csv_contract.sections."
  },
  "defaults_profiles": [
    {
      "id": "defaults-template",
      "description": "Canonical defaults template used by the geometry-to-model conversion step.",
      "defaults_path": "input/defaults/defaults_template.json",
      "sha256": "c1ee4bb476eac24a2ea5845b93dad4de4b540114de879686d5f81bc5c60b9756",
      "public_reference_urls": {
        "geometry_csv_contract_docs": "https://api.usevulcan.app/docs/geometry-csv",
        "defaults_template_download": "https://api.usevulcan.app/base_json/defaults_template.json",
        "fetching_defaults_bytes": "Published at defaults_template_download; canonical workspace path is input/defaults/defaults_template.json (legacy input/batch_parameters/base_json/ still resolved at read time). Packaged copy: resources/sample_project/batch_parameters/base_json/ after scripts/update_sample_project.sh. Also apps/web/public/launch/base_json/ in the main app bundle. Verify with sha256 above."
      }
    }
  ],
  "csv_contract": {
    "schema_source": {
      "mode": "fhs",
      "path": "hem_fhs_upstream/schema/input_fhs.schema.json",
      "repository_url": "https://github.com/communitiesuk/epb-hem-wrapper-fhs",
      "repository_name": "communitiesuk/epb-hem-wrapper-fhs",
      "wrapper_version": "1.0.0a7",
      "wrapper_version_status": "alpha_prerelease",
      "schema_surface_stability": "The pinned git_commit is authoritative for the schema snapshot; wrapper_version is an upstream prerelease label\u2014the public field surface may still change with wrapper bumps even when this contract_version is unchanged.",
      "git_commit": "cc22d8ff6e6add3134b11da7e3bb8901393c3a3b",
      "git_commit_short": "cc22d8f"
    },
    "authoring_model": {
      "geometry_to_model_conversion_is_authoritative": true,
      "parser_required_columns_mean": "Minimum column headers each non-empty row must include for that section (listed under that section in this contract).",
      "conversion_required_fields_mean": "Values conversion needs after parsing succeeds (may exceed parser-required headers).",
      "csv_column_required_mean": "When true, a serious integrator should supply the cell for a complete model: defaults_template does not invent missing geometry coordinates or fabric rows.",
      "required_in_section_header_mean": "Strict checker: the header row must name this column before non-empty data rows validate. Empty cells under that header are allowed and become JSON null.",
      "definitions": {
        "parser_required_columns": {
          "what": "Headers the parser enforces for non-empty rows in a section.",
          "source_of_truth": "Per-section authoring_requirements.parser_required_columns in this contract"
        },
        "conversion_required_fields": {
          "what": "Cells or JSON fragments conversion refuses to synthesize when missing.",
          "note": "Differs from parser-required headers when conversion reads extra_json or defaults first."
        },
        "csv_column_required": {
          "what": "Integrator should treat the cell as mandatory for a geometry-complete dwelling.",
          "why": "defaults_template does not backfill missing geometry."
        },
        "required_in_section_header": {
          "what": "Strict layout checker insists the header mentions this column.",
          "empty_cells": "Still allowed under that header; they deserialize to null."
        }
      },
      "integrator_column_axes": {
        "purpose": "Each metadata key and documented csv_column uses populate_requirement and merge_effect; optional column_hints carries shading/UI import details.",
        "populate_requirement_axis": "Enum on populate_requirement; see populate_requirement_definitions.",
        "merge_effect_axis": "Enum on merge_effect; see merge_effect_definitions."
      },
      "populate_requirement_mean": "What integrators should supply in the cell: required_accurate | required_conditional | optional_default_or_derived | optional_plot. See populate_requirement_definitions.",
      "merge_effect_mean": "What happens at geometry-to-model merge: affects_calculation_input | not_in_calculation_input | workflow_only | csv_or_ui_round_trip | section_rows_not_merged (section-level). See merge_effect_definitions."
    },
    "merge_mode_glossary": {
      "attach_to_existing_window_in_zone": {
        "short_label": "window_attach",
        "meaning": "Attach shading payload to an existing window element in the named zone."
      },
      "select_defaults_template_by_vent_type_then_overlay_csv_then_extra_json": {
        "short_label": "vent_type_template_overlay",
        "meaning": "Pick MechanicalVentilation defaults by vent_type, then overlay CSV columns, then extra_json."
      },
      "append_to_parent_mechanical_ventilation_ductwork_array": {
        "short_label": "mv_ductwork_append",
        "meaning": "For each MechanicalVentilationDuctwork row whose parent_element matches a Mechanical Ventilation row Name, build one object and append it in CSV iteration order to that parent\u2019s ductwork array. parent_element must be MVHR if ductwork is non-empty; otherwise conversion may fail (E040)."
      },
      "append_water_pipework_rows_to_model": {
        "short_label": "hws_primary_hwd_dist",
        "meaning": "Split Water Pipework rows by pipework_type: primary\u2192each object appended in order to primary_pipework[]; other values (including missing/empty) \u2192distribution, each object appended in order to HotWaterDemand.Distribution. Seeds each new segment from the first defaults-backed segment in defaults_template when present."
      },
      "replicate_primary_pipework_across_tank_shaped_hws": {
        "short_label": "hws_primary_clone",
        "meaning": "After building the primary array, conversion writes the same JSON array on every HotWaterSource entry whose type is StorageTank or the legacy `hw cylinder` value. CombiBoiler entries are not written from this section."
      },
      "seed_from_first_defaults_template_then_overlay_csv_then_extra_json": {
        "short_label": "first_template_overlay",
        "meaning": "Seed from first defaults template row, then overlay CSV then extra_json."
      },
      "merge_into_defaults_backed_root_section": {
        "short_label": "root_section_overlay",
        "meaning": "Merge into a defaults-backed root object (for example InfiltrationVentilation)."
      },
      "aggregate_rows_by_zone_and_subcategory_then_replace_existing_wet_distribution_systems": {
        "short_label": "wet_emitters_aggregate",
        "meaning": "Group Wet Emitters rows, rebuild wet distribution systems from aggregates."
      },
      "merge_into_existing_defaults_backed_hot_water_demand": {
        "short_label": "hwd_merge",
        "meaning": "Overlay HotWaterDemand fragments from defaults-backed structure."
      },
      "replace_whole_section_when_wrapped_or_insert_named_entry_when_flat": {
        "short_label": "wrapped_or_flat_replace",
        "meaning": "If extra_json uses wrapper key, replace whole section; else insert/update named entry."
      },
      "merge_wrapped_fragment_into_root_section": {
        "short_label": "wrapped_fragment_merge",
        "meaning": "Merge wrapped extra_json fragment into a top-level schema section."
      },
      "replace_whole_section_when_wrapped_or_insert_named_entry_when_flat_then_reconcile_zone_references": {
        "short_label": "wrapped_or_flat_replace_zone_fixup",
        "meaning": "Same as wrapped_or_flat_replace plus zone reference reconciliation."
      },
      "merge_wrapped_fragment_into_root_section_or_seed_named_wet_distribution": {
        "short_label": "wrapped_merge_or_wet_seed",
        "meaning": "Merge wrapped fragment or seed named wet distribution entry."
      },
      "branch_specific_by_Type_system_type_and_subcategory": {
        "short_label": "systems_branch_dispatch",
        "meaning": "Systems section: route row by Type/system_type/subcategory-specific handlers (see systems_dispatch)."
      },
      "merge_zone_rows_into_root_zone_map": {
        "short_label": "zone_root_map",
        "meaning": "Zone rows create or update each `Zone.<zone name>` object at the dwelling JSON root before fabric and system merges."
      },
      "merge_building_element_rows_under_zone": {
        "short_label": "zone_building_element",
        "meaning": "Rows merge under `Zone.<Zone>.BuildingElement.<Name>` on the schema branch for each row Type (opaque surfaces, glazing, ground-contact slabs). The Zone column selects the parent zone; Name keys the element."
      },
      "merge_thermal_bridge_rows_into_zone_thermal_bridging": {
        "short_label": "zone_thermal_bridging",
        "meaning": "Rows merge into `Zone.<Zone>.ThermalBridging.<Name>` (skipped for zones where simplified thermal bridging applies)."
      },
      "merge_lighting_rows_into_zone_lighting": {
        "short_label": "zone_lighting",
        "meaning": "Lighting rows populate the `Lighting` object on each referenced zone (counts, efficacy, power)."
      },
      "merge_context_shading_into_external_conditions_segments": {
        "short_label": "external_shading_segments",
        "meaning": "Rows contribute obstacle shading geometry into `ExternalConditions.shading_segments` (10\u00b0 horizon buckets)."
      },
      "merge_onsite_generation_named_entries": {
        "short_label": "root_onsite_generation",
        "meaning": "Rows become named entries under root `OnSiteGeneration` (currently PhotovoltaicSystem payloads)."
      }
    },
    "default_layout": {
      "shape": "section_header_row_then_column_header_row_then_data_rows",
      "delimiter": ",",
      "quoting": "double-quote escaping supported"
    },
    "section_layout_overrides": {
      "Metadata": {
        "notes": "Metadata values are interpreted as key/value-style rows by conversion logic using known metadata field names."
      },
      "Systems": {
        "notes": [
          "Outer routing: read Type, then system_type, then subcategory (first non-empty wins).",
          "PCDB-style inner payloads are selected from subcategory, but the outer row must still route as System so Systems routing runs.",
          "If the outer discriminator does not match any branch, the row may be skipped without a parser error."
        ]
      }
    },
    "field_contracts": {
      "metadata_value_row": {
        "kind": "key_value_row",
        "field_name_position": 0,
        "value_position": 1,
        "trailing_padding_columns_ignored": true
      },
      "coords_path_3d": {
        "kind": "csv_encoded_coords",
        "value_type": "string",
        "format": "x,y,z|x,y,z|...",
        "parser_default_when_missing": "0,0,0",
        "export_precision_decimal_places": 3,
        "authoring_note": "x,y locate element in plan. z is typically floor-relative height for most elements; for Thermal Bridging use physical z metres with floor_id where supplied."
      },
      "coords_polygon_3d": {
        "kind": "csv_encoded_coords",
        "value_type": "string",
        "format": "x,y,z|x,y,z|x,y,z...",
        "minimum_points": 3,
        "parser_default_when_missing": "0,0,0",
        "export_precision_decimal_places": 3,
        "authoring_note": "x,y define footprint vertices. z is typically floor-relative height for most elements."
      },
      "assembly_library_id": {
        "kind": "string_identifier",
        "domain": "assembly_library",
        "source": "creationDefaultAssemblyIds metadata"
      },
      "appliance_key_enum": {
        "kind": "enum",
        "values": [
          "Clothes_washing",
          "Clothes_drying",
          "Dishwasher",
          "Fridge",
          "Fridge-Freezer",
          "Freezer",
          "Hobs",
          "Otherdevices",
          "Oven"
        ]
      },
      "schema_profile": {
        "kind": "enum",
        "values": [
          "input_fhs",
          "ecaas_input_fhs"
        ]
      },
      "linked_window_reference": {
        "kind": "string_reference",
        "targets_section": "Window Elements",
        "match_rule": "matches window Name within the same Zone"
      },
      "ground_floor_type": {
        "kind": "enum",
        "values": [
          "Heated_basement",
          "Slab_edge_insulation",
          "Slab_no_edge_insulation",
          "Suspended_floor",
          "Unheated_basement"
        ],
        "schema_mode": "fhs"
      },
      "thermal_bridge_junction_type": {
        "kind": "string",
        "location": "extra_json.junction_type",
        "applies_to": [
          "ThermalBridgeLinear"
        ],
        "used_when_present_in_dwelling_model_merge": true,
        "dwelling_model_merge_top_level_column": true
      },
      "thermal_bridge_floor_id": {
        "kind": "integer",
        "minimum": 0,
        "location": "extra_json.floor_id",
        "authoring_note": "Canvas storey index (0 = ground, 1 = first, …), same as the floor toolbar integer. Legacy CSV may still use a string Floor.id; importers map that to storey on load.",
        "applies_to": [
          "ThermalBridgeLinear"
        ],
        "used_by_ui_canvas_floor_grouping": true,
        "used_in_dwelling_model_merge": false
      },
      "zone_volume": {
        "type": "number",
        "minimum": 0,
        "maximum": 50000
      },
      "zone_livingroom_area": {
        "type": "number",
        "minimum": 0,
        "maximum": 10000
      },
      "zone_restofdwelling_area": {
        "type": "number",
        "minimum": 0,
        "maximum": 10000
      }
    },
    "validation_rules": {
      "unique_sections": true,
      "unique_name_within_section": true,
      "zone_reference_must_exist": true,
      "zone_definition_must_precede_references": true,
      "ventilation_mechanical_vent_type_allowed_values": [
        "Intermittent MEV",
        "Centralised continuous MEV",
        "Decentralised continuous MEV",
        "MVHR"
      ]
    },
    "postprocess_rules": {
      "fhs": {
        "single_zone_consolidation": {
          "keeps": "first_built_zone",
          "merges_remaining_zones": true,
          "rewrites_zone_linked_output_paths": true
        }
      }
    },
    "sections": {
      "Metadata": {
        "description": "Project-wide settings rows (Key, Value): schema profile, defaults file paths, compliance inputs, and editor/workflow flags that the conversion step reads before merging geometry into the dwelling JSON.",
        "notes": "The Metadata keys table lists every key. In generated docs, Outside merged model matches merge_effect values other than affects_calculation_input (including workflow_only for editor/tooling keys and not_in_calculation_input for paths and canvas-only values); those keys are not merged into dwelling_calculation_input_json as ordinary dwelling fabric/system inputs. Keys with affects_calculation_input participate where each authoring_note describes. Per-key merge_effect and populate_requirement in this contract are authoritative.",
        "metadata_keys": [
          {
            "key": "SchemaProfile",
            "source_group": "workflow_only_keys",
            "field_contract_ref": "#/csv_contract/field_contracts/schema_profile",
            "authoring_note": "Documented for tooling; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "DefaultAssemblyWall",
            "source_group": "workflow_only_keys",
            "field_contract_ref": "#/csv_contract/field_contracts/assembly_library_id",
            "authoring_note": "Documented for tooling; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "DefaultAssemblyRoof",
            "source_group": "workflow_only_keys",
            "field_contract_ref": "#/csv_contract/field_contracts/assembly_library_id",
            "authoring_note": "Documented for tooling; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "DefaultAssemblyGroundFloor",
            "source_group": "workflow_only_keys",
            "field_contract_ref": "#/csv_contract/field_contracts/assembly_library_id",
            "authoring_note": "Documented for tooling; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "SapDir",
            "source_group": "workflow_only_keys",
            "authoring_note": "SAP workflow path; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "SapPdfPath",
            "source_group": "workflow_only_keys",
            "authoring_note": "SAP workflow path; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "SapXmlPath",
            "source_group": "workflow_only_keys",
            "authoring_note": "SAP workflow path; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "GuideOverlay",
            "source_group": "workflow_only_keys",
            "authoring_note": "UI/guide workflow; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "JunctionPsiDefaultsPath",
            "source_group": "workflow_only_keys",
            "authoring_note": "Thermal-bridge tooling path; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "ComplianceValidationEnabled",
            "source_group": "workflow_only_keys",
            "authoring_note": "Pipeline flag for surrounding validation; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "ScenariosBaseModelEnabled",
            "source_group": "workflow_only_keys",
            "authoring_note": "When FALSE, the merged base JSON is hidden from the Scenarios tab base-model picker. Set by the app from strict FHS/ECaaS merge outcome; may be hand-edited.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "DefaultsPath",
            "source_group": "path_keys",
            "authoring_note": "Authoring convenience; compliance merge skips this key. Defaults file is supplied by the caller, not overwritten from merged CSV metadata.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "AirPermeability_env_area",
            "source_group": "calculated_or_ignored_keys",
            "authoring_note": "Calculated in leaks path; not authored for merge as this key.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "GlobalOrientationOffset",
            "source_group": "number_keys_parsed_but_not_merged_into_batch_json",
            "plotting_note": "Workflow/editor setting; parsed but not merged into dwelling_calculation_input_json.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot",
            "authoring_note": "Applies a UI/canvas rotation offset for authored geometry interpretation. Existing coords/orientation values are interpreted in the rotated frame; changing this after authoring can visually rotate the project if geometry/orientations are not adjusted together."
          },
          {
            "key": "DefaultThermalBridging",
            "source_group": "non_negative_number_keys",
            "authoring_note": "Parsed early and affects the merged model via internal thermal-bridging defaults (e.g. zone behaviour); not a direct root property from this metadata row in the same way as counts.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "key": "NumberOfBedrooms",
            "source_group": "integer_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. If the cell is empty and defaults_template already defines the key, conversion keeps the default; if both are absent, the model is incomplete\u2014populate explicit integers for standalone CSV-first workflows.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "NumberOfWetRooms",
            "source_group": "integer_keys",
            "authoring_note": "Same merge rule as NumberOfBedrooms.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "NumberOfHabitableRooms",
            "source_group": "integer_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. Same merge rule as NumberOfBedrooms.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "NumberOfHotTappedRooms",
            "source_group": "integer_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. Same merge rule as NumberOfBedrooms.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "NumberOfUtilityRooms",
            "source_group": "integer_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. Same merge rule as NumberOfBedrooms.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "NumberOfBathrooms",
            "source_group": "integer_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. Same merge rule as NumberOfBedrooms.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "NumberOfSanitaryAccommodations",
            "source_group": "integer_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. Same merge rule as NumberOfBedrooms.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "GroundFloorArea",
            "source_group": "non_negative_number_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. If empty and defaults_template supplies GroundFloorArea, that value wins; otherwise populate an explicit area for CSV-first workflows.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "BuildingLength",
            "source_group": "non_negative_number_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "BuildingWidth",
            "source_group": "non_negative_number_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "PartO_active_cooling_required",
            "source_group": "boolean_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root. If defaults_template always sets this flag, you may classify the column as optional_default_or_derived; otherwise populate explicitly.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "PartGcompliance",
            "source_group": "boolean_keys",
            "authoring_note": "Same merge rule as PartO_active_cooling_required.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "Ventilation_noise_nuisance",
            "source_group": "boolean_keys",
            "authoring_note": "Merged into InfiltrationVentilation.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "KitchenExtractorHoodExternal",
            "source_group": "boolean_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "HeatingControlType",
            "source_group": "enum_keys",
            "authoring_note": "Merged to dwelling_calculation_input_json root as enumerated string.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "AirPermeability_test_pressure",
            "source_group": "enum_keys",
            "authoring_note": "Merged under InfiltrationVentilation.Leaks with prefix stripped.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "AirPermeability_test_result",
            "source_group": "number_keys",
            "authoring_note": "Merged under InfiltrationVentilation.Leaks.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "AirPermeability_ventilation_zone_height",
            "source_group": "number_keys",
            "authoring_note": "Merged under InfiltrationVentilation.Leaks.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "Ventilation_shield_class",
            "source_group": "enum_keys",
            "authoring_note": "Merged into InfiltrationVentilation.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "Ventilation_terrain_class",
            "source_group": "enum_keys",
            "authoring_note": "Merged into InfiltrationVentilation.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "Ventilation_altitude",
            "source_group": "number_keys",
            "authoring_note": "Merged into InfiltrationVentilation as numeric.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "Location",
            "source_group": "builder_known_field",
            "authoring_note": "Merged to dwelling_calculation_input_json root via documented metadata root mapping.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "General_build_type",
            "source_group": "enum_keys",
            "authoring_note": "Merged to `General.build_type` in dwelling JSON when the value is exactly `house` or `flat`.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "General_storeys_in_dwelling",
            "source_group": "integer_keys",
            "authoring_note": "Merged to `General.storeys_in_dwelling` (integer). The alias `General_storey_of_dwelling` is also accepted in CSV.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "key": "General_storeys_in_building",
            "source_group": "integer_keys",
            "authoring_note": "Merged to `General.storeys_in_building` (integer, e.g. for flats).",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_contract": {
          "field_contract_ref": "#/csv_contract/field_contracts/metadata_value_row",
          "workflow_key_contract_refs": {
            "SchemaProfile": "#/csv_contract/field_contracts/schema_profile",
            "DefaultAssemblyWall": "#/csv_contract/field_contracts/assembly_library_id",
            "DefaultAssemblyRoof": "#/csv_contract/field_contracts/assembly_library_id",
            "DefaultAssemblyGroundFloor": "#/csv_contract/field_contracts/assembly_library_id"
          },
          "unknown_key_behavior": "ignored_in_dwelling_model_merge",
          "workflow_only_keys": [
            "SchemaProfile",
            "DefaultAssemblyWall",
            "DefaultAssemblyRoof",
            "DefaultAssemblyGroundFloor",
            "SapDir",
            "SapPdfPath",
            "SapXmlPath",
            "GuideOverlay",
            "JunctionPsiDefaultsPath",
            "ComplianceValidationEnabled",
            "ScenariosBaseModelEnabled"
          ],
          "calculated_or_ignored_keys": [
            "AirPermeability_env_area"
          ],
          "known_key_groups": {
            "path_keys": [
              "DefaultsPath"
            ],
            "boolean_keys": [
              "PartO_active_cooling_required",
              "PartGcompliance",
              "Ventilation_noise_nuisance",
              "KitchenExtractorHoodExternal"
            ],
            "integer_keys": [
              "NumberOfBedrooms",
              "NumberOfWetRooms",
              "NumberOfHabitableRooms",
              "NumberOfHotTappedRooms",
              "NumberOfUtilityRooms",
              "NumberOfBathrooms",
              "NumberOfSanitaryAccommodations",
              "General_storeys_in_dwelling",
              "General_storeys_in_building"
            ],
            "number_keys": [
              "AirPermeability_test_result",
              "AirPermeability_ventilation_zone_height",
              "Ventilation_altitude"
            ],
            "number_keys_parsed_but_not_merged_into_batch_json": [
              "GlobalOrientationOffset"
            ],
            "non_negative_number_keys": [
              "GroundFloorArea",
              "BuildingLength",
              "BuildingWidth",
              "DefaultThermalBridging"
            ],
            "enum_keys": {
              "General_build_type": [
                "house",
                "flat"
              ],
              "HeatingControlType": [
                "SeparateTempControl",
                "SeparateTimeAndTempControl"
              ],
              "AirPermeability_test_pressure": [
                "Standard",
                "Pulse test only"
              ],
              "Ventilation_shield_class": [
                "Open",
                "Normal",
                "Shielded"
              ],
              "Ventilation_terrain_class": [
                "OpenWater",
                "OpenField",
                "Suburban",
                "Urban"
              ]
            }
          }
        }
      },
      "Exposed Elements": {
        "description": "External opaque/roof/door building elements by zone.",
        "merge_glossary_backrefs": [
          "merge_building_element_rows_under_zone"
        ],
        "fields_by_type": {
          "BuildingElementOpaque": {
            "ui_fields": {
              "standard_fields": [
                "width",
                "height",
                "area",
                "pitch",
                "orientation360",
                "base_height",
                "is_unheated_pitched_roof",
                "is_external_door",
                "parent_element"
              ],
              "advanced_fields": [
                "areal_heat_capacity",
                "colour",
                "mass_distribution_class",
                "thermal_resistance_construction",
                "u_value"
              ]
            },
            "app_managed_fields": [
              {
                "field": "area",
                "behavior": "derived_from_geometry"
              },
              {
                "field": "base_height",
                "behavior": "suggested_from_floor_heights"
              },
              {
                "field": "u_value",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "thermal_resistance_construction",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "areal_heat_capacity",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "mass_distribution_class",
                "behavior": "inserted_from_vulcan_assembly_v1"
              }
            ],
            "extra_json": {
              "supported_fields": [
                "areal_heat_capacity",
                "colour",
                "mass_distribution_class",
                "thermal_resistance_construction",
                "u_value"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "BuildingElementOpaque"
            ],
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "area",
            "required": true,
            "role": "geometry_area",
            "required_in_section_header": false,
            "authoring_note": "Builder may derive from width\u00d7height when area is at or below zero. Require explicit area in authoring guides if your QA policy disallows derivation-only.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "pitch",
            "required": true,
            "role": "element_pitch",
            "required_in_section_header": false,
            "authoring_note": "Used in geometry and zone-area heuristics alongside coords.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "width",
            "required": true,
            "role": "geometry_width",
            "required_in_section_header": false,
            "authoring_note": "Feeds area derivation when height is set.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "height",
            "required": true,
            "role": "geometry_height",
            "required_in_section_header": false,
            "authoring_note": "Feeds area derivation when width is set.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "orientation360",
            "required": true,
            "role": "element_orientation",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "base_height",
            "required": false,
            "role": "element_base_height",
            "required_in_section_header": false,
            "authoring_note": "Use optional_plot in downstream UIs if base_height is editor-only for some workflows.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "is_unheated_pitched_roof",
            "required": false,
            "role": "roof_branch_flag",
            "required_in_section_header": false,
            "when": "When opaque roof semantics apply (see fields_by_type.BuildingElementOpaque).",
            "authoring_note": "Refine when text against defaults_template for each opaque roof subtype if authors need stricter guidance.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "is_external_door",
            "required": false,
            "role": "door_branch_flag",
            "required_in_section_header": false,
            "when": "When door or opaque branch semantics apply (see fields_by_type.BuildingElementOpaque).",
            "authoring_note": "Refine when text against defaults for door vs wall opaque variants.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "parent_element",
            "required": false,
            "role": "ui_parent_link",
            "required_in_section_header": false,
            "plotting_note": "Used by geometry workflows for parent-child element relationships (e.g., openings/doors) and orientation/pitch alignment; not merged as a dwelling-model field.",
            "merge_effect": "csv_or_ui_round_trip",
            "populate_requirement": "required_conditional",
            "authoring_note": "Used for opening/door parent linkage workflows, including net-area handling and inherited orientation/pitch alignment; not a direct dwelling-model physics property."
          },
          {
            "name": "coords",
            "required": true,
            "role": "geometry_path",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "required_in_section_header": false,
            "when": "Required for geometry placement and QA/canvas plotting.",
            "plotting_note": "3D path for authoring and canvas.",
            "authoring_note": "Required for plotting. x/y locate the element in plan; z is typically floor-relative height for most elements.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "required_in_section_header": false,
            "authoring_note": "Merged when keys are allowed by schema and not overridden by column values.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ]
        }
      },
      "Window Elements": {
        "description": "Transparent elements by zone. Glazing rows merge along the transparent path (e.g. U-value and related glazing fields). Mass-category fields such as `areal_heat_capacity` do not apply as they do for opaque or ground fabric—do not expect them to populate regulated glazing inputs.",
        "merge_glossary_backrefs": [
          "merge_building_element_rows_under_zone"
        ],
        "fields_by_type": {
          "BuildingElementTransparent": {
            "ui_fields": {
              "standard_fields": [
                "width",
                "height",
                "area",
                "pitch",
                "orientation360",
                "base_height",
                "frame_area_fraction",
                "free_area_height",
                "mid_height",
                "max_window_open_area",
                "linked_wall"
              ],
              "advanced_fields": [
                "controls",
                "delta_r",
                "depth",
                "distance",
                "g_value",
                "mid_height_air_flow_path",
                "security_risk",
                "shading",
                "trans_red",
                "treatment",
                "window_part_list"
              ]
            },
            "app_managed_fields": [
              {
                "field": "area",
                "behavior": "derived_from_geometry"
              },
              {
                "field": "base_height",
                "behavior": "suggested_from_floor_heights"
              },
              {
                "field": "mid_height",
                "behavior": "derived_for_export"
              },
              {
                "field": "u_value",
                "behavior": "inserted_from_vulcan_assembly_v1"
              }
            ],
            "extra_json": {
              "supported_fields": [
                "controls",
                "delta_r",
                "depth",
                "distance",
                "g_value",
                "mid_height_air_flow_path",
                "security_risk",
                "shading",
                "trans_red",
                "treatment",
                "window_part_list"
              ],
              "notes": "Many advanced values are nested: shading[] handles obstacle/overhang distance/depth, treatment/controls/trans_red/delta_r apply to window treatments, and window_part_list carries sub-opening fields such as mid_height_air_flow_path."
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "required_in_section_header": true,
            "authoring_note": "Duplicate Name per section fails parser E007.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "required_in_section_header": true,
            "authoring_note": "Must reference a zone defined in the Zone section (parser E008 when invalid forward reference).",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "BuildingElementTransparent"
            ],
            "required_in_section_header": true,
            "authoring_note": "Maps to schema element type and drives allowlist and defaults.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "area",
            "required": true,
            "role": "geometry_area",
            "required_in_section_header": false,
            "authoring_note": "Geometry/UI round-trip support; not relied on as canonical merged FHS window input.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          },
          {
            "name": "pitch",
            "required": true,
            "role": "element_pitch",
            "required_in_section_header": false,
            "authoring_note": "Coerced or rounded for FHS integer constraints where applicable.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "width",
            "required": true,
            "role": "geometry_width",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "height",
            "required": true,
            "role": "geometry_height",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "orientation360",
            "required": true,
            "role": "element_orientation",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "base_height",
            "required": true,
            "role": "element_base_height",
            "required_in_section_header": false,
            "authoring_note": "Merged when schema allows and cell is non-empty.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "linked_wall",
            "required": false,
            "role": "window_parent_link",
            "required_in_section_header": false,
            "plotting_note": "Used for window-wall netting and inherited orientation/pitch alignment workflows.",
            "merge_effect": "csv_or_ui_round_trip",
            "populate_requirement": "required_conditional",
            "column_hints": {
              "ui_import_maps_to": "parent_element"
            },
            "authoring_note": "Used for wall-window association, net area calculations, and alignment of inherited orientation/pitch workflows."
          },
          {
            "name": "frame_area_fraction",
            "required": true,
            "role": "window_frame_fraction",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "free_area_height",
            "required": true,
            "role": "vent_opening_height",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "mid_height",
            "required": false,
            "role": "ui_exported_mid_height",
            "required_in_section_header": false,
            "authoring_note": "Export and UI round-trip; not dwelling-model merge truth.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "max_window_open_area",
            "required": true,
            "role": "max_open_area",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "coords",
            "required": true,
            "role": "geometry_path",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "required_in_section_header": false,
            "when": "Required for geometry placement and QA/canvas plotting.",
            "plotting_note": "3D path per coords_path_3d contract.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate",
            "authoring_note": "Required for plotting. x/y locate opening footprint; z is typically floor-relative placement height."
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "required_in_section_header": false,
            "authoring_note": "Column values override extra_json keys where both apply; schema gating applies.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ]
        }
      },
      "Ground Elements": {
        "description": "Ground-contact elements by zone.",
        "merge_glossary_backrefs": [
          "merge_building_element_rows_under_zone"
        ],
        "fields_by_type": {
          "BuildingElementGround": {
            "ui_fields": {
              "standard_fields": [
                "width",
                "height",
                "area",
                "total_area",
                "perimeter",
                "floor_type",
                "depth_basement_floor",
                "thickness_walls",
                "pitch"
              ],
              "advanced_fields": [
                "area_per_perimeter_vent",
                "areal_heat_capacity",
                "edge_insulation",
                "edge_thermal_resistance",
                "height_basement_walls",
                "height_upper_surface",
                "mass_distribution_class",
                "psi_wall_floor_junc",
                "shield_fact_location",
                "thermal_resist_insul",
                "thermal_resist_walls_base",
                "thermal_resistance_floor_construction",
                "thermal_transm_envi_base",
                "thermal_transm_walls",
                "u_value"
              ]
            },
            "app_managed_fields": [
              {
                "field": "total_area",
                "behavior": "mirrors_area_in_ui_roundtrip"
              },
              {
                "field": "floor_type",
                "behavior": "defaults_to_Slab_no_edge_insulation_on_import"
              },
              {
                "field": "u_value",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "thermal_resistance_floor_construction",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "thermal_resist_insul",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "areal_heat_capacity",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "mass_distribution_class",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "height_upper_surface",
                "behavior": "inserted_from_vulcan_assembly_v1_for_suspended_floor"
              }
            ],
            "extra_json": {
              "supported_fields": [
                "area_per_perimeter_vent",
                "areal_heat_capacity",
                "edge_insulation",
                "edge_thermal_resistance",
                "height_basement_walls",
                "height_upper_surface",
                "mass_distribution_class",
                "psi_wall_floor_junc",
                "shield_fact_location",
                "thermal_resist_insul",
                "thermal_resist_walls_base",
                "thermal_resistance_floor_construction",
                "thermal_transm_envi_base",
                "thermal_transm_walls",
                "u_value"
              ],
              "notes": "Ground extra_json keys are conditional by floor_type (e.g., edge_insulation for slab_edge_insulation, basement-specific fields for basement variants)."
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "required_in_section_header": true,
            "authoring_note": "BuildingElementGround; floor_type selects variant template before merge.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "area",
            "required": true,
            "role": "geometry_area",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "width",
            "required": false,
            "role": "geometry_width",
            "required_in_section_header": false,
            "authoring_note": "Merged only if schema allows the property for the active ground variant.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "height",
            "required": false,
            "role": "geometry_height",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "perimeter",
            "required": true,
            "role": "ground_perimeter",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "floor_type",
            "required": true,
            "role": "ground_variant",
            "field_contract_ref": "#/csv_contract/field_contracts/ground_floor_type",
            "required_in_section_header": false,
            "authoring_note": "Builder may also read floor_type from extra_json when shaping the ground variant.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "depth_basement_floor",
            "required": false,
            "role": "basement_depth",
            "required_in_section_header": false,
            "when": "Basement or below-grade ground variants where schema exposes depth_basement_floor.",
            "authoring_note": "Merged when allowed for the variant and non-empty.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "thickness_walls",
            "required": false,
            "role": "basement_wall_thickness",
            "required_in_section_header": false,
            "when": "Basement or enclosing-wall variants where schema exposes thickness_walls.",
            "authoring_note": "Merged when allowed and non-empty.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "coords",
            "required": true,
            "role": "geometry_polygon",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_polygon_3d",
            "required_in_section_header": false,
            "authoring_note": "Polygon coordinates; raw CSV coords feed zone-area inference when zone area is still zero.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "required_in_section_header": false,
            "authoring_note": "Supported advanced keys per fields_by_type; merge gated by schema allowlist.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ]
        }
      },
      "Non-Exposed Elements": {
        "description": "Adjacent/non-exposed elements by zone.",
        "merge_glossary_backrefs": [
          "merge_building_element_rows_under_zone"
        ],
        "fields_by_type": {
          "BuildingElementAdjacentConditionedSpace": {
            "ui_fields": {
              "standard_fields": [
                "width",
                "height",
                "area",
                "pitch"
              ],
              "advanced_fields": [
                "areal_heat_capacity",
                "mass_distribution_class",
                "thermal_resistance_construction",
                "u_value"
              ]
            },
            "app_managed_fields": [
              {
                "field": "area",
                "behavior": "derived_from_geometry"
              }
            ],
            "extra_json": {
              "supported_fields": [
                "areal_heat_capacity",
                "mass_distribution_class",
                "thermal_resistance_construction",
                "u_value"
              ]
            }
          },
          "BuildingElementAdjacentUnconditionedSpace_Simple": {
            "ui_fields": {
              "standard_fields": [
                "width",
                "height",
                "area",
                "pitch"
              ],
              "advanced_fields": [
                "areal_heat_capacity",
                "mass_distribution_class",
                "thermal_resistance_construction",
                "thermal_resistance_unconditioned_space",
                "u_value"
              ]
            },
            "app_managed_fields": [
              {
                "field": "area",
                "behavior": "derived_from_geometry"
              }
            ],
            "extra_json": {
              "supported_fields": [
                "areal_heat_capacity",
                "mass_distribution_class",
                "thermal_resistance_construction",
                "thermal_resistance_unconditioned_space",
                "u_value"
              ]
            }
          },
          "BuildingElementPartyWall": {
            "ui_fields": {
              "standard_fields": [
                "width",
                "height",
                "area",
                "pitch",
                "party_wall_cavity_type",
                "party_wall_lining_type",
                "thermal_resistance_cavity"
              ],
              "advanced_fields": [
                "areal_heat_capacity",
                "mass_distribution_class",
                "thermal_resistance_construction"
              ]
            },
            "app_managed_fields": [
              {
                "field": "area",
                "behavior": "derived_from_geometry"
              },
              {
                "field": "thermal_resistance_construction",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "areal_heat_capacity",
                "behavior": "inserted_from_vulcan_assembly_v1"
              },
              {
                "field": "mass_distribution_class",
                "behavior": "inserted_from_vulcan_assembly_v1"
              }
            ],
            "extra_json": {
              "supported_fields": [
                "areal_heat_capacity",
                "mass_distribution_class",
                "thermal_resistance_construction"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "BuildingElementAdjacentConditionedSpace",
              "BuildingElementAdjacentUnconditionedSpace_Simple",
              "BuildingElementPartyWall"
            ],
            "required_in_section_header": true,
            "authoring_note": "Controls schema branch, defaults, and allowlist for adjacent or party wall elements.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "area",
            "required": true,
            "role": "geometry_area",
            "required_in_section_header": false,
            "authoring_note": "Builder may derive area from geometry when rules allow; merge still schema-gated.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "pitch",
            "required": true,
            "role": "element_pitch",
            "required_in_section_header": false,
            "authoring_note": "Used in zone-area fallback paths with coords when zone area is still zero (horizontal pitches).",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "width",
            "required": true,
            "role": "geometry_width",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "height",
            "required": true,
            "role": "geometry_height",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "coords",
            "required": true,
            "role": "geometry_path",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "required_in_section_header": false,
            "authoring_note": "Path or polygon semantics per contract; contributes to zone-area inference when zone area is zero.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "required_in_section_header": false,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ]
        }
      },
      "Thermal Bridging Elements": {
        "description": "Linear/point thermal bridge entries by zone.",
        "merge_glossary_backrefs": [
          "merge_thermal_bridge_rows_into_zone_thermal_bridging"
        ],
        "notes": "Rows are skipped for zones where Zone.simplified thermal bridging is true; merged keys are filtered to valid thermal-bridge properties (coords are not copied onto merged TB objects).",
        "fields_by_type": {
          "ThermalBridgeLinear": {
            "ui_fields": {
              "standard_fields": [
                "length",
                "linear_thermal_transmittance"
              ]
            }
          },
          "ThermalBridgePoint": {
            "ui_fields": {
              "standard_fields": [
                "heat_transfer_coeff"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "required_in_section_header": true,
            "authoring_note": "Rows for simplified-TB zones are skipped during conversion.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "bridge_type",
            "values": [
              "ThermalBridgeLinear",
              "ThermalBridgePoint"
            ],
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "heat_transfer_coeff",
            "required": false,
            "role": "point_bridge_coeff",
            "required_in_section_header": false,
            "when": "Type is ThermalBridgePoint.",
            "authoring_note": "Template path may default numeric coefficient when absent.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "length",
            "required": false,
            "role": "linear_bridge_length",
            "required_in_section_header": false,
            "when": "Type is ThermalBridgeLinear.",
            "authoring_note": "Template path may default length when absent.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "linear_thermal_transmittance",
            "required": false,
            "role": "linear_bridge_transmittance",
            "required_in_section_header": false,
            "when": "Type is ThermalBridgeLinear.",
            "authoring_note": "Template path may default linear transmittance when absent.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "coords",
            "required": true,
            "role": "geometry_path",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "required_in_section_header": false,
            "plotting_note": "Required for plotting. x/y locate junction position; z is physical height in metres for TB placement, with floor_id used where needed.",
            "authoring_note": "Required for plotting/placement. x/y locate junction; z is physical height in metres for TB records, with floor_id used where supplied.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "required_in_section_header": false,
            "when": "ThermalBridgeLinear: junction_type may be read from extra_json when the column is absent.",
            "authoring_note": "General extra_json keys beyond junction_type are not merged on this Thermal Bridging merge path.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_kinds": {
          "linear_bridge": {
            "match": {
              "Type": [
                "ThermalBridgeLinear"
              ]
            },
            "field_paths": [
              "length",
              "linear_thermal_transmittance",
              "coords"
            ],
            "contract_ref": "#/csv_contract/sections/Thermal Bridging Elements/fields_by_type/ThermalBridgeLinear",
            "extra_json_keys": {
              "junction_type": "#/csv_contract/field_contracts/thermal_bridge_junction_type",
              "floor_id": "#/csv_contract/field_contracts/thermal_bridge_floor_id"
            }
          },
          "point_bridge": {
            "match": {
              "Type": [
                "ThermalBridgePoint"
              ]
            },
            "field_paths": [
              "heat_transfer_coeff",
              "coords"
            ],
            "contract_ref": "#/csv_contract/sections/Thermal Bridging Elements/fields_by_type/ThermalBridgePoint"
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ]
        }
      },
      "Zone": {
        "description": "Thermal zones and zone-level attributes.",
        "merge_glossary_backrefs": [
          "merge_zone_rows_into_root_zone_map"
        ],
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "zone_name",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "row_type",
            "expected_value": "Zone",
            "required_in_section_header": true,
            "authoring_note": "Parser requires this cell as row discriminator (expected_value Zone); it is not emitted as its own property on the merged zone object.",
            "merge_effect": "csv_or_ui_round_trip",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "volume",
            "required": true,
            "role": "zone_volume",
            "required_in_section_header": false,
            "authoring_note": "Builder may derive volume from floor_area and height when volume is missing or zero (see row_contract.effects).",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "floor_area",
            "required": true,
            "role": "csv_only_floor_area",
            "required_in_section_header": false,
            "when": "Required for a complete model depending on output mode: contributes to zone area on core paths; FHS handling differs (see row_contract.payload_contract and effects).",
            "authoring_note": "Product tiebreak: decide whether FHS runs treat this as mandatory in CSV or always inherited from defaults_template.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "height",
            "required": true,
            "role": "csv_only_zone_height",
            "required_in_section_header": false,
            "when": "Used for volume derivation; whether height remains on the merged zone object depends on output mode (FHS may strip).",
            "authoring_note": "Product tiebreak: classify as optional_default_or_derived if templates always supply safe height for your pipeline.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "simplified thermal bridging",
            "required": false,
            "role": "thermal_bridging_mode",
            "required_in_section_header": false,
            "authoring_note": "Boolean default false; when true uses simplified thermal bridging from summed exposed and window areas.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "livingroom_area",
            "required": true,
            "role": "fhs_primary_zone_area_split",
            "required_in_section_header": false,
            "when": "FHS-style primary zone split when that output shape applies.",
            "authoring_note": "Product tiebreak: required only when emitting FHS primary/rest split; otherwise optional_default_or_derived.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "restofdwelling_area",
            "required": true,
            "role": "fhs_primary_zone_area_split",
            "required_in_section_header": false,
            "when": "FHS-style primary zone split when that output shape applies.",
            "authoring_note": "Product tiebreak: same as livingroom_area.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          }
        ],
        "row_contract": {
          "match": {
            "Type": [
              "Zone"
            ]
          },
          "payload_contract": {
            "schema_pointer": "#/properties/Zone/additionalProperties",
            "field_contracts": {
              "volume": {
                "type": "number",
                "minimum": 0,
                "maximum": 50000
              },
              "livingroom_area": {
                "type": "number",
                "minimum": 0,
                "maximum": 10000
              },
              "restofdwelling_area": {
                "type": "number",
                "minimum": 0,
                "maximum": 10000
              },
              "floor_area": {
                "type": "number",
                "minimum": 0,
                "csv_only": true
              },
              "height": {
                "type": "number",
                "exclusiveMinimum": 0,
                "csv_only": true
              },
              "simplified thermal bridging": {
                "type": "boolean",
                "csv_only": true
              }
            },
            "effects": [
              {
                "kind": "derive_volume_when_missing",
                "inputs": [
                  "floor_area",
                  "height"
                ]
              },
              {
                "kind": "fhs_keeps_livingroom_area_and_restofdwelling_area_in_output",
                "mode": "fhs"
              },
              {
                "kind": "core_only_stores_height_in_zone_output",
                "mode": "core"
              }
            ]
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ]
        }
      },
      "Window Shading": {
        "description": "Shading objects linked to window elements.",
        "notes": "Rows reference windows via linked_window and are attached to the matching window in-zone.",
        "references": [
          {
            "field": "linked_window",
            "targets_section": "Window Elements",
            "match_rule": "matches window Name within the same Zone"
          }
        ],
        "output_mapping": {
          "target_path": "Zone.<Zone>.BuildingElement.<linked_window>.shading",
          "merge_mode": "attach_to_existing_window_in_zone"
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "required_in_section_header": true,
            "authoring_note": "Parser enforces duplicate Name per section (E007); add_window_shading_to_zones does not read Name for merge output.",
            "merge_effect": "csv_or_ui_round_trip",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "required_in_section_header": true,
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "shading_subtype",
            "values": [
              "object",
              "overhang",
              "sidefinright",
              "sidefinleft",
              "reveal"
            ],
            "batch_default_when_cell_empty": "object",
            "required_in_section_header": true,
            "authoring_note": "Empty cell defaults to object during conversion, mapped to schema obstacle.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "linked_window",
            "required": true,
            "role": "window_reference",
            "field_contract_ref": "#/csv_contract/field_contracts/linked_window_reference",
            "required_in_section_header": false,
            "authoring_note": "Not listed among parser-required columns for this section but required for a successful merge—supply the cell when non-empty shading rows exist.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "depth",
            "required": false,
            "role": "non_object_depth",
            "required_in_section_header": false,
            "when": "Type is overhang, sidefinright, sidefinleft, or reveal (see row_contract branches).",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "height",
            "required": false,
            "role": "object_height",
            "required_in_section_header": false,
            "when": "Type is object (CSV), mapped to obstacle in JSON (see row_contract branch object).",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "distance",
            "required": false,
            "role": "shading_distance",
            "required_in_section_header": false,
            "authoring_note": "Copied when present on branches that use distance in row_contract.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "transparency",
            "required": false,
            "role": "object_transparency",
            "required_in_section_header": false,
            "when": "Type is object branch.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "required_in_section_header": false,
            "plotting_note": "Not referenced in add_window_shading_to_zones merge.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "required_in_section_header": false,
            "authoring_note": "Not merged into shading array entries in the dwelling model output.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_contract": {
          "dispatch_field": "Type",
          "payload_contract": {
            "schema_pointer": "#/$defs/WindowShading/items",
            "target_path": "Zone.<Zone>.BuildingElement.<linked_window>.shading[]",
            "branches": {
              "object": {
                "output_type": "obstacle",
                "field_paths": [
                  "height",
                  "distance",
                  "transparency"
                ]
              },
              "overhang": {
                "output_type": "overhang",
                "field_paths": [
                  "depth",
                  "distance"
                ]
              },
              "sidefinright": {
                "output_type": "sidefinright",
                "field_paths": [
                  "depth",
                  "distance"
                ]
              },
              "sidefinleft": {
                "output_type": "sidefinleft",
                "field_paths": [
                  "depth",
                  "distance"
                ]
              },
              "reveal": {
                "output_type": "reveal",
                "field_paths": [
                  "depth",
                  "distance"
                ]
              }
            }
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ],
          "conversion_required_fields": [
            "linked_window"
          ]
        }
      },
      "Lighting": {
        "description": "Zone lighting entries used to build Lighting objects.",
        "merge_glossary_backrefs": [
          "merge_lighting_rows_into_zone_lighting"
        ],
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "efficacy",
            "required": true,
            "role": "bulb_efficacy",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "count",
            "required": true,
            "role": "bulb_count",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "power",
            "required": true,
            "role": "bulb_power",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "plotting_note": "Not merged into Lighting bulb objects; layout/canvas only.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot",
            "authoring_note": "Geometry-to-model merge builds bulbs from efficacy/count/power only."
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_contract": {
          "payload_contract": {
            "schema_pointer": "#/properties/Zone/additionalProperties/properties/Lighting/properties/bulbs/items",
            "target_path": "Zone.<Zone>.Lighting.bulbs[0]",
            "field_paths": [
              "count",
              "power",
              "efficacy"
            ]
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone"
          ],
          "conversion_required_fields": [
            "count",
            "efficacy",
            "power"
          ]
        }
      },
      "Ventilation Systems": {
        "description": "Ventilation rows for vents, mechanical systems, and ductwork links.",
        "fields_by_type": {
          "MechanicalVentilation": {
            "ui_fields": {
              "standard_fields": [
                "vent_type"
              ],
              "advanced_fields": [
                "EnergySupply",
                "SFP",
                "SFP_in_use_factor",
                "cross_section_shape",
                "design_outdoor_air_flow_rate",
                "design_zone_cooling_covered_by_mech_vent",
                "design_zone_heating_covered_by_mech_vent",
                "duct_type",
                "ductwork",
                "external_diameter_mm",
                "insulation_thermal_conductivity",
                "insulation_thickness_mm",
                "internal_diameter_mm",
                "length",
                "measured_air_flow_rate",
                "measured_fan_power",
                "mid_height_air_flow_path",
                "mvhr_eff",
                "mvhr_location",
                "orientation360",
                "pitch",
                "position_exhaust",
                "position_intake",
                "reflective"
              ]
            },
            "extra_json": {
              "supported_fields": [
                "EnergySupply",
                "SFP",
                "SFP_in_use_factor",
                "cross_section_shape",
                "design_outdoor_air_flow_rate",
                "design_zone_cooling_covered_by_mech_vent",
                "design_zone_heating_covered_by_mech_vent",
                "duct_type",
                "ductwork",
                "external_diameter_mm",
                "insulation_thermal_conductivity",
                "insulation_thickness_mm",
                "internal_diameter_mm",
                "length",
                "measured_air_flow_rate",
                "measured_fan_power",
                "mid_height_air_flow_path",
                "mvhr_eff",
                "mvhr_location",
                "orientation360",
                "pitch",
                "position_exhaust",
                "position_intake",
                "reflective"
              ]
            },
            "conversion_requirements": {
              "required_fields": [
                "EnergySupply",
                "design_outdoor_air_flow_rate",
                "sup_air_flw_ctrl",
                "sup_air_temp_ctrl",
                "vent_type"
              ]
            },
            "output_mapping": {
              "target_path": "InfiltrationVentilation.MechanicalVentilation.<Name>",
              "merge_mode": "select_defaults_template_by_vent_type_then_overlay_csv_then_extra_json"
            },
            "references": [
              {
                "field": "vent_type",
                "affects_output": "selects matching defaults-backed MechanicalVentilation template"
              }
            ],
            "extra_json_semantics": {
              "accepted_shape": "flat_object",
              "precedence": "CSV columns override extra_json; extra_json overrides selected defaults template",
              "unknown_keys": "filtered_to_schema_allowed_properties"
            },
            "failure_modes": [
              "fails when defaults_template.json does not contain a MechanicalVentilation template for the selected vent_type"
            ],
            "normalization_rules": [
              "Intermittent MEV and Decentralised continuous MEV drop measured_fan_power, measured_air_flow_rate, mvhr_eff, mvhr_location, position_intake, and position_exhaust after overlay.",
              "Centralised continuous MEV and MVHR accept either SFP or measured_fan_power/measured_air_flow_rate; if both are explicit, measured_* wins and SFP is removed."
            ]
          },
          "MechanicalVentilationDuctwork": {
            "ui_fields": {
              "standard_fields": [
                "duct_type",
                "length",
                "parent_element"
              ]
            },
            "output_mapping": {
              "target_path": "InfiltrationVentilation.MechanicalVentilation.<parent_element>.ductwork[]",
              "merge_mode": "append_to_parent_mechanical_ventilation_ductwork_array"
            },
            "references": [
              {
                "field": "parent_element",
                "targets_type": "MechanicalVentilation",
                "match_rule": "must match the parent MechanicalVentilation Name"
              }
            ],
            "ductwork_merge_notes": [
              "One CSV row \u2192 one ductwork[] element appended in parse/iteration order for that parent. Multiple physical lengths = multiple rows with the same parent_element.",
              "Ductwork objects are only merged for vent_type=MVHR when non-empty; on other vent_type values with ductwork rows, conversion may error (E040).",
              "Service-line 3D coords use the same `coords` / `field_contract_ref` pattern as other geometry lines; physical run length is `length` where used."
            ],
            "extra_json_semantics": {
              "accepted_shape": "flat_object",
              "precedence": "CSV columns override extra_json",
              "unknown_keys": "filtered_to_schema_allowed_properties"
            }
          },
          "Vents": {
            "ui_fields": {
              "standard_fields": [
                "mid_height_air_flow_path",
                "area_cm2",
                "orientation360",
                "pitch",
                "parent_element"
              ]
            },
            "output_mapping": {
              "target_path": "InfiltrationVentilation.Vents.<Name>",
              "merge_mode": "seed_from_first_defaults_template_then_overlay_csv_then_extra_json"
            },
            "extra_json_semantics": {
              "accepted_shape": "flat_object",
              "precedence": "CSV columns override extra_json; extra_json overrides defaults",
              "unknown_keys": "filtered_to_schema_allowed_properties"
            }
          }
        },
        "output_mapping": {
          "target_path": "InfiltrationVentilation",
          "merge_mode": "merge_into_defaults_backed_root_section"
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "ventilation_row_type",
            "values": [
              "MechanicalVentilation",
              "Vents",
              "MechanicalVentilationDuctwork"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "length",
            "required": false,
            "role": "duct_length",
            "used_by_row_kinds": [
              "ductwork"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "duct_type",
            "required": false,
            "role": "duct_variant",
            "used_by_row_kinds": [
              "ductwork"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "parent_element",
            "required": false,
            "role": "mechanical_ventilation_reference",
            "used_by_row_kinds": [
              "ductwork"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "mid_height_air_flow_path",
            "required": false,
            "role": "vent_mid_height",
            "used_by_row_kinds": [
              "vents"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "area_cm2",
            "required": false,
            "role": "vent_free_area",
            "used_by_row_kinds": [
              "vents"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "orientation360",
            "required": false,
            "role": "vent_orientation",
            "used_by_row_kinds": [
              "vents"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "pitch",
            "required": false,
            "role": "vent_pitch",
            "used_by_row_kinds": [
              "vents"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "vent_type",
            "required": false,
            "role": "mechanical_ventilation_type",
            "used_by_row_kinds": [
              "mechanical"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "plotting_note": "Skipped when merging CSV columns into vent/MV objects; canvas/export only.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_kinds": {
          "vents": {
            "match": {
              "Type": [
                "Vents"
              ]
            },
            "target_path": "InfiltrationVentilation.Vents.<Name>",
            "field_paths": [
              "mid_height_air_flow_path",
              "area_cm2",
              "orientation360",
              "pitch"
            ]
          },
          "mechanical": {
            "match": {
              "Type": [
                "MechanicalVentilation"
              ]
            },
            "target_path": "InfiltrationVentilation.MechanicalVentilation.<Name>",
            "field_paths": [
              "vent_type",
              "extra_json"
            ]
          },
          "ductwork": {
            "match": {
              "Type": [
                "MechanicalVentilationDuctwork"
              ]
            },
            "target_path": "InfiltrationVentilation.MechanicalVentilation.<parent_element>.ductwork[]",
            "field_paths": [
              "length",
              "duct_type",
              "parent_element",
              "extra_json"
            ]
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ],
          "required_values": {
            "vent_type": {
              "values": [
                "Intermittent MEV",
                "Centralised continuous MEV",
                "Decentralised continuous MEV",
                "MVHR"
              ],
              "enforced_by": "parser_validation"
            }
          }
        }
      },
      "Combustion Appliances": {
        "description": "Combustion appliance records.",
        "fields_by_type": {
          "CombustionAppliances": {
            "ui_fields": {
              "standard_fields": [
                "appliance_type",
                "exhaust_situation",
                "fuel_type",
                "supply_situation"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "CombustionAppliances"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "appliance_type",
            "required": false,
            "role": "appliance_type",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "exhaust_situation",
            "required": false,
            "role": "exhaust_situation",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "fuel_type",
            "required": false,
            "role": "fuel_type",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "supply_situation",
            "required": false,
            "role": "supply_situation",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "plotting_note": "Not merged into combustion appliance objects from CSV rows.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ]
        }
      },
      "Water Pipework": {
        "description": "DHW pipework segments: one CSV row per segment. `pipework_type` selects primary cylinder runs versus distribution; author primary cylinder piping here instead of only via Systems `extra_json`.",
        "notes": [
          "Primary segments append in file order to `HotWaterSource.<store>.primary_pipework[]`. Distribution segments append in file order to `HotWaterDemand.Distribution`. Blank or non-`primary` values count as distribution.",
          "Store keys (e.g. `hw cylinder`) come from the merged model. The same primary_pipework result is applied to each tank-shaped hot-water store; combi boilers do not consume these rows."
        ],
        "merge_glossary_backrefs": [
          "append_water_pipework_rows_to_model",
          "replicate_primary_pipework_across_tank_shaped_hws"
        ],
        "fields_by_type": {
          "WaterPipework": {
            "ui_fields": {
              "standard_fields": [
                "location",
                "length"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "WaterPipework"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "length",
            "required": false,
            "role": "pipe_length",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "location",
            "required": false,
            "role": "pipe_location",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "pipework_type",
            "required": false,
            "role": "pipework_target",
            "values": [
              "primary",
              "distribution"
            ],
            "status": "default_distribution_when_empty",
            "builder_default_when_empty": "distribution",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived",
            "authoring_note": "Use `primary` for cylinder runs; anything else (including empty) is treated as distribution."
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "plotting_note": "Ignored when overlaying pipe segment fields; editor/canvas only.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_kinds": {
          "primary": {
            "match": {
              "pipework_type": [
                "primary"
              ]
            },
            "target_path": "HotWaterSource.<DHW store key, often `hw cylinder`>.primary_pipework[]"
          },
          "distribution": {
            "match": {
              "pipework_type": [
                "distribution"
              ]
            },
            "match_note": "Also matches default path when the cell is empty, whitespace, or any value other than primary (see Water Pipework row_kinds and pipework_type routing).",
            "target_path": "HotWaterDemand.Distribution"
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ]
        }
      },
      "Wet Emitters": {
        "description": "Wet emitter records (e.g. radiators/UFH/fancoils) by zone.",
        "fields_by_type": {
          "WetEmitter": {
            "ui_fields": {
              "standard_fields": [
                "subcategory",
                "unit_number",
                "parent_element",
                "wet_emitter_type"
              ]
            },
            "extra_json": {
              "supported_fields": [
                "c",
                "n",
                "frac_convective",
                "equivalent_specific_thermal_mass",
                "system_performance_factor",
                "n_units",
                "fancoil_test_data"
              ],
              "notes": "Union of subtype keys; radiator/ufh/fancoil each use a subset (see Type branches & row kinds)."
            }
          }
        },
        "output_mapping": {
          "target_path": "SpaceHeatSystem.<Zone and subcategory derived name>",
          "merge_mode": "aggregate_rows_by_zone_and_subcategory_then_replace_existing_wet_distribution_systems"
        },
        "references": [
          {
            "field": "subcategory",
            "affects_output": "determines emitter/system branch and resulting WetDistribution naming"
          }
        ],
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Zone",
            "required": true,
            "role": "zone_reference",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "WetEmitter"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "subcategory",
            "required": true,
            "role": "wet_emitter_type",
            "values": [
              "radiator",
              "ufh",
              "fancoil"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "area",
            "required": false,
            "role": "ufh_area_or_emitter_area",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "unit_number",
            "required": false,
            "role": "radiator_or_fancoil_unit_count_hint",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot",
            "plotting_note": "Not copied onto emitter objects by merge; canvas/placement only."
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_kinds": {
          "radiator": {
            "match": {
              "subcategory": [
                "radiator"
              ]
            },
            "target_path": "SpaceHeatSystem.<Zone radiator>.emitters[]",
            "extra_json_fields": [
              "c",
              "n",
              "frac_convective"
            ]
          },
          "ufh": {
            "match": {
              "subcategory": [
                "ufh"
              ]
            },
            "target_path": "SpaceHeatSystem.<Zone ufh>.emitters[]",
            "extra_json_fields": [
              "equivalent_specific_thermal_mass",
              "system_performance_factor",
              "frac_convective"
            ]
          },
          "fancoil": {
            "match": {
              "subcategory": [
                "fancoil"
              ]
            },
            "target_path": "SpaceHeatSystem.<Zone fancoil>.emitters[]",
            "extra_json_fields": [
              "n_units",
              "fancoil_test_data",
              "frac_convective"
            ]
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Zone",
            "Type"
          ],
          "conversion_required_fields": [
            "subcategory"
          ],
          "required_values": {
            "subcategory": {
              "values": [
                "radiator",
                "ufh",
                "fancoil"
              ],
              "enforced_by": "conversion_branch_handling"
            }
          },
          "required_cross_section_support": {
            "section": "Systems",
            "rule": "fhs_requires_explicit_HeatSourceWet_system"
          }
        }
      },
      "Appliances": {
        "description": "Appliance key records used for appliance demand mapping.",
        "fields_by_type": {
          "Appliance": {
            "ui_fields": {
              "standard_fields": [
                "appliancekey",
                "parent_element"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "ui_label_only",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "Appliance"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "appliancekey",
            "required": true,
            "role": "appliance_schema_key",
            "field_contract_ref": "#/csv_contract/field_contracts/appliance_key_enum",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate",
            "values": [
              "Clothes_washing",
              "Clothes_drying",
              "Dishwasher",
              "Fridge",
              "Fridge-Freezer",
              "Freezer",
              "Hobs",
              "Otherdevices",
              "Oven"
            ]
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "plotting_note": "Merge writes only appliancekey→Default; coords ignored.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          }
        ],
        "row_contract": {
          "payload_contract": {
            "target_path": "Appliances.<appliancekey>",
            "constant_value": "Default"
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ],
          "conversion_required_fields": [
            "appliancekey"
          ]
        }
      },
      "Hot Water Outlets": {
        "description": "Hot water outlet demand records.",
        "fields_by_type": {
          "HotWaterDemand": {
            "ui_fields": {
              "standard_fields": [
                "subcategory",
                "size",
                "flowrate",
                "rated_power",
                "parent_element"
              ],
              "advanced_fields": [
                "ColdWaterSource",
                "EnergySupply",
                "HotWaterSource",
                "type"
              ]
            },
            "extra_json": {
              "supported_fields": [
                "ColdWaterSource",
                "EnergySupply",
                "HotWaterSource",
                "type"
              ]
            }
          }
        },
        "output_mapping": {
          "target_path": "HotWaterDemand",
          "merge_mode": "merge_into_existing_defaults_backed_hot_water_demand"
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "HotWaterDemand"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "subcategory",
            "required": true,
            "role": "hot_water_outlet_type",
            "values": [
              "MixerShower",
              "InstantElecShower",
              "Bath",
              "OtherWaterUseDetails"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "flowrate",
            "required": false,
            "role": "mixer_or_other_flowrate",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "size",
            "required": false,
            "role": "bath_size",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "rated_power",
            "required": false,
            "role": "instant_shower_power",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "allow_low_flowrate",
            "required": false,
            "role": "mixer_shower_low_flowrate_flag",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "plotting_note": "Not merged into HotWaterDemand outlet objects.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          }
        ],
        "row_kinds": {
          "mixer_shower": {
            "match": {
              "subcategory": [
                "MixerShower"
              ]
            },
            "target_path": "HotWaterDemand.Shower.<Name>",
            "field_paths": [
              "type",
              "flowrate",
              "allow_low_flowrate"
            ]
          },
          "instant_elec_shower": {
            "match": {
              "subcategory": [
                "InstantElecShower"
              ]
            },
            "target_path": "HotWaterDemand.Shower.<Name>",
            "field_paths": [
              "type",
              "rated_power"
            ]
          },
          "bath": {
            "match": {
              "subcategory": [
                "Bath"
              ]
            },
            "target_path": "HotWaterDemand.Bath.<Name>",
            "field_paths": [
              "size"
            ]
          },
          "other": {
            "match": {
              "subcategory": [
                "OtherWaterUseDetails"
              ]
            },
            "target_path": "HotWaterDemand.Other.<Name>",
            "field_paths": [
              "flowrate"
            ]
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ],
          "conversion_required_fields": [
            "subcategory"
          ],
          "required_values": {
            "subcategory": {
              "values": [
                "MixerShower",
                "InstantElecShower",
                "Bath",
                "OtherWaterUseDetails"
              ],
              "enforced_by": "conversion_branch_handling"
            }
          }
        }
      },
      "Context Shading": {
        "description": "Site/context shading geometry entries.",
        "merge_glossary_backrefs": [
          "merge_context_shading_into_external_conditions_segments"
        ],
        "notes": "Dwelling-model conversion accepts shading_type first, then falls back to Type. It accepts both underscore and spaced angle headers; coords and parent_element are roundtrip-only.",
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "shading_type",
            "required": false,
            "role": "batch_shading_type",
            "values": [
              "obstacle",
              "overhang"
            ],
            "maps_to_schema_field": "type",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "Type",
            "required": false,
            "role": "legacy_or_roundtrip_shading_type",
            "values": [
              "obstacle",
              "overhang",
              "ContextShading"
            ],
            "populate_requirement": "optional_default_or_derived",
            "column_hints": {
              "shading_discriminator_fallback": true,
              "fallback_after_column": "shading_type"
            },
            "merge_effect": "affects_calculation_input"
          },
          {
            "name": "start_angle",
            "required": false,
            "role": "batch_angle_start",
            "accepted_batch_header_aliases": [
              "start angle"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "end_angle",
            "required": false,
            "role": "batch_angle_end",
            "accepted_batch_header_aliases": [
              "end angle"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "distance",
            "required": false,
            "role": "shading_distance",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "height",
            "required": false,
            "role": "shading_height",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "parent_element",
            "required": false,
            "role": "ui_parent_link",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_path_3d",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          }
        ],
        "conversion_field_mapping": {
          "builder_reads": {
            "shading_type_source": [
              "shading_type",
              "Type"
            ],
            "start_angle_source": [
              "start_angle",
              "start angle"
            ],
            "end_angle_source": [
              "end_angle",
              "end angle"
            ]
          },
          "web_roundtrip_only_columns": {
            "parent_element": "retained for UI roundtrip only",
            "coords": "retained for UI roundtrip only"
          },
          "coords_used_in_dwelling_model_merge": false
        },
        "row_contract": {
          "payload_contract": {
            "schema_pointer": "#/properties/ExternalConditions/properties/shading_segments/items/properties/shading/items",
            "target_path": "ExternalConditions.shading_segments[].shading[]",
            "field_paths": [
              "shading_type",
              "Type",
              "distance",
              "height"
            ],
            "segment_angles": {
              "schema_pointer": "#/properties/ExternalConditions/properties/shading_segments/items",
              "target_path": "ExternalConditions.shading_segments[]",
              "csv_columns": [
                "start_angle",
                "end_angle"
              ],
              "maps_to_schema_properties": {
                "start_angle": "start360",
                "end_angle": "end360"
              }
            }
          }
        },
        "authoring_requirements": {
          "parser_required_columns": [
            "Name",
            "Type"
          ],
          "parser_shape_note": "Each row must include Name and Type columns (empty Type cell is allowed when shading_type supplies obstacle/overhang). Conversion reads shading_type first, then Type, for the shading kind."
        }
      },
      "On-Site Generation": {
        "description": "On-site generation systems (e.g. PV) records.",
        "merge_glossary_backrefs": [
          "merge_onsite_generation_named_entries"
        ],
        "fields_by_type": {
          "OnSiteGeneration": {
            "ui_fields": {
              "standard_fields": [
                "peak_power",
                "pitch",
                "orientation360",
                "base_height",
                "height",
                "width",
                "area"
              ],
              "advanced_fields": [
                "EnergySupply",
                "depth",
                "distance",
                "inverter_is_inside",
                "inverter_peak_power_ac",
                "inverter_peak_power_dc",
                "inverter_type",
                "shading",
                "ventilation_strategy"
              ]
            },
            "extra_json": {
              "supported_fields": [
                "EnergySupply",
                "depth",
                "distance",
                "inverter_is_inside",
                "inverter_peak_power_ac",
                "inverter_peak_power_dc",
                "inverter_type",
                "shading",
                "ventilation_strategy"
              ]
            }
          }
        },
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "Type",
            "required": true,
            "role": "element_type",
            "values": [
              "OnSiteGeneration"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "generation_type",
            "required": true,
            "role": "generation_type",
            "values": [
              "PhotovoltaicSystem"
            ],
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_accurate"
          },
          {
            "name": "pitch",
            "required": false,
            "role": "panel_pitch",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "orientation360",
            "required": false,
            "role": "panel_orientation",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "base_height",
            "required": false,
            "role": "panel_base_height",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "peak_power",
            "required": false,
            "role": "peak_power_kw",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "panel_polygon",
            "field_contract_ref": "#/csv_contract/field_contracts/coords_polygon_3d",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "advanced_payload",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          }
        ],
        "row_contract": {
          "payload_contract": {
            "schema_pointer": "#/properties/OnSiteGeneration/additionalProperties",
            "target_path": "OnSiteGeneration.<Name>",
            "field_paths": [
              "type",
              "peak_power",
              "pitch",
              "orientation360",
              "base_height"
            ],
            "effects": [
              {
                "kind": "coords_bbox_sets_width_and_height_when_missing_or_zero"
              }
            ]
          }
        },
        "authoring_requirements": {
          "conversion_required_fields": [
            "Name",
            "generation_type"
          ]
        }
      },
      "Systems": {
        "description": "System composition rows for heating/hot water/cooling components.",
        "notes": "System rows are dispatched by Type/system_type (or subcategory fallback for Type=System). Builder merge also reads zone_reference (see references) on some branches alongside Zone. FHS: `HotWaterSource` must be authored (Systems row and/or `HeatSourceWet` `extra_json` composite); the defaults template is not a substitute.",
        "fields_by_type": {
          "HeatSourceWet": {
            "output_mapping": {
              "target_path": "HeatSourceWet",
              "merge_mode": "replace_whole_section_when_wrapped_or_insert_named_entry_when_flat"
            },
            "payload_contract": {
              "schema_pointer": "#/properties/HeatSourceWet",
              "field_paths": [
                "A",
                "B",
                "EnergySupply",
                "EnergySupply_aux",
                "backup_ctrl_type",
                "battery_type",
                "boiler_location",
                "efficiency_full_load",
                "efficiency_part_load",
                "electricity_circ_pump",
                "electricity_full_load",
                "electricity_part_load",
                "electricity_standby",
                "flow_rate_l_per_min",
                "heat_storage_kJ_per_K_above_Phase_transition",
                "heat_storage_kJ_per_K_below_Phase_transition",
                "heat_storage_kJ_per_K_during_Phase_transition",
                "inlet_diameter_mm",
                "is_heat_network",
                "max_rated_losses",
                "max_temperature",
                "min_modulation_rate_20",
                "min_modulation_rate_35",
                "min_modulation_rate_55",
                "min_temp_diff_flow_return_for_hp_to_operate",
                "modulating_control",
                "modulation_load",
                "number_of_units",
                "phase_transition_temperature_lower",
                "phase_transition_temperature_upper",
                "power_crankcase_heater",
                "power_heating_circ_pump",
                "power_heating_warm_air_fan",
                "power_max_backup",
                "power_off",
                "power_source_circ_pump",
                "power_standby",
                "rated_charge_power",
                "rated_power",
                "simultaneous_charging_and_discharging",
                "sink_type",
                "source_type",
                "temp_lower_operating_limit",
                "temp_return_feed_max",
                "test_data_EN14825[]",
                "time_constant_onoff_operation",
                "var_flow_temp_ctrl_during_test",
                "velocity_in_HEX_tube_at_1_l_per_min_m_per_s"
              ],
              "runtime_branch_field_paths": {
                "HeatPump": [
                  "EnergySupply",
                  "backup_ctrl_type",
                  "is_heat_network",
                  "min_modulation_rate_20",
                  "min_modulation_rate_35",
                  "min_modulation_rate_55",
                  "min_temp_diff_flow_return_for_hp_to_operate",
                  "modulating_control",
                  "power_crankcase_heater",
                  "power_heating_circ_pump",
                  "power_heating_warm_air_fan",
                  "power_max_backup",
                  "power_off",
                  "power_source_circ_pump",
                  "power_standby",
                  "sink_type",
                  "source_type",
                  "temp_lower_operating_limit",
                  "temp_return_feed_max",
                  "test_data_EN14825[]",
                  "time_constant_onoff_operation",
                  "var_flow_temp_ctrl_during_test"
                ],
                "Boiler": [
                  "EnergySupply",
                  "EnergySupply_aux",
                  "boiler_location",
                  "efficiency_full_load",
                  "efficiency_part_load",
                  "electricity_circ_pump",
                  "electricity_full_load",
                  "electricity_part_load",
                  "electricity_standby",
                  "is_heat_network",
                  "modulation_load",
                  "rated_power"
                ],
                "HeatBattery": [
                  "A",
                  "B",
                  "EnergySupply",
                  "battery_type",
                  "electricity_circ_pump",
                  "electricity_standby",
                  "flow_rate_l_per_min",
                  "heat_storage_kJ_per_K_above_Phase_transition",
                  "heat_storage_kJ_per_K_below_Phase_transition",
                  "heat_storage_kJ_per_K_during_Phase_transition",
                  "inlet_diameter_mm",
                  "is_heat_network",
                  "max_rated_losses",
                  "max_temperature",
                  "number_of_units",
                  "phase_transition_temperature_lower",
                  "phase_transition_temperature_upper",
                  "rated_charge_power",
                  "simultaneous_charging_and_discharging",
                  "velocity_in_HEX_tube_at_1_l_per_min_m_per_s"
                ],
                "ImmersionHeater": [
                  "EnergySupply",
                  "is_heat_network"
                ]
              },
              "accepted_top_level_shapes": [
                {
                  "id": "wrapped_map",
                  "wrapper_key": "HeatSourceWet",
                  "entry_key_source": "payload_object_key",
                  "merge_behavior": "replace_root_section"
                },
                {
                  "id": "flat_named_entry",
                  "entry_key_source": "row.Name",
                  "merge_behavior": "insert_named_entry"
                }
              ],
              "effects": [
                {
                  "kind": "replace_sibling_section",
                  "target_path": "HotWaterSource",
                  "when_shape": "wrapped_map"
                },
                {
                  "kind": "repoint_reference",
                  "target_path": "SpaceHeatSystem.*.HeatSource.name",
                  "source": "first_inserted_key",
                  "when_shape": "wrapped_map"
                },
                {
                  "kind": "repoint_reference",
                  "target_path": "HotWaterSource.*",
                  "source": "first_inserted_key",
                  "when_shape": "wrapped_map"
                },
                {
                  "kind": "inject_default",
                  "field": "is_heat_network",
                  "value": false,
                  "when_shape": "flat_named_entry",
                  "when_missing": true
                }
              ]
            }
          },
          "HotWaterDemand": {
            "ui_fields": {
              "standard_fields": [
                "subcategory",
                "size",
                "flowrate",
                "rated_power",
                "parent_element"
              ]
            },
            "output_mapping": {
              "target_path": "HotWaterDemand",
              "merge_mode": "merge_wrapped_fragment_into_root_section"
            },
            "payload_contract": {
              "schema_pointer": "#/properties/HotWaterDemand",
              "field_paths": [
                "Bath",
                "Other",
                "Shower"
              ],
              "wrapped_fragment_field_paths": [
                "Bath",
                "Other",
                "Shower"
              ],
              "accepted_top_level_shapes": [
                {
                  "id": "wrapped_fragment",
                  "wrapper_key": "HotWaterDemand",
                  "merge_behavior": "merge_root_fragment"
                }
              ]
            }
          },
          "HotWaterSource": {
            "output_mapping": {
              "target_path": "HotWaterSource",
              "merge_mode": "replace_whole_section_when_wrapped_or_insert_named_entry_when_flat"
            },
            "payload_contract": {
              "schema_pointer": "#/properties/HotWaterSource",
              "field_paths": [
                "ColdWaterSource",
                "HeatSource",
                "HeatSourceWet",
                "daily_losses",
                "init_temp",
                "primary_pipework[]",
                "rejected_energy_1",
                "rejected_factor_3",
                "separate_DHW_tests",
                "storage_loss_factor_1",
                "storage_loss_factor_2",
                "volume"
              ],
              "runtime_branch_field_paths": {
                "StorageTank": [
                  "ColdWaterSource",
                  "HeatSource",
                  "daily_losses",
                  "init_temp",
                  "primary_pipework[]",
                  "volume"
                ],
                "CombiBoiler": [
                  "ColdWaterSource",
                  "HeatSourceWet",
                  "rejected_energy_1",
                  "rejected_factor_3",
                  "separate_DHW_tests",
                  "storage_loss_factor_1",
                  "storage_loss_factor_2"
                ]
              },
              "accepted_top_level_shapes": [
                {
                  "id": "wrapped_map",
                  "wrapper_key": "HotWaterSource",
                  "entry_key_source": "payload_object_key",
                  "merge_behavior": "replace_root_section"
                },
                {
                  "id": "flat_named_entry",
                  "entry_key_source": "row.Name",
                  "merge_behavior": "insert_named_entry"
                }
              ]
            }
          },
          "InfiltrationVentilation": {
            "output_mapping": {
              "target_path": "InfiltrationVentilation",
              "merge_mode": "merge_wrapped_fragment_into_root_section"
            },
            "payload_contract": {
              "schema_pointer": "#/properties/InfiltrationVentilation",
              "field_paths": [
                "Leaks.env_area",
                "Leaks.test_pressure",
                "Leaks.test_result",
                "Leaks.ventilation_zone_height",
                "MechanicalVentilation",
                "Vents",
                "ach_max_static_calcs",
                "ach_min_static_calcs",
                "altitude",
                "noise_nuisance",
                "shield_class",
                "terrain_class",
                "ventilation_zone_base_height"
              ],
              "wrapped_fragment_field_paths": [
                "Leaks.env_area",
                "Leaks.test_pressure",
                "Leaks.test_result",
                "Leaks.ventilation_zone_height",
                "MechanicalVentilation",
                "Vents",
                "ach_max_static_calcs",
                "ach_min_static_calcs",
                "altitude",
                "noise_nuisance",
                "shield_class",
                "terrain_class",
                "ventilation_zone_base_height"
              ],
              "accepted_top_level_shapes": [
                {
                  "id": "wrapped_fragment",
                  "wrapper_key": "InfiltrationVentilation",
                  "merge_behavior": "merge_root_fragment"
                }
              ]
            }
          },
          "SpaceCoolSystem": {
            "output_mapping": {
              "target_path": "SpaceCoolSystem",
              "merge_mode": "replace_whole_section_when_wrapped_or_insert_named_entry_when_flat_then_reconcile_zone_references"
            },
            "references": [
              {
                "field": "zone_reference",
                "targets_section": "Zone",
                "match_rule": "used to associate created cooling systems back to zones"
              }
            ],
            "payload_contract": {
              "schema_pointer": "#/properties/SpaceCoolSystem",
              "field_paths": [
                "EnergySupply",
                "advanced_start",
                "cooling_capacity",
                "efficiency",
                "frac_convective",
                "temp_setback"
              ],
              "runtime_branch_field_paths": {
                "AirConditioning": [
                  "EnergySupply",
                  "advanced_start",
                  "cooling_capacity",
                  "efficiency",
                  "frac_convective",
                  "temp_setback"
                ]
              },
              "accepted_top_level_shapes": [
                {
                  "id": "wrapped_map",
                  "wrapper_key": "SpaceCoolSystem",
                  "entry_key_source": "payload_object_key",
                  "merge_behavior": "replace_root_section"
                },
                {
                  "id": "flat_named_entry",
                  "entry_key_source": "row.Name",
                  "merge_behavior": "insert_named_entry"
                }
              ],
              "effects": [
                {
                  "kind": "reconcile_zone_references",
                  "source_fields": [
                    "Zone",
                    "zone_reference"
                  ],
                  "when_shape": "wrapped_map_or_flat_named_entry"
                }
              ]
            }
          },
          "SpaceHeatSystem": {
            "conversion_requirements": {
              "required_fields": [
                "Name"
              ]
            },
            "output_mapping": {
              "target_path": "SpaceHeatSystem",
              "merge_mode": "merge_wrapped_fragment_into_root_section_or_seed_named_wet_distribution"
            },
            "payload_contract": {
              "schema_pointer": "#/properties/SpaceHeatSystem",
              "field_paths": [
                "EnergySupply",
                "HeatSource.name",
                "HeatSource.temp_flow_limit_upper",
                "Zone",
                "air_flow_type",
                "bypass_fraction_recirculated",
                "convective_type",
                "design_flow_temp",
                "dry_core_max_output[]",
                "dry_core_min_output[]",
                "ecodesign_controller.ecodesign_control_class",
                "ecodesign_controller.max_outdoor_temp",
                "ecodesign_controller.min_flow_temp",
                "ecodesign_controller.min_outdoor_temp",
                "emitters[]",
                "frac_convective",
                "max_flow_rate",
                "min_flow_rate",
                "n_units",
                "pwr_in",
                "rated_power",
                "rated_power_instant",
                "storage_capacity",
                "temp_diff_emit_dsgn",
                "thermal_mass",
                "variable_flow"
              ],
              "runtime_branch_field_paths": {
                "WetDistribution": [
                  "EnergySupply",
                  "HeatSource.name",
                  "HeatSource.temp_flow_limit_upper",
                  "Zone",
                  "bypass_fraction_recirculated",
                  "design_flow_temp",
                  "ecodesign_controller.ecodesign_control_class",
                  "ecodesign_controller.max_outdoor_temp",
                  "ecodesign_controller.min_flow_temp",
                  "ecodesign_controller.min_outdoor_temp",
                  "emitters[]",
                  "max_flow_rate",
                  "min_flow_rate",
                  "temp_diff_emit_dsgn",
                  "thermal_mass",
                  "variable_flow"
                ],
                "ElecStorageHeater": [
                  "EnergySupply",
                  "Zone",
                  "air_flow_type",
                  "dry_core_max_output[]",
                  "dry_core_min_output[]",
                  "frac_convective",
                  "n_units",
                  "pwr_in",
                  "rated_power_instant",
                  "storage_capacity"
                ],
                "InstantElecHeater": [
                  "EnergySupply",
                  "convective_type",
                  "rated_power"
                ]
              },
              "accepted_top_level_shapes": [
                {
                  "id": "flat_row_overlay",
                  "entry_key_source": "row.Name",
                  "merge_behavior": "seed_named_entry_then_overlay_flat_fields"
                },
                {
                  "id": "wrapped_fragment",
                  "wrapper_key": "SpaceHeatSystem",
                  "merge_behavior": "merge_root_fragment"
                }
              ],
              "effects": [
                {
                  "kind": "force_type",
                  "field": "type",
                  "value": "WetDistribution",
                  "when_shape": "flat_row_overlay"
                },
                {
                  "kind": "seed_from_template",
                  "template_id": "SpaceHeatSystemWetDistribution",
                  "when_shape": "flat_row_overlay"
                }
              ]
            }
          },
          "WWHRS": {
            "output_mapping": {
              "target_path": "WWHRS",
              "merge_mode": "merge_wrapped_fragment_into_root_section"
            },
            "payload_contract": {
              "schema_pointer": "#/properties/WWHRS",
              "field_paths": [
                "ColdWaterSource",
                "flow_rates",
                "system_a_efficiencies",
                "system_a_utilisation_factor",
                "system_b_efficiencies",
                "system_b_efficiency_factor",
                "system_b_utilisation_factor",
                "system_c_efficiencies",
                "system_c_efficiency_factor",
                "system_c_utilisation_factor",
                "type"
              ],
              "accepted_top_level_shapes": [
                {
                  "id": "wrapped_fragment",
                  "wrapper_key": "WWHRS",
                  "merge_behavior": "merge_root_fragment"
                }
              ]
            }
          }
        },
        "output_mapping": {
          "target_path": "multiple_root_sections",
          "merge_mode": "branch_specific_by_Type_system_type_and_subcategory"
        },
        "references": [
          {
            "field": "zone_reference",
            "targets_section": "Zone",
            "match_rule": "used by some system branches when assigning zone-linked output"
          }
        ],
        "csv_columns": [
          {
            "name": "Name",
            "required": true,
            "role": "row_name",
            "used_by_row_kinds": [
              "electric_battery",
              "named_space_heat_system",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "when": "Required for named SpaceHeatSystem / WetDistribution rows and System fragment rows (see row_kinds); optional for ElectricBattery-only rows.",
            "authoring_note": "Require Name on all rows for traceability if your integrator policy demands it.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "Zone",
            "required": false,
            "role": "zone_reference",
            "used_by_row_kinds": [
              "electric_battery",
              "named_space_heat_system",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "when": "Required where merge assigns zone-linked systems (e.g. named_space_heat_system, some System subcategories); inert for other branches.",
            "authoring_note": "Builder may also read zone_reference (see references) for zone linkage.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "Type",
            "required": true,
            "role": "primary_dispatch",
            "used_by_row_kinds": [
              "electric_battery",
              "named_space_heat_system",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "when": "Effective dispatch uses Type, else system_type, else subcategory; at least one must identify the row or merge errors/skips apply.",
            "authoring_note": "For PCDB-style fragments, outer Type should be System with subcategory selecting fields_by_type.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "system_type",
            "required": false,
            "role": "legacy_primary_dispatch",
            "used_by_row_kinds": [
              "electric_battery",
              "named_space_heat_system",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "authoring_note": "Legacy alias for Type in dispatch order.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "subcategory",
            "required": false,
            "role": "secondary_dispatch",
            "used_by_row_kinds": [
              "electric_battery",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "when": "Required when Type is System (PCDB-style); can participate in legacy dispatch when Type/system_type empty.",
            "authoring_note": "Empty subcategory on System rows leads to skip or unknown-branch warning.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          },
          {
            "name": "system_preset",
            "required": false,
            "role": "ui_preset_hint",
            "used_by_row_kinds": [
              "system_fragment"
            ],
            "required_in_section_header": false,
            "authoring_note": "Tooling hint only; not merged into dwelling model JSON.",
            "merge_effect": "workflow_only",
            "populate_requirement": "optional_default_or_derived"
          },
          {
            "name": "coords",
            "required": false,
            "role": "ui_roundtrip_geometry",
            "used_by_row_kinds": [
              "electric_battery",
              "named_space_heat_system",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "plotting_note": "Editor/canvas round-trip only; coords are not used for dwelling-model physics.",
            "merge_effect": "not_in_calculation_input",
            "populate_requirement": "optional_plot"
          },
          {
            "name": "extra_json",
            "required": false,
            "role": "payload",
            "used_by_row_kinds": [
              "electric_battery",
              "named_space_heat_system",
              "system_fragment"
            ],
            "required_in_section_header": false,
            "when": "Payload for System and ElectricBattery paths; may be minimal when template defaults fill the merged object.",
            "authoring_note": "Treat as required_accurate for strict authoring if templates are not trusted to complete the fragment.",
            "merge_effect": "affects_calculation_input",
            "populate_requirement": "required_conditional"
          }
        ],
        "row_kinds": {
          "electric_battery": {
            "match": {
              "Type": [
                "ElectricBattery"
              ],
              "legacy_subcategory": [
                "ElectricBattery"
              ],
              "dispatch_fallback_order": [
                "Type",
                "system_type",
                "subcategory"
              ]
            },
            "target_path": "EnergySupply.<extra_json.EnergySupply or 'mains elec'>.ElectricBattery",
            "payload_contract": {
              "schema_pointer": "#/$defs/ElectricityFuelProperties/properties/ElectricBattery",
              "field_paths": [
                "battery_location",
                "capacity",
                "charge_discharge_efficiency_round_trip",
                "maximum_charge_rate_one_way_trip",
                "maximum_discharge_rate_one_way_trip",
                "minimum_charge_rate_one_way_trip"
              ],
              "accepted_top_level_shapes": [
                {
                  "id": "flat_object",
                  "entry_key_source": "selected_energy_supply",
                  "merge_behavior": "seed_template_then_overlay_flat_fields"
                }
              ],
              "effects": [
                {
                  "kind": "route_under_energy_supply",
                  "routing_field": "EnergySupply",
                  "default_value": "mains elec"
                },
                {
                  "kind": "force_value",
                  "target_path": "EnergySupply.<selected>.fuel",
                  "value": "electricity"
                }
              ]
            }
          },
          "named_space_heat_system": {
            "match": {
              "Type": [
                "SpaceHeatSystem",
                "WetDistribution"
              ],
              "dispatch_fallback_order": [
                "Type",
                "system_type",
                "subcategory"
              ]
            },
            "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/SpaceHeatSystem",
            "entry_key_source": "row.Name"
          },
          "system_fragment": {
            "match": {
              "Type": [
                "System"
              ],
              "dispatch_fallback_order": [
                "Type",
                "system_type",
                "subcategory"
              ]
            },
            "dispatch_field": "subcategory",
            "routes": {
              "HeatSourceWet": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/HeatSourceWet"
              },
              "HotWaterSource": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/HotWaterSource"
              },
              "SpaceCoolSystem": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/SpaceCoolSystem"
              },
              "InfiltrationVentilation": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/InfiltrationVentilation"
              },
              "HotWaterDemand": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/HotWaterDemand"
              },
              "SpaceHeatSystem": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/SpaceHeatSystem"
              },
              "WWHRS": {
                "contract_ref": "#/csv_contract/sections/Systems/fields_by_type/WWHRS"
              }
            }
          }
        },
        "authoring_requirements": {
          "alternative_required_field_groups": [
            [
              "Type",
              "system_type"
            ]
          ],
          "required_values": {
            "subcategory": {
              "values": [
                "HeatSourceWet",
                "HotWaterSource",
                "SpaceCoolSystem",
                "InfiltrationVentilation",
                "HotWaterDemand",
                "SpaceHeatSystem",
                "WWHRS"
              ],
              "enforced_by": "conversion_branch_handling"
            }
          }
        }
      }
    },
    "type_requirements": {
      "System": {
        "required_fields": [
          "Name"
        ]
      }
    },
    "extra_json_guidance": {
      "purpose": "extra_json carries fields beyond plain CSV columns; values merge after column cells using the usual precedence (CSV > extra_json > defaults unless the section says otherwise).",
      "schema_mode": "fhs",
      "schema_path": "hem_fhs_upstream/schema/input_fhs.schema.json",
      "cross_platform_warning": "Treat extra_json as strict JSON when exchanging files between tools. Browser import may drop invalid cells; other tooling may keep them as plain text\u2014do not rely on the same error handling everywhere.",
      "accepted_keys_strategy": {
        "building_elements": "Advanced keys mirror the FHS element subschemas, excluding columns already modeled as standard CSV headers and excluding fields the app UI deliberately hides (e.g. HotWaterSource primary_pipework is authored from the `Water Pipework` section, not the System \u201cHot water\u201d advanced panel in the FHS web app).",
        "ventilation_systems": "Advanced keys mirror the FHS-backed editor surface for Vents, MechanicalVentilation, and ductwork rows.",
        "combustion_appliances": "Advanced keys mirror the public FHS-backed UI/schema surface (not ad-hoc conversion allowlists).",
        "water_pipework": "On each `WaterPipework` row, extra_json overlays the WaterPipework item schema (same keys you could place on a primary_pipework[] element) after CSV column overlay; the section split primary vs distribution is by pipework_type (see that section's notes).",
        "wet_emitters": "Advanced keys mirror the public FHS-backed UI/schema surface; the app may still adjust some emitter fields outside raw extra_json editing.",
        "systems": "Use row_kinds and payload_contract in this file; field paths follow the FHS-backed editor surface with branch coverage inferred from defaults and shipped presets."
      },
      "guidance": "Use section field tables first; use row_kinds / payload_contract when the contract splits behaviour by branch.",
      "malformed_json_behavior": {
        "prominence": "Invalid JSON handling differs by product—fail closed in your exporter unless you know your runtime.",
        "rust_geometry_pipeline": "Batch/native tooling may keep malformed JSON as a string so later steps can still run.",
        "web_import": "Browser import drops invalid extra_json."
      }
    },
    "merge_effect_definitions": {
      "affects_calculation_input": {
        "label": "Merged into dwelling calculation input JSON",
        "detail": "After merge precedence (CSV > extra_json > defaults) and schema allowlists, values feed dwelling_calculation_input_json. Later FHS postprocess or exporters may reshape or omit some keys, but this flag means the conversion step treated the cell as model input."
      },
      "not_in_calculation_input": {
        "label": "Not copied into the dwelling model JSON on this path",
        "detail": "The field may exist in CSV or editor state for layout, QA, or round-trip, but the conversion step that builds the dwelling model JSON does not treat it as an input for that merge path. Overlaps conceptually with CSV/editor round-trip: both mean the regulated solver path does not consume the value from this merge."
      },
      "workflow_only": {
        "label": "Pipeline or editor workflow only",
        "detail": "Documented for surrounding tools (paths, profiles, validation switches). The geometry-to-model conversion step does not merge these keys into the dwelling model JSON."
      },
      "csv_or_ui_round_trip": {
        "label": "CSV, export, or editor round-trip",
        "detail": "For labels or UI/export round-trip—not treated as regulated model input on this path (often overlaps optional layout-only cells with “not in calculation input”)."
      },
      "section_rows_not_merged": {
        "label": "Section accepted; rows ignored for model merge",
        "detail": "Section-level tag: parser accepts the header but geometry-to-model conversion does not merge rows into dwelling_calculation_input_json. Prefer terminology.section_accepted_rows_ignored_for_model in new prose."
      }
    },
    "populate_requirement_definitions": {
      "required_accurate": {
        "label": "Must be correct for the dwelling",
        "detail": "Leaving this blank or wrong would mis-state the building for compliance or physics; defaults do not reliably replace a dwelling-specific value."
      },
      "required_conditional": {
        "label": "Required only in some cases",
        "detail": "Omit when the rule does not apply; when it does, treat like Required. Field tables show a grey “when …” line under the chip when the contract exposes a row-kind match for that column."
      },
      "optional_default_or_derived": {
        "label": "Optional if defaults or other cells fill it",
        "detail": "A blank cell can be OK because the pipeline supplies a default, derives the value from other inputs, or the field does not affect the outcome on this path."
      },
      "optional_plot": {
        "label": "For drawings, checks, or layout only",
        "detail": "Needed for meaningful plans, 3D, or QA, but not for numeric compliance correctness on its own. Include `plotting_note` where this class is used."
      }
    }
  }
}
