@things-factory/figure-service 10.1.210 → 10.1.213

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +1 -1
  2. package/dist-server/service/figure/event-subscriber.js +2 -2
  3. package/dist-server/service/figure/event-subscriber.js.map +1 -1
  4. package/dist-server/service/figure/figure-format.js +1 -1
  5. package/dist-server/service/figure/figure-format.js.map +1 -1
  6. package/dist-server/service/figure/figure-mutation.d.ts +5 -5
  7. package/dist-server/service/figure/figure-mutation.js +6 -6
  8. package/dist-server/service/figure/figure-mutation.js.map +1 -1
  9. package/dist-server/service/figure/figure-query.d.ts +3 -3
  10. package/dist-server/service/figure/figure-query.js +4 -4
  11. package/dist-server/service/figure/figure-query.js.map +1 -1
  12. package/dist-server/service/figure/figure-rename.d.ts +4 -4
  13. package/dist-server/service/figure/figure-rename.js +2 -2
  14. package/dist-server/service/figure/figure-rename.js.map +1 -1
  15. package/dist-server/service/figure/figure-tools.js +9 -9
  16. package/dist-server/service/figure/figure-tools.js.map +1 -1
  17. package/dist-server/service/figure/figure-type.d.ts +2 -2
  18. package/dist-server/service/figure/figure-type.js +2 -2
  19. package/dist-server/service/figure/figure-type.js.map +1 -1
  20. package/dist-server/service/figure/figure.d.ts +2 -2
  21. package/dist-server/service/figure/figure.js +1 -1
  22. package/dist-server/service/figure/figure.js.map +1 -1
  23. package/dist-server/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +6 -6
  25. package/recipes/belt-surface/guide.ko.md +1 -1
  26. package/recipes/roller-row/facts.md +1 -1
  27. package/recipes/roller-row/guide.ko.md +1 -1
  28. package/recipes/sliding-door/facts.md +1 -1
  29. package/recipes/sliding-door/guide.ko.md +1 -1
  30. package/server/service/figure/catalog-db.test.ts +1 -1
  31. package/server/service/figure/event-subscriber.ts +2 -2
  32. package/server/service/figure/figure-blueprint-query.test.ts +3 -3
  33. package/server/service/figure/figure-format.test.ts +7 -7
  34. package/server/service/figure/figure-format.ts +1 -1
  35. package/server/service/figure/figure-llm-smoke.test.ts +1 -1
  36. package/server/service/figure/figure-mutation.ts +6 -6
  37. package/server/service/figure/figure-propose-steps.test.ts +2 -2
  38. package/server/service/figure/figure-query.ts +4 -4
  39. package/server/service/figure/figure-rename-db.test.ts +2 -2
  40. package/server/service/figure/figure-rename.test.ts +3 -3
  41. package/server/service/figure/figure-rename.ts +6 -6
  42. package/server/service/figure/figure-subject.test.ts +1 -1
  43. package/server/service/figure/figure-tools.test.ts +19 -19
  44. package/server/service/figure/figure-tools.ts +9 -9
  45. package/server/service/figure/figure-type.ts +2 -2
  46. package/server/service/figure/figure.ts +2 -2
  47. package/translations/ko.json +31 -31
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/figure-service",
3
- "version": "10.1.210",
3
+ "version": "10.1.213",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "@things-factory:registry": "https://registry.npmjs.org"
@@ -27,16 +27,16 @@
27
27
  "dependencies": {
28
28
  "@hatiolab/figure-model": "^0.11.0",
29
29
  "@operato/typeorm-history": "^10.0.0",
30
- "@things-factory/ai-client-base": "^10.1.208",
31
- "@things-factory/attachment-base": "^10.1.208",
32
- "@things-factory/auth-base": "^10.1.208",
30
+ "@things-factory/ai-client-base": "^10.1.213",
31
+ "@things-factory/attachment-base": "^10.1.213",
32
+ "@things-factory/auth-base": "^10.1.213",
33
33
  "@things-factory/env": "^10.1.149",
34
- "@things-factory/setting-base": "^10.1.208",
34
+ "@things-factory/setting-base": "^10.1.213",
35
35
  "@things-factory/shell": "^10.1.208",
36
36
  "graphql-scalars": "^1.22.4",
37
37
  "graphql-upload": "^15.0.2",
38
38
  "jszip": "^3.10.1",
39
39
  "koa-router": "^7.4.0"
40
40
  },
41
- "gitHead": "89fbda12d43d8532ba4e95ba6d6d7e05e2da2502"
41
+ "gitHead": "81f23aa18cb584c7d8185e81cca0d688f509cf8c"
42
42
  }
@@ -15,4 +15,4 @@
15
15
 
16
16
  ## 알아 둘 것
17
17
 
18
- - 벨트는 움직이지 않습니다. 흐름은 도형의 능력(흐른다)으로 나타냅니다.
18
+ - 벨트는 움직이지 않습니다. 흐름은 피규어의 능력(흐른다)으로 나타냅니다.
@@ -17,4 +17,4 @@
17
17
 
18
18
  ## 알려진 한계
19
19
  - 롤러는 X 방향으로만 줄을 선다.
20
- - 한 줄 100개를 넘는 길이에서는 그릴 수 없어, 도형의 가장 큰 크기가 줄어든다.
20
+ - 한 줄 100개를 넘는 길이에서는 그릴 수 없어, 피규어의 가장 큰 크기가 줄어든다.
@@ -17,4 +17,4 @@
17
17
 
18
18
  ## 알아 둘 것
19
19
 
20
- - 한 줄에 100개까지 놓입니다. 그보다 길어지는 크기에서는 도형의 가장 큰 크기가 줄어듭니다.
20
+ - 한 줄에 100개까지 놓입니다. 그보다 길어지는 크기에서는 피규어의 가장 큰 크기가 줄어듭니다.
@@ -23,4 +23,4 @@
23
23
 
24
24
  ## 알려진 한계
25
25
  - 문짝은 문틀 앞에서 미끄러지며, 열리면 기둥 앞을 지난다(벽 속으로 들어가지 않는다).
26
- - 문틀 폭이 600 mm 이하가 되는 크기에서는 그릴 수 없어, 도형에 선언된 크기가 있으면 가장 작은 크기가 올라간다(넣을 때 알리지 않는다).
26
+ - 문틀 폭이 600 mm 이하가 되는 크기에서는 그릴 수 없어, 피규어에 선언된 크기가 있으면 가장 작은 크기가 올라간다(넣을 때 알리지 않는다).
@@ -19,4 +19,4 @@
19
19
  ## 알아 둘 것
20
20
 
21
21
  - 문짝은 문틀 앞에서 미끄러지고, 다 열리면 기둥 앞에 겹칩니다.
22
- - 문틀 폭이 기둥 두 개보다 좁아지는 크기에서는 문을 그릴 수 없습니다. 도형에 크기가 선언되어 있으면 그 가장 작은 크기가 올라갑니다.
22
+ - 문틀 폭이 기둥 두 개보다 좁아지는 크기에서는 문을 그릴 수 없습니다. 피규어에 크기가 선언되어 있으면 그 가장 작은 크기가 올라갑니다.
@@ -121,7 +121,7 @@ describe('태그가 정말 써진다', () => {
121
121
  expect((await readBack(saved.id))!.tags).toEqual([])
122
122
  })
123
123
 
124
- it('안 준 도형은 태그가 없다 — 빈 배열로 갈음하지 않는다', async () => {
124
+ it('안 준 피규어는 태그가 없다 — 빈 배열로 갈음하지 않는다', async () => {
125
125
  const saved = await seed()
126
126
 
127
127
  expect((await readBack(saved.id))!.tags).toBeNull()
@@ -8,14 +8,14 @@ import { FigureHistory } from './figure-history.js'
8
8
  /**
9
9
  * 판본을 남긴다 — **발행된 저장에만.**
10
10
  *
11
- * `@operato/typeorm-history` 는 원래 모든 저장을 베낀다. 그런데 도형은 저작 중에 수십 번 저장되고,
11
+ * `@operato/typeorm-history` 는 원래 모든 저장을 베낀다. 그런데 피규어는 저작 중에 수십 번 저장되고,
12
12
  * 그 전부를 남기면 판본 목록이 「내가 오늘 몇 번 눌렀나」가 된다. 사람이 판이라고 부르는 것은
13
13
  * **발행한 것**이므로 그때만 베낀다. board 가 같은 규칙으로 돈다(`board-service` 의 같은 이름 파일).
14
14
  *
15
15
  * 발행판의 정본(`__releaseSource`)은 크기 범위를 적은 발행판 사본이다 — Figure 행에는 작성자가 좁힌 끝만 남는다.
16
16
  *
17
17
  * 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어
18
- * 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 도형의 것이 아니다. 정본 형식
18
+ * 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 피규어의 것이 아니다. 정본 형식
19
19
  * (`__releaseFormat`), 잰 커널의 판(`__releaseKernel`, ADR-0109 C1), 직전 판에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과
20
20
  * 윗모습(`__releaseTopView`)도 같은 길로 옮긴다(ADR-0104).
21
21
  */
@@ -100,7 +100,7 @@ describe('figureBlueprint 질의 — 소비처(board, twin, things-scene)에 발
100
100
  await repo.save({
101
101
  domain: testDomain,
102
102
  type: 'DRAFT_FIGURE',
103
- name: '초안 도형',
103
+ name: '초안 피규어',
104
104
  state: 'draft',
105
105
  source: sampleSource,
106
106
  version: 0
@@ -116,7 +116,7 @@ describe('figureBlueprint 질의 — 소비처(board, twin, things-scene)에 발
116
116
  await repo.save({
117
117
  domain: testDomain,
118
118
  type: 'RELEASED_FIGURE',
119
- name: '발행 도형',
119
+ name: '발행 피규어',
120
120
  state: 'released',
121
121
  source: sampleSource,
122
122
  version: 1
@@ -141,7 +141,7 @@ describe('figureBlueprint 질의 — 소비처(board, twin, things-scene)에 발
141
141
  const figure = await repo.save({
142
142
  domain: testDomain,
143
143
  type: 'UPDATING_FIGURE',
144
- name: '수정 중인 도형',
144
+ name: '수정 중인 피규어',
145
145
  state: 'draft',
146
146
  source: draftSource,
147
147
  version: 1
@@ -158,8 +158,8 @@ describe('figure-format — 판을 알아보는 문', () => {
158
158
  })
159
159
 
160
160
  /*
161
- (2026-09-24) 드라이룸 램프처럼 — 붙어 있던 부품이 도형을 키우면 떨어진다.
162
- 여기서는 손으로 만든다: 램프의 높이가 도형 높이(size.y)를 따라 올라가고, 몸통은 그대로다.
161
+ (2026-09-24) 드라이룸 램프처럼 — 붙어 있던 부품이 피규어를 키우면 떨어진다.
162
+ 여기서는 손으로 만든다: 램프의 높이가 피규어 높이(size.y)를 따라 올라가고, 몸통은 그대로다.
163
163
  */
164
164
  const splitting = () => {
165
165
  let asset = createFigureAsset('Lamp post')
@@ -185,8 +185,8 @@ describe('figure-format — 판을 알아보는 문', () => {
185
185
  expect(`${finding!.message}${finding!.why}${finding!.how}`).not.toMatch(/come away|piece/)
186
186
  })
187
187
 
188
- /* 한 비율로 커진다고 선언한 도형에서 제 숫자를 가진 부품(수석 아키텍트 판정 2026-09-24 조건 ②). */
189
- it('한 비율로 커진다고 선언한 도형에서 따라 커지지 않는 부품을 막고 이름을 댄다', () => {
188
+ /* 한 비율로 커진다고 선언한 피규어에서 제 숫자를 가진 부품(수석 아키텍트 판정 2026-09-24 조건 ②). */
189
+ it('한 비율로 커진다고 선언한 피규어에서 따라 커지지 않는 부품을 막고 이름을 댄다', () => {
190
190
  let asset = createFigureAsset('Uniform')
191
191
  asset = addFigureBox(asset, { id: 'body', size: { x: 100, y: 100, z: 100 }, position: { x: 0, y: 50, z: 0 } })
192
192
  for (const axis of ['x', 'y', 'z']) {
@@ -197,7 +197,7 @@ describe('figure-format — 판을 알아보는 문', () => {
197
197
  const finding = inspectSource(serializeFigureAsset(asset), null, translatorOf(KO)).findings.find(f => f.code === 'sizing-not-uniform')
198
198
 
199
199
  expect(finding?.blocking).toBe(true)
200
- expect(finding!.message).toBe("이 도형은 한 비율로 커지는데, 크기를 X 로 2배로 하면 'body' 부품은 같이 커지지 않습니다.")
200
+ expect(finding!.message).toBe("이 피규어는 한 비율로 커지는데, 크기를 X 로 2배로 하면 'body' 부품은 같이 커지지 않습니다.")
201
201
  expect(finding!.how).toContain('크기에 비례')
202
202
  })
203
203
 
@@ -234,10 +234,10 @@ describe('figure-format — 판을 알아보는 문', () => {
234
234
  })
235
235
 
236
236
  /*
237
- 자산에는 type 이 없어 임시 이름 검사가 돌지 않았고, 새 도형이 `FIGURE_<uuid>` 로 발행됐다(:3300, 2026-09-24).
237
+ 자산에는 type 이 없어 임시 이름 검사가 돌지 않았고, 새 피규어가 `FIGURE_<uuid>` 로 발행됐다(:3300, 2026-09-24).
238
238
  발행하면 이름이 굳으므로 행의 type 으로 거절한다.
239
239
  */
240
- it('임시 이름인 도형은 발행을 막는다 — 이름은 행에 있다', () => {
240
+ it('임시 이름인 피규어는 발행을 막는다 — 이름은 행에 있다', () => {
241
241
  /* The name a new figure gets — the format's rule, the one the gate recognises. */
242
242
  const placeholder = placeholderType()
243
243
  const finding = inspectSource(figureSource(), null, translatorOf(KO), placeholder).findings.find(f => f.code === 'type-is-placeholder')
@@ -107,7 +107,7 @@ function assertFormat(sourceJson: string): void {
107
107
  }
108
108
  if ((parsed as { version?: unknown } | null)?.version !== FIGURE_ASSET_VERSION)
109
109
  throw new FigureSourceError([
110
- { code: 'source-format-unknown', message: `정본의 판을 알 수 없다 — 도형 자산은 version '${FIGURE_ASSET_VERSION}' 을 적는다`, at: 'version' }
110
+ { code: 'source-format-unknown', message: `정본의 판을 알 수 없다 — 피규어 자산은 version '${FIGURE_ASSET_VERSION}' 을 적는다`, at: 'version' }
111
111
  ])
112
112
  }
113
113
 
@@ -2,7 +2,7 @@
2
2
  * 실제 LLM Figure 후보 생성 smoke test (기본 비활성).
3
3
  *
4
4
  * 결정적 시험은 프롬프트·도구·검사 배선을 고정하지만, 실제 모델이 명령 목록(ADR-0094)을 써서 게이트를
5
- * 지나는 도형을 만드는지는 대신할 수 없다. 이 시험은 `RUN_FIGURE_LLM_SMOKE=1`과 공급자 API 키가 모두 있을 때만 실행한다.
5
+ * 지나는 피규어를 만드는지는 대신할 수 없다. 이 시험은 `RUN_FIGURE_LLM_SMOKE=1`과 공급자 API 키가 모두 있을 때만 실행한다.
6
6
  * DB·GraphQL·Figure 저장을 건드리지 않고 후보 생성 함수만 호출하므로, 외부 영향은 API 비용뿐이다.
7
7
  *
8
8
  * 실행:
@@ -273,7 +273,7 @@ export class FigureMutation {
273
273
  **타입은 발행 전에만 바뀐다** — ADR-0063 결정 4.
274
274
 
275
275
  발행된 뒤에는 이미 배치된 도면이 이 이름을 가리키고, 바꾸면 그 도면이 아무 오류 없이
276
- 빈 자리가 된다. 발행된 적 없는 도형은 가리키는 도면이 있을 수 없다 — 도면은 최신
276
+ 빈 자리가 된다. 발행된 적 없는 피규어는 가리키는 도면이 있을 수 없다 — 도면은 최신
277
277
  발행판을 그리므로 그려질 자리가 없다.
278
278
 
279
279
  행과 정본 둘 다 고친다. 정본 안에도 `type` 이 있어서 한쪽만 고치면 저장된 JSON 과
@@ -358,7 +358,7 @@ export class FigureMutation {
358
358
  *
359
359
  * ## 무엇이 일어나나
360
360
  *
361
- * `state` 가 `released` 가 되고, 판 번호가 하나 오르고, 그 순간의 도형이 판본으로 남는다
361
+ * `state` 가 `released` 가 되고, 판 번호가 하나 오르고, 그 순간의 피규어가 판본으로 남는다
362
362
  * (`FigureHistory` — 스냅샷은 구독자가 뜬다). 저작 중 저장은 이 셋 중 아무것도 하지 않는다.
363
363
  *
364
364
  * ## 왜 이미 발행된 것을 거절하나
@@ -368,12 +368,12 @@ export class FigureMutation {
368
368
  *
369
369
  * ## 번호는 판본에서 센다
370
370
  *
371
- * 도형의 현재 번호가 아니라 **판본의 최대 번호 + 1** 이다. 되돌리기로 옛 판이 현재가 되어도
371
+ * 피규어의 현재 번호가 아니라 **판본의 최대 번호 + 1** 이다. 되돌리기로 옛 판이 현재가 되어도
372
372
  * 다음 발행이 이미 쓴 번호를 다시 쓰지 않는다.
373
373
  *
374
374
  * ## 게이트를 통과해야 한다
375
375
  *
376
- * 크기를 바꿨을 때 조각이 갈라지는 도형은 발행되지 않는다(`figure-gate.ts`). 소비처는 형상을
376
+ * 크기를 바꿨을 때 조각이 갈라지는 피규어는 발행되지 않는다(`figure-gate.ts`). 소비처는 형상을
377
377
  * 늘려 쓰므로 — 그것이 이 형식의 값이다 — 늘려도 견디는지가 약속의 일부다. 화면은 같은 판정을
378
378
  * `inspectFigure` 로 미리 물어 이유를 보여 준다.
379
379
  */
@@ -473,7 +473,7 @@ export class FigureMutation {
473
473
  *
474
474
  * ## 비용은 다시 잰다
475
475
  *
476
- * 판본이 든 점수·삼각형은 **그때의 형식**으로 잰 값이다. 지금 이 도형이 그 내용이 되었으므로
476
+ * 판본이 든 점수·삼각형은 **그때의 형식**으로 잰 값이다. 지금 이 피규어가 그 내용이 되었으므로
477
477
  * 오늘 기준으로 다시 계산한다. 옛 값은 판본에 그대로 남아 있다.
478
478
  */
479
479
  @Directive('@transaction')
@@ -592,7 +592,7 @@ export class FigureMutation {
592
592
  /**
593
593
  * 저작 보조에게 제안을 시킨다(ADR-0094).
594
594
  *
595
- * **저장하지 않는다.** 모델러 명령 목록과 그것이 만드는 도형을 돌려줄 뿐이고, 정본이 되는 것은 저작자가 모델러에
595
+ * **저장하지 않는다.** 모델러 명령 목록과 그것이 만드는 피규어를 돌려줄 뿐이고, 정본이 되는 것은 저작자가 모델러에
596
596
  * 적용하고 저장한 뒤다. 커널이 거절한 명령이나 게이트가 잡은 것은 여기까지 오지 않는다 — 제안기가 사유를 모델에
597
597
  * 돌려주고 다시 시킨다. 끝내 못 만들면 **사유와 함께 던진다.** 반쯤 만든 것을 돌려주지 않는다.
598
598
  */
@@ -256,8 +256,8 @@ describe('a failure told to a person', () => {
256
256
 
257
257
  it('says the first line in the reader\'s language, the reasons as they were', () => {
258
258
  const said: any[] = []
259
- const text = proposalFailureForPerson(failure, (key, params) => (said.push([key, params]), '도형을 만들지 못했습니다.'))
260
- expect(text).toBe('도형을 만들지 못했습니다.\nATTACH_FACE: steps[4]: attach: faces along x')
259
+ const text = proposalFailureForPerson(failure, (key, params) => (said.push([key, params]), '피규어를 만들지 못했습니다.'))
260
+ expect(text).toBe('피규어를 만들지 못했습니다.\nATTACH_FACE: steps[4]: attach: faces along x')
261
261
  expect(said).toEqual([['error.figure-proposal-failed', { defaultValue: 'The figure could not be made.' }]])
262
262
  })
263
263
 
@@ -53,7 +53,7 @@ export class FigureQuery {
53
53
 
54
54
  `simple-json` 이라 칸에는 `["반출","자동"]` 이 통째로 들어 있고, LIKE 는 그 글자를
55
55
  본다. 「반출」로 찾으면 걸린다. 정확히 그 태그만 걸리는 것은 아니지만(이름에 「반출」이
56
- 든 도형도 걸린다) 찾기로는 그것이 오히려 낫다.
56
+ 든 피규어도 걸린다) 찾기로는 그것이 오히려 낫다.
57
57
  */
58
58
  searchables: ['type', 'name', 'description', 'category', 'tags']
59
59
  })
@@ -97,7 +97,7 @@ export class FigureQuery {
97
97
  * 발행된 판들 — 최근 것부터.
98
98
  *
99
99
  * 저작 중 저장은 여기 없다. 판본은 발행에서만 생기므로(`releaseFigure`), 이 목록이 곧
100
- * 「이 도형이 몇 번 약속되었나」다.
100
+ * 「이 피규어가 몇 번 약속되었나」다.
101
101
  */
102
102
  @Directive('@privilege(category: "figure", privilege: "query", domainOwnerGranted: true)')
103
103
  @Query(returns => [FigureHistory], { description: 'Released versions of a figure, newest first.' })
@@ -117,7 +117,7 @@ export class FigureQuery {
117
117
  /**
118
118
  * 지금 소비처가 쓰는 판.
119
119
  *
120
- * 도형의 현재 정본은 저작 중일 수 있다(초안). 배치된 것이 보는 것은 **마지막으로 발행된 판**이고,
120
+ * 피규어의 현재 정본은 저작 중일 수 있다(초안). 배치된 것이 보는 것은 **마지막으로 발행된 판**이고,
121
121
  * 그것을 이 자리가 답한다.
122
122
  */
123
123
  /** What a kept GLB holds, read again from its bytes (ADR-0129): the modeller asks when it reopens a figure. */
@@ -254,7 +254,7 @@ export class FigureQuery {
254
254
  }
255
255
 
256
256
  /**
257
- * 소비처(operato-board, operato-twin, things-scene)가 발행된 도형을 받아 가는 문.
257
+ * 소비처(operato-board, operato-twin, things-scene)가 발행된 피규어를 받아 가는 문.
258
258
  *
259
259
  * 이름은 보드와의 계약이라 그대로 둔다(바꾸는 일은 따로 한다). 돌려주는 것은 자산이다 —
260
260
  * `{ type, asset }`. 그리는 쪽(`registerFigure`)이 커널로 컴파일한다.
@@ -79,7 +79,7 @@ async function namespaced(domain: any) {
79
79
 
80
80
  let DOMAIN: { id: string }
81
81
 
82
- /* 도형이 도메인을 가리킨다 — 행이 없으면 외래키가 먼저 막는다. */
82
+ /* 피규어가 도메인을 가리킨다 — 행이 없으면 외래키가 먼저 막는다. */
83
83
  async function seedDomain() {
84
84
  const saved = await namespaced(await dataSource!.getRepository(shell.Domain).save({ name: 'rename-probe', subdomain: 'rename-probe' }))
85
85
  DOMAIN = { id: saved.id }
@@ -127,7 +127,7 @@ describe('이름을 바꾸기 전에 읽는 사실', () => {
127
127
  expect((await facts(figure, 'robot-arm')).hasHistory).toBe(true)
128
128
  })
129
129
 
130
- it('같은 도메인에서 그 이름을 쓰는 다른 도형을 찾는다', async () => {
130
+ it('같은 도메인에서 그 이름을 쓰는 다른 피규어를 찾는다', async () => {
131
131
  const figure = await seedFigure()
132
132
  await seedFigure({ type: 'conveyor', name: '컨베이어' })
133
133
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * 초안의 타입을 고치는 규칙 — ADR-0063 결정 4.
3
3
  *
4
- * 이 규칙이 지키는 것은 하나다: **발행된 이름은 안 바뀐다.** 도면은 그 이름 하나로 도형을
4
+ * 이 규칙이 지키는 것은 하나다: **발행된 이름은 안 바뀐다.** 도면은 그 이름 하나로 피규어를
5
5
  * 찾으므로, 바뀌면 배치된 자리가 아무 오류 없이 빈다.
6
6
  */
7
7
  import { readFileSync } from 'fs'
@@ -21,7 +21,7 @@ const never = { version: 0, hasHistory: false, takenByAnother: false }
21
21
 
22
22
  describe('초안의 type 고치기', () => {
23
23
  /*
24
- 자산에는 type 칸이 없고 형식은 모르는 칸을 거절한다. 원본에 이름을 써 넣었더니 그 도형을 다시 열 수
24
+ 자산에는 type 칸이 없고 형식은 모르는 칸을 거절한다. 원본에 이름을 써 넣었더니 그 피규어를 다시 열 수
25
25
  없었다(`parseFigureAsset` — "unknown type"). 행만 바뀐다.
26
26
  */
27
27
  it('★ 행만 바뀌고, 원본은 그대로 다시 열린다', () => {
@@ -97,7 +97,7 @@ describe('문이 이 규칙을 지난다', () => {
97
97
  저장이 임시 이름을 스스로 지었다(`FIGURE_<32 hex>`). 형식의 `isPlaceholderType` 이 그것을 못 알아봐서
98
98
  발행 판정이 기계 이름을 통과시켰다. 짓는 쪽과 알아보는 쪽이 한 규칙이어야 한다.
99
99
  */
100
- /* 새 도형의 임시 이름이 판정이 알아보는 그 규칙인지는 문을 실제로 불러 본다 — figure-rename-db.test.ts 「이름 없이 부르면」. */
100
+ /* 새 피규어의 임시 이름이 판정이 알아보는 그 규칙인지는 문을 실제로 불러 본다 — figure-rename-db.test.ts 「이름 없이 부르면」. */
101
101
 
102
102
  it('문이 type 을 받는 칸을 갖는다', () => {
103
103
  const type = source('figure-type.ts')
@@ -6,8 +6,8 @@ import { TYPE_LENGTH, TYPE_PATTERN } from '@hatiolab/figure-model'
6
6
  * ## 왜 발행 전에만인가
7
7
  *
8
8
  * `type` 은 도면에 적히는 이름이다. 도면은 `{ type, left, top, width, height }` 만 갖고 늘 최신
9
- * 발행판을 그리므로, 발행된 도형의 이름을 바꾸면 이미 배치된 도면이 아무 오류 없이 빈 자리가
10
- * 된다. 한 번도 발행되지 않은 도형은 그려질 자리가 없으니 가리키는 도면도 있을 수 없다.
9
+ * 발행판을 그리므로, 발행된 피규어의 이름을 바꾸면 이미 배치된 도면이 아무 오류 없이 빈 자리가
10
+ * 된다. 한 번도 발행되지 않은 피규어는 그려질 자리가 없으니 가리키는 도면도 있을 수 없다.
11
11
  *
12
12
  * ## 왜 열어야 했나
13
13
  *
@@ -28,10 +28,10 @@ export interface RenameFacts {
28
28
  version?: number
29
29
  /** 판본이 하나라도 있나. 되돌리기로 판 번호가 도로 낮아져도 이력은 남는다. */
30
30
  hasHistory: boolean
31
- /** 같은 도메인에서 그 이름을 이미 쓰는 **다른** 도형이 있나. */
31
+ /** 같은 도메인에서 그 이름을 이미 쓰는 **다른** 피규어가 있나. */
32
32
  takenByAnother: boolean
33
33
  /**
34
- * 같은 도메인에서 그 이름으로 발행한 뒤 지워진 도형이 있나. 발행한 도형을 지울 수 없게 되기(G4) 전에 지워진 것이다.
34
+ * 같은 도메인에서 그 이름으로 발행한 뒤 지워진 피규어가 있나. 발행한 피규어를 지울 수 없게 되기(G4) 전에 지워진 것이다.
35
35
  * 그 이름을 다시 쓰면 판 번호가 1부터 다시 매겨져 같은 `ns/type@n` 이 다른 내용을 가리킨다.
36
36
  */
37
37
  releasedBefore?: boolean
@@ -57,7 +57,7 @@ export async function typeReleasedBefore(
57
57
 
58
58
  /** Said when a type was released and deleted before: a new figure may not take it. */
59
59
  export const releasedBeforeMessage = (type: string) =>
60
- `type 「${type}」 는 이 도메인에서 발행한 뒤 지운 도형의 이름이다 — 다시 쓰면 같은 판 번호가 다른 내용을 가리키므로 다른 이름을 고른다`
60
+ `type 「${type}」 는 이 도메인에서 발행한 뒤 지운 피규어의 이름이다 — 다시 쓰면 같은 판 번호가 다른 내용을 가리키므로 다른 이름을 고른다`
61
61
 
62
62
  export class FigureRenameRefused extends Error {
63
63
  constructor(
@@ -100,7 +100,7 @@ export function renameDraftType(
100
100
  if ((facts.version ?? 0) > 0 || facts.hasHistory) {
101
101
  throw new FigureRenameRefused(
102
102
  'already-released',
103
- '발행된 도형의 type 은 바꿀 수 없다 — 이미 배치된 도면이 이 이름을 가리킨다'
103
+ '발행된 피규어의 type 은 바꿀 수 없다 — 이미 배치된 도면이 이 이름을 가리킨다'
104
104
  )
105
105
  }
106
106
 
@@ -4,7 +4,7 @@
4
4
  const mockFigures: any[] = [
5
5
  { id: 'f1', domain: 'plant-a', name: '선풍기', type: 'system/fan' },
6
6
  { id: 'f2', domain: 'plant-a', name: '', type: 'system/agv-lift' },
7
- { id: 'f3', domain: 'plant-b', name: '남의 도형', type: 'other/one' }
7
+ { id: 'f3', domain: 'plant-b', name: '남의 피규어', type: 'other/one' }
8
8
  ]
9
9
  const mockRegistered: any[] = []
10
10
 
@@ -6,7 +6,7 @@
6
6
  * 나타나는 증상이 실제로 겪은 실패와 1:1 로 대응한다.
7
7
  *
8
8
  * · guidance → 도구 호출 끊기면 → 「후보를 만들었습니다」라고만 쓰고 화면에는 아무것도 없다
9
- * · hostContext.figureId → 대상 끊기면 → 화면에 도형이 떠 있는데 「어느 도형입니까」를 되묻는다
9
+ * · hostContext.figureId → 대상 끊기면 → 화면에 피규어가 떠 있는데 「어느 피규어입니까」를 되묻는다
10
10
  * · 도메인 확인 → 대상 끊기면 → 모델이 넘긴 id 로 남의 테넌트를 읽는다
11
11
  * · hostContext.context·revision → 제안 끊기면 → 모델러가 모델이 본 판이 아닌 판에 명령을 적용한다
12
12
  *
@@ -301,7 +301,7 @@ describe('모델이 읽는 글은 영어다', () => {
301
301
  })
302
302
 
303
303
  describe('대화면 문맥에서 대상을 해소한다', () => {
304
- it('id 를 안 주면 열려 있는 도형을 읽는다 — 사용자에게 되묻지 않는다', async () => {
304
+ it('id 를 안 주면 열려 있는 피규어를 읽는다 — 사용자에게 되묻지 않는다', async () => {
305
305
  const result = await toolNamed('getFigureSource').builder({}, ctx())
306
306
 
307
307
  expect(result.id).toBe('fig-1')
@@ -316,7 +316,7 @@ describe('대화면 문맥에서 대상을 해소한다', () => {
316
316
  expect(result.source).toBeUndefined()
317
317
  })
318
318
 
319
- it('목록에서 대상을 찾아 다시 호출하면 해당 도형의 정본을 읽는다', async () => {
319
+ it('목록에서 대상을 찾아 다시 호출하면 해당 피규어의 정본을 읽는다', async () => {
320
320
  const catalog = await toolNamed('listFigures').builder({}, ctx({}))
321
321
  const target = catalog.figures.find((figure: any) => figure.name === '믹서')
322
322
  const result = await toolNamed('getFigureSource').builder({ figureId: target.id }, ctx({}))
@@ -324,7 +324,7 @@ describe('대화면 문맥에서 대상을 해소한다', () => {
324
324
  expect(result.source.name).toBe('Mixer')
325
325
  })
326
326
 
327
- it('정본이 없는 도형은 없다고 말한다 — 지어내지 않는다', async () => {
327
+ it('정본이 없는 피규어는 없다고 말한다 — 지어내지 않는다', async () => {
328
328
  const result = await toolNamed('getFigureSource').builder({ figureId: 'fig-blank' }, ctx())
329
329
 
330
330
  expect(result.source).toBeNull()
@@ -344,7 +344,7 @@ describe('대화면 문맥에서 대상을 해소한다', () => {
344
344
  있고, 그것을 그대로 믿으면 남의 테넌트를 읽는다.
345
345
  */
346
346
  describe('모델이 넘긴 id 를 믿지 않는다', () => {
347
- it('다른 도메인의 도형은 못 찾았다고 한다', async () => {
347
+ it('다른 도메인의 피규어는 못 찾았다고 한다', async () => {
348
348
  await expect(toolNamed('getFigureSource').builder({ figureId: 'fig-other' }, ctx())).rejects.toThrow(
349
349
  /not found in this tenant/
350
350
  )
@@ -362,7 +362,7 @@ describe('모델이 넘긴 id 를 믿지 않는다', () => {
362
362
  expect(result.figures.map((one: any) => one.id)).toEqual(['fig-1', 'fig-blank'])
363
363
  })
364
364
 
365
- it('도구 설명이 저장 전 도형은 모델러에 열린 것만 읽는다고 말한다', () => {
365
+ it('도구 설명이 저장 전 피규어는 모델러에 열린 것만 읽는다고 말한다', () => {
366
366
  const description = toolNamed('getFigureSource').schema.properties.figureId.description
367
367
  expect(description).not.toMatch(/never saved is not open/)
368
368
  expect(description).toMatch(/not saved yet/)
@@ -394,7 +394,7 @@ describe('목록이 잘릴 때', () => {
394
394
  expect(result.note).toMatch(/search/)
395
395
  })
396
396
 
397
- it('이름이나 타입의 일부로 찾으면 잘린 뒤의 도형도 나온다 — 대소문자 없이', async () => {
397
+ it('이름이나 타입의 일부로 찾으면 잘린 뒤의 피규어도 나온다 — 대소문자 없이', async () => {
398
398
  const byName = await toolNamed('listFigures').builder({ search: 'roll PRESS' }, ctx({}))
399
399
  const byType = await toolNamed('listFigures').builder({ search: 'old_press' }, ctx({}))
400
400
  expect(byName.figures.map((one: any) => one.id)).toEqual(['fig-old'])
@@ -411,7 +411,7 @@ describe('목록이 잘릴 때', () => {
411
411
 
412
412
  /*
413
413
  제안은 모델러의 명령 목록이다(ADR-0094). 고치는 제안은 모델러가 모델이 본 판 위에 한 단계로 적용하므로, 고칠 수
414
- 있는 것은 모델러에 열린 도형뿐이고 그 판(context · revision)을 문맥이 싣고 와야 한다.
414
+ 있는 것은 모델러에 열린 피규어뿐이고 그 판(context · revision)을 문맥이 싣고 와야 한다.
415
415
  */
416
416
  const figureDraft = () => {
417
417
  const model = require('@hatiolab/figure-model')
@@ -422,7 +422,7 @@ const figureDraft = () => {
422
422
  const modeller = (over: any = {}) => ({ figureId: 'fig-1', draftSource: figureDraft(), context: 'ctx-7', revision: 4, ...over })
423
423
 
424
424
  describe('제안을 요청할 때', () => {
425
- it('열린 도형을 고치면 그 초안이 제안기에 가고, 모델러가 적용할 판이 함께 돌아온다', async () => {
425
+ it('열린 피규어를 고치면 그 초안이 제안기에 가고, 모델러가 적용할 판이 함께 돌아온다', async () => {
426
426
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '다리를 길게' }, ctx(modeller()))
427
427
  expect(proposed[0].base.name).toBe('Probe')
428
428
  expect(proposed[0].base.version).toBe('figure-asset-1')
@@ -438,19 +438,19 @@ describe('제안을 요청할 때', () => {
438
438
  expect(proposed).toHaveLength(0)
439
439
  })
440
440
 
441
- it('모델러에 열리지 않은 도형은 고치지 않고, 열라고 말한다', async () => {
441
+ it('모델러에 열리지 않은 피규어는 고치지 않고, 열라고 말한다', async () => {
442
442
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '고쳐줘', figureId: 'fig-blank' }, ctx(modeller()))
443
443
  expect(out.error).toBe('FIGURE_NOT_OPEN')
444
444
  expect(proposed).toHaveLength(0)
445
445
  })
446
446
 
447
- it('원본이 없는 도형은 고치지 않는다 — 빈 것을 제안기에 건네지 않는다', async () => {
447
+ it('원본이 없는 피규어는 고치지 않는다 — 빈 것을 제안기에 건네지 않는다', async () => {
448
448
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '고쳐줘' }, ctx({ figureId: 'fig-blank', context: 'c', revision: 1 }))
449
449
  expect(out.error).toBe('FIGURE_NOT_OPEN')
450
450
  expect(proposed).toHaveLength(0)
451
451
  })
452
452
 
453
- it('목록에서 새 제작은 열린 도형을 요구하지 않는다', async () => {
453
+ it('목록에서 새 제작은 열린 피규어를 요구하지 않는다', async () => {
454
454
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '믹서를 새로 만들어줘', create: true, name: 'Mixer' }, ctx({}))
455
455
  expect(out.proposed).toBe(true)
456
456
  expect(proposed[0].base).toBeUndefined()
@@ -464,7 +464,7 @@ describe('제안을 요청할 때', () => {
464
464
  expect(proposed[0].base).toBeUndefined()
465
465
  })
466
466
 
467
- it('create 를 켜면 열린 도형이 있어도 새로 만든다 — 열린 것을 덮어쓰는 제안이 오지 않게', async () => {
467
+ it('create 를 켜면 열린 피규어가 있어도 새로 만든다 — 열린 것을 덮어쓰는 제안이 오지 않게', async () => {
468
468
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '새 컨베이어', create: true }, ctx(modeller()))
469
469
  expect(proposed[0].base).toBeUndefined()
470
470
  expect(out.revision).toBeUndefined()
@@ -474,7 +474,7 @@ describe('제안을 요청할 때', () => {
474
474
  await expect(toolNamed('proposeFigureCandidate').builder({ prompt: ' ' }, ctx(modeller()))).rejects.toThrow(/prompt is required/)
475
475
  })
476
476
 
477
- it('남의 도형을 고치라고 하면 못 찾았다고 한다', async () => {
477
+ it('남의 피규어를 고치라고 하면 못 찾았다고 한다', async () => {
478
478
  await expect(
479
479
  toolNamed('proposeFigureCandidate').builder({ prompt: '고쳐줘', figureId: 'fig-other' }, ctx(modeller()))
480
480
  ).rejects.toThrow(/not found in this tenant/)
@@ -600,7 +600,7 @@ describe('사람이 붙인 그림', () => {
600
600
  })
601
601
  })
602
602
 
603
- describe('도형이 모델러에 열려 있을 때', () => {
603
+ describe('피규어가 모델러에 열려 있을 때', () => {
604
604
  it('저장 전 초안을 이 모델로 읽고, 셈으로 잰다', async () => {
605
605
  const draft = figureDraft()
606
606
  const got = await toolNamed('getFigureSource').builder({}, ctx({ figureId: 'fig-1', draftSource: draft, palette: ['palette.primary'] }))
@@ -639,7 +639,7 @@ describe('도형이 모델러에 열려 있을 때', () => {
639
639
  expect(got.trying).toEqual({ clips: { open: 1 } })
640
640
  })
641
641
 
642
- it('저장된 정본을 읽을 때는 화면의 선택을 붙이지 않는다 — 다른 도형의 선택일 수 있다', async () => {
642
+ it('저장된 정본을 읽을 때는 화면의 선택을 붙이지 않는다 — 다른 피규어의 선택일 수 있다', async () => {
643
643
  const got = await toolNamed('getFigureSource').builder({ figureId: 'fig-1' }, ctx({ selection: { part: 'body', context: 'c', revision: 1 }, context: 'c', revision: 1 }))
644
644
  expect(got.draft).toBe(false)
645
645
  expect(got.selection).toBeUndefined()
@@ -661,7 +661,7 @@ describe('도형이 모델러에 열려 있을 때', () => {
661
661
  Until then the tools refused any draft over 100,000 characters: a figure that opened and saved got no read, no
662
662
  inspection and no proposal, and saving again did not help. Now it is read as an outline and the parts asked for.
663
663
  */
664
- describe('도형이 한 번에 보일 만큼보다 클 때', () => {
664
+ describe('피규어가 한 번에 보일 만큼보다 클 때', () => {
665
665
  const { FIGURE_CONTEXT_BUDGET } = require('./figure-context')
666
666
  const model = require('@hatiolab/figure-model')
667
667
  let under: any
@@ -770,7 +770,7 @@ describe('도형이 한 번에 보일 만큼보다 클 때', () => {
770
770
  the screen sent, through the same door a save goes through. Only the figure open on that screen: an id the model passes
771
771
  that has no row and is not the open one is still not found.
772
772
  */
773
- describe('저장 전 도형', () => {
773
+ describe('저장 전 피규어', () => {
774
774
  const CREATION = '33333333-3333-4333-8333-333333333333'
775
775
  const unsaved = (over: any = {}) => modeller({ figureId: CREATION, editorMode: 'new', ...over })
776
776
 
@@ -811,7 +811,7 @@ describe('저장 전 도형', () => {
811
811
  await expect(toolNamed('getFigureSource').builder({}, ctx({ figureId: CREATION, editorMode: 'new' }))).rejects.toThrow(/not found in this tenant/)
812
812
  })
813
813
 
814
- it('생성 식별자 꼴이 아닌 이름은 저장 전 도형으로 읽지 않는다', async () => {
814
+ it('생성 식별자 꼴이 아닌 이름은 저장 전 피규어로 읽지 않는다', async () => {
815
815
  await expect(toolNamed('getFigureSource').builder({}, ctx(unsaved({ figureId: 'fig-unknown' })))).rejects.toThrow(/not found in this tenant/)
816
816
  })
817
817
  })
@@ -100,7 +100,7 @@ function requireDomainId(state: any): string {
100
100
  }
101
101
 
102
102
  /**
103
- * 이 도형이 호출자 도메인 것인가.
103
+ * 이 피규어가 호출자 도메인 것인가.
104
104
  *
105
105
  * 모델이 넘긴 id 를 그대로 쓰지 않는다. 없으면 못 찾았다고 말한다 — 「권한이 없다」와 구별해
106
106
  * 알려 줄 것이 없다(다른 테넌트에 그 id 가 있다는 사실 자체가 알려 줄 것이 아니다).
@@ -211,8 +211,8 @@ function focusOf(host: any, source: any): { selection?: { part: string }; trying
211
211
  /**
212
212
  * 무엇을 고치라는 것인지 대화면 문맥에서 해소한다.
213
213
  *
214
- * 모델이 대상을 안 줬으면 **저작면이 지금 열고 있는 도형**이다. 사용자에게 식별자를 되묻지
215
- * 않는다 — 화면에 그 도형이 떠 있는데 「어느 도형입니까」를 묻는 것은 문맥을 안 읽은 것이다.
214
+ * 모델이 대상을 안 줬으면 **저작면이 지금 열고 있는 피규어**이다. 사용자에게 식별자를 되묻지
215
+ * 않는다 — 화면에 그 피규어가 떠 있는데 「어느 피규어입니까」를 묻는 것은 문맥을 안 읽은 것이다.
216
216
  */
217
217
  function figureIdFrom(args: any, host: any): string | undefined {
218
218
  const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''
@@ -303,7 +303,7 @@ function figureToolSpecs(): ToolSpec[] {
303
303
  {
304
304
  kind: 'read',
305
305
  name: 'listFigures',
306
- /* 이 도메인의 도형 목록 — 저장소를 직접 읽지만 같은 일을 하는 문은 이것이다. */
306
+ /* 이 도메인의 피규어 목록 — 저장소를 직접 읽지만 같은 일을 하는 문은 이것이다. */
307
307
  doors: ['Query.figures'],
308
308
  description:
309
309
  'Lists the figures in this tenant with their type names, states and part counts. ' +
@@ -354,8 +354,8 @@ function figureToolSpecs(): ToolSpec[] {
354
354
  {
355
355
  kind: 'read',
356
356
  name: 'getFigureSource',
357
- /* 저장된 도형의 원본. **저장 전 초안**을 물으면 저장소에 갈 것이 없어 화면이 보낸 것을 그대로 돌려준다 —
358
- * 그 갈래에는 닿는 문이 없지만 `doors: []` 로 적지 않는다. 그러면 저장된 도형을 읽는 권한 검사가 선언에서 사라진다. */
357
+ /* 저장된 피규어의 원본. **저장 전 초안**을 물으면 저장소에 갈 것이 없어 화면이 보낸 것을 그대로 돌려준다 —
358
+ * 그 갈래에는 닿는 문이 없지만 `doors: []` 로 적지 않는다. 그러면 저장된 피규어를 읽는 권한 검사가 선언에서 사라진다. */
359
359
  doors: ['Query.figure'],
360
360
  description:
361
361
  'Returns the source (the figure asset) of one figure, with its measured cost ' +
@@ -467,12 +467,12 @@ function figureToolSpecs(): ToolSpec[] {
467
467
  if (!prompt) throw new Error('prompt is required: there is nothing to ask for')
468
468
 
469
469
  /*
470
- 고치는 것인지 만드는 것인지를 **문맥에서 정한다.** 열린 도형이 있으면 고치는 것이 기본이고,
471
- 모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는 도형을 덮어쓰는
470
+ 고치는 것인지 만드는 것인지를 **문맥에서 정한다.** 열린 피규어가 있으면 고치는 것이 기본이고,
471
+ 모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는 피규어를 덮어쓰는
472
472
  후보가 온다.
473
473
 
474
474
  고치는 제안은 모델러가 **요청 당시의 판(context · revision)** 위에 한 단계로 적용한다(ADR-0094).
475
- 그래서 고칠 수 있는 것은 모델러에 열린 도형뿐이고, 그 판을 문맥이 함께 실어 와야 한다.
475
+ 그래서 고칠 수 있는 것은 모델러에 열린 피규어뿐이고, 그 판을 문맥이 함께 실어 와야 한다.
476
476
  */
477
477
  const host = ctx?.host
478
478
  const create = args?.create === true || args?.figureId === null
@@ -48,8 +48,8 @@ export class NewFigure {
48
48
  *
49
49
  * `type` 은 **한 번도 발행되지 않은 초안에서만** 바뀐다(ADR-0063 결정 4). 저장되는 식별자라
50
50
  * 발행된 뒤에 바꾸면 이미 배치된 보드가 타입을 못 찾아 오류 없이 빈 화면이 된다. 발행 전에는
51
- * 그 도형을 가리키는 도면이 있을 수 없다 — 도면은 최신 발행판을 그리므로 발행된 적 없는
52
- * 도형은 그려질 자리가 없다.
51
+ * 그 피규어를 가리키는 도면이 있을 수 없다 — 도면은 최신 발행판을 그리므로 발행된 적 없는
52
+ * 피규어는 그려질 자리가 없다.
53
53
  *
54
54
  * 닫아 두었더니 저작자가 이름을 한 번도 정하지 못했다. 새 Figure 에는 기계가 지은 이름이
55
55
  * 붙고(`FIGURE_MU6RJH47`) 칸에 자물쇠가 걸려서, 그 이름이 그대로 도면에 적히는 이름이 됐다.