You will model one parcel moving from a packing bench to a dispatch area.
The completed project validates its sources, inspects resolved state, runs a domain rule, and renders an SVG file.
Prerequisites
Complete Install and verify in an empty parcel-workflow directory.
Create the Starting State
-
Create
start.workspec.jsonwith this WorkSpec 2.2 document:JSON{ "$schema": "https://universalautomation.wiki/workspec/v2.2.schema.json", "simulation": { "schema_version": "2.2", "meta": { "title": "Parcel workflow", "description": "Pack one parcel and move it to dispatch.", "domain": "logistics" }, "config": { "time_unit": "minutes", "start_time": "09:00", "end_time": "10:00" }, "world": { "layout": { "locations": [ { "id": "packing_bench", "name": "Packing bench", "shape": { "type": "rect", "x": 20, "y": 20, "width": 220, "height": 140 } }, { "id": "dispatch_area", "name": "Dispatch area", "shape": { "type": "rect", "x": 280, "y": 20, "width": 220, "height": 140 } } ] }, "objects": [ { "id": "packer", "type": "actor", "name": "Packer", "location": "packing_bench", "properties": { "state": "available" } }, { "id": "parcel", "type": "product", "name": "Parcel", "location": "packing_bench", "properties": { "quantity": 1, "state": "unpacked" } } ] }, "process": { "tasks": [ { "id": "pack_parcel", "actor_id": "packer", "start": "09:00", "duration": "10m", "location": "packing_bench" } ] } } } -
Validate the document.
Terminalnpx workspec validate start.workspec.jsonExpected final line:
Text✓ No problems found
The Starting State declares facts and plans. It does not contain the task's effects.
Add the task effects
-
Create
changes.workspec.js:JavaScript/// <reference types="workspec/workspec-changes" /> WorkSpec.task("pack_parcel", (task) => { task.onStart(() => { set("parcel", "state", "packing", { temporary: true }); }); task.onComplete(() => { set("parcel", "state", "packed"); move("parcel", "dispatch_area"); }); }); -
Validate the project through the task's completion time.
Terminalnpx workspec validate start.workspec.json \ --time 09:10Expected final line:
Text✓ No problems found
The Changes reference owns the complete authoring and operation rules.
Inspect a snapshot
To inspect resolved state at 09:10, run:
npx workspec snapshot start.workspec.json \
--time 09:10 \
--jsonThe JSON output contains these resolved values:
{
"state": "packed",
"location": "dispatch_area",
"task_status": "completed"
}These three values appear within the larger snapshot envelope. Find them under state.objects.parcel and state.task_statuses.pack_parcel.
Add a domain rule
-
Create
constraints.workspec.js:JavaScript/// <reference types="workspec/workspec-constraints" /> WorkSpec.constraint("parcel.ready_for_dispatch", (context) => { const state = context.get("parcel", "state"); const location = context.get("parcel", "location"); if (state === "packed" && location === "dispatch_area") { return null; } return { severity: "error", objects: ["parcel"], observed: { state, location }, expected: { state: "packed", location: "dispatch_area" }, message: "The packed parcel must be in the dispatch area." }; }); -
Review the file before you execute it.
-
Run the Constraint against the resolved project.
Terminalnpx workspec constraints start.workspec.json \ --time 09:10 \ --yesExpected output:
TextRuntime constraints at 550 (resolved through 550): 0 violations (0 errors), 0 validation problems
Render the world
To render the same project time as standalone SVG, run:
npx workspec render start.workspec.json \
--time 09:10 \
--out parcel-world.svgThe success line ends with the absolute output path:
✓ Rendered 09:10 to /ABSOLUTE/PATH/parcel-world.svgOpen parcel-world.svg in an SVG viewer. The parcel appears in the dispatch area.
Result
Your project now separates declarations, predetermined effects, domain rules, resolved state, and presentation.
Next step
Review the project files before you begin the longer learning path.