@hatiolab/figure-model 0.1.76 → 0.1.78
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.
- package/CHANGELOG.md +12 -0
- package/README.md +60 -138
- package/dist/index.d.ts +1 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -26
- package/dist/index.js.map +1 -1
- package/dist/v3-asset-types.d.ts +1 -2
- package/dist/v3-asset-types.d.ts.map +1 -1
- package/dist/v3-asset.js +1 -1
- package/dist/v3-asset.js.map +1 -1
- package/dist/v3-authoring-actions.d.ts +9 -12
- package/dist/v3-authoring-actions.d.ts.map +1 -1
- package/dist/v3-authoring-actions.js +4 -5
- package/dist/v3-authoring-actions.js.map +1 -1
- package/dist/v3-capabilities.js +4 -1
- package/dist/v3-capabilities.js.map +1 -1
- package/dist/v3-cost.d.ts.map +1 -1
- package/dist/v3-cost.js +3 -5
- package/dist/v3-cost.js.map +1 -1
- package/dist/v3-create.d.ts +1 -1
- package/dist/v3-create.d.ts.map +1 -1
- package/dist/v3-examples.js +1 -1
- package/dist/v3-gate.d.ts +7 -8
- package/dist/v3-gate.d.ts.map +1 -1
- package/dist/v3-gate.js +11 -14
- package/dist/v3-gate.js.map +1 -1
- package/dist/v3-graph.d.ts +1 -2
- package/dist/v3-graph.d.ts.map +1 -1
- package/dist/v3-graph.js +5 -7
- package/dist/v3-graph.js.map +1 -1
- package/dist/v3-instance-size.d.ts +3 -5
- package/dist/v3-instance-size.d.ts.map +1 -1
- package/dist/v3-instance-size.js +2 -4
- package/dist/v3-instance-size.js.map +1 -1
- package/dist/v3-kernel-version.d.ts +1 -1
- package/dist/v3-kernel-version.js +1 -1
- package/dist/v3-part-edit.d.ts +4 -5
- package/dist/v3-part-edit.d.ts.map +1 -1
- package/dist/v3-part-edit.js +2 -2
- package/dist/v3-part-edit.js.map +1 -1
- package/dist/v3-proposal.js +1 -1
- package/dist/v3-proposal.js.map +1 -1
- package/dist/v3-release-contract.js +1 -1
- package/dist/v3-release-contract.js.map +1 -1
- package/dist/v3-score.d.ts +4 -5
- package/dist/v3-score.d.ts.map +1 -1
- package/dist/v3-score.js +7 -8
- package/dist/v3-score.js.map +1 -1
- package/dist/v3-words.d.ts +105 -0
- package/dist/v3-words.d.ts.map +1 -0
- package/dist/v3-words.js +107 -0
- package/dist/v3-words.js.map +1 -0
- package/docs/assembly-constraints-v3.md +13 -23
- package/docs/v3-asset-persistence.md +4 -4
- package/docs/v3-common-kernel-experiment.md +1 -1
- package/docs/v3-core-semantics.md +3 -3
- package/docs/v3-cutover.md +5 -3
- package/docs/v3-design.md +13 -26
- package/docs/v3-editor-integration.md +2 -2
- package/docs/v3-full-conveyor-validation.md +3 -3
- package/docs/v3-layout-system.md +1 -1
- package/docs/v3-minimal-model.md +0 -1
- package/docs/v3-motion-contract.md +21 -56
- package/docs/v3-runtime-extraction.md +7 -7
- package/docs/v3-sample-validation-expanded.md +1 -1
- package/docs/v3-sample-validation.md +1 -1
- package/docs/v3-shape-dimension-contract.md +23 -57
- package/docs/v3-status.md +5 -5
- package/docs/v3-storage-integration.md +4 -4
- package/package.json +2 -20
- package/dist/blueprint-shape.d.ts +0 -10
- package/dist/blueprint-shape.d.ts.map +0 -1
- package/dist/blueprint-shape.js +0 -194
- package/dist/blueprint-shape.js.map +0 -1
- package/dist/blueprint.d.ts +0 -73
- package/dist/blueprint.d.ts.map +0 -1
- package/dist/blueprint.js +0 -388
- package/dist/blueprint.js.map +0 -1
- package/dist/cost-chart.d.ts +0 -35
- package/dist/cost-chart.d.ts.map +0 -1
- package/dist/cost-chart.js +0 -150
- package/dist/cost-chart.js.map +0 -1
- package/dist/cost.d.ts +0 -162
- package/dist/cost.d.ts.map +0 -1
- package/dist/cost.js +0 -194
- package/dist/cost.js.map +0 -1
- package/dist/gate.d.ts +0 -65
- package/dist/gate.d.ts.map +0 -1
- package/dist/gate.js +0 -284
- package/dist/gate.js.map +0 -1
- package/dist/grouping.d.ts +0 -121
- package/dist/grouping.d.ts.map +0 -1
- package/dist/grouping.js +0 -224
- package/dist/grouping.js.map +0 -1
- package/dist/keys.d.ts +0 -45
- package/dist/keys.d.ts.map +0 -1
- package/dist/keys.js +0 -84
- package/dist/keys.js.map +0 -1
- package/dist/origin.d.ts +0 -33
- package/dist/origin.d.ts.map +0 -1
- package/dist/origin.js +0 -46
- package/dist/origin.js.map +0 -1
- package/dist/release-contract.d.ts +0 -38
- package/dist/release-contract.d.ts.map +0 -1
- package/dist/release-contract.js +0 -246
- package/dist/release-contract.js.map +0 -1
- package/dist/sizing.d.ts +0 -231
- package/dist/sizing.d.ts.map +0 -1
- package/dist/sizing.js +0 -550
- package/dist/sizing.js.map +0 -1
- package/dist/types.d.ts +0 -1233
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -547
- package/dist/types.js.map +0 -1
- package/dist/v3-from-v2.d.ts +0 -203
- package/dist/v3-from-v2.d.ts.map +0 -1
- package/dist/v3-from-v2.js +0 -2053
- package/dist/v3-from-v2.js.map +0 -1
- package/dist/v3-mesh-compare.d.ts +0 -24
- package/dist/v3-mesh-compare.d.ts.map +0 -1
- package/dist/v3-mesh-compare.js +0 -55
- package/dist/v3-mesh-compare.js.map +0 -1
- package/dist/validate.d.ts +0 -7
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js +0 -1119
- package/dist/validate.js.map +0 -1
- package/dist/visual-evidence.d.ts +0 -21
- package/dist/visual-evidence.d.ts.map +0 -1
- package/dist/visual-evidence.js +0 -52
- package/dist/visual-evidence.js.map +0 -1
- package/docs/design.md +0 -193
- package/docs/format-survey.md +0 -108
- package/docs/format.md +0 -704
- package/docs/sizing.md +0 -183
- package/docs/validation.md +0 -357
package/docs/v3-design.md
CHANGED
|
@@ -23,25 +23,14 @@ v3의 핵심은 **치수에 따라 달라지는 3차원 배치 함수**다. 문
|
|
|
23
23
|
쓴다. 임의 CAD, 물리 시뮬레이션, 일반 비선형 제약 해결은 초기 범위 밖이다. 지원하지 않는
|
|
24
24
|
관계를 그럴듯한 결과로 대체하지 않고 지원 범위를 명시한다.
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
| `src/sizing.ts` | anchor는 Figure 기준 상자의 축에 대한 위치·크기 반응 | 부품의 개구부·부착 좌표계를 직접 참조하지 못한다 |
|
|
35
|
-
| `src/types.ts`, `src/grouping.ts`, `jointOriginPosition` | parent/joint와 부모를 따라 변하는 관절 원점은 이미 있다 | 관계가 전혀 없는 것이 아니라 크기 배치 관계가 부족하다 |
|
|
36
|
-
| `src/gate.ts: spansAt/meets/clumpsOf` | AABB의 연결 개수 증가를 검사 | 실제 접촉·개구부 맞춤·어떤 부품에 연결됐는지 보장하지 못한다 |
|
|
37
|
-
| `src/gate.ts: remedyFor` | 다른 덩어리의 느리게 커지는 부품을 골라 조언 | 실제 맞댄 면을 증명하지 않고 수정 방향을 단정할 수 있다 |
|
|
38
|
-
| `src/gate.ts: sizingReport` | 기본적으로 기준 크기와 7종 2배 검사 | 연속 치수 범위·축소·운동 상태의 증명이 아니다 |
|
|
39
|
-
| anchor 후보 탐색 | 제한된 수정 조합을 탐색 | 실패했다고 v2로 해결 불가능한 것은 아니다 |
|
|
40
|
-
| `src/grouping.ts`, things-scene `figure-real-object.ts` | 재질·운동 frame·크기 반응으로 병합/분리 | 관계 추가가 무료 성능을 보장하지 않는다 |
|
|
41
|
-
|
|
42
|
-
드라이룸에서 복합 수정안이 생성되지 않은 것은 관찰했다. 고정 revision의 원본을 확보해
|
|
43
|
-
원인과 모든 대안을 검증한 상태는 아니다. 앞서 탐색 실패를 곧바로 모델 표현력의 불가능성으로
|
|
44
|
-
설명한 것은 과도했다. v3 설계의 근거는 일반적인 조립 의도와 일관된 배치 계산의 필요성이다.
|
|
26
|
+
관계 없는 단독 상자도 정상 모델이며, 미완성 초안의 저장을 금지하지 않는다.
|
|
27
|
+
|
|
28
|
+
## 2. 설계의 근거
|
|
29
|
+
|
|
30
|
+
v3 설계의 근거는 일반적인 조립 의도와 일관된 배치 계산의 필요성이다. 배치는 기준 상자의 축만이
|
|
31
|
+
아니라 부품의 개구부·부착 좌표계를 직접 참조해야 한다. 검사는 상자의 연결 개수가 아니라 실제
|
|
32
|
+
접촉·맞춤을, 몇 가지 배율이 아니라 선언한 치수 범위·축소·운동 상태를 다뤄야 한다. 관계를
|
|
33
|
+
추가한다고 성능 이득이 보장되지는 않는다.
|
|
45
34
|
|
|
46
35
|
## 3. 형식적 문제 정의
|
|
47
36
|
|
|
@@ -195,7 +184,7 @@ geometry provider는 shape spec과 함께 해당 feature binding을 반환해야
|
|
|
195
184
|
compile:
|
|
196
185
|
schema/units/IDs → single writer check → resolve references
|
|
197
186
|
→ dependency DAG → cycle diagnostic → topological order
|
|
198
|
-
→ affine coefficients → domain obligations →
|
|
187
|
+
→ affine coefficients → domain obligations → Prepared
|
|
199
188
|
|
|
200
189
|
resolve(d):
|
|
201
190
|
check d∈D → evaluate dimensions/features/rest frames
|
|
@@ -317,7 +306,7 @@ inspectResolved(prepared, resolved, profile): Inspection
|
|
|
317
306
|
|
|
318
307
|
Prepared는 식/순서/컨테이너/feature binding/geometry spec/운동 구조를,
|
|
319
308
|
Resolved는 실제 크기/rigid frame/feature/slot/port를 반환한다.
|
|
320
|
-
source version,
|
|
309
|
+
source version, Prepared version, evaluator semantic version을 분리한다.
|
|
321
310
|
2D·3D는 같은 Resolved를 소비하고 관계 의미를 재구현하지 않는다.
|
|
322
311
|
|
|
323
312
|
compile은 자산 변경 시, layout은 치수 변경 시, pose는 상태 변경 시 처리한다.
|
|
@@ -339,7 +328,7 @@ driver는 실행 의미이므로 advisory로 무시할 수 없다. required/advi
|
|
|
339
328
|
|
|
340
329
|
| 상태 | 처리 |
|
|
341
330
|
| --- | --- |
|
|
342
|
-
| 불명 참조/순환/중복 writer | 실행 불가 진단, 작업 초안 보관 가능, 정상
|
|
331
|
+
| 불명 참조/순환/중복 writer | 실행 불가 진단, 작업 초안 보관 가능, 정상 자산으로 배포 불가 |
|
|
343
332
|
| domain 밖/음수 치수 | 해당 크기 사용 불가; 마지막 정상 표시라면 현재 결과가 아님을 명시 |
|
|
344
333
|
| required assertion 위반 | 선언한 지원 범위에서 발행 불가 |
|
|
345
334
|
| required assertion 미증명 | 위반 확정과 구분; 보장 정책/범위 조정 또는 추가 검증 필요 |
|
|
@@ -369,11 +358,9 @@ AI와 자동 수정은 typed edit API를 사용한다. 후보에 baseRevision/so
|
|
|
369
358
|
전역 차단 항목이 0이어야만 수정을 제공하는 조건은 폐기한다. 국소 해결과 남은 문제를 구분한다.
|
|
370
359
|
의미/외형을 훼손하며 검사만 통과한 후보를 안전하다고 표시하지 않는다.
|
|
371
360
|
|
|
372
|
-
## 16.
|
|
361
|
+
## 16. 식별자와 구현 단계
|
|
373
362
|
|
|
374
|
-
id는 불변, label은 표시 이름이다. 기존 name 기반 외부 참조는 자산
|
|
375
|
-
변환은 원본/hash 보존, v3 후보, 기계적 변환, 의도 선택, 미검증 진단을 반환한다.
|
|
376
|
-
v2의 잘못된 동작을 보존할 의무는 없다. 의도적으로 바뀐 외형은 승인된 차분으로 기록한다.
|
|
363
|
+
id는 불변, label은 표시 이름이다. 기존 name 기반 외부 참조는 자산 재작성 시 갱신한다.
|
|
377
364
|
초안 저장과 발행 조건을 분리한다. 미지원 consumer에 v3를 부분 해석해 보내지 않는다.
|
|
378
365
|
|
|
379
366
|
세부 구현 순서와 출하 조건은 [상위 레이아웃 계약 §12](v3-layout-system.md#12-출하-전-단계와-완료-기준)를 따른다.
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
|
|
46
46
|
## 제품 연결 시 주의점
|
|
47
47
|
|
|
48
|
-
현재 figure-ui의 `client/modeller/figure-source.ts`는 장면 파트를 저장용
|
|
48
|
+
현재 figure-ui의 `client/modeller/figure-source.ts`는 장면 파트를 저장용 이전 형식 source로 변환한다. `figure-inspector.ts`와 `figure-modeller-page.ts`의 update-part/update-draft 경로도 이전 형식의 draft/parts 중심이다. V3 graph를 이 경로의 `parts`로 가장해 전달하면 원본이 이중화된다.
|
|
49
49
|
|
|
50
|
-
제품 모델러·저장·AI·렌더러를 V3 단일 경로로 전환한다. 기존 자산은
|
|
50
|
+
제품 모델러·저장·AI·렌더러를 V3 단일 경로로 전환한다. 기존 자산은 V3로 재작성한다. 호환 분기는 만들지 않는다. 제품에서는 src에서 빌드한 공용 API를 사용한다.
|
|
51
51
|
|
|
52
52
|
## 아직 해결하지 않은 범위
|
|
53
53
|
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
- 브라우저: `node docs/prototypes/render-full-dryroom.mjs --conveyor`
|
|
12
12
|
- 전체 테스트: `node --test docs/prototypes/v3-*.test.mjs`
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## 끝 롤러 공간을 먼저 확보하는 이유
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
끝 공간을 따로 두지 않고 일반 롤러를 중심 간격 150mm로 길이 전체에 깔면, 기본 길이 2,400mm에서 일반 롤러는 16개다. 양 끝 일반 롤러 중심은 ±1,125mm이며, 별도의 굵은 끝 롤러 중심은 ±1,140mm다.
|
|
17
17
|
|
|
18
18
|
일반 롤러 반지름 48mm, 끝 롤러 반지름 75mm이고 중심 거리는 15mm이므로, `15 + 48 < 75`다. 일반 롤러 길이 520mm도 끝 롤러 길이 560mm보다 작다. 즉 **일반 롤러 두 개가 끝 롤러 내부에 완전히 묻힌다.** 축 방향 회전으로 이 문제는 해결되지 않는다.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
그래서 양쪽 끝 공간을 먼저 확보한다.
|
|
21
21
|
|
|
22
22
|
```
|
|
23
23
|
끝 여백 = 끝 롤러 중심의 가장자리 거리 60 + 반지름 75 + 최소 간격 10 = 145mm
|
package/docs/v3-layout-system.md
CHANGED
|
@@ -302,7 +302,7 @@ AI: 동일 typed transaction, sourceHash 사전조건, atomic apply, undo, 변
|
|
|
302
302
|
| L1 production kernel | schema/DAG/measure/allocate/arrange | cycle, writer, NaN, overflow, 결정성, fuzz |
|
|
303
303
|
| L2 geometry/motion | 모든 지원 primitive의 치수·feature 계약 | bounds/개구부/normal, shear, pose 합성 |
|
|
304
304
|
| L3 modeller | 계층 편집·미리보기·undo·AI transaction | 원클릭 편집, 동시 변경, 오류 복구 E2E |
|
|
305
|
-
| L4 consumer
|
|
305
|
+
| L4 consumer | 2D/3D 공통 결과 | 실제 드라이룸/롤 프레스, 회귀 스냅샷 |
|
|
306
306
|
| L5 비용/범위 | 1/100/500 instance, 범위 검증 | p95·draw call·메모리 실측, 증명 분류 |
|
|
307
307
|
|
|
308
308
|
r1은 레이아웃 규칙의 검토 가능한 기준안이다. 전체 v3 출하 명세/구현이 끝났다는 뜻이 아니다.
|
package/docs/v3-minimal-model.md
CHANGED
|
@@ -234,7 +234,6 @@ UI는 원인 입력을 수정하는 후보를 만들 수 있지만 evaluator가
|
|
|
234
234
|
- 값 DAG/feature frame은 반드시 scene node로 만들지 않는다. compile에서 정리한다.
|
|
235
235
|
- compile은 저작 변경, dimension resolve는 크기 변경, pose는 상태 변경 때 수행한다.
|
|
236
236
|
- 동일 치수/재질/운동의 병합·공유 가능성을 실제 renderer에서 측정한다.
|
|
237
|
-
- v2→v3 변환은 원본 보존, id/외부 binding 대응, 외형 차분, 의도 선택을 포함한다.
|
|
238
237
|
- 새 Figure는 독립 상태에서 시작하고 실패한 후보는 기존 장면에 덧붙이지 않는다.
|
|
239
238
|
- typed edit는 sourceHash 검사, 원자 적용, undo, 재송신 멱등성을 갖춘다.
|
|
240
239
|
- 발행 정책은 invalid / assertion violation / unverified / advisory를 구별한다.
|
|
@@ -2,12 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Status: **contract, fixed 2026-09-22; revised the same day after the chief architect's review; implemented the
|
|
4
4
|
same day** (ADR-0087 decision 2, ruling 4). Implementation: `src/v3-graph.ts` (`axis-turn@1`, `axis-slide@1`),
|
|
5
|
-
`src/v3-driver.ts` (`driverValue`, `driverStates`, `validateV3Drivers`),
|
|
6
|
-
|
|
7
|
-
defines motion on its own. Not yet covered by the converter: prismatic joints (none in the live assets; V2 scaled
|
|
8
|
-
their travel by the instance, the contract does not), scale channels (refused as shape deformation), a rotation
|
|
9
|
-
channel with a pivot off the part centre, channels that vary more than one axis, and parameter curves other than
|
|
10
|
-
two linear keys. The review changed three things: the direction of every transform is written down, continuous
|
|
5
|
+
`src/v3-driver.ts` (`driverValue`, `driverStates`, `validateV3Drivers`), tests in `src/v3-motion.test.ts`. Every
|
|
6
|
+
consumer uses this contract; none of them defines motion on its own. The review changed three things: the direction of every transform is written down, continuous
|
|
11
7
|
rotation is split into an accumulated amount and a phase, and drivers carry an explicit time convention.
|
|
12
8
|
|
|
13
9
|
## What a person sees
|
|
@@ -19,7 +15,7 @@ moves. Setting the value back to its default puts the arm exactly where it was d
|
|
|
19
15
|
|
|
20
16
|
On a board, the same arm has the same six values. A connector writes them; the arm follows. Stretching the arm's
|
|
21
17
|
instance size does not change where its joints turn: a joint sits on the part that carries it and moves with that
|
|
22
|
-
part under sizing
|
|
18
|
+
part under sizing.
|
|
23
19
|
|
|
24
20
|
## One rule for how a child moves, with every direction written down
|
|
25
21
|
|
|
@@ -37,15 +33,15 @@ part under sizing, as ADR-0066 decision 3 already says for V2.
|
|
|
37
33
|
- `jointParent` and `jointChild` are two named frames per joint, `<joint>.onParent` and `<joint>.onChild`. They
|
|
38
34
|
**coincide at `q = 0`**: `motion(0)` is the identity, and the two frames are placed so that the child then sits in
|
|
39
35
|
its rest pose.
|
|
40
|
-
- A part with no joint to its parent has `motion = identity
|
|
41
|
-
- The parent and child joint frames come from the rest pose and sizing
|
|
36
|
+
- A part with no joint to its parent has `motion = identity`.
|
|
37
|
+
- The parent and child joint frames come from the rest pose and sizing, so a joint moves
|
|
42
38
|
with the part that carries it when the instance is resized.
|
|
43
39
|
- `attach@1` already computes `A × O × inverse(B)`, and its type checker refuses a chain whose frames do not meet.
|
|
44
40
|
No parent-chain node is added; `compose@1` and `attach@1` are enough.
|
|
45
41
|
|
|
46
|
-
**`q = 0` is the rest pose. That is not the same claim as "the default is the rest pose."** A
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
**`q = 0` is the rest pose. That is not the same claim as "the default is the rest pose."** A state input's default
|
|
43
|
+
may be non-zero. The joint frames are placed for the pose at `q = 0`, and the state default is stored as authored;
|
|
44
|
+
nothing subtracts the default or forces it to 0.
|
|
49
45
|
|
|
50
46
|
## Joint kinds, their state input, and the two motion operators
|
|
51
47
|
|
|
@@ -64,10 +60,10 @@ axis-slide@1 args [ax, ay, az (ratio), q (length)] params { from, to }
|
|
|
64
60
|
- An arbitrary axis is carried as three numbers and turned with axis–angle. It is **never** collapsed into one
|
|
65
61
|
Euler component.
|
|
66
62
|
|
|
67
|
-
|
|
|
63
|
+
| joint type | state input | unit stored | `motion(q)` |
|
|
68
64
|
|---|---|---|---|
|
|
69
|
-
| `revolute` | one angle, `role: 'state'`,
|
|
70
|
-
| `prismatic` | one length, `role: 'state'`,
|
|
65
|
+
| `revolute` | one angle, `role: 'state'`, joint limits as range | rad (an input may declare `deg`; the kernel converts) | `axis-turn@1` |
|
|
66
|
+
| `prismatic` | one length, `role: 'state'`, joint limits as range | mm | `axis-slide@1` |
|
|
71
67
|
| `continuous` | one **phase** angle, `role: 'state'`, range `[−180°, 180°)` | rad | `axis-turn@1` |
|
|
72
68
|
|
|
73
69
|
### Continuous rotation: an amount and a phase, not a limit
|
|
@@ -86,16 +82,15 @@ values first would interpolate 350 → 10 and turn the wrong way. Widening the r
|
|
|
86
82
|
|
|
87
83
|
## Parameters
|
|
88
84
|
|
|
89
|
-
A
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
readers, which the graph already allows.
|
|
85
|
+
A parameter is a state input: `id` is its name, `unit` and `min`/`max` give its range, `role: 'state'`, and the
|
|
86
|
+
asset's `stateDefaults` carries its default. Its target is the joint (or part channel) whose `motion(q)` reads it. A
|
|
87
|
+
parameter that drives several joints is one input read by several `axis-turn@1` nodes: one writer, many readers,
|
|
88
|
+
which the graph already allows.
|
|
94
89
|
|
|
95
90
|
## Drivers: the asset declares, figure-model evaluates, the consumer owns time
|
|
96
91
|
|
|
97
|
-
The kernel has **no clock**. Same inputs, same result, always.
|
|
98
|
-
|
|
92
|
+
The kernel has **no clock**. Same inputs, same result, always. An animation is a **driver** declaration on the asset,
|
|
93
|
+
not a graph node. Responsibilities:
|
|
99
94
|
|
|
100
95
|
| who | does |
|
|
101
96
|
|---|---|
|
|
@@ -119,9 +114,7 @@ drivers: [{
|
|
|
119
114
|
```
|
|
120
115
|
|
|
121
116
|
- **Time convention, one for all drivers.** `time.unit` is seconds; `duration` is the clip length in seconds; every
|
|
122
|
-
key `at` is a fraction of the duration in `[0, 1]`.
|
|
123
|
-
`duration`, fractions in `at`, ADR-0051 ②) into exactly this and records the source form in the report. A driver
|
|
124
|
-
with a missing or non-positive duration is refused.
|
|
117
|
+
key `at` is a fraction of the duration in `[0, 1]`. A driver with a missing or non-positive duration is refused.
|
|
125
118
|
- **Loop end.** `wrap`: time `t` maps to `t mod duration`, and the sample at `duration` equals the sample at 0 (the
|
|
126
119
|
last key's value is reached at `at = 1` and the next period starts from key 0). For an accumulating driver, wrapping
|
|
127
120
|
adds the full-period delta to the accumulated value, so the roller keeps turning rather than snapping back.
|
|
@@ -131,45 +124,17 @@ drivers: [{
|
|
|
131
124
|
source per state** explicitly (`driver` or `external`). Values are never summed and "last call wins" is not a
|
|
132
125
|
rule. figure-model's validation refuses two drivers naming the same state.
|
|
133
126
|
|
|
134
|
-
A
|
|
135
|
-
|
|
136
|
-
clip with `accumulates: true`. The conveyor's rotation animation is therefore carried, not lost.
|
|
137
|
-
|
|
138
|
-
## What the converter does with the seven motion assets
|
|
139
|
-
|
|
140
|
-
1. For every `FigureJoint`: two joint frames from the rest pose and sizing, one state input, one `axis-turn@1` or
|
|
141
|
-
`axis-slide@1`, one `attach@1`, and the child's `place@1` reads the attached pose.
|
|
142
|
-
2. For every part with `parent` and no joint: `compose@1` of the parent's pose and the rigid offset.
|
|
143
|
-
3. For every `parameter`: a state input as above; refuse (`PARAMETER_TARGET`) if its target is not a joint or a part
|
|
144
|
-
channel this contract covers.
|
|
145
|
-
4. For every animation clip: a driver, with the clip's channels mapped to state inputs; refuse
|
|
146
|
-
(`ANIMATION_CHANNEL`) for a channel path this contract does not cover (`scale`).
|
|
127
|
+
A part that spins without a joint (the conveyor roller) has a continuous state input on that part, `<part>.spin`,
|
|
128
|
+
driving an `axis-turn@1` about the part's own axis, and a driver with `accumulates: true`.
|
|
147
129
|
|
|
148
130
|
## Two corrections to earlier wording
|
|
149
131
|
|
|
150
132
|
- **Rigid does not mean affine in the state.** A rigid pose is affine in the spatial coordinates it maps, but a
|
|
151
133
|
rotation matrix is a sin/cos function of the joint angle. So `axis-turn@1` is **not affine in `q`**, and the
|
|
152
134
|
operator-list guard is restated: `geomean@1` is the only node that is non-affine in the *design inputs*;
|
|
153
|
-
`axis-turn@1` is non-affine in a *state input*.
|
|
154
|
-
the rest pose and does not become a proof of equivalence under motion.
|
|
135
|
+
`axis-turn@1` is non-affine in a *state input*.
|
|
155
136
|
- **Rotation is compared as a relative angle**, the angle of `R₂ · R₁ᵀ`, never as a difference of Euler components.
|
|
156
137
|
|
|
157
|
-
## "The same" for motion (completion criterion)
|
|
158
|
-
|
|
159
|
-
For every converted motion asset, V2 and V3 are compared at the base size and the doubled sizes with:
|
|
160
|
-
|
|
161
|
-
- each joint at its default, its mid-point and both limits;
|
|
162
|
-
- **parent and child joints changed at the same time**, not one at a time;
|
|
163
|
-
- at least one joint with an arbitrary (non-principal) axis;
|
|
164
|
-
- a non-zero default, checked at the default and away from it;
|
|
165
|
-
- a continuous joint just before and just after the phase boundary (e.g. 179° and 181°);
|
|
166
|
-
- a looping driver just before and just after the loop end (e.g. 0.99 and 1.01 durations), and a `hold` driver past
|
|
167
|
-
its end.
|
|
168
|
-
|
|
169
|
-
Same part list, same centre and extents within 1 mm, same relative rotation within 0.1°. For each driver, the state
|
|
170
|
-
value at time 0, half and end must equal V2's clip value at those times. Exact conversion and deliberate
|
|
171
|
-
re-authoring are marked separately in the report.
|
|
172
|
-
|
|
173
138
|
## Not in this contract
|
|
174
139
|
|
|
175
140
|
- Inverse kinematics, reach checks, collision between links. Consumers may add them on top; the kernel does not.
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [V3 통합 현황](v3-status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
5
|
-
> 최신 작업 기준: [V3 단일 체계 전환](v3-cutover.md). 아래의
|
|
5
|
+
> 최신 작업 기준: [V3 단일 체계 전환](v3-cutover.md). 아래의 버전별 제품 연결 방향은 과거 작업 기록이며, 향후 설계 조건에서 제외한다.
|
|
6
6
|
|
|
7
7
|
## 이번 이관 범위
|
|
8
8
|
|
|
9
|
-
실험용 JSON 입력 검사와 오류 계약을 `src/v3-json.ts`, `src/v3-contract.ts`의 strict TypeScript 소스로 옮겼다. 기본 빌드에서 JS·타입 선언을 생성하며 기존 package 루트에서 이름이 구분된 API로 내보낸다. package.json
|
|
9
|
+
실험용 JSON 입력 검사와 오류 계약을 `src/v3-json.ts`, `src/v3-contract.ts`의 strict TypeScript 소스로 옮겼다. 기본 빌드에서 JS·타입 선언을 생성하며 기존 package 루트에서 이름이 구분된 API로 내보낸다. package.json·의존성은 변경하지 않았다.
|
|
10
10
|
|
|
11
11
|
| 공개 API | 책임 |
|
|
12
12
|
|---|---|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
| v3Utf8ByteLength | 브라우저와 서버의 동일 UTF-8 바이트 계산 |
|
|
16
16
|
| V3ContractError | code/path를 가진 공통 오류 |
|
|
17
17
|
|
|
18
|
-
**parseV3Json은 모델 의미 검증기가 아니다.** JSON
|
|
18
|
+
**parseV3Json은 모델 의미 검증기가 아니다.** JSON 형식만 올바르면 V3 자산이 아닌 객체도 읽는다. V3 자산 버전·단위·그래프·appearance 검사는 여전히 자산 컴파일러가 담당한다. 공개된 이름이 전체 V3 지원이나 안정화 완료를 뜻하지 않는다.
|
|
19
19
|
|
|
20
20
|
## 단일 구현 유지
|
|
21
21
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
2026-09-21:
|
|
29
29
|
|
|
30
|
-
- `npm test`:
|
|
30
|
+
- `npm test`: 당시 소스 전체와 새 입력 경계 검사 포함 **442개 통과**.
|
|
31
31
|
- `node --test docs/prototypes/v3-*.test.mjs`: **143개 통과**.
|
|
32
32
|
- `npm run build`: 성공, JS와 타입 선언 생성.
|
|
33
33
|
- `node docs/prototypes/v3-runtime-browser.mjs`: 실제 Chrome에서 빌드된 ESM 실행 성공. Buffer/process가 없는 상태에서 한글·이모지 UTF-8 계산과 이스케이프 중복 키 거부 확인.
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
## 그래프 평가기 이관
|
|
38
38
|
|
|
39
|
-
`src/v3-graph.ts`에 기존 평가기 전체를 옮기고 루트 API에 `compileV3Graph`를 추가했다.
|
|
39
|
+
`src/v3-graph.ts`에 기존 평가기 전체를 옮기고 루트 API에 `compileV3Graph`를 추가했다. `src/v3-graph-types.ts`는 입력/상수/노드, 단위·차원, 좌표계 타입, 형상·배치, 평가 결과와 컴파일된 계획의 공개 타입을 정의한다.
|
|
40
40
|
|
|
41
41
|
실험 진입점 `docs/prototypes/v3-typed-plan.mjs`는 두 export만 남긴 호환 어댑터다. 단위 계산·위상 정렬·좌표계 검사·형상 생성·반복 배치의 구현을 두 벌 유지하지 않는다. 기존 연산자 버전과 실패 코드를 유지했다.
|
|
42
42
|
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
| v3-asset.ts | compileV3Asset, parseV3Asset, serializeV3Asset, captureV3AuthoredInputs |
|
|
63
63
|
| v3-asset-types.ts | 문서·자산·재질·binding 선언 및 평가 결과 타입 |
|
|
64
64
|
|
|
65
|
-
버전 식별자는 기존 실험 버전을 유지한다. 정식 소스에 포함되었다고 파일 포맷 안정화나 제품 저장 허용을 선언하지 않는다. package.json
|
|
65
|
+
버전 식별자는 기존 실험 버전을 유지한다. 정식 소스에 포함되었다고 파일 포맷 안정화나 제품 저장 허용을 선언하지 않는다. package.json은 변경하지 않았다.
|
|
66
66
|
|
|
67
67
|
유지한 계약:
|
|
68
68
|
|
|
@@ -104,4 +104,4 @@ workspace 이관 당시 검증: 소스 테스트 **451개**, V3 실험 테스트
|
|
|
104
104
|
|
|
105
105
|
핵심 입력·그래프·capability·자산·편집 workspace는 src로 이관했다. 제품의 저장·발행·편집·렌더러를 V3 단일 체계로 전환해야 하며, 제품 연결은 아직 미완료다. 파일 저장 실험도 제품 DB 구현으로 간주하지 않는다. 접촉/충돌 연구 모듈과 대표 모델 생성기는 계속 실험 영역에 있다.
|
|
106
106
|
|
|
107
|
-
다음 단계는 V3 단일 저작·저장·렌더링 경로의 제품 연결이다. 기존 자산은 V3 기준으로 바꾼다.
|
|
107
|
+
다음 단계는 V3 단일 저작·저장·렌더링 경로의 제품 연결이다. 기존 자산은 V3 기준으로 바꾼다. 제품 API 배포는 아직 수행하지 않았다.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [V3 통합 현황](v3-status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
5
5
|
2026-09-20. [1차 검사](v3-sample-validation.md)의 후속이다.
|
|
6
|
-
|
|
6
|
+
**당시 기존 함수 검사 / 명시한 v3 의도 후보 계산 / 기구학 수치 실험**을 구별한다.
|
|
7
7
|
테스트가 통과했다는 것은 아래 관찰이 재현됐다는 뜻이며, 결함이 해결됐다는 뜻이 아니다.
|
|
8
8
|
제품 소스, 서버, 원본 샘플을 변경하지 않았다.
|
|
9
9
|
|
|
@@ -41,7 +41,7 @@ node --test docs/prototypes/v3-samples.test.mjs
|
|
|
41
41
|
|
|
42
42
|
### 로봇암: 좌표계는 가능하지만 링크 크기 변경은 별도 문제
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
원본 샘플의 position과 joint.origin은 정지 모델 좌표다. 이를 부모-relative offset과
|
|
45
45
|
자식-local pivot으로 변환한 뒤 `parent · rest · joint`로 계산했다.
|
|
46
46
|
관절 양쪽에서 계산한 동일 pivot의 월드 위치가 일치하는지 검사했다.
|
|
47
47
|
단순히 부품 중심 거리가 일정하다는 검사보다 구체적인 기구학 불변량이다.
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# V3 shape-dimension contract — per-axis radii, elliptic sections, and dimensions that follow state
|
|
2
2
|
|
|
3
3
|
Status: **contract, fixed 2026-09-22 by the V3 designer** (ADR-0087, stage-review rulings 3 and 5). §1 (per-axis
|
|
4
|
-
dimensions) implemented the same day: `cylinder-shape@2`, `rounded-box@2`, `hollow-box@2`, the
|
|
5
|
-
them
|
|
4
|
+
dimensions) implemented the same day: `cylinder-shape@2`, `rounded-box@2`, `hollow-box@2`, and the sampler reading
|
|
5
|
+
them. §2–3 implemented the same night: dependence on state is tracked per value in the
|
|
6
6
|
compiler and printed as `dependence` beside `outputTypes`; every operator carries a `state` policy (`follows` or
|
|
7
7
|
`refuses`; an operator without one fails with `STATE_POLICY`); `occupancy.extent` may not depend on state
|
|
8
8
|
(`OCCUPANCY_STATE`); `inspectV3Asset` covers the state range and reports `proven` (corners; no state-dependent
|
|
9
9
|
rotation), `sampled` (a rotation depends on state; corners plus per-input sweeps, step stated, not a proof) or
|
|
10
10
|
`defaults` (one state, as asked). The `bounded` method of §3 (swept envelope) is not implemented; such assets report
|
|
11
|
-
`sampled`.
|
|
12
|
-
parameters (`STATE_DIMENSION` note). This is one rule for what a shape's dimensions are and what they may depend on. It is not three
|
|
11
|
+
`sampled`. This is one rule for what a shape's dimensions are and what they may depend on. It is not three
|
|
13
12
|
exceptions bolted on for the three assets that needed them.
|
|
14
13
|
|
|
15
14
|
## What a person sees
|
|
@@ -19,11 +18,11 @@ cradle gets thinner: its radius shrinks, its length does not. The edge plates th
|
|
|
19
18
|
stay on its surface. Nothing else moves. At 0 % the roll is exactly the drawn roll.
|
|
20
19
|
|
|
21
20
|
An author stretches a kiosk to twice its width. The bezel's corners stay the same round in front view where the
|
|
22
|
-
section did not stretch, and go wider than they are tall where it did, because
|
|
23
|
-
back to a circle on its own.
|
|
21
|
+
section did not stretch, and go wider than they are tall where it did, because each corner radius follows its own
|
|
22
|
+
axis. Nothing pops back to a circle on its own.
|
|
24
23
|
|
|
25
24
|
An author opens the worker figure and stretches it sideways. The legs, which the author chose not to keep round,
|
|
26
|
-
become oval
|
|
25
|
+
become oval. The renderer draws the oval it is given. It never "fixes" it to a circle.
|
|
27
26
|
|
|
28
27
|
## 1. Every round thing has per-axis dimensions
|
|
29
28
|
|
|
@@ -32,7 +31,7 @@ A section is round only when its two cross dimensions are equal. The providers w
|
|
|
32
31
|
| operator | evaluated provider | dimensions | round when | status |
|
|
33
32
|
|---|---|---|---|---|
|
|
34
33
|
| `cylinder-shape@2` | `ellipticCylinder` | `radiusX`, `radiusZ`, `length` (axis Y) | `radiusX = radiusZ` | implemented 2026-09-22 |
|
|
35
|
-
| `frustum-shape@2` | — | `topRadiusX`, `topRadiusZ`, `bottomRadiusX`, `bottomRadiusZ`, `height` | pairs equal | not implemented
|
|
34
|
+
| `frustum-shape@2` | — | `topRadiusX`, `topRadiusZ`, `bottomRadiusX`, `bottomRadiusZ`, `height` | pairs equal | not implemented |
|
|
36
35
|
| `sphere-shape@1` | `sphere` | `radiusX`, `radiusY`, `radiusZ` (already so) | all equal | implemented |
|
|
37
36
|
| `rounded-box@2` | `roundedBoxXZ` | `width`, `height`, `depth`, `roundX`, `roundZ` | `roundX = roundZ` | implemented 2026-09-22 |
|
|
38
37
|
| `hollow-box@2` | `hollowBoxXZ` | as `hollow-box@1` with `roundX`, `roundZ` in place of `round` | same | implemented 2026-09-22 |
|
|
@@ -41,38 +40,32 @@ The evaluated provider name is distinct from the `@1` one so a renderer can neve
|
|
|
41
40
|
single radius. Features on `ellipticCylinder` are `start` and `end` only; `radialBottom` has no single meaning on an
|
|
42
41
|
ellipse.
|
|
43
42
|
|
|
44
|
-
- `@1` of each provider stays valid and means the equal case
|
|
45
|
-
unequal section. Nothing that exists today is invalidated.
|
|
43
|
+
- `@1` of each provider stays valid and means the equal case. `@2` is needed only for an unequal section.
|
|
46
44
|
- **The renderer draws what it is given.** An elliptic section is an ellipse; an elliptic corner is the quadratic
|
|
47
45
|
Bézier from `(hw − roundX, −hd)` to `(hw, −hd + roundZ)` with the corner `(hw, −hd)` as control point, which is
|
|
48
|
-
what things-scene's `roundedRect` draws
|
|
49
|
-
|
|
50
|
-
section to a circle is wrong, and the mesh-level comparison of the completion criterion is what catches it.
|
|
46
|
+
what things-scene's `roundedRect` draws. It is not a circular or elliptic arc: an arc differs from the Bézier by
|
|
47
|
+
up to 0.06 × round at the corner's middle. A renderer that snaps a section to a circle is wrong.
|
|
51
48
|
- Validity: every dimension positive (a corner radius may be 0), `roundX ≤ width/2`, `roundZ ≤ depth/2`. A
|
|
52
|
-
declared corner larger than the section is refused at compile
|
|
53
|
-
what V2 drew (ruling 2) and reports it.
|
|
49
|
+
declared corner larger than the section is refused at compile.
|
|
54
50
|
|
|
55
|
-
###
|
|
51
|
+
### A round section under non-uniform sizing
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
What happens to a round section when the instance is sized differently along its two cross axes is not a flag. It
|
|
54
|
+
is two possible expressions for two dimensions:
|
|
59
55
|
|
|
60
56
|
```
|
|
61
|
-
kept round radiusX = radiusZ = r₀ · geomean(fx, fz)
|
|
62
|
-
follows axes radiusX = r₀ · fx, radiusZ = r₀ · fz
|
|
57
|
+
kept round radiusX = radiusZ = r₀ · geomean(fx, fz)
|
|
58
|
+
follows axes radiusX = r₀ · fx, radiusZ = r₀ · fz
|
|
63
59
|
```
|
|
64
60
|
|
|
65
|
-
Both are ordinary length expressions
|
|
66
|
-
|
|
67
|
-
corner written with two semi-axes. The same two shapes apply to corners: V2 scaled a rounded box's finished mesh
|
|
68
|
-
per axis, so a corner drawn with radius `r₀` becomes `roundX = r₀·fx`, `roundZ = r₀·fz`. That is what
|
|
69
|
-
`ROUND_NOT_SCALED` (40 parts in the last run) was reporting as a loss; with `@2` corners it is no longer a loss.
|
|
61
|
+
Both are ordinary length expressions; the author chooses which one to write. The same two shapes apply to corners:
|
|
62
|
+
a corner drawn with radius `r₀` that follows the axes is `roundX = r₀·fx`, `roundZ = r₀·fz`.
|
|
70
63
|
|
|
71
64
|
## 2. A dimension may depend on state
|
|
72
65
|
|
|
73
66
|
A state input (`role: 'state'`) may be an argument of a shape or length node. A consumed roll's radius is
|
|
74
67
|
`r₀ − fed · k`; a lamp's glow radius grows with the gate. This is the core-semantics §2 invariant ("state changes the
|
|
75
|
-
actual shape dimension") made concrete
|
|
68
|
+
actual shape dimension") made concrete. A dimension that scales with a state input is `dims × affine(p)`.
|
|
76
69
|
|
|
77
70
|
### Dependence is tracked in the type, apart from unit and frame
|
|
78
71
|
|
|
@@ -114,30 +107,14 @@ range, and says how it knows:
|
|
|
114
107
|
- The endpoint-only shortcut is **wrong** for a rotating long part: inside at both end angles, out in the middle.
|
|
115
108
|
That case takes the `bounded` row, not the `proven` one.
|
|
116
109
|
|
|
117
|
-
## 4.
|
|
118
|
-
|
|
119
|
-
- V2 cylinder with `keepRound: false` and differing cross factors → `cylinder-shape@2` with `radiusX`, `radiusZ`
|
|
120
|
-
following their own axes. WORKER converts; `ELLIPTIC_SECTION` is retired.
|
|
121
|
-
- V2 rect or hollow rect whose section follows the instance → `rounded-box@2` / `hollow-box@2` with per-axis corner
|
|
122
|
-
radii `r·fx`, `r·fz`. `ROUND_NOT_SCALED` is retired.
|
|
123
|
-
- V2 `scale` channel on a part, two linear keys, from a parameter → each scaled dimension becomes
|
|
124
|
-
`dim × affine(p)`; the part's centre is unchanged (V2 scaled about the part centre). The dependence set of every
|
|
125
|
-
affected length includes the parameter. DRY_ROOM's lamps and ROLL_CRADLE's roll convert; `ANIMATION_CHANNEL`
|
|
126
|
-
stays only for channels the contract does not cover (pivots, compound axes, curves other than two linear keys).
|
|
127
|
-
- The report marks every state-dependent dimension it wrote, and the occupancy inspection of a converted asset
|
|
128
|
-
runs over the parameter ranges as §3 says.
|
|
129
|
-
|
|
130
|
-
## 5. Completion criterion for this contract
|
|
110
|
+
## 4. Completion criterion for this contract
|
|
131
111
|
|
|
132
112
|
- The four providers' `@2` forms compile, evaluate, and their `@1` forms are unchanged (the operator-list guard
|
|
133
113
|
gains the four names).
|
|
134
114
|
- Dependence appears in `outputTypes`; a synthetic new operator with no policy fails to compile when handed a
|
|
135
115
|
state-dependent value; `fit-pitch@1` and `fixed-count@1` still refuse it; a shape provider accepts it.
|
|
136
|
-
- The three assets convert and match V2 at box level at 8 sizes × states, and the WORKER's legs match as ovals.
|
|
137
116
|
- An occupancy check on the roll cradle reports `proven` over the `fed` range, and a synthetic rotating long part
|
|
138
117
|
reports `bounded`, with a violation found at a middle angle that the endpoints alone would have missed.
|
|
139
|
-
- The mesh-level comparison of the completion criterion covers sections and corners, so an elliptic section drawn
|
|
140
|
-
round would fail it.
|
|
141
118
|
|
|
142
119
|
## Not in this contract
|
|
143
120
|
|
|
@@ -145,10 +122,9 @@ range, and says how it knows:
|
|
|
145
122
|
- Shape deformation beyond dimensions: bending, twisting, free-form profiles that change with state. Those would be
|
|
146
123
|
new providers with their own contracts.
|
|
147
124
|
|
|
148
|
-
##
|
|
125
|
+
## 5. 표시 여부 (visibility) — 안 보이는 것과 작은 것은 다르다
|
|
149
126
|
|
|
150
|
-
**V3 설계자 결정 2026-09-22.**
|
|
151
|
-
않는다. 0 을 아주 작은 양수로 바꾸는 것도 쓰지 않는다 — 확대·그림자·포인터 선택에서 차이가
|
|
127
|
+
**V3 설계자 결정 2026-09-22.** 부품을 숨기려고 크기를 0 으로 만들지 않는다. 0 을 아주 작은 양수로 바꾸는 것도 쓰지 않는다 — 확대·그림자·포인터 선택에서 차이가
|
|
152
128
|
생기고, 「안 보임」이 「아주 작음」이 되어 버린다.
|
|
153
129
|
|
|
154
130
|
### 규칙
|
|
@@ -172,19 +148,9 @@ range, and says how it knows:
|
|
|
172
148
|
|
|
173
149
|
| 목록 | 무엇이 들어가는가 | 누가 쓰는가 |
|
|
174
150
|
| --- | --- | --- |
|
|
175
|
-
| `v3WorldBoxesOf` | 그리는 몸통만 (`visible === false` 제외) | renderer
|
|
151
|
+
| `v3WorldBoxesOf` | 그리는 몸통만 (`visible === false` 제외) | renderer |
|
|
176
152
|
| `v3OccupiedBoxesOf` | 놓인 몸통 전부 (숨긴 것 포함) | occupancy 검사 |
|
|
177
153
|
|
|
178
|
-
### 변환기가 V2 의 scale 0 을 옮기는 방법
|
|
179
|
-
|
|
180
|
-
채널이 **모든 변하는 축에서 0 으로 시작하고, 처음 0 이 아닌 key 부터 끝까지 정확히 1** 이면
|
|
181
|
-
(= 부품 제 크기) visibility 로 옮긴다. 부품은 제 치수를 계속 갖고, flag 가 그 key 의 `at` 에서
|
|
182
|
-
켜진다. 그 외 — 숨기면서 크기도 바꾸는 채널 — 은 `SCALE_ZERO` 로 거절한다.
|
|
183
|
-
|
|
184
|
-
이것은 **의도적 재저작이다**(`method: 're-authored'`, `RE_AUTHORED_VISIBILITY` note). 0 과
|
|
185
|
-
문턱 사이에서 V2 는 자라나는 부품을 그리고 V3 는 안 그린다. DRY_ROOM 에서 실측했다: 문턱은
|
|
186
|
-
파라미터 범위의 1 %, 그 밖 모든 상태에서 V2 와 같고 차이는 그 1 % 안에서만 난다.
|
|
187
|
-
|
|
188
154
|
## When `proven` may be said (added 2026-09-23, after two counterexamples from the V3 designer)
|
|
189
155
|
|
|
190
156
|
`proven` means the gate evaluated the corners of the state box and nothing else. That is only a proof when every
|
package/docs/v3-status.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
> **2026-09-22 — this file is a progress note, not the document of record.** The decision and the order of work are
|
|
4
4
|
> `operato-application/adr/ADR-0087.md`; the current state is the app's
|
|
5
|
-
> `operato-application/packages/operato-figure/docs/CURRENT_STATUS.md
|
|
5
|
+
> `operato-application/packages/operato-figure/docs/CURRENT_STATUS.md`. Where this
|
|
6
6
|
> file disagrees with those two, they win.
|
|
7
7
|
|
|
8
8
|
기준일: 2026-09-21. **현재 상태를 판단하는 문서다.** 개별 연구·검증 문서의 과거 단계 수치나 '다음 단계'보다 이 현황을 우선한다.
|
|
9
9
|
|
|
10
10
|
## 제품 방향
|
|
11
11
|
|
|
12
|
-
모델러·AI
|
|
12
|
+
모델러·AI·저장·렌더러는 **V3(`figure-v3-asset-1`) 하나**를 쓴다. V2와 V1은 2026-09-26 코드와 명세에서 제거했다(ADR-0087 전환을 제거로 마쳤다). [전환 결정](v3-cutover.md)
|
|
13
13
|
|
|
14
14
|
## 완료 범위와 미완료 범위
|
|
15
15
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
## 검증 근거
|
|
29
29
|
|
|
30
|
-
- `
|
|
30
|
+
- `node --test src/*.test.ts`: 소스 **286개 통과**(2026-09-26, V2·V1 제거 뒤). 시험 수이며 V3 기능 수가 아니다.
|
|
31
31
|
- `node --test docs/prototypes/v3-*.test.mjs`: 실험 **143개 통과**.
|
|
32
32
|
- `npm run build`: 타입 선언·JS 생성 성공.
|
|
33
33
|
- `node docs/prototypes/v3-runtime-browser.mjs`: Chrome에서 빌드된 모듈 실행, 네 대표 모델(드라이룸·컨베이어·로봇암·포크리프트)의 계산값/형상/재질/binding을 Node와 비교.
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
4. [자산 계약](v3-asset-persistence.md), [저장 검증](v3-storage-integration.md).
|
|
44
44
|
5. [V3 단일 전환](v3-cutover.md).
|
|
45
45
|
|
|
46
|
-
다음 작업은 모델러의 사용자 동작·AI·실제 저장·렌더링을 이 공용 V3 구현에 연결하는 것이다.
|
|
46
|
+
다음 작업은 모델러의 사용자 동작·AI·실제 저장·렌더링을 이 공용 V3 구현에 연결하는 것이다.
|
|
47
47
|
|
|
48
48
|
## 제품 연결 작업 추가 기록 (2026-09-21)
|
|
49
49
|
|
|
50
|
-
things-factory의 `packages/figure-ui/docs/v3-product-cutover.md`에 제품 전환 진행 상태를 기록했다. V3 제품 세션·캔버스·편집 컴포넌트·저장 API와 페이지를 작성했으나, 기본 route는 아직 교체하지 않았다. 로컬 활성 자산32
|
|
50
|
+
things-factory의 `packages/figure-ui/docs/v3-product-cutover.md`에 제품 전환 진행 상태를 기록했다. V3 제품 세션·캔버스·편집 컴포넌트·저장 API와 페이지를 작성했으나, 기본 route는 아직 교체하지 않았다. 당시 로컬 활성 자산 32개는 아직 V3로 전환되지 않았고, 자산 전환·AI 도구·발행/소비처 연결이 남아 있었다. UI241개 테스트 및 클라이언트/서비스 타입 검사 통과는 V3 제품 end-to-end 검증 완료를 뜻하지 않는다. 운영 DB 데이터 변경이나 배포는 하지 않았다.
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
## 왜 기존 저장 API에 바로 연결하지 않았는가
|
|
14
14
|
|
|
15
|
-
제품 figure-service의 `figure-source.ts`는
|
|
15
|
+
당시 제품 figure-service의 `figure-source.ts`는 이전 형식의 검증·컴파일·비용·점수 함수를 호출했다. `figure-mutation.ts`의 생성·수정·되돌리기와 발행도 그 검사 경로를 사용했다. figure-ui도 draft/parts를 직접 편집한다.
|
|
16
16
|
|
|
17
|
-
실험 포맷만 허용하면 저장은 되지만 기존 소비자가 읽을 수 없는 자산이 된다. 따라서 **제품 V3 경로 연결은 아직 미완료**다. 실험 코드의 직접 import, package.json 변경,
|
|
17
|
+
실험 포맷만 허용하면 저장은 되지만 기존 소비자가 읽을 수 없는 자산이 된다. 따라서 **제품 V3 경로 연결은 아직 미완료**다. 실험 코드의 직접 import, package.json 변경, 기존 검증 우회는 하지 않았다.
|
|
18
18
|
|
|
19
19
|
## 저장 계약
|
|
20
20
|
|
|
@@ -51,8 +51,8 @@ scope/id 조합을 해시한 파일명으로 사용해 사용자 식별자를
|
|
|
51
51
|
## 제품 연결 순서
|
|
52
52
|
|
|
53
53
|
1. 입력·그래프·capability·문서·자산·편집 workspace의 정식 소스 이관은 [완료](v3-runtime-extraction.md)했다. 이 모듈들을 제품에 반영한다.
|
|
54
|
-
2. figure-service의 저장·조회·발행을 V3 단일 기준으로 전환하고 저장 revision CAS를 구현한다.
|
|
55
|
-
3. figure-ui와 렌더러·AI를 V3 단일 경로에 연결한다. 기존 자산은 V3로
|
|
54
|
+
2. figure-service의 저장·조회·발행을 V3 단일 기준으로 전환하고 저장 revision CAS를 구현한다.
|
|
55
|
+
3. figure-ui와 렌더러·AI를 V3 단일 경로에 연결한다. 기존 자산은 V3로 재작성한다.
|
|
56
56
|
4. 실제 인증·DB로 두 편집 세션의 충돌, 저장 실패, 재접속, 모델 전환, AI 늦은 응답을 검증한다.
|
|
57
57
|
|
|
58
58
|
이 문서의 완료 범위는 저장 경계의 실행 가능한 검증이며, 제품 연결·배포 완료가 아니다.
|