Rename the project to FieldCraft

Crates fieldcraft-*, binaries fieldcraft and fieldcraft-cli, the .fieldcraft file (format tag
fieldcraft/1, manifest fieldcraft.json), FIELDCRAFT_* environment variables, the MCP server
name, egui widget ids (fc_*), the app icon document FieldCraft.icon and its generated family,
docs and licences. No compatibility shim: no files of the earlier name exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-13 23:51:40 -04:00
1 parent 9bc4e1b182
commit d5bd74570f
268 files changed
+1666 -1666

No files matched your search

+4 -4
View File
@@ -1,4 +1,4 @@
//! `corpus [--part NAME] [--no-write]`: see [`modelcraft_testkit::runner`]; run it as
//! `corpus [--part NAME] [--no-write]`: see [`fieldcraft_testkit::runner`]; run it as
//! `cargo xtask corpus`.
//!
//! `corpus --part NAME --design PATH` writes that part's `.solidcraft` design to `PATH` instead
@@ -31,7 +31,7 @@ fn main() -> ExitCode {
let result = match (design, only) {
(Some(path), Some(name)) => write_design(name, Path::new(path)),
(Some(_), None) => Err(format!("--design needs --part\n{USAGE}")),
(None, _) => modelcraft_testkit::runner::run(&modelcraft_testkit::corpus::workspace_root(), only, write),
(None, _) => fieldcraft_testkit::runner::run(&fieldcraft_testkit::corpus::workspace_root(), only, write),
};
match result {
Ok(()) => ExitCode::SUCCESS,
@@ -44,9 +44,9 @@ fn main() -> ExitCode {
/// Write the design of the corpus part `name` to `path`.
fn write_design(name: &str, path: &Path) -> Result<(), String> {
let parts = modelcraft_testkit::corpus::parts().map_err(|e| e.to_string())?;
let parts = fieldcraft_testkit::corpus::parts().map_err(|e| e.to_string())?;
let part = parts.iter().find(|p| p.name == name).ok_or_else(|| format!("no corpus part named `{name}`"))?;
let bytes = modelcraft_testkit::corpus::design_bytes(part).map_err(|e| e.to_string())?;
let bytes = fieldcraft_testkit::corpus::design_bytes(part).map_err(|e| e.to_string())?;
std::fs::write(path, bytes).map_err(|e| format!("{}: {e}", path.display()))?;
eprintln!("corpus: wrote {} ({name})", path.display());
Ok(())
+3 -3
View File
@@ -1,11 +1,11 @@
//! `oracle [--case NAME]... [--bless NAME|all]... [--quick] [--no-write]`: see
//! [`modelcraft_testkit::oracle`]; run it as `cargo xtask oracle`.
//! [`fieldcraft_testkit::oracle`]; run it as `cargo xtask oracle`.
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
#![forbid(unsafe_code)]
use std::process::ExitCode;
use modelcraft_testkit::oracle::{Options, run};
use fieldcraft_testkit::oracle::{Options, run};
const USAGE: &str = "usage: oracle [--case NAME]... [--bless NAME|all]... [--quick] [--no-write]";
@@ -33,7 +33,7 @@ fn main() -> ExitCode {
return ExitCode::FAILURE;
}
}
match run(&modelcraft_testkit::corpus::workspace_root(), &options) {
match run(&fieldcraft_testkit::corpus::workspace_root(), &options) {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("error: {e}");
+5 -5
View File
@@ -5,14 +5,14 @@
//! `solidcraft-cli run` takes) with a `corpus` object beside its `commands` giving the
//! categories it stresses and, when it has one, its closed-form volume; `README.md` beside it is
//! one line on what it stresses. The script runs in SolidCraft's engine, the design is saved and
//! opened again through [`modelcraft_geometry::open_design`], the path a person's design takes.
//! opened again through [`fieldcraft_geometry::open_design`], the path a person's design takes.
//! - **Analytic shapes** ([`Analytic`]): sphere, torus, cylinder, thick-walled pipe and a plate
//! with a hole, built in code with their exact volume, the classic solver verification
//! geometries.
use std::path::{Path, PathBuf};
use modelcraft_geometry::{Design, open_design, sample, script_design};
use fieldcraft_geometry::{Design, open_design, sample, script_design};
use serde_json::{Value, json};
#[derive(Debug, thiserror::Error)]
@@ -22,7 +22,7 @@ pub enum Error {
#[error("{part}: {message}")]
Part { part: String, message: String },
#[error("{part}: {source}")]
Geometry { part: String, source: modelcraft_geometry::Error },
Geometry { part: String, source: fieldcraft_geometry::Error },
}
pub type Result<T> = std::result::Result<T, Error>;
@@ -107,7 +107,7 @@ impl Analytic {
}
/// The design as `.solidcraft` bytes.
pub fn design(&self) -> modelcraft_geometry::Result<Vec<u8>> {
pub fn design(&self) -> fieldcraft_geometry::Result<Vec<u8>> {
let script = match *self {
Analytic::Sphere { radius } => json!([{"command": "solid.sphere", "params": {"radius": radius, "body_name": "Sphere"}}]),
Analytic::Torus { major, minor } => json!([{"command": "solid.torus", "params": {"major": major, "minor": minor, "body_name": "Torus"}}]),
@@ -300,7 +300,7 @@ mod tests {
#[test]
fn hostile_recipes_are_an_error() {
let dir = std::env::temp_dir().join(format!("modelcraft-corpus-test-{}", std::process::id()));
let dir = std::env::temp_dir().join(format!("fieldcraft-corpus-test-{}", std::process::id()));
let part = dir.join("bad");
std::fs::create_dir_all(&part).unwrap();
std::fs::write(part.join("README.md"), "A bad part.\n").unwrap();
+7 -7
View File
@@ -5,7 +5,7 @@
//! A case directory holds:
//! - `expected.json`: the case's kind (theory, experiment, benchmark), source, status and its
//! quantities: how each is measured, the reference value, the tolerance and the reason for it;
//! - `recipe.json`: the model as ModelCraft commands (a JSON array of `{"command", "params"}`,
//! - `recipe.json`: the model as FieldCraft commands (a JSON array of `{"command", "params"}`,
//! each step optionally with an `id` that measures can read its output by); absent while a
//! case is pending;
//! - `design.json` (optional): a SolidCraft script that builds the geometry, opened first;
@@ -21,7 +21,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Instant;
use modelcraft_engine::Session;
use fieldcraft_engine::Session;
use serde_json::{Value, json};
/// Fixture band: a result may move by this fraction of its size (and a thousandth of the
@@ -232,8 +232,8 @@ pub fn run_case(dir: &Path, expected: &Expected) -> Result<Vec<Result<f64, Strin
let design = dir.join("design.json");
if design.is_file() {
let script = crate::corpus::read(&design).map_err(|e| e.to_string())?;
let bytes = modelcraft_geometry::script_design(&script).map_err(|e| format!("design.json: {e}"))?;
let opened = modelcraft_geometry::open_design(&bytes).map_err(|e| format!("design.json: {e}"))?;
let bytes = fieldcraft_geometry::script_design(&script).map_err(|e| format!("design.json: {e}"))?;
let opened = fieldcraft_geometry::open_design(&bytes).map_err(|e| format!("design.json: {e}"))?;
if let Some(e) = opened.errors.first() {
return Err(format!("design.json: feature {}: {}", e.feature, e.message));
}
@@ -402,7 +402,7 @@ pub fn run(root: &Path, options: &Options) -> Result<(), String> {
}
}
let text = serde_json::to_string_pretty(&json!({
"note": "ModelCraft's accepted results for this case, written by `cargo xtask oracle --bless`. A result outside its band fails CI.",
"note": "FieldCraft's accepted results for this case, written by `cargo xtask oracle --bless`. A result outside its band fails CI.",
"values": values,
}))
.map_err(|e| e.to_string())?;
@@ -565,7 +565,7 @@ pub fn report(cases: &[(String, Expected)], rows: &[Row]) -> String {
md,
"# Verification and validation oracle\n\n\
Generated by `cargo xtask oracle` from [`tests/oracle/`](../tests/oracle/); the policy is [verification.md](verification.md). \
Every case is our own model, built with ModelCraft commands from the problem's published description, and compared with \
Every case is our own model, built with FieldCraft commands from the problem's published description, and compared with \
the reference value its `expected.json` cites, within the stated tolerance and for the stated reason. Accepted results are \
frozen in each case's `fixture.json`: a later change that moves one beyond its band (10⁻⁹ of its size) fails CI even while \
the reference still passes. No reference value was produced with a commercial product.\n\n\
@@ -589,7 +589,7 @@ benchmark, {} experiment; {} pending cases wait for capabilities still being bui
};
let _ = write!(
md,
"## {heading}\n\n| Case | Quantity | Reference | ModelCraft | Error | Tolerance | Result | Fixture |\n|---|---|---|---|---|---|---|---|\n"
"## {heading}\n\n| Case | Quantity | Reference | FieldCraft | Error | Tolerance | Result | Fixture |\n|---|---|---|---|---|---|---|---|\n"
);
for (case, _) in &in_kind {
for r in rows.iter().filter(|r| &r.case == case) {
+8 -8
View File
@@ -13,11 +13,11 @@ use std::path::Path;
use std::time::Instant;
use crate::corpus::{self, CATEGORIES, Part};
use modelcraft_geometry::{Design, FaceSurface, Measure, SurfaceMesh};
use modelcraft_mesh::cdt::{CdtOptions, tetrahedralize};
use modelcraft_mesh::hex::{HexOptions, Surface, hex_mesh};
use modelcraft_mesh::size::UniformSize;
use modelcraft_mesh::surface::{BoundarySurface, SurfaceOptions};
use fieldcraft_geometry::{Design, FaceSurface, Measure, SurfaceMesh};
use fieldcraft_mesh::cdt::{CdtOptions, tetrahedralize};
use fieldcraft_mesh::hex::{HexOptions, Surface, hex_mesh};
use fieldcraft_mesh::size::UniformSize;
use fieldcraft_mesh::surface::{BoundarySurface, SurfaceOptions};
pub const FILE: &str = "docs/meshing/corpus.md";
/// Chordal tolerance of the boundary surface, relative to the part's bounding-box diagonal.
@@ -64,7 +64,7 @@ impl Stage for SurfaceVolume {
}
}
/// Boundary surface preparation (`modelcraft_mesh::surface`): welded, closed, manifold, outward
/// Boundary surface preparation (`fieldcraft_mesh::surface`): welded, closed, manifold, outward
/// and free of self-intersections, or the first defects found, which keep the part from being
/// volume meshed.
struct BoundaryCheck;
@@ -89,7 +89,7 @@ impl Stage for BoundaryCheck {
}
}
/// The constrained Delaunay tetrahedralization (`modelcraft_mesh::cdt`) of each body's boundary:
/// The constrained Delaunay tetrahedralization (`fieldcraft_mesh::cdt`) of each body's boundary:
/// tetrahedra, Steiner points on boundary edges, cavities refilled by gift-wrapping, and the
/// validity gate on the rounded mesh (every tetrahedron positive, volume equal to the boundary's).
struct TetCdt;
@@ -121,7 +121,7 @@ const HEX_RELATIVE_SIZE: f64 = 1.0 / 25.0;
/// Characters of a "not meshed" reason kept in the table.
const REASON_CHARS: usize = 240;
/// Structured all-hex meshing (`modelcraft_mesh::hex`): the method that meshed each body, the
/// Structured all-hex meshing (`fieldcraft_mesh::hex`): the method that meshed each body, the
/// element count and the smallest scaled Jacobian of the hex8 mesh and of the hex20 mesh (mid-edge
/// nodes on the geometry), or why no structured method fits.
struct StructuredHex;