ifc-element-type 0.2.0

Element, resource, and process type definitions: the IfcTypeObject catalogue.
Documentation
# ifc-element-type implementation plan

Status: complete; the catalogue and its writer are implemented.
Last updated: 2026-09-20

This is task state, not ambient context. Follow `AGENTS.md`; claim one task ID,
record blockers/decisions under it, and check it off only with evidence.

## Established boundary

Authoring the concrete `IfcTypeObject` subtypes: element, resource, and
process type definitions. Occurrence products stay with their own domain
crate; this crate writes only the type definition an occurrence points at.

## Planned file map

These paths are compiled private scaffold modules. Implement inside the named
owner and expose a public symbol only through an intentional parent re-export.

- `src/table/mod.rs`: generated catalogue root, `Family`, `ALL`
- `src/table/a_c.rs`: generated entries, IfcA* through IfcC*
- `src/table/d_f.rs`: generated entries, IfcD* through IfcF*
- `src/table/g_k.rs`: generated entries, IfcG* through IfcK*
- `src/table/l_p.rs`: generated entries, IfcL* through IfcP*
- `src/table/q_s.rs`: generated entries, IfcQ* through IfcS*
- `src/table/t_z.rs`: generated entries, IfcT* through IfcZ*
- `src/authoring.rs`: the writer and its refusals

## Work queue

- [x] `ETYPE-TABLE` - generate the catalogue from the EXPRESS schema
  - Evidence: `scripts/gen-element-types.py` emits 132 types across six
    shards; `the_catalogue_holds_its_invariants` asserts arity, slot and
    enum-membership properties over every entry.
- [x] `ETYPE-WRITE` - implement the type-definition writer
  - Evidence: `cargo test -p ifc-element-type` (7 tests), 10/10 mutation
    probes, crate clippy clean.

## Notes

The generator is the source of truth for `src/table/`. Regenerate with
`python3 scripts/gen-element-types.py` after a schema bump; never hand-edit
a shard.

Shards are sized against the post-rustfmt line count. rustfmt expands the
emitted constants to roughly 1.7x, and the monolith gate measures the
formatted file, so the shard count is chosen to leave headroom.

## Completion log

Append concise entries as `TASK-ID - proof command/result - material decision`.
Do not paste long logs or duplicate standing rules from `AGENTS.md`.

- `ETYPE-TABLE` - `cargo test -p ifc-element-type` 7 passed - The catalogue
  is GENERATED, not hand-written: 132 types with 1166 enum members is past
  the size where a typo stays invisible. `PredefinedType` sits at slot 9 for
  125 types, 10 for `IfcFurnitureType`, and 11 for the six resource types,
  whose supertype interposes `BaseCosts` and `BaseQuantity` - so the slot is
  per-entry data, never a constant. The USERDEFINED fallback is the mirror
  case: it is ALWAYS slot 8, because `ElementType`, `ResourceType` and
  `ProcessType` are each the last attribute their own supertype adds. Slots 6
  and 7 diverge by family (`RepresentationMaps`/`Tag` vs
  `Identification`/`LongDescription`), which is why `Family` is stored rather
  than inferred from the type name.
- `ETYPE-WRITE` - `cargo test -p ifc-element-type` 7 passed; 10/10 mutation
  probes - `CorrectPredefinedType` is enforced at construction: a token must
  belong to that entity's own enum, and USERDEFINED is refused unless the
  fallback name is present and non-blank. A blank string is refused too; it
  satisfies EXISTS in EXPRESS but names nothing, so accepting it would emit a
  file that passes a validator and still means nothing. The writer takes a
  `&ElementType` from the catalogue rather than a type-name string, so an
  unknown entity cannot be spelled at all.