Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/explanation/consumers.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ of the other language. For the parity side of the same governance, see

<!-- BEGIN GENERATED FROM consumers.toml. Edit the register, not this page. -->

Generated from [`governance/consumers.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.20/governance/consumers.toml) at `governance-2026.20`, the governance tag this
Generated from [`governance/consumers.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.22/governance/consumers.toml) at `governance-2026.22`, the governance tag this
release pins. Correct the register and regenerate; a correction made on this page would be
overwritten, and it would never reach a consumer's self-check.

Expand Down
120 changes: 113 additions & 7 deletions docs/explanation/naming-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ ledger, where permanent single-language capabilities are recorded as such.
<!-- BEGIN GENERATED FROM naming.toml. Edit the register, not this page. -->

Generated from
[`governance/naming.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.20/governance/naming.toml)
at `governance-2026.20`, the governance tag this release pins. It governs `idfkit` and
`@idfkit/core` and `@idfkit/weather` and `@idfkit/language`, and it is read at a pinned
governance-YYYY.N tag of idfkit-conformance, never the default branch. Correct the
register and regenerate; a correction made on this page would be overwritten, and it
would never reach either library's naming gate.
[`governance/naming.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.22/governance/naming.toml)
at `governance-2026.22`, the governance tag this release pins. It governs `idfkit` and
`@idfkit/core` and `@idfkit/geometry` and `@idfkit/weather` and `@idfkit/language`, and
it is read at a pinned governance-YYYY.N tag of idfkit-conformance, never the default
branch. Correct the register and regenerate; a correction made on this page would be
overwritten, and it would never reach either library's naming gate.

## Guessing a name before you look it up

Expand Down Expand Up @@ -367,6 +367,18 @@ row marked divergent or excluded links to the entry that says why, and a cell re
| a zone's floor area | `calculate_zone_floor_area` | `calculateZoneFloorArea` | aligned |
| a zone's volume | `calculate_zone_volume` | `calculateZoneVolume` | aligned |

### The scene description, registered before either language implements it { #map-the-scene-description-registered-before-either-language-implements-it }

| Concept | Python | TypeScript | Kind |
| ------- | ------ | ---------- | ---- |
| a model's resolved geometry | `get_scene` | `getScene` | aligned |
| the resolved scene | `Scene` | `Scene` | aligned |
| a resolved surface | `ResolvedSurface` | `ResolvedSurface` | aligned |
| the rules resolution applied | `AppliedRules` | `AppliedRules` | aligned |
| the scene's extent | `SceneBounds` | `SceneBounds` | aligned |
| a surface that could not be resolved | `UnresolvedObject` | `UnresolvedObject` | aligned |
| a geometry type the reader did not attempt | `UnattemptedType` | `UnattemptedType` | aligned |

### Geometry authoring (registered ahead of the port) { #map-geometry-authoring-registered-ahead-of-the-port }

| Concept | Python | TypeScript | Kind |
Expand Down Expand Up @@ -830,6 +842,18 @@ it rewrites relative surface coordinates in place and updates `GlobalGeometryRul
is registered with the extraction group because every calculation below depends on
knowing which coordinate system it is reading.

The first language's implementation of this name is wrong and is corrected by the change
that lands the scene description above. Measured against the engine's own surface vertex
report over 17 models and 532 surfaces, it agrees on 5 of the 17, worst case 201.98 m.
It applies the building rotation to each surface within its own zone frame, which leaves
the zone layout unrotated so that the building is not rotated as a rigid body, and it
collects a zone's surfaces through the reference graph, which fenestration never matches
because a window references its parent wall rather than the zone.

Recorded here rather than only in the library, because a reader meets this name at its
definition and because the register presents this function and the read-only surface
above as one capability.

**a surface's tilt**

Registered before it is written. Degrees, using the EnergyPlus convention.
Expand Down Expand Up @@ -1086,6 +1110,88 @@ like the rest of that group.

Registered before it is written, with the geometry extraction group above.

**a model's resolved geometry**

Registered before it is written. Takes a document, returns the scene, modifies nothing.
Follows the `get_*` to `get*` pairing of the geometry extraction group above, which the
`a zone's surfaces` entry also cites.

One argument and no options. A filter over the result is a list operation the caller
already has, and a viewing option would put a viewing decision in a package that does
not draw.

**the resolved scene**

Registered before it is written. Carries the resolved surfaces in document order, the
extent, the rules resolution applied, the objects it could not resolve, and the object
types it did not attempt.

The last two are not diagnostics. A model whose geometry is stated in a form the reader
does not handle must be distinguishable from a model with no geometry, and the
difference between them is the difference between telling a reader their file is
unsupported and telling them it is broken.

**a resolved surface**

Registered before it is written. One surface in the scene: its polygon in the resolved
frame, its area, its outward normal, the address of the object it came from, the facts a
reader classifies it by, and for fenestration the surface it sits on.

Carries the canonical object type alongside the name, because a name is not unique
across types and a consumer that must search the document by name to discover what its
user selected has been handed a picture rather than a view of the model.

Classification values drawn from an enumerated schema field are reported in the schema's
spelling rather than the author's. EnergyPlus matches them without regard to case and
models exercise that freely: across the example set of EnergyPlus 26.1.0 the four
surface types appear under twelve spellings and the five fenestration types under nine,
`GLASSDOOR` and `GlassDoor` among them. A value outside the enumeration passes through
unchanged, because a category invented for it would tell the reader something the model
does not say.

Carries no colour, palette or visibility. The first language's viewing surface is
registered separately as excluded, and that exclusion is terminal.

**the rules resolution applied**

Registered before it is written. The coordinate system, the vertex entry direction, the
starting vertex position and the building rotation, each recorded as declared by the
model or defaulted.

The building rotation is recorded although it has already been applied to the vertices.
That is what makes the choice reversible: the scene's numbers are the numbers the engine
computes, so the oracle means what it says, and a consumer wanting to draw the building
unrotated under a compass can undo it exactly rather than reimplementing the clause most
easily got wrong.

**the scene's extent**

Registered before it is written. The smallest box enclosing every resolved vertex,
absent rather than degenerate when nothing resolved, so that a consumer does not frame
an empty box at the origin.

**a surface that could not be resolved**

Registered before it is written. An object extraction attempted and could not place,
with its type, its name and an enumerated reason.

The reason is an enumeration rather than a message, so that a consumer can group on it
and a reworded string does not change behaviour. The alternative this replaces is the
first language's current habit of skipping such an object silently in three places,
which is fine in a notebook and wrong everywhere else: a building drawn with a wall
missing still looks like a building.

**a geometry type the reader did not attempt**

Registered before it is written. An object type present in the model that the reader
does not read, with its count.

This is the mechanism by which a deferral stays honest. The first slice of this port
reads the detailed surface forms and not the simplified family; five of the example
models state their geometry only in the simplified forms and hold no detailed surface at
all. Without this entry those five report as empty, which tells a reader their file is
broken rather than that this reader does not read it yet.

**set the window to wall ratio**

Registered before it is written. `wwr` stays lowercase in TypeScript by the same rule
Expand Down Expand Up @@ -3825,7 +3931,7 @@ one language under schedule pressure.
| Capability | npm package | Subpath | Mirrors | Tier | Built |
| ---------- | ----------- | ------- | ------- | ---- | ----- |
| schedules | `@idfkit/schedules` | `@idfkit/idfkit/schedules` | `idfkit.schedules` | 2 | not yet |
| geometry, geometry builders, surface matching, zoning | `@idfkit/geometry` | `@idfkit/idfkit/geometry` | `idfkit.geometry`, `idfkit.geometry_builders`, `idfkit.surface_matching`, `idfkit.zoning` | 2 | not yet |
| geometry, geometry builders, surface matching, zoning | `@idfkit/geometry` | `@idfkit/idfkit/geometry` | `idfkit.geometry`, `idfkit.geometry_builders`, `idfkit.surface_matching`, `idfkit.zoning` | 2 | yes |

## What the gate refuses

Expand Down
67 changes: 46 additions & 21 deletions docs/explanation/parity.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ Ids get added and deprecated. They do not get renamed.
<!-- BEGIN GENERATED FROM parity.toml. Edit the ledger, not this page. -->

Generated from
[`governance/parity.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.20/governance/parity.toml)
at `governance-2026.20`, the governance tag this release pins. Correct the ledger and
[`governance/parity.toml`](https://github.com/idfkit/idfkit-conformance/blob/governance-2026.22/governance/parity.toml)
at `governance-2026.22`, the governance tag this release pins. Correct the ledger and
regenerate; a correction made on this page would be overwritten, and it would never
reach either library's CI gate.

Expand All @@ -92,10 +92,10 @@ permanent.

| Availability | Python | JavaScript |
| ------------ | ------ | ---------- |
| complete | 31 | 17 |
| partial | 1 | 2 |
| absent, not yet | 0 | 12 |
| absent, never | 3 | 4 |
| complete | 31 | 16 |
| partial | 1 | 3 |
| absent, not yet | 0 | 11 |
| absent, never | 3 | 5 |

| Capability | Tier | Python | JavaScript |
| ---------- | ---- | ------ | ---------- |
Expand All @@ -114,7 +114,7 @@ permanent.
| [Declaring the conformance level a release passes](#conformance-declaration) | 1 | complete | complete |
| [Geocoding a place name](#geocoding) | 1 | complete | complete |
| [Formatting-preserving round-trip](#lossless-round-trip) | 2 | complete | complete |
| [Reading geometry from a model](#geometry-extraction) | 2 | complete | absent (not yet) |
| [Reading geometry from a model](#geometry-extraction) | 2 | complete | partial |
| [Building and transforming geometry](#geometry-authoring) | 2 | complete | absent (not yet) |
| [Intersecting and matching surfaces](#surface-matching) | 2 | complete | absent (not yet) |
| [Generating zoned blocks from a footprint](#zoning) | 2 | complete | absent (not yet) |
Expand All @@ -129,7 +129,7 @@ permanent.
| [Running a locally installed EnergyPlus and reading its results](#local-simulation) | permanent | complete | absent (never) |
| [Running EnergyPlus in the browser](#browser-simulation) | permanent | absent (never) | complete |
| [Rendering a model to a vector image](#svg-visualisation) | permanent | complete | absent (never) |
| [Rendering a three-dimensional scene](#scene-rendering) | permanent | absent (never) | complete |
| [Rendering a three-dimensional scene](#scene-rendering) | permanent | absent (never) | absent (never) |
| [eppy compatibility surface](#eppy-compatibility) | permanent | complete | absent (never) |
| [Caching retrieved weather files on disk](#weather-file-cache) | permanent | complete | absent (never) |
| [Language service for IDF text](#idf-language-service) | permanent | absent (never) | complete |
Expand Down Expand Up @@ -417,12 +417,20 @@ code supports.

### Reading geometry from a model { #geometry-extraction }

**Python** complete &middot; **JavaScript** absent (not yet) &middot; Tier 2 &middot; ledger id `geometry-extraction`
**Python** complete &middot; **JavaScript** partial &middot; Tier 2 &middot; ledger id `geometry-extraction`

!!! warning "Not in JavaScript yet"
!!! info "What differs, and why"

A temporary gap, not a boundary. The port is tracked in
[idfkit-js#13](https://github.com/idfkit/idfkit-js/issues/13).
TypeScript carries the vector, the polygon and the resolved scene. `getScene` places every detailed
surface a model states and reports what it could not place and what it did not attempt, so a reader
who wants a model's geometry has it in both languages.

What it does not carry is the per-object calculation surface Python spells as free functions over an
IDF object: a zone's origin and its rotation, a surface's area, tilt and azimuth read from the
object rather than from a polygon, a zone's floor area, ceiling area, height and volume, and the
two-dimensional polygon predicates. Python's `translate_to_world` has no counterpart either, and
will not have the same one: it resolves by mutating the document, where `getScene` resolves into a
value and leaves the model alone.

??? note "Vocabulary this capability owns in the naming register"

Expand All @@ -437,6 +445,13 @@ code supports.
- a surface's azimuth
- a zone's floor area
- a zone's volume
- a model's resolved geometry
- the resolved scene
- a resolved surface
- the rules resolution applied
- the scene's extent
- a surface that could not be resolved
- a geometry type the reader did not attempt

### Building and transforming geometry { #geometry-authoring }

Expand Down Expand Up @@ -683,18 +698,28 @@ two different mechanisms serving two different runtimes.

### Rendering a three-dimensional scene { #scene-rendering }

**Python** absent (never) &middot; **JavaScript** complete &middot; Permanently single-language &middot; ledger id `scene-rendering`
**Python** absent (never) &middot; **JavaScript** absent (never) &middot; Permanently single-language &middot; ledger id `scene-rendering`

!!! abstract "JavaScript only, permanently"
!!! abstract "Permanently absent"

To be delivered by @idfkit/viewer, installed by its own name like the simulation engine, and NOT
reachable through the shared install name: no subpath, no dependency, no export-map entry, and no
reserved name in the naming register. A reader would reach it by installing it explicitly, and the
documentation says so rather than implying the facade carries it.

Delivered by @idfkit/viewer, installed by its own name like the simulation engine, and NOT reachable
through the shared install name: no subpath, no dependency, no export-map entry, and no reserved
name in the naming register. A reader reaches it by installing it explicitly, and the documentation
says so rather than implying the facade carries it.
@idfkit/viewer DOES NOT EXIST. This row read `typescript = "complete"` until the change that landed
geometry extraction, and no such package is in `idfkit-js/packages`, published or unpublished. The
distinction matters more here than the word "unreachable" carries on its own: a reader meeting only
this row would otherwise conclude that a renderer is a `npm install` away, and a specification
waiting on one would be waiting on a claim rather than on a package. Nothing in feature 009 depends
on this row's value, and nothing waiting on a renderer may.

Python has no counterpart and is not getting one. A real-time interactive scene needs a rendering
context that a Python process does not have, and Python's static vector output is a different
mechanism serving a different workflow: see [`svg-visualisation`](#svg-visualisation). Neither is a gap in the other.
The single `absence_kind` covers two absences of different character, and the file has one field for
it. Python's absence is terminal: a real-time interactive scene needs a rendering context that a
Python process does not have, and Python's static vector output is a different mechanism serving a
different workflow, [`svg-visualisation`](#svg-visualisation). Neither is a gap in the other. TypeScript's absence is
merely present-tense, and the `never` this row carries is the one its tier already states: this
capability is not part of the shared surface in either language, whoever builds it and whenever.

### eppy compatibility surface { #eppy-compatibility }

Expand Down
Loading
Loading