* Windows: resize border from the first frame, DPI-correct window moves (#1381) - The egui resize zones were laid out after the start page's early return, so a launch without a design had no resize edges at all. They now run on every page. - Windows: the main window's procedure answers WM_NCHITTEST with the resize edges and corners, Windows' own border width at the window's DPI (8 px at 100 %), so the OS shows its resize cursors and runs its own resize (snap included) from the first message; no egui zones there. - Windows: WM_GETDPISCALEDSIZE returns the size winit then applies (same logical size), so the rect the OS suggests while the title bar is dragged onto a monitor with another scale is the rect the window gets. - Zone sizes and hit test shared in titlebar.rs and unit-tested; Windows CI checks the hit test right after launch and a real edge drag. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Windows resize smoke: find the main window by its title Co-Authored-By: Claude Opus 5.5 <[email protected]> * Windows resize smoke: probe the maximized window at the screen's edge Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
9.6 KiB
SolidCraft — instructions for agents
SolidCraft is a clean-room, open-source, pure-Rust parametric 3D CAD application: sketches with a constraint solver, a parametric timeline of features, a B-rep kernel, and a desktop UI that agents can drive. Projects published by storytold can serve as references for implementation conventions. Any code adapted from other projects (MIT OR Apache-2.0) is noted in ATTRIBUTION.md.
Product name
SolidCraft everywhere: crates solidcraft-*, binaries solidcraft and solidcraft-cli,
.solidcraft designs, the solidcraft/N format tag, SOLIDCRAFT_* environment variables,
settings and recovery folders, the MCP server name, docs, CI and packaging. The old name
survives only in the explicit compatibility shims listed in docs/compatibility.md; don't add
new uses of it anywhere else. Public docs/web/Flatpak deployments use project Pages
/solidcraft/; do not add permanent old-name Pages aliases.
Start every session here
- Read
plan/STATUS.md(current milestone, next task), then the task inplan/execution-plan.mdand the relevantplan/architecture.mdsection. - Kernel and library decisions:
plan/adr/0001-geometry-kernel.md(what we may depend on, what is rejected for licence reasons). - 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 SolidCraft 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!; nounsafe(unsafe_code = "forbid"). The three exceptions, in the app crate (which denies it instead), have no safe API: two functions inapps/solidcraft/src/open_documents.rs(macOS hands Finder files only to an Objective-C method), the Windows-onlyapps/solidcraft/src/native_crash.rs(the exception filter that records crashes inside native code such as graphics drivers) and the Windows-onlyapps/solidcraft/src/native_frame.rs(the window procedure that answers the resize-border hit test of the window without OS decorations). - 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
truckgoes throughsolidcraft_kernel::guard, which turns a panic intoKernelError::Internal. - Last-resort guard:
Session::executeruns every command undercatch_unwind; an escaped panic restores the design and reportsEngineError::Internal. - Crash reports: the desktop app writes every panic and every unclean exit to a local crash folder,
with the design and the commands that reproduce it (
solidcraft_engine::crash, docs/crash-reports.md). When someone says the app crashed, look there first:solidcraft-cli crashes,crashes show <id>,crashes replay <id>(or thediagnostics.crash_reportscommand / MCPcrash_reportstool). - Prove it: every crash fix lands with a regression test (see
hostile_params_never_panic); a crash report'sdesign.solidcraft+replay.jsonis the test's starting point. - Every production crate root carries
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)].
Non-negotiables
- Independent. SolidCraft is independent. Behaviour is designed from public documentation, general CAD conventions and user feedback. Reference tests use analytic values and open-source tools. Never copy another product's code, icons, artwork, help text, tooltips, templates or materials. File formats come from public specifications.
- No commercial CAD products. Agents must not drive, script, automate or extract data from commercial CAD products (Fusion, SolidWorks, Onshape, …) for this project: no test data, measurements, command lists, ids or files produced with them.
- Never read, copy or link GPL/LGPL/AGPL code: OpenCASCADE, FreeCAD (incl. planegcs),
SolveSpace, CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (
tools/freecad-oracle/runs FreeCAD as a separate program through its public scripting API to compute reference values; nothing from FreeCAD is linked, vendored or shipped.) The sketch solver and the blend operations are our own. - Assets — absolutely essential. SolidCraft contains no iconography, images, fonts or
artwork from commercial CAD products — 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 assetsenforces it). Screenshots of commercial CAD 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 = our own dotted, lower-case id<area>.<thing>[.<variant>]such assolid.extrudeorsketch.rectangle.two_point, never another product's command id; label; toolbar tab and panel; icon; shortcut; params doc;enabled; JSONrun) + tests. The toolbar, dialogs, sketch tools, palette, scripts, CLI and control channel all reach the same commands. - Programmatic calls never open dialogs.
engine.executeruns the JSON form; only toolbar clicks (ui.start) start interactive tools and dialogs, which then run commands. - Layering is enforced by
cargo xtask layers: L0geom→ L1sketch,kernel,render→ L2doc→ L3io→ L4engine→ L5ui-egui→ apps. Nothing below L5 depends on egui/eframe/winit/wgpu/rfd. The UI crate is swappable. Onlycrates/kernelmay usetruck. - The UI is thin: panels read engine state and act through
app.run(id, params)/app.start(id). Colours come fromtheme::Tokens. - Rust only. Units are millimetres and radians internally; Z is up. The one exception is
JavaScript the browser requires: the service worker
apps/solidcraft-web/sw.js(browsers only run service workers as JavaScript) and the small inline scripts inapps/solidcraft-web/index.html. Keep them minimal;cargo xtask web-offline-testcovers the service worker. - Quality gates before every commit:
cargo xtask ci(fmt, clippy -D warnings, tests, assets, layers). Commit after every feature arc that builds. - Publishing:
originis github.com/bherbruck/solidcraft. Changes land through pull requests: push a branch, open a PR, and let GitHub CI run. Maintainers (and agents working for them) may merge their own PR as soon as CI is green (gh pr merge --squash); a trivial fix (docs, typos) may be merged right away. Keep each PR to one topic, rebase or mergemaininto it when it conflicts, and never force-pushmain. Never commitplan/, build dirs (target*/) or generated reference data; checkgit ls-filesbefore pushing. - Never break wasm: everything below the apps must build for
wasm32-unknown-unknown(cargo xtask wasm, part ofcargo xtask ci).
Application releases
Development pushes are not application releases. Follow docs/releasing.md when asked to
prepare or ship a release: choose the version from the actual changes, update Cargo.toml and
Cargo.lock, pass the quality gates, advance release without force-pushing, and verify the
resulting draft and its artifacts. When shipping is authorized, publish that verified draft
and confirm its tag and downstream deployment. Do not auto-release every push to main, infer
version bumps solely from commit prefixes, overwrite published versions, or push release tags
before the draft is verified.
Running and looking at the app
cargo run --release -p solidcraft -- --sample --control PORT(sample design + control channel). Pick a free port. Without a display, run it underXvfb :99withDISPLAY=:99.- Drive it with JSON lines on
127.0.0.1:PORT(seedocs/control-protocol.md). The first request on a connection carries the launch's token as"token": read it from~/.local/share/solidcraft/control/PORT.token, or start the app withSOLIDCRAFT_CONTROL_TOKEN=$(openssl rand -hex 32)and send that.{"id":1,"method":"engine.execute","params":{"command":"solid.extrude","params":{"distance":20}}}{"id":2,"method":"ui.start","params":{"command":"sketch.create"}}thenui.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.renderorsolidcraft-cli snapshot. - Headless:
solidcraft-cli run script.json --out part.step,solidcraft-cli eval design.solidcraft,solidcraft-cli snapshot script.json --out shot.png,solidcraft-cli commands. - Reference tests:
cargo xtask oraclereplaystests/oracle/*/recipe.jsonand compares with each case'sexpected.json(analytic or FreeCAD values; writesdocs/oracle.md). Expected values never come from a commercial CAD product. - Build with
CARGO_TARGET_DIR=<repo>/target. Windows:cargo xwin build --release --target x86_64-pc-windows-msvc -p solidcraft.
Roadmap
ROADMAP.md (committed) tracks status, milestones and estimates. Update it whenever a
milestone task lands. cargo xtask features regenerates docs/features.md (SolidCraft's
commands by area, from the registry) when commands are added or renamed.