{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/arcnm-io/json-schema/arcnm-io-calculation-tuning-update-schema.json",
  "title": "CalculationTuningUpdate",
  "description": "One meaning for ``null`` on every field: *no statement*.\n\nEvery knob below is ``number | null`` with a null default, so a\nclient that serialises its whole model — or a model asked to fill a\ntool's arguments — sends nulls for the knobs it has nothing to say\nabout. That must never be a write. Clearing a knob, so that it reads\nwhat it inherits again — a parent environment's statement, else the\nplatform default — is therefore its own named gesture, ``reset``, and\nnever a value (or the absence of one) in the knob's own field.",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/arcnm-io-openapi.yml#/components/schemas/CalculationTuningUpdate",
  "properties": {
    "learning_rate": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.5
        },
        {
          "type": "null"
        }
      ],
      "title": "Learning Rate",
      "description": "Wright rate in [0.5, 1.0]; 1.0 disables learning. Omit or send null to keep it; name it in \"reset\" to return it to the platform default."
    },
    "setup_factor": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 4.0,
          "minimum": 0.25
        },
        {
          "type": "null"
        }
      ],
      "title": "Setup Factor",
      "description": "Setup-time multiplier; omit or send null to keep, 1.0 (its identity) or \"reset\" to clear it back to inherit / platform default."
    },
    "programming_factor": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 4.0,
          "minimum": 0.25
        },
        {
          "type": "null"
        }
      ],
      "title": "Programming Factor",
      "description": "Programming-time multiplier; omit or send null to keep, 1.0 (its identity) or \"reset\" to clear it back to inherit / platform default."
    },
    "cycle_factor": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 4.0,
          "minimum": 0.25
        },
        {
          "type": "null"
        }
      ],
      "title": "Cycle Factor",
      "description": "Multiplier on the whole per-unit run time — cutting, air moves, peck retract, tool changes and load/unload; omit or send null to keep, 1.0 (its identity) or \"reset\" to clear it back to inherit / platform default."
    },
    "verteilzeit_pct": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 0.5,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Verteilzeit Pct",
      "description": "Distribution allowance as a fraction of the run base time (0.10 = 10 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default. 0 is a statable allowance, not a reset."
    },
    "erholzeit_pct": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 0.5,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Erholzeit Pct",
      "description": "Recovery allowance on the RUN base time, as a fraction (0.045 = 4.5 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "ruestverteilzeit_pct": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 0.5,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Ruestverteilzeit Pct",
      "description": "Distribution allowance on setup as a fraction of the setup base time (0.10 = 10 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "ruesterholzeit_pct": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 0.5,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Ruesterholzeit Pct",
      "description": "Recovery allowance on the SETUP base time, as a fraction (0.045 = 4.5 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "edge_margin_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 100.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Edge Margin Mm",
      "description": "Edge margin kept to every side of a purchased sheet, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default. 0 is a statement, not a reset."
    },
    "skeleton_web_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 50.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Skeleton Web Mm",
      "description": "Web between two nested parts WITHOUT the cutting gap, mm — the cutter's kerf is added to it; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "remnant_min_l_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 6000.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Remnant Min L Mm",
      "description": "Longer side a reusable remnant needs, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "remnant_min_w_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 6000.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Remnant Min W Mm",
      "description": "Shorter side a reusable remnant needs, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "remnant_min_area_share": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Remnant Min Area Share",
      "description": "Area a reusable remnant needs, as a fraction of the purchased sheet's (0.05 = 5 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "remnant_value_factor": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Remnant Value Factor",
      "description": "What a reusable remnant is worth against new stock of its kind, as a fraction of its price per kg (0.8 = 80 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "full_stock_threshold": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.5
        },
        {
          "type": "null"
        }
      ],
      "title": "Full Stock Threshold",
      "description": "The fill of a started stock piece from which a lot pays it whole, as a fraction of the parts it holds (0.85 = 85 %; 1.0 turns the rule off); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "cut_to_size_increment_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1000.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Cut To Size Increment Mm",
      "description": "Step a plate ordered cut to size is bought in, mm — each side rounds up to a multiple of it, 0 buys the exact size; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "custom_format_surcharge_pct": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Custom Format Surcharge Pct",
      "description": "Premium a sheet cut to an ordered size carries on its metal, as a fraction of the metal's price (0.15 = 15 %); omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "bar_length_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 12000.0,
          "minimum": 100.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Bar Length Mm",
      "description": "Length the round bar a turned part is cut from is bought in, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "bar_clamp_remnant_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 1000.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Bar Clamp Remnant Mm",
      "description": "End of each bar the clamp holds and no part is cut from, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "bar_remnant_min_l_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 6000.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Bar Remnant Min L Mm",
      "description": "Shortest bar or tube end that counts as a reusable remnant, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "min_web_mm_to_3mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 50.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Min Web Mm To 3Mm",
      "description": "Minimum web for sheet up to 3 mm, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "min_web_mm_to_6mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 50.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Min Web Mm To 6Mm",
      "description": "Minimum web for sheet over 3 up to 6 mm, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "min_web_mm_to_12mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 50.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Min Web Mm To 12Mm",
      "description": "Minimum web for plate over 6 up to 12 mm, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "min_web_mm_over_12mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 50.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Min Web Mm Over 12Mm",
      "description": "Minimum web for plate over 12 mm, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "micro_joint_width_mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 5.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Micro Joint Width Mm",
      "description": "Micro-joint width, mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "micro_joints_to_300mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 20.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Micro Joints To 300Mm",
      "description": "Micro-joints per part with an outline up to 300 mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "micro_joints_to_1000mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 20.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Micro Joints To 1000Mm",
      "description": "Micro-joints per part with an outline over 300 up to 1000 mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "micro_joints_over_1000mm": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 20.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Micro Joints Over 1000Mm",
      "description": "Micro-joints per part with an outline over 1000 mm; omit or send null to keep, \"reset\" to clear it back to inherit / platform default."
    },
    "reset": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "title": "Reset",
      "description": "Knobs to clear on this environment, by name — learning_rate, setup_factor, programming_factor, cycle_factor, verteilzeit_pct, erholzeit_pct, ruestverteilzeit_pct, ruesterholzeit_pct, edge_margin_mm, skeleton_web_mm, remnant_min_l_mm, remnant_min_w_mm, remnant_min_area_share, remnant_value_factor, full_stock_threshold, cut_to_size_increment_mm, custom_format_surcharge_pct, bar_length_mm, bar_clamp_remnant_mm, bar_remnant_min_l_mm, min_web_mm_to_3mm, min_web_mm_to_6mm, min_web_mm_to_12mm, min_web_mm_over_12mm, micro_joint_width_mm, micro_joints_to_300mm, micro_joints_to_1000mm, micro_joints_over_1000mm. A cleared knob reads what a parent environment states, else the platform default; learning_rate is this environment's own and returns to the platform default. Clearing is a named gesture because a null in a knob's own field means 'no statement' and must never delete one. An unknown name is rejected."
    },
    "processes": {
      "anyOf": [
        {
          "additionalProperties": {
            "$ref": "#/$defs/ProcessTuningUpdate"
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "title": "Processes",
      "description": "Per-process factors, keyed by process (milling, turning, sawing, ...). Applied after the flat fields, so a flat value sets every process and a named one overrides it."
    },
    "inspection_tau_s_per_element": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 3600.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Inspection Tau S Per Element",
      "description": "Seconds to measure one characteristic; omit to keep, send null to clear your override."
    },
    "inspection_weight_gdt": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 100.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Inspection Weight Gdt",
      "description": "Effort weight of a geometric-tolerance characteristic; omit to keep, null to clear."
    },
    "inspection_weight_datum": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 100.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Inspection Weight Datum",
      "description": "Effort weight of a datum characteristic; omit to keep, null to clear."
    },
    "inspection_weight_ndt": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 100.0,
          "minimum": 0.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Inspection Weight Ndt",
      "description": "Effort weight of a non-destructive-testing callout; omit to keep, null to clear."
    }
  },
  "additionalProperties": false,
  "type": "object",
  "$defs": {
    "ProcessTuningUpdate": {
      "properties": {
        "setup_factor": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 4.0,
              "minimum": 0.25
            },
            {
              "type": "null"
            }
          ],
          "title": "Setup Factor",
          "description": "Setup-time multiplier for this process."
        },
        "programming_factor": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 4.0,
              "minimum": 0.25
            },
            {
              "type": "null"
            }
          ],
          "title": "Programming Factor",
          "description": "Programming-time multiplier for this process."
        },
        "cycle_factor": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 4.0,
              "minimum": 0.25
            },
            {
              "type": "null"
            }
          ],
          "title": "Cycle Factor",
          "description": "Run-time multiplier for this process."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "title": "ProcessTuningUpdate",
      "description": "One process's factors. Omit a field to keep it, send 1.0 to reset."
    }
  }
}