@operato/scene-storage 10.0.0-beta.57 → 10.0.0-beta.59

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 CHANGED
@@ -3,6 +3,37 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [10.0.0-beta.59](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.58...v10.0.0-beta.59) (2026-06-17)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * **routing:** Phase B1 — RoutingTarget.routingWeight capability + sink 구현 + validator warning ([d25288d](https://github.com/things-scene/operato-scene/commit/d25288d516509658f446d5a24746aa4b72faa475))
12
+
13
+
14
+ ### :bug: Bug Fix
15
+
16
+ * **routing:** 라이브 검증 발견 결함 2건 fix + E2E 단위 테스트 추가 ([88e3b59](https://github.com/things-scene/operato-scene/commit/88e3b599cb1d45f3dd804b3e33ab0dddf7c82392))
17
+
18
+
19
+
20
+ ## [10.0.0-beta.58](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.57...v10.0.0-beta.58) (2026-06-17)
21
+
22
+
23
+ ### :rocket: New Features
24
+
25
+ * **scene-base/storage:** SingleSlotHolder mixin 표준화 + records-only holder 일괄 Holdable 적용 ([2624953](https://github.com/things-scene/operato-scene/commit/2624953d6803ec43901118753b6fde8342e11aae))
26
+ * **storage:** Spot 의 Holdable 시범 채택 — _holdings 자식 시스템 (시범 첫 사례) ([d51cfff](https://github.com/things-scene/operato-scene/commit/d51cfff47d1eec8f1ddf3751c9f4e6aac8775dee))
27
+ * **transport/storage:** Mover 일괄 Holdable 적용 + Crane engage 정합 (시범 5) ([2976425](https://github.com/things-scene/operato-scene/commit/2976425ddb066f1ee8fa5d35df55d9967f6717f2))
28
+
29
+
30
+ ### :house: Code Refactoring
31
+
32
+ * **storage:** Spot receiveAt → handoverIn 위임 (3D handover inline 제거) ([6765dae](https://github.com/things-scene/operato-scene/commit/6765dae1a955943fe57f5d418a846df62bf74cf0))
33
+ * **storage:** Stockpile transient carrier → _holdings (Holdable 시범 2) ([b8cd38a](https://github.com/things-scene/operato-scene/commit/b8cd38a3fd84b204ef664da1ec735cac2fd571c4))
34
+
35
+
36
+
6
37
  ## [10.0.0-beta.57](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.56...v10.0.0-beta.57) (2026-06-15)
7
38
 
8
39
 
package/dist/crane.js CHANGED
@@ -2,7 +2,7 @@ import { __decorate } from "tslib";
2
2
  /*
3
3
  * Copyright © HatioLab Inc. All rights reserved.
4
4
  */
5
- import { ContainerAbstract, ContainerCapacity, Transfer, getWorldPose, sceneComponent } from '@hatiolab/things-scene';
5
+ import { ContainerAbstract, ContainerCapacity, Holdable, Transfer, getWorldPose, sceneComponent } from '@hatiolab/things-scene';
6
6
  import { CarrierHolder, Legendable, Mover, Placeable, isSlottedHolder, findDispatcher, resolveTransferTarget } from '@operato/scene-base';
7
7
  import * as THREE from 'three';
8
8
  import { Crane3D } from './crane-3d.js';
@@ -132,7 +132,7 @@ const NATURE = {
132
132
  * (or `crane.pickAndPlace(carrier, target)`). Mover handles navigation +
133
133
  * engage + reparent. During transit the carrier IS a child of the crane.
134
134
  */
135
- let Crane = class Crane extends Mover(CarrierHolder(ContainerCapacity(Legendable(Placeable(ContainerAbstract))))) {
135
+ let Crane = class Crane extends Mover(CarrierHolder(ContainerCapacity(Holdable(Legendable(Placeable(ContainerAbstract)))))) {
136
136
  static legends = {
137
137
  bodyColor: { from: 'status', legend: BODY_LEGEND },
138
138
  lampEmissive: { from: 'status', legend: LAMP_EMISSIVE_LEGEND }
@@ -335,7 +335,8 @@ let Crane = class Crane extends Mover(CarrierHolder(ContainerCapacity(Legendable
335
335
  if (targetBottomWorldY !== null) {
336
336
  // Phase Z PR-4: 임의 slot 의 carrier 검사 (multi-fork 대비). 단일 'forks'
337
337
  // 가정 제거 — c._transferSlotId 가 set 됐으면 어떤 slot 이든 holding.
338
- const isHoldingCarrier = this.components?.some?.((c) => c?._transferSlotId != null) ?? false;
338
+ // Holdable 자손이면 _holdings, 아니면 _components.
339
+ const isHoldingCarrier = (this._holdings ?? this.components)?.some?.((c) => c?._transferSlotId != null) ?? false;
339
340
  const liftH = numOr(this.state.forkLift, 30);
340
341
  const approachWorldY = targetBottomWorldY + (isHoldingCarrier ? liftH : 0);
341
342
  const ro = this._realObject;
@@ -430,9 +431,13 @@ let Crane = class Crane extends Mover(CarrierHolder(ContainerCapacity(Legendable
430
431
  }
431
432
  if (kind === 'pick') {
432
433
  this.setState({ status: 'loading' });
434
+ // 1. fork extend — cell 위 carrier 위치로 fork 진입.
433
435
  await this._tween({ forkExtension: extTarget }, D_EXT);
434
- // Mid-engage reparentfork cell 도달. carrier fork 위로 *즉시
435
- // snap* (animated:false). Transfer 객체 통과 → monitor panel 추적.
436
+ // 2. fork lift carrier 떠올림. 시점에 carrier *_물리적으로 fork 위에
437
+ // 얹힘_* handover 자연 타이밍.
438
+ await this._tween({ forkLiftRT: liftH }, D_LIFT);
439
+ // 3. Mid-engage reparent — carrier 가 fork 위로 *즉시 snap* (animated:false).
440
+ // Transfer 객체 통과 → monitor panel 추적. lift 직후 = 떠올린 시점.
436
441
  const source = target.parent;
437
442
  if (source) {
438
443
  try {
@@ -447,7 +452,7 @@ let Crane = class Crane extends Mover(CarrierHolder(ContainerCapacity(Legendable
447
452
  // Transfer 실패 — carrier 그대로. 후속 Mover.pick receive 가 처리.
448
453
  }
449
454
  }
450
- await this._tween({ forkLiftRT: liftH }, D_LIFT);
455
+ // 4. fork retract carrier 위에 얹힌 채로 빠짐.
451
456
  await this._tween({ forkExtension: 0 }, D_EXT);
452
457
  }
453
458
  else {
@@ -459,7 +464,8 @@ let Crane = class Crane extends Mover(CarrierHolder(ContainerCapacity(Legendable
459
464
  await this._tween({ forkLiftRT: 0 }, D_LIFT);
460
465
  // 3. dispatch — carrier world 위치 = cell 내 attach 위치, jump 없음. Transfer 추적.
461
466
  // Phase Z PR-4: 임의 slot 의 carrier 검사 (multi-fork 대비).
462
- const comps = this.components;
467
+ // Holdable 자손이면 _holdings, 아니면 _components.
468
+ const comps = (this._holdings ?? this.components);
463
469
  const carrier = comps?.find?.((c) => c?._transferSlotId != null)
464
470
  ?? comps?.[0];
465
471
  if (carrier) {