@hatiolab/figure-model 0.3.3 → 0.3.4

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 (53) hide show
  1. package/dist/asset-types.d.ts +34 -3
  2. package/dist/asset-types.d.ts.map +1 -1
  3. package/dist/capabilities.js +28 -4
  4. package/dist/capabilities.js.map +1 -1
  5. package/dist/graph-types.d.ts +60 -1
  6. package/dist/graph-types.d.ts.map +1 -1
  7. package/dist/graph.d.ts.map +1 -1
  8. package/dist/graph.js +212 -21
  9. package/dist/graph.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/kernel-version.d.ts +1 -1
  13. package/dist/kernel-version.js +1 -1
  14. package/docs/assembly-constraints.md +3 -3
  15. package/docs/asset-persistence.md +8 -8
  16. package/docs/authoring-transactions.md +2 -2
  17. package/docs/capability-bindings.md +1 -1
  18. package/docs/common-kernel-experiment.md +2 -2
  19. package/docs/completeness-review-2026-10-04.md +150 -1
  20. package/docs/core-semantics.md +2 -2
  21. package/docs/cutover.md +4 -4
  22. package/docs/document-contract.md +3 -3
  23. package/docs/dryroom-profile-validation.md +1 -1
  24. package/docs/editor-integration.md +4 -4
  25. package/docs/evaluation-changes-design.md +304 -0
  26. package/docs/evaluation-performance-summary-2026-10-05.md +218 -0
  27. package/docs/full-conveyor-validation.md +8 -8
  28. package/docs/full-dryroom-validation.md +5 -5
  29. package/docs/full-forklift-validation.md +5 -5
  30. package/docs/full-robot-validation.md +4 -4
  31. package/docs/layout-system.md +2 -2
  32. package/docs/legacy-risk-audit-2026-09-23.md +14 -14
  33. package/docs/minimal-model.md +3 -3
  34. package/docs/openusd-review.md +14 -14
  35. package/docs/operator-contracts.md +4 -4
  36. package/docs/prototypes/README.md +2 -2
  37. package/docs/prototypes/asset.schema.json +1 -1
  38. package/docs/prototypes/document.schema.json +1 -1
  39. package/docs/prototypes/editor-browser.mjs +2 -2
  40. package/docs/prototypes/linear-comparison.py +1 -1
  41. package/docs/prototypes/render-dryroom.py +1 -1
  42. package/docs/prototypes/render-full-dryroom.mjs +12 -12
  43. package/docs/prototypes/runtime-browser.mjs +3 -3
  44. package/docs/research-review.md +1 -1
  45. package/docs/review-2026-09-22.md +19 -19
  46. package/docs/runtime-extraction.md +10 -10
  47. package/docs/sample-validation-expanded.md +5 -5
  48. package/docs/sample-validation.md +5 -5
  49. package/docs/shape-dimension-contract.md +1 -1
  50. package/docs/spatial-contracts.md +2 -2
  51. package/docs/status.md +1 -1
  52. package/docs/storage-integration.md +5 -5
  53. package/package.json +1 -1
@@ -0,0 +1,218 @@
1
+ # 평가 성능 작업 정리와 채택 판단 자료 (2026-10-05)
2
+
3
+ completeness review 2026-10-04(F1~F4)에서 2026-10-05까지의 성능·메모리·호환성 근거를 한 곳에 모은다. 판단할 것은 하나다.
4
+ 일반 평가의 변경분 경로를 제품 기본값으로 채택할지. 이 문서는 그 판단에 필요한 근거만 담는다. 세부 기록은 각 줄의 문서에 있다.
5
+
6
+ ## 1. 분류
7
+
8
+ ### 유지하는 것
9
+
10
+ | 무엇 | 근거 | 위치 |
11
+ | --------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
12
+ | 증분 평가와 pose step(ADR-0108) | 앞서 적용·측정 완료 | figure-model 발행판 |
13
+ | 정적 부품 병합·운반 부품 병합(ADR-0109·0111) | 앞서 적용·측정 완료 | things-scene 발행판 |
14
+ | F1~F4 정확성 수정 | 결과 소유권, 공개 입구 검증, 깊은 그래프, 검사 옵션. 시험으로 확인 | figure-model 0.3.3 |
15
+ | 부착점 단건 조회 `place(id)`, 값 조회 `value(ref)` | 스냅샷 없이 최신 상태를 동결 사본으로 읽는다. 제품의 부착점 조회가 스냅샷 전체 공개를 일으키지 않는다 | figure-model `fe8323b`, things-scene `candidate/figure-read-scope` |
16
+ | 평면도의 전체 평가 `evaluateOnce()` | 버리는 rig로 인스턴스 evaluator를 만들지 않는다. 기존 경로와 결과가 같다 | things-scene `candidate/figure-read-scope` `2d082c7c` |
17
+ | pose step 시도의 판정 순서 | 계약 영향 없음. Node에서 크기 변경 프레임의 헛 시도 비용 0.08 → 0.004 ms(60대). 브라우저 전체 프레임 효과는 A/A 폭 안 | figure-model `a968731` |
18
+ | 평가자 오버로드 순서 | `ReturnType<...['evaluator']>`로 타입을 얻던 소비자(things-scene rig)가 그대로 컴파일된다 | figure-model `dc32aa7` |
19
+ | 시험 | 결과 소유권, 변경분 동등성, 조회 소유권, 낡은 사본 회수, 묶음 키, 은행 회수 | figure-model `src/*.test.ts`, things-scene `test/*.check.js` |
20
+ | 측정 도구 | 단계 분해(`BREAKDOWN`), 프로필(`PROFILE`), 한 페이지 교차 A/B, 실행 단위 A/A·A/B(`check-figure-runs.mjs`) | things-scene `test/browser/` |
21
+
22
+ ### 후보로 보존하는 것 (기본 채택 보류)
23
+
24
+ | 무엇 | 위치 |
25
+ | ------------------------------------- | ------------------------------------------------------------------------------------ |
26
+ | 일반 평가의 변경분 경로 `evaluator({ changes: true })` | figure-model `ac92b39`, `1d059f3`, `c34621c`, `fe8323b`(낡은 사본 해제 부분). 옵션을 고른 소비자만 받는다 |
27
+ | 변경분을 쓰는 rig | things-scene `candidate/figure-rig-changes` `8b7c0ce2`(조회 범위 축소 포함, `lastDrawn`) |
28
+
29
+ ### 코드를 되돌리고 설계·측정 기록을 남긴 것
30
+
31
+ | 무엇 | 되돌린 이유 | 기록 |
32
+ | -------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------- |
33
+ | 읽히지 않는 행의 제자리 동결 | 커널 5~10% 감소, 전체 프레임 효과 미확인 | completeness review 「제자리 동결 후보의 측정 결과」 |
34
+ | 형상별 키 캐시 | 배치 계획 약 0.2 ms 감소(잠정), 전체 프레임 효과 미확인 | completeness review 「rig 크기 변경 비용 분해」 |
35
+ | 병합 부품 geometry 장기 보유 | 끌기에서 감소가 보였으나 크기 교대 p95 악화 회차, 은행 +20% | completeness review 「병합 geometry 재생성 분해」 |
36
+ | 병합 부품 geometry 갱신 구간 보유 | 전체 프레임 차이가 A/A 폭 안 | things-scene `docs/plans/figure-merged-part-renewal.md` |
37
+
38
+ ## 2. 변경분 경로의 근거
39
+
40
+ ### 성능
41
+
42
+ 실행 단위 측정(`check-figure-runs.mjs`): 한 번에 한 판의 페이지, 실행마다 해제, 6 round × A1·A2·B, 순서 균형, 반복 수 사전 고정,
43
+ 인스턴스 60, 워밍업 60, 실행당 300프레임. 비교 기준은 F1 적용판이다.
44
+
45
+ | 사용 조건 | B−A1 중앙값 (범위) | A2−A1 중앙값 (범위) | B−A1 p95 | A2−A1 p95 |
46
+ | ----------------------------- | -------------------- | -------------------- | -------------------- | -------------------- |
47
+ | 크기 교대, 스냅샷 조회 없음 | −0.47 (−0.95~+0.08) | −0.03 (−0.23~−0.01) | +0.11 (−0.69~+1.80) | +0.22 (−0.36~+2.80) |
48
+ | 크기 교대, 30프레임마다 조회 | −0.30 (−0.42~−0.22) | −0.06 (−0.29~+0.26) | +0.42 (−3.18~+2.73) | +0.32 (−1.05~+0.71) |
49
+ | 크기 교대, 매 프레임 조회 | +0.09 (−0.10~+0.20) | +0.03 (−0.10~+0.12) | −0.34 (−0.53~−0.25) | −0.08 (−0.35~+0.23) |
50
+ | 끌기(행 개수 변화), 조회 없음 | −0.63 (−0.98~+0.02) | +0.06 (−0.06~+0.20) | −0.38 (−1.38~+0.24) | +0.19 (−0.03~+0.64) |
51
+ | 끌기, 매 프레임 조회 | +0.10 (−0.28~+0.22) | +0.00 (−0.09~+0.12) | +0.01 (−3.36~+0.50) | +0.05 (−4.03~+0.93) |
52
+ | 회전(pose step만) | +0.06 (−1.24~+0.20) | +0.02 (−0.30~+0.59) | −0.35 | −0.33 |
53
+ | 문+램프 flag | −0.12 (−0.37~−0.02) | +0.01 (−0.21~+0.11) | −0.41 | −0.18 |
54
+
55
+ - 스냅샷을 드물게 읽거나 읽지 않을 때 짝 차이의 중앙값에서 0.3~0.6 ms 감소를 관찰했다. 개별 회차는 A/A 범위와 겹치거나
56
+ 악화된 경우가 있다. 기대치(1.0~1.2 ms)에는 못 미쳤다.
57
+ - p95는 끌기에서만 대체로 줄었다. 크기 교대의 p95 차이는 A/A의 p95 변동 범위 안이다. 완료 기준(중앙값과 p95의 일관된
58
+ 개선)은 크기 교대에서 충족되지 않았다.
59
+ - 매 프레임 스냅샷을 읽으면 이득이 없다. 지금 제품에는 그런 소비자가 없다(아래 사용 조건).
60
+ - 한 페이지에 두 판을 함께 띄운 A/B는 두 쪽이 서로 영향을 주어 차이를 부풀렸다(약 −1 ms). 판단에는 쓰지 않는다.
61
+
62
+ ### 메모리
63
+
64
+ Node, 컨베이어 60대와 부착점 하나, GC 뒤 rig 생성 전보다 늘어난 MB.
65
+
66
+ | 단계 | HEAD rig | 변경분 rig(해제 포함) |
67
+ | --------------------- | -------- | --------------------- |
68
+ | 스냅샷 조회 없음 | 6.35~6.43 | 6.53~6.58 |
69
+ | 부착점 단건 조회 뒤 | 6.34~6.39 | 6.42~6.51 |
70
+ | 전체 스냅샷 한 번 뒤 | 6.35~6.47 | 7.39~7.52 |
71
+ | 재조회 뒤(놓음 / 보관) | 6.41~6.45 / 7.91~7.96 | 7.56~7.61 / 8.94~8.99 |
72
+ | dispose 뒤 | 0.01~0.09 | 0.01~0.10 |
73
+
74
+ - 제품의 드문 조회 조건(스냅샷 공개 없음)에서도 60대 기준 0.15~0.2 MB 늘어난다.
75
+ - 전체 스냅샷을 한 번 읽으면 약 1 MB가 더 남는다. 커널의 공개 사본(바뀌지 않은 것의 동일성 계약 때문에 유지)과 rig 자신의
76
+ body가 따로 있기 때문이다. 낡은 공개 사본 해제로 변경 단계에서 약 0.3 MB 줄었지만, HEAD보다 줄어든 것은 아니다.
77
+ - 브라우저 distinct 500대: heap 67.7 → 69.3 MB(첫 평가 공개를 미루기 전에는 72.7 MB).
78
+
79
+ ### 사용 조건
80
+
81
+ 세 저장소의 제품 소스에서 인스턴스 스냅샷을 읽는 곳은 부착점 노드를 처음 만들 때(이제 단건 조회)와 평면도(이제 전체 평가)뿐이다.
82
+ 매 프레임 스냅샷을 읽는 제품 소비자는 없다. figure-ui 모델러와 operato-application은 인스턴스 evaluator를 쓰지 않는다.
83
+
84
+ ### 호환성
85
+
86
+ - 기본 evaluator의 동작은 그대로다. 변경분은 옵션을 고른 소비자만 받는다. 기본 evaluator가 변경분을 받지 않음을 시험으로 확인했다.
87
+ - 추가된 공개 이름: `FigureGraphChanges`, `FigureGraphChangesEvaluator`, `FigureCapabilityChanges`, `FigureCapabilityChangesEvaluator`,
88
+ evaluator의 `value(ref)`, capabilities evaluator의 `place(id)`.
89
+ - 변경분 rig는 `lastEvaluation`(커널 스냅샷을 입힌 것)을 `lastDrawn`(rig 자신의 그리기 상태)으로 바꾼다. 밖에서 이 필드를
90
+ 읽는 곳은 시험뿐이다.
91
+ - 두 things-scene 후보 브랜치는 발행되지 않은 figure-model API가 있어야 빌드된다. 기본 브랜치에 넣으려면 figure-model 발행이 먼저다.
92
+
93
+ ### 유지보수
94
+
95
+ 계산 상태, 공개 스냅샷, 렌더 상태의 책임이 나뉘었다. 대신 경로와 수명 규칙이 늘었다. 미뤄 둔 공개, pose step이 쓴 body와 값의
96
+ 추적, 조회의 수명과 사본 규칙, 구조 변경 시 전체 슬롯 전달이 그것이다. 각 규칙에 결함을 심어 실패하는 시험이 있다.
97
+
98
+ ## 3. 판단에 남은 것
99
+
100
+ - 변경분 경로의 기본 채택 여부. 지금 근거로는 조건부 개선(중앙값)과 순증 메모리가 함께 있고, p95 기준은 충족되지 않았다.
101
+ - 최종 성능 판단의 기준은 F1 적용판 대비 개선이 아니다. 제품에서 필요한 규모와 프레임·메모리 목표를 충족하는지다. 이번 측정은
102
+ F1 적용판 대비라서, 이번 측정으로 JS 대비 우위를 확인하지 않았다. 앞선 JS 비교 결과(ADR-0108·0109의 보드 경로 비교)는 그대로
103
+ 유효하다. 다음 비교는 같은 장면에서 세 경로(현재 JS 구현, 정확성 수정과 독립 개선을 적용한 Figure 기본 경로, 변경분 경로를
104
+ 적용한 Figure 후보)를 잰다. 외형·움직임·크기 변경·부착물 기능을 맞추고, 목표 대수와 프레임·메모리 예산을 측정 전에 고정한다.
105
+ JS 컨베이어의 롤러가 돌지 않는 점처럼 기능이 다르면 맞추거나 따로 표시한다. things-scene `test/browser/bench-figure-vs-js.mjs`가
106
+ 출발점이다.
107
+ - 발행하지 않았다.
108
+
109
+ ## 4. 세 경로 비교의 목표 (측정 전 고정, 2026-10-05)
110
+
111
+ | 항목 | 고정한 값 |
112
+ | ---------- | -------------------------------------------------------------------------------------------------- |
113
+ | 대수 | 컨베이어 500대, 로봇 300대(ADR-0108·0109 측정과 같은 규모) |
114
+ | 프레임 | 전체 프레임 중앙값 16.7 ms 이하, p95 33 ms 이하. ADR-0108의 커널+rig 8.3 ms는 그 안의 내역 목표로 둔다 |
115
+ | 메모리 | 같은 장면의 JS heap(GC 뒤) 대비 1.5배 이하 |
116
+ | 움직임 | 컨베이어 롤러 회전은 JS에 없다. Figure끼리만 비교하고 JS 칸은 n/a로 둔다. 로봇은 관절 움직임으로 세 경로를 비교한다 |
117
+ | 경로 | 현재 JS 구현 · Figure 기본 경로(정확성 수정과 독립 개선) · Figure 후보(변경분 경로) |
118
+ | 재는 것 | 전체 프레임 중앙값·p95, 생성 시간, 메모리. 외형·움직임·크기 변경·부착물 기능을 맞춘다 |
119
+
120
+ 결과를 본 뒤 이 값을 바꾸지 않는다. 변경분 경로의 기본 채택은 이 목표에 대한 결과로 정한다.
121
+
122
+ ## 5. 세 경로 비교 결과 (2026-10-05)
123
+
124
+ `things-scene/test/browser/check-figure-vs-js-runs.mjs`, 실기 GPU Apple M5. 보드 경로(`Scene.create`, model-layer, threed)에서 한 번에 한
125
+ 판의 페이지만 띄웠다. 4 round(js·D1·D2·C의 라틴 방진 순서), 워밍업 30, 실행당 150프레임으로 측정 전에 고정했다. D는 Figure 기본 경로
126
+ (`candidate/figure-read-scope` 빌드), C는 변경분 후보(`candidate/figure-rig-changes` 빌드)이고, 둘 다 figure-model HEAD를 묶었다. 값은
127
+ 실행 중앙값의 중앙값(괄호 안은 p95의 중앙값) ms, heap은 빈 페이지보다 늘어난 MB다. 목표를 넘은 값에 ✗를 붙였다.
128
+
129
+ | 장면 | JS | Figure 기본 D1 / D2 | Figure 후보 C | C−D1 round별 중앙값 | D2−D1 round별 중앙값 |
130
+ | ---------------------------- | -------------------------- | ------------------------------------ | ---------------------- | ---------------------------- | -------------------------- |
131
+ | 컨베이어 500 정지 | 11.73 (12.77) | 11.77 (12.80) / 11.72 (12.57) | 11.42 (12.91) | +0.05 −0.98 −0.34 +0.43 | +0.16 −1.16 +0.15 +0.53 |
132
+ | 컨베이어 500 크기 교대 | 217.22 ✗ (236.88 ✗) | 61.45 ✗ (69.08 ✗) / 61.31 ✗ (67.38 ✗) | 49.80 ✗ (57.11 ✗) | −11.06 −11.45 −14.03 −11.28 | −0.45 +0.32 +2.04 +0.01 |
133
+ | 컨베이어 500 끌기(행 개수 변화) | 215.69 ✗ (235.63 ✗) | 63.73 ✗ (70.80 ✗) / 63.72 ✗ (71.09 ✗) | 51.87 ✗ (58.11 ✗) | −11.64 −11.60 −11.66 −12.19 | +0.48 −1.07 +1.06 −0.36 |
134
+ | 컨베이어 500 롤러 회전 | n/a(JS 롤러는 돌지 않음) | 18.68 ✗ (21.46) / 18.80 ✗ (21.01) | 18.58 ✗ (21.70) | −0.27 −0.11 +0.19 −3.90 | +0.05 −0.11 +0.19 −2.06 |
135
+ | 로봇 300 관절 | 22.67 ✗ (24.11) | 12.78 (16.62) / 12.52 (14.82) | 12.64 (14.47) | −0.01 −0.00 −0.26 −0.04 | −0.09 −0.58 −0.48 −0.18 |
136
+ | 로봇 300 집게에 상자를 든 채 관절 | 27.76 ✗ (31.87) | 20.87 ✗ (23.82) / 21.05 ✗ (23.56) | 20.49 ✗ (23.70) | −0.67 −0.09 −1.00 +0.19 | +0.24 +0.45 −1.00 +0.12 |
137
+
138
+ p95 차이(C−D1, round별): 크기 교대 −11.88 −12.06 −14.38 −9.68, 끌기 −12.99 −10.63 −12.89 −14.73. 다른 장면은 A/A 범위 안이다.
139
+
140
+ | 장면 | 생성 ms JS / D / C | heap MB JS / D / C | 메모리 목표(JS의 1.5배 이하) |
141
+ | -------------- | ------------------------- | ------------------------ | ---------------------------- |
142
+ | 컨베이어 500 | 534~560 / 637~797 / 702~752 | 82.4 / 38.6 / 40.1 | D·C 충족(JS의 약 0.5배) |
143
+ | 로봇 300 관절 | 227 / 318~321 / 345 | 48.7 / 25.5 / 23.8 | D·C 충족 |
144
+ | 로봇 300 들기 | 256 / 315~316 / 311 | 58.0 / 35.0 / 33.3 | D·C 충족 |
145
+
146
+ 로봇 300대 모두 집게에 상자를 들었다(4 round 모두 300/300).
147
+
148
+ ### 읽은 것
149
+
150
+ - 변경분 후보(C)는 보드의 크기 교대와 끌기에서 중앙값과 p95를 4 round 모두 약 11~14 ms 줄였다(D의 약 19%). 같은 조건 A/A(D2−D1)는
151
+ ±2 ms 안이다. 정지, 롤러 회전, 로봇 관절, 들기에서는 A/A 범위 안이다. 메모리는 컨베이어에서 1.5 MB 늘고 로봇에서 1.7 MB 줄었다.
152
+ - rig 단독 측정(60대, 크기 교대)의 차이는 약 0.5 ms였다. 보드 경로 500대에서 대당 차이가 그보다 크게 나타난 이유는 확인하지 않았다.
153
+ 보드는 크기 변경 한 번에 `rig.update()`를 한 번 부른다. 채택 전에 이 차이를 분해해 확인해야 한다.
154
+ - 제품 목표: 크기 교대·끌기는 세 경로 모두 프레임 목표를 크게 넘는다(JS 216~217 ms, D 61~64 ms, C 50~52 ms). 롤러 회전(D·C 18.6~18.8 ms)과
155
+ 로봇 들기(D·C 20.5~21.1 ms, JS 27.8 ms)도 중앙값 16.7 ms를 넘는다. p95 33 ms는 정지·회전·로봇 장면에서 지켜진다. 정지 컨베이어와
156
+ 로봇 관절은 Figure 두 경로가 목표 안이고 JS보다 같거나 빠르다. 메모리는 모든 장면에서 Figure가 JS의 절반 수준이다.
157
+ - 생성 시간은 Figure가 JS보다 길다(컨베이어 약 1.2~1.4배, 로봇 약 1.2~1.5배). 생성 시간 목표는 정하지 않았다.
158
+
159
+ ### 판단 자료
160
+
161
+ - 변경분 경로의 기본 채택 기준(전체 프레임 중앙값과 p95의 일관된 개선, 메모리 예산 안)은 보드 경로 목표 규모의 크기 변경 장면에서
162
+ 충족되고, 다른 장면에서 악화가 없다.
163
+ - 남는 것: rig 단독과 보드 경로의 차이 크기가 설명되지 않았다. 그리고 어느 경로도 500대 크기 변경, 롤러 회전, 로봇 들기에서 프레임
164
+ 목표를 충족하지 못한다. 이것은 기본 채택 여부와 별개의 과제다.
165
+
166
+ ## 6. 보드와 rig 단독의 차이 분해 (2026-10-05)
167
+
168
+ `things-scene/test/browser/check-figure-gap.mjs`. 같은 입력(폭 2400과 2496을 프레임마다 교대, 그 밖에는 아무것도 바꾸지 않음)을 rig
169
+ 단독(같은 빌드의 rig 클래스로 만든 rig, 보드가 그 폭에 주는 인스턴스 크기)과 보드에 주었다. 60대와 500대, D1·D2·C를 4 round 돌렸다.
170
+ 실행마다 프레임을 잰 뒤, 60프레임씩 단계 계측·할당 샘플링·CPU 프로필을 따로 돌렸다. 값은 중앙값, ms/프레임(전 인스턴스 합).
171
+
172
+ | 경로·대수 | D1 frame (p95) | C frame (p95) | C−D1 round별 중앙값 | D2−D1 round별 중앙값 |
173
+ | ----------- | -------------- | -------------- | ---------------------------- | -------------------------- |
174
+ | rig 60 | 7.24 (9.11) | 6.33 (7.84) | −1.25 −1.69 −0.41 −0.66 | +0.26 +0.54 +0.14 +0.13 |
175
+ | rig 500 | 50.02 (55.66) | 39.54 (45.23) | −11.06 −10.11 −10.37 −10.37 | +2.12 +1.37 −0.31 −0.20 |
176
+ | 보드 60 | 14.44 (16.01) | 13.95 (15.00) | +0.02 −0.17 −0.63 −2.43 | +0.25 +0.34 +0.13 −1.08 |
177
+ | 보드 500 | 60.78 (67.42) | 49.97 (56.30) | −11.04 −10.77 −10.58 −11.05 | −0.04 −0.99 +0.38 +0.00 |
178
+
179
+ 500대의 단계별 시간(D1 → C):
180
+
181
+ | 단계 | rig 500 | 보드 500 |
182
+ | ----------------------------- | --------------- | --------------- |
183
+ | rig update 전체 | 45.02 → 34.33 | 45.36 → 34.55 |
184
+ | 커널(advance) | 27.31 → 19.23 | 27.26 → 19.34 |
185
+ | 외형 입히기(dress → fromChanges) | 1.87 → 1.83 | 1.82 → 1.75 |
186
+ | 그리기 준비(draw) | 15.62 → 13.00 | 15.91 → 13.27 |
187
+ | 그 안의 배치 계획 / 병합 | 6.63 / 6.25 → 5.58 / 5.29 | 6.50 / 6.45 → 5.54 / 5.55 |
188
+ | 할당(MB/프레임) | 80.0 → 75.1 | 82.0 → 76.7 |
189
+ | GC(ms/프레임, 비율) | 5.98 (11.3%) → 3.85 (9.2%) | 6.27 (9.5%) → 4.44 (8.2%) |
190
+
191
+ 60대에서는 커널 3.20 → 2.36 ms(rig), 3.32 → 2.67 ms(보드)였다.
192
+
193
+ 같은 작업량: 네 경우 모두 D와 C의 draw call, 삼각형, geometry 수, 그린 body 수, 행 사본 수가 같다(500대: 2,000~2,001회, 944,000~944,012개,
194
+ body 20,000, 사본 12,000). 프레임마다 rig 갱신 1회, 평가 1회(D는 스냅샷 `evaluation`, C는 `changes`)이고, 스냅샷 조회(`evaluate`·
195
+ `evaluation()`·`evaluateOnce`)는 0회다.
196
+
197
+ 설명:
198
+
199
+ - 보드와 rig 단독의 차이가 아니다. 500대의 개선은 rig 단독 −10.1~−11.1 ms, 보드 −10.6~−11.1 ms로 같다. 보드는 두 판 모두에 약 10 ms의
200
+ 고정된 몫(장면 갱신·제출)을 더할 뿐이다.
201
+ - 규모와 입력의 차이다. 앞선 rig 측정(약 0.5 ms)은 60대에서 크기 교대에 롤러 회전을 함께 바꾸었고, 소스를 변환한 번들이었다. 같은 입력의
202
+ 60대에서는 rig −0.4~−1.7 ms, 보드 +0.0~−2.4 ms다.
203
+ - 500대의 개선 약 10.5 ms는 커널 약 8 ms(대당 약 16 µs)와 그리기 준비 약 2.6 ms로 나뉜다. 그리기 준비의 코드는 D와 C가 같다. C는
204
+ 프레임당 할당이 약 5 MB 적고 GC가 약 2 ms 적다. GC 정지가 그리기 준비 구간 안에서 일어나므로, 그 몫이 그리기 준비의 감소로 보인다고
205
+ 해석한다(같은 코드의 시간이 준 것을 다른 원인으로 설명할 근거는 찾지 못했다). 60대의 0.5 ms를 비례로 늘린 4.2 ms보다 큰 것은 대당 커널
206
+ 절감이 같은 입력에서 더 크고(약 16 µs), 500대에서 GC 부담의 차이가 더해지기 때문이다.
207
+ - 대당 프레임당 할당이 약 160 KB(500대에서 80 MB/프레임)로 크다. 기본 채택과 별개로 다음 성능 과제의 단서다.
208
+
209
+ ## 7. 결정 (2026-10-05)
210
+
211
+ - 변경분 경로를 things-scene의 기본 경로로 채택한다(사용자 승인). 근거는 같은 입력·같은 작업량 검증과 500대 반복 측정이다. 보드 500대 크기
212
+ 교대에서 프레임 중앙값 60.78 → 49.97 ms(약 18%), p95 67.42 → 56.30 ms(약 16%) 줄었다.
213
+ - 측정된 것은 커널 비용의 감소(500대 27.3 → 19.3 ms)다. GC가 그리기 준비 구간의 추가 감소에 기여했다는 설명은 할당과 GC 시간이 함께 준
214
+ 관측에서 끌어낸 추론이며, 직접 확인하지 않았다.
215
+ - 채택과 제품 성능 목표 달성은 별개다. 500대 크기 변경은 여전히 프레임 목표 16.7 ms를 넘는다.
216
+ - 후속 과제(이번 발행 범위 밖): 500대 크기 변경에서 프레임당 약 80 MB(대당 약 160 KB)의 할당.
217
+ - 발행 순서: figure-model 발행 → things-scene 후보(`candidate/figure-rig-changes`, 조회 범위 축소 포함) 병합과 figure-model 범위 갱신,
218
+ build와 전체 시험 → things-scene 발행·제품 설치 → 크기 변경, 롤러 회전, visibility, 부착물, 평면도 확인.
@@ -1,15 +1,15 @@
1
- # V3 전체 컨베이어 검증 — 2026-09-21
1
+ # Figure 전체 컨베이어 검증 — 2026-09-21
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
5
5
  ## 판정과 범위
6
6
 
7
- 저장소 CONVEYOR seed의 **17개 파트 유형 전체**를 실험 V3 그래프로 작성했다. 기본 형상과 재질을 재현하면서 기존 반복 배치의 겹침을 의도적으로 제거했다. 제품 모델러 통합·애니메이션 재생·AI 저작 검증은 아직 아니다.
7
+ 저장소 CONVEYOR seed의 **17개 파트 유형 전체**를 실험 Figure 그래프로 작성했다. 기본 형상과 재질을 재현하면서 기존 반복 배치의 겹침을 의도적으로 제거했다. 제품 모델러 통합·애니메이션 재생·AI 저작 검증은 아직 아니다.
8
8
 
9
9
  - 선언 및 메시 어댑터: [full-conveyor.mjs](prototypes/full-conveyor.mjs)
10
10
  - 회귀 검사: [full-conveyor.test.mjs](prototypes/full-conveyor.test.mjs)
11
11
  - 브라우저: `node docs/prototypes/render-full-dryroom.mjs --conveyor`
12
- - 전체 테스트: `node --test docs/prototypes/v3-*.test.mjs`
12
+ - 전체 테스트: `node --test docs/prototypes/*.test.mjs`
13
13
 
14
14
  ## 끝 롤러 공간을 먼저 확보하는 이유
15
15
 
@@ -51,16 +51,16 @@ Chrome WebGL에서 직접 이미지를 확인했다. 환경 반사광을 포함
51
51
  | 상태 | draw calls | 삼각형 |
52
52
  |---|---:|---:|
53
53
  | 원본 재구현 | 32 | 1,612 |
54
- | V3 기본 | 30 | 1,516 |
55
- | V3 회전 37° | 30 | 1,516 |
56
- | V3 길이3000·폭900·높이700·회전37° | 34 | 1,708 |
54
+ | Figure 기본 | 30 | 1,516 |
55
+ | Figure 회전 37° | 30 | 1,516 |
56
+ | Figure 길이3000·폭900·높이700·회전37° | 34 | 1,708 |
57
57
 
58
- 원본과 V3 기본 상태의 해당 시점 RGBA 채널 차이는 0이었다. **메시가 같다는 뜻은 아니다.** 원본의 불필요한 두 롤러가 완전히 가려져 영상에는 나타나지 않기 때문이다. 영상만으로 내부 중첩을 판정할 수 없다는 사례다. 브라우저 pageerror는 없었다. 임시 이미지: `/private/tmp/figure-full-conveyor.png`.
58
+ 원본과 Figure 기본 상태의 해당 시점 RGBA 채널 차이는 0이었다. **메시가 같다는 뜻은 아니다.** 원본의 불필요한 두 롤러가 완전히 가려져 영상에는 나타나지 않기 때문이다. 영상만으로 내부 중첩을 판정할 수 없다는 사례다. 브라우저 pageerror는 없었다. 임시 이미지: `/private/tmp/figure-full-conveyor.png`.
59
59
 
60
60
  ## 남은 한계
61
61
 
62
62
  1. 원본 비교는 제품 생성 코드를 읽고 만든 어댑터 기준이다. 제품 렌더러 직접 실행이 아니며 rounded profile 함수도 공유한다.
63
- 2. 재질·분할 수는 seed 메타데이터를 붙인다. V3 전체 직렬화/재질/품질 정책 계약의 완성을 뜻하지 않는다.
63
+ 2. 재질·분할 수는 seed 메타데이터를 붙인다. Figure 전체 직렬화/재질/품질 정책 계약의 완성을 뜻하지 않는다.
64
64
  3. 접촉 관계는 치수 의존 그래프로 표현했다. 사용자가 접합면을 선택하는 UI 및 feature 기반 저작 작업으로의 연결은 별도 검증이 필요하다.
65
65
  4. 검사한 접합과 끝 롤러 간격 외의 모든 부품 간 충돌을 증명한 것은 아니다. 받침 하단은 원본처럼 y=6mm이며 바닥 접촉으로 몰래 변경하지 않았다.
66
66
  5. 반복 ID는 순번 기반이다. 크기 변경 시 ID는 유지되지만 가운데 정렬 때문에 위치는 움직인다. 삭제 후 재생성·외부 참조의 제품 정책은 여전히 별도 계약이 필요하다.
@@ -1,10 +1,10 @@
1
- # V3 전체 DRY_ROOM 검증 — 2026-09-21
1
+ # Figure 전체 DRY_ROOM 검증 — 2026-09-21
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
5
5
  ## 판정
6
6
 
7
- 저장소 기본 DRY_ROOM의 **6개 파트 전체**를 실험 V3 그래프로 작성하고, 기준 형상 재현과 편집 관계 및 격리된 Chrome WebGL 렌더링을 검증했다. 대표 모델 전체의 제품 가치 검증은 아직 완료가 아니다. 실제 모델러 UI, 서버의 수정된 드라이룸, 다른 대표 모델 전체의 검증을 포함하지 않는다.
7
+ 저장소 기본 DRY_ROOM의 **6개 파트 전체**를 실험 Figure 그래프로 작성하고, 기준 형상 재현과 편집 관계 및 격리된 Chrome WebGL 렌더링을 검증했다. 대표 모델 전체의 제품 가치 검증은 아직 완료가 아니다. 실제 모델러 UI, 서버의 수정된 드라이룸, 다른 대표 모델 전체의 검증을 포함하지 않는다.
8
8
 
9
9
  ## 범위와 재현 방법
10
10
 
@@ -12,7 +12,7 @@
12
12
  - 전체 선언: [full-dryroom.mjs](prototypes/full-dryroom.mjs).
13
13
  - 테스트: [full-dryroom.test.mjs](prototypes/full-dryroom.test.mjs).
14
14
  - 브라우저 실험: [render-full-dryroom.mjs](prototypes/render-full-dryroom.mjs).
15
- - 실행: `node --test docs/prototypes/v3-*.test.mjs`, `node docs/prototypes/render-full-dryroom.mjs`.
15
+ - 실행: `node --test docs/prototypes/*.test.mjs`, `node docs/prototypes/render-full-dryroom.mjs`.
16
16
 
17
17
  브라우저 스크립트는 이 개발 환경의 설치된 Three.js·Playwright·Chrome을 사용한다. 별도 임시 loopback 서버를 열고 종료하며 제품 서버·DB·자산·의존성 설정을 변경하지 않는다. 경로는 개발 환경에 종속되어 있다.
18
18
 
@@ -32,8 +32,8 @@
32
32
  - 27개 치수 조합 × 하단 2개 값 × 램프 높이 3개 값 = **162개 전체 모델**, 메시 **972개** 검사 통과.
33
33
  - 원본 불변성, 유효하지 않은 입력 후 재평가, 관계 유지 검사 통과.
34
34
  - 전체 프로토타입 회귀 테스트 **80/80 통과**.
35
- - Chrome WebGL 동일 카메라 기준 원본 재구현과 V3 기본 상태의 RGBA 채널 차이 **0**.
36
- - 원본·V3 기본·하단 제거·크기 및 램프 위치 변경의 네 상태 모두 **6 draw calls / 336 triangles**. 브라우저 pageerror 없음.
35
+ - Chrome WebGL 동일 카메라 기준 원본 재구현과 Figure 기본 상태의 RGBA 채널 차이 **0**.
36
+ - 원본·Figure 기본·하단 제거·크기 및 램프 위치 변경의 네 상태 모두 **6 draw calls / 336 triangles**. 브라우저 pageerror 없음.
37
37
  - 생성 이미지: `/private/tmp/figure-full-dryroom.png` (임시 산출물).
38
38
 
39
39
  동일 영상은 해당 카메라에서만 비교했다. 보이지 않는 후면은 정점·관계 검사로 확인했으며, 후면 영상 비교나 실제 제품 전체 렌더링 검증을 대체하지 않는다.
@@ -1,14 +1,14 @@
1
- # V3 전체 포크리프트 검증 — 2026-09-21
1
+ # Figure 전체 포크리프트 검증 — 2026-09-21
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
5
5
  ## 판정
6
6
 
7
- 저장소 FORKLIFT seed의 **20개 파트 전체**와 lift/reach/drive를 실험 V3 그래프로 작성했다. 기본 형상 재현과 동시 상태 갱신 검증을 통과했다. 실제 제품 모델러·시간 재생기·적재 기능·충돌/안전성까지 완료한 것은 아니다.
7
+ 저장소 FORKLIFT seed의 **20개 파트 전체**와 lift/reach/drive를 실험 Figure 그래프로 작성했다. 기본 형상 재현과 동시 상태 갱신 검증을 통과했다. 실제 제품 모델러·시간 재생기·적재 기능·충돌/안전성까지 완료한 것은 아니다.
8
8
 
9
9
  - [전체 선언](prototypes/full-forklift.mjs)
10
10
  - [테스트](prototypes/full-forklift.test.mjs)
11
- - 실행: `node --test docs/prototypes/v3-*.test.mjs`
11
+ - 실행: `node --test docs/prototypes/*.test.mjs`
12
12
  - 브라우저: `node docs/prototypes/render-full-dryroom.mjs --forklift`
13
13
 
14
14
  ## 관계
@@ -28,7 +28,7 @@ forkLength는 설계 입력이며 포크 뒤쪽 z=360mm를 유지하고 앞쪽
28
28
  - 포크 뒤쪽 장착 좌표, 상하 포크 간격400mm, carriage와 포크 상대 높이218mm 유지.
29
29
  - 주 휠 축 방향·반지름에 따른 바닥 높이 유지, 잘못된 입력 거부, 오류 후 복구, 노드 순서 독립성 확인.
30
30
 
31
- Chrome에서 원본·V3 기본·상승1000/내밈200·상승2000/내밈400/포크1275mm 이미지를 직접 확인했다. 각 상태 **20 draw calls / 1,032 triangles**, pageerror 없음. 원본 재구현과 V3 기본의 동일 카메라 픽셀 채널 차이는 0이었다. 이미지: `/private/tmp/figure-full-forklift.png`.
31
+ Chrome에서 원본·Figure 기본·상승1000/내밈200·상승2000/내밈400/포크1275mm 이미지를 직접 확인했다. 각 상태 **20 draw calls / 1,032 triangles**, pageerror 없음. 원본 재구현과 Figure 기본의 동일 카메라 픽셀 채널 차이는 0이었다. 이미지: `/private/tmp/figure-full-forklift.png`.
32
32
 
33
33
  ## 한계
34
34
 
@@ -38,4 +38,4 @@ Chrome에서 원본·V3 기본·상승1000/내밈200·상승2000/내밈400/포
38
38
 
39
39
  적재 binding은 원본에 없으며 추가 구현한 것으로 계산하지 않는다. [capability binding 계약](capability-bindings.md)은 물리 형상과 적재/파지 위치를 분리할 설계 초안이다.
40
40
 
41
- 이로써 드라이룸·컨베이어·로봇암·포크리프트 네 대표 모델의 전체 파트 실험은 존재한다. **제품 가치 검증 완료**를 의미하지 않는다. 발견한 원본 품질 문제, capability 구현, V3 직렬화/런타임, 실제 UI와 AI 편집 검증이 남아 있다.
41
+ 이로써 드라이룸·컨베이어·로봇암·포크리프트 네 대표 모델의 전체 파트 실험은 존재한다. **제품 가치 검증 완료**를 의미하지 않는다. 발견한 원본 품질 문제, capability 구현, Figure 직렬화/런타임, 실제 UI와 AI 편집 검증이 남아 있다.
@@ -1,4 +1,4 @@
1
- # V3 전체 로봇암 검증 — 2026-09-21
1
+ # Figure 전체 로봇암 검증 — 2026-09-21
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  - [전체 선언 및 어댑터](prototypes/full-robot.mjs)
12
12
  - [검증 테스트](prototypes/full-robot.test.mjs)
13
- - `node --test docs/prototypes/v3-*.test.mjs`
13
+ - `node --test docs/prototypes/*.test.mjs`
14
14
  - `node docs/prototypes/render-full-dryroom.mjs --robot`
15
15
 
16
16
  베이스·어깨·상완·전완·손목2개·플랜지·손가락2개·tool-seat를 모두 포함한다. 원본에 있는 재질과 tool-seat capability 메타데이터를 보존한다. tool-seat에는 원본 재질이 없어 실험 어댑터에서 palette.neutral을 명시했다. 이는 제품의 기본 재질까지 동일하다는 주장이 아니다. cylinder의 기본 분할 수는 제품 코드에서 확인한 8을 사용했다.
@@ -37,7 +37,7 @@
37
37
  - 관절 범위 초과와 잘못된 링크 길이 거부, 오류 이후 복구, 노드 선언 순서 독립성 검사 통과.
38
38
  - 전체 프로토타입 회귀 테스트 **88/88 통과**. 이 숫자에는 아래 알려진 결함을 탐지하는 테스트도 포함하므로 제품 합격률이 아니다.
39
39
 
40
- Chrome WebGL에서 기본 상태·6축과 그리퍼 동시 변경·링크 길이 변경 이미지를 직접 확인했다. 네 패널 모두 **10 draw calls / 220 triangles**, pageerror 없음. 원본 재구현과 V3 기본 상태의 해당 카메라 RGBA 채널 차이는 0이다. 임시 이미지: `/private/tmp/figure-full-robot.png`.
40
+ Chrome WebGL에서 기본 상태·6축과 그리퍼 동시 변경·링크 길이 변경 이미지를 직접 확인했다. 네 패널 모두 **10 draw calls / 220 triangles**, pageerror 없음. 원본 재구현과 Figure 기본 상태의 해당 카메라 RGBA 채널 차이는 0이다. 임시 이미지: `/private/tmp/figure-full-robot.png`.
41
41
 
42
42
  원본 렌더러를 직접 구동한 것이 아니라 형상 생성 경로를 재구현했다. 독립 FK도 같은 직렬 체인이라는 전제를 공유한다. 이미지 한 시점의 일치는 전체 동작·충돌·물리적 타당성 보장이 아니다.
43
43
 
@@ -60,5 +60,5 @@ tool-seat는 폭40 × 높이20 × 깊이40mm의 실제 cube로 선언되어 있
60
60
  - 자기충돌 및 작업 공간 전체 충돌, 관절 하우징의 시각적 연결 품질.
61
61
  - IK, 물리적 로봇 안전성·동역학은 이번 범위 밖이다.
62
62
  - capability 동작, 시간 기반 애니메이션, UI/AI의 의미 있는 관절명·그리퍼 편집.
63
- - 재질·capability를 포함하는 V3 완전 직렬화와 제품 런타임 연결.
63
+ - 재질·capability를 포함하는 Figure 완전 직렬화와 제품 런타임 연결.
64
64
  - 포크리프트 전체 모델 검증.
@@ -1,4 +1,4 @@
1
- # Figure v3: 계층형 3차원 레이아웃 시스템
1
+ # Figure: 계층형 3차원 레이아웃 시스템
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
@@ -305,7 +305,7 @@ AI: 동일 typed transaction, sourceHash 사전조건, atomic apply, undo, 변
305
305
  | L4 consumer | 2D/3D 공통 결과 | 실제 드라이룸/롤 프레스, 회귀 스냅샷 |
306
306
  | L5 비용/범위 | 1/100/500 instance, 범위 검증 | p95·draw call·메모리 실측, 증명 분류 |
307
307
 
308
- r1은 레이아웃 규칙의 검토 가능한 기준안이다. 전체 v3 출하 명세/구현이 끝났다는 뜻이 아니다.
308
+ r1은 레이아웃 규칙의 검토 가능한 기준안이다. 전체 Figure 출하 명세/구현이 끝났다는 뜻이 아니다.
309
309
  geometry별 feature catalog, 전체 JSON schema, 보수적 수치 증명기, renderer/consumer
310
310
  전환 계약은 L1~L4에서 추가 고정해야 한다. 실제 사용자 조작 수와 결과 품질도 별도 측정한다.
311
311
 
@@ -1,39 +1,39 @@
1
- # V3의 V2 잔재 위험 점검
1
+ # Figure 의 V2 잔재 위험 점검
2
2
 
3
3
  2026-09-23. figure-model, things-scene, things-factory 소스 정적 점검.
4
- 목표는 V2 재현이 아니라 V3의 독립적 저작·평가 계약이다. 표본 통과는 전체 범위 증명이 아니다.
4
+ 목표는 V2 재현이 아니라 지금 형식의 독립적 저작·평가 계약이다. 표본 통과는 전체 범위 증명이 아니다.
5
5
  이 문서는 전체 제품 전환 완료 선언이 아니다. 운영 DB, 배포, 설치 버전은 변경하지 않았다.
6
6
 
7
7
  ## 우선순위와 조치
8
8
 
9
9
  | 우선순위 | 근거 | 위험 | 조치/완료 기준 |
10
10
  | --- | --- | --- | --- |
11
- | P1 | things-factory `figure-service/server/service/figure/figure-source.ts`, `figure-mutation.ts` | V3 저장은 별도 경로지만 기존 생성·수정·복원은 V2 parseSource를 사용한다. V3 데이터 전환 뒤 제품 경로가 깨질 수 있다. | 전환 전 저장·발행·복원·AI·썸네일 전체 V3 경로 시험. 이번 점검에서 운영 경로 전환하지 않음. |
12
- | P1 | things-scene `src/figure/figure-rig.ts`의 clipOf | driver ID의 `/` 앞부분을 재생 그룹으로 해석한다. V3 타입은 ID 문자열 형식을 요구하지 않는다. 이름 변경이 동작을 바꿀 수 있다. | 명시적 재생 그룹 계약을 설계하고 소비처와 변환기를 함께 수정. ID는 불투명 식별자. 런타임에서 V2 이름을 추측하는 fallback은 최종 제거. |
13
- | P2 | `src/asset-types.ts`, `asset.ts`, scene rig | legacyCapability가 V3 정본·평가·렌더러에 남아 있다. 검증된 binding과 혼동되고 유지 비용이 생긴다. | binding으로 재저작하거나 변환 보고서에 보존. 정본에서 제거할 때 fixture·소비처 동시 수정. 단순 삭제로 의미 손실을 숨기지 않음. |
14
- | P2 | `src/gate.ts` → `mesh-compare.ts` | 제품 검사기가 V2 비교용 코드를 의존한다. 비교용 변경이 제품 판정에 전파된다. | 이번 변경에서 V3 형상 유틸리티를 `shape-sampling.ts`로 분리. migration이 유틸리티를 사용하고 역방향 의존을 금지하는 테스트 추가. |
15
- | P2 | things-scene `src/figure/figure-real-object.ts` effectiveDepth | depth 생략 시 평면 크기 배율의 기하평균으로 높이를 결정하는 V2 정책이 V3 소비처에 남아 있다. | V3 설계 입력과 씬 크기 매핑 정책을 명시. 자동 기하평균은 V3 보편 규칙으로 취급하지 말 것. 정책 변경 시 기존 배치의 변화 검증. |
16
- | P2 | `src/index.ts`, `capabilities.ts`, `asset.ts` | 공개 진입점에 V2 변환·비교 API가 섞이고 capability/placement 목록을 V2 types에서 가져온다. | 제품 공통 어휘와 구버전 전용 계약을 분리하고 V3 전용 진입점과 migration 진입점을 설계. 이번 점검에서는 package.json/exports를 변경하지 않음. |
11
+ | P1 | things-factory `figure-service/server/service/figure/figure-source.ts`, `figure-mutation.ts` | 지금 형식의 저장은 별도 경로지만 기존 생성·수정·복원은 V2 parseSource를 사용한다. 지금 형식으로 데이터를 전환한 뒤 제품 경로가 깨질 수 있다. | 전환 전 저장·발행·복원·AI·썸네일 전체 경로를 지금 형식으로 시험. 이번 점검에서 운영 경로 전환하지 않음. |
12
+ | P1 | things-scene `src/figure/figure-rig.ts`의 clipOf | driver ID의 `/` 앞부분을 재생 그룹으로 해석한다. 지금 형식의 타입은 ID 문자열 형식을 요구하지 않는다. 이름 변경이 동작을 바꿀 수 있다. | 명시적 재생 그룹 계약을 설계하고 소비처와 변환기를 함께 수정. ID는 불투명 식별자. 런타임에서 V2 이름을 추측하는 fallback은 최종 제거. |
13
+ | P2 | `src/asset-types.ts`, `asset.ts`, scene rig | legacyCapability가 Figure 정본·평가·렌더러에 남아 있다. 검증된 binding과 혼동되고 유지 비용이 생긴다. | binding으로 재저작하거나 변환 보고서에 보존. 정본에서 제거할 때 fixture·소비처 동시 수정. 단순 삭제로 의미 손실을 숨기지 않음. |
14
+ | P2 | `src/gate.ts` → `mesh-compare.ts` | 제품 검사기가 V2 비교용 코드를 의존한다. 비교용 변경이 제품 판정에 전파된다. | 이번 변경에서 Figure 형상 유틸리티를 `shape-sampling.ts`로 분리. migration이 유틸리티를 사용하고 역방향 의존을 금지하는 테스트 추가. |
15
+ | P2 | things-scene `src/figure/figure-real-object.ts` effectiveDepth | depth 생략 시 평면 크기 배율의 기하평균으로 높이를 결정하는 V2 정책이 지금 형식의 소비처에 남아 있다. | Figure 설계 입력과 씬 크기 매핑 정책을 명시. 자동 기하평균은 Figure 보편 규칙으로 취급하지 말 것. 정책 변경 시 기존 배치의 변화 검증. |
16
+ | P2 | `src/index.ts`, `capabilities.ts`, `asset.ts` | 공개 진입점에 V2 변환·비교 API가 섞이고 capability/placement 목록을 V2 types에서 가져온다. | 제품 공통 어휘와 구버전 전용 계약을 분리하고 Figure 전용 진입점과 migration 진입점을 설계. 이번 점검에서는 package.json/exports를 변경하지 않음. |
17
17
 
18
18
  ## 유지할 것과 격리할 것
19
19
 
20
- - min/max, 상태 의존 치수, 표시 여부, 구간별 매핑은 V3 자체 용도로 평가한다. V2가 도입 계기였다는 이유로 삭제하지 않는다.
20
+ - min/max, 상태 의존 치수, 표시 여부, 구간별 매핑은 Figure 자체 용도로 평가한다. V2가 도입 계기였다는 이유로 삭제하지 않는다.
21
21
  - 변환기, V2 기준 구현, 비교 시험은 이행 도구다. 존재 자체가 문제가 아니라 제품 런타임의 역방향 의존이 문제다.
22
- - 공유된 축/벡터 타입 자체는 호환성 실행 코드가 아니다. 다만 V3 정책을 V2 목록과 묶어서는 안 된다.
23
- - 구면·타원·둥근 모서리의 정의는 독립적인 V3 형상 계약으로 설명한다. V2 화면 일치는 계약의 근거가 아니다.
22
+ - 공유된 축/벡터 타입 자체는 호환성 실행 코드가 아니다. 다만 Figure 정책을 V2 목록과 묶어서는 안 된다.
23
+ - 구면·타원·둥근 모서리의 정의는 독립적인 Figure 형상 계약으로 설명한다. V2 화면 일치는 계약의 근거가 아니다.
24
24
  - 실제 binding 의미를 검증하지 못한 legacy 메타데이터는 기능 구현으로 집계하지 않는다.
25
25
 
26
26
  ## 이번 변경의 한계
27
27
 
28
28
  형상 샘플링의 파일 경계를 분리했을 뿐 연속 표면의 보수적 경계를 새로 증명하지 않았다.
29
29
  유한 샘플의 min/max 또는 Hausdorff 결과를 연속 형상 전체의 보장으로 해석해서는 안 된다.
30
- 기존 API 재수출은 이행 도구를 깨뜨리지 않기 위해 유지했지만, V3 검사기의 내부 의존은 제거했다.
30
+ 기존 API 재수출은 이행 도구를 깨뜨리지 않기 위해 유지했지만, Figure 검사기의 내부 의존은 제거했다.
31
31
  이 테스트는 알려진 migration/V2 실행 파일로의 정적 의존을 차단하며 모든 의미적 호환 잔재를 검출하지는 않는다.
32
32
 
33
33
  ## 후속 검증 기준
34
34
 
35
- 1. V2 fixture 없이 작성한 V3 자산으로 생성·편집·리사이즈·동작·저장·재열기 검증.
35
+ 1. V2 fixture 없이 작성한 Figure 자산으로 생성·편집·리사이즈·동작·저장·재열기 검증.
36
36
  2. driver ID를 바꿔도 재생 그룹과 동작이 유지되는 테스트.
37
- 3. V3 정본/평가 결과에 legacyCapability가 없고 binding 의미가 명시되는 테스트.
37
+ 3. Figure 정본/평가 결과에 legacyCapability가 없고 binding 의미가 명시되는 테스트.
38
38
  4. 씬 크기 입력이 occupancy 수정과 독립적이며 높이 정책이 명시되는 테스트.
39
39
  5. migration 도구를 제품 런타임 의존 그래프에서 제외한 빌드·실행 검증.
@@ -1,4 +1,4 @@
1
- # Figure v3 최소 실행 모델 — r2 설계 후보
1
+ # Figure 최소 실행 모델 — r2 설계 후보
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
@@ -16,7 +16,7 @@
16
16
  > 반복 배치와 개별 형상 회전 순서, 상태 기반 geometry가 추가 계약으로 드러났다.
17
17
  > 부분 모델/proxy 실험이며 최종 명세가 아니다.
18
18
 
19
- 2026-09-20. **검토 중인 후보이며 v3 출하 명세나 제품 구현 완료가 아니다.**
19
+ 2026-09-20. **검토 중인 후보이며 Figure 출하 명세나 제품 구현 완료가 아니다.**
20
20
  사용자가 Flex/Grid를 도입 요구가 아닌 사고의 예시로 정정한 내용을 반영한다.
21
21
  이 문서는 r1의 컨테이너 중심 접근을 대체하는 방향이다. r1 문서는 비교·반례 기록으로 보존한다.
22
22
  어떤 기능도 추가하기 전에 이 최소 모델로 필요한 사례가 실제로 표현되는지 검증한다.
@@ -119,7 +119,7 @@ geometry 입력은 이미 결정된 의미 있는 파라미터다.
119
119
  미지원 feature를 bounds로 대체하지 않고 provider 검사 결과를 반환한다.
120
120
 
121
121
  이 표는 계약의 예시다. 기존 여섯 primitive, hollow, round, material, capability,
122
- label/port/slot을 모두 포괄하는 provider catalog를 완성하기 전에는 v3 전환을 확정하지 않는다.
122
+ label/port/slot을 모두 포괄하는 provider catalog를 완성하기 전에는 이 모델로의 전환을 확정하지 않는다.
123
123
  외부 capability slot과 배치 계산을 위한 가상 slot을 혼용하지 않는다.
124
124
 
125
125
  ## 4. 편의 조작은 식을 만드는 방법이지 추가 실행 규칙이 아니다
@@ -1,7 +1,7 @@
1
- # Figure V3 와 OpenUSD 검토
1
+ # Figure 와 OpenUSD 검토
2
2
 
3
3
  상태: **문헌·소스 검토.** 구현이나 변환 실험은 하지 않았다. 2026-09-25 작성.
4
- 범위: OpenUSD 를 Figure V3 의 개념 기반·이름 정렬 대상·교환 형식으로 쓸 수 있는지. 기준 문서는
4
+ 범위: OpenUSD 를 Figure 의 개념 기반·이름 정렬 대상·교환 형식으로 쓸 수 있는지. 기준 문서는
5
5
  [r3 핵심 의미론](core-semantics.md), [선행 연구 검토](research-review.md)(URDF·USD 는 다루지 않았다),
6
6
  `operato-application/adr/ADR-0093.md`, 그리고 이미 들어간 레코드 `src/authoring-actions.ts:52` `FigureJoint`(커밋 `d15c0ba`, 미발행).
7
7
 
@@ -11,15 +11,15 @@
11
11
 
12
12
  ## 결론
13
13
 
14
- 1. **(a) 개념 기반으로 삼지 않는다.** USD 는 평가가 끝난 값(숫자·time sample)을 합성한다. V3 정본의 중심인 「설계 입력의 식으로 정해지는 치수·pivot·반복 개수」, feature 기준 부착, occupancy, capability 를 담는 구조가 없다. 식을 계산하는 OpenExec 는 25.08 preview 이고 계산은 C++ 로 schema 에 등록해야 하며 장면 파일에 식을 적을 수 없다. 26.08 의 rig 기능도 "not yet ready for production use" 다 [S15][S20]. variable expression 은 asset path·variant 선택에만 쓰이고 산술이 없다 [S21].
14
+ 1. **(a) 개념 기반으로 삼지 않는다.** USD 는 평가가 끝난 값(숫자·time sample)을 합성한다. Figure 정본의 중심인 「설계 입력의 식으로 정해지는 치수·pivot·반복 개수」, feature 기준 부착, occupancy, capability 를 담는 구조가 없다. 식을 계산하는 OpenExec 는 25.08 preview 이고 계산은 C++ 로 schema 에 등록해야 하며 장면 파일에 식을 적을 수 없다. 26.08 의 rig 기능도 "not yet ready for production use" 다 [S15][S20]. variable expression 은 asset path·variant 선택에만 쓰이고 산술이 없다 [S21].
15
15
  2. **(b) 이름·모양은 비용이 작은 곳에서 맞춘다.** joint 레코드는 이미 UsdPhysics 의 양쪽 frame 구조와 같다(부모 feature+origin ↔ `body0`+`localPos0/localRot0`, 자식 feature ↔ `body1`+`localPos1/localRot1`). limit 필드 이름·각도 단위·축 토큰·mimic 부호 규약을 발행 전에 정한다(아래 ADR-0093 권고 R1–R7).
16
- 3. **(c) USD 는 교환 형식으로 쓴다. export 먼저, import 는 URDF 뒤에.** export 는 설계 입력을 평가한 스냅샷을 `usda` 로 쓴다(UsdGeom + UsdPhysics + UsdPreviewSurface, `metersPerUnit = 0.001`, `upAxis = "Y"`). import 한 자산은 모든 치수가 상수인 V3 자산이 된다.
17
- 4. **USD 가 담지 못하는 V3 의 것:** 설계 입력 식, 식을 따르는 joint pivot·travel, 길이를 채우는 반복의 개수 계산, 이름 있는 feature, occupancy, capability, 관계 검사(assertion). **V3 에 없고 USD 에 있는 것:** layer 합성과 비파괴 override, variantSet, payload, 교환 가능한 instancing(scenegraph instancing·PointInstancer), 질량·충돌·drive·articulation root, time sample, 표준 재질(UsdPreviewSurface·MaterialX), Omniverse·Isaac Sim·Siemens 등의 도구 생태계 [S1][S6].
16
+ 3. **(c) USD 는 교환 형식으로 쓴다. export 먼저, import 는 URDF 뒤에.** export 는 설계 입력을 평가한 스냅샷을 `usda` 로 쓴다(UsdGeom + UsdPhysics + UsdPreviewSurface, `metersPerUnit = 0.001`, `upAxis = "Y"`). import 한 자산은 모든 치수가 상수인 Figure 자산이 된다.
17
+ 4. **USD 가 담지 못하는 Figure 의 것:** 설계 입력 식, 식을 따르는 joint pivot·travel, 길이를 채우는 반복의 개수 계산, 이름 있는 feature, occupancy, capability, 관계 검사(assertion). **Figure 에 없고 USD 에 있는 것:** layer 합성과 비파괴 override, variantSet, payload, 교환 가능한 instancing(scenegraph instancing·PointInstancer), 질량·충돌·drive·articulation root, time sample, 표준 재질(UsdPreviewSurface·MaterialX), Omniverse·Isaac Sim·Siemens 등의 도구 생태계 [S1][S6].
18
18
  5. **표준 상태:** AOUSD Core Spec 1.0.1(2025-12-12)은 데이터 모델·합성·`usda/usdc/usdz` 만 규정하고 Geometry·Materials·Physics 는 별도 규격으로 작성 중이다 [S2][S3]. UsdPhysics 이름은 OpenUSD 코드(21.08 부터)가 기준이다. mimic 은 UsdPhysics 에 없고 PhysX·Newton 확장에 부호가 다른 식으로 있다 [S14][S16][S19].
19
19
 
20
- ## 1. V3 개념 → USD 대응표
20
+ ## 1. Figure 개념 → USD 대응표
21
21
 
22
- | Figure V3 개념 | USD 구성 (정확한 이름) | 맞음 |
22
+ | Figure 개념 | USD 구성 (정확한 이름) | 맞음 |
23
23
  |---|---|---|
24
24
  | 설계 입력 d (mm 길이) | 해당 없음. 기록만 하려면 custom attribute(예 `figure:design:width`) 또는 `customData`. 평가하지 않는다 | 없음 |
25
25
  | 상태 입력 q (joint 값) | UsdPhysics 에 joint 값 속성 없음. 자세는 body 의 `xformOp:*` 로 쓴다. PhysX 확장 `PhysicsJointStateAPI` 의 `state:angular:physics:position`/`state:linear:physics:position` [S16][S31] | 변환 필요 |
@@ -50,7 +50,7 @@
50
50
 
51
51
  ## 2. ADR-0093 joint 레코드 · UsdPhysics · URDF 필드 대조
52
52
 
53
- V3 열은 ADR-0093 본문과 구현된 `FigureJoint`(`src/authoring-actions.ts:52-76`)를 함께 적었다.
53
+ Figure 열은 ADR-0093 본문과 구현된 `FigureJoint`(`src/authoring-actions.ts:52-76`)를 함께 적었다.
54
54
 
55
55
  | 뜻 | (ADR-0093 / `FigureJoint`) | UsdPhysics [S14] | URDF [S18] | 판정 |
56
56
  |---|---|---|---|---|
@@ -62,8 +62,8 @@ V3 열은 ADR-0093 본문과 구현된 `FigureJoint`(`src/authoring-actions.ts:5
62
62
  | 자식 쪽 frame | 자식 face (joint frame 안에 놓임) | `point3f physics:localPos1`, `quatf physics:localRot1` (body1 frame 기준) | 없음: 자식 link frame = joint frame | USD 와 같은 구조. URDF export 는 자식 visual origin 에 `inv(B)` 를 접어 넣어야 함 (R7) |
63
63
  | 축 | `axis?: Axis` = `x`, `y`, `z` (joint frame 기준) | `uniform token physics:axis` = `"X"`, `"Y"`, `"Z"` | `<axis xyz>` 임의 단위벡터 | USD 와 같음. URDF 임의 축은 import 불가 (R4) |
64
64
  | 범위 | `limit?: {min, max}` (revolute deg, prismatic mm) | `physics:lowerLimit`, `physics:upperLimit` (revolute deg, prismatic 장면 단위) | `<limit lower upper effort velocity>` (rad, m) | 이름 변경 권고 (R1), 단위 결정 (R2) |
65
- | 거리가 치수를 따름 | `travel{source, times, plus}` | 없음 | 없음 | V3 고유. export 때 limit 숫자로 평가 |
66
- | 현재 값 | `state{id, label, start, sweep}` (상태 입력) | 없음. body 의 xformOp 가 자세. PhysX `state:*:physics:position` | 없음 (값 0 = origin 자세) | V3 고유. export 는 자세를 body xform 으로 |
65
+ | 거리가 치수를 따름 | `travel{source, times, plus}` | 없음 | 없음 | Figure 고유. export 때 limit 숫자로 평가 |
66
+ | 현재 값 | `state{id, label, start, sweep}` (상태 입력) | 없음. body 의 xformOp 가 자세. PhysX `state:*:physics:position` | 없음 (값 0 = origin 자세) | Figure 고유. export 는 자세를 body xform 으로 |
67
67
  | 따라 움직임 | `mimic{joint, multiplier, offset}` : 값 = 리더×multiplier + offset | 없음. Newton: `rel newton:mimicJoint`, `newton:mimicCoef1`, `newton:mimicCoef0` (값 = coef0 + coef1×리더). PhysX: `physxMimicJoint:<axis>:referenceJoint`, `:gearing`, `:offset` (q + gearing×q_ref + offset = 0) | `<mimic joint multiplier offset>` | URDF·Newton 과 같은 식. PhysX 는 부호 반대 (R5) |
68
68
  | 구동 | 없음 | `PhysicsDriveAPI:<dof>` `physics:type`, `maxForce`, `targetPosition`, `targetVelocity`, `stiffness`, `damping` | `<limit effort velocity>`, `<dynamics>` | 범위 밖. 쓰지 않는다 |
69
69
  | 기타 | 없음 | `physics:jointEnabled`, `physics:collisionEnabled`, `physics:excludeFromArticulation`, `physics:breakForce`, `physics:breakTorque`; `PhysicsArticulationRootAPI` | `calibration`, `safety_controller` | 범위 밖. export 기본값 사용 |
@@ -94,15 +94,15 @@ V3 열은 ADR-0093 본문과 구현된 `FigureJoint`(`src/authoring-actions.ts:5
94
94
  ### 3.2 합성: layer, references, payload, variantSet, inherits, specializes
95
95
 
96
96
  - 강도 순서는 **LIVERPS**: Local, Inherits, VariantSets, Relocates, References, Payload, Specializes [S8]. sublayer 는 같은 layer stack 을 이루고, references·payload 는 다른 prim 을 가져오며 이름을 바꿀 수 있다. payload 는 지연 로드용이다 [S8].
97
- - variantSet 은 prim 에 둔 상호 배타적 대안이다 [S8]. **크기·옵션 variant 로 쓸 수 있는 범위:** 유한 개의 프리셋(S/M/L, 옵션 있음/없음)과 V3 의 정적 선택 c. 각 variant 는 평가된 형상을 담는다. 연속 설계 입력(폭 1234 mm)은 variant 로 표현할 수 없다.
98
- - 값 해석은 opinion 의 강도 순서로 정해지고, attribute connection(`connectionPaths`)의 해석과 평가는 schema domain 몫이며 값 해석에 포함되지 않는다 [S3 §connectionPaths]. 즉 USD 합성은 어떤 값도 다른 값에서 다시 계산하지 않는다. 폭을 바꾸면 롤러 개수·pivot 이 따라 바뀌는 V3 의 동작은 USD 쪽에 옮길 수 없다.
97
+ - variantSet 은 prim 에 둔 상호 배타적 대안이다 [S8]. **크기·옵션 variant 로 쓸 수 있는 범위:** 유한 개의 프리셋(S/M/L, 옵션 있음/없음)과 Figure 의 정적 선택 c. 각 variant 는 평가된 형상을 담는다. 연속 설계 입력(폭 1234 mm)은 variant 로 표현할 수 없다.
98
+ - 값 해석은 opinion 의 강도 순서로 정해지고, attribute connection(`connectionPaths`)의 해석과 평가는 schema domain 몫이며 값 해석에 포함되지 않는다 [S3 §connectionPaths]. 즉 USD 합성은 어떤 값도 다른 값에서 다시 계산하지 않는다. 폭을 바꾸면 롤러 개수·pivot 이 따라 바뀌는 Figure 의 동작은 USD 쪽에 옮길 수 없다.
99
99
  - inherits·specializes 는 class prim 의 공통 opinion 을 여러 prim 에 적용한다 [S8]. 보드 수준에서 「이 보드의 모든 컨베이어 색」 같은 일괄 override 에 쓸 수 있다 `[짐작]`.
100
100
 
101
101
  ### 3.3 instancing: 한 figure 를 여러 번, 반복
102
102
 
103
103
  - **scenegraph instancing:** `instanceable = true` 이고 직접 합성 arc 가 있는 prim 은 암시적 prototype 의 instance 가 된다 [S8]. 합성 arc·variant 선택 등이 같은 instance 끼리 prototype 을 공유한다 [S9]. instance 아래 prim 의 속성·metadata 는 override 할 수 없고 instance proxy 는 읽기 전용이다 [S9].
104
- - 결과: **설계 입력 값이 같은 배치끼리만** prototype 을 공유한다. V3 의 형상 캐시 key(provider·해결된 형상 파라미터)와 같은 기준이다(r3 §12). 배치마다 자세(q)가 다른 로봇 팔은 figure 루트를 instance 로 만들 수 없다. Isaac Lab 은 같은 이유로 mesh prim 만 instanceable 로 만들고 link xform 은 instance 밖에 둔다 [S28, 검색 요약].
105
- - **PointInstancer:** `rel prototypes`, `int[] protoIndices`, `int64[] ids`, `point3f[] positions`, `quath[] orientations`, `quatf[] orientationsf`, `float3[] scales`, `vector3f[] velocities`, `accelerations`, `angularVelocities`, `int64[] invisibleIds` [S10]. 강체 항목의 반복(롤러 줄, 선반 칸)에 맞는다. `ids` 에 V3 반복 항목 key(ordinal)를 쓰면 항목 정체성이 유지된다. 항목 안에 joint 가 있으면 항목별 physics joint 를 둘 수 없어 개별 prim 으로 풀어야 한다. PhysX 등이 PointInstancer 안의 강체를 어디까지 지원하는지는 확인 못 함.
104
+ - 결과: **설계 입력 값이 같은 배치끼리만** prototype 을 공유한다. Figure 의 형상 캐시 key(provider·해결된 형상 파라미터)와 같은 기준이다(r3 §12). 배치마다 자세(q)가 다른 로봇 팔은 figure 루트를 instance 로 만들 수 없다. Isaac Lab 은 같은 이유로 mesh prim 만 instanceable 로 만들고 link xform 은 instance 밖에 둔다 [S28, 검색 요약].
105
+ - **PointInstancer:** `rel prototypes`, `int[] protoIndices`, `int64[] ids`, `point3f[] positions`, `quath[] orientations`, `quatf[] orientationsf`, `float3[] scales`, `vector3f[] velocities`, `accelerations`, `angularVelocities`, `int64[] invisibleIds` [S10]. 강체 항목의 반복(롤러 줄, 선반 칸)에 맞는다. `ids` 에 Figure 반복 항목 key(ordinal)를 쓰면 항목 정체성이 유지된다. 항목 안에 joint 가 있으면 항목별 physics joint 를 둘 수 없어 개별 prim 으로 풀어야 한다. PhysX 등이 PointInstancer 안의 강체를 어디까지 지원하는지는 확인 못 함.
106
106
  - three.js `USDLoader` 는 PointInstancer 와 `instanceable` 을 처리하지 않는다(소스에 해당 처리 없음) [S24].
107
107
 
108
108
  ### 3.4 UsdGeom primitive, xformOp, 단위
@@ -1,4 +1,4 @@
1
- # V3 연산·형상 계약 — 첫 실행 가능한 subset
1
+ # Figure 연산·형상 계약 — 첫 실행 가능한 subset
2
2
 
3
3
  > 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
4
4
 
@@ -6,7 +6,7 @@
6
6
  아래는 최초 scalar 단계의 기록이며, 현재 확장 범위는 후속 문서를 따른다.
7
7
 
8
8
  [r3 핵심 의미론](core-semantics.md)을 구현하는 첫 단계다.
9
- 상태: scalar 컴파일러 실험. 정식 V3 전체 schema나 제품 runtime이 아니다.
9
+ 상태: scalar 컴파일러 실험. 정식 Figure 전체 schema나 제품 runtime이 아니다.
10
10
  시스템 설계 절차에 따라 정적 오류, 입력 의존 오류, 미지원 기능을 구분했다.
11
11
 
12
12
  ## 1. 실행 구조
@@ -76,8 +76,8 @@ args 순서와 output 이름은 버전별 연산 계약이다. 전체 연산 cat
76
76
  | mul@1 | a,b | value=a*b | overflow/nonfinite |
77
77
  | div@1 | a,b | value=a/b | b=0, overflow/nonfinite |
78
78
  | geomean@1 | a,b[,c] (동일 차원) | value=(a·b[·c])^(1/n) | 음수 입력 |
79
- | at-least@1 | a,b (동일 차원) | value=flag(a≥b). **flag 는 치수·pose·occupancy 로 못 간다** — appearance.visibility 만 받는다 (V3 설계자 결정 2026-09-22) | 없음 |
80
- | curve@1 | x, at₀,v₀, at₁,v₁, … (at 는 x 와 같은 차원, v 는 한 차원; 키 2개 이상) | value=키 사이는 직선, 키 밖은 끝 값 유지 (piecewise-linear; V3 설계자 승인 2026-09-22) | at 가 strictly increasing 이 아님 (index 로 보고) |
79
+ | at-least@1 | a,b (동일 차원) | value=flag(a≥b). **flag 는 치수·pose·occupancy 로 못 간다** — appearance.visibility 만 받는다 (Figure 설계자 결정 2026-09-22) | 없음 |
80
+ | curve@1 | x, at₀,v₀, at₁,v₁, … (at 는 x 와 같은 차원, v 는 한 차원; 키 2개 이상) | value=키 사이는 직선, 키 밖은 끝 값 유지 (piecewise-linear; Figure 설계자 승인 2026-09-22) | at 가 strictly increasing 이 아님 (index 로 보고) |
81
81
  | sphere-shape@1 | radiusX,radiusY,radiusZ (길이) | shape(sphere) | 반지름≤0 |
82
82
  | polygon-shape@1 | height, x0,z0, x1,z1, … (길이, 점 3개 이상) | shape(polygon; 단면은 X–Z, Y 로 민다) | height≤0, 단면이 한 축으로 퍼지지 않음 |
83
83
  | frustum-shape@1 | radiusTop,radiusBottom,height (길이) | shape(frustum; 축은 Y, radiusTop 이 +Y) | height≤0, 반지름 음수, 둘 다 0 |
@@ -1,4 +1,4 @@
1
- # v3 레이아웃 설계 검증 예제
1
+ # Figure 레이아웃 설계 검증 예제
2
2
 
3
3
  `node --test docs/prototypes/typed-repeat.test.mjs`: 단위/좌표계 그래프와 반복 조립체 통합.
4
4
  [배치 의도 변경과 검증 한계](../typed-repeat-contracts.md)를 함께 확인한다.
@@ -17,7 +17,7 @@
17
17
  모델별 분기 없는 실행기와 실제 샘플에서 유도한 선언을 분리했다.
18
18
  범위·213개 크기/상태 조합·반례·미지원 항목은
19
19
  [공통 커널 실험 기록](../common-kernel-experiment.md)을 따른다.
20
- 제품 v3 구현이나 전체 샘플 변환 완료가 아니다.
20
+ 제품 Figure 구현이나 전체 샘플 변환 완료가 아니다.
21
21
 
22
22
  ## 외부 연구 구현 probe
23
23