@makaio/framework 1.0.0-dev-1788511348215 → 1.0.0-dev-1788721567504

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 (94) hide show
  1. package/dist/.makaio-build.json +2 -2
  2. package/dist/attempt-record-codec-BORASgzn.mjs +1 -0
  3. package/dist/bus/index.d.mts +19 -19
  4. package/dist/bus/index.mjs +1 -1
  5. package/dist/{context-resolution-841T7jBI.d.mts → context-resolution-CoKFKIqz.d.mts} +3 -3
  6. package/dist/contracts/adapter/index.d.mts +1 -1
  7. package/dist/contracts/artifact/index.d.mts +2 -2
  8. package/dist/contracts/canonical-model/index.d.mts +1 -1
  9. package/dist/contracts/capabilities/index.d.mts +1 -1
  10. package/dist/contracts/client/index.d.mts +1 -1
  11. package/dist/contracts/extension/index.d.mts +3 -3
  12. package/dist/contracts/index.d.mts +616 -122
  13. package/dist/contracts/index.mjs +1 -1
  14. package/dist/contracts/materialization/index.d.mts +2 -2
  15. package/dist/contracts/session/index.d.mts +2 -2
  16. package/dist/contracts/shared/index.d.mts +1 -1
  17. package/dist/contracts/variant/index.d.mts +1 -1
  18. package/dist/contracts/worker/index.d.mts +1 -1
  19. package/dist/contracts/worker/index.mjs +1 -1
  20. package/dist/contracts/workflow/index.d.mts +2 -2
  21. package/dist/{execution-attempt-repository-DY4KTptE.d.mts → execution-attempt-repository-CRdrgou3.d.mts} +512 -3
  22. package/dist/{index-jxPncqWZ2.d.mts → index--Ws52sWV2.d.mts} +4 -4
  23. package/dist/{index-Wbd_syN2.d.mts → index-37_b--BH.d.mts} +11 -11
  24. package/dist/{index-6trZYnUP2.d.mts → index-8NdPPzUh2.d.mts} +12 -12
  25. package/dist/{index-B-3I98nw.d.mts → index-AdcDBUnc.d.mts} +95 -95
  26. package/dist/{index-C6aSnO8m.d.mts → index-BJdkVFX9.d.mts} +288 -24
  27. package/dist/{index-DXtQRehh.d.mts → index-BKIxdzIw.d.mts} +11 -11
  28. package/dist/{index-CmwAJ8-5.d.mts → index-CFI6FxC7.d.mts} +1 -1
  29. package/dist/{index-DI2lS7VT.d.mts → index-CVcG4Q3X.d.mts} +5 -5
  30. package/dist/{index-DHH-93YD.d.mts → index-CYjgoYeX.d.mts} +1 -1
  31. package/dist/{index-CDud4NAm.d.mts → index-CxwqnZpT.d.mts} +75 -75
  32. package/dist/{index-BkbnC65b.d.mts → index-CyWGSxrs.d.mts} +291 -291
  33. package/dist/{index-C146Eq_J.d.mts → index-D1wTWSLR.d.mts} +327 -327
  34. package/dist/{index-Bqk0pJBQ2.d.mts → index-DBD_oFEt2.d.mts} +1 -1
  35. package/dist/{index-BmilK-co2.d.mts → index-DV38-klA2.d.mts} +12 -36
  36. package/dist/{index-DNI6UF9h.d.mts → index-I5a37JCm.d.mts} +4 -4
  37. package/dist/kernel/extension/index.d.mts +1 -1
  38. package/dist/kernel/index.d.mts +2 -2
  39. package/dist/kernel/observability/index.d.mts +1 -1
  40. package/dist/{namespace-l-HG1rLF.d.mts → namespace-Bo94cenp.d.mts} +136 -136
  41. package/dist/{namespace-DknCutQZ.d.mts → namespace-CPm9dhi2.d.mts} +2 -2
  42. package/dist/{namespace-BNp7n_gu.d.mts → namespace-CsnrP8AD.d.mts} +3 -3
  43. package/dist/{namespace-BGRHcrmp.d.mts → namespace-CstawJgN.d.mts} +2 -2
  44. package/dist/{package-efR90JGe.d.mts → package-DkZmsdCd.d.mts} +49 -1
  45. package/dist/package-UemD2NWn.mjs +7 -0
  46. package/dist/package.json +1 -1
  47. package/dist/runtime-node/index.d.mts +2 -2
  48. package/dist/runtime-node/index.mjs +24 -24
  49. package/dist/runtime-node/workflow-execution-bus-access.mjs +1 -1
  50. package/dist/runtime-node/workflow-worker/index.d.mts +2 -2
  51. package/dist/runtime-node/workflow-worker/index.mjs +1 -1
  52. package/dist/runtime-node/workflow-worker/worker-entry.d.mts +49 -9
  53. package/dist/runtime-node/workflow-worker/worker-entry.mjs +1 -1
  54. package/dist/runtime-registration-client-BTtFpt_k.mjs +1 -0
  55. package/dist/{schemas-D7EeKBDJ.d.mts → schemas-CJKHYluy.d.mts} +13 -13
  56. package/dist/{schemas-C1mxTfd7.d.mts → schemas-CenET9Cq.d.mts} +1 -1
  57. package/dist/{schemas-D7ScxLrf.d.mts → schemas-DTJtS14K.d.mts} +136 -136
  58. package/dist/services/adapter-runtime/index.d.mts +3 -3
  59. package/dist/services/adapter-runtime/namespace.d.mts +1 -1
  60. package/dist/services/adapter-runtime/schemas.d.mts +1 -1
  61. package/dist/services/agent-runtime/index.d.mts +2 -2
  62. package/dist/services/agent-runtime/namespace.d.mts +1 -1
  63. package/dist/services/agent-runtime/schemas.d.mts +1 -1
  64. package/dist/services/filesystem/namespace.d.mts +6 -6
  65. package/dist/services/filesystem/schemas.d.mts +3 -3
  66. package/dist/services/index.d.mts +86 -86
  67. package/dist/services/session/index.d.mts +1 -1
  68. package/dist/services/session/messages/namespace.d.mts +1 -1
  69. package/dist/services/settings/namespace.d.mts +10 -10
  70. package/dist/services/settings/storage/extension-configs/namespace.d.mts +3 -3
  71. package/dist/services/subagent-template/index.d.mts +2 -2
  72. package/dist/services/subagent-template/namespace.d.mts +1 -1
  73. package/dist/services/subagent-template/schemas.d.mts +1 -1
  74. package/dist/{transition-D3zUBTPc.d.mts → transition-DxsrTsn4.d.mts} +1 -1
  75. package/dist/{types-DcxBYlPA.d.mts → types-Czdm5op1.d.mts} +306 -306
  76. package/dist/{view-builder-B0j9p5C0.d.mts → view-builder-D-Wz_l_B.d.mts} +1 -1
  77. package/dist/worker-DlRdLf2d.mjs +1 -0
  78. package/dist/workflow-engine/execution-attempt-repository.d.mts +2 -2
  79. package/dist/workflow-engine/execution-attempt-repository.mjs +1 -1
  80. package/dist/workflow-engine/index.d.mts +205 -70
  81. package/dist/workflow-engine/index.mjs +1 -1
  82. package/dist/workflow-engine/package.d.mts +1 -1
  83. package/dist/workflow-engine/package.mjs +1 -1
  84. package/dist/workflow-engine/testing/index.d.mts +55 -3
  85. package/dist/workflow-engine/testing/index.mjs +1 -1
  86. package/dist/workflow-engine/testing/sqlite.d.mts +1 -1
  87. package/dist/workflow-engine/testing/sqlite.mjs +106 -38
  88. package/dist/workflow-worker-DjUfKshi.mjs +1 -0
  89. package/package.json +1 -1
  90. package/dist/attempt-record-codec-dC9LSFUE.mjs +0 -1
  91. package/dist/await-trigger-Bkg2BQfg.mjs +0 -1
  92. package/dist/package-Cgjpm9om.mjs +0 -7
  93. package/dist/worker-CARV52hT.mjs +0 -1
  94. package/dist/workflow-worker-Dul-wcOR.mjs +0 -1
@@ -1,5 +1,5 @@
1
1
  import { a as ProviderOperationClaim, i as ProcessBoundProvisionerLossProof, l as ProviderOperationOwnershipRecord, o as ProviderOperationClaimDecision, s as ProviderOperationMutationDecision } from "./provider-operation-DbdyFwNm.mjs";
2
- import { BoundedRecoveryEvidence, ProviderAllocationRef, WorkerAllocationLifetime } from "@makaio/framework/contracts";
2
+ import { BoundedRecoveryEvidence, ExecutionAttemptOperationKind, ProviderAllocationRef, WorkerAllocationLifetime } from "@makaio/framework/contracts";
3
3
 
4
4
  //#region subsystems/workflow-engine/src/execution-attempt-repository.d.ts
5
5
  /**
@@ -40,6 +40,25 @@ declare const EXECUTION_ATTEMPT_SETTLEMENT_KINDS: readonly ["outcome", "abandone
40
40
  * `null` when the attempt has not yet settled.
41
41
  */
42
42
  type ExecutionAttemptSettlementKind = (typeof EXECUTION_ATTEMPT_SETTLEMENT_KINDS)[number] | null;
43
+ /**
44
+ * Constant array of every state the attempt's operation start gate can hold.
45
+ *
46
+ * Declared as an array for the same reason the status vocabulary is: a stored
47
+ * value outside it is corruption, and a realization narrows what it read
48
+ * against this list rather than against a literal of its own.
49
+ */
50
+ declare const ATTEMPT_OPERATION_START_GATES: readonly ["open", "closed"];
51
+ /**
52
+ * State of the single durable ordering point an attempt admits operations
53
+ * through.
54
+ *
55
+ * - `open`: the attempt may still admit operations, subject to every other
56
+ * guard.
57
+ * - `closed`: the attempt will never admit another operation. Closing is
58
+ * one-way and happens exactly where the attempt stops being a place work may
59
+ * begin — when a newer attempt supersedes it, and when it settles.
60
+ */
61
+ type AttemptOperationStartGate = (typeof ATTEMPT_OPERATION_START_GATES)[number];
43
62
  /**
44
63
  * Compare two provider allocation references as values.
45
64
  *
@@ -263,13 +282,132 @@ declare class DuplicateExecutionAttemptError extends Error {
263
282
  */
264
283
  constructor(executionAttemptId: string, options?: ErrorOptions);
265
284
  }
285
+ /**
286
+ * The runtime and operation control state of one attempt.
287
+ *
288
+ * Ten facts that together decide who may act on an attempt's runtime endpoint
289
+ * and whether an operation may start. They live *on* the attempt rather than in
290
+ * a record beside it: every guard that reads them is also a guard the write has
291
+ * to repeat, and a single-row compare-and-set is what keeps that expressible.
292
+ *
293
+ * The three fences are independent and each answers a different question:
294
+ * {@link runtimeGeneration} says which runtime incarnation is current,
295
+ * {@link operationStartGate} says whether the attempt still starts work at all,
296
+ * and {@link activeOperationId} says whether it is already busy.
297
+ *
298
+ * It is also the shape {@link ExecutionAttemptRepository.getAttemptControlState}
299
+ * reports, so a process that lost its own memory of an attempt can read back
300
+ * exactly what a fresh decision would be made against.
301
+ */
302
+ interface AttemptControlState {
303
+ /**
304
+ * Monotonic fence over runtime incarnations, `0` before any registered.
305
+ *
306
+ * Allocated by {@link ExecutionAttemptRepository.registerRuntime} and never
307
+ * proposed by a caller: a runtime only ever echoes the generation it was
308
+ * given. Anything presented against an older generation is
309
+ * `stale-generation`.
310
+ */
311
+ readonly runtimeGeneration: number;
312
+ /**
313
+ * Runtime incarnation currently registered, or `null` before any was.
314
+ *
315
+ * The registration idempotency key. A report naming the stored incarnation
316
+ * is a replay and is answered `duplicate`; a different one is a new
317
+ * incarnation and takes the next generation.
318
+ */
319
+ readonly runtimeIncarnationId: string | null;
320
+ /**
321
+ * ISO-8601 instant at which readiness was accepted for the current
322
+ * generation, or `null` while it has not been.
323
+ *
324
+ * Written by {@link ExecutionAttemptRepository.markRuntimeReady} and cleared
325
+ * by every {@link ExecutionAttemptRepository.registerRuntime} that allocates
326
+ * a new generation: readiness is a property of one incarnation, so it can
327
+ * never outlive the incarnation that proved it.
328
+ */
329
+ readonly runtimeReadyAt: string | null;
330
+ /**
331
+ * Whether the attempt still admits operations.
332
+ *
333
+ * `open` from creation. Closed by {@link ExecutionAttemptRepository.createAttempt}
334
+ * on the attempt it supersedes, and by every terminal settlement on the
335
+ * attempt it settles. Closing is one-way.
336
+ */
337
+ readonly operationStartGate: AttemptOperationStartGate;
338
+ /**
339
+ * Operation currently occupying the attempt, or `null` when it is idle.
340
+ *
341
+ * The at-most-one guard: an attempt runs one operation at a time. Cleared by
342
+ * {@link ExecutionAttemptRepository.completeOperation} together with
343
+ * {@link activeOperationKind}, {@link activeOperationKey},
344
+ * {@link activeOperationGeneration}, and {@link activeOperationAdmittedAt} —
345
+ * one write, because a half-cleared
346
+ * operation would be neither active nor absent.
347
+ *
348
+ * A terminal settlement deliberately leaves it in place, so a completion that
349
+ * arrives after the attempt settled reads `resolved` rather than
350
+ * `not-active`.
351
+ */
352
+ readonly activeOperationId: string | null;
353
+ /**
354
+ * Kind of the active operation, or `null` when the attempt is idle.
355
+ *
356
+ * Kept because the bounded runtime probe and a durable owner's run are not
357
+ * interchangeable: the probe is admitted while readiness is still unproven
358
+ * and is never announced to anyone but its own runtime.
359
+ */
360
+ readonly activeOperationKind: ExecutionAttemptOperationKind | null;
361
+ /**
362
+ * Idempotency key the active operation was admitted under, or `null` when the
363
+ * attempt is idle.
364
+ *
365
+ * A second admission presenting this key is the same admission retried, and
366
+ * is answered `duplicate` with the operation identifier the first one
367
+ * received.
368
+ */
369
+ readonly activeOperationKey: string | null;
370
+ /**
371
+ * Runtime generation the active operation is fenced against, or `null` when
372
+ * the attempt is idle.
373
+ *
374
+ * A completion reported against an older generation belongs to a runtime that
375
+ * has since been superseded and is refused as `stale-generation`.
376
+ */
377
+ readonly activeOperationGeneration: number | null;
378
+ /**
379
+ * ISO-8601 instant at which the active operation was admitted, or `null`
380
+ * when the attempt is idle.
381
+ *
382
+ * Recorded so a replayed admission announces the instant the authority
383
+ * admitted the operation, not the instant of the replay. Cleared together
384
+ * with the other active-operation members.
385
+ */
386
+ readonly activeOperationAdmittedAt: string | null;
387
+ /**
388
+ * Operation identifier of the most recent completion, or `null` before any.
389
+ *
390
+ * What makes a replayed completion answerable: the active operation is gone
391
+ * by then, so without it the replay would be indistinguishable from a
392
+ * completion for an operation that never existed.
393
+ */
394
+ readonly lastCompletedOperationId: string | null;
395
+ }
266
396
  /**
267
397
  * Durable record for one execution attempt.
268
398
  *
269
399
  * Produced by the injected {@link ExecutionAttemptRepository} and consumed by
270
400
  * the Authority service. All fields are JSON-safe and contain no secrets.
401
+ *
402
+ * The {@link AttemptControlState} members are part of the record because they
403
+ * are columns on the attempt, not a separate aggregate — and they are required,
404
+ * unlike {@link claimable} and {@link settlementKind}. Every attempt holds all
405
+ * ten from {@link ExecutionAttemptRepository.createAttempt} onwards, so a
406
+ * record that omits one describes an attempt that cannot exist. Requiring them
407
+ * is what makes that omission a type error at the place the record is built,
408
+ * rather than a default silently resolved at each place it is read.
271
409
  */
272
- interface ExecutionAttemptRecord {
410
+ interface ExecutionAttemptRecord extends AttemptControlState {
273
411
  /** Authority-created attempt identifier. */
274
412
  readonly executionAttemptId: string;
275
413
  /** Owner identifier of the aggregate this attempt belongs to. */
@@ -569,6 +707,78 @@ interface AllocationRefEvolution {
569
707
  /** The new allocation reference to store if the CAS check passes. */
570
708
  readonly nextRef: ProviderAllocationRef;
571
709
  }
710
+ /**
711
+ * Input for registering a runtime incarnation as an attempt's endpoint.
712
+ *
713
+ * `executionId` is the active-attempt fence, not merely an ownership check: a
714
+ * superseded attempt must never acquire a fresh runtime endpoint, because
715
+ * nothing would ever address it again.
716
+ *
717
+ * No generation is supplied. The repository allocates it, exactly as
718
+ * {@link ExecutionAttemptRepository.beginProvisioning} mints the first claim,
719
+ * so a runtime can never propose a fence for itself.
720
+ */
721
+ interface RegisterRuntimeInput {
722
+ /** Attempt whose runtime endpoint is being registered. */
723
+ readonly executionAttemptId: string;
724
+ /** Owner identifier the attempt must belong to, and be active for. */
725
+ readonly executionId: ExecutionOwnerId;
726
+ /** Identifier of this concrete runtime incarnation, unique per boot. */
727
+ readonly runtimeIncarnationId: string;
728
+ }
729
+ /**
730
+ * Input for admitting one operation through an attempt's start gate.
731
+ *
732
+ * `admissionKey` is the caller's idempotency key and the only thing that makes
733
+ * a retry answerable: the repository mints the operation identifier, so a
734
+ * caller that lost the reply has no other way to ask which operation it got.
735
+ */
736
+ interface AdmitOperationInput {
737
+ /** Attempt the operation would run under. */
738
+ readonly executionAttemptId: string;
739
+ /** Owner identifier the attempt must belong to, and be active for. */
740
+ readonly executionId: ExecutionOwnerId;
741
+ /** Kind of operation being admitted. */
742
+ readonly operationKind: ExecutionAttemptOperationKind;
743
+ /** Caller-chosen idempotency key for this admission. */
744
+ readonly admissionKey: string;
745
+ /** Runtime generation the caller fences the admission against. */
746
+ readonly runtimeGeneration: number;
747
+ }
748
+ /**
749
+ * Input for completing the operation an attempt currently runs.
750
+ *
751
+ * Carries no `executionId`: completion frees a slot the attempt already
752
+ * occupies, and a superseded attempt owes that release just as much as an
753
+ * active one does. Refusing it would strand the operation forever.
754
+ */
755
+ interface CompleteOperationInput {
756
+ /** Attempt whose active operation is completing. */
757
+ readonly executionAttemptId: string;
758
+ /** Operation the caller believes it is completing. */
759
+ readonly operationId: string;
760
+ /** Runtime generation the completion is fenced against. */
761
+ readonly runtimeGeneration: number;
762
+ }
763
+ /**
764
+ * Input for recording that a registered runtime proved itself ready.
765
+ *
766
+ * Carries `executionId`, unlike {@link CompleteOperationInput}: completion
767
+ * releases a slot the attempt already occupies, but readiness asserts that the
768
+ * attempt's endpoint is current, and an attempt superseded between the probe's
769
+ * completion and this write no longer has a current endpoint. The generation
770
+ * fence alone cannot see that — a superseded attempt keeps its generation.
771
+ */
772
+ interface MarkRuntimeReadyInput {
773
+ /** Attempt whose runtime proved ready. */
774
+ readonly executionAttemptId: string;
775
+ /** Owner identifier the attempt must belong to, and be active for. */
776
+ readonly executionId: ExecutionOwnerId;
777
+ /** Generation the readiness belongs to. */
778
+ readonly runtimeGeneration: number;
779
+ /** ISO-8601 instant at which readiness was observed. */
780
+ readonly readyAt: string;
781
+ }
572
782
  /**
573
783
  * Durable decision for claiming provider provisioning ownership.
574
784
  *
@@ -842,6 +1052,186 @@ type ExecutionAttemptOutcomeDecision<TOutcome> = {
842
1052
  } | {
843
1053
  readonly kind: 'fenced';
844
1054
  };
1055
+ /**
1056
+ * Durable decision for registering a runtime incarnation as an attempt's
1057
+ * endpoint.
1058
+ *
1059
+ * - `registered`: the incarnation now owns the attempt's runtime endpoint at
1060
+ * `runtimeGeneration`, and everything it later presents must carry that
1061
+ * generation. Readiness starts unproven.
1062
+ * - `duplicate`: the attempt already holds exactly this incarnation. The
1063
+ * report is a replay, so the stored generation is reported unchanged
1064
+ * together with the readiness that generation has — `runtimeReadyAt` is
1065
+ * `null` when readiness was not proven yet, and an instant when it was,
1066
+ * which is what lets a caller tell "register again" from "already ready"
1067
+ * without a second read.
1068
+ * - `not-found`: no such attempt, or it does not belong to the named owner.
1069
+ * - `resolved`: the attempt has settled, so it will never run anything again.
1070
+ * - `fenced`: the attempt is no longer the active attempt for its owner.
1071
+ * - `not-allocated`: no allocation is recorded, or the recorded one is durably
1072
+ * confirmed terminated and only awaits its settlement, so there is no
1073
+ * infrastructure a runtime could be the endpoint of.
1074
+ * - `operation-active`: a workload operation is running against the current
1075
+ * generation. Registering would fence it mid-flight, so the reported
1076
+ * operation must complete first. A `runtime-probe` left active is not in the
1077
+ * way: the probe is the authority's own proof of an endpoint, and one that
1078
+ * was never completed belongs to a handshake that died. Registration
1079
+ * reclaims it in the same write that allocates the new generation, so a
1080
+ * crashed handshake cannot block the attempt's next incarnation.
1081
+ */
1082
+ type RuntimeRegistrationDecision = {
1083
+ readonly kind: 'registered';
1084
+ readonly runtimeGeneration: number;
1085
+ } | {
1086
+ readonly kind: 'duplicate';
1087
+ readonly runtimeGeneration: number;
1088
+ readonly runtimeReadyAt: string | null;
1089
+ } | {
1090
+ readonly kind: 'not-found';
1091
+ } | {
1092
+ readonly kind: 'resolved';
1093
+ } | {
1094
+ readonly kind: 'fenced';
1095
+ } | {
1096
+ readonly kind: 'not-allocated';
1097
+ } | {
1098
+ readonly kind: 'operation-active';
1099
+ readonly operationId: string;
1100
+ };
1101
+ /**
1102
+ * Durable decision for admitting one operation through an attempt's start gate.
1103
+ *
1104
+ * - `admitted`: the operation now occupies the attempt, under the reported
1105
+ * identifier and fenced against the reported generation.
1106
+ * - `duplicate`: an operation admitted under the same `admissionKey` is already
1107
+ * the active one. The retry receives that operation's identifier and the
1108
+ * generation it was admitted under rather than a second admission.
1109
+ * - `not-found`: no such attempt, or it does not belong to the named owner.
1110
+ * - `resolved`: the attempt has settled.
1111
+ * - `fenced`: the attempt is no longer the active attempt for its owner.
1112
+ * - `not-allocated`: no allocation is recorded, or the recorded one is durably
1113
+ * confirmed terminated and only awaits its settlement, so there is nothing
1114
+ * to run on.
1115
+ * - `operation-active`: a different operation already occupies the attempt.
1116
+ * - `gate-closed`: the attempt was superseded or settled, so it will never
1117
+ * admit another operation. Distinct from `fenced` and `resolved` because the
1118
+ * gate is the durable fact, and the two of them are how it came to be closed.
1119
+ * - `not-ready`: readiness has not been proven for the current generation.
1120
+ * Every kind but `runtime-probe` waits for it — the probe is precisely what
1121
+ * proves readiness, so it cannot require it.
1122
+ * - `stale-generation`: the caller fenced against a generation the attempt has
1123
+ * moved past. The current generation is reported so the caller can re-fence
1124
+ * rather than re-read.
1125
+ */
1126
+ type OperationAdmissionDecision = {
1127
+ readonly kind: 'admitted';
1128
+ readonly operationId: string;
1129
+ readonly runtimeGeneration: number; /** ISO-8601 instant the admission was recorded at. */
1130
+ readonly admittedAt: string;
1131
+ } | {
1132
+ readonly kind: 'duplicate';
1133
+ readonly operationId: string;
1134
+ readonly runtimeGeneration: number; /** ISO-8601 instant the first pass recorded the admission at. */
1135
+ readonly admittedAt: string;
1136
+ } | {
1137
+ readonly kind: 'not-found';
1138
+ } | {
1139
+ readonly kind: 'resolved';
1140
+ } | {
1141
+ readonly kind: 'fenced';
1142
+ } | {
1143
+ readonly kind: 'not-allocated';
1144
+ } | {
1145
+ readonly kind: 'operation-active';
1146
+ readonly operationId: string;
1147
+ } | {
1148
+ readonly kind: 'gate-closed';
1149
+ } | {
1150
+ readonly kind: 'not-ready';
1151
+ } | {
1152
+ readonly kind: 'stale-generation';
1153
+ readonly runtimeGeneration: number;
1154
+ };
1155
+ /**
1156
+ * Durable decision for completing the operation an attempt currently runs.
1157
+ *
1158
+ * - `completed`: the operation was the active one and the attempt is idle
1159
+ * again.
1160
+ * - `duplicate`: this operation was already completed. A replay, answered from
1161
+ * {@link AttemptControlState.lastCompletedOperationId} rather than from an
1162
+ * active operation that is by then gone.
1163
+ * - `mismatch`: a different operation occupies the attempt. The active one is
1164
+ * reported, because the caller's next move depends on which it is.
1165
+ * - `not-active`: no operation occupies the attempt and this one is not the
1166
+ * last completed one, so the caller is completing something that never ran.
1167
+ * - `stale-generation`: the completion is fenced against an older generation
1168
+ * than the operation it names, so it comes from a superseded runtime.
1169
+ * - `resolved`: the attempt has settled. Reported ahead of `not-active`
1170
+ * because a terminal settlement leaves the active operation in place
1171
+ * precisely so a late completion learns why nobody is waiting for it.
1172
+ * - `not-found`: no such attempt.
1173
+ */
1174
+ type OperationCompletionDecision = {
1175
+ readonly kind: 'completed';
1176
+ } | {
1177
+ readonly kind: 'duplicate';
1178
+ } | {
1179
+ readonly kind: 'mismatch';
1180
+ readonly activeOperationId: string;
1181
+ } | {
1182
+ readonly kind: 'not-active';
1183
+ } | {
1184
+ readonly kind: 'stale-generation';
1185
+ } | {
1186
+ readonly kind: 'resolved';
1187
+ } | {
1188
+ readonly kind: 'not-found';
1189
+ };
1190
+ /**
1191
+ * Durable decision for recording that a registered runtime proved itself ready.
1192
+ *
1193
+ * Evaluated in this order, in both realizations:
1194
+ * `not-found → resolved → fenced → not-allocated → stale-generation → duplicate → operation-active`.
1195
+ *
1196
+ * - `ready`: readiness is now durable for the fenced generation, at the
1197
+ * reported instant.
1198
+ * - `duplicate`: readiness was already recorded for this generation. The
1199
+ * instant reported is the stored one, not the caller's, so two callers
1200
+ * converge on one answer.
1201
+ * - `operation-active`: an operation occupies the attempt. Readiness is a
1202
+ * statement about an idle runtime, and recording it under a running
1203
+ * operation would claim a proof nothing performed.
1204
+ * - `stale-generation`: the caller fenced against a generation the attempt has
1205
+ * moved past, so the readiness it proved belongs to a runtime that is gone.
1206
+ * - `not-allocated`: no allocation is recorded, or the recorded one is durably
1207
+ * confirmed terminated and only awaits its settlement. A probe completed on
1208
+ * a dead allocation proves nothing that can be announced.
1209
+ * - `fenced`: the attempt is no longer the active attempt for its owner. Its
1210
+ * generation may still match, but a superseded attempt has no current
1211
+ * endpoint to declare ready.
1212
+ * - `resolved`: the attempt has settled.
1213
+ * - `not-found`: no such attempt for the given execution.
1214
+ */
1215
+ type RuntimeReadinessDecision = {
1216
+ readonly kind: 'ready';
1217
+ readonly acceptedAt: string;
1218
+ } | {
1219
+ readonly kind: 'duplicate';
1220
+ readonly acceptedAt: string;
1221
+ } | {
1222
+ readonly kind: 'operation-active';
1223
+ readonly operationId: string;
1224
+ } | {
1225
+ readonly kind: 'stale-generation';
1226
+ } | {
1227
+ readonly kind: 'not-allocated';
1228
+ } | {
1229
+ readonly kind: 'fenced';
1230
+ } | {
1231
+ readonly kind: 'resolved';
1232
+ } | {
1233
+ readonly kind: 'not-found';
1234
+ };
845
1235
  /**
846
1236
  * Passive injected port for durable execution attempt persistence.
847
1237
  *
@@ -890,6 +1280,32 @@ type ExecutionAttemptOutcomeDecision<TOutcome> = {
890
1280
  * {@link commitOutcome} deliberately requires neither, so a worker can
891
1281
  * always deliver its canonical answer.
892
1282
  *
1283
+ * 3. **An attempt starts work through one gate, and the gate closes for
1284
+ * good.** {@link AttemptControlState.operationStartGate} is the single
1285
+ * durable ordering point between "this attempt may still run something" and
1286
+ * "it never will again". It opens at {@link createAttempt} and closes
1287
+ * exactly twice over an attempt's life, both times inside the transaction
1288
+ * that made the closing true: on the attempt a newer {@link createAttempt}
1289
+ * supersedes, and on the attempt a terminal settlement settles. Closing it
1290
+ * anywhere else, or reopening it, would let work begin on an attempt whose
1291
+ * answer is already fixed.
1292
+ *
1293
+ * The gate orders admission only. It never gates {@link commitOutcome}: a
1294
+ * settled attempt closes its gate and *keeps* its active operation, so a
1295
+ * worker's canonical answer and a late completion both still find the state
1296
+ * that explains them.
1297
+ *
1298
+ * The runtime fence beside it is monotonic in the same one-way sense.
1299
+ * {@link registerRuntime} allocates each generation, refuses while an
1300
+ * operation is active, and clears readiness when it advances — so a
1301
+ * generation always names one incarnation, and readiness always names one
1302
+ * generation.
1303
+ *
1304
+ * Every refusal these transitions report is evaluated in one fixed order,
1305
+ * stated with {@link RuntimeRegistrationDecision} and
1306
+ * {@link OperationAdmissionDecision}. A realization that reorders it is
1307
+ * non-conforming.
1308
+ *
893
1309
  * An operation stays remediable after its attempt stops being the active
894
1310
  * attempt for its execution. Claim-fenced discovery, absence, cleanup, and
895
1311
  * terminal convergence may update such an attempt and close its operation,
@@ -975,6 +1391,17 @@ interface ExecutionAttemptRepository<TOutcome> {
975
1391
  * `executionAttemptId` generation; the repository only persists. The new
976
1392
  * attempt atomically becomes the active attempt for its execution.
977
1393
  *
1394
+ * The new attempt starts with its {@link AttemptControlState} at rest:
1395
+ * generation `0`, no incarnation, no readiness, no active operation, and
1396
+ * {@link AttemptControlState.operationStartGate} `open`.
1397
+ *
1398
+ * **The attempt it supersedes has its start gate closed in this same
1399
+ * transaction**, alongside the active pointer moving. A superseded attempt
1400
+ * whose gate stayed open could admit an operation between the pointer move
1401
+ * and any later cleanup, which is work begun on an attempt nobody addresses
1402
+ * any more. The pointer and the gate therefore become true together or not
1403
+ * at all.
1404
+ *
978
1405
  * `executionAttemptId` is unique for all time. Creating an attempt whose
979
1406
  * identifier already exists is a caller bug and is rejected — never
980
1407
  * answered with a decision and never applied. There is no correct way to
@@ -1145,6 +1572,88 @@ interface ExecutionAttemptRepository<TOutcome> {
1145
1572
  * @returns The durable termination decision.
1146
1573
  */
1147
1574
  recordAllocationTerminated(input: RecordAllocationTerminatedInput): Promise<AllocationTerminationDecision>;
1575
+ /**
1576
+ * Register a runtime incarnation as the attempt's endpoint.
1577
+ *
1578
+ * The repository allocates the generation — the caller supplies only the
1579
+ * incarnation identifier, which is both what it is registering and the
1580
+ * idempotency key for having registered it. A registration that succeeds
1581
+ * advances the generation by exactly one and clears
1582
+ * {@link AttemptControlState.runtimeReadyAt}, because the readiness the
1583
+ * previous incarnation proved says nothing about this one.
1584
+ *
1585
+ * It refuses while an operation is active. Advancing the generation there
1586
+ * would fence a running operation's own completion, so the reported
1587
+ * operation has to finish first — and this is why a replay by the incarnation
1588
+ * that is already registered is answered `duplicate` ahead of that refusal:
1589
+ * the operation in the way is frequently the very probe that registration
1590
+ * started.
1591
+ *
1592
+ * The refusal order is the fixed one; see {@link RuntimeRegistrationDecision}.
1593
+ * @param input - Attempt identity, owning execution, and the runtime incarnation.
1594
+ * @returns The durable registration decision.
1595
+ */
1596
+ registerRuntime(input: RegisterRuntimeInput): Promise<RuntimeRegistrationDecision>;
1597
+ /**
1598
+ * Admit one operation through the attempt's start gate.
1599
+ *
1600
+ * At most one operation occupies an attempt at a time, and the repository
1601
+ * mints its identifier. `admissionKey` is what makes a retry answerable: a
1602
+ * second admission presenting the key the active operation was admitted
1603
+ * under receives that operation's identifier rather than a second slot.
1604
+ *
1605
+ * Every kind requires proven readiness except `runtime-probe`, which is
1606
+ * admitted while {@link AttemptControlState.runtimeReadyAt} is still `null` —
1607
+ * the probe is the bounded no-op that *proves* the endpoint, so requiring
1608
+ * readiness of it would make readiness unreachable.
1609
+ *
1610
+ * The refusal order is the fixed one; see {@link OperationAdmissionDecision}.
1611
+ * @param input - Attempt identity, owning execution, kind, idempotency key, and fence.
1612
+ * @returns The durable admission decision.
1613
+ */
1614
+ admitOperation(input: AdmitOperationInput): Promise<OperationAdmissionDecision>;
1615
+ /**
1616
+ * Release the attempt's active operation.
1617
+ *
1618
+ * Clears the four active-operation members in one write and records the
1619
+ * completed identifier, so a replay is answered `duplicate` rather than
1620
+ * mistaken for a completion of something that never ran.
1621
+ *
1622
+ * Deliberately unfenced by the active-attempt pointer: a superseded attempt
1623
+ * owes the release exactly as much as an active one, and refusing it would
1624
+ * leave the operation occupying the attempt for good.
1625
+ * @param input - Attempt identity, the operation being completed, and its fence.
1626
+ * @returns The durable completion decision.
1627
+ */
1628
+ completeOperation(input: CompleteOperationInput): Promise<OperationCompletionDecision>;
1629
+ /**
1630
+ * Record that the registered runtime proved itself ready.
1631
+ *
1632
+ * Written only for the generation the caller fences against, so a proof that
1633
+ * a superseded incarnation produced can never mark the current one ready, and
1634
+ * only while the attempt is still the active attempt for its owner, so a
1635
+ * proof that completed before the attempt was superseded is refused `fenced`
1636
+ * rather than announced for an endpoint nobody will address. Recording is
1637
+ * idempotent: a second call for the same generation reports the instant
1638
+ * already stored, never the caller's own.
1639
+ * @param input - Attempt identity, the generation the proof belongs to, and when it was observed.
1640
+ * @returns The durable readiness decision.
1641
+ */
1642
+ markRuntimeReady(input: MarkRuntimeReadyInput): Promise<RuntimeReadinessDecision>;
1643
+ /**
1644
+ * Read an attempt's runtime and operation control state.
1645
+ *
1646
+ * The recovery read of {@link AttemptControlState}: a process that lost its
1647
+ * own memory of an attempt — a restart, a second controller — asks what the
1648
+ * durable state is instead of inferring it. Unfenced and regardless of
1649
+ * status, exactly like
1650
+ * {@link ExecutionAttemptRecoveryOperations.getAttemptWithAllocation}, because
1651
+ * the state of a superseded or settled attempt is precisely what a recovering
1652
+ * process needs to see.
1653
+ * @param executionAttemptId - Attempt whose control state to read.
1654
+ * @returns The control state, or `null` when no such attempt exists.
1655
+ */
1656
+ getAttemptControlState(executionAttemptId: string): Promise<AttemptControlState | null>;
1148
1657
  /**
1149
1658
  * Retrieve the active attempt for a given execution.
1150
1659
  *
@@ -1355,4 +1864,4 @@ interface ExecutionAttemptRecoveryOperations {
1355
1864
  getRecoverableAttempts(executionId: ExecutionOwnerId): Promise<readonly RecoverableAttemptRecord[]>;
1356
1865
  }
1357
1866
  //#endregion
1358
- export { RecordProviderOperationUncertaintyInput as A, PendingAttemptAbandonmentDecision as C, RecordAllocationInput as D, ProvisioningClaimDecision as E, TakeOverProviderOperationInput as F, decodeDurableOutcome as I, durableOutcome as L, RecordProvisioningAbsentInput as M, RecoverableAttemptRecord as N, RecordAllocationTerminatedInput as O, RenewProviderOperationClaimInput as P, sameAllocationRef as R, OutcomeCodec as S, ProvisioningAbsenceDecision as T, ExecutionAttemptSettlementKind as _, BeginProvisioningInput as a, HandoffProviderOperationInput as b, DurableOutcome as c, ExecutionAttemptCreate as d, ExecutionAttemptOutcomeCommit as f, ExecutionAttemptRepository as g, ExecutionAttemptRecoveryOperations as h, AllocationTerminationDecision as i, RecordProvisionerIncarnationLostInput as j, RecordInfrastructureFailureInput as k, EXECUTION_ATTEMPT_SETTLEMENT_KINDS as l, ExecutionAttemptRecord as m, AllocationRefEvolution as n, DiscoveredAllocationDecision as o, ExecutionAttemptOutcomeDecision as p, AllocationRefEvolutionDecision as r, DuplicateExecutionAttemptError as s, AllocationRecordingDecision as t, EXECUTION_ATTEMPT_STATUSES as u, ExecutionAttemptStatus as v, ProvisionerIncarnationLossDecision as w, InfrastructureFailureDecision as x, ExecutionOwnerId as y, sameDurableOutcome as z };
1867
+ export { OutcomeCodec as A, RecordProvisioningAbsentInput as B, ExecutionAttemptStatus as C, MarkRuntimeReadyInput as D, InfrastructureFailureDecision as E, RecordAllocationInput as F, RuntimeRegistrationDecision as G, RegisterRuntimeInput as H, RecordAllocationTerminatedInput as I, durableOutcome as J, TakeOverProviderOperationInput as K, RecordInfrastructureFailureInput as L, ProvisionerIncarnationLossDecision as M, ProvisioningAbsenceDecision as N, OperationAdmissionDecision as O, ProvisioningClaimDecision as P, RecordProviderOperationUncertaintyInput as R, ExecutionAttemptSettlementKind as S, HandoffProviderOperationInput as T, RenewProviderOperationClaimInput as U, RecoverableAttemptRecord as V, RuntimeReadinessDecision as W, sameDurableOutcome as X, sameAllocationRef as Y, ExecutionAttemptOutcomeCommit as _, AllocationRefEvolutionDecision as a, ExecutionAttemptRecoveryOperations as b, AttemptOperationStartGate as c, DiscoveredAllocationDecision as d, DuplicateExecutionAttemptError as f, ExecutionAttemptCreate as g, EXECUTION_ATTEMPT_STATUSES as h, AllocationRefEvolution as i, PendingAttemptAbandonmentDecision as j, OperationCompletionDecision as k, BeginProvisioningInput as l, EXECUTION_ATTEMPT_SETTLEMENT_KINDS as m, AdmitOperationInput as n, AllocationTerminationDecision as o, DurableOutcome as p, decodeDurableOutcome as q, AllocationRecordingDecision as r, AttemptControlState as s, ATTEMPT_OPERATION_START_GATES as t, CompleteOperationInput as u, ExecutionAttemptOutcomeDecision as v, ExecutionOwnerId as w, ExecutionAttemptRepository as x, ExecutionAttemptRecord as y, RecordProvisionerIncarnationLostInput as z };
@@ -27,8 +27,8 @@ type MakaioVariant = z.infer<typeof MakaioVariantSchema>;
27
27
  */
28
28
  declare const VariantUpgradeStatusSchema: z.ZodEnum<{
29
29
  error: "error";
30
- complete: "complete";
31
30
  progress: "progress";
31
+ complete: "complete";
32
32
  downloading: "downloading";
33
33
  applying: "applying";
34
34
  }>;
@@ -101,8 +101,8 @@ declare const VariantSchemas: {
101
101
  upgradeProgress: z.ZodObject<{
102
102
  status: z.ZodEnum<{
103
103
  error: "error";
104
- complete: "complete";
105
104
  progress: "progress";
105
+ complete: "complete";
106
106
  downloading: "downloading";
107
107
  applying: "applying";
108
108
  }>;
@@ -158,8 +158,8 @@ declare const VariantNamespace: _$_makaio_core0.BusNamespaceDefinition<"host:var
158
158
  upgradeProgress: _$zod.ZodObject<{
159
159
  status: _$zod.ZodEnum<{
160
160
  error: "error";
161
- complete: "complete";
162
161
  progress: "progress";
162
+ complete: "complete";
163
163
  downloading: "downloading";
164
164
  applying: "applying";
165
165
  }>;
@@ -205,8 +205,8 @@ declare const VariantSubjects: _$_makaio_core0.BusSubjects<_$_makaio_core0.FlatS
205
205
  upgradeProgress: _$zod.ZodObject<{
206
206
  status: _$zod.ZodEnum<{
207
207
  error: "error";
208
- complete: "complete";
209
208
  progress: "progress";
209
+ complete: "complete";
210
210
  downloading: "downloading";
211
211
  applying: "applying";
212
212
  }>;