diff --git a/AGENTS.md b/AGENTS.md
index f611856..96ec450 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -58,9 +58,14 @@ People trust ModelCraft with their models; a crash loses their work. **This outr
sources. Permissively licensed code (MIT, BSD, Apache-2.0, MPL-2.0) may be read for reference;
anything adapted is noted in ATTRIBUTION.md with its licence.
- **Assets — absolutely essential.** ModelCraft contains **no iconography, images, fonts or
- artwork from commercial CAE products — ever.** Icons are drawn in code. Any file asset must be
+ artwork from commercial CAE products — ever.** Icons are original artwork made with VectorCraft:
+ commit the editable `.vectorcraft` source beside the exported SVG/PNG. Any file asset must be
original or openly licensed and **must have a row in ATTRIBUTION.md** (`cargo xtask assets`
enforces it). Screenshots of commercial software are never committed.
+- **Test geometry is our own.** Meshing and solver test parts are built with SolidCraft and
+ committed as recipes (scripts or designs) that regenerate them; analytic shapes are generated in
+ code. No public CAD datasets (ABC, MAMBO, Thingi10K, GrabCAD) and nothing made in a commercial
+ CAD or CAE product.
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
(`CommandSpec`: our own dotted, lower-case id `.[.]` such as
`mesh.node.add` or `mesh.tet.generate`, never another product's keyword; label; params doc;
@@ -78,8 +83,10 @@ People trust ModelCraft with their models; a crash loses their work. **This outr
MPa); geometry from SolidCraft is in millimetres. Z is up.
- **Rust only.** **Never break wasm**: everything below the apps builds for
`wasm32-unknown-unknown` (`cargo xtask wasm`, part of `cargo xtask ci`).
-- **Quality gates** before every commit: `cargo xtask ci` (fmt, assets, licences, layers, clippy
- -D warnings, tests, wasm).
+- **Quality gates:** GitHub CI runs `cargo xtask ci` (fmt, assets, licences, layers, clippy -D
+ warnings, tests, wasm) on every PR; don't run the full gate locally. Before pushing: `cargo fmt
+ --all`, `cargo check` the touched crates, and run the tests you added or changed. Commit after
+ each working step (a layer that compiles with its tests passing), not one big commit per PR.
- **Publishing**: `origin` is github.com/jyviko/modelcraft. Changes land through pull requests:
branch, push, open a PR, let CI run, then `gh pr merge --squash` when green. Rebase onto `main`
(never merge `main` into a branch); never force-push `main`. Never commit `plan/`,
diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md
index 33e88a3..7402518 100644
--- a/ATTRIBUTION.md
+++ b/ATTRIBUTION.md
@@ -7,7 +7,8 @@ asset file is missing from this table.
**Policy (mandatory):** ModelCraft contains **no iconography, images, artwork, fonts, templates,
example decks or help text from commercial CAE products.** Every asset is original work by
ModelCraft contributors or third-party material under an open licence. Screenshots of commercial
-software are never committed.
+software are never committed. Icons are made with VectorCraft; each icon's `.vectorcraft` source
+is committed and listed here with its exports.
## Files
diff --git a/docs/adr/0001-libraries.md b/docs/adr/0001-libraries.md
index 7a4fda7..9a44ec3 100644
--- a/docs/adr/0001-libraries.md
+++ b/docs/adr/0001-libraries.md
@@ -57,8 +57,9 @@ sources is in `docs/meshing/literature.md`.
**Test geometry** follows the same rule as test data: nothing produced with a commercial CAD or
CAE product. That excludes ABC (Onshape), MAMBO (files from commercial translators) and the HexMe
models that come from ABC, GrabCAD or Siemens NX; HexMe's Gmsh-made models are allowed (CC-BY-4.0).
-Thingi10K (per-model Creative Commons licences, authoring tool unrecorded) is pending an owner
-decision. The default corpus is generated: SolidCraft-built parts and analytic shapes.
+Thingi10K is not used either (owner decision 2026-10-13: authoring tools unrecorded). **The test
+corpus is our own:** parts built with SolidCraft (scripts or designs authored in SolidCraft,
+committed as their recipes so the geometry is regenerated, not stored) and analytic shapes.
**Commercial products** (Abaqus, Nastran, LS-DYNA, LS-PrePost, HyperMesh, ANSA, Femap, Patran,
ANSYS) are never run, scripted or used as a source of data. Deck formats come from the vendors'
diff --git a/xtask/src/assets.rs b/xtask/src/assets.rs
index 700af3b..b446d1d 100644
--- a/xtask/src/assets.rs
+++ b/xtask/src/assets.rs
@@ -3,8 +3,29 @@
use std::path::Path;
-const ASSET_EXT: &[&str] =
- &["png", "jpg", "jpeg", "svg", "ico", "icns", "ttf", "otf", "woff", "woff2", "gif", "bmp", "webp", "wav", "mp3", "stl", "step", "stp", "obj"];
+const ASSET_EXT: &[&str] = &[
+ "png",
+ "jpg",
+ "jpeg",
+ "svg",
+ "ico",
+ "icns",
+ "ttf",
+ "otf",
+ "woff",
+ "woff2",
+ "gif",
+ "bmp",
+ "webp",
+ "wav",
+ "mp3",
+ "stl",
+ "step",
+ "stp",
+ "obj",
+ "vectorcraft",
+ "solidcraft",
+];
const SKIP_DIRS: &[&str] = &["target", ".git", "plan", "dist"];
fn walk(dir: &Path, root: &Path, out: &mut Vec) {