# 옮길 수 있는 SVG 심볼

> 안전한 Ganter 바인딩과 형식 있는 연결점을 갖춘 정적 SVG 심볼을 만들고 나누어 씁니다.

Ganter 심볼은 그림과 실시간 데이터를 따로 둡니다. 그림은 평범한 정적 SVG이고, 값 대응과 움직임은 모두 Ganter Lab이 가집니다. 그래서 가져온 파일은 스크립트도, 이벤트 처리기도, 안에 심어 둔 애니메이션 코드도, 네트워크 요청도 돌릴 수 없습니다. 이 페이지는 그것을 만드는 모델에 대한 완전한 참고 자료입니다. 심볼이 무엇을 선언하는지, 가져오기가 무엇을 받아들이고 무엇을 거부하는지, 그리고 심볼이 스테이션 사이를 어떻게 옮겨 다니는지입니다.

심볼은 자기 그림 위에 세 가지를 선언합니다.

- **가변 영역**: 이름이 붙은 입력(채움, 선, 움직임, 글자, 보임)이며, 나중에 놓인 [대시보드](home) 인스턴스가 Logic 주소나 고정된 값으로 그것을 먹입니다.
- **연결점**: 테두리에 놓인 형식 있는 연결 지점이며, 대시보드가 심볼 사이로 배관과 덕트와 배선과 축을 이어 갈 수 있게 합니다.
- **추천 항목**: 선택 사항이며, 다른 심볼과 어떻게 놓이는지를 자세로까지 밝힌 조합입니다.

## 시스템 심볼과 내 심볼 {#system-symbols-and-my-symbols}

카탈로그의 출처는 둘이며, 심볼이 나열되는 모든 곳에서 걸러 볼 수 있습니다.

| 출처 | 참조 | 무엇인가 |
| --- | --- | --- |
| 시스템 | `system:<stable-key>` | 앱과 함께 실리는 내장 라이브러리입니다. 안을 볼 수 있고 내보낼 수 있지만 그 자리에서 편집할 수는 없습니다. |
| 내 것 | `user:<guid>` | 사용자가 만들거나 가져오거나 복제한 심볼입니다. 편집하고 지울 수 있습니다. |

모든 시스템 심볼은 **내 심볼로 복제**를 내놓습니다. 복사본은 얼어붙은, 독립적으로 소유되는 사용자 자산이며(그림, 뷰 박스, 맞춤, 크기, 가변 영역, 종류 구성, 연결점, 제안이 함께 복사됩니다), 나중에 앱을 갱신하면서 원본이 바뀌어도 고른 그대로 동작합니다. 사용자 심볼을 지울 때는 확인을 묻고, 그것을 아직 참조하는 대시보드는 깨지는 대신 자리 표시를 보여 줍니다.

## 심볼을 만드는 방법 {#ways-to-create-a-symbol}

- **파일 가져오기**: **Logic > Assets > Symbols > 심볼 가져오기**는 평범한 `.svg`나 완전한 `.ganter-symbol.json` 패키지를 받습니다. 모든 가져오기는 자기 신원을 가진 **새** 자산을 만듭니다. 있던 심볼을 결코 덮어쓰지 않으며, 이름이 부딪히면 실패하는 대신 꼬리를 붙여 풉니다(" 2", " 3", …). 선택기는 **1 MB**가 넘는 파일을 바이트를 읽기 전에 거부합니다. 평범한 SVG를 가져온 뒤에는 안전하지 않은 항목을 몇 개나 없앴는지 앱이 알려 줍니다.
- **앱 안에서 만들기**: **새 사용자 심볼**은 이름, SVG 마크업, 대시보드 배치(맞춤과 처음 크기), 그리고 가변 영역을 위한 편집기를 엽니다. 심볼이 생긴 뒤에는 올바른 변경이 저절로 저장됩니다. 연결점의 좌표는 앱에서 일부러 편집할 수 **없습니다**. 형식 있는 연결점은 패키지로만 넣을 수 있고, 패키지가 정한 연결점은 나중에 편집해도 읽기 전용으로 그대로 남습니다.
- **AI에게 부탁하기**: 두 길이 똑같은 규약을 함께 씁니다. 내장 [MCP endpoint](agent)에서는 `symbol_validate` 도구가 가져오기를 시험 삼아 돌려 보고 `symbol_import`가 새 자산을 저장합니다. 둘 다 그 설명에 규약 전체를 담고 있습니다. 앱에 닿을 수 없는 바깥 대화에서는 심볼 패널의 **대화 지시문 복사**가 자족적인 지시문을 복사합니다. 돌아온 SVG나 패키지를 파일로 저장해 여기에서 가져오십시오.

둘레의 자산 작업 영역은 [Logic](logic)을 보십시오.

## 평범한 SVG 준비하기 {#prepare-a-plain-svg}

묶고 싶은 부분마다 변하지 않는 SVG `id`를 주십시오. 가져온 뒤에는 그 id가 가변 영역의 대상 선택기에 나타납니다. id와 가변 영역 이름은 하나의 문법을 함께 씁니다. 글자나 `_`로 시작해 글자와 숫자와 `_`와 `.`와 `:`와 `-`로 이어지며 최대 128자입니다.

선택 사항인 `data-ganter-*` 속성은 심볼이 담을 수 있는 유일한 Ganter 전용 마크업입니다.

| 속성 | 붙는 곳 | 선언하는 것 |
| --- | --- | --- |
| `data-ganter-pivot="x y"` | 묶을 수 있는 모든 요소 | rotate와 scale과 spin 가변 영역을 위한 정확한 회전 중심(뷰 박스 좌표)입니다. 그 세 갈래의 대상 요소에는 필수입니다. |
| `data-ganter-spin-ratio` | 도는 요소의 자식 | 눈에 보이는 자식 회전체의 상대 속도입니다. 유한하고 0이 아니며 크기가 최대 100입니다. 음수는 반대로 돕니다. 그 요소가 자기 회전 중심도 선언하지 않으면 걷어 냅니다. |
| `data-ganter-role` | 모든 요소 | 만드는 도구를 위한, 변하지 않는 의미 역할입니다. 알려 주는 뜻만 있습니다. |
| `data-ganter-fit-width` | `<text>` / `<tspan>` | Text 가변 영역을 위한, 원할 때만 켜는 폭 제한 읽기 표시입니다. 묶인 글자가 이 뷰 박스 단위보다 넓게 재어지면 글꼴이 맞도록 줄어듭니다. |
| `data-ganter-fit-min-font-size` | `<text>` / `<tspan>` | 맞춤이 줄일 수 있는 가장 작은 글꼴 크기입니다. 그보다 작아져야 한다면 요소는 대체 글자를 보여 주고, 값 전체는 접근성 이름과 도구 설명에 그대로 남습니다. |
| `data-ganter-fit-fallback` | `<text>` / `<tspan>` | 가장 작은 글꼴 크기로도 값이 들어가지 않을 때 보여 주는 글자입니다. |

연결점은 SVG 안에 살지 않으며 SVG 요소 id를 겨냥하지도 않습니다. `data-ganter-port`나 `data-ganter-port-*`라는 이름의 속성은 이 형식의 일부가 아닙니다. 평범한 SVG 가져오기는 그것을 걷어 내고, 그것을 담은 엄격한 패키지는 거부됩니다.

평범한 SVG 가져오기는 언제나 올바른 **보기 전용** 심볼을 내놓습니다. 연결점 0개, 가변 영역 0개입니다. 검사기는 역할과 종류와 바깥 방향과 내부 경로가 선언되지 않았기 때문에 이을 수 있는 연결점이 없다고 알립니다. Ganter는 파일 이름이나 범주나 그림에서 그 값을 추측하지 않으며, 내부 연결점 편집기나 경로 편집기를 열지도 않습니다.

## 정화기가 받아들이는 것 {#what-the-sanitizer-accepts}

같은 SVG 정책이 모든 길(파일 가져오기, 앱 안 편집기, MCP, 패키지)에 적용됩니다. 이 정책은 일부러 SVG보다 좁습니다.

- **남기는 것**: 동작이 없는 기하와 구조입니다. `svg`, `g`, `defs`, `symbol`, `use`, `path`, `rect`, `circle`, `ellipse`, `line`, `polyline`, `polygon`, `text`, `tspan`, `title`, `desc`, `clipPath`, `mask`, `linearGradient`, `radialGradient`, `stop`, `pattern`, `marker`이며 표시 속성(채움, 선, 불투명도, 변환, 스타일)과 ARIA 이름표가 함께 남습니다.
- **걷어 내거나 거부하는 것**: `<script>`, `<style>`, `<foreignObject>`, 이벤트 처리기, 안에 심어 둔 애니메이션, 그리고 모든 외부 URL과 `data:`/`file:`/`http(s)` URL입니다. 내부 `url(#id)`와 `href="#id"` 참조만 살아남습니다.
- **한계**: 마크업은 최대 **512 KB**, 요소 **4096개**까지입니다.

안전한 칠하기는 16진수 색, CSS 이름 색, `rgb()`/`rgba()`/`hsl()`/`hsla()`, 그리고 앱의 테마 토큰 `var(--color-<name>)`(예를 들어 `var(--color-success)`, `var(--color-symbol-off)`)입니다. 테마 토큰은 하나의 그림이 밝은 테마와 어두운 테마에 함께 맞는 방법입니다. 테마 변형 둘을 만들지 말고 토큰을 참조하는 그림 하나를 실으십시오.

어긴 것을 어떻게 다루는지는 길에 따라 다릅니다. **평범한 SVG**는 고칩니다(안전하지 않은 항목을 걷어 내고 걷어 낸 것마다 경고로 알립니다). **패키지**는 엄격해서, 조용히 고쳐지는 대신 처음 어긴 것들을 밝히며 거부됩니다.

## 옮길 수 있는 패키지 v2 {#portable-package-v2}

심볼을 내보내면 `.ganter-symbol.json` 파일이 만들어집니다. 봉투의 모든 칸이 필수입니다. 규약의 배열 셋은 비어 있어도 되지만 반드시 있어야 합니다.

| 칸 | 요구 사항 |
| --- | --- |
| `$schema` | 정확히 `https://ganterlab.com/schemas/ganter-symbol-v2.schema.json`입니다. |
| `format` | 정확히 `ganter-symbol`입니다. |
| `version` | 정확히 `2`입니다. 버전 1 패키지는 옛 해석기로 넘어가는 대신 거부됩니다. |
| `name` | 표시 이름입니다. 가져오기가 그것을 덮어쓸 수 있고, 부딪히면 꼬리가 저절로 붙습니다. |
| `svg` | 정화된 정적 SVG이며, 그 뿌리 요소는 `viewBox` 칸과 같은 `viewBox`를 담아야 합니다. |
| `viewBox` | `minX minY width height`이며, 너비와 높이가 양수인 유한한 숫자 넷입니다. |
| `fit` | `contain`, `stretch`, `stretch-x`, `stretch-y` 가운데 하나입니다. |
| `footprint` | `{ "width": 1..24, "height": 1..12 }`이며 제안하는 대시보드 칸 수입니다. |
| `slots` | 가변 영역 선언의 배열입니다(아래를 보십시오). |
| `typeConfigurations` | 함께 쓰는 연결점 종류 선택의 배열입니다(아래를 보십시오). |
| `terminals` | 최대 16개의 완전한 연결점 배열입니다(아래를 보십시오). |
| `suggestions` | 순서가 있는, 작성자가 정한 조합의 배열입니다(아래를 보십시오). |

공개된 [Ganter symbol v2 JSON Schema](/schemas/ganter-symbol-v2.schema.json)가 전송 봉투를 검사합니다. 그다음 가져오기가 JSON Schema로는 표현할 수 없는 의미 검사를 합니다. SVG 대상이 있는지, 내부 경로의 기하가 맞는지, 제안이 어울리는지입니다. 패키지는 모든 면에서 엄격합니다. 안전하지 않은 마크업, 알 수 없는 칸, 배열 안의 null 항목, 그리고 예전의 `ports[]`와 `anchors[]`와 `profile`과 `connectionStyle` 규약은 고쳐지는 것이 아니라 거부됩니다.

패키지는 스테이션 주소도, 대시보드 바인딩도, 인스턴스마다의 종류 선택도, 데이터베이스 GUID도, 사용자 신원도 결코 담지 않습니다. Logic 주소를 담은 가변 영역은 내보낼 수조차 없습니다. 그 주소는 다시 쓰는 심볼이 아니라 놓인 인스턴스의 것이기 때문입니다.

## 크기와 뷰 박스와 맞춤 {#size-view-box-and-fit}

**뷰 박스**는 심볼의 자연스러운 좌표 공간입니다. 연결점과 내부 경로가 그 안에서 선언되며, SVG 뿌리 자신의 `viewBox`와 정확히 같아야 합니다. 두 뷰 박스가 어긋나는 패키지는 거부됩니다. 정사각형이 아닌 뷰 박스도 온전히 지원하므로, 긴 컨베이어가 정사각형 안에 살 필요는 없습니다.

**맞춤 방식**은 운전자가 그린 대시보드 사각형을 그림이 어떻게 쓰는지 말합니다.

| 맞춤 | 동작 |
| --- | --- |
| `contain` | 가로세로 비율을 지킵니다. 그림이 칸 사각형 안에서 여백을 두고 들어갑니다. 기본값입니다. |
| `stretch` | 두 축 모두로 사각형을 채우며 필요하면 일그러집니다. |
| `stretch-x` | 가로로 늘이고 세로는 자연스러운 비율을 지킵니다. |
| `stretch-y` | 세로로 늘이고 가로는 자연스러운 비율을 지킵니다. |

**크기**는 심볼을 처음 놓을 때의 대시보드 격자 칸 수입니다. 너비 1에서 24, 높이 1에서 12입니다(편집기의 기본값은 4 × 4입니다). 이것은 제약이 아니라 제안이며, 운전자는 그 뒤에 자유롭게 크기를 바꿉니다.

가져오기의 크기는 서로 다른 두 관문이 가릅니다. 파일 선택기는 **1 MB**가 넘는 것을 읽기 전에 거부하고, 정화기는 **512 KB**나 요소 **4096개**를 넘는 마크업을 거부합니다.

## 가변 영역, 곧 바인딩 표면 {#slots--the-binding-surface}

가변 영역은 입력 하나를 선언합니다. 어느 요소를 움직이는지, 그것에 무엇을 하는지, 그리고 입력 값이 출력으로 어떻게 대응되는지입니다. 나중에 놓인 대시보드 인스턴스가 가변 영역마다 그 신호원(Logic 주소나 고정된 값)을 고릅니다. 심볼 자신은 결코 신호원을 저장하지 않습니다.

가변 영역마다 담는 것은 이렇습니다.

| 칸 | 뜻 |
| --- | --- |
| `name` | 대시보드를 만드는 사람에게 보이는 매개변수 이름입니다. 위의 식별자 문법을 따르며 그 심볼의 가변 영역 안에서 고유해야 합니다. |
| `elementId` | 있는 SVG 요소의 `id`입니다. 한 요소는 채널마다 많아야 가변 영역 하나를 받으므로, 가변 영역 둘이 같은 요소의 채움을 두고 다툴 수 없습니다. |
| `kind` | 아래 열세 갈래 가운데 하나입니다. |
| `inMin`, `inMax` | 입력 범위이며 `outMin`과 `outMax`에 대응되는 두 값입니다. 유한한 숫자이고, 연속인 갈래가 쓰며 `fill`과 `stroke`에서는 문턱의 가운데로 쓰입니다. |
| `outMin`, `outMax` | 그 갈래의 단위로 적은 출력 범위입니다(도, 뷰 박스 단위, 0에서 1, 초당 도). 유한한 숫자입니다. |
| `outMinSecondary`, `outMaxSecondary` | 선택 사항인 두 번째 출력 축이며 `translate`와 `scale`에만 있습니다. 첫 출력이 X이고 두 번째가 Y입니다. 둘 다 주거나 둘 다 주지 마십시오. |
| `onColor`, `offColor` | `fill`과 `stroke`를 위한 안전한 칠하기입니다(문턱의 두 상태). `fillColor`와 `strokeColor`에서는 `onColor`가 검사기의 미리 보기 색입니다. |

열세 가지 가변 영역 갈래는 이렇습니다.

| 갈래 | 움직이는 것 | 비고 |
| --- | --- | --- |
| `rotate` | 요소를 회전시킵니다. 입력이 도 단위로 선형 대응됩니다. | 대상이 `data-ganter-pivot`을 선언해야 합니다. |
| `opacity` | 요소의 불투명도이며 입력이 0에서 1로 대응됩니다. | |
| `fill` | 입력 범위의 가운데보다 아래에서는 `offColor`로, 그 자리이거나 위에서는 `onColor`로 채움을 칠합니다. 부울 입력은 곧바로 바뀝니다. | 채울 수 있는 도형을 겨냥합니다(`<line>`은 안 됩니다). |
| `visible` | 값의 참 거짓으로 요소를 보이거나 감춥니다. | |
| `text` | 요소의 글자 내용을 형식을 갖춘 값으로 바꿉니다. | `<text>`와 `<tspan>`만 겨냥합니다. 폭 제한 읽기 표시를 쓰려면 `data-ganter-fit-*` 속성과 함께 쓰십시오. |
| `translate` | 요소를 뷰 박스 단위로 옮깁니다. 첫 출력이 X이고 선택 사항인 두 번째가 Y입니다. | |
| `scale` | 요소의 배율을 바꿉니다. 첫 출력이 X이고 두 번째가 Y입니다(빠뜨리면 양쪽이 같습니다). | 대상이 `data-ganter-pivot`을 선언해야 합니다. |
| `stroke` | `fill`과 같은 문턱 규칙으로 선을 칠합니다. | |
| `spin` | 시간에 따라 계속 회전합니다. 입력이 초당 도의 각속도로 대응됩니다. `data-ganter-spin-ratio`를 가진 자식은 선언한 비율로 함께 돕니다. | 대상이 `data-ganter-pivot`을 선언해야 합니다. 움직임은 호스트가 일정을 잡으며 운영 체제의 애니메이션 기본 설정과 무관합니다. |
| `spinEnabled` | 같은 요소의 `spin` 가변 영역을 요소를 감추지 않고 멈추거나 다시 돌립니다. | 같은 요소를 겨냥하는 `spin` 가변 영역이 있어야 합니다. |
| `fillColor` | 묶인 색 값(색 자산, 색 변수, 또는 안전한 CSS 색)에서 채움을 그대로 정합니다. | |
| `strokeColor` | 묶인 색 값에서 선을 그대로 정합니다. | |
| `strokeWidth` | 선 두께를 SVG 사용자 단위 **0.5에서 32까지**로 그대로 정합니다. 단위 접미사나 CSS는 받지 않습니다. | 올바르지 않거나 풀리지 않거나 품질이 나쁜 입력은 원래 적힌 `stroke-width`를 되돌립니다. 되돌리기와 다시 붙이기와 없애기도 마찬가지입니다. |

이 가변 영역은 그림을 꾸밉니다. 대시보드 연결선 경로는 결코 꾸미지 않습니다. 그 색과 폭은 연결선 종류마다 공통입니다.

## 바인딩의 소유 {#binding-ownership}

심볼은 매개변수와 허락된 종류 선택을 선언하지, 실시간 신호원이나 인스턴스의 선택을 선언하지 않습니다. 심볼 구성 요소를 놓은 뒤에 운전자가 가변 영역마다 Logic 주소나 고정된 값을 대응시키고, 그 인스턴스에서 구성할 수 있는 연결선 종류를 고릅니다. 그 선택은 스테이션 안에 머물고 다시 쓰는 심볼과 함께 결코 내보내지지 않습니다. 대응되지 않은 가변 영역은 중립으로 남습니다. 요소는 원래 적힌 겉모습을 그대로 지킵니다.

## 공통 위치와 연결선 종류 {#global-positions-and-connection-types}

모든 연결점은 고정된 열여섯 앵커 테두리 카탈로그에서 위치 하나를 참조합니다. 패키지는 `anchorId`만 저장하며 좌표를 되풀이하거나 덮어쓰지 않습니다. 뷰 박스에 대한 정규화된 비율로 적은 위치는 이렇습니다.

- 위: `top-left` (0, 0), `top-25` (0.25, 0), `top-50` (0.5, 0), `top-75` (0.75, 0), `top-right` (1, 0)
- 오른쪽: `right-25` (1, 0.25), `right-50` (1, 0.5), `right-75` (1, 0.75)
- 아래, 시계 방향으로: `bottom-right` (1, 1), `bottom-75` (0.75, 1), `bottom-50` (0.5, 1), `bottom-25` (0.25, 1), `bottom-left` (0, 1)
- 왼쪽, 시계 방향을 이어서: `left-75` (0, 0.75), `left-50` (0, 0.5), `left-25` (0, 0.25)

이것은 테두리 위의 위치이지 5×5 격자가 아닙니다. 심볼이 위치를 더하거나 자기 앵커 좌표를 저장할 수는 없습니다.

여덟 가지 공통 연결선 종류는 `liquid`, `gas`, `air-duct`, `electrical`, `signal`, `network`, `material`, `mechanical-shaft`입니다. 종류마다의 색과 표시 선 두께는 **Logic > Assets > Connection types**에서 설정하십시오. 심볼과 연결선은 변하지 않는 종류 id를 지니므로, 공통 값을 바꾸면 그것을 쓰는 모든 경로가 다시 칠해집니다. 패키지는 색이나 두께를 결코 복사하지 않으며 작음, 표준, 큼 같은 경로 변형도 두지 않습니다.

끝점 둘이 같은 종류로 풀릴 때 정의된 연결이 됩니다. 연결점의 역할은 만들고 검토하는 데 도움을 주지만, 그 자체로 어떤 연결망 배치를 금지하지는 않습니다.

## 함께 쓰는 종류 선택 {#shared-type-choices}

여러 매체와 함께 일할 수 있는 심볼은 그림을 복제하는 대신 함께 쓰는 종류 구성을 선언합니다.

```json
{
  "id": "process-type",
  "name": "Process type",
  "allowedTypes": ["liquid", "gas"],
  "defaultType": "liquid"
}
```

`id`는 변하지 않는 키입니다. 소문자와 숫자를 붙임표 하나로 이으며 처음과 끝은 글자나 숫자여야 합니다(대문자는 거부됩니다). `allowedTypes`는 비어 있지 않고 공통 종류 id를 겹치지 않게 담습니다. `defaultType`은 그 안에 있어야 하고 `name`은 필수입니다. `process-type`을 참조하는 모든 연결점은 놓인 대시보드 인스턴스에서 한 번 고른 선택을 따릅니다. 정의 하나가 공정 매체와 배기 매체처럼 서로 독립된 구성 여럿을 담을 수도 있고, 그동안 다른 연결점은 고정으로 남을 수 있습니다.

## 완전한 연결점 {#complete-terminals}

이을 수 있는 연결점은 저마다 공통 위치 하나, 역할 하나, 고정된 종류 하나 **또는** 함께 쓰는 구성 하나, 원래 방향에서의 바깥 방향, 그리고 안으로 들어오는 경로를 선언합니다.

```json
{
  "anchorId": "left-50",
  "role": "input",
  "typeConfiguration": "process-type",
  "direction": "west",
  "internalPath": [
    { "x": 18, "y": 50 },
    { "x": 36, "y": 50 },
    { "x": 48, "y": 62 }
  ]
}
```

가져올 때 모두 지켜지는 규칙은 이렇습니다.

- 연결점은 최대 **16**개이고, 앵커 id는 저마다 많아야 한 번 쓰입니다.
- `role`은 `input`이나 `output`이나 `bidirectional`이고, `direction`은 `north`나 `east`나 `south`나 `west`입니다.
- `type`(공통 연결선 종류)과 `typeConfiguration`(선언된 구성 id) 가운데 정확히 하나여야 합니다. 둘 다도 안 되고 아무것도 없는 것도 안 됩니다.
- 공통 앵커를 SVG의 자연스러운 뷰 박스로 옮긴 자리가 `internalPath`의 암묵적인 시작점입니다. 그것을 첫 점으로 되풀이하지 마십시오. 좌표는 정규화된 비율이 아니라 뷰 박스의 절대값이고, 경로에는 적어도 점 하나가 있습니다.
- 모든 선분은 뷰 박스 안에 머물고 길이가 0이 아니며 수평이거나 수직이거나 정확히 45°입니다. 이어지는 선분은 많아야 90°까지 꺾입니다.
- 연결점을 두려면 SVG에 뷰 박스가 있어야 합니다.

대시보드는 내부 경로를 장비 그림 아래에 그리고, 크기 바꾸기와 90° 회전과 뒤집기에 맞추어 변환하며, 심볼과 함께 배율을 키우는 대신 공통 연결선 종류의 표시 폭을 지킵니다. 그래서 하나의 이어진 선이 한 본체 안쪽에서 다른 본체 안쪽까지 흐릅니다.

연결점은 전부이거나 전무입니다. 일부만 있는 연결점을 담은 엄격한 패키지는 올바르지 않습니다. 보기 전용 패키지는 대신 빈 `terminals` 배열을 씁니다. 빈자리를 채우려고 무엇을 추측하는 일은 결코 없습니다.

## 순서가 있는 제안 {#ordered-suggestions}

제안은 정확한 목표 자세까지 포함해 의도한 조합을 기록합니다.

```json
{
  "sourceAnchorId": "right-75",
  "targetSymbol": "system:capping-station",
  "targetAnchorId": "left-75",
  "targetRotationDegrees": 0,
  "targetFlipHorizontal": false,
  "targetFlipVertical": false,
  "connectionType": "material"
}
```

검사는 이렇습니다. `sourceAnchorId`는 이 심볼 자신의 연결점 가운데 하나여야 합니다. `targetSymbol`은 출처가 밝혀진 참조여야 하고, 옮길 수 있는 패키지에서는 `system:<stable-key>`만 될 수 있으며(사용자 GUID는 그것을 가진 스테이션 안에서만 뜻이 있습니다) 시스템 카탈로그에 있으면서 `targetAnchorId`에 연결점을 가진 심볼을 불러야 합니다. 회전은 `0`, `90`, `180`, `270` 가운데 하나이고 뒤집기 표시 둘은 모두 필수입니다. 제안은 저마다 고유해야 합니다. `connectionType`은 양쪽 끝의 고정된 종류가 같아서 상황이 분명할 때에만 빠뜨릴 수 있습니다. 어느 한쪽이라도 구성할 수 있으면 필수이며, 그때는 양쪽 끝에서 모두 허락되어야 합니다.

제안에는 방향이 있고 배열 순서가 우선순위를 정하지만, 평범한 대시보드 연결선의 허용 목록은 결코 아닙니다. `suggestions` 배열이 비어 있으면 검사기는 카탈로그 짝을 지어내는 대신 제안된 조합이 없다고 알립니다.

## 가져오기가 거부하는 것 {#what-the-import-refuses}

실패한 가져오기를 짐작하는 대신 읽을 수 있도록, 거부를 빠르게 훑어보는 목록입니다. 평범한 SVG에는 첫 묶음만 해당하고, 그 안에서도 크기 상한과 깨진 XML과 없는 `<svg>` 뿌리만이 가져오기를 거부합니다. 허용되지 않은 마크업은 대신 경고와 함께 고쳐집니다. 패키지에서는 아래의 모든 것이 그대로 거부 사유입니다.

**그림**

- 1 MB가 넘는 파일, 512 KB가 넘는 마크업, 또는 요소 4096개가 넘는 것.
- 깨진 XML, 또는 정화된 `<svg>`가 아닌 뿌리.
- 패키지에서는 허용 목록이 걷어 내야 했을 모든 마크업(스크립트, 이벤트 처리기, 외부 참조, 허용되지 않은 요소나 속성).
- 너비와 높이가 양수인 유한한 숫자 넷이 아니거나 SVG 뿌리의 것과 다른 `viewBox`, 그리고 뿌리 뷰 박스가 아예 없는 패키지.

**봉투**

- v2 규약이 아닌 스키마나 형식이나 버전, 어디에든 있는 알 수 없는 칸, 없는 `name`이나 `fit`이나 `footprint`나 배열 셋 가운데 하나, 그리고 배열 안의 null 항목.
- 네 가지 방식 밖의 `fit`, 그리고 1~24 × 1~12 밖의 크기.

**가변 영역**

- 식별자 문법 밖의 이름이나 요소 id, 겹치는 가변 영역 이름, SVG에 없는 대상 id, 그리고 대상 요소가 받을 수 없는 갈래(글자가 아닌 요소의 text, `<line>`의 fill).
- 대상에 유한한 `data-ganter-pivot`이 없는 `rotate`나 `spin`이나 `scale` 가변 영역, 그리고 같은 요소에 `spin` 가변 영역이 없는 `spinEnabled` 가변 영역.
- 한 요소의 같은 채널에 놓인 가변 영역 둘. `fill`과 `fillColor`가 채움 채널을, `stroke`와 `strokeColor`가 선 채널을 함께 쓰는 것 말고는 갈래마다 자기 채널이므로, 한 요소가 회전 둘을 받을 수 없듯 채움 둘도 받을 수 없습니다.
- 유한하지 않은 범위 숫자, 한쪽 끝만 있는 두 번째 출력이나 `translate`와 `scale`이 아닌 갈래의 두 번째 출력, 안전하지 않은 칠하기, 그리고 Logic 주소를 담은 가변 영역.

**연결**

- 연결점 16개를 넘는 것, 되풀이되거나 알 수 없는 앵커 id, `type`과 `typeConfiguration`을 둘 다 가지거나 둘 다 가지지 않은 연결점, 알 수 없는 종류나 구성 id, 그리고 올바르지 않은 내부 경로(뷰 박스 밖, 길이가 0이거나 각도가 어긋난 선분, 90°가 넘는 꺾임).
- 올바르지 않은 id, 없는 이름, 겹치거나 알 수 없는 허용 종류, 또는 자기 목록 밖의 기본값을 가진 종류 구성.
- 원본 연결점이 없는 제안, 대상이 그 이름의 연결점을 가진 시스템 심볼이 아닌 제안, 자세가 90° 단위가 아닌 제안, 또는 연결선 종류가 양쪽 끝에서 받아들여지지 않는 제안.

[MCP endpoint](agent)의 `symbol_validate`는 바로 이 가져오기를 시험 삼아 돌려 보고, 아무것도 저장하지 않은 채 모든 오류와 경고와 참고 사항을 알려 줍니다.

## 꾸리기와 나누어 쓰기 {#packaging-and-sharing}

**패키지 내보내기**(시스템 심볼과 사용자 심볼 모두에 있습니다)는 정화된 그림과 규약 전체를 담은 `<name>.ganter-symbol.json`을 내려받습니다. `$schema`, `format`, `version`, `name`, `svg`, `viewBox`, `fit`, `footprint`, `slots[]`, `typeConfigurations[]`, `terminals[]`, `suggestions[]`이며, 연결 관련 배열 셋은 비어 있어도 들어 있습니다. 결코 함께 가지 않는 것은 스테이션 주소, 인스턴스마다의 종류 선택, 데이터베이스 신원, 사용자 신원, 그리고 그 스테이션의 연결선 종류 색과 두께입니다.

받는 스테이션에서는 같은 파일이 **심볼 가져오기**(또는 MCP의 `symbol_import`)를 지나 연결점까지 그대로 새 사용자 심볼로 놓입니다. 종류의 신원이 변하지 않는 id이고 겉모습이 공통이므로, 가져온 심볼의 경로는 곧바로 받는 스테이션 자신의 연결선 종류 꾸밈을 따릅니다.
