Files
CableGUI/internal
mAi 813d59b068 feat(v5 slice 6): export clamps + cable mid-vertices to mxdrw
Excalidraw scene now mirrors the v5 routing model:

- Clamps export as 12×12 grey rounded squares (BackgroundColor=#888888,
  StrokeColor=#555555, Roundness type 3). Distinct from the red IO
  marker diamonds so wall outlets vs. routing anchors stay readable.
  Frame_id propagates into the element's FrameID per the existing
  pattern.
- Cable arrows include clamp positions as mid-vertices in the
  `points` array. Pre-grouped + sort.Slice-sorted by ord; each
  mid-vertex is added as an (x-fromAnchor.x, y-fromAnchor.y) offset.
  startBinding / endBinding still point at the from / to endpoint
  excalidraw_ids; mid-vertices are unbound (Excalidraw doesn't have
  per-vertex binding).
- IDAssignment grows a Clamps map; PersistExcalidrawIDs accepts it
  and updates clamps.excalidraw_id on first export so re-exports
  reuse the same element ids (collab cursors / undo history survive).
- Bundle-stripe overlay is **viewer-only** — Excalidraw can't
  represent gradient strokes losslessly, so we export individual
  cable arrows and let the in-app viewer derive the bundle viz.

Tests:
- TestBuildScene_ClampsRenderAsRectangles — 2 clamps → 2 rectangle
  elements + 2 ids in IDAssignment.Clamps.
- TestBuildScene_ArrowPointsIncludeClamps — cable with 1 clamp →
  arrow.Points has 3 entries; middle vertex equals the clamp's
  position relative to fromAnchor.

This closes the v5 slice plan (§11.10). Six slices, one branch,
one redeploy below.
2026-05-16 13:58:32 +02:00
..