Files
OrcaSlicer/docs/ux/tool_atlas.json
T
Tommaso Bianchi cfc2555c3a Design: a verb's address is data, so the toolbar widget can stop existing
snaporca-7ih's remaining half. Both flyout factories registered their verbs INSIDE the
widget-building loop, so the ~40 retired tool buttons had to be constructed and then
Hide()n: skipping construction would have deleted 42 offer verbs (26 fly:<family>#<row>
+ 16 Shift+keys) while their rows still rendered and did nothing when picked.

Register first, build second. The addresses are pure data; the widget is one door onto
them, not their owner. A family absent from kBarKeep now returns before any wxWindow is
made. The keep-list stays a one-line data decision, not a structural one.

And close the class of bug for good: the constructor now verifies, once, that every verb
the atlas marks wired resolves to a real registration, logging each break and asserting in
debug. Rows that render and do nothing have shipped three times (edit_feature and sk_move
with action:null, then this) and are invisible from either side alone.

Verified on the snaporca rig by walking the offer, not by reading the code — all four
at-risk address kinds run with no widget behind them: fly:design_rect#2 drew an OBLIQUE
rectangle (the third variant, not the family's first), key:S+E opened Extrude with its
10 mm gizmo, fly:material#4 opened Thicken. Hover hints, icons and nesting intact. This
fork is code-identical here bar the two permitted DropDown divergences; it still owes a
build of its own (snaporca-5pl).

Two hints were wrong and are fixed: Cut said "Split the body with a plane", colliding with
the Split verb one row away and pointing at a card for a value the canvas already offers as
a draggable arrow; Split never said its plane comes from a picked face.

Also, because it blocked the verification and will block the next one: gui-session.sh
killed by full path while its own app_pid() matched by basename, so a differently-pathed
instance survived, held the single-instance lock, and got reported as a healthy session —
a Jul-30 binary nearly passed as this build. It now kills by basename and prints which
binary is actually on screen. Traps 6 and 7 documented.
2026-08-02 08:37:44 +02:00

2051 lines
47 KiB
JSON

{
"_comment": [
"Source of truth for the object-driven tool offer (see docs/cad_ux_guidelines.md 4.1).",
"Every verb, the selections it accepts, the document state it needs, and its fixed",
"compass address. Extracted from the code, not from memory:",
" verbs + shortcuts + refusal messages -> src/slic3r/GUI/DesignPanel.cpp (feat_dropdown",
" call sites at 524/662/734/790/874/904, sk_key table at 369-400, m_keys_feature)",
" kernel coverage -> src/libslic3r/CadDocument.hpp (enum CadFeatureType)",
" headless coverage -> src/slic3r/GUI/McpControl.cpp (method == \"...\")",
" selection kinds -> src/slic3r/GUI/DesignCanvas.hpp (the on_*_selected callbacks)",
"gen_offer_mockups.py reads this file; the eventual C++ offer table is generated from it",
"too, so the map exists once."
],
"slots": [
{
"id": "create",
"pos": "N",
"angle": 270,
"label": "Create",
"why": "makes new geometry from nothing you have yet"
},
{
"id": "add",
"pos": "NE",
"angle": 315,
"label": "Add material",
"why": "grows solid or sheet material"
},
{
"id": "remove",
"pos": "E",
"angle": 0,
"label": "Remove",
"why": "takes material away Shell lives here by decision of 2026-08-01, not by oversight."
},
{
"id": "dressup",
"pos": "SE",
"angle": 45,
"label": "Fillet / chamfer / draft",
"why": "finishes faces and edges without changing the shape's intent; named for the tools it holds, not for the trade word. RATIFIED 2026-08-01: Shell stays in Remove and Delete Face in Modify — this row is deliberately NOT the same set as the toolbar's dressup dropdown, which groups all five. Shell hollows a solid, so it belongs with the verbs that take material away. Do not re-open: a verb's row is its address and reordering breaks learned reach."
},
{
"id": "repeat",
"pos": "S",
"angle": 90,
"label": "Repeat",
"why": "copies what exists"
},
{
"id": "transform",
"pos": "SW",
"angle": 135,
"label": "Transform",
"why": "moves without changing shape"
},
{
"id": "reference",
"pos": "W",
"angle": 180,
"label": "Reference",
"why": "makes datums, curves and measurements"
},
{
"id": "modify",
"pos": "NW",
"angle": 225,
"label": "Modify",
"why": "edits or removes what is already there"
}
],
"selections": [
{
"id": "none",
"name": "Nothing selected",
"mode": "model",
"shape": "empty"
},
{
"id": "face_planar",
"name": "Planar face",
"mode": "model",
"shape": "box_top"
},
{
"id": "face_cyl",
"name": "Cylindrical face",
"mode": "model",
"shape": "box_bore"
},
{
"id": "face_other",
"name": "Curved face",
"mode": "model",
"shape": "box_fillet_face"
},
{
"id": "edge_str",
"name": "Straight edge",
"mode": "model",
"shape": "box_edge"
},
{
"id": "edge_circ",
"name": "Circular edge",
"mode": "model",
"shape": "box_bore_rim"
},
{
"id": "vertex",
"name": "Vertex",
"mode": "model",
"shape": "box_vertex"
},
{
"id": "body_solid",
"name": "Solid body",
"mode": "model",
"shape": "box_whole"
},
{
"id": "body_sheet",
"name": "Sheet body",
"mode": "model",
"shape": "sheet"
},
{
"id": "bodies_2",
"name": "Two bodies",
"mode": "model",
"shape": "two_boxes"
},
{
"id": "datum_plane",
"name": "Datum plane",
"mode": "model",
"shape": "datum"
},
{
"id": "datum_axis",
"name": "Datum axis",
"mode": "model",
"shape": "axis"
},
{
"id": "coordsys",
"name": "Coordinate system",
"mode": "model",
"shape": "csys"
},
{
"id": "art",
"name": "Text / imported art",
"mode": "model",
"shape": "art"
},
{
"id": "sk_loop",
"name": "Closed sketch loop",
"mode": "model",
"shape": "loop"
},
{
"id": "sk_none",
"name": "Sketch, nothing picked",
"mode": "sketch",
"shape": "sk_empty"
},
{
"id": "sk_line",
"name": "Sketch line",
"mode": "sketch",
"shape": "sk_line"
},
{
"id": "sk_arc",
"name": "Sketch arc or circle",
"mode": "sketch",
"shape": "sk_arc"
},
{
"id": "sk_point",
"name": "Sketch point",
"mode": "sketch",
"shape": "sk_point"
},
{
"id": "sk_2ent",
"name": "Two sketch entities",
"mode": "sketch",
"shape": "sk_two"
}
],
"doc_states": [
{
"id": "rich",
"name": "Working document",
"bodies": 2,
"sketches": 2,
"sheet": true,
"note": "two solids, two sketches, one sheet body — everything doc-gated is legal"
},
{
"id": "fresh",
"name": "Fresh document",
"bodies": 0,
"sketches": 0,
"sheet": false,
"note": "nothing built yet — shows how much of the ring is empty on first open"
}
],
"verbs": [
{
"id": "sketch",
"name": "Sketch",
"slot": "create",
"key": "Shift+S",
"feature": "Sketch",
"mcp": null,
"accepts": [
"face_planar",
"datum_plane",
"none"
],
"needs": {},
"refusal": "Click a face or a reference plane in the viewport, then a sketch tool",
"gui": true,
"action": "key:S+S",
"icon": "design_sketch",
"hint": "Click a face or a reference plane, then pick a drawing tool"
},
{
"id": "extrude",
"name": "Extrude",
"slot": "add",
"key": "Shift+E",
"feature": "Extrude",
"mcp": "extrude",
"accepts": [
"sk_loop",
"face_planar"
],
"needs": {},
"refusal": "Create a sketch, or pick a solid face, first",
"gui": true,
"action": "key:S+E",
"icon": "design_extrude",
"hint": "Extrude a sketch profile, or push/pull a picked face"
},
{
"id": "revolve",
"name": "Revolve",
"slot": "add",
"key": "Shift+R",
"feature": "Revolve",
"mcp": "revolve",
"accepts": [
"sk_loop"
],
"needs": {},
"refusal": "Create a sketch profile to revolve first",
"gui": true,
"action": "key:S+R",
"icon": "design_revolve",
"hint": "Revolve a profile about an axis"
},
{
"id": "sweep",
"name": "Sweep",
"slot": "add",
"key": "Shift+W",
"feature": "Sweep",
"mcp": null,
"accepts": [
"sk_loop"
],
"needs": {
"sketches": 2
},
"refusal": "Create a profile sketch to sweep first",
"gui": true,
"action": "key:S+W",
"icon": "design_sweep",
"hint": "Sweep a profile along a path"
},
{
"id": "loft",
"name": "Loft",
"slot": "add",
"key": "Shift+L",
"feature": "Loft",
"mcp": null,
"accepts": [
"sk_loop"
],
"needs": {
"sketches": 2
},
"refusal": "Create at least two profile sketches to loft",
"gui": true,
"action": "key:S+L",
"icon": "design_loft",
"hint": "Loft (skin) between two or more profiles"
},
{
"id": "thicken",
"name": "Thicken",
"slot": "add",
"key": null,
"feature": "Thicken",
"mcp": "thicken",
"accepts": [
"face_planar",
"face_other"
],
"needs": {
"bodies": 1
},
"refusal": "Thicken needs a solid body — add or import one first",
"gui": true,
"action": "fly:material#4",
"icon": "design_thicken",
"hint": "Offset a solid face into a thin plate (new body)"
},
{
"id": "rib",
"name": "Rib",
"slot": "add",
"key": null,
"feature": "Rib",
"mcp": "rib",
"accepts": [
"sk_line"
],
"needs": {
"bodies": 1
},
"refusal": "Rib needs a solid body — add or import one first",
"gui": true,
"action": "fly:material#5",
"icon": "design_rib",
"hint": "Grow a thin wall from an open sketch line, fused to a body"
},
{
"id": "boolean",
"name": "Union",
"slot": "add",
"key": "Shift+B",
"feature": "Boolean",
"mcp": "boolean",
"accepts": [
"bodies_2"
],
"needs": {
"bodies": 2
},
"refusal": "Boolean needs two bodies — create or import a second solid",
"gui": true,
"action": "btn:bool#0",
"icon": "design_boolean",
"hint": "Fuse the tool body into the target — one solid, no seam"
},
{
"id": "bool_subtract",
"name": "Subtract",
"slot": "add",
"key": null,
"feature": "Boolean",
"mcp": null,
"accepts": [
"bodies_2"
],
"needs": {
"bodies": 2
},
"refusal": "Boolean needs two bodies — create or import a second solid",
"gui": true,
"action": "btn:bool#1",
"mode": null,
"icon": "design_boolean",
"hint": "Cut the tool body out of the target"
},
{
"id": "bool_intersect",
"name": "Intersect",
"slot": "add",
"key": null,
"feature": "Boolean",
"mcp": null,
"accepts": [
"bodies_2"
],
"needs": {
"bodies": 2
},
"refusal": "Boolean needs two bodies — create or import a second solid",
"gui": true,
"action": "btn:bool#2",
"mode": null,
"icon": "design_boolean",
"hint": "Keep only where the two bodies overlap"
},
{
"id": "surf_extrude",
"name": "Surface Extrude",
"slot": "add",
"key": "Shift+G",
"feature": "SurfaceExtrude",
"mcp": "surface_extrude",
"accepts": [
"sk_loop"
],
"needs": {},
"refusal": "Create a sketch first",
"gui": true,
"action": "key:S+G",
"icon": "design_extrude",
"hint": "Extrude a sketch into a sheet body (no end caps)"
},
{
"id": "surf_revolve",
"name": "Surface Revolve",
"slot": "add",
"key": null,
"feature": "SurfaceRevolve",
"mcp": "surface_revolve",
"accepts": [
"sk_loop"
],
"needs": {},
"refusal": "Create a sketch profile to revolve first",
"gui": true,
"action": "fly:surface#1",
"icon": "design_revolve",
"hint": "Revolve a sketch profile into a sheet body"
},
{
"id": "surf_loft",
"name": "Surface Loft",
"slot": "add",
"key": null,
"feature": "SurfaceLoft",
"mcp": "surface_loft",
"accepts": [
"sk_loop"
],
"needs": {
"sketches": 2
},
"refusal": "Create at least two profile sketches to loft",
"gui": true,
"action": "fly:surface#2",
"icon": "design_loft",
"hint": "Loft (skin) between 2+ profiles, open (no end caps)"
},
{
"id": "surf_fill",
"name": "Surface Fill",
"slot": "add",
"key": null,
"feature": "SurfaceFill",
"mcp": "surface_fill",
"accepts": [
"sk_loop"
],
"needs": {},
"refusal": "Create a closed sketch first",
"gui": true,
"action": "fly:surface#3",
"icon": "design_surface",
"hint": "Fill a sketch boundary with a smooth face"
},
{
"id": "thicken_surf",
"name": "Thicken Surface",
"slot": "add",
"key": null,
"feature": "ThickenSurface",
"mcp": "thicken_surface",
"accepts": [
"body_sheet"
],
"needs": {
"sheet": true
},
"refusal": "target is not a sheet body",
"gui": true,
"action": "fly:surface#5",
"icon": "design_thicken",
"hint": "Thicken a sheet body into a solid"
},
{
"id": "hole",
"name": "Hole",
"slot": "remove",
"key": "Shift+H",
"feature": "Hole",
"mcp": "hole",
"accepts": [
"face_planar",
"datum_plane"
],
"needs": {
"bodies": 1
},
"refusal": "Pick a face or a plane to drill into",
"gui": true,
"action": "key:S+H",
"icon": "design_hole",
"hint": "Drill a hole, centred on a picked face or placed on a plane"
},
{
"id": "thread",
"name": "Thread",
"slot": "remove",
"key": "Shift+T",
"feature": "Thread",
"mcp": null,
"accepts": [
"face_cyl",
"edge_circ"
],
"needs": {
"bodies": 1
},
"refusal": "Pick a cylindrical surface (bore / outer) or a circular edge for a thread",
"gui": true,
"action": "key:S+T",
"icon": "design_thread",
"hint": "Thread a cylindrical surface (inner bore / outer) or a circular edge"
},
{
"id": "shell",
"name": "Shell",
"slot": "remove",
"key": "Shift+K",
"feature": "Shell",
"mcp": "shell",
"accepts": [
"face_planar",
"body_solid"
],
"needs": {
"bodies": 1
},
"refusal": "Shell needs a solid body",
"gui": true,
"action": "key:S+K",
"icon": "design_shell",
"hint": "Hollow the body to a wall thickness, opening a picked face"
},
{
"id": "cut",
"name": "Cut",
"slot": "remove",
"key": "Shift+X",
"feature": "Cut",
"mcp": null,
"accepts": [
"body_solid",
"datum_plane"
],
"needs": {
"bodies": 1
},
"refusal": "Create a solid body to cut first",
"gui": true,
"action": "key:S+X",
"icon": "design_cut",
"hint": "Trim the body with a plane — drag the offset arrow; keep one half or both"
},
{
"id": "split",
"name": "Split",
"slot": "remove",
"key": null,
"feature": "Cut",
"mcp": "split",
"accepts": [
"body_solid"
],
"needs": {
"bodies": 1
},
"refusal": "Split needs a solid body",
"gui": false,
"action": null,
"icon": null,
"hint": "Split the body along a picked face into two solids"
},
{
"id": "fillet",
"name": "Fillet",
"slot": "dressup",
"key": "Shift+F",
"feature": "Fillet",
"mcp": "fillet",
"accepts": [
"edge_str",
"edge_circ",
"face_planar",
"body_solid"
],
"needs": {
"bodies": 1
},
"refusal": "Pick an edge to round",
"gui": true,
"action": "btn:dress#0",
"icon": "design_filletedge",
"hint": "Pick an edge, then drag the radius arrow or type it"
},
{
"id": "chamfer",
"name": "Chamfer",
"slot": "dressup",
"key": null,
"feature": "Chamfer",
"mcp": "chamfer",
"accepts": [
"edge_str",
"edge_circ",
"face_planar",
"body_solid"
],
"needs": {
"bodies": 1
},
"refusal": "Pick an edge to bevel",
"gui": true,
"action": "btn:dress#1",
"icon": "design_chamfer",
"hint": "Pick an edge, then drag the distance arrow or type it"
},
{
"id": "draft",
"name": "Draft",
"slot": "dressup",
"key": "Shift+D",
"feature": "Draft",
"mcp": "draft",
"accepts": [
"face_planar",
"face_other"
],
"needs": {
"bodies": 1
},
"refusal": "Pick a face to taper",
"gui": true,
"action": "key:S+D",
"icon": "design_draft",
"hint": "Tilt a picked face by a draft angle"
},
{
"id": "surf_offset",
"name": "Surface Offset",
"slot": "dressup",
"key": null,
"feature": "SurfaceOffset",
"mcp": "surface_offset",
"accepts": [
"body_sheet"
],
"needs": {
"sheet": true
},
"refusal": "target is not a sheet body",
"gui": true,
"action": "fly:surface#4",
"icon": "design_offset",
"hint": "Offset a sheet body's shell by a signed distance"
},
{
"id": "pattern",
"name": "Linear pattern",
"slot": "repeat",
"key": "Shift+N",
"feature": "Pattern",
"mcp": "pattern",
"accepts": [
"body_solid",
"face_planar",
"sk_loop",
"art"
],
"needs": {
"bodies": 1
},
"refusal": "Create a solid body to pattern first",
"gui": true,
"action": "btn:pat#0",
"icon": "design_array",
"hint": "Repeat the body along a direction — drag the spacing, set the count"
},
{
"id": "pattern_circular",
"name": "Circular pattern",
"slot": "repeat",
"key": null,
"feature": "Pattern",
"mcp": null,
"accepts": [
"body_solid",
"face_planar",
"sk_loop",
"art"
],
"needs": {
"bodies": 1
},
"refusal": "Create a solid body to pattern first",
"gui": true,
"action": "btn:pat#1",
"mode": null,
"icon": "design_polararray",
"hint": "Repeat the body around an axis — set the count and sweep"
},
{
"id": "mirror",
"name": "Mirror",
"slot": "repeat",
"key": "Shift+Z",
"feature": "Mirror",
"mcp": "mirror",
"accepts": [
"body_solid",
"datum_plane"
],
"needs": {
"bodies": 1
},
"refusal": "Mirror needs a body — add or import one first",
"gui": true,
"action": "key:S+Z",
"icon": "design_mirror",
"hint": "Reflect a body about a plane"
},
{
"id": "pat_curve",
"name": "Pattern on Curve",
"slot": "repeat",
"key": null,
"feature": "Pattern",
"mcp": "pattern_on_curve",
"accepts": [
"body_solid",
"edge_str"
],
"needs": {
"bodies": 1
},
"refusal": "Pattern on curve needs a body and a curve",
"gui": false,
"action": null,
"icon": null,
"hint": "Repeat the body along a picked curve"
},
{
"id": "transform",
"name": "Move",
"slot": "transform",
"key": "Shift+Y",
"feature": "Transform",
"mcp": "transform",
"accepts": [
"body_solid",
"body_sheet",
"art"
],
"needs": {
"bodies": 1
},
"refusal": "Transform needs a body — add or import one first",
"gui": true,
"action": "key:S+Y",
"icon": "design_move",
"hint": "Move and/or rotate an existing body"
},
{
"id": "mate",
"name": "Mate",
"slot": "transform",
"key": null,
"feature": "Mate",
"mcp": "mate",
"accepts": [
"coordsys",
"bodies_2",
"face_planar"
],
"needs": {
"bodies": 2
},
"refusal": "A mate needs two coordinate systems",
"gui": true,
"action": "fly:placement#2",
"icon": "design_c_coincident",
"hint": "Assembly: align two CoordSys features (fastened, planar, revolute, slider, cylindrical)"
},
{
"id": "align",
"name": "Align to",
"slot": "transform",
"key": null,
"feature": "Transform",
"mcp": "transform",
"accepts": [
"face_planar"
],
"needs": {
"bodies": 1
},
"refusal": "Align needs a body",
"gui": false,
"action": null,
"icon": null,
"hint": "Align the body to a picked face or plane"
},
{
"id": "plane",
"name": "Plane",
"slot": "reference",
"key": "Shift+P",
"feature": "Plane",
"mcp": null,
"accepts": [
"none",
"face_planar",
"edge_str",
"datum_plane",
"vertex"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:S+P",
"icon": "design_plane",
"hint": "Reference plane (offset / tilt / midplane / tangent / two edges / coincident)"
},
{
"id": "axis",
"name": "Axis",
"slot": "reference",
"key": "Shift+A",
"feature": "Axis",
"mcp": "axis",
"accepts": [
"none",
"face_planar",
"face_cyl",
"edge_str",
"vertex"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:S+A",
"icon": "design_line",
"hint": "Datum axis (two points, face normal, cylinder centerline, two planes, along edge)"
},
{
"id": "coordsys_v",
"name": "Coord Sys",
"slot": "reference",
"key": "Shift+C",
"feature": "CoordSys",
"mcp": "coordsys",
"accepts": [
"none",
"face_planar",
"vertex"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:S+C",
"icon": "design_point",
"hint": "Datum coordinate system (world point, or face + direction edge)"
},
{
"id": "helix",
"name": "Helix",
"slot": "reference",
"key": null,
"feature": "Helix",
"mcp": "helix",
"accepts": [
"none",
"datum_plane",
"face_cyl"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:plane#3",
"icon": "design_thread",
"hint": "Helical curve (spring path) — use as a sweep path for coils / springs / augers"
},
{
"id": "project",
"name": "Project",
"slot": "reference",
"key": null,
"feature": "Project",
"mcp": "project",
"accepts": [
"body_solid",
"face_planar",
"datum_plane"
],
"needs": {
"bodies": 1
},
"refusal": "Project needs a body — add or import one first",
"gui": true,
"action": "fly:plane#4",
"icon": "design_sketch",
"hint": "Project body edges onto a plane as sketch entities"
},
{
"id": "measure",
"name": "Measure",
"slot": "reference",
"key": null,
"feature": null,
"mcp": "measure",
"accepts": [
"face_planar",
"face_cyl",
"face_other",
"edge_str",
"edge_circ",
"vertex",
"body_solid",
"body_sheet",
"bodies_2",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": false,
"action": null,
"icon": null,
"hint": "Measure between the picked points, edges or faces"
},
{
"id": "mass_props",
"name": "Mass",
"slot": "reference",
"key": null,
"feature": null,
"mcp": "mass_properties",
"accepts": [
"body_solid"
],
"needs": {
"bodies": 1
},
"refusal": null,
"gui": true,
"action": "btn:mass",
"icon": "info",
"hint": "Report the volume and surface area of the selected body"
},
{
"id": "interference",
"name": "Interference",
"slot": "reference",
"key": null,
"feature": null,
"mcp": "check_interference",
"accepts": [
"bodies_2"
],
"needs": {
"bodies": 2
},
"refusal": null,
"gui": false,
"action": null,
"icon": null,
"hint": "Check whether two bodies overlap — reports, changes nothing"
},
{
"id": "edit_feature",
"name": "Edit",
"slot": "modify",
"key": null,
"feature": null,
"mcp": "set_feature_expr",
"accepts": [
"body_solid",
"face_planar",
"face_cyl",
"face_other",
"sk_loop",
"art",
"datum_plane",
"datum_axis",
"coordsys",
"body_sheet"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:edit",
"icon": "design_edit",
"hint": "Reopen the selected feature to change what it was made from"
},
{
"id": "delete_face",
"name": "Delete Face",
"slot": "modify",
"key": null,
"feature": "DeleteFace",
"mcp": "delete_face",
"accepts": [
"face_planar",
"face_cyl",
"face_other"
],
"needs": {
"bodies": 1
},
"refusal": "Delete Face needs a body — add or import one first",
"gui": true,
"action": "fly:dressup#3",
"icon": "design_delete",
"hint": "Remove faces from a body and heal the solid"
},
{
"id": "colour",
"name": "Colour",
"slot": "modify",
"key": null,
"feature": null,
"mcp": null,
"accepts": [
"body_solid",
"body_sheet"
],
"needs": {
"bodies": 1
},
"refusal": null,
"gui": true,
"action": "btn:colour",
"icon": "color_palette",
"hint": "Set the selected body's display colour"
},
{
"id": "delete",
"name": "Delete",
"slot": "modify",
"key": "Del",
"feature": null,
"mcp": null,
"accepts": [
"body_solid",
"body_sheet",
"sk_loop",
"art",
"datum_plane",
"datum_axis",
"coordsys",
"bodies_2",
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:delete",
"icon": "design_delete",
"hint": "Delete what is selected"
},
{
"id": "sk_line_t",
"name": "Line",
"slot": "create",
"key": "L",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:L",
"family": "Line",
"icon": "design_line",
"hint": "Line — click start, then end"
},
{
"id": "sk_polyline",
"name": "Polyline",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_line#1",
"mode": "sketch",
"family": "Line",
"icon": "design_polyline",
"hint": "Click points; click first / right-click to close the loop"
},
{
"id": "sk_rect",
"name": "Corner rectangle",
"slot": "create",
"key": "R",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:R",
"family": "Rectangle",
"icon": "design_rect",
"hint": "Rectangle — click two opposite corners"
},
{
"id": "sk_rect_center",
"name": "Centre rectangle",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_rect#1",
"mode": "sketch",
"family": "Rectangle",
"icon": "design_crect",
"hint": "Click center, then a corner"
},
{
"id": "sk_rect_oblique",
"name": "Oblique rectangle",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_rect#2",
"mode": "sketch",
"family": "Rectangle",
"icon": "design_rect_oblique",
"hint": "Click two corners of one edge, then a point for the width"
},
{
"id": "sk_rect_rounded",
"name": "Rounded rectangle",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_rect#3",
"mode": "sketch",
"family": "Rectangle",
"icon": "design_rect_rounded",
"hint": "Click two opposite corners, then a point for the corner radius"
},
{
"id": "sk_circle",
"name": "Centre circle",
"slot": "create",
"key": "C",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:C",
"family": "Circle",
"icon": "design_circle",
"hint": "Circle — click center, then radius"
},
{
"id": "sk_circle_2pt",
"name": "2-point circle",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_circle#1",
"mode": "sketch",
"family": "Circle",
"icon": "design_circle2pt",
"hint": "Click two ends of the diameter"
},
{
"id": "sk_circle_3pt",
"name": "3-point circle",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_circle#2",
"mode": "sketch",
"family": "Circle",
"icon": "design_circle3pt",
"hint": "Click three points on the circle"
},
{
"id": "sk_arc_t",
"name": "3-point arc",
"slot": "create",
"key": "A",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:A",
"family": "Arc",
"icon": "design_arc3pt",
"hint": "Arc — click start, end, then a point"
},
{
"id": "sk_arc_tangent",
"name": "Tangent arc",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_arc3pt#1",
"mode": "sketch",
"family": "Arc",
"icon": "design_tangentarc",
"hint": "Click start (on the last entity) then end"
},
{
"id": "sk_arc_center",
"name": "Centre-point arc",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_arc3pt#2",
"mode": "sketch",
"family": "Arc",
"icon": "design_arc_center",
"hint": "Click center, then start, then a point for the end angle"
},
{
"id": "sk_slot",
"name": "Slot",
"slot": "create",
"key": "S",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:S",
"family": "Slot",
"icon": "design_slot",
"hint": "Slot — two centerline ends, then end radius"
},
{
"id": "sk_slot_arc",
"name": "Arc slot",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_slot#1",
"mode": "sketch",
"family": "Slot",
"icon": "design_slot_arc",
"hint": "Click center, start, end, then a point for the width"
},
{
"id": "sk_ellipse",
"name": "Ellipse",
"slot": "create",
"key": "E",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:E",
"family": "Ellipse",
"icon": "design_ellipse",
"hint": "Ellipse — center, major end, minor point"
},
{
"id": "sk_ellipse_arc",
"name": "Elliptical arc",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_ellipse#1",
"mode": "sketch",
"family": "Ellipse",
"icon": "design_ellipse_arc",
"hint": "Click center, major-axis end, minor point, then arc start and end"
},
{
"id": "sk_spline",
"name": "Spline",
"slot": "create",
"key": "B",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:B",
"icon": "design_bspline",
"hint": "Spline — click control points"
},
{
"id": "sk_poly_3",
"name": "Triangle",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:poly#3",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Triangle — click centre, then a vertex"
},
{
"id": "sk_poly_4",
"name": "Square",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:poly#4",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Square — click centre, then a vertex"
},
{
"id": "sk_poly_5",
"name": "Pentagon",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:poly#5",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Pentagon — click centre, then a vertex"
},
{
"id": "sk_polygon",
"name": "Hexagon",
"slot": "create",
"key": "G",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:poly#6",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Hexagon — click centre, then a vertex"
},
{
"id": "sk_poly_8",
"name": "Octagon",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:poly#8",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Octagon — click centre, then a vertex"
},
{
"id": "sk_poly_12",
"name": "Dodecagon",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:poly#12",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Dodecagon — click centre, then a vertex"
},
{
"id": "sk_poly_inscribed",
"name": "Inscribed",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:polyfit#0",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Measure the polygon to its corners (inscribed)"
},
{
"id": "sk_poly_circumscribed",
"name": "Circumscribed",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:polyfit#1",
"mode": "sketch",
"family": "Polygon",
"icon": "design_polygon",
"hint": "Measure the polygon to its flats (circumscribed)"
},
{
"id": "sk_point_t",
"name": "Point",
"slot": "create",
"key": "P",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:P",
"icon": "design_point",
"hint": "Point — click to place"
},
{
"id": "sk_text",
"name": "Text",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:text",
"mode": "sketch",
"icon": "design_text",
"hint": "Type text; its outline is added to this sketch as editable lines"
},
{
"id": "sk_svg",
"name": "SVG",
"slot": "create",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_none",
"sk_point",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:svg",
"mode": "sketch",
"icon": "design_svg",
"hint": "Import an SVG outline into this sketch as editable lines"
},
{
"id": "sk_offset",
"name": "Offset",
"slot": "add",
"key": "O",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:O",
"icon": "design_offset",
"hint": "Offset — pick an entity, drag the distance"
},
{
"id": "sk_trim",
"name": "Trim",
"slot": "remove",
"key": "T",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:T",
"icon": "design_trim",
"hint": "Trim — click a segment to trim it"
},
{
"id": "sk_fillet",
"name": "Fillet",
"slot": "dressup",
"key": "F",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:F",
"icon": "design_filletedge",
"hint": "Fillet — pick two lines, set the radius"
},
{
"id": "sk_chamfer",
"name": "Chamfer",
"slot": "dressup",
"key": "H",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:H",
"icon": "design_chamfer",
"hint": "Chamfer — pick two lines, set the distance"
},
{
"id": "sk_array",
"name": "Linear array",
"slot": "repeat",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_array#0",
"mode": "sketch",
"family": "Array",
"icon": "design_array",
"hint": "Pick entities, drag the spacing handle, click the count; click empty to apply"
},
{
"id": "sk_array_polar",
"name": "Polar array",
"slot": "repeat",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_array#1",
"mode": "sketch",
"family": "Array",
"icon": "design_polararray",
"hint": "Pick entities, drag the sweep handle, click the count; click empty to apply"
},
{
"id": "sk_mirror",
"name": "Mirror",
"slot": "repeat",
"key": "M",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:M",
"icon": "design_mirror",
"hint": "Mirror — pick axis, then entities"
},
{
"id": "sk_move",
"name": "Move",
"slot": "transform",
"key": null,
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_move#0",
"family": "Move",
"icon": "design_move",
"hint": "Pick entities, then drag the handle or click the distance; click empty to apply"
},
{
"id": "sk_rotate",
"name": "Rotate",
"slot": "transform",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_move#1",
"mode": "sketch",
"family": "Move",
"icon": "design_rotate",
"hint": "Pick entities, then drag around the pivot or click the angle; click empty to apply"
},
{
"id": "sk_scale",
"name": "Scale",
"slot": "transform",
"key": null,
"feature": "Sketch",
"mcp": null,
"accepts": [
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "fly:design_move#2",
"mode": "sketch",
"family": "Move",
"icon": "design_scale",
"hint": "Pick entities, then drag the handle or click the factor; click empty to apply"
},
{
"id": "sk_dimension",
"name": "Dimension",
"slot": "reference",
"key": "D",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:D",
"icon": "design_dimension",
"hint": "Dimension — click 2 points or an entity"
},
{
"id": "sk_constrain",
"name": "Constrain",
"slot": "reference",
"key": "K",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:K",
"icon": "design_constrain",
"hint": "Constrain the selected sketch entities to each other"
},
{
"id": "sk_construct",
"name": "Construction",
"slot": "reference",
"key": "Q",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_none",
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:Q",
"icon": null,
"hint": "Toggle construction: geometry that guides but is never built"
},
{
"id": "sk_extend",
"name": "Extend",
"slot": "modify",
"key": "X",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "key:X",
"icon": "design_extend",
"hint": "Extend — click a line/arc to extend it"
},
{
"id": "sk_delete",
"name": "Delete",
"slot": "modify",
"key": "Del",
"feature": "Sketch",
"mcp": null,
"mode": "sketch",
"accepts": [
"sk_line",
"sk_arc",
"sk_point",
"sk_2ent"
],
"needs": {},
"refusal": null,
"gui": true,
"action": "btn:delete",
"icon": "design_delete",
"hint": "Delete the selected sketch entities"
}
],
"chrome_only": {
"_why": "document-level actions act on the DOCUMENT, not on a selection, so they stay in chrome and never enter the offer (see 4.1) Text and SVG were removed from this list 2026-08-01: they create a Sketch feature on the picked face, so they consume a selection like any other Create verb.",
"items": [
"Import STEP",
"Import mesh",
"Export STEP",
"Commit to Plate",
"Undo",
"Redo",
"Variables",
"Section view",
"Origin planes",
"World axes"
]
},
"_ratified": "Row order ratified 2026-07-31 by Tommaso. Changing an index is a breaking change (charter 4.1)."
}