@operato/twin-kernel 0.11.2 → 0.11.3
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/flow-engine.d.ts +38 -1
- package/dist/flow-engine.js +50 -6
- package/dist-cjs/index.cjs +83 -8
- package/package.json +1 -1
package/dist/flow-engine.d.ts
CHANGED
|
@@ -1311,7 +1311,44 @@ export declare abstract class FlowEngine implements TwinKernel {
|
|
|
1311
1311
|
subject: string;
|
|
1312
1312
|
basis: 'declared' | 'twin-local';
|
|
1313
1313
|
};
|
|
1314
|
-
|
|
1314
|
+
/**
|
|
1315
|
+
* 운영 델타 방출 — **같은 사실을 다시 적지 않는다.**
|
|
1316
|
+
*
|
|
1317
|
+
* ── 무엇이 있었나 (2026-09-05 실측) ────────────────────────────────────────
|
|
1318
|
+
* `flow-engine.ts` 의 배정 패스가 **매 틱** `created` 인 오더 전부에 `allocate` 를 건다. 자재가
|
|
1319
|
+
* 모자란 오더는 그때마다 `mes-kernel` 의 「모자람을 적고 다음 틱에 다시 본다」 줄에 닿았고, 거기서
|
|
1320
|
+
* **바뀐 것이 없어도 방출**했다.
|
|
1321
|
+
*
|
|
1322
|
+
* hatio-mx2 오더 315개 → 세 시간에 order.status 2,433,116건 (오더당 7,700)
|
|
1323
|
+
* 다른 트윈 오더당 1~2건
|
|
1324
|
+
* 틱 로그 「journal 706.92ms(88%)」
|
|
1325
|
+
*
|
|
1326
|
+
* 다시 보는 것은 옳다(모자람은 채워질 수 있다). **다시 볼 때마다 적는 것**이 결함이다.
|
|
1327
|
+
*
|
|
1328
|
+
* ── 파급이 디스크가 아니다 ─────────────────────────────────────────────────
|
|
1329
|
+
* 재기동 저널을 접어 상태를 세운다 — 되세우는 시간이 그만큼 는다
|
|
1330
|
+
* 구독 이 사건들은 방송된다. 막힌 오더 × 매 틱 × 구독자 수
|
|
1331
|
+
* 틱 시뮬 틱은 메인 이벤트 루프에서 돈다 — HTTP·구독이 함께 느려진다
|
|
1332
|
+
* 지표 오더 사건을 세는 모든 것이 부푼다
|
|
1333
|
+
* 진짜 문제 「오더가 자재를 못 구해 멈췄다」가 자기가 만든 소음에 묻힌다
|
|
1334
|
+
*
|
|
1335
|
+
* 가장 나쁜 것은 방향이다. **현장이 막힐수록 트윈이 더 무너진다** — 잘 흐르면 사건이 적고 막히면
|
|
1336
|
+
* 폭증한다. 트윈이 가장 필요한 순간에 가장 약해진다.
|
|
1337
|
+
*
|
|
1338
|
+
* ── 왜 여기인가 ────────────────────────────────────────────────────────────
|
|
1339
|
+
* 부르는 자리 하나를 막으면 다른 자리에서 같은 일이 난다 — `emitOrder` 를 부르는 곳만 열다섯이다.
|
|
1340
|
+
* 그리고 `revision` 이 여기서 오르므로, 여기서 막지 않으면 **적지 않고도 판만 올라간다.**
|
|
1341
|
+
*
|
|
1342
|
+
* ── 무엇을 같다고 보나 ─────────────────────────────────────────────────────
|
|
1343
|
+
* `data` 가 바이트까지 같으면 같다. 시각은 `data` 에 없다(여기서 붙인다) — 그래서 「같은 사실을
|
|
1344
|
+
* 다른 시각에 다시 말한 것」이 정확히 걸러진다.
|
|
1345
|
+
*
|
|
1346
|
+
* `subject` 를 안 주면 거르지 않는다. 대상이 없는 사건(주의 등)은 반복 자체가 사실이다.
|
|
1347
|
+
*
|
|
1348
|
+
* 재기동하면 이 기억이 비므로 **첫 방출은 언제나 나간다** — 되세운 상태가 조용히 빠지지 않는다.
|
|
1349
|
+
*/
|
|
1350
|
+
private lastEmitted;
|
|
1351
|
+
protected emitOp(eventType: string, data: unknown, subject?: string): void;
|
|
1315
1352
|
/**
|
|
1316
1353
|
* 작업 전이 방출 — **커널이 아는 것을 미러도 알게** 한다.
|
|
1317
1354
|
*
|
package/dist/flow-engine.js
CHANGED
|
@@ -2820,7 +2820,51 @@ export class FlowEngine {
|
|
|
2820
2820
|
subjectOf(kind, localId) {
|
|
2821
2821
|
return resolveSubject(kind, localId, { tenantId: this.tenantId, scopeId: this.scopeId, identityOf: (k, id) => (k === 'equipment' ? this.equipmentIdentity(id) : undefined) });
|
|
2822
2822
|
}
|
|
2823
|
-
|
|
2823
|
+
/**
|
|
2824
|
+
* 운영 델타 방출 — **같은 사실을 다시 적지 않는다.**
|
|
2825
|
+
*
|
|
2826
|
+
* ── 무엇이 있었나 (2026-09-05 실측) ────────────────────────────────────────
|
|
2827
|
+
* `flow-engine.ts` 의 배정 패스가 **매 틱** `created` 인 오더 전부에 `allocate` 를 건다. 자재가
|
|
2828
|
+
* 모자란 오더는 그때마다 `mes-kernel` 의 「모자람을 적고 다음 틱에 다시 본다」 줄에 닿았고, 거기서
|
|
2829
|
+
* **바뀐 것이 없어도 방출**했다.
|
|
2830
|
+
*
|
|
2831
|
+
* hatio-mx2 오더 315개 → 세 시간에 order.status 2,433,116건 (오더당 7,700)
|
|
2832
|
+
* 다른 트윈 오더당 1~2건
|
|
2833
|
+
* 틱 로그 「journal 706.92ms(88%)」
|
|
2834
|
+
*
|
|
2835
|
+
* 다시 보는 것은 옳다(모자람은 채워질 수 있다). **다시 볼 때마다 적는 것**이 결함이다.
|
|
2836
|
+
*
|
|
2837
|
+
* ── 파급이 디스크가 아니다 ─────────────────────────────────────────────────
|
|
2838
|
+
* 재기동 저널을 접어 상태를 세운다 — 되세우는 시간이 그만큼 는다
|
|
2839
|
+
* 구독 이 사건들은 방송된다. 막힌 오더 × 매 틱 × 구독자 수
|
|
2840
|
+
* 틱 시뮬 틱은 메인 이벤트 루프에서 돈다 — HTTP·구독이 함께 느려진다
|
|
2841
|
+
* 지표 오더 사건을 세는 모든 것이 부푼다
|
|
2842
|
+
* 진짜 문제 「오더가 자재를 못 구해 멈췄다」가 자기가 만든 소음에 묻힌다
|
|
2843
|
+
*
|
|
2844
|
+
* 가장 나쁜 것은 방향이다. **현장이 막힐수록 트윈이 더 무너진다** — 잘 흐르면 사건이 적고 막히면
|
|
2845
|
+
* 폭증한다. 트윈이 가장 필요한 순간에 가장 약해진다.
|
|
2846
|
+
*
|
|
2847
|
+
* ── 왜 여기인가 ────────────────────────────────────────────────────────────
|
|
2848
|
+
* 부르는 자리 하나를 막으면 다른 자리에서 같은 일이 난다 — `emitOrder` 를 부르는 곳만 열다섯이다.
|
|
2849
|
+
* 그리고 `revision` 이 여기서 오르므로, 여기서 막지 않으면 **적지 않고도 판만 올라간다.**
|
|
2850
|
+
*
|
|
2851
|
+
* ── 무엇을 같다고 보나 ─────────────────────────────────────────────────────
|
|
2852
|
+
* `data` 가 바이트까지 같으면 같다. 시각은 `data` 에 없다(여기서 붙인다) — 그래서 「같은 사실을
|
|
2853
|
+
* 다른 시각에 다시 말한 것」이 정확히 걸러진다.
|
|
2854
|
+
*
|
|
2855
|
+
* `subject` 를 안 주면 거르지 않는다. 대상이 없는 사건(주의 등)은 반복 자체가 사실이다.
|
|
2856
|
+
*
|
|
2857
|
+
* 재기동하면 이 기억이 비므로 **첫 방출은 언제나 나간다** — 되세운 상태가 조용히 빠지지 않는다.
|
|
2858
|
+
*/
|
|
2859
|
+
lastEmitted = new Map();
|
|
2860
|
+
emitOp(eventType, data, subject) {
|
|
2861
|
+
if (subject !== undefined) {
|
|
2862
|
+
const key = `${eventType}\u0000${subject}`;
|
|
2863
|
+
const json = JSON.stringify(data);
|
|
2864
|
+
if (this.lastEmitted.get(key) === json)
|
|
2865
|
+
return;
|
|
2866
|
+
this.lastEmitted.set(key, json);
|
|
2867
|
+
}
|
|
2824
2868
|
this.revision++;
|
|
2825
2869
|
const e = { eventId: `${this.tenantId}-evt-${++this.eventSeq}`, eventType, eventTime: this.now(), tenantId: this.tenantId, ...(this._correlationId ? { correlationId: this._correlationId } : {}), data };
|
|
2826
2870
|
for (const h of this.handlers)
|
|
@@ -2852,14 +2896,14 @@ export class FlowEngine {
|
|
|
2852
2896
|
...(t.startTime ? { startTime: t.startTime } : {}),
|
|
2853
2897
|
...(t.endTime ? { endTime: t.endTime } : {}),
|
|
2854
2898
|
...(inProgress ? { remainingMs: t.remainingMs, startedAtSimMs: t.startedAtSimMs, progress: t.durationMs ? done / t.durationMs : undefined } : {})
|
|
2855
|
-
});
|
|
2899
|
+
}, t.id);
|
|
2856
2900
|
}
|
|
2857
2901
|
/** 사람 상태 전이 — 설비와 별개 채널(어휘가 다르다: 고장이 아니라 교대·투입). */
|
|
2858
2902
|
emitAsset(a) {
|
|
2859
|
-
this.emitOp(OP_EVENT.asset, { assetId: a.id, assetClassIds: a.assetClassIds, ...(a.ratedUsage ? { ratedUsage: a.ratedUsage } : {}), ...(a.usedUsage ? { usedUsage: a.usedUsage } : {}), status: a.status, location: a.location, taskId: a.taskId ?? undefined, carrying: a.carrying, ...effectiveOnly(a) });
|
|
2903
|
+
this.emitOp(OP_EVENT.asset, { assetId: a.id, assetClassIds: a.assetClassIds, ...(a.ratedUsage ? { ratedUsage: a.ratedUsage } : {}), ...(a.usedUsage ? { usedUsage: a.usedUsage } : {}), status: a.status, location: a.location, taskId: a.taskId ?? undefined, carrying: a.carrying, ...effectiveOnly(a) }, a.id);
|
|
2860
2904
|
}
|
|
2861
2905
|
emitPerson(p) {
|
|
2862
|
-
this.emitOp(OP_EVENT.person, { personId: p.id, personnelClassIds: p.personnelClassIds, status: p.status, taskId: p.taskId ?? undefined, ...(p.location ? { location: p.location } : {}), ...effectiveOnly(p) });
|
|
2906
|
+
this.emitOp(OP_EVENT.person, { personId: p.id, personnelClassIds: p.personnelClassIds, status: p.status, taskId: p.taskId ?? undefined, ...(p.location ? { location: p.location } : {}), ...effectiveOnly(p) }, p.id);
|
|
2863
2907
|
/* `offShift` 를 더 이상 실어 보내지 않는다 — 교대 경계는 **이벤트 없이 시각만으로** 넘어가므로
|
|
2864
2908
|
전이 순간의 판정을 보내면 유휴로 경계를 지난 사람이 옛 값에 머문다. 미러는 같은 함수
|
|
2865
2909
|
(`offCalendarAt`)를 자기 시각으로 부른다(유효 기간과 같은 규율). */
|
|
@@ -2867,7 +2911,7 @@ export class FlowEngine {
|
|
|
2867
2911
|
/** 설비 상태 전이 — `taskId` 를 함께 싣는다(사람·자산 델타와 같은 규칙). 없으면 미러가 "이 설비가
|
|
2868
2912
|
* 무슨 일을 하는 중인가" 를 알 수 없어 작업↔자원 연결이 한쪽에서만 성립한다. */
|
|
2869
2913
|
emitEquipment(m, motion) {
|
|
2870
|
-
this.emitOp(OP_EVENT.equipment, { moverId: m.id, kind: m.kind, ...(m.equipmentClassIds ? { equipmentClassIds: m.equipmentClassIds } : {}), status: m.status, location: m.location, ...(m.homeLocation ? { homeLocation: m.homeLocation } : {}), taskId: m.taskId ?? undefined, motion, ...(m.held ? { held: true } : {}), ...effectiveOnly(m) });
|
|
2914
|
+
this.emitOp(OP_EVENT.equipment, { moverId: m.id, kind: m.kind, ...(m.equipmentClassIds ? { equipmentClassIds: m.equipmentClassIds } : {}), status: m.status, location: m.location, ...(m.homeLocation ? { homeLocation: m.homeLocation } : {}), taskId: m.taskId ?? undefined, motion, ...(m.held ? { held: true } : {}), ...effectiveOnly(m) }, m.id);
|
|
2871
2915
|
}
|
|
2872
2916
|
/** 오더 델타 — **라인까지 싣는다.** 라인이 빠지면 미러가 남은 데맨드를 라인별로 재계획할 수 없다. */
|
|
2873
2917
|
emitOrder(o) {
|
|
@@ -2888,7 +2932,7 @@ export class FlowEngine {
|
|
|
2888
2932
|
/* 약속해 둔 자리·시각창 — 이것이 빠져서 야드 트윈이 재기동마다 첫 틱에 죽었다(§dockDoor). */
|
|
2889
2933
|
...(o.dockDoor ? { dockDoor: o.dockDoor } : {}),
|
|
2890
2934
|
...(o.windowStartMs !== undefined ? { windowStartMs: o.windowStartMs } : {})
|
|
2891
|
-
});
|
|
2935
|
+
}, o.id);
|
|
2892
2936
|
}
|
|
2893
2937
|
// ── 내부 mechanics ─────────────────────────────────────────────────────────
|
|
2894
2938
|
/**
|
package/dist-cjs/index.cjs
CHANGED
|
@@ -792,6 +792,7 @@ var ENERGY_EVENT = {
|
|
|
792
792
|
*/
|
|
793
793
|
drSuggested: "energy.dr.suggested"
|
|
794
794
|
};
|
|
795
|
+
var MATERIAL_ACTUAL_USE = ["consumed", "produced"];
|
|
795
796
|
var CMD = {
|
|
796
797
|
orderHold: "order.hold",
|
|
797
798
|
orderResume: "order.resume",
|
|
@@ -1574,13 +1575,23 @@ function objectUri(namespace, objId) {
|
|
|
1574
1575
|
function bizTransactionUri(namespace, transId) {
|
|
1575
1576
|
return underNamespace(namespace, "bt", transId);
|
|
1576
1577
|
}
|
|
1578
|
+
var STRUCTURE_BREAKING = /[%/:?# ]/g;
|
|
1579
|
+
var PERCENT_ENCODED = {
|
|
1580
|
+
"%": "%25",
|
|
1581
|
+
"/": "%2F",
|
|
1582
|
+
":": "%3A",
|
|
1583
|
+
"?": "%3F",
|
|
1584
|
+
"#": "%23",
|
|
1585
|
+
" ": "%20"
|
|
1586
|
+
};
|
|
1577
1587
|
function underNamespace(namespace, marker, id) {
|
|
1578
1588
|
const ns = namespace?.trim();
|
|
1579
1589
|
if (!ns)
|
|
1580
1590
|
return void 0;
|
|
1581
|
-
const
|
|
1582
|
-
if (!
|
|
1591
|
+
const raw = String(id);
|
|
1592
|
+
if (!raw)
|
|
1583
1593
|
return void 0;
|
|
1594
|
+
const v = raw.replace(STRUCTURE_BREAKING, (c) => PERCENT_ENCODED[c]);
|
|
1584
1595
|
if (/^https?:\/\/[^/\s]+/.test(ns))
|
|
1585
1596
|
return `${ns.replace(/\/+$/, "")}/${marker}/${v}`;
|
|
1586
1597
|
if (/^urn:epc(global)?:/.test(ns))
|
|
@@ -1770,6 +1781,27 @@ var SPECS = {
|
|
|
1770
1781
|
materialActual: "object[]",
|
|
1771
1782
|
recordTime: "string"
|
|
1772
1783
|
},
|
|
1784
|
+
/*
|
|
1785
|
+
* **자재 줄의 안쪽** — 계약의 `MaterialActual` 그대로다.
|
|
1786
|
+
*
|
|
1787
|
+
* `definitionId` 를 요구하는 이유: 이 이름이 없으면 그 줄이 무엇을 가리키는지 아무도 모른다.
|
|
1788
|
+
* 실제로 `materialDefinitionId` 로 온 줄이 저널에 앉았고, 계약의 타입으로 읽으면 비어 있었다.
|
|
1789
|
+
*
|
|
1790
|
+
* `quantity` 를 `positive` 에 두는 이유: 「모른다」는 **비워서** 말한다. 0 으로 실으면 받는
|
|
1791
|
+
* 쪽에서 「0개」와 구별되지 않고, 소요량 집계가 조용히 틀린다.
|
|
1792
|
+
*
|
|
1793
|
+
* `uom` 은 요구하지 않는다 — 계약에서 선택이다(§`MaterialActual`). ERP 경로는 요구하는데
|
|
1794
|
+
* 그것은 **그 경로의 규칙**이다(정산에 단위 없는 수량을 쓸 수 없다). 커널이 그 규칙을 통째로
|
|
1795
|
+
* 물려받으면 단위를 모르는 현장의 사실이 통째로 거절된다.
|
|
1796
|
+
*/
|
|
1797
|
+
shapes: {
|
|
1798
|
+
materialActual: {
|
|
1799
|
+
required: ["definitionId", "use"],
|
|
1800
|
+
fields: { definitionId: "string", lotId: "string", quantity: "number", uom: "string" },
|
|
1801
|
+
enums: { use: MATERIAL_ACTUAL_USE },
|
|
1802
|
+
positive: ["quantity"]
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
1773
1805
|
enums: {
|
|
1774
1806
|
status: TASK_STATUS,
|
|
1775
1807
|
intent: ["transport", "process", "dwell"],
|
|
@@ -5718,7 +5750,50 @@ var FlowEngine = class {
|
|
|
5718
5750
|
subjectOf(kind, localId) {
|
|
5719
5751
|
return resolveSubject(kind, localId, { tenantId: this.tenantId, scopeId: this.scopeId, identityOf: (k, id) => k === "equipment" ? this.equipmentIdentity(id) : void 0 });
|
|
5720
5752
|
}
|
|
5721
|
-
|
|
5753
|
+
/**
|
|
5754
|
+
* 운영 델타 방출 — **같은 사실을 다시 적지 않는다.**
|
|
5755
|
+
*
|
|
5756
|
+
* ── 무엇이 있었나 (2026-09-05 실측) ────────────────────────────────────────
|
|
5757
|
+
* `flow-engine.ts` 의 배정 패스가 **매 틱** `created` 인 오더 전부에 `allocate` 를 건다. 자재가
|
|
5758
|
+
* 모자란 오더는 그때마다 `mes-kernel` 의 「모자람을 적고 다음 틱에 다시 본다」 줄에 닿았고, 거기서
|
|
5759
|
+
* **바뀐 것이 없어도 방출**했다.
|
|
5760
|
+
*
|
|
5761
|
+
* hatio-mx2 오더 315개 → 세 시간에 order.status 2,433,116건 (오더당 7,700)
|
|
5762
|
+
* 다른 트윈 오더당 1~2건
|
|
5763
|
+
* 틱 로그 「journal 706.92ms(88%)」
|
|
5764
|
+
*
|
|
5765
|
+
* 다시 보는 것은 옳다(모자람은 채워질 수 있다). **다시 볼 때마다 적는 것**이 결함이다.
|
|
5766
|
+
*
|
|
5767
|
+
* ── 파급이 디스크가 아니다 ─────────────────────────────────────────────────
|
|
5768
|
+
* 재기동 저널을 접어 상태를 세운다 — 되세우는 시간이 그만큼 는다
|
|
5769
|
+
* 구독 이 사건들은 방송된다. 막힌 오더 × 매 틱 × 구독자 수
|
|
5770
|
+
* 틱 시뮬 틱은 메인 이벤트 루프에서 돈다 — HTTP·구독이 함께 느려진다
|
|
5771
|
+
* 지표 오더 사건을 세는 모든 것이 부푼다
|
|
5772
|
+
* 진짜 문제 「오더가 자재를 못 구해 멈췄다」가 자기가 만든 소음에 묻힌다
|
|
5773
|
+
*
|
|
5774
|
+
* 가장 나쁜 것은 방향이다. **현장이 막힐수록 트윈이 더 무너진다** — 잘 흐르면 사건이 적고 막히면
|
|
5775
|
+
* 폭증한다. 트윈이 가장 필요한 순간에 가장 약해진다.
|
|
5776
|
+
*
|
|
5777
|
+
* ── 왜 여기인가 ────────────────────────────────────────────────────────────
|
|
5778
|
+
* 부르는 자리 하나를 막으면 다른 자리에서 같은 일이 난다 — `emitOrder` 를 부르는 곳만 열다섯이다.
|
|
5779
|
+
* 그리고 `revision` 이 여기서 오르므로, 여기서 막지 않으면 **적지 않고도 판만 올라간다.**
|
|
5780
|
+
*
|
|
5781
|
+
* ── 무엇을 같다고 보나 ─────────────────────────────────────────────────────
|
|
5782
|
+
* `data` 가 바이트까지 같으면 같다. 시각은 `data` 에 없다(여기서 붙인다) — 그래서 「같은 사실을
|
|
5783
|
+
* 다른 시각에 다시 말한 것」이 정확히 걸러진다.
|
|
5784
|
+
*
|
|
5785
|
+
* `subject` 를 안 주면 거르지 않는다. 대상이 없는 사건(주의 등)은 반복 자체가 사실이다.
|
|
5786
|
+
*
|
|
5787
|
+
* 재기동하면 이 기억이 비므로 **첫 방출은 언제나 나간다** — 되세운 상태가 조용히 빠지지 않는다.
|
|
5788
|
+
*/
|
|
5789
|
+
lastEmitted = /* @__PURE__ */ new Map();
|
|
5790
|
+
emitOp(eventType, data, subject) {
|
|
5791
|
+
if (subject !== void 0) {
|
|
5792
|
+
const key = `${eventType}\0${subject}`;
|
|
5793
|
+
const json = JSON.stringify(data);
|
|
5794
|
+
if (this.lastEmitted.get(key) === json) return;
|
|
5795
|
+
this.lastEmitted.set(key, json);
|
|
5796
|
+
}
|
|
5722
5797
|
this.revision++;
|
|
5723
5798
|
const e = { eventId: `${this.tenantId}-evt-${++this.eventSeq}`, eventType, eventTime: this.now(), tenantId: this.tenantId, ...this._correlationId ? { correlationId: this._correlationId } : {}, data };
|
|
5724
5799
|
for (const h of this.handlers) h(e);
|
|
@@ -5755,19 +5830,19 @@ var FlowEngine = class {
|
|
|
5755
5830
|
...t.startTime ? { startTime: t.startTime } : {},
|
|
5756
5831
|
...t.endTime ? { endTime: t.endTime } : {},
|
|
5757
5832
|
...inProgress ? { remainingMs: t.remainingMs, startedAtSimMs: t.startedAtSimMs, progress: t.durationMs ? done / t.durationMs : void 0 } : {}
|
|
5758
|
-
});
|
|
5833
|
+
}, t.id);
|
|
5759
5834
|
}
|
|
5760
5835
|
/** 사람 상태 전이 — 설비와 별개 채널(어휘가 다르다: 고장이 아니라 교대·투입). */
|
|
5761
5836
|
emitAsset(a) {
|
|
5762
|
-
this.emitOp(OP_EVENT.asset, { assetId: a.id, assetClassIds: a.assetClassIds, ...a.ratedUsage ? { ratedUsage: a.ratedUsage } : {}, ...a.usedUsage ? { usedUsage: a.usedUsage } : {}, status: a.status, location: a.location, taskId: a.taskId ?? void 0, carrying: a.carrying, ...effectiveOnly(a) });
|
|
5837
|
+
this.emitOp(OP_EVENT.asset, { assetId: a.id, assetClassIds: a.assetClassIds, ...a.ratedUsage ? { ratedUsage: a.ratedUsage } : {}, ...a.usedUsage ? { usedUsage: a.usedUsage } : {}, status: a.status, location: a.location, taskId: a.taskId ?? void 0, carrying: a.carrying, ...effectiveOnly(a) }, a.id);
|
|
5763
5838
|
}
|
|
5764
5839
|
emitPerson(p) {
|
|
5765
|
-
this.emitOp(OP_EVENT.person, { personId: p.id, personnelClassIds: p.personnelClassIds, status: p.status, taskId: p.taskId ?? void 0, ...p.location ? { location: p.location } : {}, ...effectiveOnly(p) });
|
|
5840
|
+
this.emitOp(OP_EVENT.person, { personId: p.id, personnelClassIds: p.personnelClassIds, status: p.status, taskId: p.taskId ?? void 0, ...p.location ? { location: p.location } : {}, ...effectiveOnly(p) }, p.id);
|
|
5766
5841
|
}
|
|
5767
5842
|
/** 설비 상태 전이 — `taskId` 를 함께 싣는다(사람·자산 델타와 같은 규칙). 없으면 미러가 "이 설비가
|
|
5768
5843
|
* 무슨 일을 하는 중인가" 를 알 수 없어 작업↔자원 연결이 한쪽에서만 성립한다. */
|
|
5769
5844
|
emitEquipment(m, motion) {
|
|
5770
|
-
this.emitOp(OP_EVENT.equipment, { moverId: m.id, kind: m.kind, ...m.equipmentClassIds ? { equipmentClassIds: m.equipmentClassIds } : {}, status: m.status, location: m.location, ...m.homeLocation ? { homeLocation: m.homeLocation } : {}, taskId: m.taskId ?? void 0, motion, ...m.held ? { held: true } : {}, ...effectiveOnly(m) });
|
|
5845
|
+
this.emitOp(OP_EVENT.equipment, { moverId: m.id, kind: m.kind, ...m.equipmentClassIds ? { equipmentClassIds: m.equipmentClassIds } : {}, status: m.status, location: m.location, ...m.homeLocation ? { homeLocation: m.homeLocation } : {}, taskId: m.taskId ?? void 0, motion, ...m.held ? { held: true } : {}, ...effectiveOnly(m) }, m.id);
|
|
5771
5846
|
}
|
|
5772
5847
|
/** 오더 델타 — **라인까지 싣는다.** 라인이 빠지면 미러가 남은 데맨드를 라인별로 재계획할 수 없다. */
|
|
5773
5848
|
emitOrder(o) {
|
|
@@ -5793,7 +5868,7 @@ var FlowEngine = class {
|
|
|
5793
5868
|
/* 약속해 둔 자리·시각창 — 이것이 빠져서 야드 트윈이 재기동마다 첫 틱에 죽었다(§dockDoor). */
|
|
5794
5869
|
...o.dockDoor ? { dockDoor: o.dockDoor } : {},
|
|
5795
5870
|
...o.windowStartMs !== void 0 ? { windowStartMs: o.windowStartMs } : {}
|
|
5796
|
-
});
|
|
5871
|
+
}, o.id);
|
|
5797
5872
|
}
|
|
5798
5873
|
// ── 내부 mechanics ─────────────────────────────────────────────────────────
|
|
5799
5874
|
/**
|
package/package.json
CHANGED