BIM OOTB — Roadmap¶
Principle¶
DB = model. Template = view. Browser = runtime. Three concerns, never merged.
Shipped¶
| # | What | Files |
|---|---|---|
| S200-S209b | Browser viewer, site camera, walk mode, mobile UX, modular refactor, 149 tests | deploy/sandbox/ (16 modules) |
Next¶
S210 — Template + Forex (quick win)¶
boq_charts.htmlreads?tpl=(JSON template override)- Forex: USD/EUR column next to RM, configurable rate
- Work Package grouping in Excel export
- Chart images embedded in Excel
- Template JSON schema: rates, forex, grouping, dimensions, charts
S211 — NLP Query DSL (harden + browser port + voice)¶
Port the Python NLP DSL (federation/dataintelligence/nlp/) to browser JS running against sql.js.
No LLM, no API — pure keyword intent classification + pattern-matched SQL generation.
Voice input via Web Speech API (built into Chrome/Safari — no server, no key, no cost).
What exists (Python, ~1400 lines):
- intent_classifier.py — 9 intents (COUNT, FIND, TOTAL, LIST, SEARCH, DISCIPLINE, MANUFACTURER, PROPERTY, STOREY), confidence scoring, ambiguity suggestions
- query_parser.py — NL → SQL with IFC synonyms (150+ terms), pluralization, storey normalization (EN/MY/DE/FR)
- query_patterns.py — 40+ patterns across 8 categories (element_count, manufacturer, property, quantity, cost, material, freetext, discipline)
- query_executor.py — execute + format results
Browser port (deploy/sandbox/nlp.js):
- Port intent classifier + query patterns to JS (no Python dependency)
- Wire to existing search input (#search-box in index.html, currently hidden)
- db.exec(generatedSQL) against loaded sql.js DB — zero server round-trip
- Results panel: table below search box, clickable rows highlight elements in 3D
- Ambiguity feedback: if classifier returns suggestions, show them as clickable chips
- Query history: last 10 queries in dropdown, stored in localStorage
- Example chip bar: "How many doors?" | "ACMV elements" | "Cost of MEP" (clickable)
Voice input (webkitSpeechRecognition / SpeechRecognition):
- Mic button (🎤) next to search input — tap to listen, tap again to stop
- continuous: false, interimResults: true, lang: 'en-US'
- Interim text shown live in search input (grey italic), final result triggers NLP parse
- On mobile: mic button is primary input (larger, thumb-reachable); keyboard is secondary
- Designed for short byte commands, not sentences (see §Voice Script in MOBILE_DEPLOY.md)
- Fallback: if SpeechRecognition unavailable, mic button hidden — text input only
Voice-safe word design:
Commands use short, phonetically distinct words that speech engines recognise reliably.
Avoid: long sentences, ambiguous homophones, technical jargon the engine mishears.
Pattern: [SCOPE] [TARGET] — two to four words max.
- Scope: "floor one", "level two", "all", "this building"
- Target: "doors", "beams", "walls", "lights", "cost", "area"
- Action: "count", "show", "total", "find", "search"
- Example: "floor one doors" → COUNT doors on level 1
- Example: "total cost" → total building cost
- Example: "show ACMV" → list ACMV elements
Hardening (beyond current Python):
- SQL injection guard: parameterized templates only (current Python uses _sanitize_value regex)
- Unknown query fallback: show "Did you mean...?" with closest pattern match
- Empty result UX: "No {element_type} found. Building has: {available_classes}" from SELECT DISTINCT ifc_class
- Cross-building: if city mode, prepend building filter to all generated SQL
- FTS5 graceful degradation: if elements_fts table missing, fall back to LIKE queries
- Voice misheard correction: show recognised text + "Not right? [Try again] [Edit]" link
- Test: port Python __main__ test queries to test_all.js (14 queries, expected intent + SQL shape)
UI — Progressive, non-cluttering:
Stage 1 — Dormant: Search icon (🔍) in toolbar. One button. Nothing else visible.
Stage 2 — Search bar: Click 🔍 → slim bar slides in below toolbar (not a panel). Contains: text input + 🎤 mic button + example chips (3 most relevant for current building). Auto-focuses. Press Enter or tap mic. No extra panels, no menus.
Stage 3 — Results toast: Query runs → results appear as a floating toast card (bottom-centre). Shows: summary line ("47 doors on Level 1") + [Show in 3D] button. Auto-dismisses after 8s unless pinned. Tapping [Show in 3D] highlights elements + dismisses.
Stage 4 — Results table (on demand): If user taps the summary line, toast expands to scrollable table (max 6 rows visible, rest scrollable). Click row → fly to element. [Pin] keeps table open. [x] dismisses entirely.
Stage 5 — History: Arrow-down on empty search bar → dropdown of last 5 queries. Each shows query + result count. Click to re-run.
Dismissed = gone. No residual panels, no orphaned UI. Each stage cleans up the previous. Mobile: toast card is full-width at bottom. Desktop: card is 350px, bottom-right.
S211a — Clash Detection (template-driven, R-tree bbox)¶
Port the Python clash detector (federation/clash/detector.py) to browser JS.
R-tree bbox collision against sql.js — same algorithm, same O(n log n) with spatial prefiltering.
Clash template (JSON, user-configurable):
{
"name": "Default Coordination",
"tolerance_mm": 10,
"pairs": [
{ "disc_a": "STR", "disc_b": "ACMV", "tolerance_mm": 25 },
{ "disc_a": "STR", "disc_b": "ELEC", "tolerance_mm": 15 },
{ "disc_a": "STR", "disc_b": "PLB", "tolerance_mm": 20 },
{ "disc_a": "ARC", "disc_b": "MEP", "tolerance_mm": 10 }
],
"ignore_classes": ["IfcOpeningElement", "IfcSpace"],
"ignore_same_storey": false,
"severity": {
"hard": { "clearance_mm": 0, "color": "0xff0000" },
"soft": { "clearance_mm": -50, "color": "0xff8800" },
"near": { "clearance_mm": -150, "color": "0xffff00" }
}
}
localStorage or loaded from ?clash_tpl= URL param
- Settings panel: tolerance slider, discipline pair checkboxes (same layout as Bonsai federation addon)
- Per-pair tolerance overrides default (STR-ACMV ducts need wider tolerance than STR-ELEC conduit)
Algorithm (JS port of detector.py):
- sql.js has no R-tree virtual table → use elements_rtree as regular table with bbox range queries
- For each element in disc_a: SELECT FROM elements_rtree WHERE minX <= ? AND maxX >= ? ... filtered to disc_b
- check_bbox_clash() identical to Python: expand by tolerance, check 3-axis overlap, compute clearance
- Progress: status bar percentage during scan
Visualization:
- Clash pairs coloured by severity (hard=red, soft=orange, near=yellow) — emissive on both meshes
- Clash list panel (scrollable, sortable by clearance/discipline/class)
- Click clash row → fly-to midpoint of pair, isolate both elements, show info box:
┌─ CLASH #47 ─────────────────────┐
│ STR IfcBeam ↔ ACMV IfcDuct │
│ Clearance: -12.3 mm (HARD) │
│ Overlap: 0.025 m³ │
│ Storey: Level 2 │
│ [Resolve] [Ignore] [Export BCF] │
└──────────────────────────────────┘
localStorage (or IndexedDB)
- Export: clash list → Excel (reuse excel.js pattern) or BCF XML
UI: Clash icon (⚡) in toolbar. Badge shows count. Same toggle pattern as Issues.
S211b — Heatmap Costing ($ icon → colour by value)¶
Colour elements by any numeric property. Continuous gradient mapped to geometry already in scene.
UI: Dollar icon ($) in toolbar → opens heatmap selection panel:
┌─ Heatmap ──────────────────────────┐
│ Colour by: [Cost ▾] │
│ ○ Cost (RM) ○ Area (m²) │
│ ○ Volume (m³) ○ Custom field │
│ │
│ Gradient: 🟢───🟡───🔴 │
│ Min: 0 Max: 50,000 (auto) │
│ Legend: [Show] [Hide] │
│ │
│ [Apply] [Clear] │
└────────────────────────────────────┘
Data source:
- Cost: simple_qto.total_cost_rm joined to elements_meta.guid via ifc_class
- Area/Volume: simple_qto.total_quantity where measurement_type = AREA/VOLUME
- Custom: element_properties.property_value (numeric cast) for user-chosen property name
- If simple_qto absent, show "No QTO data — run 4D/5D first" with link to BOQ
Rendering:
- THREE.Color.lerpColors() green→yellow→red based on normalized value (0→1)
- Set mesh.material.color per element, preserve original in userData.origColor
- Floating legend overlay (gradient bar with min/max labels, positioned bottom-right)
- Hover: show element value in tooltip (reuse hover highlight from tools.js)
- Clear: restore userData.origColor on all meshes
Integration with NLP (S211): Query "cost of ACMV" → auto-applies ACMV heatmap
S211c — Post-it Notes (3D pinned annotations)¶
Pin text notes to 3D world positions. Store in IndexedDB. Export to Excel/BCF.
UI: Notes icon (📝) in toolbar → opens Notes panel:
┌─ Notes ────────────────────────────┐
│ [+ Post-it] [Export] [Clear All] │
│ │
│ 📌 "Check fire seal" — Level 2 │
│ STR IfcBeam · 2026-04-23 │
│ 📌 "Wrong material" — Level 1 │
│ ARC IfcWall · 2026-04-22 │
│ 📌 "Duct clearance OK" — Level 3 │
│ ACMV IfcDuct · 2026-04-23 │
└────────────────────────────────────┘
Workflow:
1. Click "Post-it" button → cursor changes to crosshair
2. Click element in 3D → raycaster gets hit point + GUID (reuse picking.js pattern)
3. Note input — two modes:
- Type: textarea popup (desktop default)
- Voice: hold 🎤 button → MediaRecorder captures audio → auto-transcribed via
SpeechRecognition → text shown for review → [Save] / [Re-record]
Audio blob also stored alongside text (playback on click).
On mobile, voice is primary — bigger 🎤 button, textarea secondary.
4. Creates:
- Yellow sprite at hit.point (Three.js Sprite with CanvasTexture, capped at 50 notes visible)
- Entry in IndexedDB notes store:
{ id, guid, text, audio: Blob|null, point: {x,y,z}, timestamp, building, storey, disc, ifc_class }
5. Click existing sprite → show note popup with [Edit] [Delete] [▶ Play] (if audio attached)
Voice note details:
- MediaRecorder API (audio/webm) — records actual audio, stored as Blob in IndexedDB
- SpeechRecognition runs in parallel — provides text transcription for search/export
- Playback: <audio> element in note popup, no external player
- Export includes text transcription (audio stays local — too large for Excel/BCF)
- Max 30 seconds per note (auto-stops, prevents accidental long recordings)
- Visual feedback: pulsing red dot on sprite while recording, mic button turns red
Export:
- Excel: same pattern as excel.js — columns: ID, Text, GUID, Building, Storey, Discipline, Class, X, Y, Z, Timestamp
(text column contains voice transcription if voice note)
- BCF: each note → BCF Topic with viewpoint (camera position + direction). Interops with Revit/Solibri/BIMcollab.
- Clear All: confirm dialog → delete all from IndexedDB + remove sprites
Persistence: IndexedDB keyed by DB filename. Notes survive page reload. Different buildings = different note sets. Audio blobs stored in same IndexedDB (binary, ~50KB per 30s recording). No server upload.
S211d — Revision Diff (on-demand delta, not dual load)¶
Compare two versions of the same building. Loads diff only — not both full models.
Approach: SQL EXCEPT on metadata, geometry load on demand
- User loads current DB normally (already streamed)
- "Compare" button → file picker for older DB
- Open older DB as second sql.js instance (db2)
- Diff query (runs instantly, no geometry):
-- Added elements (in new, not in old)
SELECT guid FROM elements_meta EXCEPT SELECT guid FROM db2.elements_meta
-- Removed elements (in old, not in new)
SELECT guid FROM db2.elements_meta EXCEPT SELECT guid FROM elements_meta
-- Changed elements (same GUID, different properties)
SELECT a.guid FROM elements_meta a JOIN db2.elements_meta b ON a.guid = b.guid
WHERE a.element_name != b.element_name OR a.material_name != b.material_name
OR a.storey != b.storey OR a.discipline != b.discipline
Visualization (diff-only geometry loading):
- Added (green): load geometry from new DB, colour green. These are new meshes.
- Removed (red): load geometry from OLD DB (db2), colour red with 50% opacity. Ghost overlay.
- Changed (yellow): already loaded from new DB, just recolour yellow.
- Unchanged: leave as-is (already streamed from current DB)
- Only removed elements require additional geometry load — minimal overhead.
UI: - Compare button (⇔) appears after streaming complete - Diff summary panel:
┌─ Revision Diff ──────────────────┐
│ 🟢 Added: 47 elements │
│ 🔴 Removed: 12 elements │
│ 🟡 Changed: 89 elements │
│ ⚪ Same: 1,021 elements │
│ │
│ [Show Added] [Show Removed] │
│ [Show Changed] [Show All] │
│ [Export Diff Excel] [Clear] │
└───────────────────────────────────┘
Prerequisite: None (does NOT depend on S217 edit_log). Pure SQL set difference on GUIDs.
S212 — JSONFormMaker → BIM Template Compiler¶
- JSONFormMaker (source) outputs BIM template JSON
- Compile to binary BLOB →
INSERT INTO templates (name, concern, version, compiled) - boq_charts.html reads template from DB, no separate file
- Concerns: QS, Factory, Owner, Inspector, Green
S213 — Prefab Factory¶
- Pod = BOM. QR per component. Checklist = repurposed issue log.
- Exploded view (BOM children offset along Z)
- QR generator per GUID (sticker sheet)
checklist.js(quality gate per step, photo evidence)- Pod progress on landing page
- Factory template (production rates, pod grouping, step-level 4D)
S214 — 2D BOM Editor¶
editor2d.js— orthographic view, room placement- BOM editor UI — rooms, areas, adjacencies as recipe
- Live recompile via DAGCompiler rules
- DXF export via
2D_Layout/python/drawing_writer.py
S215 — Plugin Marketplace (ADUI Metadata) — THE MULTIPLIER¶
- Plugin = JSON manifest (ADUI schema from JSONFormMaker) + JS module
- Manifest declares: name, concern, inputs, outputs, template, icon
- Plugin registry = SQLite table in a shared
marketplace.db - Landing page renders plugin cards (same pattern as building cards)
- Install = copy folder to
plugins/, add to manifest, refresh - No build step, no SDK, no API key, no approval process
- Plugin types:
- Template — rates, forex, grouping (QS, factory, green)
- View — custom chart type, dashboard layout
- Tool — new toolbar button (e.g. clash detector, carbon calc)
- Connector — import/export (IFC, COBie, BCF, CSV)
- Runtime:
plugin_loader.jsreads manifests, injects scripts, wires buttons - Community publishes via PR to
plugins/or upload to OCI bucket
Stable Plugin API (guaranteed surface):
| Method | What |
|---|---|
APP.db.exec(sql) |
Query extracted DB (sql.js) |
APP.libDb.exec(sql) |
Query library DB (sql.js) |
APP.scene.add/remove(obj) |
3D objects (Three.js) |
APP.camera |
Current viewpoint |
APP.activeBuilding |
Current building name |
APP.guidMap[meshId] |
Element metadata for picked mesh |
APP.status.textContent |
Status bar message |
APP.addToolbarButton(icon, title, fn) |
Register toolbar button |
APP.addPanel(id, html) |
Register collapsible panel |
APP.on(event, fn) |
Lifecycle hooks (load, pick, stream_done) |
Everything else is standard (sql.js, Three.js, DOM, XLSX, Chart.js). We expose, not wrap.
Plugin Test Harness:
- plugin_test.js — offline testing module, no browser needed
- Ships a mock APP object with in-memory sql.js DB (Duplex as fixture)
- Plugin author runs: node plugin_test.js plugins/my_plugin/
- Harness calls plugin's setup*() against mock APP
- Logs every APP.db.exec() call with SQL + row counts
- Logs every APP.scene.add() with object type + vertex count
- Logs every APP.status write
- Validates manifest schema (required fields, valid types)
- Validates API usage (no access to internals, only stable surface)
- Output: plugin_test.log with §PLUGIN_PASS / §PLUGIN_FAIL per check
- Same pattern as test_all.js — run locally, read the log, fix, repeat
- Community plugins must pass harness before merge to registry
Plugin API (5 block categories, ~30 methods): - Query — byClass, byStorey, byDisc, byGuid, neighbours, path, schedule, areas, totals - Display — colorBy, highlight, hide, isolate, label, overlay, chart, table, toast - Interact — onPick, onStoreyChange, toolbarButton, contextMenu, prompt, drag - Export — excel, csv, pdf, screenshot, share, qr - Store — get, set, table, sync
Plugin IDE (browser-based, no install):
- Block palette (draggable API methods) + code editor (CodeMirror CDN)
- Run against live APP + real Duplex DB (1119 elements as fixture)
- Log panel: §-tagged output per API call with real row counts
- 3D preview: live model with plugin effects applied
- Save → auto-generates manifest.json from code analysis
- Package → zip. Publish → upload to OCI plugins/ bucket
- Duplex = starter fixture. Hospital = scale test.
- AI Assist button: sends user intent + API schema + DB schema to LLM, returns plugin code
- User describes in English, AI writes, IDE verifies, log proves. Standard practice.
- Full spec: docs/PLUGIN_SDK.md
S216 — Property Editing + Save DB (viewer → tool)¶
APP.db.exec("UPDATE ...")on in-memory sql.js DBA.interact.prompt()on element pick → edit material, name, status, custom fields- Save: download modified DB as file, or push to OCI
- Changes tracked in
edit_logtable (guid, field, old, new, timestamp, user) - No schema change needed — sql.js UPDATE on existing tables
S217 — IFC Export (tool → interop)¶
- DB → IFC4 STEP file, entirely in browser (string concatenation from SQL)
- Tessellated geometry via IfcTriangulatedFaceSet (vertices/faces BLOBs already stored)
- Full spatial hierarchy from
spatial_structure+rel_aggregates - Element placement from
element_transforms - Materials from
material_layers, colours fromsurface_styles - Containment from
rel_contained_in_space - NOT parametric round-trip — tessellated coordination model (industry standard for federated models)
- Output:
.ifcfile download. Valid IFC4 readable by Revit, ArchiCAD, Solibri, any IFC viewer. - Writer walks tables in order:
- Project + OwnerHistory + Units (project_metadata)
- Site → Building → Storeys → Spaces (spatial_structure)
- Elements with placement (elements_meta + element_transforms)
- Geometry per element (base_geometries BLOBs → IfcTriangulatedFaceSet)
- Materials + surface styles
- Containment relationships
- Missing from export: property sets (Pset_*), parametric geometry, type definitions, opening links
- Plugin:
ifc_export/plugin.js— toolbar button, runs SQL, builds STEP text, downloads file
S218 — Change Tracking + Version History (interop → team)¶
edit_logtable tracks every UPDATE (guid, field, old_value, new_value, timestamp, user)- Version = DB snapshot saved to IndexedDB with timestamp
- Diff two versions: SQL EXCEPT between snapshots → added/removed/changed elements
- Colour diff in viewer: green=added, red=removed, yellow=changed
- Export diff report to Excel
- Simple multi-user: download DB → edit → upload. edit_log enables manual merge.
- Future: row-level conflict resolution, CRDT for real-time (spec only, not built)
S219 — Multi-User + Access Control + Federation¶
Three levels (Level 1-2 cover 95% of real teams):
Level 1 — File-level turns (works with OCI today):
- .lock file in OCI bucket (user + timestamp). Check before download, release on upload.
- One editor at a time, others view read-only with their own templates.
- No server — just OCI object put/get.
Level 2 — Change-level merge (S218 edit_log):
- Multiple users download same version, edit different parts, upload changes.
- edit_log table = changeset. Merge = replay logs in timestamp order.
- Conflict = same GUID + same field by two users → last-write-wins or manual pick.
- Same concept as Bentley iTwin changesets, but SQLite files not proprietary server.
Level 3 — Real-time collaboration (future, spec only): - Yjs CRDT (30KB CDN) or WebRTC peer-to-peer. Not needed for most teams.
Access control via templates (no server-side auth): - Template defines: visible disciplines, visible storeys, can_edit, can_export, can_run_rules - Different template = different role. Swap template = swap role. - No SSO/SAML needed — template IS the access filter.
ISO 19650 audit compliance:
- edit_log table satisfies ISO 19650 information management audit trail
- Every change: who (user), what (guid + field), when (timestamp), before/after (old/new value)
- Version snapshots prove state at any point in time
- Auditor queries the log directly with SQL — no proprietary tool needed
- Export audit trail to Excel for submission
Federation: - Load multiple extracted DBs (different disciplines) into one viewer - Already works — city mode loads multiple buildings. Same pattern for disciplines. - STR engineer's DB + MEP engineer's DB → one coordinated scene - Clash detection across federated DBs = cross-DB spatial query
S220 — Browser IFC Import (self-service onboarding)¶
- Drag-and-drop IFC file onto landing page → extract to DB entirely in browser
- Uses
web-ifc(WebAssembly IFC parser, MIT, ~2MB CDN) — no server, no Python - Extraction mirrors
extractIFCtoDB_open.pyoutput schema (same tables, same contract) - Pipeline:
File → ArrayBuffer → web-ifc parse → walk spatial tree → populate sql.js DB - Tables populated:
project_metadata,spatial_structure,elements_meta,element_transforms,base_geometries(tessellated BLOBs),surface_styles,material_layers,simple_qto - Progress bar per phase: parsing IFC (30%) → extracting elements (50%) → tessellating geometry (20%)
- Output: download extracted DB file, or stream directly into viewer (no save needed)
- Large file handling: Web Worker for parsing (no UI freeze), chunked element processing
- Tested against: IFC2x3 (Revit, ArchiCAD), IFC4 (Bonsai, Tekla), IFC4x3
- Fallback for unsupported geometry: log skipped elements, show count in summary
- Exit criterion: user drops any valid IFC, gets a viewable DB in <60s for <50MB files
- Replaces: CLI
onboard_ifc.shfor simple cases. CLI remains for batch/scripted pipelines.
S221 — 4D Construction Animation (timeline playback)¶
- Auto-play mode on 4D timeline — elements appear as construction date advances
- Data source:
construction_scheduletable (already populated bynD_engine.py) - Playback controls: play/pause, speed (1×/2×/5×/10×), scrub slider, date display
- Element visibility: hidden before start_date, ghost (0.3α) during construction, solid after end_date
- Phase colouring: each discipline gets its construction colour (matches BOQ charts palette)
- Camera path: auto-orbit or user-defined waypoints (click to set, drag to reorder)
- Construction sequence: Substructure → Superstructure → MEP Rough-in → Architecture → MEP Final → Finishes (from
phasecolumn) - Overlay: running cost accumulator (5D) ticking alongside 4D date — shows spend-to-date
- Export: canvas capture → WebM video download (MediaRecorder API, no server)
- Shareable: URL with
?t=2026-03-15deep-links to specific construction date - Exit criterion: Hospital 224-task schedule plays as smooth animation, exportable as video
- Replaces: Synchro ($25K/yr), Navisworks TimeLiner ($8K/yr)
S222 — Incremental Diff Extraction (Bonsai re-export)¶
- Re-export IFC from Bonsai → compiler extracts only the delta against previous DB
- Algorithm: GUID-based set comparison (same as S211d but at extraction time)
- New GUIDs → INSERT into extracted DB
- Missing GUIDs → mark as
status='REMOVED'(soft delete, geometry retained for diff view) - Same GUID, different properties/geometry → UPDATE + log old values in
change_logtable change_logtable:(guid, field, old_value, new_value, ifc_version, timestamp)- Geometry diff: hash comparison on tessellated BLOBs — only re-tessellate changed elements
- Browser reflects changes immediately: green/red/yellow overlay (reuses S211d visualization)
- Workflow: Bonsai edit → IFC export →
extractIFCtoDB_open.py --diff previous.db→ updated DB → browser auto-shows delta - Browser-side (S220): if user drops a new IFC and a previous DB exists, auto-diff mode
- Backward compatible: new DB works standalone without previous version. Diff is additive metadata.
- Exit criterion: modify 5 elements in Bonsai, re-export, see exactly those 5 highlighted in browser
S223 — Designer Presets (common changes without Bonsai)¶
- Preset = named recipe: target selector (SQL WHERE) + action (UPDATE fields or swap product)
- Built-in preset categories:
- Finishes: wall paint colour, floor material, ceiling type — dropdown from
surface_styles - Doors/Windows: swap type (single→double, sliding→hinged) — replaces
product_type+ geometry BLOB - Furniture: swap product from catalogue (desk→standing desk, chair→armchair) — BOM child replacement
- MEP equipment: swap unit (AC split→cassette, basin→sensor basin) — product + clearance zone update
- Spatial: room name, function, department —
elements_metaUPDATE - Preset library: JSON definitions in
presets/folder, loaded as plugin (S215 compatible) - UI: pick element → right-click → "Apply Preset" → category → specific preset → preview → confirm
- Preview: ghost overlay showing before/after side by side (split opacity)
- Cascade: preset triggers BOQ recalc (quantity/cost update), schedule impact shown in toast
- Community presets: users publish preset packs (country-specific finishes, manufacturer catalogues)
- Geometry presets use pre-tessellated BLOBs from a preset library DB — no modelling engine needed
- Exit criterion: user swaps 3 door types and a floor finish, sees updated BOQ totals, no Bonsai involved
- Replaces: round-trip to Blender for the 80% of changes that are data, not geometry
S224 — Clash Detection on Diff (auto-clash on variation import)¶
- When S222 diff detects added/changed elements, auto-run S211a clash detection on the delta
- Only check new/changed elements against existing elements — not full O(n²) rescan
- Clash report embedded in Variation Order Excel (separate sheet: "Clashes")
- Viewer: clash pairs highlighted alongside diff colours (red emissive on both clashing elements)
- Clash count shown in diff summary panel:
⚡ 3 clashes detected - Click clash → fly-to, show both elements, clearance value, discipline pair
- No manual trigger — clash runs automatically whenever a variation is imported
- Uses same clash template from S211a (
tolerance,pairs,severity) - Why this matters: The variation didn't just change cost — it introduced conflicts. The QS and coordinator see both in one report.
- Exit criterion: Import MEP_v2 with a duct that passes through a wall → clash auto-detected, shown in viewer + Excel
- Replaces: Solibri ($15K/yr), Navisworks Clash Detective ($8K/yr)
S225 — QR Code per Element → Scan → Full History¶
- Generate QR sticker sheet from viewer: select elements → "Print QR" → PDF with one QR per GUID
- QR URL:
{viewer_url}?guid={GUID}— opens viewer, flies to that element - Element history panel (on scan): which variation introduced it, cost, phase, approval status, site cam photos
- History assembled from:
change_logtable (S222), issues log (S210), site cam photos (S204) - Print formats: A4 sheet (20 QRs), label printer (single), sticker roll
- Site workflow: print QR sheet → stick on physical elements during construction → scan to inspect/report
- Why this matters: Bridges digital twin to physical site. No other browser tool does this.
- Exit criterion: Print QR for 5 elements, scan on phone, see full history for each
- Replaces: BIM Track ($), manual tagging systems
S226 — Regulatory Auto-Check on Import (rule checker at extraction)¶
- After S220 import extracts IFC to DB, auto-run rule checker before card appears
- Rules from country pack JSON (
locales/MY.json→ UBBL,locales/GB.json→ Building Regs) - Each rule = SQL query + pass/fail condition (same pattern as S211a Rule Checker plugin)
- Card shows compliance badge:
✅ 247 PASS · ⚠ 3 WARN · ❌ 1 FAIL - Click badge → compliance panel with rule-by-rule results
- Click any fail → fly-to element, show rule text + what's wrong
- Rules cover: fire escape distance, corridor width, accessibility, MEP clearance, structural spans
- No separate tool. Compliance is part of the import pipeline.
- Export: compliance report Excel (rule, status, element GUID, storey, value, required value)
- Why this matters: Compliance checking today = Solibri license + manual config. Here it's automatic on drop.
- Exit criterion: Import a building with a corridor below minimum width → ❌ FAIL badge, fly-to the corridor
- Replaces: Solibri Rule Checker ($15K/yr), manual code review
S227 — Live Cost Dashboard per Project¶
- Landing page shows running cost total per project group:
Hospital — RM 67M · 3 variations · +RM 39,700 - Cost computed from: merged DB element counts ×
5D_rates.jsonrates - Variation impact: sum of all Variation Order net impacts (S222)
- Click → full BOQ breakdown (opens
boq_charts.htmlwith that project's DB) - Dashboard updates live as parts are imported/merged/varied
- Multi-project view: all projects on landing page, each with cost summary
- Trend sparkline: cost over time (from variation history in IndexedDB)
- Why this matters: Project manager's dashboard. Not a viewer — a control room. One page, all projects, all costs.
- Exit criterion: Import 3 projects, each with 2 variations → landing shows all 3 with cost totals and net change
- Replaces: Custom Excel dashboards, Procore cost module ($)
S228 — COBie / IFC Export from Merged DB¶
- After merge (S222), export merged DB as:
- COBie: 6-tab Excel spreadsheet (Facility, Floor, Space, Type, Component, System) — government handover
- IFC4: STEP file from S217 — tessellated coordination model
- Export buttons on merged card:
⬇ COBie·⬇ IFC·⬇ .db - COBie mapping:
elements_meta→ Component,spatial_structure→ Floor/Space,product_types→ Type - Handover package = one click: COBie + IFC + .db in a ZIP
- Why this matters: Government projects require COBie. Nobody does it from a browser. Close the loop.
- Exit criterion: Merge 3 parts, download COBie Excel, validate with COBie QC tool
- Replaces: Revit COBie toolkit, manual spreadsheet compilation
S229 — AI Query on Diff (NLP → change_log)¶
- Extend S211 NLP DSL to query
change_logtable (S222) - Natural language: "What changed in MEP on Level 3?" → SQL on change_log → results + fly-to
- Voice command (S211 voice): same queries via microphone
- Queries supported:
- "What was added?" → added GUIDs list
- "What was removed from Level 2?" → filtered removed list
- "How much did variation MEP_v2 cost?" → net impact from VO
- "Show me clashes in STR" → clash results for that discipline
- "Compare v1 and v3" → diff between any two versions
- Results panel: table + fly-to buttons + export
- Why this matters: PM asks question, gets answer instantly. No training, no query builder.
- Exit criterion: Voice "what changed on Level 3" → correct results, fly-to first element
- Replaces: Manual report digging, Navisworks search, Solibri filters
Starter Plugin Pack (ships with S215)¶
Pre-installed plugins that prove the marketplace. All use the plugin API, no core changes.
| Plugin | What | Effort | Replaces |
|---|---|---|---|
| BCF Export | Issue log → BCF XML zip (interop with Revit/Solibri/BIMcollab) | Low | BIMcollab ($) |
| COBie Export | DB → 6-tab spreadsheet (government handover) | Low | Revit COBie toolkit |
| Colour by Property | Colour elements by material/discipline/status/custom | Low | Solibri/Navisworks |
| Door/Window Schedule | Sortable table of types, sizes, fire ratings | Low | Revit schedules |
| Rule Checker | JSON rule packs (SQL query + pass/fail check) per standard | Medium | Solibri ($15K/yr) |
| Revision Compare | Load two DBs, show added/removed/changed elements | Medium | Navisworks ($8K/yr) |
| Selection Sets | Save/recall named GUID groups | Low | All BIM tools |
| 4D Timeline Slider | Scrub + animated playback of construction phases (see S221) | Medium | Synchro/Navisworks |
Localization (country config drives everything):
- Setup script on first launch: pick country → sets currency, rates, rules, standards, templates
- Config = one JSON per country (locales/MY.json, locales/GB.json, locales/US.json)
- Cascades to: forex in 4D/5D, rates in BOQ, rules in checker, labour in schedule
- Users change defaults anytime in Settings
- Community contributes country packs (rates + rules + templates) to marketplace
Background reports (DB processing, no UI needed): - User toggles which reports run: compliance, COBie, carbon, cost variance, schedules, clash - Trigger: on-change (DB updated), weekly, monthly, or manual - Output: Excel to project reports folder, silent, no popup - Reports panel lists generated files for download - Viewer is optional — DB processing is the core value - User adds more report types from marketplace, unticks what they don't need - One shop: headless DB processing + coupled responsive viewer when needed
Country packs (community-contributed): - Malaysia (UBBL, MS 1184, CIDB 2024 rates, JKR) - UK (Building Regs Part B/M/L, NRM rates) - US (ADA 2010, CSI MasterFormat, RS Means rates) - Fire safety, MEP clearance (cross-country)
Scenarios (template + DB + browser, no new systems)¶
| # | Scenario | What's needed |
|---|---|---|
| 1 | Building inspector on phone | Template |
| 2 | Offline construction site | Already works |
| 3 | Owner handover (two files) | Template |
| 4 | Clash detection in SQL | S211a |
| 5 | QR per element | QR generator (S213) |
| 6 | Fleet dashboard | Already works (city mode) |
| 7 | Voice to BOM | LLM + BOM API |
| 8 | Diff two buildings | S211d |
| 9 | Prefab factory floor | S213 |
| 10 | Insurance claim on-site | Template + site camera |
| 11 | External user brings own IFC | S220 (browser import) |
| 12 | Construction progress animation | S221 (4D playback) |
| 13 | Designer updates without Bonsai | S223 (presets) |
| 14 | Bonsai re-export shows only changes | S222 (incremental diff) |
| 15 | Variation introduces clash | S224 (auto-clash on diff) |
| 16 | QR on physical element → scan → history | S225 (QR per element) |
| 17 | Drop IFC, get compliance report | S226 (auto-check on import) |
| 18 | PM sees all project costs on one page | S227 (live cost dashboard) |
| 19 | Government handover from browser | S228 (COBie/IFC export) |
| 20 | "What changed on Level 3?" | S229 (AI query on diff) |