@pegma/support-desk-application 0.2.4 → 0.2.6

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 (58) hide show
  1. package/README.md +18 -9
  2. package/dist/attachments.d.ts +57 -0
  3. package/dist/attachments.d.ts.map +1 -0
  4. package/dist/attachments.js +91 -0
  5. package/dist/attachments.js.map +1 -0
  6. package/dist/engineering-evidence.d.ts.map +1 -1
  7. package/dist/engineering-evidence.js +45 -8
  8. package/dist/engineering-evidence.js.map +1 -1
  9. package/dist/engineering-mutation-guard.d.ts +9 -0
  10. package/dist/engineering-mutation-guard.d.ts.map +1 -0
  11. package/dist/engineering-mutation-guard.js +71 -0
  12. package/dist/engineering-mutation-guard.js.map +1 -0
  13. package/dist/engineering-policy.d.ts.map +1 -1
  14. package/dist/engineering-policy.js +8 -3
  15. package/dist/engineering-policy.js.map +1 -1
  16. package/dist/engineering-types.d.ts +12 -7
  17. package/dist/engineering-types.d.ts.map +1 -1
  18. package/dist/engineering-work.d.ts.map +1 -1
  19. package/dist/engineering-work.js +10 -3
  20. package/dist/engineering-work.js.map +1 -1
  21. package/dist/index.d.ts +80 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +855 -41
  24. package/dist/index.js.map +1 -1
  25. package/dist/resolution-learning-records.d.ts +2 -0
  26. package/dist/resolution-learning-records.d.ts.map +1 -1
  27. package/dist/resolution-learning-records.js +7 -0
  28. package/dist/resolution-learning-records.js.map +1 -1
  29. package/dist/resolution-learning-review-commit.d.ts +18 -0
  30. package/dist/resolution-learning-review-commit.d.ts.map +1 -0
  31. package/dist/resolution-learning-review-commit.js +199 -0
  32. package/dist/resolution-learning-review-commit.js.map +1 -0
  33. package/dist/resolution-learning-review-identity.d.ts +28 -0
  34. package/dist/resolution-learning-review-identity.d.ts.map +1 -0
  35. package/dist/resolution-learning-review-identity.js +110 -0
  36. package/dist/resolution-learning-review-identity.js.map +1 -0
  37. package/dist/resolution-learning-staged-records.d.ts +45 -0
  38. package/dist/resolution-learning-staged-records.d.ts.map +1 -0
  39. package/dist/resolution-learning-staged-records.js +193 -0
  40. package/dist/resolution-learning-staged-records.js.map +1 -0
  41. package/dist/resolution-learning-staged-types.d.ts +88 -0
  42. package/dist/resolution-learning-staged-types.d.ts.map +1 -0
  43. package/dist/resolution-learning-staged-types.js +2 -0
  44. package/dist/resolution-learning-staged-types.js.map +1 -0
  45. package/dist/resolution-learning-staged.d.ts +12 -0
  46. package/dist/resolution-learning-staged.d.ts.map +1 -0
  47. package/dist/resolution-learning-staged.js +585 -0
  48. package/dist/resolution-learning-staged.js.map +1 -0
  49. package/dist/resolution-learning-types.d.ts +6 -0
  50. package/dist/resolution-learning-types.d.ts.map +1 -1
  51. package/dist/resolution-learning-worker.d.ts.map +1 -1
  52. package/dist/resolution-learning-worker.js +58 -186
  53. package/dist/resolution-learning-worker.js.map +1 -1
  54. package/dist/resolution-learning.d.ts +3 -2
  55. package/dist/resolution-learning.d.ts.map +1 -1
  56. package/dist/resolution-learning.js +29 -2
  57. package/dist/resolution-learning.js.map +1 -1
  58. package/package.json +3 -3
@@ -0,0 +1,585 @@
1
+ import { hasPermission } from "@pegma/authorization-core";
2
+ import { MAX_SCAN_PAGE_SIZE } from "@pegma/storage-core";
3
+ import { SupportDeskAuthorizationError, SupportDeskConflictError, SupportDeskLimitError, SupportDeskNotFoundError, supportPermissions, supportTicketAuditActions, } from "./index.js";
4
+ import { canonical, fields, fingerprint, integer, text, timestamp, } from "./assistant-turn-records.js";
5
+ import { safeLearningSnapshot as snapshot, resolutionLearningWorkKey, resolutionLearningReviewKey, } from "./resolution-learning-records.js";
6
+ import { assertResolutionLearningReviewAttempt, assertResolutionLearningReviewReservation, maximumResolutionLearningReviewAttemptBytes, resolutionLearningReviewAttemptKey, validateStagedReviewFence, validateStagedReviewIntent, validateStagedReviewProof, } from "./resolution-learning-staged-records.js";
7
+ import { resolutionLearningReviewIdentity, requireResolutionLearningReviewTicket, readResolutionLearningReviewSlot, resolutionLearningReviewReceiptValue, resolutionLearningReviewReceiptAction, } from "./resolution-learning-review-identity.js";
8
+ import { commitResolutionLearningReview } from "./resolution-learning-review-commit.js";
9
+ function permission(access, process = false) {
10
+ text(access.principalId, "principalId");
11
+ const names = process
12
+ ? [supportPermissions.learningProcess]
13
+ : [supportPermissions.learningReview, supportPermissions.queueRead];
14
+ for (const name of names)
15
+ if (!hasPermission(access, name))
16
+ throw new SupportDeskAuthorizationError(name);
17
+ }
18
+ function unclaim(row) {
19
+ const { claim: _claim, leaseUntil: _lease, ...rest } = row;
20
+ return rest;
21
+ }
22
+ function check(row) {
23
+ assertResolutionLearningReviewAttempt(row, {
24
+ partition: row.partition,
25
+ id: row.id,
26
+ });
27
+ if (maximumResolutionLearningReviewAttemptBytes(row) > 60_000)
28
+ throw new SupportDeskLimitError("serialized_record", 60_000);
29
+ }
30
+ function guardRequired(guard) {
31
+ if (typeof guard !== "function")
32
+ throw new TypeError("Staged review requires a current-authority proof guard");
33
+ }
34
+ async function checkedGuard(guard) {
35
+ const assertion = await guard();
36
+ return () => {
37
+ if (assertion !== undefined &&
38
+ (typeof assertion !== "function" || assertion() !== true))
39
+ throw new SupportDeskConflictError("Review guard refused commit");
40
+ };
41
+ }
42
+ /** Every mutation performs one conditional transaction; uncertain/conflict callers resume in another invocation. */
43
+ export function createResolutionLearningStagedReviewServices(deps, load) {
44
+ const { records, clock, options } = deps;
45
+ const now = () => timestamp(clock.now(), "now");
46
+ async function at(ticketId, commandId) {
47
+ const value = await records.getVersioned(resolutionLearningReviewAttemptKey(ticketId, commandId));
48
+ if (value === null)
49
+ return null;
50
+ assertResolutionLearningReviewAttempt(value.value, {
51
+ partition: ticketId,
52
+ id: resolutionLearningReviewAttemptKey(ticketId, commandId).id,
53
+ });
54
+ return { value: value.value, version: value.version };
55
+ }
56
+ function owner(access, row) {
57
+ if (access.principalId !== row.reviewerId)
58
+ throw new SupportDeskAuthorizationError(supportPermissions.learningReview);
59
+ }
60
+ function exact(identity, row) {
61
+ if (identity.hash !== row.fingerprint)
62
+ throw new SupportDeskConflictError("Review command reused");
63
+ }
64
+ function held(row) {
65
+ return (row.state !== "pending" ||
66
+ timestamp(row.expiresAt, "expiresAt") <= now() ||
67
+ (row.phase === "commit" &&
68
+ (row.proof === undefined ||
69
+ timestamp(row.proof.validUntil, "proof.validUntil") <= now())));
70
+ }
71
+ function pending(row) {
72
+ return snapshot({
73
+ outcome: "pending",
74
+ ticketId: row.ticketId,
75
+ commandId: row.command.commandId,
76
+ phase: row.phase,
77
+ claimed: row.claim !== undefined &&
78
+ timestamp(row.leaseUntil, "leaseUntil") > now(),
79
+ held: held(row),
80
+ expiresAt: row.expiresAt,
81
+ });
82
+ }
83
+ function hint(row) {
84
+ return snapshot({
85
+ ticketId: row.ticketId,
86
+ commandId: row.command.commandId,
87
+ reviewerId: row.reviewerId,
88
+ phase: row.phase,
89
+ expiresAt: row.expiresAt,
90
+ ...(row.leaseUntil === undefined ? {} : { leaseUntil: row.leaseUntil }),
91
+ held: held(row),
92
+ });
93
+ }
94
+ function live(row, fence, phase) {
95
+ validateStagedReviewFence(fence);
96
+ if (row.state !== "pending" ||
97
+ row.phase !== phase ||
98
+ row.claim === undefined ||
99
+ row.leaseUntil === undefined ||
100
+ canonical(row.claim) !== canonical(fence) ||
101
+ timestamp(row.leaseUntil, "leaseUntil") <= now() ||
102
+ timestamp(row.expiresAt, "expiresAt") <= now() ||
103
+ (phase === "commit" &&
104
+ (row.proof === undefined ||
105
+ timestamp(row.proof.validUntil, "proof.validUntil") <= now())))
106
+ throw new SupportDeskConflictError("Review claim or proof expired/changed");
107
+ }
108
+ async function retainedIdentity(row) {
109
+ const identity = await resolutionLearningReviewIdentity(row.command, row.reviewerId);
110
+ if (row.state === "pending" && identity.hash !== row.fingerprint)
111
+ throw new SupportDeskConflictError("Review attempt fingerprint differs");
112
+ // Privacy withdrawal may scrub reason text. Recovery uses its original
113
+ // retained fingerprint, never a new mutation reconstructed from redacted data.
114
+ return {
115
+ ...identity,
116
+ hash: row.fingerprint,
117
+ cancellationHash: await fingerprint({
118
+ operation: "cancel_resolution_learning_review",
119
+ reviewFingerprint: row.fingerprint,
120
+ }),
121
+ };
122
+ }
123
+ async function reviewSlot(identity) {
124
+ await requireResolutionLearningReviewTicket(records, identity);
125
+ return readResolutionLearningReviewSlot(records, identity);
126
+ }
127
+ async function currentWork(loaded, row) {
128
+ const work = await records.getVersioned(resolutionLearningWorkKey(row.ticketId, row.command.sourceGeneration));
129
+ if (work?.value.kind !== "resolution_learning_work" ||
130
+ loaded.source.value.state !== "eligible" ||
131
+ !["resolved", "closed"].includes(loaded.ticket.value.ticket.status) ||
132
+ loaded.ticket.value.ticket.resolvedAt !==
133
+ loaded.source.value.resolvedAt ||
134
+ loaded.source.value.sourceGeneration !== row.command.sourceGeneration ||
135
+ loaded.source.value.resolutionCycle !== work.value.resolutionCycle ||
136
+ loaded.source.value.sourceBindingHash !== work.value.sourceBindingHash ||
137
+ work.value.workGeneration !== row.command.expectedWorkGeneration ||
138
+ !loaded.source.value.destinations.some((entry) => entry.articleId === row.command.target.articleId))
139
+ throw new SupportDeskConflictError("Review source/work/target changed");
140
+ return work;
141
+ }
142
+ return {
143
+ async admit(access, input, rawIntent, guard) {
144
+ permission(access);
145
+ guardRequired(guard);
146
+ const identity = await resolutionLearningReviewIdentity(input, access.principalId);
147
+ const intent = snapshot(rawIntent);
148
+ validateStagedReviewIntent(intent);
149
+ if (intent.reviewerId !== access.principalId ||
150
+ intent.ticketId !== identity.command.ticketId ||
151
+ intent.sourceGeneration !== identity.command.sourceGeneration ||
152
+ intent.expectedWorkGeneration !==
153
+ identity.command.expectedWorkGeneration ||
154
+ intent.policy.version !== identity.command.policyVersion ||
155
+ canonical(intent.target) !== canonical(identity.command.target) ||
156
+ identity.command.intentBinding !== (await fingerprint(intent)))
157
+ throw new SupportDeskConflictError("Review intent differs from command");
158
+ const slot = await reviewSlot(identity);
159
+ const prior = slot.receipt;
160
+ if (prior !== null)
161
+ return prior;
162
+ const previous = await at(identity.command.ticketId, identity.command.commandId);
163
+ if (previous !== null) {
164
+ owner(access, previous.value);
165
+ exact(identity, previous.value);
166
+ if (slot.reservation === null)
167
+ throw new SupportDeskConflictError("Review canonical receipt/reservation is unavailable");
168
+ return pending(previous.value);
169
+ }
170
+ if (slot.reservation !== null)
171
+ throw new SupportDeskConflictError("Review reservation has no retained attempt");
172
+ const row = {
173
+ kind: "resolution_learning_review_attempt",
174
+ partition: identity.command.ticketId,
175
+ id: resolutionLearningReviewAttemptKey(identity.command.ticketId, identity.command.commandId).id,
176
+ ticketId: identity.command.ticketId,
177
+ reviewerId: access.principalId,
178
+ command: identity.command,
179
+ intent,
180
+ fingerprint: identity.hash,
181
+ state: "pending",
182
+ phase: "proof",
183
+ claimGeneration: 0,
184
+ completionRows: 2,
185
+ createdAt: clock.now(),
186
+ expiresAt: intent.policy.validUntil,
187
+ };
188
+ check(row);
189
+ const loaded = await load(row.ticketId);
190
+ if (loaded.rows.filter((value) => value.kind === "resolution_learning_review_attempt").length >= options.maxStagedReviewAttempts)
191
+ throw new SupportDeskLimitError("staged_review_attempts", options.maxStagedReviewAttempts);
192
+ const work = await currentWork(loaded, row);
193
+ const bindingKey = await resolutionLearningReviewKey(loaded.source.value, identity.command.target, identity.command.policyVersion);
194
+ const existingBinding = await records.get(bindingKey);
195
+ if (existingBinding !== null &&
196
+ existingBinding.kind !== "resolution_learning_review")
197
+ throw new SupportDeskConflictError("Review binding key collision");
198
+ if (existingBinding === null &&
199
+ loaded.source.value.reviewBindingCount >= options.maxReviewBindings)
200
+ throw new SupportDeskLimitError("ticket_partition", deps.limits.maxRecordsPerTicket);
201
+ const reservation = {
202
+ kind: "resolution_learning_review_reservation",
203
+ partition: row.ticketId,
204
+ id: identity.key.id,
205
+ ticketId: row.ticketId,
206
+ commandId: row.command.commandId,
207
+ reviewerId: row.reviewerId,
208
+ fingerprint: row.fingerprint,
209
+ expiresAt: row.expiresAt,
210
+ };
211
+ assertResolutionLearningReviewReservation(reservation, identity.key);
212
+ // Attempt, admission Audit and canonical reservation plus two future rows.
213
+ deps.admission(loaded.ticket.value.ticket, loaded.rows, 5);
214
+ const assert = await checkedGuard(guard);
215
+ if (timestamp(intent.policy.verifiedAt, "verifiedAt") > now() ||
216
+ timestamp(row.expiresAt, "expiresAt") <= now())
217
+ throw new SupportDeskConflictError("Review intent expired");
218
+ assert();
219
+ if (!(await records.transact(row.ticketId, [
220
+ {
221
+ action: "putIfUnchanged",
222
+ version: loaded.ticket.version,
223
+ value: loaded.ticket.value,
224
+ },
225
+ {
226
+ action: "putIfUnchanged",
227
+ version: loaded.source.version,
228
+ value: loaded.source.value,
229
+ },
230
+ {
231
+ action: "putIfUnchanged",
232
+ version: work.version,
233
+ value: work.value,
234
+ },
235
+ { action: "insert", value: row },
236
+ { action: "insert", value: reservation },
237
+ deps.audit(identity.command, loaded.ticket.value.ticket, access.principalId, row.createdAt, supportTicketAuditActions.learningReviewRequested, "\u0000support.learning.review.requested:" +
238
+ identity.command.commandId),
239
+ ])).committed)
240
+ throw new SupportDeskConflictError();
241
+ return pending(row);
242
+ },
243
+ async readStatus(access, input) {
244
+ permission(access);
245
+ const identity = await resolutionLearningReviewIdentity(input, access.principalId);
246
+ const slot = await reviewSlot(identity);
247
+ const prior = slot.receipt;
248
+ if (prior !== null)
249
+ return prior;
250
+ const stored = await at(identity.command.ticketId, identity.command.commandId);
251
+ if (stored === null) {
252
+ if (slot.reservation !== null)
253
+ throw new SupportDeskConflictError("Review reservation has no retained attempt");
254
+ return null;
255
+ }
256
+ owner(access, stored.value);
257
+ exact(identity, stored.value);
258
+ if (stored.value.state === "accepted" ||
259
+ stored.value.state === "cancelled")
260
+ throw new SupportDeskConflictError("Terminal review receipt is unavailable");
261
+ if (slot.reservation === null)
262
+ throw new SupportDeskConflictError("Review canonical receipt/reservation is unavailable");
263
+ return pending(stored.value);
264
+ },
265
+ async readPending(access, key) {
266
+ permission(access, true);
267
+ const value = fields(key, "review key", ["ticketId", "commandId"]);
268
+ const ticketId = value.ticketId;
269
+ const commandId = value.commandId;
270
+ resolutionLearningReviewAttemptKey(ticketId, commandId);
271
+ // Both exact keys are derived from the validated request, never decoded data.
272
+ // Observe every result; the same Store may coalesce these independent reads.
273
+ const [attemptRead, slotRead] = await Promise.allSettled([
274
+ at(ticketId, commandId),
275
+ records.getVersioned({
276
+ partition: ticketId,
277
+ id: `learning-command:${commandId}`,
278
+ }),
279
+ ]);
280
+ if (attemptRead.status === "rejected")
281
+ throw attemptRead.reason;
282
+ if (slotRead.status === "rejected")
283
+ throw slotRead.reason;
284
+ const stored = attemptRead.value;
285
+ const canonical = slotRead.value;
286
+ if (stored === null) {
287
+ if (canonical?.value.kind !== "resolution_learning_review_reservation")
288
+ return null;
289
+ const reservation = canonical.value;
290
+ assertResolutionLearningReviewReservation(reservation, {
291
+ partition: ticketId,
292
+ id: `learning-command:${commandId}`,
293
+ });
294
+ return snapshot({
295
+ ticketId,
296
+ commandId,
297
+ reviewerId: reservation.reviewerId,
298
+ phase: "proof",
299
+ expiresAt: reservation.expiresAt,
300
+ held: true,
301
+ });
302
+ }
303
+ const identity = await retainedIdentity(stored.value);
304
+ const receipt = resolutionLearningReviewReceiptValue(identity, canonical?.value ?? null);
305
+ if (receipt !== null)
306
+ return null;
307
+ const metadata = hint(stored.value);
308
+ // A retained terminal attempt without its canonical receipt is unknown,
309
+ // never authoritative absence and never permission to relabel acceptance.
310
+ return canonical === null
311
+ ? snapshot({ ...metadata, held: true })
312
+ : metadata;
313
+ },
314
+ async scanPending(access, input) {
315
+ permission(access, true);
316
+ const bounds = fields(input, "review scan", ["limit"], ["cursor"]);
317
+ integer(bounds.limit, "limit", 1, MAX_SCAN_PAGE_SIZE);
318
+ if (bounds.cursor !== undefined)
319
+ text(bounds.cursor, "cursor", 20_000);
320
+ const page = await records.scan({
321
+ limit: bounds.limit,
322
+ ...(bounds.cursor === undefined
323
+ ? {}
324
+ : { cursor: bounds.cursor }),
325
+ });
326
+ const candidates = [];
327
+ for (const entry of page.records) {
328
+ if (entry.value.kind !== "resolution_learning_review_attempt")
329
+ continue;
330
+ assertResolutionLearningReviewAttempt(entry.value, entry.key);
331
+ if (entry.value.state !== "pending")
332
+ continue;
333
+ const value = hint(entry.value);
334
+ if (value !== null &&
335
+ !value.held &&
336
+ (value.leaseUntil === undefined ||
337
+ timestamp(value.leaseUntil, "leaseUntil") <= now()))
338
+ candidates.push(value);
339
+ }
340
+ return {
341
+ candidates,
342
+ nextCursor: page.nextCursor,
343
+ physicalRows: page.records.length,
344
+ pages: 1,
345
+ };
346
+ },
347
+ async claim(access, input) {
348
+ permission(access);
349
+ const command = snapshot(fields(input, "claim review", [
350
+ "ticketId",
351
+ "commandId",
352
+ "workerId",
353
+ "claimId",
354
+ "leaseMilliseconds",
355
+ ]));
356
+ for (const name of ["ticketId", "commandId", "workerId", "claimId"])
357
+ text(command[name], name);
358
+ const duration = integer(command.leaseMilliseconds, "leaseMilliseconds", 1, options.maxLeaseMilliseconds);
359
+ const stored = await at(command.ticketId, command.commandId);
360
+ if (stored === null)
361
+ return null;
362
+ const row = stored.value;
363
+ owner(access, row);
364
+ const identity = await retainedIdentity(row);
365
+ const slot = await reviewSlot(identity);
366
+ if (slot.receipt !== null)
367
+ return null;
368
+ if (slot.reservation === null)
369
+ throw new SupportDeskConflictError("Review canonical receipt/reservation is unavailable");
370
+ if (row.state !== "pending" ||
371
+ timestamp(row.expiresAt, "expiresAt") <= now() ||
372
+ (row.phase === "commit" &&
373
+ (row.proof === undefined ||
374
+ timestamp(row.proof.validUntil, "proof.validUntil") <= now())))
375
+ return null;
376
+ const result = (value) => snapshot({
377
+ fence: value.claim,
378
+ reviewerId: value.reviewerId,
379
+ command: value.command,
380
+ intent: value.intent,
381
+ phase: value.phase,
382
+ leaseUntil: value.leaseUntil,
383
+ expiresAt: value.expiresAt,
384
+ ...(value.proof === undefined ? {} : { proof: value.proof }),
385
+ });
386
+ if (row.claim !== undefined &&
387
+ timestamp(row.leaseUntil, "leaseUntil") > now())
388
+ return row.claim.workerId === command.workerId &&
389
+ row.claim.claimId === command.claimId
390
+ ? result(row)
391
+ : null;
392
+ const fence = {
393
+ ticketId: row.ticketId,
394
+ commandId: row.command.commandId,
395
+ workerId: command.workerId,
396
+ claimId: command.claimId,
397
+ claimGeneration: integer(row.claimGeneration + 1, "claimGeneration", 1),
398
+ };
399
+ const next = {
400
+ ...row,
401
+ claimGeneration: fence.claimGeneration,
402
+ claim: fence,
403
+ leaseUntil: new Date(Math.min(now() + duration, timestamp(row.expiresAt, "expiresAt"), row.proof === undefined
404
+ ? Infinity
405
+ : timestamp(row.proof.validUntil, "proof.validUntil"))).toISOString(),
406
+ };
407
+ check(next);
408
+ if (!(await records.transact(row.ticketId, [
409
+ { action: "putIfUnchanged", version: stored.version, value: next },
410
+ {
411
+ action: "putIfUnchanged",
412
+ version: slot.reservation.version,
413
+ value: slot.reservation.value,
414
+ },
415
+ ])).committed)
416
+ throw new SupportDeskConflictError();
417
+ return result(next);
418
+ },
419
+ async prepare(access, input, guard) {
420
+ permission(access);
421
+ guardRequired(guard);
422
+ const command = snapshot(fields(input, "prepare review", ["fence", "proof"]));
423
+ validateStagedReviewFence(command.fence);
424
+ validateStagedReviewProof(command.proof);
425
+ const fence = command.fence;
426
+ const proof = command.proof;
427
+ const stored = await at(fence.ticketId, fence.commandId);
428
+ if (stored === null)
429
+ throw new SupportDeskNotFoundError();
430
+ const row = stored.value;
431
+ owner(access, row);
432
+ const identity = await retainedIdentity(row);
433
+ const slot = await reviewSlot(identity);
434
+ const prior = slot.receipt;
435
+ if (prior !== null)
436
+ return prior;
437
+ if (slot.reservation === null)
438
+ throw new SupportDeskConflictError("Review canonical receipt/reservation is unavailable");
439
+ live(row, fence, "proof");
440
+ if (timestamp(proof.validUntil, "proof.validUntil") >
441
+ timestamp(row.expiresAt, "expiresAt"))
442
+ throw new SupportDeskConflictError("P1 proof exceeds original intent");
443
+ const loaded = await load(row.ticketId);
444
+ const work = await currentWork(loaded, row);
445
+ const next = {
446
+ ...unclaim(row),
447
+ phase: "commit",
448
+ proof,
449
+ };
450
+ check(next);
451
+ const assert = await checkedGuard(guard);
452
+ live(row, fence, "proof");
453
+ if (timestamp(proof.validUntil, "proof.validUntil") <= now())
454
+ throw new SupportDeskConflictError("P1 proof expired");
455
+ assert();
456
+ if (!(await records.transact(row.ticketId, [
457
+ {
458
+ action: "putIfUnchanged",
459
+ version: loaded.ticket.version,
460
+ value: loaded.ticket.value,
461
+ },
462
+ {
463
+ action: "putIfUnchanged",
464
+ version: loaded.source.version,
465
+ value: loaded.source.value,
466
+ },
467
+ {
468
+ action: "putIfUnchanged",
469
+ version: work.version,
470
+ value: work.value,
471
+ },
472
+ { action: "putIfUnchanged", version: stored.version, value: next },
473
+ {
474
+ action: "putIfUnchanged",
475
+ version: slot.reservation.version,
476
+ value: slot.reservation.value,
477
+ },
478
+ ])).committed)
479
+ throw new SupportDeskConflictError();
480
+ return pending(next);
481
+ },
482
+ async complete(access, rawFence, guard) {
483
+ permission(access);
484
+ guardRequired(guard);
485
+ const fence = snapshot(rawFence);
486
+ validateStagedReviewFence(fence);
487
+ const stored = await at(fence.ticketId, fence.commandId);
488
+ if (stored === null)
489
+ throw new SupportDeskNotFoundError();
490
+ const row = stored.value;
491
+ owner(access, row);
492
+ const identity = await retainedIdentity(row);
493
+ const slot = await reviewSlot(identity);
494
+ const prior = slot.receipt;
495
+ if (prior !== null)
496
+ return prior;
497
+ if (slot.reservation === null)
498
+ throw new SupportDeskConflictError("Review canonical receipt/reservation is unavailable");
499
+ const next = {
500
+ ...unclaim(row),
501
+ state: "accepted",
502
+ completionRows: 0,
503
+ };
504
+ check(next);
505
+ const result = await commitResolutionLearningReview(deps, load, access, row.command, guard, {
506
+ version: stored.version,
507
+ value: next,
508
+ ensure: () => live(row, fence, "commit"),
509
+ });
510
+ return { outcome: "accepted", result };
511
+ },
512
+ async cancel(access, input, guard) {
513
+ permission(access);
514
+ guardRequired(guard);
515
+ const identity = await resolutionLearningReviewIdentity(input, access.principalId);
516
+ const slot = await reviewSlot(identity);
517
+ const prior = slot.receipt;
518
+ if (prior !== null) {
519
+ (await checkedGuard(guard))();
520
+ return prior;
521
+ }
522
+ const stored = await at(identity.command.ticketId, identity.command.commandId);
523
+ if (stored !== null) {
524
+ owner(access, stored.value);
525
+ exact(identity, stored.value);
526
+ if (stored.value.state === "accepted" ||
527
+ stored.value.state === "cancelled" ||
528
+ slot.reservation === null)
529
+ throw new SupportDeskConflictError("Terminal review receipt is unavailable");
530
+ }
531
+ else if (slot.reservation !== null)
532
+ throw new SupportDeskConflictError("Review reservation has no retained attempt");
533
+ const loaded = await load(identity.command.ticketId);
534
+ const next = stored === null
535
+ ? undefined
536
+ : { ...unclaim(stored.value), state: "cancelled", completionRows: 0 };
537
+ if (next !== undefined)
538
+ check(next);
539
+ deps.admission(loaded.ticket.value.ticket, next === undefined
540
+ ? loaded.rows
541
+ : loaded.rows.map((row) => (row.id === next.id ? next : row)), slot.reservation === null ? 2 : 1);
542
+ const result = {
543
+ ticketId: loaded.source.value.ticketId,
544
+ sourceGeneration: loaded.source.value.sourceGeneration,
545
+ resolutionCycle: loaded.source.value.resolutionCycle,
546
+ state: loaded.source.value.state,
547
+ };
548
+ const audit = deps.audit(identity.command, loaded.ticket.value.ticket, access.principalId, clock.now(), "support.learning.review_cancelled");
549
+ const assert = await checkedGuard(guard);
550
+ assert();
551
+ if (!(await records.transact(identity.command.ticketId, [
552
+ {
553
+ action: "putIfUnchanged",
554
+ version: loaded.ticket.version,
555
+ value: loaded.ticket.value,
556
+ },
557
+ ...(stored === null || next === undefined
558
+ ? []
559
+ : [
560
+ {
561
+ action: "putIfUnchanged",
562
+ version: stored.version,
563
+ value: next,
564
+ },
565
+ ]),
566
+ audit,
567
+ resolutionLearningReviewReceiptAction(slot, {
568
+ kind: "resolution_learning_receipt",
569
+ partition: identity.command.ticketId,
570
+ id: identity.key.id,
571
+ fingerprint: identity.cancellationHash,
572
+ result,
573
+ }),
574
+ ])).committed)
575
+ throw new SupportDeskConflictError();
576
+ (await checkedGuard(guard))();
577
+ return {
578
+ outcome: "cancelled",
579
+ ticketId: identity.command.ticketId,
580
+ commandId: identity.command.commandId,
581
+ };
582
+ },
583
+ };
584
+ }
585
+ //# sourceMappingURL=resolution-learning-staged.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution-learning-staged.js","sourceRoot":"","sources":["../src/resolution-learning-staged.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAsB,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAwB,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,GAE1B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,SAAS,EACT,MAAM,EACN,WAAW,EACX,OAAO,EACP,IAAI,EACJ,SAAS,GACV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,IAAI,QAAQ,EAChC,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,qCAAqC,EACrC,yCAAyC,EAEzC,2CAA2C,EAC3C,kCAAkC,EAClC,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,GAE1B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,gCAAgC,EAChC,qCAAqC,EACrC,gCAAgC,EAChC,oCAAoC,EACpC,qCAAqC,GAEtC,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAoBxF,SAAS,UAAU,CAAC,MAAqB,EAAE,OAAO,GAAG,KAAK;IACxD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO;QACnB,CAAC,CAAC,CAAC,kBAAkB,CAAC,eAAe,CAAC;QACtC,CAAC,CAAC,CAAC,kBAAkB,CAAC,cAAc,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACtE,KAAK,MAAM,IAAI,IAAI,KAAK;QACtB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC;YAC9B,MAAM,IAAI,6BAA6B,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AACD,SAAS,OAAO,CACd,GAA0C;IAE1C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AACD,SAAS,KAAK,CAAC,GAA0C;IACvD,qCAAqC,CAAC,GAAG,EAAE;QACzC,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,EAAE,EAAE,GAAG,CAAC,EAAE;KACX,CAAC,CAAC;IACH,IAAI,2CAA2C,CAAC,GAAG,CAAC,GAAG,MAAM;QAC3D,MAAM,IAAI,qBAAqB,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC;AACD,SAAS,aAAa,CAAC,KAA0C;IAC/D,IAAI,OAAO,KAAK,KAAK,UAAU;QAC7B,MAAM,IAAI,SAAS,CACjB,wDAAwD,CACzD,CAAC;AACN,CAAC;AACD,KAAK,UAAU,YAAY,CACzB,KAA0C;IAE1C,MAAM,SAAS,GAAG,MAAM,KAAK,EAAE,CAAC;IAChC,OAAO,GAAG,EAAE;QACV,IACE,SAAS,KAAK,SAAS;YACvB,CAAC,OAAO,SAAS,KAAK,UAAU,IAAI,SAAS,EAAE,KAAK,IAAI,CAAC;YAEzD,MAAM,IAAI,wBAAwB,CAAC,6BAA6B,CAAC,CAAC;IACtE,CAAC,CAAC;AACJ,CAAC;AACD,oHAAoH;AACpH,MAAM,UAAU,4CAA4C,CAC1D,IAAoC,EACpC,IAA2C;IAE3C,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzC,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IAChD,KAAK,UAAU,EAAE,CACf,QAAgB,EAChB,SAAiB;QAEjB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,YAAY,CACtC,kCAAkC,CAAC,QAAQ,EAAE,SAAS,CAAC,CACxD,CAAC;QACF,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAChC,qCAAqC,CAAC,KAAK,CAAC,KAAK,EAAE;YACjD,SAAS,EAAE,QAAQ;YACnB,EAAE,EAAE,kCAAkC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE;SAC/D,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACxD,CAAC;IACD,SAAS,KAAK,CACZ,MAAqB,EACrB,GAA0C;QAE1C,IAAI,MAAM,CAAC,WAAW,KAAK,GAAG,CAAC,UAAU;YACvC,MAAM,IAAI,6BAA6B,CACrC,kBAAkB,CAAC,cAAc,CAClC,CAAC;IACN,CAAC;IACD,SAAS,KAAK,CACZ,QAA0C,EAC1C,GAA0C;QAE1C,IAAI,QAAQ,CAAC,IAAI,KAAK,GAAG,CAAC,WAAW;YACnC,MAAM,IAAI,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;IAChE,CAAC;IACD,SAAS,IAAI,CAAC,GAA0C;QACtD,OAAO,CACL,GAAG,CAAC,KAAK,KAAK,SAAS;YACvB,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,GAAG,EAAE;YAC9C,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ;gBACrB,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS;oBACtB,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,kBAAkB,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CACnE,CAAC;IACJ,CAAC;IACD,SAAS,OAAO,CACd,GAA0C;QAE1C,OAAO,QAAQ,CAAC;YACd,OAAO,EAAE,SAAkB;YAC3B,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;YAChC,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,OAAO,EACL,GAAG,CAAC,KAAK,KAAK,SAAS;gBACvB,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,GAAG,EAAE;YACjD,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;YACf,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;IACL,CAAC;IACD,SAAS,IAAI,CACX,GAA0C;QAE1C,OAAO,QAAQ,CAAC;YACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;YAChC,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,GAAG,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;YACvE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;SAChB,CAAC,CAAC;IACL,CAAC;IACD,SAAS,IAAI,CACX,GAA0C,EAC1C,KAA0C,EAC1C,KAAyB;QAEzB,yBAAyB,CAAC,KAAK,CAAC,CAAC;QACjC,IACE,GAAG,CAAC,KAAK,KAAK,SAAS;YACvB,GAAG,CAAC,KAAK,KAAK,KAAK;YACnB,GAAG,CAAC,KAAK,KAAK,SAAS;YACvB,GAAG,CAAC,UAAU,KAAK,SAAS;YAC5B,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC;YACzC,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,GAAG,EAAE;YAChD,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,GAAG,EAAE;YAC9C,CAAC,KAAK,KAAK,QAAQ;gBACjB,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS;oBACtB,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,kBAAkB,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;YAElE,MAAM,IAAI,wBAAwB,CAChC,uCAAuC,CACxC,CAAC;IACN,CAAC;IACD,KAAK,UAAU,gBAAgB,CAC7B,GAA0C;QAE1C,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CACrD,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,UAAU,CACf,CAAC;QACF,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,GAAG,CAAC,WAAW;YAC9D,MAAM,IAAI,wBAAwB,CAAC,oCAAoC,CAAC,CAAC;QAC3E,uEAAuE;QACvE,+EAA+E;QAC/E,OAAO;YACL,GAAG,QAAQ;YACX,IAAI,EAAE,GAAG,CAAC,WAAW;YACrB,gBAAgB,EAAE,MAAM,WAAW,CAAC;gBAClC,SAAS,EAAE,mCAAmC;gBAC9C,iBAAiB,EAAE,GAAG,CAAC,WAAW;aACnC,CAAC;SACH,CAAC;IACJ,CAAC;IACD,KAAK,UAAU,UAAU,CAAC,QAA0C;QAClE,MAAM,qCAAqC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC/D,OAAO,gCAAgC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;IACD,KAAK,UAAU,WAAW,CACxB,MAAc,EACd,GAA0C;QAE1C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,YAAY,CACrC,yBAAyB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CACtE,CAAC;QACF,IACE,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,0BAA0B;YAC/C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU;YACxC,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;YACnE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU;gBACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU;YAChC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,GAAG,CAAC,OAAO,CAAC,gBAAgB;YACrE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,KAAK,IAAI,CAAC,KAAK,CAAC,eAAe;YAClE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC,KAAK,CAAC,iBAAiB;YACtE,IAAI,CAAC,KAAK,CAAC,cAAc,KAAK,GAAG,CAAC,OAAO,CAAC,sBAAsB;YAChE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CACpC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAC5D;YAED,MAAM,IAAI,wBAAwB,CAAC,mCAAmC,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;YACzC,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CACrD,KAAK,EACL,MAAM,CAAC,WAAW,CACnB,CAAC;YACF,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;YACnC,0BAA0B,CAAC,MAAM,CAAC,CAAC;YACnC,IACE,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,WAAW;gBACxC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,OAAO,CAAC,QAAQ;gBAC7C,MAAM,CAAC,gBAAgB,KAAK,QAAQ,CAAC,OAAO,CAAC,gBAAgB;gBAC7D,MAAM,CAAC,sBAAsB;oBAC3B,QAAQ,CAAC,OAAO,CAAC,sBAAsB;gBACzC,MAAM,CAAC,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,OAAO,CAAC,aAAa;gBACxD,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC/D,QAAQ,CAAC,OAAO,CAAC,aAAa,KAAK,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;gBAE9D,MAAM,IAAI,wBAAwB,CAChC,oCAAoC,CACrC,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;YAC3B,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,MAAM,QAAQ,GAAG,MAAM,EAAE,CACvB,QAAQ,CAAC,OAAO,CAAC,QAAQ,EACzB,QAAQ,CAAC,OAAO,CAAC,SAAS,CAC3B,CAAC;YACF,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACtB,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC9B,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;oBAC3B,MAAM,IAAI,wBAAwB,CAChC,qDAAqD,CACtD,CAAC;gBACJ,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAC3B,MAAM,IAAI,wBAAwB,CAChC,4CAA4C,CAC7C,CAAC;YACJ,MAAM,GAAG,GAA0C;gBACjD,IAAI,EAAE,oCAAoC;gBAC1C,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ;gBACpC,EAAE,EAAE,kCAAkC,CACpC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EACzB,QAAQ,CAAC,OAAO,CAAC,SAAS,CAC3B,CAAC,EAAE;gBACJ,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ;gBACnC,UAAU,EAAE,MAAM,CAAC,WAAW;gBAC9B,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,MAAM;gBACN,WAAW,EAAE,QAAQ,CAAC,IAAI;gBAC1B,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,OAAO;gBACd,eAAe,EAAE,CAAC;gBAClB,cAAc,EAAE,CAAC;gBACjB,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE;gBACtB,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;aACpC,CAAC;YACF,KAAK,CAAC,GAAG,CAAC,CAAC;YACX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxC,IACE,MAAM,CAAC,IAAI,CAAC,MAAM,CAChB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,oCAAoC,CAC/D,CAAC,MAAM,IAAI,OAAO,CAAC,uBAAuB;gBAE3C,MAAM,IAAI,qBAAqB,CAC7B,wBAAwB,EACxB,OAAO,CAAC,uBAAuB,CAChC,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC5C,MAAM,UAAU,GAAG,MAAM,2BAA2B,CAClD,MAAM,CAAC,MAAM,CAAC,KAAK,EACnB,QAAQ,CAAC,OAAO,CAAC,MAAM,EACvB,QAAQ,CAAC,OAAO,CAAC,aAAa,CAC/B,CAAC;YACF,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACtD,IACE,eAAe,KAAK,IAAI;gBACxB,eAAe,CAAC,IAAI,KAAK,4BAA4B;gBAErD,MAAM,IAAI,wBAAwB,CAAC,8BAA8B,CAAC,CAAC;YACrE,IACE,eAAe,KAAK,IAAI;gBACxB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,IAAI,OAAO,CAAC,iBAAiB;gBAEnE,MAAM,IAAI,qBAAqB,CAC7B,kBAAkB,EAClB,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAChC,CAAC;YACJ,MAAM,WAAW,GAA8C;gBAC7D,IAAI,EAAE,wCAAwC;gBAC9C,SAAS,EAAE,GAAG,CAAC,QAAQ;gBACvB,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;gBACnB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;gBAChC,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,SAAS,EAAE,GAAG,CAAC,SAAS;aACzB,CAAC;YACF,yCAAyC,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrE,2EAA2E;YAC3E,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;YACzC,IACE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,GAAG,EAAE;gBACzD,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,GAAG,EAAE;gBAE9C,MAAM,IAAI,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;YAC9D,MAAM,EAAE,CAAC;YACT,IACE,CAAC,CACC,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACnC;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;oBAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;iBAC3B;gBACD;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;oBAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;iBAC3B;gBACD;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB;gBACD,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;gBAChC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE;gBACxC,IAAI,CAAC,KAAK,CACR,QAAQ,CAAC,OAAO,EAChB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAC1B,MAAM,CAAC,WAAW,EAClB,GAAG,CAAC,SAAS,EACb,yBAAyB,CAAC,uBAAuB,EACjD,0CAA0C;oBACxC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAC7B;aACF,CAAC,CACH,CAAC,SAAS;gBAEX,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACvC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK;YAC5B,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CACrD,KAAK,EACL,MAAM,CAAC,WAAW,CACnB,CAAC;YACF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;YAC3B,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,EAAE,CACrB,QAAQ,CAAC,OAAO,CAAC,QAAQ,EACzB,QAAQ,CAAC,OAAO,CAAC,SAAS,CAC3B,CAAC;YACF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;oBAC3B,MAAM,IAAI,wBAAwB,CAChC,4CAA4C,CAC7C,CAAC;gBACJ,OAAO,IAAI,CAAC;YACd,CAAC;YACD,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,IACE,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU;gBACjC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,WAAW;gBAElC,MAAM,IAAI,wBAAwB,CAChC,wCAAwC,CACzC,CAAC;YACJ,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAC3B,MAAM,IAAI,wBAAwB,CAChC,qDAAqD,CACtD,CAAC;YACJ,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG;YAC3B,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACzB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAkB,CAAC;YAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAmB,CAAC;YAC5C,kCAAkC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACxD,8EAA8E;YAC9E,6EAA6E;YAC7E,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;gBACvD,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;gBACvB,OAAO,CAAC,YAAY,CAAC;oBACnB,SAAS,EAAE,QAAQ;oBACnB,EAAE,EAAE,oBAAoB,SAAS,EAAE;iBACpC,CAAC;aACH,CAAC,CAAC;YACH,IAAI,WAAW,CAAC,MAAM,KAAK,UAAU;gBAAE,MAAM,WAAW,CAAC,MAAM,CAAC;YAChE,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU;gBAAE,MAAM,QAAQ,CAAC,MAAM,CAAC;YAC1D,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC;YACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC;YACjC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,IAAI,SAAS,EAAE,KAAK,CAAC,IAAI,KAAK,wCAAwC;oBACpE,OAAO,IAAI,CAAC;gBACd,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC;gBACpC,yCAAyC,CAAC,WAAW,EAAE;oBACrD,SAAS,EAAE,QAAQ;oBACnB,EAAE,EAAE,oBAAoB,SAAS,EAAE;iBACpC,CAAC,CAAC;gBACH,OAAO,QAAQ,CAAC;oBACd,QAAQ;oBACR,SAAS;oBACT,UAAU,EAAE,WAAW,CAAC,UAAU;oBAClC,KAAK,EAAE,OAAgB;oBACvB,SAAS,EAAE,WAAW,CAAC,SAAS;oBAChC,IAAI,EAAE,IAAI;iBACX,CAAC,CAAC;YACL,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,oCAAoC,CAClD,QAAQ,EACR,SAAS,EAAE,KAAK,IAAI,IAAI,CACzB,CAAC;YACF,IAAI,OAAO,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpC,wEAAwE;YACxE,0EAA0E;YAC1E,OAAO,SAAS,KAAK,IAAI;gBACvB,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;gBACvC,CAAC,CAAC,QAAQ,CAAC;QACf,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK;YAC7B,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;YACnE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC;YACtD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAC9B,KAAK,EAAE,MAAM,CAAC,KAAe;gBAC7B,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;oBAC7B,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAgB,EAAE,CAAC;aACzC,CAAC,CAAC;YACH,MAAM,UAAU,GAAyC,EAAE,CAAC;YAC5D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,oCAAoC;oBAAE,SAAS;gBACxE,qCAAqC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC9D,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS;oBAAE,SAAS;gBAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAChC,IACE,KAAK,KAAK,IAAI;oBACd,CAAC,KAAK,CAAC,IAAI;oBACX,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS;wBAC7B,SAAS,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,GAAG,EAAE,CAAC;oBAErD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;YACD,OAAO;gBACL,UAAU;gBACV,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBACjC,KAAK,EAAE,CAAC;aACT,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK;YACvB,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,MAAM,OAAO,GAAG,QAAQ,CACtB,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE;gBAC5B,UAAU;gBACV,WAAW;gBACX,UAAU;gBACV,SAAS;gBACT,mBAAmB;aACpB,CAAC,CACH,CAAC;YACF,KAAK,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC;gBACjE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CACtB,OAAO,CAAC,iBAAiB,EACzB,mBAAmB,EACnB,CAAC,EACD,OAAO,CAAC,oBAAoB,CAC7B,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,EAAE,CACrB,OAAO,CAAC,QAAkB,EAC1B,OAAO,CAAC,SAAmB,CAC5B,CAAC;YACF,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YACjC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YACvC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAC3B,MAAM,IAAI,wBAAwB,CAChC,qDAAqD,CACtD,CAAC;YACJ,IACE,GAAG,CAAC,KAAK,KAAK,SAAS;gBACvB,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,GAAG,EAAE;gBAC9C,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ;oBACrB,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS;wBACtB,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,kBAAkB,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;gBAElE,OAAO,IAAI,CAAC;YACd,MAAM,MAAM,GAAG,CAAC,KAA4C,EAAE,EAAE,CAC9D,QAAQ,CAAC;gBACP,KAAK,EAAE,KAAK,CAAC,KAAM;gBACnB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,UAAU,EAAE,KAAK,CAAC,UAAW;gBAC7B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;aAC7D,CAAC,CAAC;YACL,IACE,GAAG,CAAC,KAAK,KAAK,SAAS;gBACvB,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,GAAG,EAAE;gBAE/C,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ;oBAC5C,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO;oBACrC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;oBACb,CAAC,CAAC,IAAI,CAAC;YACX,MAAM,KAAK,GAAwC;gBACjD,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAkB;gBACpC,OAAO,EAAE,OAAO,CAAC,OAAiB;gBAClC,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC;aACxE,CAAC;YACF,MAAM,IAAI,GAA0C;gBAClD,GAAG,GAAG;gBACN,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,KAAK,EAAE,KAAK;gBACZ,UAAU,EAAE,IAAI,IAAI,CAClB,IAAI,CAAC,GAAG,CACN,GAAG,EAAE,GAAG,QAAQ,EAChB,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,EACrC,GAAG,CAAC,KAAK,KAAK,SAAS;oBACrB,CAAC,CAAC,QAAQ;oBACV,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,kBAAkB,CAAC,CACxD,CACF,CAAC,WAAW,EAAE;aAChB,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,CAAC;YACZ,IACE,CAAC,CACC,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACnC,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE;gBAClE;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO;oBACjC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;iBAC9B;aACF,CAAC,CACH,CAAC,SAAS;gBAEX,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACvC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK;YAChC,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,OAAO,GAAG,QAAQ,CACtB,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CACpD,CAAC;YACF,yBAAyB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACzC,yBAAyB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YACzD,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM,IAAI,wBAAwB,EAAE,CAAC;YAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;YAC3B,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAC3B,MAAM,IAAI,wBAAwB,CAChC,qDAAqD,CACtD,CAAC;YACJ,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAC1B,IACE,SAAS,CAAC,KAAK,CAAC,UAAU,EAAE,kBAAkB,CAAC;gBAC/C,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC;gBAErC,MAAM,IAAI,wBAAwB,CAAC,kCAAkC,CAAC,CAAC;YACzE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC5C,MAAM,IAAI,GAA0C;gBAClD,GAAG,OAAO,CAAC,GAAG,CAAC;gBACf,KAAK,EAAE,QAAQ;gBACf,KAAK;aACN,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,CAAC;YACZ,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAC1B,IAAI,SAAS,CAAC,KAAK,CAAC,UAAU,EAAE,kBAAkB,CAAC,IAAI,GAAG,EAAE;gBAC1D,MAAM,IAAI,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;YACzD,MAAM,EAAE,CAAC;YACT,IACE,CAAC,CACC,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACnC;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;oBAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;iBAC3B;gBACD;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;oBAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;iBAC3B;gBACD;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB;gBACD,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE;gBAClE;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO;oBACjC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;iBAC9B;aACF,CAAC,CACH,CAAC,SAAS;gBAEX,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACvC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK;YACpC,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACjC,yBAAyB,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YACzD,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM,IAAI,wBAAwB,EAAE,CAAC;YAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;YAC3B,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAC3B,MAAM,IAAI,wBAAwB,CAChC,qDAAqD,CACtD,CAAC;YACJ,MAAM,IAAI,GAA0C;gBAClD,GAAG,OAAO,CAAC,GAAG,CAAC;gBACf,KAAK,EAAE,UAAU;gBACjB,cAAc,EAAE,CAAC;aAClB,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,CAAC;YACZ,MAAM,MAAM,GAAG,MAAM,8BAA8B,CACjD,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,GAAG,CAAC,OAAO,EACX,KAAK,EACL;gBACE,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC;aACzC,CACF,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK;YAC/B,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CACrD,KAAK,EACL,MAAM,CAAC,WAAW,CACnB,CAAC;YACF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;YAC3B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC9B,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,EAAE,CACrB,QAAQ,CAAC,OAAO,CAAC,QAAQ,EACzB,QAAQ,CAAC,OAAO,CAAC,SAAS,CAC3B,CAAC;YACF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5B,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC9B,IACE,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU;oBACjC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,WAAW;oBAClC,IAAI,CAAC,WAAW,KAAK,IAAI;oBAEzB,MAAM,IAAI,wBAAwB,CAChC,wCAAwC,CACzC,CAAC;YACN,CAAC;iBAAM,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAClC,MAAM,IAAI,wBAAwB,CAChC,4CAA4C,CAC7C,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrD,MAAM,IAAI,GACR,MAAM,KAAK,IAAI;gBACb,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;YAC1E,IAAI,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,SAAS,CACZ,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAC1B,IAAI,KAAK,SAAS;gBAChB,CAAC,CAAC,MAAM,CAAC,IAAI;gBACb,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAC/D,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAClC,CAAC;YACF,MAAM,MAAM,GAAG;gBACb,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ;gBACtC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB;gBACtD,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe;gBACpD,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK;aACjC,CAAC;YACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACtB,QAAQ,CAAC,OAAO,EAChB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAC1B,MAAM,CAAC,WAAW,EAClB,KAAK,CAAC,GAAG,EAAE,EACX,mCAAmC,CACpC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,EAAE,CAAC;YACT,IACE,CAAC,CACC,MAAM,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAChD;oBACE,MAAM,EAAE,gBAAgB;oBACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;oBAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;iBAC3B;gBACD,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;oBACvC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC;wBACE;4BACE,MAAM,EAAE,gBAAyB;4BACjC,OAAO,EAAE,MAAM,CAAC,OAAO;4BACvB,KAAK,EAAE,IAAI;yBACZ;qBACF,CAAC;gBACN,KAAK;gBACL,qCAAqC,CAAC,IAAI,EAAE;oBAC1C,IAAI,EAAE,6BAA6B;oBACnC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ;oBACpC,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;oBACnB,WAAW,EAAE,QAAQ,CAAC,gBAAgB;oBACtC,MAAM;iBACP,CAAC;aACH,CAAC,CACH,CAAC,SAAS;gBAEX,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACvC,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC9B,OAAO;gBACL,OAAO,EAAE,WAAW;gBACpB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ;gBACnC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS;aACtC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { ResolutionLearningStagedReviewApplication } from "./resolution-learning-staged-types.js";
1
2
  import type { AccessContext } from "@pegma/authorization-core";
2
3
  import type { IsoTimestamp, PrincipalId } from "@pegma/spine";
3
4
  import type { TicketId } from "@pegma/support-desk-contracts";
@@ -120,6 +121,10 @@ export interface ResolutionLearningChecksPort {
120
121
  verify(receipt: string, binding: ResolutionLearningChecksBinding): Promise<VerifiedResolutionLearningChecks | null>;
121
122
  }
122
123
  export interface ResolutionLearningOptions {
124
+ /** Opt-in durable human-review commands. Inline review remains the default. */
125
+ readonly stagedReviews?: boolean;
126
+ /** Counts all retained pending and terminal attempts; preserves bounded privacy withdrawal. */
127
+ readonly maxStagedReviewAttempts?: number;
123
128
  readonly enabled?: boolean;
124
129
  readonly productContext?: ResolutionProductContextPort;
125
130
  readonly testReceipts?: ResolutionTestReceiptPort;
@@ -334,6 +339,7 @@ export interface RecordResolutionLearningReconciliationCommand {
334
339
  };
335
340
  }
336
341
  export interface ResolutionLearningApplication {
342
+ readonly stagedResolutionLearningReviews?: ResolutionLearningStagedReviewApplication;
337
343
  enrollResolutionLearning(access: AccessContext, command: EnrollResolutionLearningCommand): Promise<ResolutionLearningSourceResult>;
338
344
  submitResolutionEvidence(access: AccessContext, command: SubmitResolutionEvidenceCommand): Promise<ResolutionLearningSourceResult>;
339
345
  readResolutionLearningSource(access: AccessContext, ticketId: TicketId): Promise<ResolutionLearningSourceRecord>;