@farmslot/protocol 0.21.0 → 0.25.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 (117) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/dist/contracts/agents.d.ts +16 -0
  3. package/dist/contracts/agents.d.ts.map +1 -1
  4. package/dist/contracts/backlog.d.ts +8 -0
  5. package/dist/contracts/backlog.d.ts.map +1 -1
  6. package/dist/contracts/backlog.js.map +1 -1
  7. package/dist/contracts/device-inventory.d.ts +118 -0
  8. package/dist/contracts/device-inventory.d.ts.map +1 -0
  9. package/dist/contracts/device-inventory.js +51 -0
  10. package/dist/contracts/device-inventory.js.map +1 -0
  11. package/dist/contracts/dispatch.d.ts +2 -0
  12. package/dist/contracts/dispatch.d.ts.map +1 -1
  13. package/dist/contracts/execution-templates.d.ts +10 -0
  14. package/dist/contracts/execution-templates.d.ts.map +1 -1
  15. package/dist/contracts/gate-park.d.ts +284 -0
  16. package/dist/contracts/gate-park.d.ts.map +1 -0
  17. package/dist/contracts/gate-park.js +415 -0
  18. package/dist/contracts/gate-park.js.map +1 -0
  19. package/dist/contracts/index.d.ts +4 -0
  20. package/dist/contracts/index.d.ts.map +1 -1
  21. package/dist/contracts/index.js +4 -0
  22. package/dist/contracts/index.js.map +1 -1
  23. package/dist/contracts/pressure-admission.d.ts +175 -0
  24. package/dist/contracts/pressure-admission.d.ts.map +1 -0
  25. package/dist/contracts/pressure-admission.js +26 -0
  26. package/dist/contracts/pressure-admission.js.map +1 -0
  27. package/dist/contracts/resource-posture.d.ts +379 -0
  28. package/dist/contracts/resource-posture.d.ts.map +1 -0
  29. package/dist/contracts/resource-posture.js +293 -0
  30. package/dist/contracts/resource-posture.js.map +1 -0
  31. package/dist/contracts/resources.d.ts +27 -1
  32. package/dist/contracts/resources.d.ts.map +1 -1
  33. package/dist/contracts/resources.js +1 -1
  34. package/dist/contracts/resources.js.map +1 -1
  35. package/dist/contracts/reviews.d.ts +2 -0
  36. package/dist/contracts/reviews.d.ts.map +1 -1
  37. package/dist/contracts/reviews.js.map +1 -1
  38. package/dist/contracts/runs.d.ts +480 -7
  39. package/dist/contracts/runs.d.ts.map +1 -1
  40. package/dist/contracts/runs.js +130 -1
  41. package/dist/contracts/runs.js.map +1 -1
  42. package/dist/contracts/runtime-capabilities.d.ts +255 -3
  43. package/dist/contracts/runtime-capabilities.d.ts.map +1 -1
  44. package/dist/contracts/runtime-capabilities.js +113 -1
  45. package/dist/contracts/runtime-capabilities.js.map +1 -1
  46. package/dist/contracts/slots.d.ts +53 -1
  47. package/dist/contracts/slots.d.ts.map +1 -1
  48. package/dist/recipes/step-io.d.ts +10 -1
  49. package/dist/recipes/step-io.d.ts.map +1 -1
  50. package/dist/rpc/config.d.ts +9 -1
  51. package/dist/rpc/config.d.ts.map +1 -1
  52. package/dist/rpc/copilot-runtime.d.ts +17 -0
  53. package/dist/rpc/copilot-runtime.d.ts.map +1 -1
  54. package/dist/rpc/copilot-runtime.js +5 -0
  55. package/dist/rpc/copilot-runtime.js.map +1 -1
  56. package/dist/rpc/dispatch.d.ts +39 -1
  57. package/dist/rpc/dispatch.d.ts.map +1 -1
  58. package/dist/rpc/dispatch.js +2 -0
  59. package/dist/rpc/dispatch.js.map +1 -1
  60. package/dist/rpc/git.d.ts +35 -0
  61. package/dist/rpc/git.d.ts.map +1 -1
  62. package/dist/rpc/index.d.ts +3 -0
  63. package/dist/rpc/index.d.ts.map +1 -1
  64. package/dist/rpc/index.js +3 -0
  65. package/dist/rpc/index.js.map +1 -1
  66. package/dist/rpc/machine-pause.d.ts +158 -0
  67. package/dist/rpc/machine-pause.d.ts.map +1 -0
  68. package/dist/rpc/machine-pause.js +8 -0
  69. package/dist/rpc/machine-pause.js.map +1 -0
  70. package/dist/rpc/registry.d.ts +16 -0
  71. package/dist/rpc/registry.d.ts.map +1 -1
  72. package/dist/rpc/registry.js +17 -0
  73. package/dist/rpc/registry.js.map +1 -1
  74. package/dist/rpc/resource-posture.d.ts +36 -0
  75. package/dist/rpc/resource-posture.d.ts.map +1 -0
  76. package/dist/rpc/resource-posture.js +7 -0
  77. package/dist/rpc/resource-posture.js.map +1 -0
  78. package/dist/rpc/resource-pressure-selection.d.ts +4 -0
  79. package/dist/rpc/resource-pressure-selection.d.ts.map +1 -0
  80. package/dist/rpc/resource-pressure-selection.js +21 -0
  81. package/dist/rpc/resource-pressure-selection.js.map +1 -0
  82. package/dist/rpc/resources.d.ts +176 -1
  83. package/dist/rpc/resources.d.ts.map +1 -1
  84. package/dist/rpc/resources.js +6 -0
  85. package/dist/rpc/resources.js.map +1 -1
  86. package/dist/rpc/run.d.ts +122 -5
  87. package/dist/rpc/run.d.ts.map +1 -1
  88. package/dist/rpc/run.js +1 -0
  89. package/dist/rpc/run.js.map +1 -1
  90. package/dist/rpc/runtime-capabilities.d.ts +73 -3
  91. package/dist/rpc/runtime-capabilities.d.ts.map +1 -1
  92. package/dist/rpc/runtime-capabilities.js +11 -0
  93. package/dist/rpc/runtime-capabilities.js.map +1 -1
  94. package/dist/rpc/slot.d.ts +9 -1
  95. package/dist/rpc/slot.d.ts.map +1 -1
  96. package/dist/rpc/slot.js.map +1 -1
  97. package/dist/rpc/tmux.d.ts +4 -0
  98. package/dist/rpc/tmux.d.ts.map +1 -1
  99. package/dist/runs/decision-resolution.d.ts +7 -0
  100. package/dist/runs/decision-resolution.d.ts.map +1 -1
  101. package/dist/runs/decision-resolution.js +1 -0
  102. package/dist/runs/decision-resolution.js.map +1 -1
  103. package/dist/slots/tracking-branch.d.ts +12 -0
  104. package/dist/slots/tracking-branch.d.ts.map +1 -1
  105. package/dist/slots/tracking-branch.js +12 -0
  106. package/dist/slots/tracking-branch.js.map +1 -1
  107. package/dist/transport/events.d.ts +7 -1
  108. package/dist/transport/events.d.ts.map +1 -1
  109. package/dist/transport/events.js +2 -0
  110. package/dist/transport/events.js.map +1 -1
  111. package/dist/transport/signal.d.ts +11 -0
  112. package/dist/transport/signal.d.ts.map +1 -1
  113. package/dist/transport/signal.js +19 -1
  114. package/dist/transport/signal.js.map +1 -1
  115. package/dist/version.d.ts +1 -1
  116. package/dist/version.js +1 -1
  117. package/package.json +6 -1
@@ -0,0 +1,415 @@
1
+ /**
2
+ * Gate-park state for clients (ADR-054 `free-slot` at an operator wait).
3
+ *
4
+ * A run parked with `free-slot` keeps its gate answerable while its slot goes
5
+ * back to dispatch. Three facts then live in three different places — the park
6
+ * record's slot disposition, the restore stages the record owes, and the
7
+ * Gateway's verdict on whether the original slot can take the run back — and a
8
+ * surface that reads any one of them alone gets the run's state wrong:
9
+ *
10
+ * - occupancy alone reports a restore that re-bound the slot and then failed
11
+ * as "back", so the gate looks answerable against a worker nothing proved;
12
+ * - the phase alone reports a `partial` that never reached the slot the same
13
+ * way as one that freed it;
14
+ * - a client that decides slot availability itself picks a slot the Gateway
15
+ * did not, which is the one thing ADR-054 forbids.
16
+ *
17
+ * So this module owns the single reading, and Command Center, Companion, and
18
+ * the CLI all render it. Availability is never derived here: it is carried in
19
+ * from a Gateway verdict, or reported as not known.
20
+ *
21
+ * The predicates below moved out of the Gateway so clients share the exact
22
+ * definitions the Gateway acts on rather than approximations of them.
23
+ */
24
+ import { MACHINE_PARK_RESTORE_STAGES, } from './runs.js';
25
+ /**
26
+ * Whether this run's machine-park record released its slot (ADR-054
27
+ * `free-slot` at an operator wait, amending ADR-038's gate-held slot hold).
28
+ *
29
+ * `slotFreedAt` records the fact, not the intent: it is written only after the
30
+ * park stopped the runner and every manifest resource AND the ownership
31
+ * release landed, so a partial park never reads as freed. While it is set, the
32
+ * park record — not the slot row — is the authority for the run's slot
33
+ * binding: the run keeps `slotId` (the recovery handle and the workspace
34
+ * branch key off it) but stops counting as an occupant of that slot.
35
+ *
36
+ * This is the OCCUPANCY predicate. It must never claim a slot is free before
37
+ * the release actually landed, so dispatch cannot hand out a slot whose worker
38
+ * is still running. Use `isGateParkInFlightOrFreed` for the safety fences,
39
+ * which have the opposite bias.
40
+ */
41
+ export function isSlotFreedByPark(run) {
42
+ const park = run.park;
43
+ if (!park?.slotFreedAt)
44
+ return false;
45
+ // `slotReboundAt` is the counterpart fact, and it is what ends the release.
46
+ // `slotFreedAt` deliberately survives the whole restore — it is what tells a
47
+ // retry which stages it still owes — so reading it alone would report a slot
48
+ // the run is sitting in as free for dispatch.
49
+ return !park.slotReboundAt;
50
+ }
51
+ /**
52
+ * Whether a gate park still owes a restore before its gate may be answered.
53
+ *
54
+ * The question consumption asks, and it is NOT "does the run occupy its slot".
55
+ * A restore that re-bound the slot, booted its resources, and then failed to
56
+ * get a structured acknowledgement out of the worker leaves an occupied slot
57
+ * and a running process — and answering the gate there drives the engine
58
+ * against a worker that never confirmed it came back. So this keys on the
59
+ * restore's own stage record, which is the only thing that says what landed.
60
+ */
61
+ export function needsGateParkRestore(run) {
62
+ const park = run.park;
63
+ if (!park)
64
+ return false;
65
+ // `restored` is the ONLY thing that ends the obligation. Not the stage list:
66
+ // every stage can be complete and the record still be `partial`, because the
67
+ // orchestration resume after them failed — and reading the stages as done
68
+ // there left the run unable to answer its gate and unable to be restored
69
+ // through it. Not the residuals either: a reload that started the worker and
70
+ // lost its acknowledgement leaves an occupied slot and a running process.
71
+ if (park.phase === 'restored' || park.phase === 'cancelled')
72
+ return false;
73
+ if (park.mode !== 'release' || park.slotDisposition !== 'freed')
74
+ return false;
75
+ // The park itself is still landing. There is nothing coherent to restore
76
+ // into yet, and the in-flight fence covers that case instead.
77
+ //
78
+ // Everything else got PAST the park: it freed the slot, or a restore already
79
+ // re-bound it. A record written before stages were tracked lands here through
80
+ // `slotReboundAt` — it cleared its freed marker at the rebind, so that is the
81
+ // only fact left saying a restore touched it.
82
+ //
83
+ // A park that settled without reaching the slot at all is deliberately NOT
84
+ // here. It owes no freed-slot stages, and the outstanding-effect fence below
85
+ // is the right guard for it: it can still leave a run answerable where it
86
+ // stands when the park stopped nothing.
87
+ return Boolean(park.slotFreedAt) || Boolean(park.slotReboundAt);
88
+ }
89
+ /**
90
+ * Whether a slot-freeing park is either done or still in flight for this run.
91
+ *
92
+ * The opposite bias to `isSlotFreedByPark`: it goes true the moment the
93
+ * write-ahead record declares a freeing park and stays true through the window
94
+ * where the runner and resources are being stopped but `slotFreedAt` has not
95
+ * been written yet.
96
+ *
97
+ * Every guard that must not act on a run whose slot is disappearing uses this:
98
+ * resolving a gate, applying a posture, driving a resolved gate onward, or
99
+ * tearing the slot down after a failure. Answering a gate mid-park would
100
+ * publish against a worker that is being stopped underneath it.
101
+ *
102
+ * It is keyed on intent-or-fact HONESTLY, which matters as much as the fence
103
+ * itself. A fence that never lifts is not a fence, it is a strand: the run can
104
+ * neither answer its gate nor be restored, and cancelling it is the only exit.
105
+ * So:
106
+ *
107
+ * - the record owes a restore — it freed the slot, or a restore re-bound it
108
+ * and has not settled `restored`. Fenced, until that restore or a cancel.
109
+ * - a park that never reached the slot and settled `partial` — it will not
110
+ * finish. It is still fenced
111
+ * while ANY of its effects is outstanding: a detach not yet rolled back, or
112
+ * a runner that is not PROVABLY still running. A stopped worker cannot act
113
+ * on a gate answer, and letting the operator answer anyway would be the
114
+ * silent version of the strand. `machine.pause.restore` is the exit: it
115
+ * reloads the worker and settles the record, which lifts the fence. Only a
116
+ * park that detached nothing and left an observably live worker leaves the
117
+ * run answerable where it stands.
118
+ * - otherwise, while the intent is live — fenced.
119
+ */
120
+ export function isGateParkInFlightOrFreed(run) {
121
+ const park = run.park;
122
+ if (!park)
123
+ return false;
124
+ // A record the operator already settled fences nothing, even though it still
125
+ // carries the historical `slotFreedAt` of the release it undid.
126
+ if (park.phase === 'restored' || park.phase === 'cancelled')
127
+ return false;
128
+ // Everything that still owes a restore is fenced, by construction rather than
129
+ // by two lists of conditions that have to be kept in step. A gate that can be
130
+ // answered while a restore is outstanding is the whole failure this guards,
131
+ // and `needsGateParkRestore` already covers every freed or re-bound record —
132
+ // so what remains below is only the park that never reached the slot.
133
+ if (needsGateParkRestore(run))
134
+ return true;
135
+ if (park.mode !== 'release' || park.slotDisposition !== 'freed')
136
+ return false;
137
+ if (park.phase === 'partial') {
138
+ if (park.preservedWorkspace?.detachedAt)
139
+ return true;
140
+ // The park stops the runner before it ever touches the slot, so a partial
141
+ // that got past that point has a dead worker even though the run still owns
142
+ // its slot. Restore is what brings it back.
143
+ //
144
+ // `unknown` fences too, and that direction matters: it means the probe
145
+ // could not see the worker, which for a failure before the re-host is the
146
+ // NORMAL answer — the recorded handle still names the pane a successor
147
+ // destroyed. Reading "could not observe" as "still running" lifts the fence
148
+ // on a dead worker, and the next gate answer runs FINALIZE against it. Only
149
+ // an observed live worker leaves the run answerable.
150
+ return park.residuals?.runner !== 'running';
151
+ }
152
+ return true;
153
+ }
154
+ /**
155
+ * Whether machine parking still holds this run.
156
+ *
157
+ * The park RECORD is the authority for "is this run parked", not the run's
158
+ * persisted posture. A restore or a cancel settles the record while the posture
159
+ * it was applied under stays on the run, so a reader that trusts the posture
160
+ * decides an already-restored run is still parked — and then refuses to park it
161
+ * again, forever, as a no-op.
162
+ */
163
+ export function hasLiveParkRecord(run) {
164
+ const park = run.park;
165
+ if (!park)
166
+ return false;
167
+ return park.phase !== 'restored' && park.phase !== 'cancelled';
168
+ }
169
+ function slotStateOf(park) {
170
+ if (park.phase === 'restored' || park.phase === 'cancelled')
171
+ return 'settled';
172
+ if (park.mode !== 'release' || park.slotDisposition !== 'freed')
173
+ return 'retained';
174
+ if (park.slotFreedAt && !park.slotReboundAt)
175
+ return 'freed';
176
+ // The re-home note is written write-ahead, before the claim, so it can be
177
+ // present while the slot is still freed — which is why occupancy is read
178
+ // FIRST above. Here the slot is bound, and `rehome` says which one.
179
+ if (park.slotReboundAt)
180
+ return park.rehome ? 'rehoming' : 'restoring';
181
+ // A `partial` never reached the slot AND has stopped trying, so it is not
182
+ // "still landing". Whether its gate is answerable is not a second opinion
183
+ // formed here — it is `isGateParkInFlightOrFreed`, the same predicate
184
+ // `assertNotGateParked` fences the resolution on. Deriving it any other way
185
+ // is how the surfaces came to tell an operator to wait for a park that had
186
+ // already given up, on a run whose worker was alive and whose gate the
187
+ // Gateway would have accepted.
188
+ if (park.phase === 'partial') {
189
+ return isGateParkInFlightOrFreed({ park }) ? 'partial-needs-restore' : 'partial-answerable';
190
+ }
191
+ // The write-ahead record declares the intent before any release effect lands.
192
+ return 'freeing';
193
+ }
194
+ function restoreStageView(park) {
195
+ const progress = park.restoreProgress;
196
+ if (!progress) {
197
+ return {
198
+ state: 'not-started',
199
+ attempting: null,
200
+ completed: [],
201
+ remaining: MACHINE_PARK_RESTORE_STAGES,
202
+ };
203
+ }
204
+ const completed = MACHINE_PARK_RESTORE_STAGES.filter((stage) => progress.completed.includes(stage));
205
+ const remaining = MACHINE_PARK_RESTORE_STAGES.filter((stage) => !progress.completed.includes(stage));
206
+ // An attempted stage is in flight, not complete: the marker is written BEFORE
207
+ // the stage runs, so a crash inside one is visible as unfinished rather than
208
+ // as an absence. `complete` therefore requires every stage landed AND nothing
209
+ // being attempted, which is `machineParkRestoreComplete`.
210
+ const state = remaining.length === 0 && !progress.attempting
211
+ ? 'complete'
212
+ : completed.length === 0 && !progress.attempting
213
+ ? 'not-started'
214
+ : 'in-progress';
215
+ return {
216
+ state,
217
+ attempting: progress.attempting ?? null,
218
+ completed,
219
+ remaining,
220
+ };
221
+ }
222
+ /**
223
+ * The one reading of a run's gate park, or `null` when the run has no park
224
+ * record at all.
225
+ *
226
+ * `verdict` carries a Gateway-resolved restore target when the caller has read
227
+ * one (`machine.pause.restore`). Without it the target's `available` stays
228
+ * `null`: the record says which slot a restore would use, never whether that
229
+ * slot is free right now.
230
+ */
231
+ export function gateParkView(run, verdict) {
232
+ const park = run.park;
233
+ if (!park)
234
+ return null;
235
+ const disposition = park.slotDisposition ?? 'retained';
236
+ const slotState = slotStateOf(park);
237
+ const proof = park.recoveryProof;
238
+ return {
239
+ runId: run.id,
240
+ machine: park.machine,
241
+ slotId: park.slotId,
242
+ phase: park.phase,
243
+ slotState,
244
+ slotDisposition: disposition,
245
+ freedSlotId: isSlotFreedByPark({ park }) ? park.slotId : null,
246
+ ...(park.slotFreedAt ? { slotFreedAt: park.slotFreedAt } : {}),
247
+ ...(park.slotReboundAt ? { slotReboundAt: park.slotReboundAt } : {}),
248
+ ...(park.preservedWorkspace ? { preservedWorkspace: park.preservedWorkspace } : {}),
249
+ restoreBeforeGateAnswer: needsGateParkRestore({ park }),
250
+ restoreStage: restoreStageView(park),
251
+ restoreTarget: {
252
+ slotId: verdict?.target.slotId ?? park.rehome?.toSlotId ?? park.slotId,
253
+ // The park's ORIGINAL slot, which the record no longer names once a
254
+ // re-home has moved `slotId`. `rehome.fromSlotId` is the only surviving
255
+ // record of it, so it wins over the record's current binding.
256
+ originalSlotId: verdict?.target.originalSlotId ?? park.rehome?.fromSlotId ?? park.slotId,
257
+ disposition: verdict?.target.disposition ?? disposition,
258
+ available: verdict ? verdict.target.available : null,
259
+ ...(verdict?.eligibility ? { code: verdict.eligibility.code } : {}),
260
+ ...(verdict?.eligibility ? { reason: verdict.eligibility.reason } : {}),
261
+ },
262
+ ...(park.restoreRefusal ? { refusal: park.restoreRefusal } : {}),
263
+ ...(proof
264
+ ? {
265
+ workerProof: {
266
+ kind: proof.acknowledgement.kind,
267
+ reason: proof.acknowledgement.reason,
268
+ acceptedAt: proof.acceptedAt,
269
+ },
270
+ }
271
+ : {}),
272
+ };
273
+ }
274
+ /**
275
+ * The gate park a client should render beside a run's gate, or `null` when
276
+ * there is nothing outstanding to say.
277
+ *
278
+ * A settled record is deliberately excluded: it describes a park the operator
279
+ * already resolved, and showing it beside a live gate reads as "this run is
280
+ * parked" when it is not.
281
+ */
282
+ export function liveGateParkView(run, verdict) {
283
+ const view = gateParkView(run, verdict);
284
+ if (!view || view.slotState === 'settled')
285
+ return null;
286
+ return view;
287
+ }
288
+ /**
289
+ * Operator wording for the run's slot under its park.
290
+ *
291
+ * The sentences live here rather than in each client because the same claim has
292
+ * to read the same way in Command Center, Companion, and the CLI. A per-client
293
+ * copy is how "parked" came to mean the slot was gone on one surface and still
294
+ * held on another.
295
+ */
296
+ export function gateParkStateLabel(view) {
297
+ if (view.slotState === 'retained')
298
+ return 'Parked, slot retained';
299
+ if (view.slotState === 'freeing')
300
+ return 'Parking, slot not freed yet';
301
+ // Neither partial says "parking": the park stopped, and the difference
302
+ // between the two is the only thing that tells the operator what to do next.
303
+ if (view.slotState === 'partial-answerable') {
304
+ return 'Park failed before the slot; worker still running';
305
+ }
306
+ if (view.slotState === 'partial-needs-restore')
307
+ return 'Park failed partway; needs a restore';
308
+ if (view.slotState === 'freed')
309
+ return 'Parked, slot freed for dispatch';
310
+ if (view.slotState === 'restoring')
311
+ return 'Restoring into its slot';
312
+ if (view.slotState === 'rehoming') {
313
+ return `Restoring into ${view.restoreTarget.slotId} (was ${view.restoreTarget.originalSlotId})`;
314
+ }
315
+ return 'Park settled';
316
+ }
317
+ /** One compact line: what the park did with the slot, the branch it preserved, what it still owes. */
318
+ export function gateParkSummaryLine(view) {
319
+ const target = view.restoreTarget;
320
+ const rehomed = target.slotId !== target.originalSlotId;
321
+ const parts = [
322
+ gateParkStateLabel(view),
323
+ // The slot the run is going to, and where it came from. A single `slot X`
324
+ // after a re-home named the NEW slot with no hint it had moved, which reads
325
+ // as if the park had always been there.
326
+ rehomed ? `slot ${target.slotId} (was ${target.originalSlotId})` : `slot ${view.slotId}`,
327
+ ];
328
+ if (view.preservedWorkspace) {
329
+ const workspace = view.preservedWorkspace;
330
+ parts.push(`branch ${workspace.branch} at ${workspace.headSha}${workspace.detachedAt ? ' (detached)' : ''}`);
331
+ }
332
+ if (view.restoreStage.remaining.length && view.restoreStage.state !== 'not-started') {
333
+ parts.push(`restore owes ${view.restoreStage.remaining.join(', ')}`);
334
+ }
335
+ if (view.restoreStage.attempting)
336
+ parts.push(`attempting ${view.restoreStage.attempting}`);
337
+ if (view.workerProof)
338
+ parts.push(`worker ${view.workerProof.kind}`);
339
+ return parts.join(' · ');
340
+ }
341
+ export function gateParkGateNotice(view) {
342
+ if (!view)
343
+ return null;
344
+ if (view.slotState === 'freeing') {
345
+ return {
346
+ kind: 'park-in-flight',
347
+ blocking: true,
348
+ message: 'A free-slot park is still landing for this run, so its gate cannot be answered yet.',
349
+ };
350
+ }
351
+ if (view.slotState === 'partial-needs-restore') {
352
+ return {
353
+ kind: 'park-needs-restore',
354
+ blocking: true,
355
+ // Deliberately says what to DO. This park has stopped, so "wait" is the
356
+ // one instruction that cannot work, and it is what the old copy gave.
357
+ message: `A free-slot park failed partway and left an effect outstanding, so this gate cannot be answered until a restore settles it. Waiting will not clear it — restore the run into ${view.slotId}, or cancel it.`,
358
+ ...(view.refusal ? { refusal: view.refusal } : {}),
359
+ };
360
+ }
361
+ if (view.slotState === 'partial-answerable') {
362
+ return {
363
+ kind: 'park-answerable',
364
+ blocking: false,
365
+ message: `A free-slot park failed before it reached ${view.slotId} and left the worker running, so this gate can be answered where it stands.`,
366
+ ...(view.refusal ? { refusal: view.refusal } : {}),
367
+ };
368
+ }
369
+ if (!view.restoreBeforeGateAnswer)
370
+ return null;
371
+ const target = view.restoreTarget;
372
+ // `available === null` is "not known", never "unavailable": only a Gateway
373
+ // verdict answers it, and treating an unread answer as a block would stand in
374
+ // the operator's way for a restore that would have succeeded.
375
+ //
376
+ // A recorded refusal is likewise not a current verdict. It says the LAST
377
+ // attempt refused, which is the best thing known only while nothing newer has
378
+ // looked; an `available: true` verdict is newer by construction, and letting
379
+ // a stale refusal outrank it blocks a restore the Gateway just approved.
380
+ if (target.available === false) {
381
+ return {
382
+ kind: 'restore-blocked',
383
+ blocking: true,
384
+ message: `Answering this gate restores the run into ${target.slotId} first, and the Gateway reports that slot cannot take it back.${target.reason ? ` ${target.reason}` : ''}`,
385
+ ...(view.refusal ? { refusal: view.refusal } : {}),
386
+ };
387
+ }
388
+ if (target.available === null && view.refusal) {
389
+ return {
390
+ kind: 'restore-blocked',
391
+ blocking: true,
392
+ message: `Answering this gate restores the run into ${target.slotId} first, and the last restore attempt refused. Nothing has re-checked that slot since.`,
393
+ refusal: view.refusal,
394
+ };
395
+ }
396
+ if (target.slotId !== target.originalSlotId) {
397
+ return {
398
+ kind: 'restore-first',
399
+ blocking: false,
400
+ // Says the slot MOVED, because the operator's attach target moves with
401
+ // it. A message naming only the new slot reads as if the park had been
402
+ // there all along, and one naming only the old sends them to a pane a
403
+ // successor owns.
404
+ message: `Answering this gate restores the run into ${target.slotId} first — ${target.originalSlotId} was taken — then resolves the decision.`,
405
+ ...(view.refusal ? { refusal: view.refusal, refusalSuperseded: true } : {}),
406
+ };
407
+ }
408
+ return {
409
+ kind: 'restore-first',
410
+ blocking: false,
411
+ message: `Answering this gate restores the run into ${target.slotId} first, then resolves the decision.`,
412
+ ...(view.refusal ? { refusal: view.refusal, refusalSuperseded: true } : {}),
413
+ };
414
+ }
415
+ //# sourceMappingURL=gate-park.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-park.js","sourceRoot":"","sources":["../../src/contracts/gate-park.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EACL,2BAA2B,GAQ5B,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAsB;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,WAAW;QAAE,OAAO,KAAK,CAAC;IACrC,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,8CAA8C;IAC9C,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC;AAC7B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAsB;IACzD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,6EAA6E;IAC7E,6EAA6E;IAC7E,0EAA0E;IAC1E,yEAAyE;IACzE,6EAA6E;IAC7E,0EAA0E;IAC1E,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC9E,yEAAyE;IACzE,8DAA8D;IAC9D,EAAE;IACF,6EAA6E;IAC7E,8EAA8E;IAC9E,8EAA8E;IAC9E,8CAA8C;IAC9C,EAAE;IACF,2EAA2E;IAC3E,6EAA6E;IAC7E,0EAA0E;IAC1E,wCAAwC;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAAsB;IAC9D,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,6EAA6E;IAC7E,gEAAgE;IAChE,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAC1E,8EAA8E;IAC9E,8EAA8E;IAC9E,4EAA4E;IAC5E,6EAA6E;IAC7E,sEAAsE;IACtE,IAAI,oBAAoB,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC9E,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,kBAAkB,EAAE,UAAU;YAAE,OAAO,IAAI,CAAC;QACrD,0EAA0E;QAC1E,4EAA4E;QAC5E,4CAA4C;QAC5C,EAAE;QACF,uEAAuE;QACvE,0EAA0E;QAC1E,uEAAuE;QACvE,4EAA4E;QAC5E,4EAA4E;QAC5E,qDAAqD;QACrD,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAsB;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC;AACjE,CAAC;AAuID,SAAS,WAAW,CAAC,IAAuB;IAC1C,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IAC9E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO;QAAE,OAAO,UAAU,CAAC;IACnF,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,aAAa;QAAE,OAAO,OAAO,CAAC;IAC5D,0EAA0E;IAC1E,yEAAyE;IACzE,oEAAoE;IACpE,IAAI,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;IACtE,0EAA0E;IAC1E,0EAA0E;IAC1E,sEAAsE;IACtE,4EAA4E;IAC5E,2EAA2E;IAC3E,uEAAuE;IACvE,+BAA+B;IAC/B,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,yBAAyB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,oBAAoB,CAAC;IAC9F,CAAC;IACD,8EAA8E;IAC9E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAuB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC;IACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,KAAK,EAAE,aAAa;YACpB,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,2BAA2B;SACvC,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7D,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CACnC,CAAC;IACF,MAAM,SAAS,GAAG,2BAA2B,CAAC,MAAM,CAClD,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC/C,CAAC;IACF,8EAA8E;IAC9E,6EAA6E;IAC7E,8EAA8E;IAC9E,0DAA0D;IAC1D,MAAM,KAAK,GACT,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU;QAC5C,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU;YAC9C,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,aAAa,CAAC;IACtB,OAAO;QACL,KAAK;QACL,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,IAAI;QACvC,SAAS;QACT,SAAS;KACV,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,GAA6B,EAC7B,OAAgC;IAEhC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,IAAI,UAAU,CAAC;IACvD,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;IACjC,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,EAAE;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS;QACT,eAAe,EAAE,WAAW;QAC5B,WAAW,EAAE,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;QAC7D,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,uBAAuB,EAAE,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC;QACvD,YAAY,EAAE,gBAAgB,CAAC,IAAI,CAAC;QACpC,aAAa,EAAE;YACb,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC,MAAM;YACtE,oEAAoE;YACpE,wEAAwE;YACxE,8DAA8D;YAC9D,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,cAAc,IAAI,IAAI,CAAC,MAAM,EAAE,UAAU,IAAI,IAAI,CAAC,MAAM;YACxF,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,WAAW,IAAI,WAAW;YACvD,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YACpD,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE;QACD,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,KAAK;YACP,CAAC,CAAC;gBACE,WAAW,EAAE;oBACX,IAAI,EAAE,KAAK,CAAC,eAAe,CAAC,IAAI;oBAChC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,MAAM;oBACpC,UAAU,EAAE,KAAK,CAAC,UAAU;iBAC7B;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAA6B,EAC7B,OAAgC;IAEhC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU;QAAE,OAAO,uBAAuB,CAAC;IAClE,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,6BAA6B,CAAC;IACvE,uEAAuE;IACvE,6EAA6E;IAC7E,IAAI,IAAI,CAAC,SAAS,KAAK,oBAAoB,EAAE,CAAC;QAC5C,OAAO,mDAAmD,CAAC;IAC7D,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,uBAAuB;QAAE,OAAO,sCAAsC,CAAC;IAC9F,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO;QAAE,OAAO,iCAAiC,CAAC;IACzE,IAAI,IAAI,CAAC,SAAS,KAAK,WAAW;QAAE,OAAO,yBAAyB,CAAC;IACrE,IAAI,IAAI,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,kBAAkB,IAAI,CAAC,aAAa,CAAC,MAAM,SAAS,IAAI,CAAC,aAAa,CAAC,cAAc,GAAG,CAAC;IAClG,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,mBAAmB,CAAC,IAAkB;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC;IAClC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,cAAc,CAAC;IACxD,MAAM,KAAK,GAAG;QACZ,kBAAkB,CAAC,IAAI,CAAC;QACxB,0EAA0E;QAC1E,4EAA4E;QAC5E,wCAAwC;QACxC,OAAO,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE;KACzF,CAAC;IACF,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC;QAC1C,KAAK,CAAC,IAAI,CACR,UAAU,SAAS,CAAC,MAAM,OAAO,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CACjG,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;QACpF,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,IAAI,CAAC,YAAY,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3F,IAAI,IAAI,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAoCD,MAAM,UAAU,kBAAkB,CAAC,IAAyB;IAC1D,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE,IAAI;YACd,OAAO,EACL,qFAAqF;SACxF,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,uBAAuB,EAAE,CAAC;QAC/C,OAAO;YACL,IAAI,EAAE,oBAAoB;YAC1B,QAAQ,EAAE,IAAI;YACd,wEAAwE;YACxE,sEAAsE;YACtE,OAAO,EAAE,gLAAgL,IAAI,CAAC,MAAM,iBAAiB;YACrN,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,oBAAoB,EAAE,CAAC;QAC5C,OAAO;YACL,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,6CAA6C,IAAI,CAAC,MAAM,6EAA6E;YAC9I,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,uBAAuB;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC;IAClC,2EAA2E;IAC3E,8EAA8E;IAC9E,8DAA8D;IAC9D,EAAE;IACF,yEAAyE;IACzE,8EAA8E;IAC9E,6EAA6E;IAC7E,yEAAyE;IACzE,IAAI,MAAM,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;QAC/B,OAAO;YACL,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,6CAA6C,MAAM,CAAC,MAAM,iEAAiE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YAC9K,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO;YACL,IAAI,EAAE,iBAAiB;YACvB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,6CAA6C,MAAM,CAAC,MAAM,uFAAuF;YAC1J,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,cAAc,EAAE,CAAC;QAC5C,OAAO;YACL,IAAI,EAAE,eAAe;YACrB,QAAQ,EAAE,KAAK;YACf,uEAAuE;YACvE,uEAAuE;YACvE,sEAAsE;YACtE,kBAAkB;YAClB,OAAO,EAAE,6CAA6C,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,cAAc,0CAA0C;YAC9I,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,6CAA6C,MAAM,CAAC,MAAM,qCAAqC;QACxG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5E,CAAC;AACJ,CAAC"}
@@ -6,14 +6,18 @@ export * from './bug-score.js';
6
6
  export * from './chat.js';
7
7
  export * from './common.js';
8
8
  export * from './config.js';
9
+ export * from './device-inventory.js';
9
10
  export * from './dispatch.js';
10
11
  export * from './evals.js';
11
12
  export * from './execution-templates.js';
12
13
  export * from './family.js';
14
+ export * from './gate-park.js';
13
15
  export * from './interactive-operator-packets.js';
14
16
  export * from './pr-recommendation.js';
17
+ export * from './pressure-admission.js';
15
18
  export * from './provider-accounts.js';
16
19
  export * from './recipes.js';
20
+ export * from './resource-posture.js';
17
21
  export * from './resources.js';
18
22
  export * from './reviews.js';
19
23
  export * from './roadmap.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,mCAAmC,CAAC;AAClD,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mCAAmC,CAAC;AAClD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC"}
@@ -6,14 +6,18 @@ export * from './bug-score.js';
6
6
  export * from './chat.js';
7
7
  export * from './common.js';
8
8
  export * from './config.js';
9
+ export * from './device-inventory.js';
9
10
  export * from './dispatch.js';
10
11
  export * from './evals.js';
11
12
  export * from './execution-templates.js';
12
13
  export * from './family.js';
14
+ export * from './gate-park.js';
13
15
  export * from './interactive-operator-packets.js';
14
16
  export * from './pr-recommendation.js';
17
+ export * from './pressure-admission.js';
15
18
  export * from './provider-accounts.js';
16
19
  export * from './recipes.js';
20
+ export * from './resource-posture.js';
17
21
  export * from './resources.js';
18
22
  export * from './reviews.js';
19
23
  export * from './roadmap.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,mCAAmC,CAAC;AAClD,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mCAAmC,CAAC;AAClD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,175 @@
1
+ import type { ProcessAttributionConfidence, ProcessOwnershipClass } from '../rpc/resources.js';
2
+ import type { HostPressureAdmissionMode } from './runtime-capabilities.js';
3
+ /**
4
+ * Dispatch admission has no queue: a machine under sustained pressure either
5
+ * accepts new dispatches or refuses them. Same vocabulary as the capability
6
+ * side so one word means one thing across both gates.
7
+ */
8
+ export type DispatchPressureAdmissionMode = Exclude<HostPressureAdmissionMode, 'queue'>;
9
+ export declare const DISPATCH_PRESSURE_ADMISSION_MODES: readonly DispatchPressureAdmissionMode[];
10
+ /** Machine-level admission state derived from the bounded pressure sample
11
+ * ring. `disabled` means the gateway-owned switch is off — the DEFAULT: the
12
+ * dispatch is admitted whatever the evidence says, while the evidence itself
13
+ * is still evaluated and carried as an advisory, and sampling/history/charts
14
+ * continue. */
15
+ export type PressureAdmissionState = 'green' | 'transient' | 'sustained-critical' | 'unavailable' | 'stale' | 'override' | 'disabled';
16
+ /** Stable machine-readable rejection codes. Never rename — clients and
17
+ * operators key automation off these. */
18
+ export declare const PRESSURE_ADMISSION_REJECTION_CODES: readonly ["PRESSURE_SUSTAINED_CRITICAL", "PRESSURE_EVIDENCE_UNAVAILABLE", "PRESSURE_EVIDENCE_STALE", "PRESSURE_PREVIEW_STALE", "PRESSURE_OVERRIDE_STALE", "PRESSURE_OVERRIDE_MISMATCH", "PRESSURE_OVERRIDE_REASON_REQUIRED", "PRESSURE_OVERRIDE_CONSUMED"];
19
+ export type PressureAdmissionRejectionCode = (typeof PRESSURE_ADMISSION_REJECTION_CODES)[number];
20
+ /** One normalized sample from the bounded machine pressure ring. Ratios are
21
+ * 0..1 (load1 is load average over cores, so it can exceed 1). */
22
+ export interface PressureAdmissionSample {
23
+ collectedAt: string;
24
+ /** Process-inventory generation the sample was collected under, when known. */
25
+ generation?: string;
26
+ sampleId?: number;
27
+ cpu: number;
28
+ memory: number;
29
+ disk: number;
30
+ load1?: number;
31
+ /** True when this sample crossed the policy's critical thresholds. */
32
+ critical: boolean;
33
+ }
34
+ /** Attributed cause behind the pressure, from Goal 1 process attribution.
35
+ * Unknown/manual ownership can explain pressure but is never a cleanup target. */
36
+ export interface PressureAdmissionCause {
37
+ process: string;
38
+ processCount: number;
39
+ cpuPercent: number;
40
+ rssBytes: number;
41
+ classification: ProcessOwnershipClass;
42
+ confidence: ProcessAttributionConfidence;
43
+ slotId?: string;
44
+ runId?: string;
45
+ /** False for unknown/manual ownership — those rows must never be rendered as
46
+ * cleanup targets, only as explanation. */
47
+ cleanupEligible: boolean;
48
+ }
49
+ /** Evidence backing an admission decision. `generation` is the preview
50
+ * identity: execution rejects decisions bound to a generation that no longer
51
+ * matches the current ring. */
52
+ export interface PressureAdmissionEvidence {
53
+ machine: string;
54
+ /** Opaque identity of the latest sample (generation/sampleId/collectedAt
55
+ * digest). Null when no sample exists — nothing to bind an override to. */
56
+ generation: string | null;
57
+ evaluatedAt: string;
58
+ /** Tail of the bounded ring the policy evaluated, oldest first. */
59
+ samples: PressureAdmissionSample[];
60
+ consecutiveCriticalSamples: number;
61
+ requiredConsecutiveCriticalSamples: number;
62
+ /** Milliseconds after which the newest sample counts as stale. */
63
+ staleAfterMs: number;
64
+ latestSampleAt: string | null;
65
+ /** Present when a validation-only fixture forced this machine's state.
66
+ * Real fleet evidence never carries this flag. */
67
+ validationFixture?: true;
68
+ }
69
+ /** Preview identity carried from an admitted preview into execution. FIND_SLOT
70
+ * validates it against fresh evidence BEFORE claiming a slot and, on success,
71
+ * consumes it by stamping `consumedAt` — so a long PREPARE cannot turn a
72
+ * green-to-green generation move into a failure at launch time. Execution
73
+ * still recomputes fresh evidence and rejects if pressure became unsafe; an
74
+ * UNconsumed ref reaching execution (a path that skipped FIND_SLOT
75
+ * validation) is rejected with PRESSURE_PREVIEW_STALE as defense in depth.
76
+ * `consumedAt` is gateway-stamped only; client-supplied values are stripped. */
77
+ export interface PressureAdmissionReference {
78
+ machine: string;
79
+ pressureGeneration: string;
80
+ consumedAt?: string;
81
+ }
82
+ /** One-dispatch operator override request. Bound to an exact machine and the
83
+ * pressure generation the operator saw; execution recomputes and rejects the
84
+ * override when the generation moved. */
85
+ export interface PressureDispatchOverride {
86
+ machine: string;
87
+ pressureGeneration: string;
88
+ reason: string;
89
+ }
90
+ /** Audit record stamped by the gateway when an override is accepted. */
91
+ export interface PressureOverrideAudit extends PressureDispatchOverride {
92
+ /** Authenticated principal that requested the override ('system' for
93
+ * in-process maintenance callers, which cannot originate from an ingress). */
94
+ principalId: string;
95
+ requestedAt: string;
96
+ /** An override never outlives the single dispatch it was issued for. */
97
+ scope: 'single-dispatch';
98
+ /**
99
+ * Durable consumption record, persisted at the launch gate BEFORE the
100
+ * runner starts (intent before effect). Bound to one exact DISPATCH engine
101
+ * attempt: a same-attempt provider retry sees its own attempt key and stays
102
+ * idempotent; a replay or new attempt rejects with
103
+ * PRESSURE_OVERRIDE_CONSUMED and needs a fresh override.
104
+ */
105
+ consumed?: {
106
+ attemptKey: string;
107
+ consumedAt: string;
108
+ };
109
+ }
110
+ /**
111
+ * What the policy WOULD have rejected with, on a dispatch that was admitted
112
+ * anyway because the gate is switched off. Advisory only: nothing downstream
113
+ * may turn this into a refusal.
114
+ */
115
+ export interface PressureAdmissionAdvisory {
116
+ code: PressureAdmissionRejectionCode;
117
+ /** Operator-facing reason. Backend-owned; clients render it verbatim. */
118
+ reason: string;
119
+ causes: PressureAdmissionCause[];
120
+ }
121
+ export interface PressureAdmissionAdmitted {
122
+ outcome: 'admitted';
123
+ machine: string;
124
+ state: Extract<PressureAdmissionState, 'green' | 'transient' | 'override' | 'disabled'>;
125
+ evidence: PressureAdmissionEvidence;
126
+ /** Present only when state='override': the accepted one-shot override. */
127
+ override?: PressureOverrideAudit;
128
+ /**
129
+ * Present ONLY on state='disabled': the gate is switched off, so this
130
+ * dispatch was admitted without enforcement. Distinguishes "evaluated and
131
+ * green" from "not enforced at all".
132
+ */
133
+ enforced?: false;
134
+ /** Present when an unenforced decision would otherwise have been rejected. */
135
+ advisory?: PressureAdmissionAdvisory;
136
+ }
137
+ export interface PressureAdmissionRejected {
138
+ outcome: 'rejected';
139
+ machine: string;
140
+ state: Extract<PressureAdmissionState, 'sustained-critical' | 'unavailable' | 'stale'>;
141
+ code: PressureAdmissionRejectionCode;
142
+ /** Operator-facing reason. Backend-owned; clients render it verbatim. */
143
+ reason: string;
144
+ causes: PressureAdmissionCause[];
145
+ evidence: PressureAdmissionEvidence;
146
+ /** True when a fresh explicit override against `evidence.generation` can
147
+ * admit one dispatch. False for unavailable/stale evidence — fail closed. */
148
+ overridable: boolean;
149
+ }
150
+ export type PressureAdmissionDecision = PressureAdmissionAdmitted | PressureAdmissionRejected;
151
+ /** Gateway-owned durable switch for pressure-based dispatch prevention.
152
+ * Default DISABLED — sustained-pressure dispatch prevention is opt-in. Enabling
153
+ * turns on pressure rejection/override prompts; sampling, history, and charts
154
+ * run either way. Never affects slot ownership, capability, runner, branch, or
155
+ * other safety checks. */
156
+ export interface PressureAdmissionControlState {
157
+ enabled: boolean;
158
+ /** ISO timestamp of the last change; null when still at the default. */
159
+ updatedAt: string | null;
160
+ /** Authenticated principal that made the last change; null at the default. */
161
+ updatedBy: string | null;
162
+ /**
163
+ * Set when FARMSLOT_DISPATCH_PRESSURE_ADMISSION is exported on the gateway
164
+ * process. The env value WINS over the durable state above, which is still
165
+ * reported verbatim so an operator can see both.
166
+ */
167
+ envOverride?: DispatchPressureAdmissionMode;
168
+ }
169
+ export interface PressureAdmissionSetEnabledParams {
170
+ enabled: boolean;
171
+ }
172
+ export type PressureAdmissionGetResult = PressureAdmissionControlState;
173
+ export type PressureAdmissionSetEnabledResult = PressureAdmissionControlState;
174
+ export declare function isPressureAdmissionRejected(decision: PressureAdmissionDecision | undefined): decision is PressureAdmissionRejected;
175
+ //# sourceMappingURL=pressure-admission.d.ts.map