@operato/twin-kernel 0.7.52 → 0.7.53

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.
@@ -70,10 +70,21 @@ export declare class MesKernel extends FlowEngine {
70
70
  * 그 트윈은 「도는데 아무 일도 안 일어나는」 모습이 된다 — 실제로 `allocateDef` 가 첫 공정의 자리를
71
71
  * 못 찾으면 조용히 `return` 했고, 오더는 영원히 배정되지 않은 채 화면에는 「running」이라 적혔다.
72
72
  *
73
- * ── 좁히지 않는다 ─────────────────────────────────────────────────────────
74
- * 「이 트윈이 실제로 지나는 라우트만 본다」는 예외를 검토했다가 버렸다. 근거로 삼은 「여러
75
- * 트윈이 한 선언을 공유한다」가 **이 코드에 없는 이야기**였다: 호스트는 트윈마다 자기 모델에서
76
- * 선언을 만든다(`productionSpecOf(model)`). 없는 사정을 상상해 검사에 구멍을 내지 않는다.
73
+ * ── 「지나는 것」만 본다 — 좁히지 않았던 것을 되돌렸다 (2026-08-23) ──────────
74
+ * 처음에는 선언된 **모든** 자재·공정을 검사했다. 근거는 「여러 트윈이 선언을 공유하는 사정은
75
+ * 코드에 없다 호스트는 트윈마다 자기 모델에서 선언을 만든다(`productionSpecOf(model)`)」였다.
76
+ * **그 전제가 틀렸다.** 선언을 만드는 번째 길이 이미 있었다: 카탈로그다. `trailer-manufacturing`
77
+ * 은 스스로 「자재 반입→보관→공정 변환→완제품 반출 … 양끝 야드 물류(YMS·WMS·MES)」라 말한다 —
78
+ * **한 선언이 사이트 전체를 덮고, 도메인마다 다른 트윈이 그 일부를 지난다.**
79
+ *
80
+ * 그래서 MES 판(여섯 노드)이 `receive`→`dock-door` · `park`→`yard-slot` · `dispatch`→`gate` 때문에
81
+ * **아예 열리지 않았다.** 셋 다 이 트윈이 지나지 않는 공정이다. 없는 사정을 상상하지 말라던 규율을
82
+ * 지키려다, **있는 사정을 못 본 채로** 검사를 넓힌 것이 잘못이었다.
83
+ *
84
+ * 좁혀도 이 가드가 지키려던 것은 그대로 남는다. 막으려던 실패는 **「오더가 영원히 배정되지 않는
85
+ * 것」**이고, 그것은 `allocateDef` 가 지나는 공정의 자리를 못 찾을 때만 생긴다(§`routeOps`). 지나지
86
+ * 않는 공정은 그 실패를 만들 수 없다. 그러니 **레시피가 쓰는 라우트의 단계**와 **그 레시피가 드나
87
+ * 내는 자재**만 본다 — 검사의 값은 유지되고, 거짓 실패만 사라진다.
77
88
  *
78
89
  * 모아서 한 번에 말한다 — 하나씩 실패하면 사람이 같은 기동을 열 번 반복한다.
79
90
  */
@@ -223,10 +223,21 @@ export class MesKernel extends FlowEngine {
223
223
  * 그 트윈은 「도는데 아무 일도 안 일어나는」 모습이 된다 — 실제로 `allocateDef` 가 첫 공정의 자리를
224
224
  * 못 찾으면 조용히 `return` 했고, 오더는 영원히 배정되지 않은 채 화면에는 「running」이라 적혔다.
225
225
  *
226
- * ── 좁히지 않는다 ─────────────────────────────────────────────────────────
227
- * 「이 트윈이 실제로 지나는 라우트만 본다」는 예외를 검토했다가 버렸다. 근거로 삼은 「여러
228
- * 트윈이 한 선언을 공유한다」가 **이 코드에 없는 이야기**였다: 호스트는 트윈마다 자기 모델에서
229
- * 선언을 만든다(`productionSpecOf(model)`). 없는 사정을 상상해 검사에 구멍을 내지 않는다.
226
+ * ── 「지나는 것」만 본다 — 좁히지 않았던 것을 되돌렸다 (2026-08-23) ──────────
227
+ * 처음에는 선언된 **모든** 자재·공정을 검사했다. 근거는 「여러 트윈이 선언을 공유하는 사정은
228
+ * 코드에 없다 호스트는 트윈마다 자기 모델에서 선언을 만든다(`productionSpecOf(model)`)」였다.
229
+ * **그 전제가 틀렸다.** 선언을 만드는 번째 길이 이미 있었다: 카탈로그다. `trailer-manufacturing`
230
+ * 은 스스로 「자재 반입→보관→공정 변환→완제품 반출 … 양끝 야드 물류(YMS·WMS·MES)」라 말한다 —
231
+ * **한 선언이 사이트 전체를 덮고, 도메인마다 다른 트윈이 그 일부를 지난다.**
232
+ *
233
+ * 그래서 MES 판(여섯 노드)이 `receive`→`dock-door` · `park`→`yard-slot` · `dispatch`→`gate` 때문에
234
+ * **아예 열리지 않았다.** 셋 다 이 트윈이 지나지 않는 공정이다. 없는 사정을 상상하지 말라던 규율을
235
+ * 지키려다, **있는 사정을 못 본 채로** 검사를 넓힌 것이 잘못이었다.
236
+ *
237
+ * 좁혀도 이 가드가 지키려던 것은 그대로 남는다. 막으려던 실패는 **「오더가 영원히 배정되지 않는
238
+ * 것」**이고, 그것은 `allocateDef` 가 지나는 공정의 자리를 못 찾을 때만 생긴다(§`routeOps`). 지나지
239
+ * 않는 공정은 그 실패를 만들 수 없다. 그러니 **레시피가 쓰는 라우트의 단계**와 **그 레시피가 드나
240
+ * 내는 자재**만 본다 — 검사의 값은 유지되고, 거짓 실패만 사라진다.
230
241
  *
231
242
  * 모아서 한 번에 말한다 — 하나씩 실패하면 사람이 같은 기동을 열 번 반복한다.
232
243
  */
@@ -241,12 +252,22 @@ export class MesKernel extends FlowEngine {
241
252
  'The kernel no longer carries a built-in demo product — what is made is decided by the model.');
242
253
  }
243
254
  const have = new Set([...this.locations.values()].map(l => l.type));
255
+ const decl = this.productionSpec.definition;
256
+ /* 이 트윈이 지나는 공정 — 선언된 레시피가 쓰는 라우트의 단계들. */
257
+ const routeKeys = new Set(this.distinctRouteKeys());
258
+ const traversed = new Set((decl.routes ?? []).filter(r => routeKeys.has(r.key)).flatMap(r => r.steps ?? []));
259
+ /* 이 트윈이 드나내는 자재 — 그 레시피들의 입력과 산출. */
260
+ const handled = new Set(this.recipesDef().flatMap(r => [...(r.inputs ?? []), ...(r.outputs ?? [])].map(x => x.material)));
244
261
  const missing = [];
245
- for (const m of this.productionSpec.definition.materials ?? []) {
262
+ for (const m of decl.materials ?? []) {
263
+ if (!handled.has(m.key))
264
+ continue;
246
265
  if (m.locationType && !have.has(m.locationType))
247
266
  missing.push(`material '${m.key}' → '${m.locationType}'`);
248
267
  }
249
- for (const op of this.productionSpec.definition.operations ?? []) {
268
+ for (const op of decl.operations ?? []) {
269
+ if (!traversed.has(op.key))
270
+ continue;
250
271
  if (op.locationType && !have.has(op.locationType))
251
272
  missing.push(`operation '${op.key}' → '${op.locationType}'`);
252
273
  }
@@ -7114,10 +7114,21 @@ var MesKernel = class extends FlowEngine {
7114
7114
  * 그 트윈은 「도는데 아무 일도 안 일어나는」 모습이 된다 — 실제로 `allocateDef` 가 첫 공정의 자리를
7115
7115
  * 못 찾으면 조용히 `return` 했고, 오더는 영원히 배정되지 않은 채 화면에는 「running」이라 적혔다.
7116
7116
  *
7117
- * ── 좁히지 않는다 ─────────────────────────────────────────────────────────
7118
- * 「이 트윈이 실제로 지나는 라우트만 본다」는 예외를 검토했다가 버렸다. 근거로 삼은 「여러
7119
- * 트윈이 한 선언을 공유한다」가 **이 코드에 없는 이야기**였다: 호스트는 트윈마다 자기 모델에서
7120
- * 선언을 만든다(`productionSpecOf(model)`). 없는 사정을 상상해 검사에 구멍을 내지 않는다.
7117
+ * ── 「지나는 것」만 본다 — 좁히지 않았던 것을 되돌렸다 (2026-08-23) ──────────
7118
+ * 처음에는 선언된 **모든** 자재·공정을 검사했다. 근거는 「여러 트윈이 선언을 공유하는 사정은
7119
+ * 코드에 없다 호스트는 트윈마다 자기 모델에서 선언을 만든다(`productionSpecOf(model)`)」였다.
7120
+ * **그 전제가 틀렸다.** 선언을 만드는 번째 길이 이미 있었다: 카탈로그다. `trailer-manufacturing`
7121
+ * 은 스스로 「자재 반입→보관→공정 변환→완제품 반출 … 양끝 야드 물류(YMS·WMS·MES)」라 말한다 —
7122
+ * **한 선언이 사이트 전체를 덮고, 도메인마다 다른 트윈이 그 일부를 지난다.**
7123
+ *
7124
+ * 그래서 MES 판(여섯 노드)이 `receive`→`dock-door` · `park`→`yard-slot` · `dispatch`→`gate` 때문에
7125
+ * **아예 열리지 않았다.** 셋 다 이 트윈이 지나지 않는 공정이다. 없는 사정을 상상하지 말라던 규율을
7126
+ * 지키려다, **있는 사정을 못 본 채로** 검사를 넓힌 것이 잘못이었다.
7127
+ *
7128
+ * 좁혀도 이 가드가 지키려던 것은 그대로 남는다. 막으려던 실패는 **「오더가 영원히 배정되지 않는
7129
+ * 것」**이고, 그것은 `allocateDef` 가 지나는 공정의 자리를 못 찾을 때만 생긴다(§`routeOps`). 지나지
7130
+ * 않는 공정은 그 실패를 만들 수 없다. 그러니 **레시피가 쓰는 라우트의 단계**와 **그 레시피가 드나
7131
+ * 내는 자재**만 본다 — 검사의 값은 유지되고, 거짓 실패만 사라진다.
7121
7132
  *
7122
7133
  * 모아서 한 번에 말한다 — 하나씩 실패하면 사람이 같은 기동을 열 번 반복한다.
7123
7134
  */
@@ -7129,11 +7140,19 @@ var MesKernel = class extends FlowEngine {
7129
7140
  );
7130
7141
  }
7131
7142
  const have = new Set([...this.locations.values()].map((l) => l.type));
7143
+ const decl = this.productionSpec.definition;
7144
+ const routeKeys = new Set(this.distinctRouteKeys());
7145
+ const traversed = new Set((decl.routes ?? []).filter((r) => routeKeys.has(r.key)).flatMap((r) => r.steps ?? []));
7146
+ const handled = new Set(
7147
+ this.recipesDef().flatMap((r) => [...r.inputs ?? [], ...r.outputs ?? []].map((x) => x.material))
7148
+ );
7132
7149
  const missing = [];
7133
- for (const m of this.productionSpec.definition.materials ?? []) {
7150
+ for (const m of decl.materials ?? []) {
7151
+ if (!handled.has(m.key)) continue;
7134
7152
  if (m.locationType && !have.has(m.locationType)) missing.push(`material '${m.key}' \u2192 '${m.locationType}'`);
7135
7153
  }
7136
- for (const op of this.productionSpec.definition.operations ?? []) {
7154
+ for (const op of decl.operations ?? []) {
7155
+ if (!traversed.has(op.key)) continue;
7137
7156
  if (op.locationType && !have.has(op.locationType)) missing.push(`operation '${op.key}' \u2192 '${op.locationType}'`);
7138
7157
  }
7139
7158
  if (missing.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@operato/twin-kernel",
3
- "version": "0.7.52",
3
+ "version": "0.7.53",
4
4
  "type": "module",
5
5
  "description": "Twin Domain Kernel — framework-agnostic, zero-dep (domain + sim + 3-channel contract). WMS/YMS/MES, EPCIS 2.0 · ISA-95.",
6
6
  "publishConfig": {