Release planning

CadCraft 1.0 impact map

Every fix and feature lined up for 1.0, and what each one touches: which apps, and which layers of the stack.

ProjectCadCraft
Sheet0.10 impact
Items110
Date2026-11-09
51Fix
22Feature
0Spike
28Platform
0Site ops
8Sanity check
1Decision
≈ 319days in the written 0.10 plans
  • Planned 101 on the plan for the release it is filed under
  • Built 0 built and working in /lab (the dev builds). Whether the public has it is its reach: "in the lab", "Live" (the last gate) or "switched off"; see docs/REACH-LIVE.md
  • Partly built 1 part of it is built in /lab; the rest waits (see "Waits on")
  • Promised 0 the live site already says it is coming
  • Moved 0 moved here from an earlier release or wishlist
  • Found 0 bug found after a release shipped; fixed in a point release or the next one
  • Candidate 3 recommended in a spike or session log; owner to choose
  • Community please test 0 built and in /use; a Discord post gives the steps and the expected result and asks people to try it on their own devices, files or know-how
  • Decision Time 5 a decision, check, file, key, flag or go only you can give; folds into the list once answered

Built means built and working in the lab. Live means the public can use it, and is the last gate: 0 Built · Live, 0 Built · in the lab.

Sheet 1 · impact areas

Where 0.10 lands

How many items touch each app and each layer, by kind. One item can touch several areas, so the rows add up to more than the item count. Pick a row to filter the schedule below.

Impact areaFixFeatureSpikePlatformSite opsSanity checkDecisionAll
Apps
CadCraft 20 17 – 10 – 3 1 51
BimCraft 18 20 – 9 – 4 1 52
ModelCraft 19 20 – 10 – 3 1 53
MarkupCraft 12 16 – 9 – 3 1 41
TakeoffCraft 14 16 – 9 – 3 1 43
CivilCraft 21 18 – 10 – 4 1 54
DetailCraft 15 17 – 9 – 4 1 46
PartCraft 15 17 – 9 – 3 1 45
Studio – 1 – – – – – 1
SuperCad Studio – 6 – 6 – 1 1 14
Layers
Site and services 13 3 – 8 – 1 – 25
Desktop host – 1 – 1 – – – 2
App shell 5 15 – 8 – 2 1 31
App code 23 4 – 3 – – – 30
Our engines 8 – – 1 – 1 – 10
Vendor engines – – – – – – – 0
Drawing surface 3 – – – – – – 3
Help and words 2 1 – – – 1 – 4
Tests and tooling 2 1 – 2 – 3 – 8

Sheet 2 · schedule

Every fix and feature

Grouped by track. App chips carry each app’s layer colour; Studio is in ink. "Waits on" names what has to happen first; the small lines under it say who asked and where the item is written up.

Add an item Fork map (Rust and C++ forks) The roadmap

Issues sync every 10 minutes; last sync Nov 9, 2026 7:00 pm.

ItemWhatAppsLayersStatusDaysWaits onIssues
Performance roadmap — wave 3 60
FixPERF.20 Link to PERF.20Comment on PERF.20 Scale: every text format reader holds the whole file as one JS string (DXF, LandXML, OBJ, DAE, ASCII STL, USDA, the native JSON documents)

Measured: a 1 GB DXF and a 692 MB LandXML die in TextDecoder.decode ("Cannot create a string longer than 0x1fffffe8"); a 358 MB LandXML needs 4.9 GB and 27 s; a 10 MB DXF needs 364 MB (38 bytes of heap per file byte, parsed twice through dxf-model.js:65). Sites: dxf-decode.js:35-49 and dxf.js:68-74, civilcraft.js:2485 and xml.js:27, modelcraft io/obj.js:84, and JSON.parse(await file.text()) for every .modelcraft/.detailcraft/.civilcraft document (modelcraft.js:3210). The caps that exist (CivilCraft 200 MB, ModelCraft 200 MB, OBJ 64 MB) are honest and stay until the readers stream. Change: byte-level tokenizers over Uint8Array fed from Blob.slice with lazily decoded values and Float64Array/Uint32Array output, the way lib/ifc scanStep already works. DXF first (the reader is 1,563 lines, L), then LandXML (M), OBJ and ASCII STL (S each). Target: 100 MB DXF under 1 GB of memory, 1 GB files open with a progress bar instead of an error.

CadCraftModelCraftCivilCraft App codeOur engines Planned 12 – docs/0.9-sessions/perf-wave3/
FixPERF.22 Link to PERF.22Comment on PERF.22 Scale: cc-dwg keeps 35 bytes of heap per file byte, clones the drawing out of the worker, and the writer is super-linear (extends PERF.5, PERF.9, PERF.10)

Measured at 10x (a 76 MB R2004 drawing, 1.4 M entities): readDwg 19.9 s and 2.6 GB after read (one object per entity and per vertex, objects-read.js:608-613 and :1105), the worker reply structuredClone adds 1.06 GB and 14.6 s (read-async.js:67), writeDwg 66 s (33 s from a fresh model), exponent 1.3. A 760 MB drawing would need about 27 GB: it does not fit anywhere. Browser ceiling today about 55 to 110 MB. Change: a struct-of-arrays entity store with lazy per-entity decode from the object map (the map and section locators are small; readDwg(bytes) at read.js:30 becomes openDwg(blob) with byte-range decoding), the worker reply as transferable typed buffers (or decode on the page from the transferred bytes), and a writer that streams sections to a FileSystemWritableFileStream. Reader L, writer M. The four apps carry byte copies of lib/dwg.

CadCraftBimCraftModelCraftCivilCraft Our engines Planned 12 – docs/0.9-sessions/perf-wave3/
FixPERF.23 Link to PERF.23Comment on PERF.23 Scale: cc-ifc copies the file for the worker and keeps every mesh in memory; save is O(lines) (extends PERF.8, PERF.10)

Measured: the index scans 1.9 GB in 15.9 s and 3.3 GB in Node (linear, typed arrays, lazy per-line parse: the healthy template for the other readers). But open-async.js:33 data.slice() doubles the bytes on the page (ceiling about 1 GB in a tab), open plus geometry plus save holds 12.8 times the file (2.57 GB at 200 MB; in the browser the heap grows about 1 GB per 100 MB of IFC: 210 MB peaked at 1.99 GB, 1 GB would need 10 GB), and save() walks every line with three chunks each (model.js:232-256, 8.8 s at 115 MB). Change: transfer the caller's buffer or let the worker read from the Blob; stream meshes to GPU buffers with an LRU instead of keeping all triangles in JS; save by coalesced byte ranges into a writable stream. Pairs with the BimCraft geometry-off-the-page-thread row (PERF.8).

BimCraftDetailCraft Our engines Planned 4 – docs/0.9-sessions/perf-wave3/
FixPERF.25 Link to PERF.25Comment on PERF.25 Scale: point clouds pass 2 GB, but the octree merge is single-threaded, LAZ copies the whole file into WASM and E57 is one 512 MB buffer (extends PERF.10)

Measured with lib/pointcloud (tools/perf/gen/gen-las.mjs made 50 M and 100 M point LAS files): 212 MB/10.6 M points 5.5 s, 954 MB/50 M 36.5 s, 1.9 GB/100 M 59.5 s with 3.8 GB in the in-memory store. This is the one path that reads a 2 GB user file without holding it (file-backed Blob, 2 MB windows, OPFS/IndexedDB store, packed octree nodes, transferred worker replies). The merge step is 70 % of the time (2.2 s, 25 s, 42 s) and runs on one thread; LAZ allocates the whole file in the WASM heap (las.js:187-197 _malloc(file.size)); E57 reads one 512 MB buffer (e57.js:440). So a 2 GB LAZ or a 600 MB E57 fails where the LAS passes. Change: merge across a worker pool (subtrees are independent), LAZ chunk-table streaming through a bounded heap window, E57 section slicing.

CadCraftBimCraftCivilCraft Our engines Planned 4 – docs/0.9-sessions/perf-wave3/
FixPERF.31 Link to PERF.31Comment on PERF.31 CivilCraft: Surface.outline() takes 20 to 30 s per call at 1 M triangles and runs again on every zoom bucket (63 % of a 30 s open)

Measured on the 500k-point survey (survey-500k.civilcraft.json and landxml-tin-500k.xml): tin.js:633-648 builds string keys for 3 M directed edges with no memo, and planScene calls outline() on every mmBucket change, so it is 63 % of the 30 s open, 79 % of the scene phase, and wheel frames have a p95 of 13 to 36 s on both files. Change: memoize the outline per surface version and use integer or half-edge keys (about 100 ms once). The biggest single win of the 2D track. Healthy around it: elevationAt 0.25 ms, profiles 4 to 10 ms, Delaunator about 0.3 s at 500k, indexed picking (16 ms sweeps).

CivilCraft App codeOur engines Planned 1 – docs/0.9-sessions/perf-wave3/
FixPERF.37 Link to PERF.37Comment on PERF.37 BimCraft: the first click builds the inverse index on the page thread (5 to 12 s), picking raycasts every triangle, a section plane rebuilds all caps

Measured in /use 0.8.1 on 22.5 / 115 / 201 MB IFC (tools/perf/apps3d-bimcraft.mjs): the first property lookup calls ifc/model.js:173 inverse() (api.js:347-421) over the whole file: one 5.1 s task at 115 MB, 7.7 s plus properties = 12.1 s blocked at 201 MB. hitAt (viewer3d.js:833) has no bounding-volume tree although three-mesh-bvh is vendored: 47 to 133 ms per raycast at 683k triangles, 180 to 508 ms at 2.26 M, on every hover. setSection rebuilds every batch's stencil caps (updateCaps viewer3d.js:504): 1.4 s, 3.9 s, 8.0 s. Change: build the inverse index in the scan worker (open-async.js) or in idle slices after open; computeBoundsTree per batch; cache per-batch cap geometry and cull batches by the plane. Open itself: blocking 9.0, 13.9, 18.5 s with longest tasks 3.0, 5.5, 8.2 s (StreamAllMeshes api.js:312 in one synchronous loop, appendGeometry ifc-model.js:238 into JS arrays, runEdges ifc-vis.js:111 at 1.1 s per million triangles, the property index put at open): that is PERF.8, now with 10x numbers. Healthy: batching (46 to 104 draw calls), render CPU 2 to 7 ms, the tree panel (19k nodes, setTree 12 ms), idle after open.

BimCraft App codeOur engines Planned 3 – docs/0.9-sessions/perf-wave3/
FixPERF.39 Link to PERF.39Comment on PERF.39 PartCraft: a rebuild is one synchronous task (750 features 3.0 s, a 40 by 40 hole plate 8.9 s, every edit 1.3 to 1.6 s) and the D7.51 checkpoints save nothing

Measured in /use 0.8.1 (tools/perf/apps3d-partcraft.mjs): rebuilds are linear (4 to 8 ms per feature, 5.6 ms per hole: 50 features 0.32 s, 200 1.6 s, 750 3.0 s; plates 10x10 0.43 s, 20x20 1.5 s where the 0.5 JS died, 30x30 3.7 s, 40x40 8.9 s), but rebuild() (partcraft.js:351 into the manifold wasm) runs on the page thread as one task, so the app freezes for the whole of it, and an edit of the LAST feature with the checkpoint costs 1,475 ms against 1,352 ms for a full rebuild because prefixKeys (kernel.js:814) hashes every feature's JSON per rebuild. Change: the mesh kernel in a worker like brep-worker.js with progress and cancel, cheap prefix hashing (a per-feature hash kept on the feature), undo and redo (1.6 and 1.3 s today) from cached results. Healthy: orbit at 15 draw calls, the Parameters window 5 ms.

PartCraft App codeOur engines Planned 4 – docs/0.9-sessions/perf-wave3/
FixPERF.76 Link to PERF.76Comment on PERF.76 Code: O(n squared) searches in kernel code (ModelCraft mesh ops, the shared m3d model, CivilCraft LandXML) and render functions that rebuild whole panels

Nested-loop searches with includes/some inside N by N loops: modelcraft mesh/ops.js:421 subdivide (also :471, :820, :915), m3d model.js:693, :778, :1637, :1957 (in both ModelCraft and CadCraft's copy), civilcraft landxml.js:298-322. These are the places a 10x model turns into a 100x wait; the 3D track's numbers (ModelCraft push/pull and undo at 500k faces) land here. Change: Sets and Maps keyed by vertex or id, measured before and after with tools/perf/scale-bench.mjs and the apps3d scripts. Render functions that rebuild and re-query the DOM on every call (196 querySelectorAll and 315 addEventListener inside render functions; takeoffcraft.js sheet list on every sheet switch, shell app-workspace.js, supercadcraft.js, cadcraft renderLayers and renderSelTotals): keyed children and incremental updates, measured on the 2D track's 2,000-sheet set.

CadCraftModelCraftTakeoffCraftCivilCraft App codeOur engines Planned 4 – docs/0.9-sessions/perf-wave3/
Suggest an item

Anyone can send one; no account and no name needed. The team reads each idea, and the ones we take on appear on this page. Please leave out web addresses.