{
 "date": "2026-10-20",
 "machine": "AMD Ryzen 9 7950X3D, Windows 11 Pro 10.0.26200",
 "exe_sha256": "71b803ee246f1b29792e59d616eb4ee7905e71efaf7cf7987ecc30079138c0e6",
 "request": {
  "name": "Example parts on a CO2 laser bed",
  "parts": [
   {
    "id": "parts-1",
    "quantity": 4
   },
   {
    "id": "parts-2",
    "quantity": 12,
    "rotations": {
     "kind": "free"
    }
   },
   {
    "id": "parts-3",
    "quantity": 6,
    "allow_mirror": true
   },
   {
    "id": "parts-4",
    "quantity": 10,
    "rotations": {
     "kind": "list",
     "degrees": [
      0,
      180
     ]
    }
   }
  ],
  "sheets": [
   {
    "width_mm": 600,
    "height_mm": 400,
    "margins_mm": {
     "left": 5,
     "right": 5,
     "bottom": 5,
     "top": 5
    }
   }
  ],
  "spacing_mm": 1.0,
  "edge_spacing_mm": 1.0
 },
 "steps": {
  "import": {
   "tool": "import_parts",
   "arguments": {
    "paths": [
     "parts.svg"
    ],
    "library_path": "lib.json"
   },
   "isError": false,
   "body": {
    "imports": [
     {
      "file": "parts.svg",
      "report": {
       "cleanup": {
        "duplicate_segments_removed": 0,
        "overlapping_segments_merged": 0,
        "zero_length_segments_removed": 0
       },
       "close_gaps_mm": null,
       "closed_gaps": [],
       "colors": [
        {
         "entities": 5,
         "geometry_entities": 5,
         "name": "#000000",
         "selected_entities": 5
        }
       ],
       "layers": [
        {
         "entities": 5,
         "geometry_entities": 5,
         "name": "0",
         "selected_entities": 5
        }
       ],
       "open_contours": [],
       "selection_mode": "closed_contours",
       "silent_join_mm": 0.005,
       "units": null
      }
     }
    ],
    "library_path": "lib.json",
    "lightburn": null,
    "part_count": 4,
    "parts": [
     {
      "area_mm2": 2400.0,
      "bounds_mm": [
       0.0,
       -60.0,
       80.0,
       0.0
      ],
      "holes": 1,
      "id": "parts-1",
      "source": "parts.svg#frame"
     },
     {
      "area_mm2": 373.7015062251943,
      "bounds_mm": [
       98.00498388411378,
       -31.99875396427968,
       122.0,
       -8.001246035720323
      ],
      "holes": 1,
      "id": "parts-2",
      "source": "parts.svg#washer-outer"
     },
     {
      "area_mm2": 2058.619842636201,
      "bounds_mm": [
       100.0,
       -96.875,
       150.0,
       -50.0
      ],
      "holes": 1,
      "id": "parts-3",
      "source": "parts.svg#bracket"
     },
     {
      "area_mm2": 508.7515368487275,
      "bounds_mm": [
       157.45848243590828,
       -34.862955889377396,
       192.54151756409172,
       -15.1370441106226
      ],
      "holes": 0,
      "id": "parts-4",
      "source": "parts.svg#tab"
     }
    ],
    "parts_truncated": false,
    "sheet_outline_count": 0,
    "sheet_outlines": [],
    "sheet_outlines_truncated": false,
    "warnings": []
   },
   "elapsed_s": 0.001,
   "reply_bytes": 2639,
   "notifications": 0,
   "notification_messages": []
  },
  "nest_a": {
   "tool": "nest",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "parts-1",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    },
    "time_budget_s": 10,
    "seed": 0,
    "out_dir": "out-a"
   },
   "isError": false,
   "body": {
    "algorithm": "nestbolt-sheet-separator-v1",
    "elapsed_s": 3.1617268,
    "files": [
     "out-a/sheet-0.svg",
     "out-a/sheet-0.dxf"
    ],
    "layout_path": "out-a/layout.json",
    "out_dir": "out-a",
    "parts_in_holes": 8,
    "repeatable": true,
    "seed": 0,
    "time_budget_s": 10.0,
    "unsupported": null,
    "validation": {
     "metrics": {
      "full_stock_area": 240000.0,
      "last_sheet_id": "sheet-0",
      "last_sheet_used_height": 92.04464399999999,
      "material_area": 55226.78639999998,
      "normalized_material": 0.23011160999999994,
      "placed_area": 31523.65254087845,
      "placed_parts": 32,
      "placed_priority": 32.0,
      "requested_parts": 32,
      "sheets_used": 1,
      "trailing_offcut_area": 184773.21360000002,
      "utilization": 0.5708036732855863
     },
     "valid": true,
     "violation_count": 0,
     "violations": []
    },
    "version": 1,
    "work_version": "nestbolt-work-v2"
   },
   "elapsed_s": 3.172,
   "reply_bytes": 1647,
   "notifications": 3,
   "notification_messages": [
    {
     "jsonrpc": "2.0",
     "method": "notifications/progress",
     "params": {
      "message": "material 0.2319 sheets",
      "progress": 0.6629348795712698,
      "progressToken": "a",
      "total": 10.0
     }
    },
    {
     "jsonrpc": "2.0",
     "method": "notifications/progress",
     "params": {
      "message": "material 0.2302 sheets",
      "progress": 3.94240937357127,
      "progressToken": "a",
      "total": 10.0
     }
    },
    {
     "jsonrpc": "2.0",
     "method": "notifications/progress",
     "params": {
      "message": "material 0.2301 sheets",
      "progress": 5.0267462175712705,
      "progressToken": "a",
      "total": 10.0
     }
    }
   ]
  },
  "nest_b": {
   "tool": "nest",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "parts-1",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    },
    "time_budget_s": 10,
    "seed": 0,
    "out_dir": "out-b"
   },
   "isError": false,
   "body": {
    "algorithm": "nestbolt-sheet-separator-v1",
    "elapsed_s": 3.7303179,
    "files": [
     "out-b/sheet-0.svg",
     "out-b/sheet-0.dxf"
    ],
    "layout_path": "out-b/layout.json",
    "out_dir": "out-b",
    "parts_in_holes": 8,
    "repeatable": true,
    "seed": 0,
    "time_budget_s": 10.0,
    "unsupported": null,
    "validation": {
     "metrics": {
      "full_stock_area": 240000.0,
      "last_sheet_id": "sheet-0",
      "last_sheet_used_height": 92.04464399999999,
      "material_area": 55226.78639999998,
      "normalized_material": 0.23011160999999994,
      "placed_area": 31523.65254087845,
      "placed_parts": 32,
      "placed_priority": 32.0,
      "requested_parts": 32,
      "sheets_used": 1,
      "trailing_offcut_area": 184773.21360000002,
      "utilization": 0.5708036732855863
     },
     "valid": true,
     "violation_count": 0,
     "violations": []
    },
    "version": 1,
    "work_version": "nestbolt-work-v2"
   },
   "elapsed_s": 3.735,
   "reply_bytes": 1647,
   "notifications": 3,
   "notification_messages": [
    {
     "jsonrpc": "2.0",
     "method": "notifications/progress",
     "params": {
      "message": "material 0.2319 sheets",
      "progress": 0.6629348795712698,
      "progressToken": "b",
      "total": 10.0
     }
    },
    {
     "jsonrpc": "2.0",
     "method": "notifications/progress",
     "params": {
      "message": "material 0.2302 sheets",
      "progress": 3.94240937357127,
      "progressToken": "b",
      "total": 10.0
     }
    },
    {
     "jsonrpc": "2.0",
     "method": "notifications/progress",
     "params": {
      "message": "material 0.2301 sheets",
      "progress": 5.0267462175712705,
      "progressToken": "b",
      "total": 10.0
     }
    }
   ]
  },
  "validate": {
   "tool": "validate_layout",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "parts-1",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    },
    "layout_path": "out-a/layout.json"
   },
   "isError": false,
   "body": {
    "metrics": {
     "full_stock_area": 240000.0,
     "last_sheet_id": "sheet-0",
     "last_sheet_used_height": 92.04464399999999,
     "material_area": 55226.78639999998,
     "normalized_material": 0.23011160999999994,
     "placed_area": 31523.65254087845,
     "placed_parts": 32,
     "placed_priority": 32.0,
     "requested_parts": 32,
     "sheets_used": 1,
     "trailing_offcut_area": 184773.21360000002,
     "utilization": 0.5708036732855863
    },
    "valid": true,
    "violation_count": 0,
    "violations": []
   },
   "elapsed_s": 0.009,
   "reply_bytes": 983,
   "notifications": 0,
   "notification_messages": []
  },
  "export": {
   "tool": "export_layout",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "parts-1",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    },
    "layout_path": "out-a/layout.json",
    "out_dir": "out-c"
   },
   "isError": false,
   "body": {
    "common_line": null,
    "files": [
     "out-c/sheet-0.svg",
     "out-c/sheet-0.dxf"
    ]
   },
   "elapsed_s": 0.01,
   "reply_bytes": 259,
   "notifications": 0,
   "notification_messages": []
  },
  "estimate": {
   "tool": "estimate_sheets",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "parts-1",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    }
   },
   "isError": false,
   "body": {
    "kind": "necessary lower bound, not a layout or feasibility guarantee",
    "largest_usable_sheet_mm2": 230100.0,
    "net_part_area_mm2": 31523.652499006832,
    "parts_fitting_no_sheet": [],
    "sheets_lower_bound": 1.0
   },
   "elapsed_s": 0.0,
   "reply_bytes": 521,
   "notifications": 0,
   "notification_messages": []
  },
  "refuse_outside": {
   "tool": "import_parts",
   "arguments": {
    "paths": [
     "../ws2-outside.svg"
    ],
    "library_path": "lib2.json"
   },
   "isError": true,
   "body": {
    "code": -32602,
    "message": "../ws2-outside.svg is outside the workspace <probe-dir>\\ws2; use a path inside it"
   },
   "elapsed_s": 0.0,
   "reply_bytes": 200,
   "notifications": 0,
   "notification_messages": []
  },
  "refuse_overwrite": {
   "tool": "nest",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "parts-1",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    },
    "time_budget_s": 10,
    "seed": 0,
    "out_dir": "out-a"
   },
   "isError": true,
   "body": {
    "code": -32602,
    "message": "<probe-dir>\\ws2\\out-a already exists and is not empty; choose a new out_dir"
   },
   "elapsed_s": 0.0,
   "reply_bytes": 196,
   "notifications": 0,
   "notification_messages": []
  },
  "refuse_unknown_id": {
   "tool": "nest",
   "arguments": {
    "library_path": "lib.json",
    "request": {
     "name": "Example parts on a CO2 laser bed",
     "parts": [
      {
       "id": "no-such-part",
       "quantity": 4
      },
      {
       "id": "parts-2",
       "quantity": 12,
       "rotations": {
        "kind": "free"
       }
      },
      {
       "id": "parts-3",
       "quantity": 6,
       "allow_mirror": true
      },
      {
       "id": "parts-4",
       "quantity": 10,
       "rotations": {
        "kind": "list",
        "degrees": [
         0,
         180
        ]
       }
      }
     ],
     "sheets": [
      {
       "width_mm": 600,
       "height_mm": 400,
       "margins_mm": {
        "left": 5,
        "right": 5,
        "bottom": 5,
        "top": 5
       }
      }
     ],
     "spacing_mm": 1.0,
     "edge_spacing_mm": 1.0
    },
    "time_budget_s": 10,
    "seed": 0,
    "out_dir": "out-d"
   },
   "isError": true,
   "body": {
    "code": -32602,
    "message": "unknown part id \"no-such-part\"; use one returned by import_parts"
   },
   "elapsed_s": 0.0,
   "reply_bytes": 129,
   "notifications": 0,
   "notification_messages": []
  }
 },
 "server": {
  "name": "nestbolt",
  "version": "0.1.0"
 },
 "protocolVersion": "2025-06-18",
 "instructions": "Nestbolt nests parts on fixed sheets for laser, CNC and fabric cutting. 1) import_parts with SVG/DXF or LightBurn paths inside the workspace (<probe-dir>\\ws2). 2) nest with the library_path, a request (parts by id with quantities, sheets in mm, spacing_mm) and time_budget_s. 3) Use the returned SVG/DXF or preserving LBRN2 files. validate_layout and export_layout work on layout files; estimate_sheets gives a lower bound only. Lengths are millimetres. Results always pass an independent geometry check.",
 "initialize_elapsed_s": 0.0,
 "tools": [
  "estimate_sheets",
  "export_layout",
  "import_parts",
  "nest",
  "validate_layout"
 ],
 "tools_list_bytes": 20752,
 "tools_list_elapsed_s": 0.001,
 "tools_list_reply": {
  "tools": [
   {
    "name": "estimate_sheets",
    "description": "A fast lower bound on sheets for planning and quotes: net part area divided by usable sheet area. Necessary, not sufficient: real layouts can need more sheets. Also flags parts that fit no sheet in any allowed rotation.",
    "inputSchema": {
     "$defs": {
      "Margins": {
       "additionalProperties": false,
       "properties": {
        "bottom": {
         "format": "double",
         "type": "number"
        },
        "left": {
         "format": "double",
         "type": "number"
        },
        "right": {
         "format": "double",
         "type": "number"
        },
        "top": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "left",
        "right",
        "bottom",
        "top"
       ],
       "type": "object"
      },
      "Mode": {
       "enum": [
        "all",
        "fill_area",
        "fill_priority"
       ],
       "type": "string"
      },
      "Options": {
       "additionalProperties": false,
       "properties": {
        "kerf_mm": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "kerf_mm"
       ],
       "type": "object"
      },
      "Polygon": {
       "additionalProperties": false,
       "properties": {
        "holes": {
         "default": [],
         "items": {
          "items": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "maxItems": 2,
           "minItems": 2,
           "type": "array"
          },
          "type": "array"
         },
         "type": "array"
        },
        "outer": {
         "items": {
          "items": {
           "format": "double",
           "type": "number"
          },
          "maxItems": 2,
          "minItems": 2,
          "type": "array"
         },
         "type": "array"
        }
       },
       "required": [
        "outer"
       ],
       "type": "object"
      },
      "Request": {
       "additionalProperties": false,
       "description": "What to nest. Lengths are millimetres.",
       "properties": {
        "common_line": {
         "anyOf": [
          {
           "$ref": "#/$defs/Options"
          },
          {
           "type": "null"
          }
         ],
         "description": "Optional compensated common-line cutting. Its kerf replaces part spacing."
        },
        "edge_spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts and the sheet edge or a defect.",
         "format": "double",
         "type": "number"
        },
        "mode": {
         "$ref": "#/$defs/Mode",
         "default": "all"
        },
        "name": {
         "type": [
          "string",
          "null"
         ]
        },
        "parts": {
         "default": [],
         "description": "Parts to place; all library parts with default settings when empty.",
         "items": {
          "$ref": "#/$defs/RequestPart"
         },
         "type": "array"
        },
        "sheets": {
         "items": {
          "$ref": "#/$defs/RequestSheet"
         },
         "type": "array"
        },
        "spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts (kerf plus margin).",
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "sheets"
       ],
       "type": "object"
      },
      "RequestPart": {
       "additionalProperties": false,
       "properties": {
        "allow_mirror": {
         "default": false,
         "type": "boolean"
        },
        "id": {
         "description": "A library part id.",
         "type": "string"
        },
        "priority": {
         "default": 1.0,
         "format": "double",
         "type": "number"
        },
        "quantity": {
         "default": 1,
         "format": "uint32",
         "minimum": 0,
         "type": "integer"
        },
        "rotations": {
         "$ref": "#/$defs/Rotations",
         "default": {
          "degrees": [
           0.0,
           90.0,
           180.0,
           270.0
          ],
          "kind": "list"
         }
        }
       },
       "required": [
        "id"
       ],
       "type": "object"
      },
      "RequestSheet": {
       "additionalProperties": false,
       "properties": {
        "count": {
         "description": "Available sheets of this size; absent means unlimited.",
         "format": "uint32",
         "minimum": 0,
         "type": [
          "integer",
          "null"
         ]
        },
        "defects_mm": {
         "default": [],
         "description": "Areas that must stay clear (knots, damage, clamps), in sheet coordinates.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "from_import": {
         "default": null,
         "description": "An imported stock-outline id from Library.sheet_outlines. Omit dimensions\nto use its measured size, or supply those same dimensions explicitly.",
         "type": [
          "string",
          "null"
         ]
        },
        "height_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        },
        "id": {
         "type": [
          "string",
          "null"
         ]
        },
        "margins_mm": {
         "$ref": "#/$defs/Margins",
         "default": {
          "bottom": 0.0,
          "left": 0.0,
          "right": 0.0,
          "top": 0.0
         }
        },
        "outline_mm": {
         "default": [],
         "description": "A remnant's usable outline inside its width × height; empty means the\nwhole rectangle.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "outline_tolerance_mm": {
         "default": 0.0,
         "description": "Curve-to-polygon error of an imported stock outline. Edge clearance is\nincreased by this error as well as the part-library curve tolerance.",
         "format": "double",
         "type": "number"
        },
        "width_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        }
       },
       "type": "object"
      },
      "Rotations": {
       "oneOf": [
        {
         "additionalProperties": false,
         "properties": {
          "kind": {
           "const": "free",
           "type": "string"
          }
         },
         "required": [
          "kind"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "format": "double",
           "type": "number"
          },
          "kind": {
           "const": "step",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "type": "array"
          },
          "kind": {
           "const": "list",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        }
       ]
      }
     },
     "$schema": "https://json-schema.org/draft/2020-12/schema",
     "properties": {
      "library_path": {
       "type": "string"
      },
      "request": {
       "$ref": "#/$defs/Request"
      }
     },
     "required": [
      "library_path",
      "request"
     ],
     "type": "object"
    }
   },
   {
    "name": "export_layout",
    "description": "Write per-sheet SVG/DXF or preserving LBRN2 for a valid layout, transforming the original curves (arcs and splines stay curves). Refuses invalid layouts.",
    "inputSchema": {
     "$defs": {
      "Margins": {
       "additionalProperties": false,
       "properties": {
        "bottom": {
         "format": "double",
         "type": "number"
        },
        "left": {
         "format": "double",
         "type": "number"
        },
        "right": {
         "format": "double",
         "type": "number"
        },
        "top": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "left",
        "right",
        "bottom",
        "top"
       ],
       "type": "object"
      },
      "Mode": {
       "enum": [
        "all",
        "fill_area",
        "fill_priority"
       ],
       "type": "string"
      },
      "Options": {
       "additionalProperties": false,
       "properties": {
        "kerf_mm": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "kerf_mm"
       ],
       "type": "object"
      },
      "Polygon": {
       "additionalProperties": false,
       "properties": {
        "holes": {
         "default": [],
         "items": {
          "items": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "maxItems": 2,
           "minItems": 2,
           "type": "array"
          },
          "type": "array"
         },
         "type": "array"
        },
        "outer": {
         "items": {
          "items": {
           "format": "double",
           "type": "number"
          },
          "maxItems": 2,
          "minItems": 2,
          "type": "array"
         },
         "type": "array"
        }
       },
       "required": [
        "outer"
       ],
       "type": "object"
      },
      "Request": {
       "additionalProperties": false,
       "description": "What to nest. Lengths are millimetres.",
       "properties": {
        "common_line": {
         "anyOf": [
          {
           "$ref": "#/$defs/Options"
          },
          {
           "type": "null"
          }
         ],
         "description": "Optional compensated common-line cutting. Its kerf replaces part spacing."
        },
        "edge_spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts and the sheet edge or a defect.",
         "format": "double",
         "type": "number"
        },
        "mode": {
         "$ref": "#/$defs/Mode",
         "default": "all"
        },
        "name": {
         "type": [
          "string",
          "null"
         ]
        },
        "parts": {
         "default": [],
         "description": "Parts to place; all library parts with default settings when empty.",
         "items": {
          "$ref": "#/$defs/RequestPart"
         },
         "type": "array"
        },
        "sheets": {
         "items": {
          "$ref": "#/$defs/RequestSheet"
         },
         "type": "array"
        },
        "spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts (kerf plus margin).",
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "sheets"
       ],
       "type": "object"
      },
      "RequestPart": {
       "additionalProperties": false,
       "properties": {
        "allow_mirror": {
         "default": false,
         "type": "boolean"
        },
        "id": {
         "description": "A library part id.",
         "type": "string"
        },
        "priority": {
         "default": 1.0,
         "format": "double",
         "type": "number"
        },
        "quantity": {
         "default": 1,
         "format": "uint32",
         "minimum": 0,
         "type": "integer"
        },
        "rotations": {
         "$ref": "#/$defs/Rotations",
         "default": {
          "degrees": [
           0.0,
           90.0,
           180.0,
           270.0
          ],
          "kind": "list"
         }
        }
       },
       "required": [
        "id"
       ],
       "type": "object"
      },
      "RequestSheet": {
       "additionalProperties": false,
       "properties": {
        "count": {
         "description": "Available sheets of this size; absent means unlimited.",
         "format": "uint32",
         "minimum": 0,
         "type": [
          "integer",
          "null"
         ]
        },
        "defects_mm": {
         "default": [],
         "description": "Areas that must stay clear (knots, damage, clamps), in sheet coordinates.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "from_import": {
         "default": null,
         "description": "An imported stock-outline id from Library.sheet_outlines. Omit dimensions\nto use its measured size, or supply those same dimensions explicitly.",
         "type": [
          "string",
          "null"
         ]
        },
        "height_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        },
        "id": {
         "type": [
          "string",
          "null"
         ]
        },
        "margins_mm": {
         "$ref": "#/$defs/Margins",
         "default": {
          "bottom": 0.0,
          "left": 0.0,
          "right": 0.0,
          "top": 0.0
         }
        },
        "outline_mm": {
         "default": [],
         "description": "A remnant's usable outline inside its width × height; empty means the\nwhole rectangle.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "outline_tolerance_mm": {
         "default": 0.0,
         "description": "Curve-to-polygon error of an imported stock outline. Edge clearance is\nincreased by this error as well as the part-library curve tolerance.",
         "format": "double",
         "type": "number"
        },
        "width_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        }
       },
       "type": "object"
      },
      "Rotations": {
       "oneOf": [
        {
         "additionalProperties": false,
         "properties": {
          "kind": {
           "const": "free",
           "type": "string"
          }
         },
         "required": [
          "kind"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "format": "double",
           "type": "number"
          },
          "kind": {
           "const": "step",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "type": "array"
          },
          "kind": {
           "const": "list",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        }
       ]
      }
     },
     "$schema": "https://json-schema.org/draft/2020-12/schema",
     "properties": {
      "format": {
       "description": "Optional svg, dxf or lbrn2; omit to use the source format default.",
       "type": [
        "string",
        "null"
       ]
      },
      "layout_path": {
       "type": "string"
      },
      "library_path": {
       "type": "string"
      },
      "out_dir": {
       "description": "New output directory; preserving .lbrn2 for LightBurn, SVG/DXF otherwise.",
       "type": "string"
      },
      "request": {
       "$ref": "#/$defs/Request"
      },
      "sheet_outline": {
       "description": "Draw sheet boundaries (default true for LightBurn, false for SVG/DXF).",
       "type": [
        "boolean",
        "null"
       ]
      }
     },
     "required": [
      "library_path",
      "request",
      "layout_path",
      "out_dir"
     ],
     "type": "object"
    }
   },
   {
    "name": "import_parts",
    "description": "Import SVG/DXF outlines or one LightBurn lbrn2/lbrn project into a part library (mm). LightBurn groups stay rigid and original artwork/settings are retained for lbrn2 export. Writes the library to a file and returns part ids, areas, bounds, layer kerf and import warnings. Use the ids in nest requests.",
    "inputSchema": {
     "$schema": "https://json-schema.org/draft/2020-12/schema",
     "properties": {
      "close_gaps_mm": {
       "description": "Explicitly close gaps up to this many mm (off by default, maximum 1).",
       "format": "double",
       "type": [
        "number",
        "null"
       ]
      },
      "colors": {
       "description": "DXF ACI numbers as strings (e.g. \"7\") or RGB colours (e.g. \"#000000\").",
       "items": {
        "type": "string"
       },
       "type": [
        "array",
        "null"
       ]
      },
      "dxf_unit_mm": {
       "description": "Millimetres per DXF unit when `$INSUNITS` is missing (default 1).",
       "format": "double",
       "type": [
        "number",
        "null"
       ]
      },
      "layers": {
       "description": "Cut layer names; omit to prefer cut/outline/profile, then all closed contours.",
       "items": {
        "type": "string"
       },
       "type": [
        "array",
        "null"
       ]
      },
      "library_path": {
       "description": "Where to write the part library JSON; a new file under `nestbolt/` by default.",
       "type": [
        "string",
        "null"
       ]
      },
      "paths": {
       "description": "SVG/DXF files or one .lbrn/.lbrn2 project, inside the workspace.",
       "items": {
        "type": "string"
       },
       "type": "array"
      },
      "sheet_layers": {
       "description": "Stock-outline layers offered separately from parts (defaults to SHEET).",
       "items": {
        "type": "string"
       },
       "type": [
        "array",
        "null"
       ]
      },
      "svg_user_unit_mm": {
       "description": "Millimetres per SVG user unit when a document has no absolute size (default 25.4/96).",
       "format": "double",
       "type": [
        "number",
        "null"
       ]
      },
      "tolerance_mm": {
       "description": "Maximum distance between exact curves and nesting polygons, in mm (default 0.005).",
       "format": "double",
       "type": [
        "number",
        "null"
       ]
      }
     },
     "required": [
      "paths"
     ],
     "type": "object"
    }
   },
   {
    "name": "nest",
    "description": "Nest library parts on fixed sheets with a repeatable budget (time_budget_s, at most 300). Writes job.json, layout.json, report.json and one SVG and DXF per sheet (preserving LBRN2 for LightBurn); returns the independently checked metrics. Sends progress notifications.",
    "inputSchema": {
     "$defs": {
      "Margins": {
       "additionalProperties": false,
       "properties": {
        "bottom": {
         "format": "double",
         "type": "number"
        },
        "left": {
         "format": "double",
         "type": "number"
        },
        "right": {
         "format": "double",
         "type": "number"
        },
        "top": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "left",
        "right",
        "bottom",
        "top"
       ],
       "type": "object"
      },
      "Mode": {
       "enum": [
        "all",
        "fill_area",
        "fill_priority"
       ],
       "type": "string"
      },
      "Options": {
       "additionalProperties": false,
       "properties": {
        "kerf_mm": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "kerf_mm"
       ],
       "type": "object"
      },
      "Polygon": {
       "additionalProperties": false,
       "properties": {
        "holes": {
         "default": [],
         "items": {
          "items": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "maxItems": 2,
           "minItems": 2,
           "type": "array"
          },
          "type": "array"
         },
         "type": "array"
        },
        "outer": {
         "items": {
          "items": {
           "format": "double",
           "type": "number"
          },
          "maxItems": 2,
          "minItems": 2,
          "type": "array"
         },
         "type": "array"
        }
       },
       "required": [
        "outer"
       ],
       "type": "object"
      },
      "Request": {
       "additionalProperties": false,
       "description": "What to nest. Lengths are millimetres.",
       "properties": {
        "common_line": {
         "anyOf": [
          {
           "$ref": "#/$defs/Options"
          },
          {
           "type": "null"
          }
         ],
         "description": "Optional compensated common-line cutting. Its kerf replaces part spacing."
        },
        "edge_spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts and the sheet edge or a defect.",
         "format": "double",
         "type": "number"
        },
        "mode": {
         "$ref": "#/$defs/Mode",
         "default": "all"
        },
        "name": {
         "type": [
          "string",
          "null"
         ]
        },
        "parts": {
         "default": [],
         "description": "Parts to place; all library parts with default settings when empty.",
         "items": {
          "$ref": "#/$defs/RequestPart"
         },
         "type": "array"
        },
        "sheets": {
         "items": {
          "$ref": "#/$defs/RequestSheet"
         },
         "type": "array"
        },
        "spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts (kerf plus margin).",
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "sheets"
       ],
       "type": "object"
      },
      "RequestPart": {
       "additionalProperties": false,
       "properties": {
        "allow_mirror": {
         "default": false,
         "type": "boolean"
        },
        "id": {
         "description": "A library part id.",
         "type": "string"
        },
        "priority": {
         "default": 1.0,
         "format": "double",
         "type": "number"
        },
        "quantity": {
         "default": 1,
         "format": "uint32",
         "minimum": 0,
         "type": "integer"
        },
        "rotations": {
         "$ref": "#/$defs/Rotations",
         "default": {
          "degrees": [
           0.0,
           90.0,
           180.0,
           270.0
          ],
          "kind": "list"
         }
        }
       },
       "required": [
        "id"
       ],
       "type": "object"
      },
      "RequestSheet": {
       "additionalProperties": false,
       "properties": {
        "count": {
         "description": "Available sheets of this size; absent means unlimited.",
         "format": "uint32",
         "minimum": 0,
         "type": [
          "integer",
          "null"
         ]
        },
        "defects_mm": {
         "default": [],
         "description": "Areas that must stay clear (knots, damage, clamps), in sheet coordinates.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "from_import": {
         "default": null,
         "description": "An imported stock-outline id from Library.sheet_outlines. Omit dimensions\nto use its measured size, or supply those same dimensions explicitly.",
         "type": [
          "string",
          "null"
         ]
        },
        "height_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        },
        "id": {
         "type": [
          "string",
          "null"
         ]
        },
        "margins_mm": {
         "$ref": "#/$defs/Margins",
         "default": {
          "bottom": 0.0,
          "left": 0.0,
          "right": 0.0,
          "top": 0.0
         }
        },
        "outline_mm": {
         "default": [],
         "description": "A remnant's usable outline inside its width × height; empty means the\nwhole rectangle.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "outline_tolerance_mm": {
         "default": 0.0,
         "description": "Curve-to-polygon error of an imported stock outline. Edge clearance is\nincreased by this error as well as the part-library curve tolerance.",
         "format": "double",
         "type": "number"
        },
        "width_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        }
       },
       "type": "object"
      },
      "Rotations": {
       "oneOf": [
        {
         "additionalProperties": false,
         "properties": {
          "kind": {
           "const": "free",
           "type": "string"
          }
         },
         "required": [
          "kind"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "format": "double",
           "type": "number"
          },
          "kind": {
           "const": "step",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "type": "array"
          },
          "kind": {
           "const": "list",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        }
       ]
      }
     },
     "$schema": "https://json-schema.org/draft/2020-12/schema",
     "properties": {
      "library_path": {
       "description": "A library written by `import_parts`.",
       "type": "string"
      },
      "out_dir": {
       "description": "New output directory; `nestbolt/runs/<name>` by default.",
       "type": [
        "string",
        "null"
       ]
      },
      "request": {
       "$ref": "#/$defs/Request",
       "description": "Parts (ids from `import_parts`, quantities, rotations), sheets and spacing, in mm."
      },
      "seed": {
       "description": "Random seed (default 0). The same inputs, budget and seed repeat exactly.",
       "format": "uint64",
       "minimum": 0,
       "type": [
        "integer",
        "null"
       ]
      },
      "time_budget_s": {
       "description": "Search budget in seconds, 1 to 300 (default 10). Also the hard real-time limit.",
       "format": "double",
       "type": [
        "number",
        "null"
       ]
      }
     },
     "required": [
      "library_path",
      "request"
     ],
     "type": "object"
    }
   },
   {
    "name": "validate_layout",
    "description": "Check a layout file against the library parts, sheets and spacing of a request with the independent validator; returns validity, violations and material metrics.",
    "inputSchema": {
     "$defs": {
      "Margins": {
       "additionalProperties": false,
       "properties": {
        "bottom": {
         "format": "double",
         "type": "number"
        },
        "left": {
         "format": "double",
         "type": "number"
        },
        "right": {
         "format": "double",
         "type": "number"
        },
        "top": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "left",
        "right",
        "bottom",
        "top"
       ],
       "type": "object"
      },
      "Mode": {
       "enum": [
        "all",
        "fill_area",
        "fill_priority"
       ],
       "type": "string"
      },
      "Options": {
       "additionalProperties": false,
       "properties": {
        "kerf_mm": {
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "kerf_mm"
       ],
       "type": "object"
      },
      "Polygon": {
       "additionalProperties": false,
       "properties": {
        "holes": {
         "default": [],
         "items": {
          "items": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "maxItems": 2,
           "minItems": 2,
           "type": "array"
          },
          "type": "array"
         },
         "type": "array"
        },
        "outer": {
         "items": {
          "items": {
           "format": "double",
           "type": "number"
          },
          "maxItems": 2,
          "minItems": 2,
          "type": "array"
         },
         "type": "array"
        }
       },
       "required": [
        "outer"
       ],
       "type": "object"
      },
      "Request": {
       "additionalProperties": false,
       "description": "What to nest. Lengths are millimetres.",
       "properties": {
        "common_line": {
         "anyOf": [
          {
           "$ref": "#/$defs/Options"
          },
          {
           "type": "null"
          }
         ],
         "description": "Optional compensated common-line cutting. Its kerf replaces part spacing."
        },
        "edge_spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts and the sheet edge or a defect.",
         "format": "double",
         "type": "number"
        },
        "mode": {
         "$ref": "#/$defs/Mode",
         "default": "all"
        },
        "name": {
         "type": [
          "string",
          "null"
         ]
        },
        "parts": {
         "default": [],
         "description": "Parts to place; all library parts with default settings when empty.",
         "items": {
          "$ref": "#/$defs/RequestPart"
         },
         "type": "array"
        },
        "sheets": {
         "items": {
          "$ref": "#/$defs/RequestSheet"
         },
         "type": "array"
        },
        "spacing_mm": {
         "default": 0.0,
         "description": "Minimum gap between parts (kerf plus margin).",
         "format": "double",
         "type": "number"
        }
       },
       "required": [
        "sheets"
       ],
       "type": "object"
      },
      "RequestPart": {
       "additionalProperties": false,
       "properties": {
        "allow_mirror": {
         "default": false,
         "type": "boolean"
        },
        "id": {
         "description": "A library part id.",
         "type": "string"
        },
        "priority": {
         "default": 1.0,
         "format": "double",
         "type": "number"
        },
        "quantity": {
         "default": 1,
         "format": "uint32",
         "minimum": 0,
         "type": "integer"
        },
        "rotations": {
         "$ref": "#/$defs/Rotations",
         "default": {
          "degrees": [
           0.0,
           90.0,
           180.0,
           270.0
          ],
          "kind": "list"
         }
        }
       },
       "required": [
        "id"
       ],
       "type": "object"
      },
      "RequestSheet": {
       "additionalProperties": false,
       "properties": {
        "count": {
         "description": "Available sheets of this size; absent means unlimited.",
         "format": "uint32",
         "minimum": 0,
         "type": [
          "integer",
          "null"
         ]
        },
        "defects_mm": {
         "default": [],
         "description": "Areas that must stay clear (knots, damage, clamps), in sheet coordinates.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "from_import": {
         "default": null,
         "description": "An imported stock-outline id from Library.sheet_outlines. Omit dimensions\nto use its measured size, or supply those same dimensions explicitly.",
         "type": [
          "string",
          "null"
         ]
        },
        "height_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        },
        "id": {
         "type": [
          "string",
          "null"
         ]
        },
        "margins_mm": {
         "$ref": "#/$defs/Margins",
         "default": {
          "bottom": 0.0,
          "left": 0.0,
          "right": 0.0,
          "top": 0.0
         }
        },
        "outline_mm": {
         "default": [],
         "description": "A remnant's usable outline inside its width × height; empty means the\nwhole rectangle.",
         "items": {
          "$ref": "#/$defs/Polygon"
         },
         "type": "array"
        },
        "outline_tolerance_mm": {
         "default": 0.0,
         "description": "Curve-to-polygon error of an imported stock outline. Edge clearance is\nincreased by this error as well as the part-library curve tolerance.",
         "format": "double",
         "type": "number"
        },
        "width_mm": {
         "default": 0.0,
         "format": "double",
         "type": "number"
        }
       },
       "type": "object"
      },
      "Rotations": {
       "oneOf": [
        {
         "additionalProperties": false,
         "properties": {
          "kind": {
           "const": "free",
           "type": "string"
          }
         },
         "required": [
          "kind"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "format": "double",
           "type": "number"
          },
          "kind": {
           "const": "step",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        },
        {
         "additionalProperties": false,
         "properties": {
          "degrees": {
           "items": {
            "format": "double",
            "type": "number"
           },
           "type": "array"
          },
          "kind": {
           "const": "list",
           "type": "string"
          }
         },
         "required": [
          "kind",
          "degrees"
         ],
         "type": "object"
        }
       ]
      }
     },
     "$schema": "https://json-schema.org/draft/2020-12/schema",
     "properties": {
      "layout_path": {
       "description": "A layout JSON file, for example `layout.json` written by `nest`.",
       "type": "string"
      },
      "library_path": {
       "type": "string"
      },
      "request": {
       "$ref": "#/$defs/Request"
      }
     },
     "required": [
      "library_path",
      "request",
      "layout_path"
     ],
     "type": "object"
    }
   }
  ]
 },
 "files": {
  "out-a": {
   "job.json": "fca69bd2a3ad15dfd4abce39ea65cdcf903aea5002bcfaa789f7880236ffd057",
   "layout.json": "7fc2ed6234fa674194ad68147d37b2c88efab3ad8494c10163cc533d795c83f4",
   "report.json": "986a863eb95a7443f0b57c687a91970e3e7e0668006adfc5cd04e3743ef4f250",
   "sheet-0.dxf": "d3bd5c31f6568fa19a7dbe330512f7300fabf1b91b3297efbf9975244b091e38",
   "sheet-0.svg": "8727f9b903884b36ec160f4692f6725849c9f47f522d684cde7af80dcf58a12d"
  },
  "out-b": {
   "job.json": "fca69bd2a3ad15dfd4abce39ea65cdcf903aea5002bcfaa789f7880236ffd057",
   "layout.json": "7fc2ed6234fa674194ad68147d37b2c88efab3ad8494c10163cc533d795c83f4",
   "report.json": "311394c65d0db786f7379351a0a725365cb5ff9318a66b4313c51aa8dff7486c",
   "sheet-0.dxf": "d3bd5c31f6568fa19a7dbe330512f7300fabf1b91b3297efbf9975244b091e38",
   "sheet-0.svg": "8727f9b903884b36ec160f4692f6725849c9f47f522d684cde7af80dcf58a12d"
  },
  "out-c": {
   "sheet-0.dxf": "d3bd5c31f6568fa19a7dbe330512f7300fabf1b91b3297efbf9975244b091e38",
   "sheet-0.svg": "8727f9b903884b36ec160f4692f6725849c9f47f522d684cde7af80dcf58a12d"
  }
 },
 "layout_a_equals_b": true,
 "stderr_tail": []
}
