The old ids live only in crates/engine/src/legacy_ids.rs (the legacy migration table): find_command maps them, so old scripts, recipes and control calls keep working, and saved shortcuts, recent and pinned commands are migrated on load (designs store no command ids). Parity maps the observed catalog ids to ours through xtask/data/fusion-ids.tsv. The agent rule now reads: our own dotted id, never another product's. Cargo.toml's repository points at github.com/bherbruck/solvecraft.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- solvecraft_io::vfs: the engine's file access (disk natively; in the browser an in-memory set of
files the host loads and stores). File commands and write_atomic go through it.
- Web host (apps/solvecraft-web/src/files.rs): stored designs are read from OPFS at start
(storage.persist() asked for) and written back when a command writes one; Save/Save As keep
designs in the browser, exports (STEP, STL, 3MF, OBJ, ...) download as files.
- File > Open shows "Files in this browser": open, insert, rename, download, delete, plus open or
insert from the computer (showOpenFilePicker where there is one, an <input type=file>
otherwise). Files dropped on the page are inserted or opened.
- Unsaved work is autosaved to OPFS and offered again after a reload or crash.
- Start page recents come from the stored designs, with thumbnails. In the browser the samples
are built when opened (a picture blocks the page there, and a kernel panic can't be caught).
- Pages without OPFS (http on a network address, old browsers) keep designs in local storage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
- IGES import (kernel iges_in, from the published specification). The file
is restated as STEP and read by the STEP reader, so an IGES file becomes
the same Import base feature.
- Manifold solid B-reps (186/514/510/508/504/502).
- Trimmed (144), bounded (143) and bare B-spline surfaces, sewn into a
solid by shared edges, with face orientation made consistent.
- Curves: lines, arcs, ellipses, composite and rational B-spline curves.
- Surfaces: planes, analytic surfaces 190-198, B-spline surfaces,
surfaces of revolution and tabulated cylinders.
- Transformations, units, colours, names (406 form 15 or labels).
Open, insert and drop .igs/.iges like STEP.
- IGES export (kernel iges_out): each body as a manifold solid B-rep on the
surfaces a STEP export uses, with name properties and colours.
ExportCommand to .igs.
- OBJ import as mesh bodies: objects/groups, polygons fanned, negative
indices, bad lines reported.
- STL: binary files whose header starts with "solid" and those with a zero
triangle count read as binary; non-finite vertices dropped; facet
normals ignored; ASCII with non-UTF-8 names. Mesh bodies get consistent
winding (stray inverted facets turned over).
- Tests: primitives and features round-trip through IGES (volume, area,
name, colour). Six trimmed patches sew into a closed box. Hostile IGES,
OBJ and STL inputs never panic. STL quirks. The engine exports a design
to IGES and opens it again. All 76 oracle parts round-trip through IGES
with matching volume (local check).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Fusion round trip WARNs on face counts:
- 48: the pulley's annular end faces arrived as 240° and 120° sectors.
- 54: the side faces and holes of a body glued to its mirror image came
in halves.
Changes:
- Planes merge: PLANE faces and flat B-spline sheets, as well as revolved
planes. A plane keeps several loops (an annulus, a face with holes), no
seam. Flat B-spline sheets are written as PLANE.
- Pieces of an extruded cylinder (B-spline sheets) merge when their edges
are circles square to the axis. The merged face is written as a
CYLINDRICAL_SURFACE, with its parameter seam on the face's seam edge.
- A full turn's loop is built explicitly: ring, seam, other ring (or the
apex on the axis), seam back. Before, it depended on edge order, and
after 81c85b5 the pulley's last pieces no longer merged.
- The read-back check moved to the whole file. If the merged file reads
with warnings and the unmerged one does not, the unmerged one is
written.
Results: 48 has 12 faces (Fusion 12), 54 has 12 (Fusion 12). Oracle
results are unchanged (73 PASS) and the STEP corpus passes 76/76. New
test: a plate with a hole glued to its mirror exports 8 faces, all
planes and cylinders, and round-trips.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Start page (shown on launch without a file, and from the house button in the application bar):
New Design, Open, recent designs (kept in the preferences, newest first) and built-in samples,
each card with a picture rendered from the design in the background. Samples are scripts of
engine commands: the sample plate plus a sheet metal bracket, a hinge assembly with a revolute
joint, a plastic enclosure (lip, bosses, rest, snap fit), a bolted flange with a parametric
circular pattern and a vent plate with a parametric rectangular pattern (test: all build
without a failing feature).
Several open designs as tabs in the application bar: each keeps its own session (undo,
selection), camera and hidden/shown items; + and Ctrl+N open a new design, opening a file or a
sample uses a new tab unless the current design is blank, closing a tab with unsaved changes
asks Save / Don't Save / Cancel. Control channel: ui.documents and ui.home (docs/control-protocol.md).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
- Surfaces of revolution follow ISO 10303-42 strictly in reader and writer: the
normal is d/d(angle) x d/d(profile), the opposite of truck's revolution, as
Fusion reads it (fixes Fusion inverting fillet sphere corners and the dimple).
step_orientation_errors flags faces whose loop runs clockwise round their
normal; engine, oracle and kernel round trips assert it.
- Revolved faces with analytic profiles are written as native PLANE,
CYLINDRICAL/CONICAL/SPHERICAL/TOROIDAL surfaces, and the pieces truck splits
a revolution into are merged back into one face per surface (with a seam
edge for full turns), so face counts match other systems.
- A horn torus (tight sweep: tube touching its axis) is written as one rational
B-spline face whose loop passes the pole twice, with truck's zero-length pole
edges collapsed, instead of a degenerate surface of revolution; the reader
starts such figure-eight loops off the pole (Fusion's own part 50 now imports
with the right volume).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Our writer assembles the file: AP242 header and contexts, a product per part
(or per component, with NEXT_ASSEMBLY_USAGE_OCCURRENCE and item-defined
placements per occurrence), named solids, surface colours as styled items,
ADVANCED_FACE for advanced breps. truck now writes only each body's B-rep,
which we copy in; identical geometric entities are written once and shared.
Designs with components export as assemblies (bodies in component frames).
step_validate also rejects unreferenced non-root entities. Tests: the sample
plate and a component assembly export, validate and read back with no
warnings and the same volume, area and face counts; the oracle replay checks
area and faces too (39 rebuildable cases pass). An independent Part 21
parser (step-p21, run outside the repo) accepts our exports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Vendored truck-stepio (writer only): an intersection curve's second surface
was written at the first one's id (duplicate ids for every boolean edge),
and revolved surfaces lost their orientation (the modeling-surface sense was
always true; inverted or mirrored revolutions came out inside out). Export
now writes intersection edges as C1 cubic B-splines through exact points,
so files carry plain 3D curves and no redundant surfaces.
Vendored truck-meshalgo: hinted parameter searches that run off a B-spline's
domain are rejected or clamped (meshing their grid never finished).
STEP import: straight revolution profiles are bounded in the meridian plane
and stop at the axis; loops on revolutions start away from the axis; face
extents include edge end points. Edges between pieces of one split surface
draw as seams.
kernel::step_validate checks a STEP file (duplicate ids, dangling
references, dense numbering); the oracle replay now exports every rebuilt
part, validates it and re-imports it with no warnings and the same volume
(all 32 rebuildable cases pass).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Export: ExportCommand/CLI --out/MCP export with .3mf write a 3MF Core package
([Content_Types].xml, _rels/.rels, 3D/3dmodel.model; millimetres), one
mesh object and build item per body, named after it, vertices shared and
welded watertight (T-junctions between faces split), base-material colours
when bodies carry one (STEP colours now ride on bodies). Tessellation as
for STL. File > Export 3MF.
Import: doc.open/drag-drop/CLI/MCP open accept .3mf and .stl; Insert Mesh
(ParaMeshInsertAlignCommand) adds them to a design as a MeshImport feature.
Kernel mesh bodies render, measure exactly, move and export; solid
features refuse them with a clear error. 3MF reading flattens components
and build transforms, converts units, reads colours; sizes, entries,
nesting and element counts are capped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
solvecraft-cli step-corpus and cargo xtask step-corpus [DIR]: open every
Fusion oracle part.step and compare body count, volume and area (1e-3) and
face count with Fusion's measurements; docs/step-import.md (29/29 pass).
solvecraft-cli eval/run accept STEP files and --in FILE.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
Import base feature (FeatureKind::Import, timeline type BaseFeature) holding
the STEP text and the file's product tree; bodies named from the file.
doc.open accepts .step/.stp (any case) as a new design; Insert STEP
(FusionImportCommandFromToolbar) adds one to the current design; File menu,
SOLID > INSERT, drag-and-drop (insert into a non-empty design, else open),
'solvecraft part.step', MCP open. Features (fillet, hole, sketch-on-face
cut, shell) work on imported bodies. Imports are cached so a file is read
once per command. Measure tightens its chord tolerance for small radii.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL