@highstate/backend 0.19.1 → 0.20.0

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.
Files changed (120) hide show
  1. package/dist/{chunk-V2NILDHS.js → chunk-52MY2TCE.js} +347 -19
  2. package/dist/chunk-52MY2TCE.js.map +1 -0
  3. package/dist/{chunk-I7BWSAN6.js → chunk-UAWBPTDW.js} +3 -3
  4. package/dist/{chunk-I7BWSAN6.js.map → chunk-UAWBPTDW.js.map} +1 -1
  5. package/dist/highstate.manifest.json +4 -4
  6. package/dist/index.js +4159 -785
  7. package/dist/index.js.map +1 -1
  8. package/dist/library/worker/main.js +5 -2
  9. package/dist/library/worker/main.js.map +1 -1
  10. package/dist/shared/index.js +2 -2
  11. package/package.json +7 -7
  12. package/prisma/backend/_schema/object.prisma +12 -0
  13. package/prisma/backend/sqlite/migrations/20260222113554_add_object_tracking/migration.sql +7 -0
  14. package/prisma/project/artifact.prisma +3 -0
  15. package/prisma/project/entity.prisma +125 -0
  16. package/prisma/project/instance.prisma +6 -0
  17. package/prisma/project/migrations/20260301210131_add_entity_tracking/migration.sql +70 -0
  18. package/prisma/project/migrations/20260302212734_add_resource_hooks_flag/migration.sql +1 -0
  19. package/prisma/project/operation.prisma +3 -0
  20. package/src/business/artifact.test.ts +22 -2
  21. package/src/business/artifact.ts +7 -1
  22. package/src/business/entity-snapshot.test.ts +684 -0
  23. package/src/business/entity-snapshot.ts +904 -0
  24. package/src/business/evaluation.test.ts +56 -0
  25. package/src/business/evaluation.ts +102 -22
  26. package/src/business/global-search.test.ts +344 -0
  27. package/src/business/global-search.ts +902 -0
  28. package/src/business/index.ts +4 -0
  29. package/src/business/instance-lock.ts +58 -74
  30. package/src/business/instance-state.test.ts +15 -1
  31. package/src/business/instance-state.ts +37 -14
  32. package/src/business/object-ref-index.test.ts +140 -0
  33. package/src/business/object-ref-index.ts +193 -0
  34. package/src/business/operation.test.ts +15 -1
  35. package/src/business/operation.ts +4 -0
  36. package/src/business/project-model.ts +154 -13
  37. package/src/business/project-unlock.ts +25 -2
  38. package/src/business/project.ts +9 -0
  39. package/src/business/secret.test.ts +35 -2
  40. package/src/business/secret.ts +32 -9
  41. package/src/business/settings.ts +761 -0
  42. package/src/business/unit-output.test.ts +477 -0
  43. package/src/business/unit-output.ts +461 -0
  44. package/src/business/worker.ts +55 -4
  45. package/src/database/_generated/backend/postgresql/browser.ts +6 -0
  46. package/src/database/_generated/backend/postgresql/client.ts +6 -0
  47. package/src/database/_generated/backend/postgresql/internal/class.ts +23 -5
  48. package/src/database/_generated/backend/postgresql/internal/prismaNamespace.ts +89 -5
  49. package/src/database/_generated/backend/postgresql/internal/prismaNamespaceBrowser.ts +9 -0
  50. package/src/database/_generated/backend/postgresql/models/Object.ts +1076 -0
  51. package/src/database/_generated/backend/postgresql/models.ts +1 -0
  52. package/src/database/_generated/backend/sqlite/browser.ts +6 -0
  53. package/src/database/_generated/backend/sqlite/client.ts +6 -0
  54. package/src/database/_generated/backend/sqlite/internal/class.ts +23 -5
  55. package/src/database/_generated/backend/sqlite/internal/prismaNamespace.ts +89 -5
  56. package/src/database/_generated/backend/sqlite/internal/prismaNamespaceBrowser.ts +9 -0
  57. package/src/database/_generated/backend/sqlite/models/Object.ts +1074 -0
  58. package/src/database/_generated/backend/sqlite/models.ts +1 -0
  59. package/src/database/_generated/project/browser.ts +23 -0
  60. package/src/database/_generated/project/client.ts +23 -0
  61. package/src/database/_generated/project/commonInputTypes.ts +87 -53
  62. package/src/database/_generated/project/enums.ts +8 -0
  63. package/src/database/_generated/project/internal/class.ts +53 -5
  64. package/src/database/_generated/project/internal/prismaNamespace.ts +367 -13
  65. package/src/database/_generated/project/internal/prismaNamespaceBrowser.ts +48 -1
  66. package/src/database/_generated/project/models/Artifact.ts +199 -11
  67. package/src/database/_generated/project/models/Entity.ts +1274 -0
  68. package/src/database/_generated/project/models/EntitySnapshot.ts +2389 -0
  69. package/src/database/_generated/project/models/EntitySnapshotContent.ts +1260 -0
  70. package/src/database/_generated/project/models/EntitySnapshotReference.ts +1449 -0
  71. package/src/database/_generated/project/models/InstanceState.ts +361 -1
  72. package/src/database/_generated/project/models/Operation.ts +148 -3
  73. package/src/database/_generated/project/models/OperationLog.ts +0 -4
  74. package/src/database/_generated/project/models.ts +4 -0
  75. package/src/database/migration.ts +3 -0
  76. package/src/library/worker/evaluator.ts +7 -1
  77. package/src/orchestrator/manager.ts +7 -0
  78. package/src/orchestrator/operation-context.captured-outputs.test.ts +118 -0
  79. package/src/orchestrator/operation-context.ts +154 -16
  80. package/src/orchestrator/operation-plan.destroy.test.md +33 -12
  81. package/src/orchestrator/operation-plan.destroy.test.ts +140 -2
  82. package/src/orchestrator/operation-plan.fixtures.ts +2 -0
  83. package/src/orchestrator/operation-plan.md +4 -1
  84. package/src/orchestrator/operation-plan.ts +286 -92
  85. package/src/orchestrator/operation-plan.update.test.md +286 -11
  86. package/src/orchestrator/operation-plan.update.test.ts +656 -5
  87. package/src/orchestrator/operation-workset.ts +72 -22
  88. package/src/orchestrator/operation.cancel.test.ts +4 -0
  89. package/src/orchestrator/operation.composite.test.ts +341 -0
  90. package/src/orchestrator/operation.destroy.test.ts +4 -0
  91. package/src/orchestrator/operation.output-validation.failure.test.ts +124 -0
  92. package/src/orchestrator/operation.preview.test.ts +4 -0
  93. package/src/orchestrator/operation.refresh.test.ts +4 -0
  94. package/src/orchestrator/operation.test-utils.ts +52 -13
  95. package/src/orchestrator/operation.ts +228 -68
  96. package/src/orchestrator/operation.update.failure.test.ts +4 -0
  97. package/src/orchestrator/operation.update.skip.test.ts +110 -0
  98. package/src/orchestrator/operation.update.test.ts +4 -0
  99. package/src/orchestrator/plan-test-builder.ts +1 -0
  100. package/src/orchestrator/unit-input-values.test.ts +450 -0
  101. package/src/orchestrator/unit-input-values.ts +281 -0
  102. package/src/pubsub/manager.ts +3 -0
  103. package/src/runner/abstractions.ts +23 -54
  104. package/src/runner/local.ts +109 -85
  105. package/src/services.ts +52 -1
  106. package/src/shared/models/prisma.ts +1 -0
  107. package/src/shared/models/project/entity.ts +121 -0
  108. package/src/shared/models/project/index.ts +1 -0
  109. package/src/shared/models/project/operation.ts +61 -3
  110. package/src/shared/models/project/state.ts +10 -0
  111. package/src/shared/models/project/worker.ts +7 -0
  112. package/src/shared/resolvers/effective-output-type.test.ts +494 -0
  113. package/src/shared/resolvers/effective-output-type.ts +162 -0
  114. package/src/shared/resolvers/index.ts +1 -0
  115. package/src/shared/resolvers/input.ts +59 -9
  116. package/src/shared/utils/index.ts +1 -0
  117. package/src/shared/utils/stable-json.ts +41 -0
  118. package/src/terminal/manager.ts +6 -0
  119. package/src/worker/manager.ts +97 -1
  120. package/dist/chunk-V2NILDHS.js.map +0 -1
@@ -210,6 +210,7 @@ export type OperationWhereInput = {
210
210
  finishedAt?: Prisma.DateTimeNullableFilter<"Operation"> | Date | string | null
211
211
  operationStates?: Prisma.InstanceOperationStateListRelationFilter
212
212
  logs?: Prisma.OperationLogListRelationFilter
213
+ entitySnapshots?: Prisma.EntitySnapshotListRelationFilter
213
214
  }
214
215
 
215
216
  export type OperationOrderByWithRelationInput = {
@@ -225,6 +226,7 @@ export type OperationOrderByWithRelationInput = {
225
226
  finishedAt?: Prisma.SortOrderInput | Prisma.SortOrder
226
227
  operationStates?: Prisma.InstanceOperationStateOrderByRelationAggregateInput
227
228
  logs?: Prisma.OperationLogOrderByRelationAggregateInput
229
+ entitySnapshots?: Prisma.EntitySnapshotOrderByRelationAggregateInput
228
230
  }
229
231
 
230
232
  export type OperationWhereUniqueInput = Prisma.AtLeast<{
@@ -243,6 +245,7 @@ export type OperationWhereUniqueInput = Prisma.AtLeast<{
243
245
  finishedAt?: Prisma.DateTimeNullableFilter<"Operation"> | Date | string | null
244
246
  operationStates?: Prisma.InstanceOperationStateListRelationFilter
245
247
  logs?: Prisma.OperationLogListRelationFilter
248
+ entitySnapshots?: Prisma.EntitySnapshotListRelationFilter
246
249
  }, "id">
247
250
 
248
251
  export type OperationOrderByWithAggregationInput = {
@@ -290,6 +293,7 @@ export type OperationCreateInput = {
290
293
  finishedAt?: Date | string | null
291
294
  operationStates?: Prisma.InstanceOperationStateCreateNestedManyWithoutOperationInput
292
295
  logs?: Prisma.OperationLogCreateNestedManyWithoutOperationInput
296
+ entitySnapshots?: Prisma.EntitySnapshotCreateNestedManyWithoutOperationInput
293
297
  }
294
298
 
295
299
  export type OperationUncheckedCreateInput = {
@@ -305,6 +309,7 @@ export type OperationUncheckedCreateInput = {
305
309
  finishedAt?: Date | string | null
306
310
  operationStates?: Prisma.InstanceOperationStateUncheckedCreateNestedManyWithoutOperationInput
307
311
  logs?: Prisma.OperationLogUncheckedCreateNestedManyWithoutOperationInput
312
+ entitySnapshots?: Prisma.EntitySnapshotUncheckedCreateNestedManyWithoutOperationInput
308
313
  }
309
314
 
310
315
  export type OperationUpdateInput = {
@@ -320,6 +325,7 @@ export type OperationUpdateInput = {
320
325
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
321
326
  operationStates?: Prisma.InstanceOperationStateUpdateManyWithoutOperationNestedInput
322
327
  logs?: Prisma.OperationLogUpdateManyWithoutOperationNestedInput
328
+ entitySnapshots?: Prisma.EntitySnapshotUpdateManyWithoutOperationNestedInput
323
329
  }
324
330
 
325
331
  export type OperationUncheckedUpdateInput = {
@@ -335,6 +341,7 @@ export type OperationUncheckedUpdateInput = {
335
341
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
336
342
  operationStates?: Prisma.InstanceOperationStateUncheckedUpdateManyWithoutOperationNestedInput
337
343
  logs?: Prisma.OperationLogUncheckedUpdateManyWithoutOperationNestedInput
344
+ entitySnapshots?: Prisma.EntitySnapshotUncheckedUpdateManyWithoutOperationNestedInput
338
345
  }
339
346
 
340
347
  export type OperationCreateManyInput = {
@@ -376,6 +383,11 @@ export type OperationUncheckedUpdateManyInput = {
376
383
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
377
384
  }
378
385
 
386
+ export type OperationScalarRelationFilter = {
387
+ is?: Prisma.OperationWhereInput
388
+ isNot?: Prisma.OperationWhereInput
389
+ }
390
+
379
391
  export type OperationCountOrderByAggregateInput = {
380
392
  id?: Prisma.SortOrder
381
393
  meta?: Prisma.SortOrder
@@ -407,9 +419,18 @@ export type OperationMinOrderByAggregateInput = {
407
419
  finishedAt?: Prisma.SortOrder
408
420
  }
409
421
 
410
- export type OperationScalarRelationFilter = {
411
- is?: Prisma.OperationWhereInput
412
- isNot?: Prisma.OperationWhereInput
422
+ export type OperationCreateNestedOneWithoutEntitySnapshotsInput = {
423
+ create?: Prisma.XOR<Prisma.OperationCreateWithoutEntitySnapshotsInput, Prisma.OperationUncheckedCreateWithoutEntitySnapshotsInput>
424
+ connectOrCreate?: Prisma.OperationCreateOrConnectWithoutEntitySnapshotsInput
425
+ connect?: Prisma.OperationWhereUniqueInput
426
+ }
427
+
428
+ export type OperationUpdateOneRequiredWithoutEntitySnapshotsNestedInput = {
429
+ create?: Prisma.XOR<Prisma.OperationCreateWithoutEntitySnapshotsInput, Prisma.OperationUncheckedCreateWithoutEntitySnapshotsInput>
430
+ connectOrCreate?: Prisma.OperationCreateOrConnectWithoutEntitySnapshotsInput
431
+ upsert?: Prisma.OperationUpsertWithoutEntitySnapshotsInput
432
+ connect?: Prisma.OperationWhereUniqueInput
433
+ update?: Prisma.XOR<Prisma.XOR<Prisma.OperationUpdateToOneWithWhereWithoutEntitySnapshotsInput, Prisma.OperationUpdateWithoutEntitySnapshotsInput>, Prisma.OperationUncheckedUpdateWithoutEntitySnapshotsInput>
413
434
  }
414
435
 
415
436
  export type EnumOperationTypeFieldUpdateOperationsInput = {
@@ -452,6 +473,82 @@ export type OperationUpdateOneRequiredWithoutLogsNestedInput = {
452
473
  update?: Prisma.XOR<Prisma.XOR<Prisma.OperationUpdateToOneWithWhereWithoutLogsInput, Prisma.OperationUpdateWithoutLogsInput>, Prisma.OperationUncheckedUpdateWithoutLogsInput>
453
474
  }
454
475
 
476
+ export type OperationCreateWithoutEntitySnapshotsInput = {
477
+ id?: string
478
+ meta:PrismaJson.OperationMeta
479
+ type: $Enums.OperationType
480
+ status?: $Enums.OperationStatus
481
+ options:PrismaJson.OperationOptions
482
+ requestedInstanceIds:PrismaJson.InstanceIds
483
+ phases?:PrismaJson.OperationPhase[] | Prisma.NullableJsonNullValueInput
484
+ startedAt?: Date | string
485
+ updatedAt?: Date | string
486
+ finishedAt?: Date | string | null
487
+ operationStates?: Prisma.InstanceOperationStateCreateNestedManyWithoutOperationInput
488
+ logs?: Prisma.OperationLogCreateNestedManyWithoutOperationInput
489
+ }
490
+
491
+ export type OperationUncheckedCreateWithoutEntitySnapshotsInput = {
492
+ id?: string
493
+ meta:PrismaJson.OperationMeta
494
+ type: $Enums.OperationType
495
+ status?: $Enums.OperationStatus
496
+ options:PrismaJson.OperationOptions
497
+ requestedInstanceIds:PrismaJson.InstanceIds
498
+ phases?:PrismaJson.OperationPhase[] | Prisma.NullableJsonNullValueInput
499
+ startedAt?: Date | string
500
+ updatedAt?: Date | string
501
+ finishedAt?: Date | string | null
502
+ operationStates?: Prisma.InstanceOperationStateUncheckedCreateNestedManyWithoutOperationInput
503
+ logs?: Prisma.OperationLogUncheckedCreateNestedManyWithoutOperationInput
504
+ }
505
+
506
+ export type OperationCreateOrConnectWithoutEntitySnapshotsInput = {
507
+ where: Prisma.OperationWhereUniqueInput
508
+ create: Prisma.XOR<Prisma.OperationCreateWithoutEntitySnapshotsInput, Prisma.OperationUncheckedCreateWithoutEntitySnapshotsInput>
509
+ }
510
+
511
+ export type OperationUpsertWithoutEntitySnapshotsInput = {
512
+ update: Prisma.XOR<Prisma.OperationUpdateWithoutEntitySnapshotsInput, Prisma.OperationUncheckedUpdateWithoutEntitySnapshotsInput>
513
+ create: Prisma.XOR<Prisma.OperationCreateWithoutEntitySnapshotsInput, Prisma.OperationUncheckedCreateWithoutEntitySnapshotsInput>
514
+ where?: Prisma.OperationWhereInput
515
+ }
516
+
517
+ export type OperationUpdateToOneWithWhereWithoutEntitySnapshotsInput = {
518
+ where?: Prisma.OperationWhereInput
519
+ data: Prisma.XOR<Prisma.OperationUpdateWithoutEntitySnapshotsInput, Prisma.OperationUncheckedUpdateWithoutEntitySnapshotsInput>
520
+ }
521
+
522
+ export type OperationUpdateWithoutEntitySnapshotsInput = {
523
+ id?: Prisma.StringFieldUpdateOperationsInput | string
524
+ meta?:PrismaJson.OperationMeta
525
+ type?: Prisma.EnumOperationTypeFieldUpdateOperationsInput | $Enums.OperationType
526
+ status?: Prisma.EnumOperationStatusFieldUpdateOperationsInput | $Enums.OperationStatus
527
+ options?:PrismaJson.OperationOptions
528
+ requestedInstanceIds?:PrismaJson.InstanceIds
529
+ phases?:PrismaJson.OperationPhase[] | Prisma.NullableJsonNullValueInput
530
+ startedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
531
+ updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
532
+ finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
533
+ operationStates?: Prisma.InstanceOperationStateUpdateManyWithoutOperationNestedInput
534
+ logs?: Prisma.OperationLogUpdateManyWithoutOperationNestedInput
535
+ }
536
+
537
+ export type OperationUncheckedUpdateWithoutEntitySnapshotsInput = {
538
+ id?: Prisma.StringFieldUpdateOperationsInput | string
539
+ meta?:PrismaJson.OperationMeta
540
+ type?: Prisma.EnumOperationTypeFieldUpdateOperationsInput | $Enums.OperationType
541
+ status?: Prisma.EnumOperationStatusFieldUpdateOperationsInput | $Enums.OperationStatus
542
+ options?:PrismaJson.OperationOptions
543
+ requestedInstanceIds?:PrismaJson.InstanceIds
544
+ phases?:PrismaJson.OperationPhase[] | Prisma.NullableJsonNullValueInput
545
+ startedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
546
+ updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
547
+ finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
548
+ operationStates?: Prisma.InstanceOperationStateUncheckedUpdateManyWithoutOperationNestedInput
549
+ logs?: Prisma.OperationLogUncheckedUpdateManyWithoutOperationNestedInput
550
+ }
551
+
455
552
  export type OperationCreateWithoutOperationStatesInput = {
456
553
  id?: string
457
554
  meta:PrismaJson.OperationMeta
@@ -464,6 +561,7 @@ export type OperationCreateWithoutOperationStatesInput = {
464
561
  updatedAt?: Date | string
465
562
  finishedAt?: Date | string | null
466
563
  logs?: Prisma.OperationLogCreateNestedManyWithoutOperationInput
564
+ entitySnapshots?: Prisma.EntitySnapshotCreateNestedManyWithoutOperationInput
467
565
  }
468
566
 
469
567
  export type OperationUncheckedCreateWithoutOperationStatesInput = {
@@ -478,6 +576,7 @@ export type OperationUncheckedCreateWithoutOperationStatesInput = {
478
576
  updatedAt?: Date | string
479
577
  finishedAt?: Date | string | null
480
578
  logs?: Prisma.OperationLogUncheckedCreateNestedManyWithoutOperationInput
579
+ entitySnapshots?: Prisma.EntitySnapshotUncheckedCreateNestedManyWithoutOperationInput
481
580
  }
482
581
 
483
582
  export type OperationCreateOrConnectWithoutOperationStatesInput = {
@@ -508,6 +607,7 @@ export type OperationUpdateWithoutOperationStatesInput = {
508
607
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
509
608
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
510
609
  logs?: Prisma.OperationLogUpdateManyWithoutOperationNestedInput
610
+ entitySnapshots?: Prisma.EntitySnapshotUpdateManyWithoutOperationNestedInput
511
611
  }
512
612
 
513
613
  export type OperationUncheckedUpdateWithoutOperationStatesInput = {
@@ -522,6 +622,7 @@ export type OperationUncheckedUpdateWithoutOperationStatesInput = {
522
622
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
523
623
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
524
624
  logs?: Prisma.OperationLogUncheckedUpdateManyWithoutOperationNestedInput
625
+ entitySnapshots?: Prisma.EntitySnapshotUncheckedUpdateManyWithoutOperationNestedInput
525
626
  }
526
627
 
527
628
  export type OperationCreateWithoutLogsInput = {
@@ -536,6 +637,7 @@ export type OperationCreateWithoutLogsInput = {
536
637
  updatedAt?: Date | string
537
638
  finishedAt?: Date | string | null
538
639
  operationStates?: Prisma.InstanceOperationStateCreateNestedManyWithoutOperationInput
640
+ entitySnapshots?: Prisma.EntitySnapshotCreateNestedManyWithoutOperationInput
539
641
  }
540
642
 
541
643
  export type OperationUncheckedCreateWithoutLogsInput = {
@@ -550,6 +652,7 @@ export type OperationUncheckedCreateWithoutLogsInput = {
550
652
  updatedAt?: Date | string
551
653
  finishedAt?: Date | string | null
552
654
  operationStates?: Prisma.InstanceOperationStateUncheckedCreateNestedManyWithoutOperationInput
655
+ entitySnapshots?: Prisma.EntitySnapshotUncheckedCreateNestedManyWithoutOperationInput
553
656
  }
554
657
 
555
658
  export type OperationCreateOrConnectWithoutLogsInput = {
@@ -580,6 +683,7 @@ export type OperationUpdateWithoutLogsInput = {
580
683
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
581
684
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
582
685
  operationStates?: Prisma.InstanceOperationStateUpdateManyWithoutOperationNestedInput
686
+ entitySnapshots?: Prisma.EntitySnapshotUpdateManyWithoutOperationNestedInput
583
687
  }
584
688
 
585
689
  export type OperationUncheckedUpdateWithoutLogsInput = {
@@ -594,6 +698,7 @@ export type OperationUncheckedUpdateWithoutLogsInput = {
594
698
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
595
699
  finishedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
596
700
  operationStates?: Prisma.InstanceOperationStateUncheckedUpdateManyWithoutOperationNestedInput
701
+ entitySnapshots?: Prisma.EntitySnapshotUncheckedUpdateManyWithoutOperationNestedInput
597
702
  }
598
703
 
599
704
 
@@ -604,11 +709,13 @@ export type OperationUncheckedUpdateWithoutLogsInput = {
604
709
  export type OperationCountOutputType = {
605
710
  operationStates: number
606
711
  logs: number
712
+ entitySnapshots: number
607
713
  }
608
714
 
609
715
  export type OperationCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
610
716
  operationStates?: boolean | OperationCountOutputTypeCountOperationStatesArgs
611
717
  logs?: boolean | OperationCountOutputTypeCountLogsArgs
718
+ entitySnapshots?: boolean | OperationCountOutputTypeCountEntitySnapshotsArgs
612
719
  }
613
720
 
614
721
  /**
@@ -635,6 +742,13 @@ export type OperationCountOutputTypeCountLogsArgs<ExtArgs extends runtime.Types.
635
742
  where?: Prisma.OperationLogWhereInput
636
743
  }
637
744
 
745
+ /**
746
+ * OperationCountOutputType without action
747
+ */
748
+ export type OperationCountOutputTypeCountEntitySnapshotsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
749
+ where?: Prisma.EntitySnapshotWhereInput
750
+ }
751
+
638
752
 
639
753
  export type OperationSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
640
754
  id?: boolean
@@ -649,6 +763,7 @@ export type OperationSelect<ExtArgs extends runtime.Types.Extensions.InternalArg
649
763
  finishedAt?: boolean
650
764
  operationStates?: boolean | Prisma.Operation$operationStatesArgs<ExtArgs>
651
765
  logs?: boolean | Prisma.Operation$logsArgs<ExtArgs>
766
+ entitySnapshots?: boolean | Prisma.Operation$entitySnapshotsArgs<ExtArgs>
652
767
  _count?: boolean | Prisma.OperationCountOutputTypeDefaultArgs<ExtArgs>
653
768
  }, ExtArgs["result"]["operation"]>
654
769
 
@@ -695,6 +810,7 @@ export type OperationOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs
695
810
  export type OperationInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
696
811
  operationStates?: boolean | Prisma.Operation$operationStatesArgs<ExtArgs>
697
812
  logs?: boolean | Prisma.Operation$logsArgs<ExtArgs>
813
+ entitySnapshots?: boolean | Prisma.Operation$entitySnapshotsArgs<ExtArgs>
698
814
  _count?: boolean | Prisma.OperationCountOutputTypeDefaultArgs<ExtArgs>
699
815
  }
700
816
  export type OperationIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {}
@@ -711,6 +827,10 @@ export type $OperationPayload<ExtArgs extends runtime.Types.Extensions.InternalA
711
827
  * The logs of the operation.
712
828
  */
713
829
  logs: Prisma.$OperationLogPayload<ExtArgs>[]
830
+ /**
831
+ * The entity snapshots created by this operation.
832
+ */
833
+ entitySnapshots: Prisma.$EntitySnapshotPayload<ExtArgs>[]
714
834
  }
715
835
  scalars: runtime.Types.Extensions.GetPayloadResult<{
716
836
  /**
@@ -1157,6 +1277,7 @@ export interface Prisma__OperationClient<T, Null = never, ExtArgs extends runtim
1157
1277
  readonly [Symbol.toStringTag]: "PrismaPromise"
1158
1278
  operationStates<T extends Prisma.Operation$operationStatesArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Operation$operationStatesArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$InstanceOperationStatePayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
1159
1279
  logs<T extends Prisma.Operation$logsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Operation$logsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$OperationLogPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
1280
+ entitySnapshots<T extends Prisma.Operation$entitySnapshotsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.Operation$entitySnapshotsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$EntitySnapshotPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
1160
1281
  /**
1161
1282
  * Attaches callbacks for the resolution and/or rejection of the Promise.
1162
1283
  * @param onfulfilled The callback to execute when the Promise is resolved.
@@ -1629,6 +1750,30 @@ export type Operation$logsArgs<ExtArgs extends runtime.Types.Extensions.Internal
1629
1750
  distinct?: Prisma.OperationLogScalarFieldEnum | Prisma.OperationLogScalarFieldEnum[]
1630
1751
  }
1631
1752
 
1753
+ /**
1754
+ * Operation.entitySnapshots
1755
+ */
1756
+ export type Operation$entitySnapshotsArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
1757
+ /**
1758
+ * Select specific fields to fetch from the EntitySnapshot
1759
+ */
1760
+ select?: Prisma.EntitySnapshotSelect<ExtArgs> | null
1761
+ /**
1762
+ * Omit specific fields from the EntitySnapshot
1763
+ */
1764
+ omit?: Prisma.EntitySnapshotOmit<ExtArgs> | null
1765
+ /**
1766
+ * Choose, which related nodes to fetch as well
1767
+ */
1768
+ include?: Prisma.EntitySnapshotInclude<ExtArgs> | null
1769
+ where?: Prisma.EntitySnapshotWhereInput
1770
+ orderBy?: Prisma.EntitySnapshotOrderByWithRelationInput | Prisma.EntitySnapshotOrderByWithRelationInput[]
1771
+ cursor?: Prisma.EntitySnapshotWhereUniqueInput
1772
+ take?: number
1773
+ skip?: number
1774
+ distinct?: Prisma.EntitySnapshotScalarFieldEnum | Prisma.EntitySnapshotScalarFieldEnum[]
1775
+ }
1776
+
1632
1777
  /**
1633
1778
  * Operation without action
1634
1779
  */
@@ -405,10 +405,6 @@ export type OperationLogUncheckedUpdateManyWithoutOperationNestedInput = {
405
405
  deleteMany?: Prisma.OperationLogScalarWhereInput | Prisma.OperationLogScalarWhereInput[]
406
406
  }
407
407
 
408
- export type BoolFieldUpdateOperationsInput = {
409
- set?: boolean
410
- }
411
-
412
408
  export type OperationLogCreateWithoutStateInput = {
413
409
  id: string
414
410
  isSystem?: boolean
@@ -11,6 +11,10 @@
11
11
  export type * from './models/ApiKey.ts'
12
12
  export type * from './models/Artifact.ts'
13
13
  export type * from './models/InstanceCustomStatus.ts'
14
+ export type * from './models/Entity.ts'
15
+ export type * from './models/EntitySnapshot.ts'
16
+ export type * from './models/EntitySnapshotReference.ts'
17
+ export type * from './models/EntitySnapshotContent.ts'
14
18
  export type * from './models/InstanceEvaluationState.ts'
15
19
  export type * from './models/InstanceState.ts'
16
20
  export type * from './models/UserProjectViewport.ts'
@@ -23,6 +23,7 @@ export const migrationPacks = {
23
23
  migrationNames: [
24
24
  //
25
25
  "20250928124105_initial_migration",
26
+ "20260222113554_add_object_tracking",
26
27
  ],
27
28
  },
28
29
  project: {
@@ -32,6 +33,8 @@ export const migrationPacks = {
32
33
  //
33
34
  "20250928130725_initial_migration",
34
35
  "20260123000000_add_instance_state_self_hash",
36
+ "20260301210131_add_entity_tracking",
37
+ "20260302212734_add_resource_hooks_flag",
35
38
  ],
36
39
  },
37
40
  }
@@ -11,6 +11,12 @@ import {
11
11
  import { mapValues } from "remeda"
12
12
  import { errorToString } from "../../common"
13
13
 
14
+ function toCloneSafeInstanceModel(instance: InstanceModel): InstanceModel {
15
+ // Runtime instances may contain Proxy-based accessors in outputs/resolvedOutputs.
16
+ // Serialize to plain data so worker thread postMessage can structured-clone it.
17
+ return JSON.parse(JSON.stringify(instance)) as InstanceModel
18
+ }
19
+
14
20
  export function evaluateProject(
15
21
  logger: Logger,
16
22
  components: Readonly<Record<string, Component>>,
@@ -42,7 +48,7 @@ export function evaluateProject(
42
48
  success: true,
43
49
 
44
50
  virtualInstances: getRuntimeInstances()
45
- .map(instance => instance.instance)
51
+ .map(instance => toCloneSafeInstanceModel(instance.instance))
46
52
  // only include top-level composite instances and their children
47
53
  .filter(instance => instance.kind === "composite" || !allInstancesMap.has(instance.id)),
48
54
 
@@ -1,6 +1,7 @@
1
1
  import type { InstanceId } from "@highstate/contract"
2
2
  import type { Logger } from "pino"
3
3
  import type {
4
+ EntitySnapshotService,
4
5
  InstanceLockService,
5
6
  InstanceStateService,
6
7
  OperationService,
@@ -8,6 +9,7 @@ import type {
8
9
  ProjectUnlockService,
9
10
  SecretService,
10
11
  UnitExtraService,
12
+ UnitOutputService,
11
13
  } from "../business"
12
14
  import type { ArtifactService } from "../business/artifact"
13
15
  import type { DatabaseManager, Operation, Project } from "../database"
@@ -37,6 +39,8 @@ export class OperationManager {
37
39
  private readonly instanceStateService: InstanceStateService,
38
40
  private readonly projectModelService: ProjectModelService,
39
41
  private readonly unitExtraService: UnitExtraService,
42
+ private readonly entitySnapshotService: EntitySnapshotService,
43
+ private readonly unitOutputService: UnitOutputService,
40
44
  private readonly database: DatabaseManager,
41
45
  private readonly logger: Logger,
42
46
  ) {
@@ -71,6 +75,7 @@ export class OperationManager {
71
75
  this.libraryBackend,
72
76
  this.instanceStateService,
73
77
  this.projectModelService,
78
+ undefined,
74
79
  this.logger,
75
80
  )
76
81
 
@@ -141,6 +146,8 @@ export class OperationManager {
141
146
  this.instanceStateService,
142
147
  this.projectModelService,
143
148
  this.unitExtraService,
149
+ this.entitySnapshotService,
150
+ this.unitOutputService,
144
151
  this.logger.child({ operationId: operation.id }),
145
152
  )
146
153
 
@@ -0,0 +1,118 @@
1
+ import pino from "pino"
2
+ import { describe, expect, test } from "vitest"
3
+ import { OperationContext } from "./operation-context"
4
+
5
+ describe("OperationContext.updateCapturedOutputValuesFromUnitOutputs", () => {
6
+ test("captures single + multiple outputs and clears missing ones", () => {
7
+ const context = new (
8
+ OperationContext as unknown as {
9
+ new (...args: unknown[]): OperationContext
10
+ }
11
+ )(
12
+ { id: "project" },
13
+ {
14
+ components: {
15
+ "component.v1": {
16
+ outputs: {
17
+ single: { type: "entity.single.v1" },
18
+ multi: { type: "entity.multi.v1", multiple: true },
19
+ },
20
+ },
21
+ },
22
+ entities: {},
23
+ },
24
+ pino({ level: "silent" }),
25
+ )
26
+
27
+ context.updateCapturedOutputValuesFromUnitOutputs({
28
+ instanceId: "component.v1:one",
29
+ instanceType: "component.v1",
30
+ outputs: {
31
+ single: { value: { a: 1 } },
32
+ multi: { value: [{ b: 2 }, { b: 3 }] },
33
+ },
34
+ })
35
+
36
+ expect(context.getCapturedOutputValues("component.v1:one", "single")).toEqual([
37
+ { ok: true, value: { a: 1 } },
38
+ ])
39
+ expect(context.getCapturedOutputValues("component.v1:one", "multi")).toEqual([
40
+ { ok: true, value: { b: 2 } },
41
+ { ok: true, value: { b: 3 } },
42
+ ])
43
+
44
+ context.updateCapturedOutputValuesFromUnitOutputs({
45
+ instanceId: "component.v1:one",
46
+ instanceType: "component.v1",
47
+ outputs: {
48
+ single: { value: null },
49
+ multi: { value: undefined },
50
+ },
51
+ })
52
+
53
+ expect(context.getCapturedOutputValues("component.v1:one", "single")).toEqual([])
54
+ expect(context.getCapturedOutputValues("component.v1:one", "multi")).toEqual([])
55
+ })
56
+
57
+ test("throws when multiple output is not an array", () => {
58
+ const context = new (
59
+ OperationContext as unknown as {
60
+ new (...args: unknown[]): OperationContext
61
+ }
62
+ )(
63
+ { id: "project" },
64
+ {
65
+ components: {
66
+ "component.v1": {
67
+ outputs: {
68
+ multi: { type: "entity.multi.v1", multiple: true },
69
+ },
70
+ },
71
+ },
72
+ entities: {},
73
+ },
74
+ pino({ level: "silent" }),
75
+ )
76
+
77
+ expect(() =>
78
+ context.updateCapturedOutputValuesFromUnitOutputs({
79
+ instanceId: "component.v1:one",
80
+ instanceType: "component.v1",
81
+ outputs: {
82
+ multi: { value: { b: 1 } },
83
+ },
84
+ }),
85
+ ).toThrow('Output "multi" for instance "component.v1:one" must be an array')
86
+ })
87
+
88
+ test("throws when output item is not an object", () => {
89
+ const context = new (
90
+ OperationContext as unknown as {
91
+ new (...args: unknown[]): OperationContext
92
+ }
93
+ )(
94
+ { id: "project" },
95
+ {
96
+ components: {
97
+ "component.v1": {
98
+ outputs: {
99
+ multi: { type: "entity.multi.v1", multiple: true },
100
+ },
101
+ },
102
+ },
103
+ entities: {},
104
+ },
105
+ pino({ level: "silent" }),
106
+ )
107
+
108
+ expect(() =>
109
+ context.updateCapturedOutputValuesFromUnitOutputs({
110
+ instanceId: "component.v1:one",
111
+ instanceType: "component.v1",
112
+ outputs: {
113
+ multi: { value: [123] },
114
+ },
115
+ }),
116
+ ).toThrow('Output "multi" for instance "component.v1:one" must contain objects')
117
+ })
118
+ })