One change list for every Layer X tool that proposes a change: Set point, Hardware, Injector holes.
A tool's answer is a list of changes a person can act on, each saying what moves, from what to
what, on which part of the drawing or the design, where the new number comes from, and what it
costs to make (``cad_impact``). One record per change::
{"component": "SV-LOX-PRESS", "pid_node_id": "SV_LOX_PRESS", "field": "Cv",
"before": 1.7, "after": 3.8, "unit": "Cv",
"provenance": "catalog row vent-solenoid-cv3.8 (estimated): ...",
"effect": {"mean_thrust_N": +41.2, "of_mean": -0.0011, ...},
"cad_impact": "new part",
# and, beyond the required keys:
"target": "node:SV_LOX_PRESS", "domain": "drawing", "label": "...", "source": "estimated",
"before_provenance": "...", "catalog": {...} | None, "drill": {...} | None, "note": "..."}
``target`` says where the number lives, and with it which way the change is written:
* ``node:<id>`` / ``edge:<id>`` (domain ``drawing``): a drawing parameter. Never written over the
drawing: :func:`pid_designer_export` gives a patched copy for pid-designer ("You own the drawing.
We own what it does", docs/integration/pid-to-feedtwin-handoff.md).
* ``design:<dotted path>`` (domain ``design``): the engine config. Written only on confirmation,
through ``PUT /api/config?expect_sha256=`` (backend/routers/config.py), which refuses with 409 when
the live design is no longer the one the change was computed for (:func:`design_write`).
* ``op:<name>`` (domain ``operation``): a stand setting (dome dial, lockup, fill). Nothing is
written; :func:`settings_patch` fills the Layer X rail.
* ``model:<dotted path>`` (domain ``model``): a fitted model number, not a part (the feed K0).
``effect`` is the change in each graded figure, after minus before, from the *verifying burn* of the
whole list. With more than one change it is the list's combined effect, said so in
``effect_basis``: separating them needs a burn per change, which no tool here pays for.
pid-designer has no import endpoint (lib/stardesign/stardesign/documents.py: create takes a name
only). Its payload is the graph itself, ``{"nodes": [...], "edges": [...]}``, which ``copy`` then
``autosave`` accept; :func:`pid_designer_export` returns that graph, patched, with the steps.