@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.
- package/dist/asset-types.d.ts +34 -3
- package/dist/asset-types.d.ts.map +1 -1
- package/dist/capabilities.js +28 -4
- package/dist/capabilities.js.map +1 -1
- package/dist/graph-types.d.ts +60 -1
- package/dist/graph-types.d.ts.map +1 -1
- package/dist/graph.d.ts.map +1 -1
- package/dist/graph.js +212 -21
- package/dist/graph.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/kernel-version.d.ts +1 -1
- package/dist/kernel-version.js +1 -1
- package/docs/assembly-constraints.md +3 -3
- package/docs/asset-persistence.md +8 -8
- package/docs/authoring-transactions.md +2 -2
- package/docs/capability-bindings.md +1 -1
- package/docs/common-kernel-experiment.md +2 -2
- package/docs/completeness-review-2026-10-04.md +150 -1
- package/docs/core-semantics.md +2 -2
- package/docs/cutover.md +4 -4
- package/docs/document-contract.md +3 -3
- package/docs/dryroom-profile-validation.md +1 -1
- package/docs/editor-integration.md +4 -4
- package/docs/evaluation-changes-design.md +304 -0
- package/docs/evaluation-performance-summary-2026-10-05.md +218 -0
- package/docs/full-conveyor-validation.md +8 -8
- package/docs/full-dryroom-validation.md +5 -5
- package/docs/full-forklift-validation.md +5 -5
- package/docs/full-robot-validation.md +4 -4
- package/docs/layout-system.md +2 -2
- package/docs/legacy-risk-audit-2026-09-23.md +14 -14
- package/docs/minimal-model.md +3 -3
- package/docs/openusd-review.md +14 -14
- package/docs/operator-contracts.md +4 -4
- package/docs/prototypes/README.md +2 -2
- package/docs/prototypes/asset.schema.json +1 -1
- package/docs/prototypes/document.schema.json +1 -1
- package/docs/prototypes/editor-browser.mjs +2 -2
- package/docs/prototypes/linear-comparison.py +1 -1
- package/docs/prototypes/render-dryroom.py +1 -1
- package/docs/prototypes/render-full-dryroom.mjs +12 -12
- package/docs/prototypes/runtime-browser.mjs +3 -3
- package/docs/research-review.md +1 -1
- package/docs/review-2026-09-22.md +19 -19
- package/docs/runtime-extraction.md +10 -10
- package/docs/sample-validation-expanded.md +5 -5
- package/docs/sample-validation.md +5 -5
- package/docs/shape-dimension-contract.md +1 -1
- package/docs/spatial-contracts.md +2 -2
- package/docs/status.md +1 -1
- package/docs/storage-integration.md +5 -5
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "Experimental
|
|
3
|
+
"title": "Experimental Figure asset envelope; not a complete V2 migration contract",
|
|
4
4
|
"type": "object", "additionalProperties": false,
|
|
5
5
|
"required": ["version", "name", "document", "designInputs", "stateDefaults", "palette", "appearance"],
|
|
6
6
|
"properties": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "Experimental
|
|
3
|
+
"title": "Experimental Figure graph and capability document (not the complete Figure asset format)",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"additionalProperties": false,
|
|
6
6
|
"required": ["version", "model", "capabilities"],
|
|
@@ -16,9 +16,9 @@ import {geometryOf as portal} from './full-dryroom.mjs'
|
|
|
16
16
|
const directory=await mkdtemp(join(tmpdir(),'editor-store-'))
|
|
17
17
|
const store=createAssetStore(directory),workspace=createEditorWorkspace();let saved=null,storage=null
|
|
18
18
|
const view=()=>{const v=workspace.read();return {...v,render:v.geometry.map(g=>{const mesh=(g.shape.provider==='portal'?portal:ordinary)(g);const json=mesh.toJSON();mesh.dispose();return {id:g.id,geometry:json,material:g.material}})}}
|
|
19
|
-
const html=`<!doctype html><meta charset="utf-8"><title>
|
|
19
|
+
const html=`<!doctype html><meta charset="utf-8"><title>Figure 편집 연결 검증</title>
|
|
20
20
|
<style>body{margin:0;font:14px system-ui;color:#263543;background:#eef2f6}header{padding:16px;display:flex;gap:10px;align-items:center;background:white;border-bottom:1px solid #ccd5dd}main{display:grid;grid-template-columns:1fr 340px;height:650px}aside{padding:18px;background:white;overflow:auto}h2{font-size:15px;margin:22px 0 12px}label{display:grid;grid-template-columns:110px 1fr 46px;align-items:center;gap:8px;margin:8px 0}input,button,select{height:36px;box-sizing:border-box;border:1px solid #bdc9d2;border-radius:5px;background:white;padding:5px 8px}input{min-width:0;width:100%}button{cursor:pointer}#canvas{overflow:hidden}#status{padding:12px}#error{color:#a12626;white-space:pre-wrap}small{color:#526574}</style>
|
|
21
|
-
<header><strong>
|
|
21
|
+
<header><strong>Figure 편집 연결 검증</strong><button id="new">새 Figure</button><button id="add">상자 추가</button><select id="model"><option value="forklift">포크리프트</option><option value="robot">로봇암</option><option value="conveyor">컨베이어</option><option value="dryroom">드라이룸</option></select><button id="open">열기</button><button id="undo">되돌리기</button><button id="redo">다시 실행</button><button id="save">검증 저장</button><button id="reload">저장본 열기</button><button id="close">빈 화면</button></header>
|
|
22
22
|
<main><section><div id="canvas"></div><div id="status"></div></section><aside><small>제품 화면이 아닌 격리된 실험 UI · 임시 파일에 저장</small><div id="fields"></div><p id="error" role="alert"></p></aside></main>
|
|
23
23
|
<script type="module">
|
|
24
24
|
import * as T from '/three.module.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Independent linear design comparison; not a production evaluator.
|
|
2
2
|
Requires kiwisolver==1.4.9 in an isolated research environment.
|
|
3
|
-
Run: python docs/prototypes/
|
|
3
|
+
Run: python docs/prototypes/linear-comparison.py
|
|
4
4
|
All lengths mm. No external research implementation is copied.
|
|
5
5
|
"""
|
|
6
6
|
import itertools
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Software orthographic rendering of the actual generated triangle meshes.
|
|
2
|
-
Input: JSON from
|
|
2
|
+
Input: JSON from dryroom-mesh.mjs on stdin. Requires Pillow, no product changes.
|
|
3
3
|
Output path must be explicitly supplied. Not a screenshot of the product renderer.
|
|
4
4
|
"""
|
|
5
5
|
import json,sys,math
|
|
@@ -30,29 +30,29 @@ function payloadVariants(){
|
|
|
30
30
|
const variants=isPayload?payloadVariants():isForklift?[
|
|
31
31
|
{title:'Source seed · rest pose',parts:pack(forklift.seed.parts.map(p=>({id:p.name,material:p.material,geometry:forklift.sourceGeometry(p)})))},
|
|
32
32
|
...[
|
|
33
|
-
['
|
|
34
|
-
['
|
|
35
|
-
['
|
|
33
|
+
['Figure · same rest pose',forklift.defaults],
|
|
34
|
+
['Figure · lift 1000 / reach 200 / drive 37',{...forklift.defaults,lift:1000,reach:200,drive:37}],
|
|
35
|
+
['Figure · longer forks / lift 2000 / reach 400',{forkLength:1275,lift:2000,reach:400,drive:73}]
|
|
36
36
|
].map(([title,args])=>({title,parts:pack(forklift.evaluateFull(args).map(x=>({...x,geometry:forklift.geometryOf(x)})))}))
|
|
37
37
|
]:isRobot?[
|
|
38
38
|
{title:'Source fixture · rest pose',parts:pack(robot.seed.parts.map(p=>({id:p.name,material:p.material??{token:'palette.neutral'},geometry:robot.sourceGeometry(p)})))},
|
|
39
39
|
...[
|
|
40
|
-
['
|
|
41
|
-
['
|
|
42
|
-
['
|
|
40
|
+
['Figure · same rest pose',robot.defaults],
|
|
41
|
+
['Figure · six joints + gripper',robotPose],
|
|
42
|
+
['Figure · changed link lengths + same joints',{...robotPose,upperLength:630,foreLength:570}]
|
|
43
43
|
].map(([title,args])=>({title,parts:pack(robot.evaluateFull(args).map(x=>({...x,geometry:robot.geometryOf(x)})))}))
|
|
44
44
|
]:isConveyor?[
|
|
45
45
|
{title:'Source seed · overlapping end rollers',parts:pack(conveyor.sourceItems())},
|
|
46
46
|
...[
|
|
47
|
-
['
|
|
48
|
-
['
|
|
49
|
-
['
|
|
47
|
+
['Figure · reserved end roller space',conveyor.defaults],
|
|
48
|
+
['Figure · roller rotation 37 degrees',{...conveyor.defaults,angle:37}],
|
|
49
|
+
['Figure · resized assembly',{length:3000,width:900,rollerHeight:700,angle:37}]
|
|
50
50
|
].map(([title,args])=>({title,parts:pack(conveyor.evaluateFull(args).map(x=>({...x,geometry:conveyor.geometryOf(x)})))}))
|
|
51
51
|
]:[
|
|
52
52
|
{title:'Source seed · six parts',parts:pack(seed.parts.map(p=>({id:p.name,material:p.material,geometry:sourceGeometry(p)})))},
|
|
53
|
-
{title:'
|
|
54
|
-
{title:'
|
|
55
|
-
{title:'
|
|
53
|
+
{title:'Figure · same dimensions',parts:fromFigure(defaults)},
|
|
54
|
+
{title:'Figure · portal bottom trimmed to floor',parts:fromFigure({...defaults,bottom:0})},
|
|
55
|
+
{title:'Figure · resized + lamps raised',parts:fromFigure({...defaults,width:4800,height:3600,depth:7200,bottom:0,lampLift:100})}
|
|
56
56
|
]
|
|
57
57
|
const html=`<!doctype html><meta charset="utf-8"><style>body{margin:0;background:#e9edf2;font:16px sans-serif;color:#17283b}main{display:grid;grid-template-columns:1fr 1fr;gap:12px;padding:12px}section{background:white;border-radius:8px;overflow:hidden}h3{margin:12px;font-size:16px}canvas{display:block;width:100%}p{margin:12px;font-size:12px}</style><main></main><script type="module">
|
|
58
58
|
import * as T from '/three.module.js';
|
|
@@ -15,9 +15,9 @@ const graphEntry=url(graphSource.replace('./contract.js',contract))
|
|
|
15
15
|
const modules=new Map()
|
|
16
16
|
async function moduleUrl(name){
|
|
17
17
|
if(modules.has(name))return modules.get(name)
|
|
18
|
-
assert.match(name,/^
|
|
18
|
+
assert.match(name,/^[a-z-]+\.js$/)
|
|
19
19
|
let code=await readFile(new URL('../../dist/'+name,import.meta.url),'utf8')
|
|
20
|
-
for(const match of [...code.matchAll(/from ['"]\.\/(
|
|
20
|
+
for(const match of [...code.matchAll(/from ['"]\.\/([a-z-]+\.js)['"]/g)]){
|
|
21
21
|
code=code.replace(match[0],'from '+JSON.stringify(await moduleUrl(match[1])))
|
|
22
22
|
}
|
|
23
23
|
const entry=url(code);modules.set(name,entry);return entry
|
|
@@ -64,7 +64,7 @@ try{
|
|
|
64
64
|
console.log(JSON.stringify({browserWorkspace:editing},null,2))
|
|
65
65
|
const authored=await page.evaluate(async({createEntry,assetEntry,workspaceEntry})=>{
|
|
66
66
|
const c=await import(createEntry),a=await import(assetEntry),w=(await import(workspaceEntry)).createFigureEditorWorkspace()
|
|
67
|
-
const empty=c.createFigureAsset('New
|
|
67
|
+
const empty=c.createFigureAsset('New Figure'),emptyCount=a.compileFigureAsset(empty).evaluate().geometry.length
|
|
68
68
|
const model=c.addFigureBox(empty,{id:'gate',size:{x:800,y:2000,z:100},position:{x:0,y:1000,z:0}})
|
|
69
69
|
const opened=w.open(a.serializeFigureAsset(model))
|
|
70
70
|
w.apply({context:opened.context,origin:'ui',expectedRevision:0,changes:[{kind:'set-design',input:'gate.size.y',unit:'mm',value:1500}]})
|
package/docs/research-review.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Figure 평가 — figure 레인, 2026-09-22
|
|
2
2
|
|
|
3
3
|
figure-model 0.1.32 (`54d30c2`) 기준. 문서를 읽고 판단한 것이 아니라 **돌려서 확인한 것**을 적는다.
|
|
4
4
|
확인에 쓴 명령은 항목마다 적어 두었다.
|
|
@@ -6,7 +6,7 @@ figure-model 0.1.32 (`54d30c2`) 기준. 문서를 읽고 판단한 것이 아니
|
|
|
6
6
|
## 한 줄
|
|
7
7
|
|
|
8
8
|
**수학은 선다. 전환 경로가 없다.** 커널의 핵심 주장은 실측으로 성립하고 구현도 하나로 모여 있다.
|
|
9
|
-
막는 것은 설계가 아니라 **살아 있는 자산 32 개를
|
|
9
|
+
막는 것은 설계가 아니라 **살아 있는 자산 32 개를 지금 형식으로 옮길 길이 아직 없다**는 것이다.
|
|
10
10
|
|
|
11
11
|
## 1. 선 것 — 확인함
|
|
12
12
|
|
|
@@ -16,10 +16,10 @@ figure-model 0.1.32 (`54d30c2`) 기준. 문서를 읽고 판단한 것이 아니
|
|
|
16
16
|
`src/graph.ts` 를 다시 내보낸다. 실험 143 개가 **제품 소스를 시험하고 있다.**
|
|
17
17
|
|
|
18
18
|
```
|
|
19
|
-
src/
|
|
19
|
+
src/ Figure 모듈 13 개 · 2,266 줄(시험 포함)
|
|
20
20
|
index.ts 10 개를 내보낸다 — compileFigureGraph · createFigureAsset · …
|
|
21
21
|
npm test 461 통과 · 0 빨강
|
|
22
|
-
node --test docs/prototypes
|
|
22
|
+
node --test docs/prototypes/*.test.mjs 143 통과 · 0 빨강
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### 핵심 주장이 실측으로 성립한다
|
|
@@ -44,34 +44,34 @@ CYCLE: a: a -> b -> a
|
|
|
44
44
|
|
|
45
45
|
### 현황 문서가 정직하다
|
|
46
46
|
|
|
47
|
-
`status.md` 가 격리 UI 의 성공을 제품 배포로 적지 않고, 「소스 455 통과」가
|
|
47
|
+
`status.md` 가 격리 UI 의 성공을 제품 배포로 적지 않고, 「소스 455 통과」가 Figure 기능 수가
|
|
48
48
|
아니라고 먼저 밝힌다. 오늘 이 집이 여러 번 틀린 자리를 그쪽은 안 틀렸다.
|
|
49
49
|
|
|
50
50
|
## 2. 위험 — 위험 순
|
|
51
51
|
|
|
52
52
|
### ① 전환 경로가 없다. 자산 32 개를 손으로 다시 쓴다
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
**옛 형식(V2)에서 지금 형식으로 바꾸는 변환기가 없다.** 이름으로도 동작으로도 찾지 못했다.
|
|
55
55
|
|
|
56
|
-
`cutover.md` 는 「기존 자산도
|
|
56
|
+
`cutover.md` 는 「기존 자산도 지금 형식 기준으로 변환하거나 재작성한다」고 적는데, **변환**에
|
|
57
57
|
해당하는 것이 없고 재작성만 있다. 네 대표 자산(드라이룸·컨베이어·로봇암·포크리프트)은
|
|
58
|
-
V2 seed 를 읽어 **결과를 견주는 용도**로 쓰고,
|
|
58
|
+
V2 seed 를 읽어 **결과를 견주는 용도**로 쓰고, 지금 형식 쪽은 손으로 적은 그래프다.
|
|
59
59
|
|
|
60
60
|
```js
|
|
61
61
|
// docs/prototypes/full-conveyor.mjs — 컨베이어 하나가 이 밀도로 60 줄
|
|
62
62
|
add('endX','halfLength',-60); add('legX','halfLength',-260); add('frameZ','halfWidth',-18)
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
그리고 **되돌아갈 자리도 없다.** 전환 결정으로 figure-ui·figure-service 의 V2
|
|
65
|
+
그리고 **되돌아갈 자리도 없다.** 전환 결정으로 figure-ui·figure-service 의 옛 형식(V2)·지금 형식 분기
|
|
66
66
|
코드를 이미 지웠다. 활성 자산 32 개가 전부 V2 다.
|
|
67
67
|
|
|
68
|
-
> 이것이
|
|
68
|
+
> 이것이 지금 형식이 나갈지 말지를 정하는 한 가지다. 나머지는 다 그 뒤의 일이다.
|
|
69
69
|
|
|
70
|
-
### ② v2 가 세운 게이트가
|
|
70
|
+
### ② v2 가 세운 게이트가 지금 형식으로 안 넘어왔다
|
|
71
71
|
|
|
72
|
-
ADR-0044 와 ADR-0051 이 닫은 문 셋이
|
|
72
|
+
ADR-0044 와 ADR-0051 이 닫은 문 셋이 지금 소스에 없다.
|
|
73
73
|
|
|
74
|
-
| v2 의 문 |
|
|
74
|
+
| v2 의 문 | 지금 소스 | 지금 문서 |
|
|
75
75
|
|---|---|---|
|
|
76
76
|
| `part-outside-base` (ADR-0044) | 0 | 0 |
|
|
77
77
|
| `parts-off-placement-face` (ADR-0045) | 0 | 0 |
|
|
@@ -80,13 +80,13 @@ ADR-0044 와 ADR-0051 이 닫은 문 셋이 V3 소스에 없다.
|
|
|
80
80
|
|
|
81
81
|
`src/capabilities.ts` 는 있지만 **다른 것을 본다** — 표면 소유권과 수용 조건이다. 능력
|
|
82
82
|
이름은 `name()` 이 「빈 문자열이 아니면 통과」로 받는다. **`capabilities: ['hoist']` 가
|
|
83
|
-
|
|
83
|
+
지금 형식에서 다시 지나간다.** 그 구멍은 09-16 에 닫은 것이고, 닫기 전에는 검증과 발행을 지나
|
|
84
84
|
렌더링에서 죽었다.
|
|
85
85
|
|
|
86
|
-
셋 다 「그려지지 않는 것」이라
|
|
86
|
+
셋 다 「그려지지 않는 것」이라 지금 형식으로 옮기는 동안 조용히 빠지기 쉽다. **화면에는 아무 일도
|
|
87
87
|
안 일어난다.**
|
|
88
88
|
|
|
89
|
-
### ③ 지금
|
|
89
|
+
### ③ 지금 형식을 저작할 길은 그래프 코드뿐이다
|
|
90
90
|
|
|
91
91
|
`status.md` 의 남은 작업이 「다른 primitive 추가, 삭제·재질·관계 편집」이다. 지금 서 있는
|
|
92
92
|
것은 빈 자산과 상자 하나다. 설계는 모델러와 AI 가 template 으로 이 식을 만든다고 하는데,
|
|
@@ -112,11 +112,11 @@ V3 에서 다시 지나간다.** 그 구멍은 09-16 에 닫은 것이고, 닫
|
|
|
112
112
|
|
|
113
113
|
①이 나머지를 다 막는다. 그래서 순서는 이것이다.
|
|
114
114
|
|
|
115
|
-
1. **표본 하나로 전환 비용을 잰다.** 컨베이어 하나를 V2 원본에서
|
|
115
|
+
1. **표본 하나로 전환 비용을 잰다.** 컨베이어 하나를 V2 원본에서 지금 형식으로 옮기는 데 사람이 몇
|
|
116
116
|
분 걸리는지. 32 개를 곱하면 이 결정이 바로 보인다. 자동 변환이 어디까지 가능한지도 그때
|
|
117
117
|
드러난다 — `sizing`·`anchor` 의 상당수는 기계적으로 옮길 수 있어 보인다.
|
|
118
|
-
2. **②의 문 셋을
|
|
119
|
-
세워야 한다. 능력 이름은 목록을 그대로 쓸 수 있고, `base` 포함은
|
|
118
|
+
2. **②의 문 셋을 지금 계약에 어떻게 세울지 정한다.** 옮기는 것이 아니라 지금 형식의 말로 다시
|
|
119
|
+
세워야 한다. 능력 이름은 목록을 그대로 쓸 수 있고, `base` 포함은 지금 형식의 `NO_SPACE` ·
|
|
120
120
|
`LAYOUT_DOMAIN` 과 겹쳐 보인다.
|
|
121
121
|
3. 그 뒤에 모델러 연결.
|
|
122
122
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Figure 런타임 정식 소스 이관 — 그래프·capability·자산
|
|
2
2
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
5
|
-
> 최신 작업 기준: [
|
|
5
|
+
> 최신 작업 기준: [단일 체계 전환](cutover.md). 아래의 버전별 제품 연결 방향은 과거 작업 기록이며, 향후 설계 조건에서 제외한다.
|
|
6
6
|
|
|
7
7
|
## 이번 이관 범위
|
|
8
8
|
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
| figureUtf8ByteLength | 브라우저와 서버의 동일 UTF-8 바이트 계산 |
|
|
16
16
|
| FigureContractError | code/path를 가진 공통 오류 |
|
|
17
17
|
|
|
18
|
-
**
|
|
18
|
+
**parseFigureJson은 모델 의미 검증기가 아니다.** JSON 형식만 올바르면 Figure 자산이 아닌 객체도 읽는다. 자산 버전·단위·그래프·appearance 검사는 여전히 자산 컴파일러가 담당한다. 공개된 이름이 전체 형식 지원이나 안정화 완료를 뜻하지 않는다.
|
|
19
19
|
|
|
20
20
|
## 단일 구현 유지
|
|
21
21
|
|
|
22
|
-
`docs/prototypes/document.mjs`는 새 모듈을 import/re-export한다. 원래 JSON 검사 구현은 제거했다. `typed-plan.mjs`의 ContractError도 정식
|
|
22
|
+
`docs/prototypes/document.mjs`는 새 모듈을 import/re-export한다. 원래 JSON 검사 구현은 제거했다. `typed-plan.mjs`의 ContractError도 정식 FigureContractError를 다시 내보낸다. 따라서 기존 실험 테스트도 이관된 코드와 같은 오류 타입을 사용한다.
|
|
23
23
|
|
|
24
24
|
문서·자산의 Buffer.byteLength를 TextEncoder 기반 계산으로 대체했다. 생산 소스에는 docs import, 절대경로, Node 내장 모듈 import가 없다. 실험 도구가 src에 의존하는 방향이며 역방향은 없다.
|
|
25
25
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
2026-09-21:
|
|
29
29
|
|
|
30
30
|
- `npm test`: 당시 소스 전체와 새 입력 경계 검사 포함 **442개 통과**.
|
|
31
|
-
- `node --test docs/prototypes
|
|
31
|
+
- `node --test docs/prototypes/*.test.mjs`: **143개 통과**.
|
|
32
32
|
- `npm run build`: 성공, JS와 타입 선언 생성.
|
|
33
33
|
- `node docs/prototypes/runtime-browser.mjs`: 실제 Chrome에서 빌드된 ESM 실행 성공. Buffer/process가 없는 상태에서 한글·이모지 UTF-8 계산과 이스케이프 중복 키 거부 확인.
|
|
34
34
|
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
|
|
43
43
|
추가 검증:
|
|
44
44
|
|
|
45
|
-
- 타입 검사·빌드 성공. 소스 테스트 **445개 통과**,
|
|
45
|
+
- 타입 검사·빌드 성공. 소스 테스트 **445개 통과**, 실험 테스트 **143개 통과**.
|
|
46
46
|
- 실제 Chrome에서 빌드된 그래프 평가기를 실행했다. 기본 드라이룸6개, 컨베이어30개, 로봇암10개, 포크리프트20개 형상 및 전체 계산값이 Node 결과와 일치했다.
|
|
47
47
|
- 그래프 원본·반환 타입 정보·평가 결과를 호출자가 수정해도 컴파일된 계획의 이후 계산은 변하지 않는지 소스 테스트로 확인했다.
|
|
48
48
|
- 이 브라우저 검사는 평가 결과 비교다. 실제 제품 모델러 렌더러 연결이나 전체 상태 공간의 브라우저 검증을 뜻하지 않는다. 폭넓은 상태 공간 검사는 기존 Node 실험 테스트가 담당한다.
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
- 일반 저장은 설계 입력만 캡처하고 동작 미리보기는 명시적 옵션이 있어야 기본값으로 저장.
|
|
73
73
|
- 제품 DB·파일 IO·렌더러는 이 순수 모듈에 포함하지 않음.
|
|
74
74
|
|
|
75
|
-
자산 계층 이관 당시 검증: 소스 테스트 **448개**,
|
|
75
|
+
자산 계층 이관 당시 검증: 소스 테스트 **448개**, 실험 테스트 **143개** 통과. 타입 검사·빌드 성공. 실제 Chrome에서 네 대표 모델의 저장 JSON을 빌드된 모듈로 파싱·컴파일·평가하여 형상, 재질, 팔레트, 입력값, binding이 Node 결과와 일치함을 확인했다. 이것은 계산 결과 일치이며 재질 픽셀 재현이나 제품 화면 연결을 의미하지 않는다.
|
|
76
76
|
|
|
77
77
|
내부 heterogeneous dispatch에는 앞서 설명한 Dynamic 경계가 capability/asset에도 일부 남아 있다. 공개 타입과 런타임 검사 이관을 완료했지만 모든 내부 접근의 정적 타입 증명까지 완료한 것은 아니다.
|
|
78
78
|
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
- export는 저장 완료가 아니다. 저장 확인은 현재 context/revision 및 내용 일치가 필요하다.
|
|
90
90
|
- 빈 화면은 자산·메시·입력을 비우며 기본 상자를 만들지 않는다.
|
|
91
91
|
|
|
92
|
-
workspace 이관 당시 검증: 소스 테스트 **451개**,
|
|
92
|
+
workspace 이관 당시 검증: 소스 테스트 **451개**, 실험 테스트 **143개** 통과, 타입 검사·빌드 성공. Chrome에서 빌드된 workspace를 실행해 preview 비변경성, undo/redo 후 revision4, 오래된 저장 응답 거부, 로봇10개로 전환, 이전 AI context 거부, 저장 snapshot의 포크1500mm 복원, 빈 geometry0개를 확인했다.
|
|
93
93
|
|
|
94
94
|
별도로 격리 편집 UI에서 포크1275mm 수정 → HTTP 파일 저장 → 로봇 전환 → 저장본 복원 → 빈 화면의 경로를 다시 통과했다. page error0개. 생성된 편집 화면과 빈 캔버스 스크린샷을 직접 확인했다. 이 UI는 제품 서버가 아니며 테스트 후 임시 저장 파일을 정리한다.
|
|
95
95
|
|
|
@@ -102,6 +102,6 @@ workspace 이관 당시 검증: 소스 테스트 **451개**, V3 실험 테스트
|
|
|
102
102
|
|
|
103
103
|
## 남은 제품 연결
|
|
104
104
|
|
|
105
|
-
핵심 입력·그래프·capability·자산·편집 workspace는 src로 이관했다. 제품의 저장·발행·편집·렌더러를
|
|
105
|
+
핵심 입력·그래프·capability·자산·편집 workspace는 src로 이관했다. 제품의 저장·발행·편집·렌더러를 단일 체계로 전환해야 하며, 제품 연결은 아직 미완료다. 파일 저장 실험도 제품 DB 구현으로 간주하지 않는다. 접촉/충돌 연구 모듈과 대표 모델 생성기는 계속 실험 영역에 있다.
|
|
106
106
|
|
|
107
|
-
다음 단계는
|
|
107
|
+
다음 단계는 단일 저작·저장·렌더링 경로의 제품 연결이다. 기존 자산은 지금 형식 기준으로 바꾼다. 제품 API 배포는 아직 수행하지 않았다.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Figure 샘플 검증 확대 — 16종
|
|
2
2
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
5
5
|
2026-09-20. [1차 검사](sample-validation.md)의 후속이다.
|
|
6
|
-
**당시 기존 함수 검사 / 명시한
|
|
6
|
+
**당시 기존 함수 검사 / 명시한 Figure 의도 후보 계산 / 기구학 수치 실험**을 구별한다.
|
|
7
7
|
테스트가 통과했다는 것은 아래 관찰이 재현됐다는 뜻이며, 결함이 해결됐다는 뜻이 아니다.
|
|
8
8
|
제품 소스, 서버, 원본 샘플을 변경하지 않았다.
|
|
9
9
|
|
|
@@ -59,7 +59,7 @@ AGV 앞왼쪽 바퀴의 현행 사이징 계산:
|
|
|
59
59
|
| 2,1,2 | 162.63456 | -47.63456 |
|
|
60
60
|
|
|
61
61
|
다른 세 바퀴도 같은 결과다. 원형 복원으로 반지름은 바뀌지만 중심 위치는 다른 규칙을 따른다.
|
|
62
|
-
|
|
62
|
+
Figure 후보는 바닥 접촉 의도에서 `centerY = floorY + radius`라는 동일 치수 참조를 사용해야 한다.
|
|
63
63
|
원형 유지 옵션이 곧 접촉 보장이라는 전제는 폐기한다. 브라우저 렌더링으로 확인한 결과는 아니다.
|
|
64
64
|
|
|
65
65
|
### 2. 반복에는 최소 두 가지 의도가 있다
|
|
@@ -72,7 +72,7 @@ v3 후보는 바닥 접촉 의도에서 `centerY = floorY + radius`라는 동일
|
|
|
72
72
|
오류라고 단정할 수는 없지만, 층 번호·외부 binding·사용자가 보는 이동을 정의해야 한다.
|
|
73
73
|
id 정책 없이 단순 배열 인덱스를 영속 참조로 사용하면 의미가 바뀔 위험이 있다.
|
|
74
74
|
|
|
75
|
-
트레이의 -12mm는 **벽 두께를 고정한다는
|
|
75
|
+
트레이의 -12mm는 **벽 두께를 고정한다는 Figure 후보**에서 나온 결과다.
|
|
76
76
|
현행 renderer의 벽이 실제로 30mm로 유지된다는 검증은 하지 않았다.
|
|
77
77
|
고정 벽 후보는 `clearance = 36*s − 30 ≥ 0`, 즉 `s ≥ 5/6`이라는 입력 제한을 요구한다.
|
|
78
78
|
원본 크기만 재현하는 변환은 이런 축소 영역의 불가능성을 숨긴다.
|
|
@@ -91,7 +91,7 @@ id 정책 없이 단순 배열 인덱스를 영속 참조로 사용하면 의미
|
|
|
91
91
|
파렛트 terminal은 base보다 위에 있고, 롤 프레스는 닫힌 두 롤 사이에 두께 24의 web을 그린다.
|
|
92
92
|
web의 각 측 여유는 `(nip−24)/2`로, nip=0에서 -12mm다.
|
|
93
93
|
압축된 소재의 도식적 표현인지 물리적 간극 오류인지 원본만으로 결정할 수 없다.
|
|
94
|
-
|
|
94
|
+
Figure는 명시한 접촉·containment·간극 assertion을 검사해야 하며,
|
|
95
95
|
모든 AABB 겹침/이탈을 전역 금지하거나 모두 허용하는 양극단을 피한다.
|
|
96
96
|
|
|
97
97
|
## 확정 전에 남은 것
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Figure 실제 샘플 대입 검증 — 2026-09-20
|
|
2
2
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**r2를 그대로 확정하면 안 된다.** 실제 샘플은 반복 개수 변화, 복합 운동,
|
|
10
10
|
비대칭 단면의 실제 기준점을 요구한다. 개념을 늘리기 전에 이 요구들을 실행 계약으로 닫아야 한다.
|
|
11
|
-
이 기록은 설계 수치 실험이며
|
|
11
|
+
이 기록은 설계 수치 실험이며 Figure 전체 모델 변환·렌더러·제품 테스트 완료가 아니다.
|
|
12
12
|
|
|
13
13
|
시스템 설계 절차에 따라 요구사항, 실행된 검사, 미검증 범위를 분리했다.
|
|
14
14
|
|
|
@@ -59,7 +59,7 @@ node --test docs/prototypes/samples.test.mjs
|
|
|
59
59
|
반복을 치수 계산과 구분되는 제한된 생성 단계로 둘지, 저작 시 고정 개수로 펼칠지
|
|
60
60
|
명시적으로 결정해야 한다. 후자는 현재의 크기 변경 의미를 보존하지 못한다.
|
|
61
61
|
반복 instance id, 개수 감소 시 외부 binding, 끝 여백, 최대 개수 초과 진단을 먼저 정의한다.
|
|
62
|
-
현재 함수의 최소1·최대100 제한을 그대로
|
|
62
|
+
현재 함수의 최소1·최대100 제한을 그대로 Figure의 정답으로 채택한 것은 아니다.
|
|
63
63
|
head/tail 롤러와 반복 롤러의 실제 간섭은 이번 검사에 포함되지 않는다.
|
|
64
64
|
|
|
65
65
|
### 포크리프트: 평면 채널을 계층으로 옮길 때의 위험
|
|
@@ -67,7 +67,7 @@ head/tail 롤러와 반복 롤러의 실제 간섭은 이번 검사에 포함되
|
|
|
67
67
|
시드는 부모 관계 없이 mast/stage/carriage/fork 각각에 reach=400 이동을 기록한다.
|
|
68
68
|
이를 계층화하고 같은 채널도 복사하면 부모의 400과 자식의 400이 중복될 수 있다.
|
|
69
69
|
변환은 `자식 상대 이동 = 기존 자식 이동 − 새 부모의 상속 이동`으로 재구성해야 한다.
|
|
70
|
-
이는 현재 제품에 중복 버그가 있다는 발견이 아니라 **
|
|
70
|
+
이는 현재 제품에 중복 버그가 있다는 발견이 아니라 **Figure 마이그레이션 위험**이다.
|
|
71
71
|
|
|
72
72
|
9개 조합은 실제 채널의 시작·끝이 선형 translation이라는 조건을 확인한 뒤 평가했다.
|
|
73
73
|
회전이 섞인 일반 채널을 같은 뺄셈으로 변환할 수 있다는 주장은 아니다.
|
|
@@ -84,7 +84,7 @@ transform.size의 대칭 반치수로 계산하면 이 비대칭 단면의 실
|
|
|
84
84
|
원본은 수정하지 않았다. 이 연산을 임의 polygon clipping으로 일반화하지 않는다.
|
|
85
85
|
서버 편집본의 같은 문제를 확정하거나 자동 수정 완료를 선언하는 근거로도 쓰지 않는다.
|
|
86
86
|
|
|
87
|
-
##
|
|
87
|
+
## Figure 명세 확정 전 필수 보완
|
|
88
88
|
|
|
89
89
|
1. 반복 topology와 안정된 참조 정책: 컨베이어 및 트레이.
|
|
90
90
|
2. 실제 geometry feature의 좌표·id 계약: 비대칭 polygon, 문틀 안쪽 면.
|
|
@@ -124,7 +124,7 @@ range, and says how it knows:
|
|
|
124
124
|
|
|
125
125
|
## 5. 표시 여부 (visibility) — 안 보이는 것과 작은 것은 다르다
|
|
126
126
|
|
|
127
|
-
**
|
|
127
|
+
**Figure 설계자 결정 2026-09-22.** 부품을 숨기려고 크기를 0 으로 만들지 않는다. 0 을 아주 작은 양수로 바꾸는 것도 쓰지 않는다 — 확대·그림자·포인터 선택에서 차이가
|
|
128
128
|
생기고, 「안 보임」이 「아주 작음」이 되어 버린다.
|
|
129
129
|
|
|
130
130
|
### 규칙
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Figure 타입·공간 그래프 통합 실험
|
|
2
2
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
@@ -81,4 +81,4 @@ node --test docs/prototypes/spatial-plan.test.mjs docs/prototypes/typed-plan.tes
|
|
|
81
81
|
5. 실제 자산 전체를 변환해 mesh/시각 결과 및 예산 측정.
|
|
82
82
|
|
|
83
83
|
지금 통합한 것의 가치는 '한 엔진에 숫자와 좌표계 의존성이 함께 들어왔다'는 데 있다.
|
|
84
|
-
이 상태를 전체
|
|
84
|
+
이 상태를 전체 Figure 완성으로 해석하지 않는다.
|
package/docs/status.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
- 완결성·확장성 및 공개 경계 검토: [점검 결과](completeness-review-2026-10-04.md).
|
|
9
9
|
- 점검 때 `npm test`: 타입 검사와 696개 시험 통과.
|
|
10
|
-
- 재현된 F1~F4는 같은 날 고쳤다(`122b3c0` · `c86d74b` · `4f32334` · `9a332e7
|
|
10
|
+
- 재현된 F1~F4는 같은 날 고쳤다(`122b3c0` · `c86d74b` · `4f32334` · `9a332e7`). figure-model 0.3.3 · things-scene 10.1.72 로 발행, operato-application 설치(2026-10-04). 고친 뒤 `npm test`는
|
|
11
11
|
타입 검사와 725개 시험 통과, build 성공. 선택한 계약과 남은 제한은 점검 결과 문서의 「해결 현황」에 있다.
|
|
12
12
|
- 발행 판정: 「정확성·검증 경계 개선, 일반 평가 비용 증가」. 성능은 CPU rig까지만 쟀다(매 프레임 evaluate
|
|
13
13
|
+40~55%). 대규모 resize 최적화는 별도 과제다.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Figure 저장 API 경계와 파일 영속화 검증
|
|
2
2
|
|
|
3
3
|
> 현재 구현·검증·제품 연결 상태는 [구현·검증 현황](status.md)을 따른다. 본문의 단계별 연구/검증 기록은 제품 전체 완료 선언이 아니다.
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
당시 제품 figure-service의 `figure-source.ts`는 이전 형식의 검증·컴파일·비용·점수 함수를 호출했다. `figure-mutation.ts`의 생성·수정·되돌리기와 발행도 그 검사 경로를 사용했다. figure-ui도 draft/parts를 직접 편집한다.
|
|
16
16
|
|
|
17
|
-
실험 포맷만 허용하면 저장은 되지만 기존 소비자가 읽을 수 없는 자산이 된다. 따라서 **제품
|
|
17
|
+
실험 포맷만 허용하면 저장은 되지만 기존 소비자가 읽을 수 없는 자산이 된다. 따라서 **제품 경로 연결은 아직 미완료**다. 실험 코드의 직접 import, package.json 변경, 기존 검증 우회는 하지 않았다.
|
|
18
18
|
|
|
19
19
|
## 저장 계약
|
|
20
20
|
|
|
@@ -35,7 +35,7 @@ scope/id 조합을 해시한 파일명으로 사용해 사용자 식별자를
|
|
|
35
35
|
- 별도 Node 프로세스에서 포크 길이1275mm와 저장 revision 복원.
|
|
36
36
|
- 동일 revision 동시 저장 두 건 중 한 건만 성공.
|
|
37
37
|
- scope가 다른 자산 조회 차단(NOT_FOUND), 생성 중복 및 누락 precondition 거부.
|
|
38
|
-
- 잘못된
|
|
38
|
+
- 잘못된 Figure 자산 저장 시 기존 파일 보존.
|
|
39
39
|
- 충돌 시 화면의 변경값과 미저장 상태 보존.
|
|
40
40
|
- Chrome에서 HTTP 파일 저장, 로봇 전환, 파일 복원, 빈 캔버스 초기화 확인. page error 0개.
|
|
41
41
|
|
|
@@ -51,8 +51,8 @@ scope/id 조합을 해시한 파일명으로 사용해 사용자 식별자를
|
|
|
51
51
|
## 제품 연결 순서
|
|
52
52
|
|
|
53
53
|
1. 입력·그래프·capability·문서·자산·편집 workspace의 정식 소스 이관은 [완료](runtime-extraction.md)했다. 이 모듈들을 제품에 반영한다.
|
|
54
|
-
2. figure-service의 저장·조회·발행을
|
|
55
|
-
3. figure-ui와 렌더러·AI를
|
|
54
|
+
2. figure-service의 저장·조회·발행을 단일 기준으로 전환하고 저장 revision CAS를 구현한다.
|
|
55
|
+
3. figure-ui와 렌더러·AI를 단일 경로에 연결한다. 기존 자산은 지금 형식으로 재작성한다.
|
|
56
56
|
4. 실제 인증·DB로 두 편집 세션의 충돌, 저장 실패, 재접속, 모델 전환, AI 늦은 응답을 검증한다.
|
|
57
57
|
|
|
58
58
|
이 문서의 완료 범위는 저장 경계의 실행 가능한 검증이며, 제품 연결·배포 완료가 아니다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hatiolab/figure-model",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "The figure format (figure-asset-1): a kernel that evaluates a figure from its declared relations, the authoring commands a modeller and an AI share, the release gate and the score.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"figure",
|