@pegma/support-desk-application 0.1.1 → 0.2.1

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 (86) hide show
  1. package/README.md +237 -7
  2. package/dist/assistant-turn-capacity.d.ts +13 -0
  3. package/dist/assistant-turn-capacity.d.ts.map +1 -0
  4. package/dist/assistant-turn-capacity.js +111 -0
  5. package/dist/assistant-turn-capacity.js.map +1 -0
  6. package/dist/assistant-turn-records.d.ts +68 -0
  7. package/dist/assistant-turn-records.d.ts.map +1 -0
  8. package/dist/assistant-turn-records.js +418 -0
  9. package/dist/assistant-turn-records.js.map +1 -0
  10. package/dist/assistant-turn-types.d.ts +133 -0
  11. package/dist/assistant-turn-types.d.ts.map +1 -0
  12. package/dist/assistant-turn-types.js +2 -0
  13. package/dist/assistant-turn-types.js.map +1 -0
  14. package/dist/assistant-turns.d.ts +42 -0
  15. package/dist/assistant-turns.d.ts.map +1 -0
  16. package/dist/assistant-turns.js +660 -0
  17. package/dist/assistant-turns.js.map +1 -0
  18. package/dist/engineering-evidence.d.ts +20 -0
  19. package/dist/engineering-evidence.d.ts.map +1 -0
  20. package/dist/engineering-evidence.js +899 -0
  21. package/dist/engineering-evidence.js.map +1 -0
  22. package/dist/engineering-followup-internal.d.ts +45 -0
  23. package/dist/engineering-followup-internal.d.ts.map +1 -0
  24. package/dist/engineering-followup-internal.js +2 -0
  25. package/dist/engineering-followup-internal.js.map +1 -0
  26. package/dist/engineering-followup-records.d.ts +209 -0
  27. package/dist/engineering-followup-records.d.ts.map +1 -0
  28. package/dist/engineering-followup-records.js +1434 -0
  29. package/dist/engineering-followup-records.js.map +1 -0
  30. package/dist/engineering-followup-source.d.ts +168 -0
  31. package/dist/engineering-followup-source.d.ts.map +1 -0
  32. package/dist/engineering-followup-source.js +1144 -0
  33. package/dist/engineering-followup-source.js.map +1 -0
  34. package/dist/engineering-followup-types.d.ts +364 -0
  35. package/dist/engineering-followup-types.d.ts.map +1 -0
  36. package/dist/engineering-followup-types.js +2 -0
  37. package/dist/engineering-followup-types.js.map +1 -0
  38. package/dist/engineering-followup-work.d.ts +70 -0
  39. package/dist/engineering-followup-work.d.ts.map +1 -0
  40. package/dist/engineering-followup-work.js +1153 -0
  41. package/dist/engineering-followup-work.js.map +1 -0
  42. package/dist/engineering-internal.d.ts +38 -0
  43. package/dist/engineering-internal.d.ts.map +1 -0
  44. package/dist/engineering-internal.js +11 -0
  45. package/dist/engineering-internal.js.map +1 -0
  46. package/dist/engineering-policy.d.ts +47 -0
  47. package/dist/engineering-policy.d.ts.map +1 -0
  48. package/dist/engineering-policy.js +579 -0
  49. package/dist/engineering-policy.js.map +1 -0
  50. package/dist/engineering-reconciliation.d.ts +6 -0
  51. package/dist/engineering-reconciliation.d.ts.map +1 -0
  52. package/dist/engineering-reconciliation.js +464 -0
  53. package/dist/engineering-reconciliation.js.map +1 -0
  54. package/dist/engineering-records.d.ts +227 -0
  55. package/dist/engineering-records.d.ts.map +1 -0
  56. package/dist/engineering-records.js +1272 -0
  57. package/dist/engineering-records.js.map +1 -0
  58. package/dist/engineering-types.d.ts +505 -0
  59. package/dist/engineering-types.d.ts.map +1 -0
  60. package/dist/engineering-types.js +2 -0
  61. package/dist/engineering-types.js.map +1 -0
  62. package/dist/engineering-work.d.ts +32 -0
  63. package/dist/engineering-work.d.ts.map +1 -0
  64. package/dist/engineering-work.js +1757 -0
  65. package/dist/engineering-work.js.map +1 -0
  66. package/dist/index.d.ts +609 -14
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +3680 -233
  69. package/dist/index.js.map +1 -1
  70. package/dist/resolution-learning-records.d.ts +154 -0
  71. package/dist/resolution-learning-records.d.ts.map +1 -0
  72. package/dist/resolution-learning-records.js +657 -0
  73. package/dist/resolution-learning-records.js.map +1 -0
  74. package/dist/resolution-learning-types.d.ts +356 -0
  75. package/dist/resolution-learning-types.d.ts.map +1 -0
  76. package/dist/resolution-learning-types.js +2 -0
  77. package/dist/resolution-learning-types.js.map +1 -0
  78. package/dist/resolution-learning-worker.d.ts +21 -0
  79. package/dist/resolution-learning-worker.d.ts.map +1 -0
  80. package/dist/resolution-learning-worker.js +1027 -0
  81. package/dist/resolution-learning-worker.js.map +1 -0
  82. package/dist/resolution-learning.d.ts +38 -0
  83. package/dist/resolution-learning.d.ts.map +1 -0
  84. package/dist/resolution-learning.js +860 -0
  85. package/dist/resolution-learning.js.map +1 -0
  86. package/package.json +6 -6
package/README.md CHANGED
@@ -3,6 +3,93 @@
3
3
  Authorized customer ticket services and provider-neutral durable outbox
4
4
  records for Support Desk. The host supplies an `@pegma/storage-core` `Store`
5
5
  and a trusted Authorization Core access context.
6
+ The host server supplies `correlationId` on commands; the application validates
7
+ and propagates it and never generates it.
8
+
9
+ The verified published synchronized release is `0.2.0` and includes changes
10
+ beyond the immutable `0.1.1` artifacts. SD-01 adds handling/handoff foundations
11
+ without model generation or a KB dependency. See the
12
+ [publication receipt](../../docs/RELEASING.md#verified-sd-06-publication-2026-11-08).
13
+ Host adoption retains its own activation gates; source checkouts and
14
+ overwritten registry versions are not release substitutes.
15
+
16
+ Source here prepares the synchronized **unpublished `0.2.1` candidate** for
17
+ assistant-answering read batching. Independent Store reads are grouped while
18
+ current authority, ticket and turn fences remain required. This package gains
19
+ no KB or provider dependency. Current-head validation, review, trusted release
20
+ and strict registry verification remain pending; grouped reads do not establish
21
+ a universal host query or CPU budget.
22
+
23
+ SD-02's merged source adds opt-in `assistantTurns` and the
24
+ `AssistantTurnApplication` methods `scanAssistantTurnCandidates`,
25
+ `claimAssistantTurn`, `prepareAssistantTurnAttempt`, `completeAssistantTurn`,
26
+ and `finishAssistantTurnAttempt`. These keep bounded causal turn work beside
27
+ the ticket and expose fixed answer/escalation completion with a read-only
28
+ validation guard. They add no KB or provider dependency to this package;
29
+ the optional `@pegma/support-desk-ai` coordinator owns those integrations.
30
+ Lease/preparation/retry metadata do not bump Ticket revision, exact receipts recover
31
+ ambiguous commits, and request-person/takeover remain provider-independent.
32
+ See the [layout checkpoint](../../docs/COLLECTIONS.md#sd-02-assistant-turn-layout-checkpoint)
33
+ and [coordination guide](../../docs/ASSISTANT_COORDINATION.md). SDK validation
34
+ and publication do not establish host activation.
35
+
36
+ SD-03's merged source adds opt-in `resolutionLearning` and fixed evidence,
37
+ work, exact staff review, withdrawal, and reconciliation operations. The
38
+ [resolution learning guide](../../docs/RESOLUTION_LEARNING.md) documents the
39
+ `support.learning.*` permissions, trusted evidence ports, 13-row human reserve
40
+ plus two withdrawal rows, and source retention requirements. The public AI
41
+ learning coordinator and KB delivery integration live in the optional AI
42
+ package. This application
43
+ package still has no KB or model-provider dependency.
44
+
45
+ SD-04's merged source adds optional `engineering` evidence/work services and
46
+ bounded `engineeringPolicy` configuration. Repository policy has its own
47
+ declared collection and atomic Audit/receipts. Engineering source/work records
48
+ share the ticket partition, with independent withdrawal and terminal-result
49
+ capacity reserved before external dispatch. The optional AI package supplies
50
+ model and GitHub coordination through host ports. See the
51
+ [engineering guide](../../docs/ENGINEERING_EXPORT.md). Host adoption retains
52
+ its own activation gates after verified SDK publication.
53
+
54
+ SD-05's merged source adds optional `engineeringFollowup` services
55
+ through `EngineeringFollowupApplication`. Signed allowlisted input and current
56
+ confirmed fix-to-product/build/deployment mapping establish bounded private
57
+ follow-up work; issue closure or a release tag alone does not. Independent
58
+ issue/deployment generations and captured source/destination revocation epochs
59
+ fence stale associations. Default four, hard maximum eight semantic work sets
60
+ share the existing ticket partition; delivered work never rearms.
61
+
62
+ `prepareEngineeringFollowupBundle` requires mode `prepare` or
63
+ `staff_reassessment`. `rejectEngineeringFollowupBundle` is a local staff review
64
+ with a reason, independent of provider/export availability. The combined
65
+ `approveAndPostEngineeringFollowupWebUpdate` commits one authenticated web
66
+ notice, quota, Audit/receipt, and delivered marker while preserving status,
67
+ handling, and first-staff-response facts. No worker or email sends a notice.
68
+ Five prepaid rows and one message slot cover bundle preparation and posting;
69
+ parent engineering withdrawal scrubs children using its existing privacy reserve.
70
+ Admission checks each actual stage: exact model manifests and their completion
71
+ states before paid work, then actual bundle/request counts and later retest/post
72
+ states at bundle preparation. Retest Audit/receipts use ordinary capacity.
73
+ `recoverEngineeringFollowupPreparation` returns only an opaque accepted result
74
+ bound to the current staff actor and exact recovery intent before live work or
75
+ proof reads, preventing duplicate preparation after a lost acknowledgement.
76
+ `retryEngineeringFollowupWork` explicitly readmits held/superseded or expired
77
+ draftless model work under fresh same-semantic proof, retaining its ID and
78
+ lifetime attempt cap and reserving five rows plus a slot. Its two Audit/receipt
79
+ rows use ordinary capacity. `abandonEngineeringFollowupWork` locally holds
80
+ undelivered work without provider/proof ports, spends its own two funded rows or
81
+ ordinary capacity, and releases the remaining tail/slot while preserving history.
82
+ Both use current review and queue authority; parent withdrawal remains the
83
+ privacy-erasure operation.
84
+ The optional coordinator additionally needs follow-up read and queue grants for
85
+ new private processing/review; direct base operations retain their purpose
86
+ permissions. Metadata-only receipt replay remains available under each base
87
+ operation's current grants. Zero-row stale/unchanged/unavailable observations
88
+ are live reevaluated reads, with no persisted command receipt.
89
+ See the [release follow-up guide](../../docs/ENGINEERING_FOLLOWUP.md) for trusted
90
+ ports, explicit retry/reassessment, private KB/retest handoffs, and capacity rules.
91
+ SDK validation and publication are recorded in the receipt above; host
92
+ acceptance remains separate.
6
93
 
7
94
  Customer create uses `support.ticket.create`; list and read both use the
8
95
  documented `support.ticket.read.own` permission and then confirm authoritative
@@ -22,8 +109,101 @@ Staff services use the same application factory and ticket partition:
22
109
  | `resolveTicket` | `support.queue.read` + `support.ticket.manage` | → `resolved` (closed tickets must reopen first) |
23
110
  | `closeTicket` | `support.queue.read` + `support.ticket.manage` | → `closed` (resolved only) |
24
111
  | `reopenTicket` | `support.queue.read` + `support.ticket.manage` | resolved/closed → `waiting_on_support` |
112
+ | `setTags` | `support.queue.read` + `support.ticket.manage` | Replace staff tags; status, customer time, and mail unchanged |
25
113
  | `readTicketAuditHistory` | `support.audit.read` | Ordered Audit history for one ticket |
26
114
 
115
+ ### Optional handling and human controls (SD-01)
116
+
117
+ The factory's `assistantHandlingEnabled` defaults to false. Explicit trusted
118
+ web create with `initialHandling: "assistant"` requires both create and
119
+ `support.ticket.assistant.start`. Legacy omission remains human handling with
120
+ no rewrite. No model or KB is configured by enabling these source commands.
121
+ Turning the flag off refuses new assistant creation/replies. Exact committed
122
+ replays remain available after current command permissions and customer
123
+ ownership checks, without new rows or reservations; receipts do not restore
124
+ revoked access.
125
+
126
+ | Method | Permission and boundary |
127
+ | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
128
+ | `readAssistantConversation` | `support.ticket.assistant.read`; service-only safe messages plus revision/handling/customer-trigger fences |
129
+ | `replyAsAssistant` | `support.ticket.assistant.reply`; exact revision/handling/trigger, attributed plain-text reply, no mail |
130
+ | `escalateToHuman` | `support.ticket.assistant.escalate`; exact fences plus bounded handoff work |
131
+ | `requestPerson` | `support.ticket.request_person.own` and ownership; deterministic human request with current customer-safe result |
132
+ | `takeOverTicket` | Queue read plus `support.ticket.take_over`; exact revision/handling fences and historical staff result |
133
+ | `confirmCustomerSuccess` | `support.ticket.confirm_success.own` and ownership/current visible-message proof; always resolves |
134
+ | `readCustomerSuccessConfirmations` | Queue read plus audit read; private text-free confirmation evidence |
135
+
136
+ `readHandoffWork(access, ticketId)` requires queue read and returns bounded
137
+ staff-only work DTOs with summary/guide IDs/transcript references, separate
138
+ from historical staff replay and customer/assistant results.
139
+
140
+ Assistant reads omit internal notes and requester identity. Their extra
141
+ revision/generation metadata is service-only. Assistant commits require the
142
+ latest visible message to remain the triggering customer message; new input
143
+ or human handling defeats stale work. Only a public staff reply establishes
144
+ `firstStaffRespondedAt`. Staff reopen enters human-pending for explicit
145
+ handling; fresh inbound mail and verified email into assistant chat use humans.
146
+
147
+ Customer confirmation supplies `lastSeenVisibleMessageId`, never internal
148
+ revision/generation or free-form evidence. It always resolves (no optional
149
+ flag), requires reopening closed work, and stores proof privately. Already
150
+ human active requests and repeated accepted resolved proof add no rows.
151
+ Assistant reply/escalation return only bounded `HandlingCommandResult` fields.
152
+ Ticket change, work/evidence, Audit, and replay receipt commit together;
153
+ handoff stores bounded summary/guide IDs and transcript references, not copied
154
+ transcripts, notes, or mail jobs.
155
+
156
+ Default `listStaffQueue` uses `handling: "human"`; `"assistant"`/`"all"`
157
+ are explicit supervision views. Quota `assistantManaged` reserves 12 ordinary
158
+ rows and one human message slot until the first staff response; controls keep
159
+ a four-row/one-message tail. Legacy quotas retain their limits. Repeated
160
+ no-ops avoid churn, but finite control cycles remain subject to named capacity.
161
+ See [host composition](../../docs/HOST_COMPOSITION.md#optional-handling-and-deterministic-controls-sd-01)
162
+ and [collections](../../docs/COLLECTIONS.md#sd-01-handling-and-handoff-layout-checkpoint)
163
+ for exact admission, replay, and source/release boundaries.
164
+
165
+ Handoff summaries are limited to 2,000 UTF-16 code units with
166
+ `SupportDeskLimitError` field `handoff_summary`. Complete serialized assistant
167
+ message/handoff records, including wrappers, are limited to 60,000 UTF-16
168
+ bytes with field `serialized_record`; refusal occurs before commit.
169
+
170
+ ### Optional lifecycle extras
171
+
172
+ `setTags` requires queue read plus `support.ticket.manage`. Configure
173
+ `allowedTags` (at most 32 raw entries, normalized, deduplicated, sorted) and
174
+ `maxTagsPerTicket` (default 8, maximum 32). Tags follow the category identifier
175
+ discipline after trimming and lowercasing; each raw label is at most 64
176
+ characters with no controls. `[]` clears tags. This command updates staff time
177
+ and revision only, with an atomic `support.ticket.tags_changed` audit action
178
+ and receipt, and no messages or mail. Queue query `tag` matches one label.
179
+
180
+ Pass optional `responseTargetPolicy: { computeTargets(context) }` to both
181
+ `createSupportDeskApplication` and `createInboundMailProcessor`. The host
182
+ returns canonical ISO `firstResponseDueAt` / `resolutionDueAt` fields as a
183
+ complete replacement on create, customer follow-up (web/email), and priority
184
+ changes. Omitted result fields clear targets; absent policy preserves them.
185
+ The frozen context is content-free and hooks must tolerate retries. First
186
+ public staff reply sets `firstStaffRespondedAt` once. `resolvedAt` describes
187
+ the current resolution cycle; reopen/reply clears it and re-resolution sets
188
+ it again. Calendars, business hours, and presence remain host responsibilities.
189
+
190
+ Queue queries select `target: "first_response" | "resolution"` (resolution
191
+ by default), `targetState: "overdue" | "due_soon"`, and the latter's required
192
+ `dueSoonMilliseconds` (0 to 30 days, rejected otherwise). Sort by `due_soonest` or `due_latest`,
193
+ with completed/missing targets last and ticket ID tie-breaking. All values
194
+ come from authoritative confirmation within existing scan budgets. Tags,
195
+ targets, and milestones stay out of customer DTOs and automatic customer mail.
196
+
197
+ Every staff mutation accepts optional `expectedRevision`. A mismatch fails
198
+ before ticket changes with `SupportDeskStaleRevisionError`, exposing only
199
+ `currentRevision` and `updatedAt` for HTTP 409. Omission retains existing
200
+ conflict retries. Replay detection precedes revision checking; new receipts
201
+ return the original result using a ticket snapshot and message revision cutoff.
202
+ Legacy receipts retain current-detail replay. Run queue repair after upgrade
203
+ to enrich old rows; no automatic target or historical milestone backfill runs.
204
+ See [host composition](../../docs/HOST_COMPOSITION.md#optional-lifecycle-extras-task-13)
205
+ for complete retry, lifecycle, and HTTP semantics.
206
+
27
207
  ### Staff queue projection
28
208
 
29
209
  `support-desk.queue-index.v1` holds one projection row per ticket (partition =
@@ -46,6 +226,12 @@ still terminal beyond the shared cutoff). Both workers require an explicit
46
226
  the application so projection, repair, and sweep share one cutoff. The
47
227
  projection is never ownership or permission evidence.
48
228
 
229
+ A valid positive older active hint can discover a newer active canonical
230
+ ticket, including a human handoff, without waiting for projection repair.
231
+ Malformed, nonpositive, future-revision, and inactive hints are refused;
232
+ canonical fields alone govern handling/filter/sort. Missing or inactive hints
233
+ can still cause a temporary repair gap.
234
+
49
235
  Staff reads return `StaffTicketView` (full `Ticket` and all `TicketMessage`
50
236
  rows). Mutations that return that view also require `support.queue.read` so a
51
237
  narrow write permission cannot bypass the staff-detail boundary. They do not
@@ -87,12 +273,12 @@ When a create includes a notification, Support Desk sets the
87
273
  lifecycle changes. Internal notes, assignment, and priority changes advance
88
274
  only staff-facing `updatedAt` (in core workflow events).
89
275
 
90
- Accepted-change history is exact `@pegma/audit@0.1.0` projected into the
276
+ Accepted-change history is exact `@pegma/audit@0.2.0` projected into the
91
277
  ticket partition with `defineAudit`. Customer create/reply and every staff
92
278
  mutation drop Audit transaction actions beside the state change; history is
93
279
  read through `readTicketAuditHistory` / Audit, not a private sorter. Domain
94
280
  `TicketEvent` remains pure workflow input and is not stored as a second audit
95
- shape. Authorization Core is exact `0.1.2`.
281
+ shape. Authorization Core is exact `0.4.0`.
96
282
 
97
283
  Customer and staff commands are snapshotted from own data properties exactly
98
284
  once before validation, idempotency fingerprinting, or persistence. Accessors
@@ -109,7 +295,7 @@ Outbound `Message-ID` values must be at most 254 ASCII characters with a
109
295
  dot-atom local part, a valid DNS domain, and no controls or malformed dots.
110
296
 
111
297
  Outbound state is the application projection of published exact
112
- `@pegma/mail@0.1.0`. Support Desk keeps its `delivery:*` physical record and
298
+ `@pegma/mail@0.1.1`. Support Desk keeps its `delivery:*` physical record and
113
299
  stores immutable template, subject, and `Message-ID` content on the causal
114
300
  message in the same transaction. The generic package owns claims, provider
115
301
  idempotency, submission generations, retry/reconciliation transitions,
@@ -129,10 +315,54 @@ Reply timestamps are sampled and validated on every transaction attempt, then
129
315
  clamped to the stored ticket's `updatedAt` so clock skew cannot move a
130
316
  conversation backward.
131
317
 
132
- Inbound processing remains a future phase, but its declared receipt collection
133
- is already hard-bounded to 256 hash slots per partition. Terminal receipt
134
- retention uses trusted processing time, a 30-day deduplication horizon, and
135
- version-conditional deletion; in-flight receipts are never swept.
318
+ ### Inbound mail
319
+
320
+ `createInboundMailProcessor({ store, clock, accountMatcher, routingPolicy,
321
+ notificationPolicy?, subjectMarkerPrefix?, supportAddresses?, ... })` returns
322
+ `processInboundEmail(input)`. The host calls it only after verifying the
323
+ provider event and normalizing bounded MIME into `InboundEmailInput` (safe
324
+ text, sender address, host-evaluated `senderAuthentication`, threading headers,
325
+ candidate reply token, and loop signals). There is no permission check: the
326
+ caller is a trusted worker, and the input has no principal, role, plan,
327
+ priority, or session field.
328
+
329
+ For a ticket with `requester.email`, every reply locator requires the
330
+ case-insensitive normalized `from` address to equal that email and a passing
331
+ sender result bound to the same `from`. DMARC requires aligned DKIM or aligned
332
+ SPF; `host_identity` represents an equivalent host-authenticated identity.
333
+ Missing, failed, unaligned, or differently bound results create a new
334
+ unverified related ticket and leave the named ticket unchanged. A ticket
335
+ without a requester email retains the opaque routing-token flow; headers and
336
+ subject markers alone remain insufficient. Sender authentication never selects
337
+ a principal or grants web access.
338
+
339
+ Processing reserves the `support-desk.inbound-receipts.v1` receipt with
340
+ `insertIfAbsent` before ticket work (256 hash slots per partition), suppresses
341
+ bounce and auto-reply loops, persists one routing decision on the receipt,
342
+ and then creates or replies in one ticket-partition transaction with an Audit
343
+ event (`system` actor `support-desk.inbound-email`), a command receipt, and an
344
+ optional notification. Retries and concurrent duplicates return the first
345
+ delivery's result and identifiers. Earlier receipts without a canonical replay
346
+ fingerprint recognize only their exact prior payload shapes, bind the current
347
+ fingerprint before continuing, and retain their original ticket-command
348
+ fingerprint. Matching order is reply token,
349
+ `In-Reply-To`/`References`, then subject marker, all through
350
+ `support-desk.thread-index.v1` key lookups confirmed against authoritative
351
+ records. A repeated inbound message's own `Message-ID` is checked for duplicate
352
+ delivery first; when it does not qualify, its ticket precedes the subject
353
+ marker as the related-ticket fallback. Unsafe or ambiguous matches create a new
354
+ unverified ticket with the staff-only `Ticket.relatedTicketId`. A unique account
355
+ match creates a `matched_email` ticket that stays invisible to customer web
356
+ services.
357
+
358
+ Notifications may carry an optional `replyRoutingToken` (22 to 128 URL-safe
359
+ characters) for the host to render into the reply address. The application
360
+ indexes it by SHA-256, with each notification `Message-ID` and every ticket
361
+ number, after commit. Schedule `repairThreadIndexPage` and
362
+ `sweepThreadIndexPage` with the same `threadIndexRetentionMilliseconds` as the
363
+ processor. Terminal receipt retention uses trusted processing time, a 30-day
364
+ deduplication horizon, and version-conditional deletion; in-flight receipts
365
+ are never swept.
136
366
 
137
367
  ## Host composition
138
368
 
@@ -0,0 +1,13 @@
1
+ import { type AssistantTurnRecord } from "./assistant-turn-records.js";
2
+ /**
3
+ * Reserve a constructive upper bound before a paid request can be prepared.
4
+ * Earlier bindings and metadata remain verbatim. Only the current attempt's
5
+ * accounting/metadata can change; a later preparation must reserve again.
6
+ *
7
+ * The old 8KB gap alone was insufficient: maximum legal processing metadata
8
+ * is 10,898 encoded bytes and finish stores it twice. Count complete reply,
9
+ * escalation, retry/supersession receipts and the largest replacement claim,
10
+ * using the same processing builder and encoder as actual writes.
11
+ */
12
+ export declare function maximumPostPreparationRecordBytes(job: AssistantTurnRecord): number;
13
+ //# sourceMappingURL=assistant-turn-capacity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant-turn-capacity.d.ts","sourceRoot":"","sources":["../src/assistant-turn-capacity.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAmBrC;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,mBAAmB,GACvB,MAAM,CAoFR"}
@@ -0,0 +1,111 @@
1
+ import { assistantTurnProcessingState, encodedBytes, withoutAssistantTurnLease, } from "./assistant-turn-records.js";
2
+ // Each accepted UTF-16 code unit can occupy at most six JSON characters.
3
+ // Lone surrogates reach that bound and are allowed by the text validator.
4
+ const maximumText = "\ud800".repeat(200);
5
+ const maximumProcessing = Object.freeze({
6
+ provider: maximumText,
7
+ model: maximumText,
8
+ requestId: maximumText,
9
+ currency: maximumText,
10
+ failureCategory: "\ud800".repeat(80),
11
+ inputTokens: Number.MAX_SAFE_INTEGER,
12
+ outputTokens: Number.MAX_SAFE_INTEGER,
13
+ costMicros: Number.MAX_SAFE_INTEGER,
14
+ });
15
+ // Extended ISO years have the longest canonical Date.toISOString() shape.
16
+ const maximumTimestamp = "+100000-01-01T00:00:00.000Z";
17
+ const maximumFingerprint = "f".repeat(64);
18
+ /**
19
+ * Reserve a constructive upper bound before a paid request can be prepared.
20
+ * Earlier bindings and metadata remain verbatim. Only the current attempt's
21
+ * accounting/metadata can change; a later preparation must reserve again.
22
+ *
23
+ * The old 8KB gap alone was insufficient: maximum legal processing metadata
24
+ * is 10,898 encoded bytes and finish stores it twice. Count complete reply,
25
+ * escalation, retry/supersession receipts and the largest replacement claim,
26
+ * using the same processing builder and encoder as actual writes.
27
+ */
28
+ export function maximumPostPreparationRecordBytes(job) {
29
+ const base = withoutAssistantTurnLease(job);
30
+ const processed = assistantTurnProcessingState(base, maximumProcessing, {
31
+ attemptId: `${job.turnId}:${job.attempt}`,
32
+ accounting: "not_called", // Longest supported accounting value.
33
+ });
34
+ const key = { ticketId: job.ticketId, turnId: job.turnId };
35
+ const result = {
36
+ ticketId: job.ticketId,
37
+ revision: Number.MAX_SAFE_INTEGER,
38
+ handlingGeneration: Number.MAX_SAFE_INTEGER,
39
+ };
40
+ const finishReceipt = (finishResult) => ({
41
+ fingerprint: maximumFingerprint,
42
+ result: finishResult,
43
+ });
44
+ const retry = {
45
+ ...processed,
46
+ status: "retry",
47
+ nextAttemptAt: maximumTimestamp,
48
+ lastFinish: finishReceipt({
49
+ ...key,
50
+ outcome: "retry_scheduled",
51
+ nextAttemptAt: maximumTimestamp,
52
+ }),
53
+ };
54
+ const superseded = {
55
+ ...processed,
56
+ status: "superseded",
57
+ lastFinish: finishReceipt({ ...key, outcome: "superseded" }),
58
+ };
59
+ const escalated = {
60
+ ...processed,
61
+ status: "escalated",
62
+ terminalResult: result,
63
+ lastFinish: finishReceipt({ ...key, outcome: "escalated", result }),
64
+ };
65
+ const completed = {
66
+ ...assistantTurnProcessingState(base, maximumProcessing),
67
+ status: "completed",
68
+ terminalResult: { ...result, messageId: maximumText },
69
+ };
70
+ const directEscalation = {
71
+ ...assistantTurnProcessingState(base, maximumProcessing),
72
+ status: "escalated",
73
+ terminalResult: result,
74
+ };
75
+ // Retry/expired-lease recovery must still admit the next owner before that
76
+ // owner's preparation can perform its own size reservation. In particular,
77
+ // don't assume its workerId/claimId will be as short as the current owner's.
78
+ const nextAttempt = Math.min(job.maxAttempts, job.attempt + 1);
79
+ const attemptId = `${job.turnId}:${nextAttempt}`;
80
+ const claim = {
81
+ ...key,
82
+ workerId: maximumText,
83
+ claimId: maximumText,
84
+ claimGeneration: nextAttempt,
85
+ attempt: nextAttempt,
86
+ attemptId,
87
+ commandId: `assistant-complete:${attemptId}`,
88
+ correlationId: job.correlationId,
89
+ expectedRevision: Number.MAX_SAFE_INTEGER,
90
+ expectedHandlingGeneration: job.triggerHandlingGeneration,
91
+ triggerMessageId: job.triggerMessageId,
92
+ };
93
+ const { nextAttemptAt: _retryAt, ...afterRetry } = retry;
94
+ const replacement = {
95
+ ...afterRetry,
96
+ status: "claimed",
97
+ attempt: nextAttempt,
98
+ claimGeneration: nextAttempt,
99
+ claim,
100
+ leaseUntil: maximumTimestamp,
101
+ };
102
+ return Math.max(...[
103
+ retry,
104
+ superseded,
105
+ escalated,
106
+ completed,
107
+ directEscalation,
108
+ replacement,
109
+ ].map(encodedBytes));
110
+ }
111
+ //# sourceMappingURL=assistant-turn-capacity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant-turn-capacity.js","sourceRoot":"","sources":["../src/assistant-turn-capacity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { IsoTimestamp } from "@pegma/spine";
2
+ import type { EntityKey } from "@pegma/storage-core";
3
+ import type { Ticket, TicketMessage } from "@pegma/support-desk-contracts";
4
+ import type { HandlingCommandResult } from "./index.js";
5
+ import type { AssistantAttemptBinding, AssistantPreparedAttempt, AssistantTurnClaimFence, AssistantTurnAccounting, AssistantTurnFinishResult, AssistantTurnOptions, AssistantTurnProcessingMetadata } from "./assistant-turn-types.js";
6
+ export interface ResolvedAssistantTurnOptions {
7
+ readonly maxAttempts: number;
8
+ readonly maxTurnMilliseconds: number;
9
+ readonly maxLeaseMilliseconds: number;
10
+ }
11
+ /** One bounded row per causal message; attempts never append physical rows. */
12
+ export interface AssistantTurnRecord {
13
+ readonly kind: "assistant_turn";
14
+ readonly partition: string;
15
+ readonly id: string;
16
+ readonly ticketId: string;
17
+ readonly turnId: string;
18
+ readonly triggerMessageId: string;
19
+ readonly triggerRevision: number;
20
+ readonly triggerHandlingGeneration: number;
21
+ readonly correlationId: string;
22
+ readonly createdAt: IsoTimestamp;
23
+ readonly turnDeadline: IsoTimestamp;
24
+ readonly maxAttempts: number;
25
+ readonly status: "pending" | "claimed" | "retry" | "completed" | "escalated" | "superseded";
26
+ readonly attempt: number;
27
+ readonly claimGeneration: number;
28
+ readonly claim?: AssistantTurnClaimFence;
29
+ readonly leaseUntil?: IsoTimestamp;
30
+ readonly nextAttemptAt?: IsoTimestamp;
31
+ readonly preparedAttempts: readonly AssistantPreparedAttempt[];
32
+ readonly processing?: AssistantTurnProcessingMetadata;
33
+ readonly terminalResult?: HandlingCommandResult;
34
+ readonly lastFinish?: {
35
+ readonly fingerprint: string;
36
+ readonly result: AssistantTurnFinishResult;
37
+ };
38
+ }
39
+ export declare const maximumRecordBytes = 60000;
40
+ /** Initial ceiling; preparation also reserves the largest reachable later state. */
41
+ export declare const preparedRecordBytes = 52000;
42
+ export declare const maximumBindingBytes = 12000;
43
+ export declare function dataObject(value: unknown, name: string): Record<string, unknown>;
44
+ export declare function fields(value: unknown, name: string, required: readonly string[], optional?: readonly string[]): Record<string, unknown>;
45
+ export declare function dataArray(value: unknown, name: string, maximum: number): readonly unknown[];
46
+ export declare function text(value: unknown, name: string, maximum?: number): string;
47
+ export declare function integer(value: unknown, name: string, minimum?: number, maximum?: number): number;
48
+ export declare function timestamp(value: unknown, name: string): number;
49
+ export declare function encodedBytes(value: unknown): number;
50
+ export declare function canonical(value: unknown): string;
51
+ export declare function fingerprint(value: unknown): Promise<string>;
52
+ export declare function snapshot<T>(value: T): T;
53
+ export declare function resolveAssistantTurnOptions(input: AssistantTurnOptions | undefined): ResolvedAssistantTurnOptions | undefined;
54
+ export declare function assistantTurnKey(ticketId: string, turnId: string): EntityKey;
55
+ export declare function terminalTurn(record: AssistantTurnRecord): boolean;
56
+ export declare function withoutAssistantTurnLease(job: AssistantTurnRecord): AssistantTurnRecord;
57
+ /** Shared by real state changes and the constructive preparation size bound. */
58
+ export declare function assistantTurnProcessingState(job: AssistantTurnRecord, processing: AssistantTurnProcessingMetadata | undefined, accounting?: {
59
+ readonly attemptId: string;
60
+ readonly accounting: AssistantTurnAccounting;
61
+ }): AssistantTurnRecord;
62
+ export declare function createAssistantTurnRecord(ticket: Ticket, message: TicketMessage, correlationId: string, options: ResolvedAssistantTurnOptions): Promise<AssistantTurnRecord>;
63
+ export declare const assistantTurnFenceFields: readonly string[];
64
+ export declare function validateFence(input: unknown, extraRequired?: readonly string[], extraOptional?: readonly string[]): AssistantTurnClaimFence & Record<string, unknown>;
65
+ export declare function validateProcessing(input: unknown): AssistantTurnProcessingMetadata | undefined;
66
+ export declare function validateBinding(input: unknown): AssistantAttemptBinding;
67
+ export declare function assertAssistantTurnRecord(value: AssistantTurnRecord, physical?: EntityKey): void;
68
+ //# sourceMappingURL=assistant-turn-records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant-turn-records.d.ts","sourceRoot":"","sources":["../src/assistant-turn-records.ts"],"names":[],"mappings":"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"}