Skip to content

feat(ids): add IDSSpecification.verify() for the specification-level verdict - #852

Open
helenkwok wants to merge 2 commits into
ThatOpen:mainfrom
helenkwok:fix/ids-specification-verify
Open

helenkwok wants to merge 2 commits into
ThatOpen:mainfrom
helenkwok:fix/ids-specification-verify

Conversation

@helenkwok

@helenkwok helenkwok commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Description

Part of #831 (the "Specification cardinality" row). It builds on #851 (the minOccurs / maxOccurs load and export change), so that PR's commit is included here and the diff shrinks to the last commit once #851 is merged.

IDSSpecification.test() returns per-element results only, so a required specification with nothing applicable cannot fail, and a prohibited one cannot fail when its applicability matches. The IDS developer guide defines the three states by how many elements the applicability selects (Optionality): required needs at least one and then all requirements must pass, optional may select none, and prohibited must select none, with its requirements ignored.

New IDSSpecification.verify(modelIds, config?) applies that and returns { pass, applicable, result }: the specification-level verdict, the number of applicable elements, and the same per-element result as test(). test() is unchanged, so no existing caller sees a difference. The requirements of a prohibited specification are not evaluated, so the buildingSMART case ids/invalid-prohibited_specifications_invalid_if_requirements_are_specified does not throw.

Additional context

  • New specification-cardinality.test.ts (6 tests, on tests/fixtures/type-psets.ifc, six walls and no slabs): required with nothing applicable fails, required with applicable elements is still judged by its requirements, optional with nothing applicable passes, prohibited fails when the applicability matches and passes when it does not, and a prohibited specification given requirements does not throw. They fail on main because verify does not exist.
  • Against the buildingSMART implementer test cases, ids/fail-prohibited_specifications_fails_if_the_applicability_matches and ids/fail-required_specifications_need_at_least_one_applicable_entity_2_2 now agree through verify(), and the other ids/ cases still agree.
  • One effect to know about: a required specification whose applicability selects a class the importer keeps no items for (for example IFCTASKTIME) now fails through verify(), because nothing is applicable, where test() returned an empty result. That is the importer's entity selection, not this change, and it is listed in IDS conformance: status against buildingSMART's implementer test cases, and what is left #831.
  • vitest --run on the IDS folder: all pass. tsc -p tsconfig-build.json --noEmit is clean.

What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following:

  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Follow the Conventional Commits v1.0.0 standard for PR naming (e.g. feat(examples): add hello-world example).
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

… export

The cardinality of a specification is set by minOccurs and maxOccurs on its applicability: required is 1 and unbounded, optional is 0 and unbounded, prohibited is 0 and 0. They were ignored on load and always written as 1 and unbounded on export, so an optional or prohibited specification came back required.

Read both on load into IDSSpecification.minOccurs and maxOccurs (default 1 and unbounded) and write them back on export.
…verdict

A required specification fails when too few elements are applicable, a prohibited one fails when any is, and an optional one may pass with none (IDS developer guide, Optionality). The requirements of a prohibited specification are ignored. The existing test() is unchanged.

verify() returns the verdict, the number of applicable elements and the same per-element result as test().

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant