M0: docs (README, CLAUDE/AGENTS, ROADMAP, control protocol, NOTICE, attribution), example, parity and oracle reports
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
8a811f8eff
commit
0f3e7701a7
10 files changed
+446
No files matched your search
@@ -0,0 +1,85 @@
|
||||
# SolveCraft — instructions for agents
|
||||
|
||||
SolveCraft is a clean-room, open-source, pure-Rust parametric 3D CAD application in the style of
|
||||
Autodesk Fusion: sketches with a constraint solver, a parametric timeline of features, a B-rep
|
||||
kernel, and a desktop UI that agents can drive. Siblings with the same conventions live next to
|
||||
it in `storytold/`: `cadcraft` (AutoCAD-style, the closest relative), `photocraft`, `vectorcraft`,
|
||||
`gridcraft`, `designcraft`, `wordcraft`, `deckcraft`, `soundcraft`. Repos don't share code; when
|
||||
code is adapted from a sibling (MIT OR Apache-2.0) it is noted in ATTRIBUTION.md.
|
||||
|
||||
## Start every session here
|
||||
1. Read `plan/STATUS.md` (current milestone, next task), then the task in `plan/execution-plan.md`
|
||||
and the relevant `plan/architecture.md` section. Behaviour reference: `plan/fusion/`
|
||||
(`menu-tree.json` is Fusion's toolbar dump; `oracle/*/` are parts built in Fusion with their
|
||||
recipes and measurements).
|
||||
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
||||
is rejected for licence reasons).
|
||||
3. Follow the autonomous operation protocol (`plan/execution-plan.md` §6). Don't stop to ask
|
||||
unless it lists the decision as the owner's.
|
||||
|
||||
`plan/` is gitignored (local only).
|
||||
|
||||
## Never crash
|
||||
People trust SolveCraft with their designs; a crash loses their work. **This outranks feature work.**
|
||||
- **No panics in non-test code:** no `unwrap()`, `expect()`, `panic!`, `unreachable!`, `todo!`,
|
||||
`unimplemented!`; no `unsafe` (`unsafe_code = "forbid"`).
|
||||
- **Errors are `Result<T, E>`** through the crate's error type and `?`. An unfinished feature
|
||||
returns an error ("not supported yet: …"); it never panics.
|
||||
- **Input-derived numbers are hostile** (command parameters, design files, control-channel
|
||||
input): `get()` not `[i]`, finite checks, caps on sizes and loop counts.
|
||||
- **Third-party kernel calls are guarded:** everything that calls `truck` goes through
|
||||
`solvecraft_kernel::guard`, which turns a panic into `KernelError::Internal`.
|
||||
- **Last-resort guard:** `Session::execute` runs every command under `catch_unwind`; an escaped
|
||||
panic restores the design and reports `EngineError::Internal`.
|
||||
- **Prove it:** every crash fix lands with a regression test (see `hostile_params_never_panic`).
|
||||
- Every production crate root carries
|
||||
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
||||
|
||||
## Non-negotiables
|
||||
- **Clean-room.** Fusion may be *observed* black-box (its UI, its toolbar dump, parts built in it
|
||||
and their measurements, kept under `plan/fusion/`, never committed). Never copy Autodesk icons,
|
||||
artwork, help text, tooltips, templates or materials, and never commit files produced by
|
||||
Fusion. Command ids and command names are used as identifiers only (`xtask/data/fusion-catalog.tsv`
|
||||
holds ids and names, nothing else). File formats come from public specifications. **Never read,
|
||||
copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs), SolveSpace,
|
||||
CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. The sketch solver and the blend
|
||||
operations are our own.
|
||||
- **Assets — absolutely essential.** SolveCraft contains **no Autodesk iconography, images,
|
||||
fonts or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`). Any
|
||||
file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
||||
(`cargo xtask assets` enforces it). Screenshots of Autodesk software are never committed.
|
||||
Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
|
||||
(`CommandSpec`: id = Fusion's command id where Fusion has the command, else a dotted id; label;
|
||||
toolbar tab and panel; icon; shortcut; params doc; `enabled`; JSON `run`) + tests. The toolbar,
|
||||
dialogs, sketch tools, palette, scripts, CLI and control channel all reach the same commands.
|
||||
- **Programmatic calls never open dialogs.** `engine.execute` runs the JSON form; only toolbar
|
||||
clicks (`ui.start`) start interactive tools and dialogs, which then run commands.
|
||||
- **Layering** is enforced by `cargo xtask layers`: L0 `geom` → L1 `sketch`, `kernel`, `render`
|
||||
→ L2 `doc` → L3 `io` → L4 `engine` → L5 `ui-egui` → apps. Nothing below L5 depends on
|
||||
egui/eframe/winit/wgpu/rfd. **The UI crate is swappable.** Only `crates/kernel` may use `truck`.
|
||||
- **The UI is thin**: panels read engine state and act through `app.run(id, params)` /
|
||||
`app.start(id)`. Colours come from `theme::Tokens`.
|
||||
- **Rust only.** Units are millimetres and radians internally; Z is up.
|
||||
- **Quality gates** before every commit: `cargo xtask ci` (fmt, clippy -D warnings, tests,
|
||||
assets, layers). Commit after every feature arc that builds.
|
||||
|
||||
## Running and looking at the app
|
||||
- `cargo run --release -p solvecraft -- --sample --control PORT` (sample design + control channel).
|
||||
Pick a free port. Without a display, run it under `Xvfb :99` with `DISPLAY=:99`.
|
||||
- Drive it with JSON lines on `127.0.0.1:PORT` (see `docs/control-protocol.md`):
|
||||
- `{"id":1,"method":"engine.execute","params":{"command":"Extrude","params":{"distance":20}}}`
|
||||
- `{"id":2,"method":"ui.start","params":{"command":"SketchCreate"}}` then `ui.click {x, y}`
|
||||
- `{"id":3,"method":"ui.screenshot","params":{"path":"/tmp/shot.png"}}` then read the PNG.
|
||||
- **For UI work, look at the result** (screenshot, read the PNG). Without a window use
|
||||
`ui.render` or `solvecraft-cli snapshot`.
|
||||
- Headless: `solvecraft-cli run script.json --out part.step`, `solvecraft-cli eval design.solvecraft`,
|
||||
`solvecraft-cli snapshot script.json --out shot.png`, `solvecraft-cli commands`.
|
||||
- Fusion oracle: `cargo xtask oracle` replays `plan/fusion/oracle/*/recipe.json` and compares
|
||||
with Fusion's `measure.json` (writes `docs/oracle.md`).
|
||||
- Build with `CARGO_TARGET_DIR=<repo>/target`. Windows: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||
|
||||
## Roadmap
|
||||
`ROADMAP.md` (committed) tracks status, milestones, parity and estimates. Update it whenever a
|
||||
milestone task lands. `cargo xtask parity` recomputes command parity in `docs/parity.md`;
|
||||
`cargo xtask oracle` recomputes `docs/oracle.md`.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Attribution
|
||||
|
||||
Every non-code asset in this repository (images, icons, fonts, example parts) is listed here with
|
||||
its author, source and licence. `cargo xtask assets` (part of `cargo xtask ci`) fails if an asset
|
||||
file is missing from this table.
|
||||
|
||||
**Policy (mandatory):** SolveCraft contains **no Autodesk iconography, images, artwork, fonts,
|
||||
templates, materials or help text.** Every asset is original work by SolveCraft contributors or
|
||||
third-party material under an open licence. Screenshots of Autodesk software are never committed.
|
||||
|
||||
Generated-in-code assets are original and have no file to list:
|
||||
- the UI icon set (`crates/ui-egui/src/icons.rs`);
|
||||
- the view cube, navigation bar and timeline glyphs (`crates/ui-egui/src/viewport.rs`,
|
||||
`crates/ui-egui/src/timeline.rs`).
|
||||
|
||||
## Files
|
||||
|
||||
| File | Author | Source | Licence |
|
||||
|---|---|---|---|
|
||||
| docs/screenshots/sample-plate.png | SolveCraft contributors | screenshot of SolveCraft itself (`solvecraft --sample`) | MIT OR Apache-2.0 |
|
||||
|
||||
## Code adapted from sibling projects
|
||||
|
||||
| SolveCraft file | Adapted from | Licence |
|
||||
|---|---|---|
|
||||
| xtask/src/layers.rs | CADCraft `xtask/src/layers.rs` (dependency layering rules and tests) | MIT OR Apache-2.0 |
|
||||
| apps/solvecraft/src/control_server.rs | CADCraft `apps/cadcraft/src/control_server.rs` (loopback JSON-lines server) | MIT OR Apache-2.0 |
|
||||
| crates/ui-egui/src/lib.rs (screenshot queue, synthetic input) | CADCraft `crates/ui-egui/src/lib.rs` | MIT OR Apache-2.0 |
|
||||
| crates/ui-egui/src/control.rs (method dispatch and screenshot saving) | CADCraft `crates/ui-egui/src/control.rs` | MIT OR Apache-2.0 |
|
||||
| crates/ui-egui/src/gpu.rs (paint-callback structure) | CADCraft `crates/ui-egui/src/gpu.rs` | MIT OR Apache-2.0 |
|
||||
| LICENSE-MIT, LICENSE-APACHE (licence text) | CADCraft | — |
|
||||
@@ -0,0 +1,85 @@
|
||||
# SolveCraft — instructions for agents
|
||||
|
||||
SolveCraft is a clean-room, open-source, pure-Rust parametric 3D CAD application in the style of
|
||||
Autodesk Fusion: sketches with a constraint solver, a parametric timeline of features, a B-rep
|
||||
kernel, and a desktop UI that agents can drive. Siblings with the same conventions live next to
|
||||
it in `storytold/`: `cadcraft` (AutoCAD-style, the closest relative), `photocraft`, `vectorcraft`,
|
||||
`gridcraft`, `designcraft`, `wordcraft`, `deckcraft`, `soundcraft`. Repos don't share code; when
|
||||
code is adapted from a sibling (MIT OR Apache-2.0) it is noted in ATTRIBUTION.md.
|
||||
|
||||
## Start every session here
|
||||
1. Read `plan/STATUS.md` (current milestone, next task), then the task in `plan/execution-plan.md`
|
||||
and the relevant `plan/architecture.md` section. Behaviour reference: `plan/fusion/`
|
||||
(`menu-tree.json` is Fusion's toolbar dump; `oracle/*/` are parts built in Fusion with their
|
||||
recipes and measurements).
|
||||
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
||||
is rejected for licence reasons).
|
||||
3. Follow the autonomous operation protocol (`plan/execution-plan.md` §6). Don't stop to ask
|
||||
unless it lists the decision as the owner's.
|
||||
|
||||
`plan/` is gitignored (local only).
|
||||
|
||||
## Never crash
|
||||
People trust SolveCraft with their designs; a crash loses their work. **This outranks feature work.**
|
||||
- **No panics in non-test code:** no `unwrap()`, `expect()`, `panic!`, `unreachable!`, `todo!`,
|
||||
`unimplemented!`; no `unsafe` (`unsafe_code = "forbid"`).
|
||||
- **Errors are `Result<T, E>`** through the crate's error type and `?`. An unfinished feature
|
||||
returns an error ("not supported yet: …"); it never panics.
|
||||
- **Input-derived numbers are hostile** (command parameters, design files, control-channel
|
||||
input): `get()` not `[i]`, finite checks, caps on sizes and loop counts.
|
||||
- **Third-party kernel calls are guarded:** everything that calls `truck` goes through
|
||||
`solvecraft_kernel::guard`, which turns a panic into `KernelError::Internal`.
|
||||
- **Last-resort guard:** `Session::execute` runs every command under `catch_unwind`; an escaped
|
||||
panic restores the design and reports `EngineError::Internal`.
|
||||
- **Prove it:** every crash fix lands with a regression test (see `hostile_params_never_panic`).
|
||||
- Every production crate root carries
|
||||
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
||||
|
||||
## Non-negotiables
|
||||
- **Clean-room.** Fusion may be *observed* black-box (its UI, its toolbar dump, parts built in it
|
||||
and their measurements, kept under `plan/fusion/`, never committed). Never copy Autodesk icons,
|
||||
artwork, help text, tooltips, templates or materials, and never commit files produced by
|
||||
Fusion. Command ids and command names are used as identifiers only (`xtask/data/fusion-catalog.tsv`
|
||||
holds ids and names, nothing else). File formats come from public specifications. **Never read,
|
||||
copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs), SolveSpace,
|
||||
CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. The sketch solver and the blend
|
||||
operations are our own.
|
||||
- **Assets — absolutely essential.** SolveCraft contains **no Autodesk iconography, images,
|
||||
fonts or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`). Any
|
||||
file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
||||
(`cargo xtask assets` enforces it). Screenshots of Autodesk software are never committed.
|
||||
Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
|
||||
(`CommandSpec`: id = Fusion's command id where Fusion has the command, else a dotted id; label;
|
||||
toolbar tab and panel; icon; shortcut; params doc; `enabled`; JSON `run`) + tests. The toolbar,
|
||||
dialogs, sketch tools, palette, scripts, CLI and control channel all reach the same commands.
|
||||
- **Programmatic calls never open dialogs.** `engine.execute` runs the JSON form; only toolbar
|
||||
clicks (`ui.start`) start interactive tools and dialogs, which then run commands.
|
||||
- **Layering** is enforced by `cargo xtask layers`: L0 `geom` → L1 `sketch`, `kernel`, `render`
|
||||
→ L2 `doc` → L3 `io` → L4 `engine` → L5 `ui-egui` → apps. Nothing below L5 depends on
|
||||
egui/eframe/winit/wgpu/rfd. **The UI crate is swappable.** Only `crates/kernel` may use `truck`.
|
||||
- **The UI is thin**: panels read engine state and act through `app.run(id, params)` /
|
||||
`app.start(id)`. Colours come from `theme::Tokens`.
|
||||
- **Rust only.** Units are millimetres and radians internally; Z is up.
|
||||
- **Quality gates** before every commit: `cargo xtask ci` (fmt, clippy -D warnings, tests,
|
||||
assets, layers). Commit after every feature arc that builds.
|
||||
|
||||
## Running and looking at the app
|
||||
- `cargo run --release -p solvecraft -- --sample --control PORT` (sample design + control channel).
|
||||
Pick a free port. Without a display, run it under `Xvfb :99` with `DISPLAY=:99`.
|
||||
- Drive it with JSON lines on `127.0.0.1:PORT` (see `docs/control-protocol.md`):
|
||||
- `{"id":1,"method":"engine.execute","params":{"command":"Extrude","params":{"distance":20}}}`
|
||||
- `{"id":2,"method":"ui.start","params":{"command":"SketchCreate"}}` then `ui.click {x, y}`
|
||||
- `{"id":3,"method":"ui.screenshot","params":{"path":"/tmp/shot.png"}}` then read the PNG.
|
||||
- **For UI work, look at the result** (screenshot, read the PNG). Without a window use
|
||||
`ui.render` or `solvecraft-cli snapshot`.
|
||||
- Headless: `solvecraft-cli run script.json --out part.step`, `solvecraft-cli eval design.solvecraft`,
|
||||
`solvecraft-cli snapshot script.json --out shot.png`, `solvecraft-cli commands`.
|
||||
- Fusion oracle: `cargo xtask oracle` replays `plan/fusion/oracle/*/recipe.json` and compares
|
||||
with Fusion's `measure.json` (writes `docs/oracle.md`).
|
||||
- Build with `CARGO_TARGET_DIR=<repo>/target`. Windows: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||
|
||||
## Roadmap
|
||||
`ROADMAP.md` (committed) tracks status, milestones, parity and estimates. Update it whenever a
|
||||
milestone task lands. `cargo xtask parity` recomputes command parity in `docs/parity.md`;
|
||||
`cargo xtask oracle` recomputes `docs/oracle.md`.
|
||||
@@ -0,0 +1,21 @@
|
||||
SolveCraft
|
||||
Copyright (c) 2026 SolveCraft contributors.
|
||||
Licensed under the MIT License or the Apache License, Version 2.0, at your option
|
||||
(LICENSE-MIT, LICENSE-APACHE).
|
||||
|
||||
Third-party material
|
||||
|
||||
Software dependencies are listed in Cargo.lock. The geometry kernel builds on the truck crates
|
||||
(truck-modeling, truck-shapeops, truck-meshalgo, truck-stepio, truck-topology and their
|
||||
dependencies, https://github.com/ricosjp/truck), licensed under the Apache License 2.0 and used
|
||||
unmodified as libraries.
|
||||
|
||||
Some code is adapted from sibling projects in the storytold family (CADCraft), which are
|
||||
licensed MIT OR Apache-2.0; ATTRIBUTION.md lists the files.
|
||||
|
||||
None of the bundled assets come from third parties: every icon is drawn in code. The per-file
|
||||
list is in ATTRIBUTION.md.
|
||||
|
||||
SolveCraft is an independent project and is not affiliated with, sponsored by or endorsed by
|
||||
Autodesk, Inc. Autodesk and Fusion are trademarks of Autodesk, Inc.; they are used here only to
|
||||
describe compatibility goals.
|
||||
@@ -0,0 +1,79 @@
|
||||
# SolveCraft
|
||||
|
||||
SolveCraft is an open-source parametric 3D CAD application written in Rust, in the style of
|
||||
Autodesk Fusion: sketch on a plane, constrain and dimension the sketch, turn profiles into solids
|
||||
with extrude and revolve, round edges, combine bodies, and change a parameter to watch the whole
|
||||
timeline rebuild. It is a clean-room implementation (see [CLAUDE.md](CLAUDE.md)) and part of the
|
||||
storytold "craft" family.
|
||||
|
||||

|
||||
|
||||
**Status: early (milestone M0 done, M1 in progress).** See [ROADMAP.md](ROADMAP.md),
|
||||
[docs/parity.md](docs/parity.md) (command parity with Fusion's Design workspace) and
|
||||
[docs/oracle.md](docs/oracle.md) (parts built in Fusion, rebuilt and measured in SolveCraft).
|
||||
|
||||
## What works
|
||||
|
||||
- **Sketches** on the origin planes, offset planes or planar faces: lines, rectangles (2-point,
|
||||
3-point, centre), circles (centre, 2-point, 3-point), arcs (3-point, centre), polygons, slots
|
||||
and points; construction geometry.
|
||||
- **Constraints and dimensions** solved by our own solver (damped Gauss–Newton with
|
||||
degree-of-freedom analysis): coincident, horizontal/vertical, parallel, perpendicular, tangent,
|
||||
equal, concentric, collinear, midpoint, symmetry, fix; linear, aligned, horizontal, vertical,
|
||||
radius, diameter and angle dimensions driven by parameters. Over-constraining edits are
|
||||
rejected; fully constrained geometry turns black.
|
||||
- **Profiles** found automatically, including regions split by lines and holes inside outlines.
|
||||
- **Features** on a parametric timeline: extrude (one side, flipped, symmetric, two-sided, start
|
||||
offset; new body, join, cut, intersect), revolve, fillet and chamfer (straight convex edges),
|
||||
box, cylinder, sphere, torus, combine, move. The timeline rebuilds incrementally from the first
|
||||
changed feature; it can be rolled back, and features can be suppressed, renamed, edited and
|
||||
deleted.
|
||||
- **Parameters** with unit-aware expressions (`2 * width + 5 mm`, `angle / 2`).
|
||||
- **Files**: designs as JSON (`.solvecraft`), export to STEP, STL (binary/ASCII) and OBJ.
|
||||
- **Desktop app** (egui + wgpu): toolbar with workspace tabs, browser, timeline, 3D viewport with
|
||||
view cube and navigation bar, sketch tools, feature dialogs, command palette, and a JSON-lines
|
||||
control channel so agents and tests can drive it.
|
||||
- **Headless CLI** `solvecraft-cli`: run command scripts, measure (volume, area, centre of mass,
|
||||
face/edge/vertex counts), export, render PNG snapshots, replay Fusion oracle recipes.
|
||||
|
||||
## Build and run
|
||||
|
||||
```sh
|
||||
cargo run --release -p solvecraft -- --sample # desktop app with a sample part
|
||||
cargo run --release -p solvecraft-cli -- commands # the command registry
|
||||
cargo run --release -p solvecraft-cli -- run examples/bracket.json --out bracket.step
|
||||
cargo run --release -p solvecraft-cli -- snapshot examples/bracket.json --out bracket.png
|
||||
cargo xtask ci # fmt, clippy, tests, assets, layers
|
||||
```
|
||||
|
||||
Windows builds: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||
|
||||
## Scripts
|
||||
|
||||
A script is a JSON list of commands, the same ones the UI runs:
|
||||
|
||||
```json
|
||||
{"commands": [
|
||||
{"command": "SketchCreate", "params": {"plane": "XY"}},
|
||||
{"command": "ShapeRectangleTwoPoint", "params": {"p0": [0, 0], "p1": [40, 30]}},
|
||||
{"command": "Extrude", "params": {"distance": 20}},
|
||||
{"command": "FusionFilletEdgesCommand", "params": {"edges": [[0, 0, 10]], "radius": 3}}
|
||||
]}
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
| Layer | Crates | Role |
|
||||
|---|---|---|
|
||||
| L0 | `geom` | vectors, planes, profiles, meshes and their measures |
|
||||
| L1 | `sketch`, `kernel`, `render` | constraint solver and profiles; the B-rep kernel boundary (truck); view math and CPU rasterizer |
|
||||
| L2 | `doc` | parameters, expressions, the feature timeline and its incremental evaluation |
|
||||
| L3 | `io` | design files, STL/OBJ/STEP export |
|
||||
| L4 | `engine` | the session and the command registry (everything is a command) |
|
||||
| L5 | `ui-egui` | the swappable desktop front end |
|
||||
| apps | `solvecraft`, `solvecraft-cli` | desktop app, headless CLI |
|
||||
|
||||
## Licence
|
||||
|
||||
MIT OR Apache-2.0, at your option. SolveCraft is not affiliated with Autodesk; Fusion is a
|
||||
trademark of Autodesk, Inc.
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
# SolveCraft roadmap
|
||||
|
||||
Status as of **2026-10-07**. SolveCraft targets Fusion-style parametric modelling (sketch →
|
||||
features → parametric timeline) as an open, pure-Rust, agent-drivable application.
|
||||
|
||||
## At a glance
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Where are we? | **M0 (vertical slice) done.** Sketch with solver, extrude/revolve/fillet/chamfer/cut, parameters that rebuild the timeline, STEP/STL export, desktop app, CLI, oracle harness. |
|
||||
| Command parity (SOLID + SKETCH toolbar) | **46 / 291 (16%)** — [docs/parity.md](docs/parity.md) |
|
||||
| Fusion oracle | **2 / 29 parts match** Fusion's measurements (16 need features not built yet) — [docs/oracle.md](docs/oracle.md) |
|
||||
| Tests | 60 (solver, profiles, kernel booleans/blends/measures, expressions, timeline, file formats, camera, engine end-to-end, hostile-input fuzz over every command) |
|
||||
| Gates | `cargo xtask ci`: fmt, clippy -D warnings, tests, asset attribution, layering — green |
|
||||
| Weighted parity estimate | **≈ 5%** of Fusion's Design workspace by importance (sketch + basic solids are the core, but surfaces, assemblies, sheet metal, CAM, drawings are untouched) |
|
||||
| Time to a useful alpha (M0–M6) | ≈ **150 agent hours** remain |
|
||||
|
||||
## Milestones
|
||||
|
||||
| # | Milestone | Status | Hours left |
|
||||
|---|---|---|---|
|
||||
| M0 | Vertical slice | done | — |
|
||||
| M1 | Sketch depth, oracle sketch cases (arcs, taper, two-sided, sketch modify tools) | in progress | 16 |
|
||||
| M2 | Robust modelling: coplanar booleans in the kernel, holes, patterns, mirror, shell, draft, split, construction geometry | planned | 24 |
|
||||
| M3 | General fillets and chamfers (curved edges, chains, vertex blends) | planned | 30 |
|
||||
| M4 | Files: STEP import, mesh import, DXF sketches, 3MF | planned | 16 |
|
||||
| M5 | Persistent naming of faces and edges | planned | 20 |
|
||||
| M6 | UI depth: profile shading, selection filters, measure tool, section view, edit dialogs, drag-solve | planned | 24 |
|
||||
| M7 | Sweep, loft, rib, web, emboss, thread, coil, pipe | planned | 24 |
|
||||
| M8 | Surface workspace | planned | 30 |
|
||||
| M9 | Assemblies and joints | planned | 40 |
|
||||
| M10 | Sheet metal | planned | 30 |
|
||||
| M11 | 2D drawings | planned | 30 |
|
||||
| M12 | Release: installers, signing, docs, performance | planned | 16 |
|
||||
|
||||
## Known limitations
|
||||
|
||||
- Fillets and chamfers: straight convex edges between planar faces with perpendicular planar end
|
||||
faces; two blended edges may not share a corner yet.
|
||||
- Booleans of bodies with coincident faces fail unless they come from extrudes (where the tool is
|
||||
extended automatically); fully internal voids are not supported.
|
||||
- Mass properties come from fine tessellation (curved faces within ~1e-4 relative).
|
||||
- No STEP import yet; no persistent naming (fillet edges are re-found by position).
|
||||
|
||||
## Kernel
|
||||
|
||||
truck (Apache-2.0) behind our own `kernel` crate, with our own blend operation and boolean
|
||||
retry/validation; see `plan/adr/0001-geometry-kernel.md` (local) — summary in README.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Control protocol
|
||||
|
||||
`solvecraft --control PORT` (or `SOLVECRAFT_CONTROL_PORT=PORT`) listens on `127.0.0.1:PORT` for
|
||||
JSON lines. Each request is one line `{"id": …, "method": "…", "params": {…}}`; each reply is one
|
||||
line `{"id": …, "ok": true, "result": …}` or `{"id": …, "ok": false, "error": "…"}`. Requests are
|
||||
handled on the UI thread between frames; pointer and keyboard input is injected as real egui
|
||||
events, one pointer event per frame.
|
||||
|
||||
## Engine
|
||||
|
||||
| Method | Params | Result |
|
||||
|---|---|---|
|
||||
| `engine.execute` | `command`: command id, `params`: JSON object | the command's result |
|
||||
| `engine.script` | `commands`: `[{command, params}, …]` | results, stops at the first error |
|
||||
| `engine.commands` | — | every command: id, label, tab, panel, icon, shortcut, params doc, enabled |
|
||||
| `document.inspect` | `measure?`: bool | parameters, timeline (errors, timings), bodies, sketches, selection |
|
||||
|
||||
Commands never open dialogs when run this way. `solvecraft-cli commands` prints the same registry.
|
||||
|
||||
## UI
|
||||
|
||||
| Method | Params | Notes |
|
||||
|---|---|---|
|
||||
| `ui.inspect` | — | UI state, viewport rect, camera, active tool/dialog, hover, renderer, timings |
|
||||
| `ui.set` | any `UiState` field (`tab`, `perspective`, `showGrid`, `hiddenBodies`, …) | |
|
||||
| `ui.view` | `view`: `front`, `back`, `top`, `bottom`, `left`, `right`, `iso`, `home`, `fit` | |
|
||||
| `ui.start` | `command` | like a toolbar click: starts the sketch tool or dialog for the command |
|
||||
| `ui.click` | `x`, `y` (screen points), `button?`: left/right/middle, `shift?` | real pointer input |
|
||||
| `ui.move` | `x`, `y` | |
|
||||
| `ui.scroll` | `x`, `y`, `delta?` | wheel zoom at the cursor |
|
||||
| `ui.key` | `key` (egui key name, `Enter`, `Escape`…), `cmd?`, `shift?` | |
|
||||
| `ui.text` | `text` | typed text |
|
||||
| `ui.screenshot` | `path?` | PNG of the window (needs a presented frame) |
|
||||
| `ui.render` | `path`, `width?`, `height?` | CPU render of the model with the current camera (no window needed) |
|
||||
| `ui.resize` | `width`, `height` | |
|
||||
| `app.quit` | — | |
|
||||
|
||||
## Example
|
||||
|
||||
```text
|
||||
{"id":1,"method":"engine.execute","params":{"command":"SketchCreate","params":{"plane":"XY"}}}
|
||||
{"id":2,"method":"engine.execute","params":{"command":"ShapeRectangleTwoPoint","params":{"p0":[0,0],"p1":[40,30]}}}
|
||||
{"id":3,"method":"engine.execute","params":{"command":"Extrude","params":{"distance":20}}}
|
||||
{"id":4,"method":"engine.execute","params":{"command":"FusionFilletEdgesCommand","params":{"edges":[[0,0,10]],"radius":3}}}
|
||||
{"id":5,"method":"ui.screenshot","params":{"path":"/tmp/part.png"}}
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
# Fusion oracle
|
||||
|
||||
Generated by `cargo xtask oracle`. Each case is a part built in Fusion (recipe and measurements kept locally in `plan/fusion/oracle/`, not committed). SolveCraft replays the recipe through its command engine and compares body count, volume and area (relative tolerance 1e-3) and face/edge/vertex counts (exact).
|
||||
|
||||
**2 / 29 cases pass** (16 need features not implemented yet).
|
||||
|
||||
| Case | Result | Notes |
|
||||
|---|---|---|
|
||||
| 01-box | pass | |
|
||||
| 02-cylinder | pass | |
|
||||
| 03-box-through-hole | FAIL | step 11 (Extrude): invalid parameters for `Extrude`: `distance` must be a number or an expression |
|
||||
| 04-revolve-vase | not yet | recipe: sketch entity type `arc_three_point` is not supported yet |
|
||||
| 05-taper-extrude | FAIL | volume_mm3: got 48000.0 want 61814.82596; area_mm2: got 8000.0 want 9676.91517 |
|
||||
| 06-symmetric-extrude | FAIL | volume_mm3: got 15000.0 want 30000.0; area_mm2: got 4100.0 want 6200.0 |
|
||||
| 07-fillet-all-edges | FAIL | step 8 (FusionFilletEdgesCommand): not supported yet: the faces at the edge ends must be planar |
|
||||
| 08-chamfer | FAIL | step 8 (FusionChamferCommand): not supported yet: the faces at the edge ends must be perpendicular to the edge |
|
||||
| 09-shell | not yet | recipe: feature op `shell` is not supported yet |
|
||||
| 10-rect-pattern-holes | not yet | recipe: feature op `rectangular_pattern` is not supported yet |
|
||||
| 11-circular-pattern-flange | not yet | recipe: feature op `circular_pattern` is not supported yet |
|
||||
| 12-mirror-feature | not yet | recipe: feature op `mirror` is not supported yet |
|
||||
| 13-combine-join | not yet | recipe: feature op `combine` is not supported yet |
|
||||
| 14-combine-cut | not yet | recipe: sketch entity type `arc_three_point` is not supported yet |
|
||||
| 15-combine-intersect | not yet | recipe: sketch entity type `arc_three_point` is not supported yet |
|
||||
| 16-sweep | not yet | recipe: sketch entity type `arc_three_point` is not supported yet |
|
||||
| 17-loft | not yet | recipe: feature op `construction_plane` is not supported yet |
|
||||
| 18-hole-features | not yet | recipe: feature op `hole` is not supported yet |
|
||||
| 19-l-bracket-constrained | FAIL | step 8 (ConstraintHorizontalVertical): invalid parameters for `ConstraintHorizontalVertical`: `line` must be a curve id |
|
||||
| 20-slot-constrained | not yet | recipe: sketch entity type `arc_center_start_sweep` is not supported yet |
|
||||
| 21-draft | not yet | recipe: feature op `draft` is not supported yet |
|
||||
| 22-split-body | not yet | recipe: feature op `construction_plane` is not supported yet |
|
||||
| 23-bracket-multifeature | not yet | recipe: feature op `construction_plane` is not supported yet |
|
||||
| 24-user-parameters | FAIL | step 11 (ConstraintCoincident): invalid parameters for `ConstraintCoincident`: `a` must be a point reference |
|
||||
| 25-sketch-triangle | FAIL | step 5 (ConstraintCoincident): invalid parameters for `ConstraintCoincident`: `a` must be a point reference |
|
||||
| 26-sketch-belt | not yet | recipe: constraint `horizontal_points` is not supported yet |
|
||||
| 27-sketch-trapezoid | FAIL | step 9 (ConstraintHorizontalVertical): invalid parameters for `ConstraintHorizontalVertical`: `line` must be a curve id |
|
||||
| 28-blind-pocket-fillets | FAIL | step 15 (FusionFilletEdgesCommand): not supported yet: the blend is larger than the neighbouring faces |
|
||||
| 29-two-sided-and-partial-revolve | FAIL | step 7 (Extrude): invalid parameters for `Extrude`: `distance` must be a number or an expression |
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@@ -0,0 +1,14 @@
|
||||
{"commands": [
|
||||
{"command": "ChangeParameterCommand", "params": {"name": "width", "expression": "60 mm"}},
|
||||
{"command": "ChangeParameterCommand", "params": {"name": "thickness", "expression": "6 mm"}},
|
||||
{"command": "SketchCreate", "params": {"plane": "XZ", "name": "Profile"}},
|
||||
{"command": "DrawPolyline", "params": {"points": [[0, 0], [40, 0], [40, 6], [6, 6], [6, 30], [0, 30]], "closed": true, "ids": ["a", "b", "c", "d", "e", "f"]}},
|
||||
{"command": "SketchStop", "params": {}},
|
||||
{"command": "Extrude", "params": {"distance": "width", "direction": "negative", "body_name": "Bracket"}},
|
||||
{"command": "FusionFilletEdgesCommand", "params": {"edges": [[40, 30, 6]], "radius": 2}},
|
||||
{"command": "SketchCreate", "params": {"plane": "XY", "name": "Holes"}},
|
||||
{"command": "CircleCenterRadius", "params": {"center": [25, 15], "diameter": 8}},
|
||||
{"command": "CircleCenterRadius", "params": {"center": [25, 45], "diameter": 8}},
|
||||
{"command": "SketchStop", "params": {}},
|
||||
{"command": "Extrude", "params": {"distance": "thickness", "operation": "cut"}}
|
||||
]}
|
||||
Reference in new issue
Block a user