forked from 1b-agent/fieldcraft-upstream
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 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
9bc4e1b182
commit
d5bd74570f
268 files changed
+1666
-1666
No files matched your search
+15
-15
@@ -1,4 +1,4 @@
|
||||
//! `cargo xtask app-icon`: draw ModelCraft's application icon family with VectorCraft.
|
||||
//! `cargo xtask app-icon`: draw FieldCraft's application icon family with VectorCraft.
|
||||
//!
|
||||
//! The mark is an L-shaped bracket with a bolt hole, drawn in isometric view and covered by a
|
||||
//! structured hexahedral mesh (an O-grid around the hole). The faces are separated by
|
||||
@@ -12,9 +12,9 @@
|
||||
//! - `icon-small.vectorcraft`, `icon-small.svg`, `icon-small.png`: simplified artwork (no mesh,
|
||||
//! no floor grid, faces meeting edge to edge so the tones alone separate them) for 16–32 px.
|
||||
//! - `icon.iconset/` (sips), `icon.icns` (iconutil) and `icon.ico` (ImageMagick).
|
||||
//! - `ModelCraft.icon/`: an Icon Composer document with separate floor-grid (Default and Dark),
|
||||
//! - `FieldCraft.icon/`: an Icon Composer document with separate floor-grid (Default and Dark),
|
||||
//! part and mesh layers; their editable sources are `layers/*.vectorcraft`.
|
||||
//! - `Assets.car`: Apple's actool compilation of `ModelCraft.icon`, when Xcode 26 or later is
|
||||
//! - `Assets.car`: Apple's actool compilation of `FieldCraft.icon`, when Xcode 26 or later is
|
||||
//! installed (otherwise the step is skipped with a note and the checked-in catalog stays).
|
||||
//!
|
||||
//! macOS only (sips, iconutil); ImageMagick (`magick`) writes the Windows icon.
|
||||
@@ -498,10 +498,10 @@ fn composite(detail: Detail, appearance: Appearance) -> Result<Doc, String> {
|
||||
layers.push(mesh_layer()?);
|
||||
}
|
||||
let title = match (detail, appearance) {
|
||||
(Detail::Full, Appearance::Light) => "ModelCraft application icon",
|
||||
(Detail::Full, Appearance::Dark) => "ModelCraft application icon (dark preview)",
|
||||
(Detail::Small, Appearance::Light) => "ModelCraft application icon, small sizes",
|
||||
(Detail::Small, Appearance::Dark) => "ModelCraft application icon, small sizes (dark preview)",
|
||||
(Detail::Full, Appearance::Light) => "FieldCraft application icon",
|
||||
(Detail::Full, Appearance::Dark) => "FieldCraft application icon (dark preview)",
|
||||
(Detail::Small, Appearance::Light) => "FieldCraft application icon, small sizes",
|
||||
(Detail::Small, Appearance::Dark) => "FieldCraft application icon, small sizes (dark preview)",
|
||||
};
|
||||
Ok(Doc { title, layers })
|
||||
}
|
||||
@@ -617,7 +617,7 @@ fn icon_json() -> Value {
|
||||
pub fn run(root: &Path) -> Result<(), String> {
|
||||
let dir = root.join("assets/app-icon");
|
||||
let layers = dir.join("layers");
|
||||
let bundle = dir.join("ModelCraft.icon");
|
||||
let bundle = dir.join("FieldCraft.icon");
|
||||
let assets = bundle.join("Assets");
|
||||
let iconset = dir.join("icon.iconset");
|
||||
let target = std::env::var_os("CARGO_TARGET_DIR").map_or_else(|| root.join("target"), PathBuf::from);
|
||||
@@ -639,10 +639,10 @@ pub fn run(root: &Path) -> Result<(), String> {
|
||||
// Icon Composer layers: the system supplies the backdrop.
|
||||
let single = |title, layer| Doc { title, layers: vec![layer] };
|
||||
let layer_docs = [
|
||||
("01-floor", single("ModelCraft icon floor grid", floor_layer(Appearance::Light))),
|
||||
("01-floor-dark", single("ModelCraft icon floor grid (Dark)", floor_layer(Appearance::Dark))),
|
||||
("02-part", single("ModelCraft icon part", part_layer(Detail::Full)?)),
|
||||
("03-mesh", single("ModelCraft icon mesh", mesh_layer()?)),
|
||||
("01-floor", single("FieldCraft icon floor grid", floor_layer(Appearance::Light))),
|
||||
("01-floor-dark", single("FieldCraft icon floor grid (Dark)", floor_layer(Appearance::Dark))),
|
||||
("02-part", single("FieldCraft icon part", part_layer(Detail::Full)?)),
|
||||
("03-mesh", single("FieldCraft icon mesh", mesh_layer()?)),
|
||||
];
|
||||
for (name, doc) in &layer_docs {
|
||||
vectorcraft(doc, &layers.join(format!("{name}.vectorcraft")), &[assets.join(format!("{name}.svg"))])?;
|
||||
@@ -682,7 +682,7 @@ pub fn run(root: &Path) -> Result<(), String> {
|
||||
"--minimum-deployment-target",
|
||||
"11.0",
|
||||
"--app-icon",
|
||||
"ModelCraft",
|
||||
"FieldCraft",
|
||||
"--output-partial-info-plist",
|
||||
path_str(&partial)?,
|
||||
"--output-format",
|
||||
@@ -692,9 +692,9 @@ pub fn run(root: &Path) -> Result<(), String> {
|
||||
match compiled {
|
||||
Ok(()) => {
|
||||
std::fs::copy(work.join("Assets.car"), dir.join("Assets.car")).map_err(|e| format!("Assets.car: {e}"))?;
|
||||
println!("app-icon: compiled ModelCraft.icon into assets/app-icon/Assets.car");
|
||||
println!("app-icon: compiled FieldCraft.icon into assets/app-icon/Assets.car");
|
||||
}
|
||||
Err(e) => println!("app-icon: note: actool could not compile ModelCraft.icon, Assets.car left as it was ({e})"),
|
||||
Err(e) => println!("app-icon: note: actool could not compile FieldCraft.icon, Assets.car left as it was ({e})"),
|
||||
}
|
||||
println!("app-icon: wrote assets/app-icon (dark previews in {})", work.display());
|
||||
Ok(())
|
||||
|
||||
+37
-37
@@ -32,7 +32,7 @@ impl Class {
|
||||
}
|
||||
}
|
||||
|
||||
/// The layering table. Names are package names without the `modelcraft-`
|
||||
/// The layering table. Names are package names without the `fieldcraft-`
|
||||
/// prefix.
|
||||
pub const TABLE: &[(&str, Class)] = &[
|
||||
// L0: the solver-neutral model.
|
||||
@@ -58,7 +58,7 @@ pub const TABLE: &[(&str, Class)] = &[
|
||||
("mcp", Class::Layer(7)),
|
||||
("testkit", Class::Testkit),
|
||||
// apps and tooling
|
||||
("modelcraft", Class::Exempt),
|
||||
("fieldcraft", Class::Exempt),
|
||||
("cli", Class::Exempt),
|
||||
("web", Class::Exempt),
|
||||
("xtask", Class::Exempt),
|
||||
@@ -92,7 +92,7 @@ pub const TESTKIT_LAYER: u8 = UI_MIN_LAYER + 1;
|
||||
const APPS_LAYER: u8 = TESTKIT_LAYER + 1;
|
||||
|
||||
pub fn short_name(pkg: &str) -> &str {
|
||||
pkg.strip_prefix("modelcraft-").unwrap_or(pkg)
|
||||
pkg.strip_prefix("fieldcraft-").unwrap_or(pkg)
|
||||
}
|
||||
|
||||
pub fn classify(pkg: &str) -> Option<Class> {
|
||||
@@ -151,13 +151,13 @@ impl std::fmt::Display for Violation {
|
||||
write!(f, "{krate}: standalone crate must not depend on workspace crate {dep}")
|
||||
}
|
||||
Violation::TestkitAsNormalDep { krate } => {
|
||||
write!(f, "{krate}: modelcraft-testkit may only be a dev-dependency")
|
||||
write!(f, "{krate}: fieldcraft-testkit may only be a dev-dependency")
|
||||
}
|
||||
Violation::UiBelowUiLayer { krate, dep, layer } => {
|
||||
write!(f, "{krate} (L{layer}) depends on UI crate `{dep}`; UI toolkits are only allowed in L{UI_MIN_LAYER}+")
|
||||
}
|
||||
Violation::SolidCraftOutsideGeometry { krate, dep } => {
|
||||
write!(f, "{krate} depends on `{dep}`; only modelcraft-{SOLIDCRAFT_GATEWAY} may use SolidCraft")
|
||||
write!(f, "{krate} depends on `{dep}`; only fieldcraft-{SOLIDCRAFT_GATEWAY} may use SolidCraft")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,92 +263,92 @@ mod tests {
|
||||
#[test]
|
||||
fn clean_downward_graph_passes() {
|
||||
let g = [
|
||||
c("modelcraft-model", &[("serde", Normal, false)]),
|
||||
c("modelcraft-doc", &[("modelcraft-model", Normal, true)]),
|
||||
c("modelcraft-engine", &[("modelcraft-doc", Normal, true), ("modelcraft-testkit", Dev, true)]),
|
||||
c("modelcraft-ui-egui", &[("modelcraft-engine", Normal, true), ("egui", Normal, false)]),
|
||||
c("modelcraft-cli", &[("modelcraft-ui-egui", Normal, true)]),
|
||||
c("fieldcraft-model", &[("serde", Normal, false)]),
|
||||
c("fieldcraft-doc", &[("fieldcraft-model", Normal, true)]),
|
||||
c("fieldcraft-engine", &[("fieldcraft-doc", Normal, true), ("fieldcraft-testkit", Dev, true)]),
|
||||
c("fieldcraft-ui-egui", &[("fieldcraft-engine", Normal, true), ("egui", Normal, false)]),
|
||||
c("fieldcraft-cli", &[("fieldcraft-ui-egui", Normal, true)]),
|
||||
];
|
||||
assert!(check(&g).is_empty(), "{:?}", check(&g));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upward_dependency_flagged() {
|
||||
let v = check(&[c("modelcraft-doc", &[("modelcraft-engine", Normal, true)])]);
|
||||
let v = check(&[c("fieldcraft-doc", &[("fieldcraft-engine", Normal, true)])]);
|
||||
assert!(matches!(v[..], [Violation::Upward { from: 4, to: 6, .. }]));
|
||||
let v = check(&[c("modelcraft-fem", &[("modelcraft-solver", Normal, true)])]);
|
||||
let v = check(&[c("fieldcraft-fem", &[("fieldcraft-solver", Normal, true)])]);
|
||||
assert!(matches!(v[..], [Violation::Upward { from: 1, to: 2, .. }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sideways_dependency_flagged() {
|
||||
let v = check(&[c("modelcraft-mesh", &[("modelcraft-fem", Normal, true)])]);
|
||||
let v = check(&[c("fieldcraft-mesh", &[("fieldcraft-fem", Normal, true)])]);
|
||||
assert!(matches!(v[..], [Violation::Upward { from: 1, to: 1, .. }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_dev_dependency_ignored() {
|
||||
assert!(check(&[c("modelcraft-doc", &[("modelcraft-doc", Dev, true)])]).is_empty());
|
||||
assert!(check(&[c("fieldcraft-doc", &[("fieldcraft-doc", Dev, true)])]).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upward_dev_dependency_flagged() {
|
||||
let v = check(&[c("modelcraft-model", &[("modelcraft-doc", Dev, true)])]);
|
||||
let v = check(&[c("fieldcraft-model", &[("fieldcraft-doc", Dev, true)])]);
|
||||
assert!(matches!(v[..], [Violation::Upward { kind: Dev, .. }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solvers_sit_above_the_kernels() {
|
||||
let g = [
|
||||
c("modelcraft-fem", &[("modelcraft-model", Normal, true)]),
|
||||
c("modelcraft-solver", &[("modelcraft-fem", Normal, true), ("modelcraft-mesh", Normal, true)]),
|
||||
c("modelcraft-engine", &[("modelcraft-solver", Normal, true)]),
|
||||
c("fieldcraft-fem", &[("fieldcraft-model", Normal, true)]),
|
||||
c("fieldcraft-solver", &[("fieldcraft-fem", Normal, true), ("fieldcraft-mesh", Normal, true)]),
|
||||
c("fieldcraft-engine", &[("fieldcraft-solver", Normal, true)]),
|
||||
];
|
||||
assert!(check(&g).is_empty(), "{:?}", check(&g));
|
||||
let v = check(&[c("modelcraft-solver", &[("modelcraft-engine", Normal, true)])]);
|
||||
let v = check(&[c("fieldcraft-solver", &[("fieldcraft-engine", Normal, true)])]);
|
||||
assert!(matches!(v[..], [Violation::Upward { from: 2, to: 6, .. }]));
|
||||
let v = check(&[c("modelcraft-engine", &[("modelcraft-cli", Normal, true)])]);
|
||||
let v = check(&[c("fieldcraft-engine", &[("fieldcraft-cli", Normal, true)])]);
|
||||
assert!(matches!(v[..], [Violation::Upward { from: 6, to: APPS_LAYER, .. }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ui_crates_below_the_ui_layer_flagged() {
|
||||
for dep in ["egui", "eframe", "winit", "egui_kittest", "rfd", "bevy_ecs", "bevy"] {
|
||||
let v = check(&[c("modelcraft-engine", &[(dep, Normal, false)])]);
|
||||
let v = check(&[c("fieldcraft-engine", &[(dep, Normal, false)])]);
|
||||
assert!(matches!(v[..], [Violation::UiBelowUiLayer { layer: 6, .. }]), "{dep}");
|
||||
let v = check(&[c("modelcraft-solver", &[(dep, Normal, false)])]);
|
||||
let v = check(&[c("fieldcraft-solver", &[(dep, Normal, false)])]);
|
||||
assert!(matches!(v[..], [Violation::UiBelowUiLayer { layer: 2, .. }]), "{dep}");
|
||||
}
|
||||
assert!(check(&[c("modelcraft-engine", &[("egui_extras_not", Normal, false)])]).is_empty());
|
||||
assert!(check(&[c("modelcraft-ui-egui", &[("winit", Normal, false)])]).is_empty());
|
||||
assert!(check(&[c("fieldcraft-engine", &[("egui_extras_not", Normal, false)])]).is_empty());
|
||||
assert!(check(&[c("fieldcraft-ui-egui", &[("winit", Normal, false)])]).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_geometry_uses_solidcraft() {
|
||||
assert!(check(&[c("modelcraft-geometry", &[("solidcraft-kernel", Normal, false)])]).is_empty());
|
||||
let v = check(&[c("modelcraft-mesh", &[("solidcraft-geom", Normal, false)])]);
|
||||
assert!(check(&[c("fieldcraft-geometry", &[("solidcraft-kernel", Normal, false)])]).is_empty());
|
||||
let v = check(&[c("fieldcraft-mesh", &[("solidcraft-geom", Normal, false)])]);
|
||||
assert!(matches!(v[..], [Violation::SolidCraftOutsideGeometry { .. }]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unregistered_crate_is_error() {
|
||||
let v = check(&[c("modelcraft-mystery", &[])]);
|
||||
assert!(matches!(&v[..], [Violation::Unregistered { krate }] if krate == "modelcraft-mystery"));
|
||||
let v = check(&[c("fieldcraft-mystery", &[])]);
|
||||
assert!(matches!(&v[..], [Violation::Unregistered { krate }] if krate == "fieldcraft-mystery"));
|
||||
assert!(v[0].to_string().contains("register"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testkit_only_as_dev_dependency() {
|
||||
let v = check(&[c("modelcraft-doc", &[("modelcraft-testkit", Normal, true)])]);
|
||||
let v = check(&[c("fieldcraft-doc", &[("fieldcraft-testkit", Normal, true)])]);
|
||||
assert!(matches!(v[..], [Violation::TestkitAsNormalDep { .. }]));
|
||||
assert!(check(&[c("modelcraft-doc", &[("modelcraft-testkit", Dev, true)])]).is_empty());
|
||||
assert!(check(&[c("modelcraft-testkit", &[("modelcraft-engine", Normal, true)])]).is_empty());
|
||||
assert!(check(&[c("fieldcraft-doc", &[("fieldcraft-testkit", Dev, true)])]).is_empty());
|
||||
assert!(check(&[c("fieldcraft-testkit", &[("fieldcraft-engine", Normal, true)])]).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apps_and_xtask_exempt() {
|
||||
for app in ["modelcraft", "modelcraft-cli", "xtask"] {
|
||||
assert!(check(&[c(app, &[("egui", Normal, false), ("modelcraft-ui-egui", Normal, true)])]).is_empty());
|
||||
for app in ["fieldcraft", "fieldcraft-cli", "xtask"] {
|
||||
assert!(check(&[c(app, &[("egui", Normal, false), ("fieldcraft-ui-egui", Normal, true)])]).is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,17 +356,17 @@ mod tests {
|
||||
fn metadata_parsing() {
|
||||
let meta: Value = serde_json::from_str(
|
||||
r#"{"packages":[
|
||||
{"name":"modelcraft-doc","dependencies":[
|
||||
{"name":"modelcraft-model","kind":null,"path":"/x/crates/model"},
|
||||
{"name":"fieldcraft-doc","dependencies":[
|
||||
{"name":"fieldcraft-model","kind":null,"path":"/x/crates/model"},
|
||||
{"name":"serde","kind":null},
|
||||
{"name":"proptest","kind":"dev"}]},
|
||||
{"name":"modelcraft-model","dependencies":[]}
|
||||
{"name":"fieldcraft-model","dependencies":[]}
|
||||
]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
let g = from_metadata(&meta).unwrap();
|
||||
assert_eq!(g.len(), 2);
|
||||
let doc = g.iter().find(|c| c.name == "modelcraft-doc").unwrap();
|
||||
let doc = g.iter().find(|c| c.name == "fieldcraft-doc").unwrap();
|
||||
assert!(doc.deps[0].workspace && !doc.deps[1].workspace);
|
||||
assert_eq!(doc.deps[2].kind, Dev);
|
||||
assert!(check(&g).is_empty());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! `cargo xtask licences [--check]`: THIRD-PARTY-LICENSES.txt, the licences of every crate built
|
||||
//! into the shipped programs (modelcraft, modelcraft-cli, modelcraft-web), read from
|
||||
//! into the shipped programs (fieldcraft, fieldcraft-cli, fieldcraft-web), read from
|
||||
//! `cargo metadata` and the crates' own licence files, so a release download can carry them.
|
||||
//! `--check` (part of `cargo xtask ci`) fails when the committed file is out of date, e.g. after a
|
||||
//! dependency changed.
|
||||
@@ -12,7 +12,7 @@ use serde_json::Value;
|
||||
use crate::cargo;
|
||||
|
||||
pub const FILE: &str = "THIRD-PARTY-LICENSES.txt";
|
||||
const ROOTS: &[&str] = &["modelcraft", "modelcraft-cli", "modelcraft-web"];
|
||||
const ROOTS: &[&str] = &["fieldcraft", "fieldcraft-cli", "fieldcraft-web"];
|
||||
|
||||
pub fn run(root: &Path, check: bool) -> Result<(), String> {
|
||||
let text = generate()?;
|
||||
@@ -118,9 +118,9 @@ fn licence_files(dir: &Path, p: &Value) -> Vec<(String, String)> {
|
||||
fn render(crates: &[Crate]) -> String {
|
||||
let rule = "=".repeat(80);
|
||||
let mut out = format!(
|
||||
"Third-party software in ModelCraft\n\nModelCraft (the desktop app, modelcraft-cli and the web app) is built from the {} crates below.\n\
|
||||
"Third-party software in FieldCraft\n\nFieldCraft (the desktop app, fieldcraft-cli and the web app) is built from the {} crates below.\n\
|
||||
Generated by `cargo xtask licences` from Cargo.lock and the crates' own licence files.\n\
|
||||
ModelCraft's own licence is in LICENSE-MIT and LICENSE-APACHE, and NOTICE.\n\n",
|
||||
FieldCraft's own licence is in LICENSE-MIT and LICENSE-APACHE, and NOTICE.\n\n",
|
||||
crates.len()
|
||||
);
|
||||
for c in crates {
|
||||
@@ -144,7 +144,7 @@ fn render(crates: &[Crate]) -> String {
|
||||
}
|
||||
if !without.is_empty() {
|
||||
out += &format!(
|
||||
"\n{rule}\nCrates whose package carries no licence file (their licence is named in Cargo.toml; the MIT and Apache-2.0\ntexts are as in ModelCraft's own LICENSE-MIT and LICENSE-APACHE)\n{rule}\n\n"
|
||||
"\n{rule}\nCrates whose package carries no licence file (their licence is named in Cargo.toml; the MIT and Apache-2.0\ntexts are as in FieldCraft's own LICENSE-MIT and LICENSE-APACHE)\n{rule}\n\n"
|
||||
);
|
||||
for c in without {
|
||||
out += &format!(
|
||||
|
||||
+2
-2
@@ -75,13 +75,13 @@ fn main() -> ExitCode {
|
||||
Some("corpus") => {
|
||||
// A binary of the testkit, so xtask itself stays free of SolidCraft.
|
||||
let mut c = cargo();
|
||||
c.args(["run", "--release", "-p", "modelcraft-testkit", "--bin", "corpus", "--"]).args(&rest);
|
||||
c.args(["run", "--release", "-p", "fieldcraft-testkit", "--bin", "corpus", "--"]).args(&rest);
|
||||
run(c, "corpus")
|
||||
}
|
||||
Some("oracle") => {
|
||||
// A binary of the testkit, which has the engine and SolidCraft scripts for geometry.
|
||||
let mut c = cargo();
|
||||
c.args(["run", "--release", "-p", "modelcraft-testkit", "--bin", "oracle", "--"]).args(&rest);
|
||||
c.args(["run", "--release", "-p", "fieldcraft-testkit", "--bin", "oracle", "--"]).args(&rest);
|
||||
run(c, "oracle")
|
||||
}
|
||||
Some("wasm") => cmd_wasm(),
|
||||
|
||||
Reference in new issue
Block a user