AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Bonsai Agents Ifc Validator

skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-bonsai-agents-ifc-validator · by Impertio-Studio

>

No reviews yet
0 installs
22 views
0.0% view→install

Install

$ agentstack add skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-bonsai-agents-ifc-validator

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-bonsai-agents-ifc-validator)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
5mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Bonsai Agents Ifc Validator? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Bonsai IFC Validator Agent

> Version: Bonsai v0.8.x | IfcOpenShell v0.8+ | Blender 4.2.0+ | Python 3.11 > IFC Schemas: IFC2X3, IFC4, IFC4X3 > Dependencies: bonsai-core-architecture, bonsai-syntax-properties, ifcos-impl-validation

Quick Reference: When to Activate

Activate this validator when the user:

  • Requests validation, auditing, checking, or verification of an IFC model
  • Asks to run quality assurance (QA) on a Bonsai project
  • Needs to verify IFC compliance before model handover or delivery
  • Wants to check an IFC model against an IDS specification
  • Asks to diagnose structural or data issues in an IFC file
  • Requests a pre-submission or pre-export quality check
  • Needs to verify spatial hierarchy, property completeness, or classification correctness

Critical Warnings

  1. ALWAYS run validation in the prescribed order: Schema → Spatial → Properties → Geometry → Classification → IDS. Schema failures invalidate all subsequent checks.
  2. ALWAYS check model.schema before applying version-specific validation logic. IFC2X3, IFC4, and IFC4X3 have different entity sets and rules.
  3. NEVER assume a model is valid because ifcopenshell.validate.validate() completes without exception. Validation issues are logged, NOT raised. Use json_logger or LogDetectionHandler to detect issues.
  4. ALWAYS use ifcopenshell.util.element.get_psets() for property reading. NEVER traverse IsDefinedBy relationships manually.
  5. ALWAYS use ifctester for IDS validation. ifcopenshell.validate checks schema compliance only — it does NOT check project-specific requirements.
  6. NEVER confuse schema validation with IDS validation. Schema validation verifies IFC file structure per EXPRESS schema. IDS validation verifies IFC data meets project information requirements.
  7. ALWAYS access the IFC model via tool.Ifc.get() inside Bonsai or IfcStore.get_file(). NEVER access IfcStore.file directly.
  8. ALWAYS guard against None return from IfcStore.get_file() before running any validation.

Validation Process: Execution Order

Execute these phases sequentially. If Phase 1 (Schema) produces BLOCKER-level issues, STOP and report before continuing.

Phase 1: Schema Validation

Validates IFC file structure against the EXPRESS schema definition.

import ifcopenshell
import ifcopenshell.validate

model = ifcopenshell.open("project.ifc")  # or tool.Ifc.get() inside Bonsai

# Step 1: Basic schema validation
json_log = ifcopenshell.validate.json_logger()
ifcopenshell.validate.validate(model, json_log)

schema_errors = [s for s in json_log.statements if s["level"] == "ERROR"]
schema_warnings = [s for s in json_log.statements if s["level"] == "WARNING"]

# Step 2: If basic passes, run EXPRESS WHERE rules (10-100x slower)
if not schema_errors:
    json_log_express = ifcopenshell.validate.json_logger()
    ifcopenshell.validate.validate(model, json_log_express, express_rules=True)

Severity mapping: | Condition | Severity | |-----------|----------| | Any ERROR in jsonlog.statements | BLOCKER | | Any WARNING in jsonlog.statements | WARNING | | EXPRESS WHERE rule violation | WARNING | | Clean schema validation pass | INFO (proceed) |

Phase 2: Spatial Hierarchy Validation

Verifies the required IFC spatial structure exists and all elements are contained.

import ifcopenshell
import ifcopenshell.util.element

def validate_spatial_hierarchy(model):
    errors = []
    schema = model.schema

    # 2a: Verify IfcProject exists (exactly one)
    projects = model.by_type("IfcProject")
    if len(projects) != 1:
        errors.append(("BLOCKER", f"Expected 1 IfcProject, found {len(projects)}"))
        return errors

    # 2b: Verify IfcSite exists
    sites = model.by_type("IfcSite")
    if len(sites) == 0:
        errors.append(("BLOCKER", "No IfcSite found"))

    # 2c: Verify IfcBuilding exists
    buildings = model.by_type("IfcBuilding")
    if len(buildings) == 0:
        errors.append(("BLOCKER", "No IfcBuilding found"))

    # 2d: Verify IfcBuildingStorey exists (standard buildings)
    storeys = model.by_type("IfcBuildingStorey")
    if len(storeys) == 0 and len(buildings) > 0:
        errors.append(("WARNING", "No IfcBuildingStorey found"))

    # 2e: Verify spatial decomposition chain
    # IFC4X3 allows IfcFacility / IfcFacilityPart as alternatives
    if schema == "IFC4X3":
        facilities = model.by_type("IfcFacility")
        if len(buildings) == 0 and len(facilities) == 0:
            errors.append(("BLOCKER", "No IfcBuilding or IfcFacility found"))

    # 2f: Check all physical elements have spatial containment
    for element in model.by_type("IfcElement"):
        container = ifcopenshell.util.element.get_container(element)
        if container is None:
            errors.append((
                "WARNING",
                f"#{element.id()} {element.is_a()} '{element.Name}': "
                f"Not contained in any spatial element"
            ))

    return errors

Severity mapping: | Condition | Severity | |-----------|----------| | Missing IfcProject or count != 1 | BLOCKER | | Missing IfcSite | BLOCKER | | Missing IfcBuilding (IFC2X3/IFC4) | BLOCKER | | Missing IfcBuilding AND IfcFacility (IFC4X3) | BLOCKER | | Missing IfcBuildingStorey | WARNING | | IfcElement without spatial containment | WARNING | | Spatial hierarchy complete | INFO |

Phase 3: Property Set Compliance

Validates property sets exist and contain required properties.

import ifcopenshell.util.element

def validate_property_compliance(model, requirements):
    """
    requirements: dict of {ifc_class: {pset_name: [prop_names]}}
    Example: {"IfcWall": {"Pset_WallCommon": ["IsExternal", "FireRating"]}}
    """
    errors = []
    for ifc_class, pset_reqs in requirements.items():
        elements = model.by_type(ifc_class)
        for element in elements:
            psets = ifcopenshell.util.element.get_psets(element)
            for pset_name, required_props in pset_reqs.items():
                if pset_name not in psets:
                    errors.append((
                        "WARNING",
                        f"#{element.id()} {element.is_a()} '{element.Name}': "
                        f"Missing pset '{pset_name}'"
                    ))
                    continue
                for prop in required_props:
                    val = psets[pset_name].get(prop)
                    if val is None:
                        errors.append((
                            "WARNING",
                            f"#{element.id()} {element.Name}: "
                            f"Missing {pset_name}.{prop}"
                        ))
    return errors

Standard property requirements by element type:

| IFC Class | Standard Pset | Key Properties | |-----------|--------------|----------------| | IfcWall | Pset_WallCommon | IsExternal, LoadBearing, FireRating | | IfcSlab | Pset_SlabCommon | IsExternal, LoadBearing | | IfcDoor | Pset_DoorCommon | IsExternal, FireRating | | IfcWindow | Pset_WindowCommon | IsExternal, ThermalTransmittance | | IfcBeam | Pset_BeamCommon | LoadBearing | | IfcColumn | Pset_ColumnCommon | LoadBearing | | IfcSpace | Pset_SpaceCommon | IsExternal, GrossPlannedArea |

Severity mapping: | Condition | Severity | |-----------|----------| | Standard pset completely missing on element | WARNING | | Required property missing from existing pset | WARNING | | Property value is empty/null | INFO | | All required properties present | INFO |

Phase 4: Geometry Validation

Checks geometry representations exist and are valid.

def validate_geometry(model):
    errors = []

    for element in model.by_type("IfcElement"):
        # 4a: Check element has a representation
        if not element.Representation:
            errors.append((
                "WARNING",
                f"#{element.id()} {element.is_a()} '{element.Name}': "
                f"No geometry representation"
            ))
            continue

        # 4b: Check representation has items
        for rep in element.Representation.Representations:
            if not rep.Items or len(rep.Items) == 0:
                errors.append((
                    "WARNING",
                    f"#{element.id()} {element.Name}: "
                    f"Empty representation '{rep.RepresentationIdentifier}'"
                ))

    # 4c: Check for placement consistency
    for element in model.by_type("IfcElement"):
        if element.ObjectPlacement is None:
            errors.append((
                "INFO",
                f"#{element.id()} {element.is_a()} '{element.Name}': "
                f"No IfcLocalPlacement"
            ))

    return errors

Severity mapping: | Condition | Severity | |-----------|----------| | IfcElement with no Representation at all | WARNING | | Empty representation (no Items) | WARNING | | Missing IfcLocalPlacement | INFO | | Valid geometry present | INFO |

Phase 5: Classification Validation

Verifies classification references (Uniclass, OmniClass, NL-SfB, etc.) are present and correctly structured.

import ifcopenshell.util.classification

def validate_classifications(model, required_system=None):
    errors = []

    # 5a: Check classification systems exist
    systems = model.by_type("IfcClassification")
    if len(systems) == 0:
        errors.append(("INFO", "No classification system referenced in model"))
        return errors

    if required_system:
        system_names = [s.Name for s in systems]
        if required_system not in system_names:
            errors.append((
                "WARNING",
                f"Required classification system '{required_system}' not found. "
                f"Available: {system_names}"
            ))

    # 5b: Check elements have classification references
    classified_count = 0
    unclassified = []
    for element in model.by_type("IfcElement"):
        refs = ifcopenshell.util.classification.get_references(element)
        if refs:
            classified_count += 1
        else:
            unclassified.append(element)

    total = len(model.by_type("IfcElement"))
    if unclassified:
        errors.append((
            "INFO",
            f"{len(unclassified)}/{total} elements lack classification references"
        ))

    # 5c: Validate classification reference format
    for ref in model.by_type("IfcClassificationReference"):
        if not ref.Identification and not ref.ItemReference:
            errors.append((
                "WARNING",
                f"#{ref.id()} IfcClassificationReference: "
                f"Missing Identification/ItemReference"
            ))

    return errors

Severity mapping: | Condition | Severity | |-----------|----------| | No classification system in model | INFO | | Required classification system missing | WARNING | | Element lacks classification reference | INFO | | IfcClassificationReference with empty ID | WARNING |

Phase 6: IDS Validation (Information Delivery Specification)

Validates the IFC model against an IDS specification file using ifctester.

import ifctester
import ifctester.ids
import ifctester.reporter

def validate_ids(model, ids_path):
    """Validate model against IDS specification."""
    errors = []

    # 6a: Load IDS specification
    ids = ifctester.open(ids_path)

    # 6b: Run validation
    ids.validate(model)

    # 6c: Collect results per specification
    for spec in ids.specifications:
        total = spec.total_applicable
        passed = spec.total_pass
        failed = spec.total_fail

        if failed > 0:
            severity = "BLOCKER" if spec.minOccurs > 0 else "WARNING"
            errors.append((
                severity,
                f"IDS '{spec.name}': {failed}/{total} elements failed"
            ))

    # 6d: Generate report
    reporter = ifctester.reporter.Json(ids)
    reporter.report()
    report_data = reporter.to_string()

    return errors, report_data

Bonsai UI access: BIM > IFC Tester panel provides integrated IDS validation.

Severity mapping: | Condition | Severity | |-----------|----------| | Required IDS specification failed | BLOCKER | | Optional IDS specification failed | WARNING | | All IDS specifications passed | INFO | | No IDS specification provided | INFO (skip phase) |


Decision Tree: Validation Severity Classification

Issue found during validation
|
+--> Does it violate IFC schema rules?
|    +--> YES --> BLOCKER (invalid IFC file, model cannot be trusted)
|    +--> NO --> continue
|
+--> Does it break spatial hierarchy completeness?
|    +--> Missing IfcProject/IfcSite/IfcBuilding? --> BLOCKER
|    +--> Missing IfcBuildingStorey? --> WARNING
|    +--> Element not spatially contained? --> WARNING
|    +--> NO --> continue
|
+--> Does it fail a required IDS specification?
|    +--> YES (minOccurs > 0) --> BLOCKER
|    +--> YES (optional) --> WARNING
|    +--> NO --> continue
|
+--> Does it involve missing required properties?
|    +--> Missing standard pset entirely? --> WARNING
|    +--> Missing individual property? --> WARNING
|    +--> Empty property value? --> INFO
|    +--> NO --> continue
|
+--> Does it involve geometry issues?
|    +--> No representation at all? --> WARNING
|    +--> Empty representation? --> WARNING
|    +--> Missing placement? --> INFO
|    +--> NO --> continue
|
+--> Does it involve classification?
     +--> Required system missing? --> WARNING
     +--> Element unclassified? --> INFO
     +--> Malformed reference? --> WARNING

Severity Definitions:

| Severity | Meaning | Action | |----------|---------|--------| | BLOCKER | Model is invalid or non-compliant. Delivery MUST NOT proceed. | Fix immediately. Re-validate after fix. | | WARNING | Data quality issue. Model is technically valid but incomplete. | Fix before delivery if requirements demand it. | | INFO | Observation. No action required unless project rules specify otherwise. | Document for awareness. |


IDS Integration: ifctester Usage Patterns

Core Workflow

import ifctester
import ifctester.ids
import ifctester.reporter
import ifcopenshell

# Load IDS and IFC
ids = ifctester.open("specification.ids")
model = ifcopenshell.open("project.ifc")

# Validate and report
ids.validate(model)
ifctester.reporter.Console(ids).report()

Report Formats

| Format | Reporter Class | Use Case | |--------|---------------|----------| | Console | ifctester.reporter.Console(ids) | Quick interactive checks | | JSON | ifctester.reporter.Json(ids) | CI/CD pipelines | | HTML | ifctester.reporter.Html(ids) | Stakeholder reports | | BCF | ifctester.reporter.Bcf(ids) | BIM coordination | | ODS | ifctester.reporter.Ods(ids) | Spreadsheet review |

IDS Facet Types

| Facet | Checks | |-------|--------| | Entity | IFC class and predefined type | | Attribute | Entity attribute values | | Classification | Classification references present | | Property | Property set values | | Material | Material assignments | | PartOf | Spatial/aggregation relationships |


Model Access

| Context | Access Method | |---------|--------------| | Inside Bonsai | model = tool.Ifc.get() — ALWAYS check for None | | Inside Bonsai (legacy) | model = IfcStore.get_file() | | Standalone/headless | model = ifcopenshell.open("project.ifc") | | Bonsai UI IDS | BIM > IFC Tester panel |


Version-Specific Validation Notes

| Aspect | IFC2X3 | IFC4 | IFC4X3 | |--------|--------|------|--------| | Spatial root | IfcProject → IfcSite → IfcBuilding | Same as IFC2X3 | IfcProject → IfcSite → IfcBuilding OR IfcFacility | | Georeferencing | Property sets on IfcProject | IfcMapConversion + IfcProjectedCRS entities | Same as IFC4 + IfcMapConversionScaled | | Classification | IfcClassificationReference.ItemReference | IfcClassificationReference.Identification | Same as

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.