Engine: each command lists what it needs, and execute checks it first

CommandSpec gains `requires: &[Requirement]` (crates/engine/src/requirement.rs): an open
design, geometry, nodes, a mesh, something to analyse, materials and sections for the
elements, sets, the definition an edit or delete acts on, a step, a result. Session::execute
checks them before running, so a command missing one fails at once with no partial work,
naming each missing piece and the toolbar entry that provides it ("Needs a material —
Properties › Material"). Requirements are real prerequisites (the model's own reference
checks and model.check's rules), never a workflow order. engine.commands / list_commands
list them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-14 18:43:29 -04:00
1 parent 06b98f01c7
commit e0d5adba23
20 files changed
+448 -25

No files matched your search

+2 -2
View File
@@ -1256,8 +1256,8 @@ mod tests {
#[test]
fn mesh_quality_reports_in_a_line() {
let mut app = ModelApp::new(Session::default());
app.run("mesh.quality", json!({})).unwrap();
assert_eq!(app.status.as_ref().map(|s| s.text.as_str()), Some("Mesh Quality: no elements to measure"));
// Nothing to measure: the command needs a mesh and says so.
assert!(app.run("mesh.quality", json!({})).is_err());
app.run_script(&fieldcraft_engine::sample::script()).unwrap();
app.run("mesh.quality", json!({})).unwrap();
let status = app.status.clone().unwrap();