# Conformance

An implementation conforms to OpenEik 0.3 in one or more **classes**. It claims a class by meeting every requirement this page lists for it; it MAY claim several. A claim names the version (`OpenEik 0.3.0`) and the classes, for example "OpenEik 0.3.0 reader and validator". A claim to 0.2 (`OpenEik 0.2`) is a claim to the classes of 0.2 as the tag `v0.2.3` has them, the same twelve without the rules 0.3 adds; a claim to 0.1 (`OpenEik 0.1`) is a claim to the classes of 0.1 as the tag `v0.1.0` has them: eight, without the requirements of Parts XIII to XVIII, which were proposals in 0.1.

## 1. The classes

| Class | Does | MUST meet |
|---|---|---|
| **Reader** | reads models | Part I: 3, 4, 9 (formats and versions), 10 (keeps unknown members, and the elements and types of unknown categories), 11.2, rule 5 (reads a model with extension members as the model without them, and keeps them). Part II: 8.1 and 9 (keeps profile members, application records and values); 12.1 (keeps `declaredGeometry` unchanged, uses it only for what it is authoritative for, and never presents an envelope declared at the `interface` level as the part's detail). Part III: 1, 2, 4.1, rules 4 and 5 (accepts a component and a generic record in the folders they may be in), 7 (kept files; those of rule 8 left alone, the folder read on, and a version that holds one refused), 9, 10.4, 11, rule 3, and 11.1, rule 3 (reads the single-file form, whatever its file is called), 12 (reading, without a built-in library: it refuses what it cannot read, the list of section 12; the whole-model check of rule 5 is a SHOULD, and a reader that performs it refuses a folder that fails it). Part VI: 8, when it reads results or proposals (the earlier format ids read as the same formats; whether results are current) |
| **Validator** | says whether a model is valid, and why not | everything a reader must, plus: the whole-model check of Part III, 12, rule 5: validates every file against its schema (Part III, 3) and checks the rules of Parts I and II, among them two records' paths that fold to one and an id's length (Part I, 6, rules 7 and 8), a declaration's level, its terms, that it carries data for exactly the terms it lists, and its tolerances (Part II, 12.1, rules 1 to 4), a railing's host and edges and the type members its kind requires (Part II, 12.2), and that a generic element has declared geometry, its own or its type's, and no host (Part II, 6.6); checks the stored form and the paths (Part III, 4 and 5), and reports a file that is not in the stored form and a record at a path that disagrees with it as errors (Part III, 4.2 and 5, rule 6); reports the files Part III, 7, rule 8 leaves alone, as warnings, and such entries of a single-file model's `extras` as errors; names the file and the rule of every failure; never refuses an unknown member, an extension member or a record of an unknown category (Part I, 10, rules 2 and 5; 11.2, rules 5 and 9) |
| **Writer** | writes models | Part I: 6, 8, 9.2, 11 (members of its own only as extension members, under its prefix, and none added with the value `null`; no files in a reserved folder or another application's). Part II: 5.3, 6.4 (no legacy members), 6.6, rule 5 (a category that fits before `generic`), 10 (no derived data); 12.1 (moves, turns, mirrors and copies an element's declared geometry with it, rule 6, and never writes costs, prices or quotes into a record); 12.2, rule 4 (rewrites a hosted railing's profile, level and offset from its host). Part III: 4 (a record of an unknown category written back where it was read), 5, 7, rule 8 (no kept file whose name a file system refuses or reads otherwise, or whose path folds to another of the model's), 8 (the members of `eik.json` it does not know kept), 10, 13 (every named type written; kept files left alone). Part VI: 8, when it writes results or proposals |
| **Compiler (core)** | derives bodies from records | Part I: 11.2, rule 5 (derives from a model with extension members what it derives from the model without them). Part IV: 1 (nothing derived is stored; no body for an element of an unknown category, unless it can place its declared geometry), 4, 5 and 6 (the class-A rules, a shaft's cut, slab edge elements and gutters among them, and members' reference lines and axes); 7.3 to 7.6 (the class-A rules of straight, L and U stairs, a framed wall layer's members, a roof's truss layout and its hip ends, a floor's joists, a room's boundary, ceiling and quantities, and a component's frame and its bodies); 12 (pipe and duct bodies, within 12.5); 11.1 (derives nothing beyond what a declaration is authoritative for, uses the declared aspects in place of its own, and never derives fabrication data from declared geometry); 11.2 (the line of a railing on an outline, a wall's top or a slab edge element, and its given posts); 11.3 (a generic element: its declared bodies placed, and nothing more derived); 1.1 when it reads or writes the derived layer |
| **Command processor** | changes models by commands | Part I: 11.2, rule 5 (changes a model with extension members as it changes the model without them, but for keeping them, a precondition comparing the whole record). Part V: 1 to 9 and 11 (no record of an unknown category made, and those a model holds kept; no extension member whose value is `null` added; no new kinds; the transforms carry declared geometry, where it implements them), for the core record operations at least; the whole-model check of Parts I and II after every command |
| **Version store** | keeps versions | Part VI: 1 to 5, and 6 when it fetches from, pushes to, pulls from or clones a remote |
| **Agent host** | serves models to agents | Part VII: 1 to 8, headless; it says how many of a model's elements are generic (Part II, 6.6, rule 5); it is also a reader and, if it writes, a writer and a command processor |
| **Bridge** | exports to another format | Part VIII, 1, for each format it claims (for IFC, rule 4: generic elements, and 1.3: shafts' openings); Part IV, 11.1, rule 6 (says in its fidelity report which bodies are declared envelopes, and at which level) |
| **Drawing validator** | checks issued drawings | everything a validator must, plus Part XIV, 19.2: works out freshness (9.4; 9.7, rules 7 to 10), verifies sign-offs (14.3), and checks the rules that need the history where it has it; Part XVIII, 9: verifies statements, receipts and acceptances (4.3, rule 6; 5.3, rule 7; 6.2, rule 7), given the hosts' keys and the time-stamp authorities' certificates, and keeps 5.6, rules 6 and 7 |
| **Drawing issuer** | issues drawings | Part XIV, 19.2: issued drawings in the SVG profile (6), with the files, records and register of sections 7 to 11, a complete read set (9.1; 9.7, rule 6) and deterministic output; no drawing issued while a view on the sheet holds a proposed agent's item (3.4, rule 4), and never an SVG written by hand |
| **Host** | keeps a project's versions for several parties, and serves its reviews and issues | everything a version store must, plus Part XVI, 4, rule 4 (holds a change for its owners' approvals); Part XVIII, 9: keeps the events of 5.1 and offers receipts, publishes its keys as 5.6, rules 1 to 5 say, and keeps section 8, rules 1 and 4 |
| **Authoring tool** | makes the model people issue | everything a writer must, plus Part XVIII, 9: saves what a host offers, and records a named version of what it issues (3.2, rule 3) |

### 1.1 What Parts XIII to XVIII add to each class

Each part says, in its own section on conformance, what it asks of each class; a claim to a class of 0.2 is a claim to those requirements too. Where a part names no requirement for a class, it adds none.

| Class | Part XIII (11) | Part XIV (19) | Part XV (11) | Part XVI (8) | Part XVII (13) | Part XVIII (9) |
|---|---|---|---|---|---|---|
| Reader | circuits as records; the three categories as the part defines them | sheets and people as records; the drawing files as the part defines them | the files of `assets/`, as section 2 says | `project/owners.json` | | its files, as section 1 says |
| Validator | 2.3, 3.3, 4.1, 4.3, 4.4, 5 and 6, by severity | the rules the folder decides, by 19.3 | sections 2, 3, 4 and 8 | sections 2 and 3, rule 2 | | sections 2 to 6, as 9 lists |
| Writer | 2.3, rule 3; 3.3, rule 5; the circuits at their paths; a view's lighting scene (4.3) | sheets and people at their paths; issued files kept (7.4, rule 4) | section 4, rule 3 | | | |
| Compiler (core) | the bodies of section 7 | | | | | |
| Command processor | section 9 | 17.1 | | a change's paths (4) | envelopes and bare batches (8), sections 2, 3, 5, 6, 9, 10 and 11 | |
| Version store | | issued files and assets in its versions (7.3) | sections 5 and 6 | | | |
| Agent host | | | | | authentication and attribution (4.2) | |
| Bridge | section 10 (informative) | section 18 (informative) | | | | the version it prints from (7.2) |

Clash and layout checks are not a conformance class; Part II, 12.1, says how they use declared geometry.

## 2. How a claim is checked

- **Schemas.** `schemas/0.3/` holds a JSON Schema (2020-12) for every kind of file of 0.3, and `schemas/0.3/index.json` maps paths to them; `schemas/0.2/` holds those of 0.2 and `schemas/` those of 0.1, beside them, for reading a model of 0.2 or 0.1 (Part I, 9.4 and 9.6, rule 3).
- **The check tool.** `tools/check.mjs` checks a folder or a single-file model against the schemas, the stored form, the paths, unique ids, references and the format version, and the rules that need geometry or the types' sizes (an opening that fits its wall, an outline that does not cross itself, a top that lies above its base, an attached base or top over its host, the sizes a type sets), read from the records as Part IV states them. It is a partial validator: it does not check the framing families' expression language and parameters (Part II, 5.4), or that a sheet section follows its profiled sheet (5.2).
- **Examples.** `examples/` holds two folders written by the reference implementation, as folders of 0.2: `@openeik/tools` migrates them from 0.1 (`tools/build-example.mjs`), which changes their `eik.json` and their projects' files only. A reader MUST read both without error. A writer that reads one and writes it back without changes MUST write every record file it keeps byte for byte as it was (the reference writer does, and adds its library: see Part III, 13).
- **The conformance suite.** [`conformance/`](https://gitlab.com/openeik/spec/-/blob/main/conformance/README.md) holds test cases for the reader and validator classes, and for the drawing validator, each a small model and what a validator says and a reader does with it: one suite for 0.3, with the cases of Parts XIII to XVIII, of the sections 0.2 adds and of those 0.3 adds; the suite of 0.2 is at the tag `v0.2.3`.
- **Conformance vectors** for the compiler (Part IV, 10) are not published in 0.1. The pipe and duct fixtures of Part IV, 12.5 are a first set: runs with the results the rule gives, and the reference implementation's.
- **Model quality.** `openeik check --quality` in `packages/openeik` adds warnings for elements modelled under a category that does not fit them (a railing drawn as a plain component or a thin wall, a window as a box in a wall, a stair as stepped slabs), so that a supplier who looks for its parts by category finds them (Part II, 12). They are heuristics, not requirements of this specification: no claim depends on them, and a model with them can be valid.
- **Applications' files and a supplier's parts.** The schemas of the result manifest and the proposal file (Part VI, 8), in `schemas/applications/`, are written by hand from the text, and `index.json` lists them by their `format`; the check tool checks the result manifests and proposal files among a model's kept files against them, as warnings: a kept file is not a record, so a malformed one does not make the model invalid (Part III, 7). It also checks the rules of Part II, 12 that the schemas cannot state: a railing's host and the edges it names, as one run (12.2), the order of `railing.posts.at`, a load at a declared fixing, unit fixing directions, closed meshes and convex polyhedra (12.1); and that a generic element has declared geometry, its own or its type's (Part II, 6.6, rule 2).

## 3. The reference implementation's status

The reference implementation (Stomra's engine and `ek`) is the evidence that each requirement can be met. This text was written from it at `ff8574ec`; where it has met a requirement since, the table names the change. Where it does not yet meet one, this text says so beside the rule, and [open questions, section 2](https://openeik.org/spec/0.3/open-questions#2) lists it, a row each.

It reads and writes OpenEik 0.1: it refuses a folder or a version of 0.2, and writes `openeik/0.1-draft` in 0.1's folders, with no migration to 0.2 (open questions, section 2, rows 42 and 43). So it claims no class of 0.2 yet. The table says where it stands in each class with a model of 0.1, and what it does of Parts XIII to XVIII and of the sections 0.2 adds, as their notes say.

| Class | Status | Not yet met |
|---|---|---|
| Reader | meets most | adds its built-in library on load, so it also reads folders that lack a built-in type they name (Part III, 12); has no `generic` category (Part II, 6.6), and refuses an element or a type of a category it does not know, the generic ones among them (Part I, 10, rule 5), nor carries one through a pull. It reads and checks `eik.json` (Part I, 9.2) and keeps unknown members at every depth (Part I, 10) since Stomra #778 (live since 11 October 2026, `main` `8ebedf05`), and reads and keeps declared geometry and the railing members since #786 and #787 (live since 12 October 2026, `main` `1e1089db`). It reads names of files escaped as Part III, 2 says since Stomra 506 (live since 15 October 2026, `main` `a34cc1a1`). It keeps as kept files the files Part III, 7, rule 8 leaves alone: those whose names a file system refuses or reads otherwise, those whose paths fold to another of the model's, and those under a folder named `AGENTS.md`; and it reads a version that a reader refuses (Security and privacy, 5.3, rule 2): one that holds such a file, a kept text over 1 MiB or with NUL, or a hidden name. Of 0.2's records, it reads and writes the devices, boards and circuits of Part XIII (its works 532 and 534), its sheets as application records (Part XIV, 1.6, the note), no members between two points and no sloped slabs (Part II, 6.2.1 and 6.3.1, the notes), and reads 0.1's folders alone (Part III, 4.4; rows 39 and 42 to 53 of open questions, section 2) |
| Validator (`ek validate`) | meets most | refuses a record of a category it does not know (Part I, 10, rule 5); does not compare a file's path with its record (Part III, 4.2); accepts `/` in ids other than those of originals and copies (Part I, 6.4); accepts a `swept` body and the `line` frame in a declaration of any category (Part II, 12.1, rules 4 and 7); compares no paths folded and bounds no id's segment (Part I, 6, rules 7 and 8), and reports none of the files Part III, 7, rule 8 leaves alone. Since #778 it lists unknown members as warnings, no longer refusing them (Part I, 10.2); its view's filter by system reads a number with a leading zero or 0 in an older model, and since Stomra 669 refuses `0` in a new command and writes no leading zero (Part II, 13.6, rule 1; open questions, section 2, row 31). It accepts a bar set in a wall, which Part II, 6.1, rule 6 does not, and refuses one in a slab edge element, and reinforcement in a layer anywhere but in a slab or a foundation, which the rule allows since 26 October 2026 (open questions, section 2, row 37) |
| Writer | meets most | writes an id with `/` as `%2F` rather than refusing it (Part I, 6.4); since Stomra 641 (live since 23 October 2026) it leaves out the types of its library that nothing names, and since Stomra 685 (live since 25 October 2026) its title blocks and detail families too, but a title block an earlier build gave otherwise, never edited and unused (Part III, 13). At `37e8f202` that library holds five types of a category 0.1 does not have (`person`), which it wrote into every folder it exported until 641 (Part II, 6.2); a 0.1 reader keeps them and warns (Part I, 10, rule 5). It puts a sectioned beam's depth into its `height` since Stomra #777 (live since 11 October 2026, `main` `21cd71c6`), and moves, turns and mirrors a world-frame declaration with its element since #787. It names files as Part III, 2 says since Stomra 506. It writes, without a prefix, members and a value 0.1 does not define (Part I, 11.2, rules 2 and 6): `notches`, `person` (on its library's `person` types among others), the `pattern` value `clt`, and members of views, detail items and detail families, each of which joins 0.2 or becomes its extension member by the steward's decision of 30 October 2026 (open questions, 115); it keeps a component's `along` past its pipe's or its duct's end (Part II, 6.9, rule 7; open questions, section 2, row 29); until Stomra 669 (live since 24 October 2026) it wrote a pipe's insulation code by its parts (`bti`, deprecated) and no run's own thickness (rules 3 and 4; row 27); and it names its single-file models `*.stomra.json` (Part III, 11.1, a SHOULD). It writes a model whose records' paths fold to one, or whose ids make segments longer than 200 bytes (Part I, 6, rules 7 and 8), and the kept files Part III, 7, rule 8 leaves out, among them one under a folder named `AGENTS.md`. It keeps the members of `eik.json` it does not know in a folder whose `eik.json` names `openeik/0.1-draft` in mm, but writes its own over one that names another format id of 0.1, and holds its own in every version's tree, without them (Part III, 8.1). Its `rebar.quick` writes a bar set in a wall, which Part II, 6.1, rule 6 does not allow (open questions, section 2, row 37). Of 0.2: it writes 0.1's folders, not the owners' (Part III, 4.4, rule 7; row 39); emergency luminaires as `fire` elements (Part XIII, 2.3, rule 7; row 44); a railing's copy of an outline (Part II, 12.2.1; row 46); and a truss layout's members with Swedish names (Part IV, 7.4.13 and 7.4.16; row 40) |
| Compiler (core) | meets the class-A rules | the reference line of Part IV, 6.5 and the taper rule (6.5.3) are met since Stomra #777 (live in Stomra since 11 October 2026, `main` `21cd71c6`); the axis with its centroid offset (6.5.5) is met since Stomra work 480 (live since 13 October 2026) for members with a section; no derived layer (1.1). Declared geometry (11.1), since #787: it draws a declared envelope, or declared parts, in place of the derived body in 3D, sections, quantities and IFC, but draws a type's declaration only for railings (a `swept` section), so a declaration on a type of another category is kept and not drawn. The line of a railing on an outline and its given posts (11.2) are met since #786. Pipe and duct bodies (12): met since Stomra work 503 (live since 14 October 2026, `main` `d0774a48`), which keeps a rectangular duct's section up a vertical piece (12.3, rule 3); all eighteen runs of `run-bodies.json` agree. Outline edges trimmed to a wall's face (4.5): met, for a wall whose type has no layers since Stomra 612 (live since 21 October 2026, `main` `7e68027f`; open questions, section 2, row 26). Until Stomra 669 it drew a duct larger by the thickness its insulation code has in a table that no model holds (Part IV, 12.1, rule 3; open questions, section 2, row 28). The rules written on 26 October 2026 (open questions, 74, 75 and 77): its slab edge elements, their mitres, its hosts' thickened edges and chamfers' fills, and its shafts' cuts in slabs, ceilings, roofs and foundations meet Part IV, 4.2, rule 8, and 4.6 (Stomra `main` `0c8fcea1`; `packages/openeik/test/fixtures/hosted-bodies.json`); its gutters meet 4.7 but for rule 6, where it finds the part another roof of the group buries at 25 points and runs a piece on to the first point it finds buried, which the steward's decision lets stand, within a twenty-fourth of the eave line, until it finds it exactly (open questions, section 2, row 34). Of 0.2: it has no member between two points and no sloped slab (Part IV, 6.7 and 4.2.1; rows 52 and 53), draws a frame's members as boxes and no profile (Part IV, 4.3.1, rule 15; row 54), bounds rooms otherwise in seven points that made no difference on the rooms compared (Part IV, 7.5; row 55), runs a bolt's shank by its table of ISO bolts rather than within its group's grip (Part IV, 7.6, rule 7; row 56), and places a timber section by its profile, its `axes` not read (Part IV, 7.6, rule 2; row 57) |
| Command processor | meets most | refuses a member it does not know in an element, a patch or a view, and drops one at the top level of a command or in a type (Part V, 1.3 and 1.4), except a member that a record of the model holds and that a command carries back as read, which it keeps since #778, so it drops, where it should refuse, an extension member whose value is `null` that a command adds to a type (Part V, 1.3); accepts new ids with `/` (Part I, 6.4). It carries declared geometry through the transforms (Part V, 11) since #787. It implements none of Part XVII yet: its commands carry no id, and 14 of its 91 kinds take no precondition (row 49) |
| Version store | meets most | saves versions that a 0.1 reader refuses (Security and privacy, 5.3, rule 2; open questions, section 2, row 24): with a kept file Part III, 7, rule 8 leaves out, `AGENTS.md/notes.md` among them; with a kept text over 1 MiB or with NUL, from a single-file model it imports; and, before Stomra 506, with a record or a level whose id starts with `.` under a hidden name. It clones `main` into a new project, a single-ref clone, since Stomra 500 (live since 14 October 2026, `main` `cd7173c9`; Part VI, 6.5). `eik.json` is in every version it saves since Stomra #778 (Part VI, 2.2); it fetches, pushes and pulls one remote ref, and keeps its tracking ref, since Stomra 495 (live since 14 October 2026, `main` `a7b7b13b`; Part VI, 6). Of Part XV: it keeps the PDFs it publishes outside the model, and its issued SVGs as kept files, not as assets (Part XV, 11, the note; row 48) |
| Agent host (`ek`, `ek-mcp`) | meets | 3D snapshots need a screen (allowed: a SHOULD operation) |
| Bridge (IFC) | meets for IFC4 | its fidelity report does not name the bodies that are declared envelopes (Part IV, 11.1, rule 6, a SHOULD); since #787 it marks each element whose body is a declaration in a property set of the IFC file, with the declaration's level; until Stomra 669 it put a terminal other than a component in its system under the number 1, not the number of the runs joined to it (Part VIII, 1.1, informative; open questions, section 2, row 32); until Stomra 750 step 1 (live since 28 October 2026, `main` `5f5fc807`) it wrote a shaft's recess as an OPENING and no opening in a foundation a stair's shaft cuts (Part VIII, 1.3; open questions, section 2, row 35), and until Stomra 727 step 4 (merged, `main` `bb4037f2`) a door's operation type only where it slid, on the occurrence (Part VIII, 1.2; row 36); and it writes an element's and an opening's imported property sets (`ifcSource.properties`) under the names they were imported with and untyped, a text an IfcLabel and a number an IfcReal, and a space's and a type's not at all, where Part VIII, 1.5 types a set IFC4 defines by its template and writes every other property under a name without `Pset_` (a SHOULD; open questions, 88). Its prints say neither which version they came from nor that they are prints (Part XVIII, 7.2, the note; row 51) |
| Drawing validator | not met | its sheets are application records, and the SVG it draws is its screen's markup, which the SVG profile refuses (Part XIV, 1.6, the note; row 47) |
| Drawing issuer | not claimed | it issues drawings in Part XIV's files since Stomra 566 (Part XIV, 1.6's note), from sheets that are still application records of 0.1 (row 47); it claims no class of 0.2 yet |
| Host | not a host | it pushes to a host, EikHub, which holds a change for its owners' approvals (Part XVI, 8, the note) and records which client opened a proposal (Part XVII, 4.3, the note) |
| Authoring tool | not yet stated | this text does not yet record what it does of Part XVIII, 9; its prints of IFC are row 51's |

`tools/check.mjs` reports no error on the two folders in `examples/`, on all nine of the reference implementation's example projects exported with `ek export` at `ff8574ec`, and on their single-file forms except where those name a built-in type they do not contain (Part III, 12). Exported at `37e8f202` (14 October 2026), each of the nine folders has no error. Besides the warnings about library records no record uses, it has two for each of the five `person` types of the built-in library: a record of a category 0.1 does not have, and its `person` member, which no schema knows; both are kept (Part I, 10).

Declared geometry in the reference implementation (Stomra pull request #787, live since 12 October 2026, `main` `1e1089db`): it reads and checks `declaredGeometry` on any element or type (Part II, 12.1, rules 1 to 3, 5 and 7 to 9), draws a declared envelope, or declared parts, in place of the derived body, moves, turns and mirrors a world-frame declaration with its element and has a line-frame declaration follow its line (rule 6), and reports a changed basis (rule 5). Fixings, clearances, positions and loads are kept and read but not drawn or checked, and it has no clash or layout check (not a conformance class). The railing members (Part II, 12.2) are implemented by #786, live since the same day.

## 4. Security and privacy, by class

The requirements of the [security and privacy considerations](https://openeik.org/spec/0.3/security-and-privacy) bind these classes, in addition to those of section 1. The numbers are that page's sections and rules.

| Class | Security and privacy |
|---|---|
| **Reader** | 5.3, rules 1, 2, 4 and 5; 6.4, rule 1; 7.2, rules 1 and 2; 7.3 |
| **Validator** | everything a reader must, plus 6.2, rule 2, and 10, rules 1 to 3 |
| **Writer** | 2.2; 2.3, rules 1 and 2; 6.1, rules 1 to 3; 6.2, rule 1; 6.3; 6.4, rule 2; 8, rule 1 |
| **Compiler (core)** | 11, rule 2, which binds any validator that evaluates expressions too |
| **Command processor** | 4.2, rule 5, when it runs a proposal on a person's word |
| **Version store** | 5.3, rules 1 to 5; 8, rules 1 and 3; 9, rules 1, 2 and 5 |
| **Agent host** | 3.3, rules 1 to 3; and 4.2, rule 5, when it runs proposals |
| **Bridge** | none beyond its other classes |

The page binds some parties outside the classes as well: agents (2.2 and 3.4), applications (8, rule 2, and 11, rule 4), command-line tools (9, rule 4), and people who keep a model's folder in git (9, rule 3).
