@sagentlab/navarch-runtime 0.1.116 → 0.1.117

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 (51) hide show
  1. package/README.md +43 -17
  2. package/bin/muse-mcp-bridge.cjs +3 -0
  3. package/dist/adapters/index.cjs +6 -1
  4. package/dist/adapters/muse.cjs +433 -0
  5. package/dist/agent-auth.cjs +2 -1
  6. package/dist/config.cjs +8 -1
  7. package/dist/conversation/capability.cjs +1 -1
  8. package/dist/exit-conditions.cjs +1 -1
  9. package/dist/muse-mcp-bridge.cjs +167 -0
  10. package/dist/session.cjs +30 -8
  11. package/node_modules/@muse-code/sdk/LICENSE +21 -0
  12. package/node_modules/@muse-code/sdk/README.md +88 -0
  13. package/node_modules/@muse-code/sdk/dist/src/connection/connection.d.ts +149 -0
  14. package/node_modules/@muse-code/sdk/dist/src/connection/connection.js +581 -0
  15. package/node_modules/@muse-code/sdk/dist/src/connection/spawn.d.ts +188 -0
  16. package/node_modules/@muse-code/sdk/dist/src/connection/spawn.js +496 -0
  17. package/node_modules/@muse-code/sdk/dist/src/errors.d.ts +71 -0
  18. package/node_modules/@muse-code/sdk/dist/src/errors.js +76 -0
  19. package/node_modules/@muse-code/sdk/dist/src/facade/approval.d.ts +96 -0
  20. package/node_modules/@muse-code/sdk/dist/src/facade/approval.js +293 -0
  21. package/node_modules/@muse-code/sdk/dist/src/facade/client.d.ts +171 -0
  22. package/node_modules/@muse-code/sdk/dist/src/facade/client.js +442 -0
  23. package/node_modules/@muse-code/sdk/dist/src/facade/discarded.d.ts +36 -0
  24. package/node_modules/@muse-code/sdk/dist/src/facade/discarded.js +36 -0
  25. package/node_modules/@muse-code/sdk/dist/src/facade/gap-fill.d.ts +80 -0
  26. package/node_modules/@muse-code/sdk/dist/src/facade/gap-fill.js +388 -0
  27. package/node_modules/@muse-code/sdk/dist/src/facade/host-death.d.ts +139 -0
  28. package/node_modules/@muse-code/sdk/dist/src/facade/host-death.js +96 -0
  29. package/node_modules/@muse-code/sdk/dist/src/facade/host-start.d.ts +62 -0
  30. package/node_modules/@muse-code/sdk/dist/src/facade/host-start.js +81 -0
  31. package/node_modules/@muse-code/sdk/dist/src/facade/session.d.ts +309 -0
  32. package/node_modules/@muse-code/sdk/dist/src/facade/session.js +654 -0
  33. package/node_modules/@muse-code/sdk/dist/src/facade/turn-handle.d.ts +156 -0
  34. package/node_modules/@muse-code/sdk/dist/src/facade/turn-handle.js +271 -0
  35. package/node_modules/@muse-code/sdk/dist/src/facade/turn-submit.d.ts +72 -0
  36. package/node_modules/@muse-code/sdk/dist/src/facade/turn-submit.js +183 -0
  37. package/node_modules/@muse-code/sdk/dist/src/fingerprint.d.ts +37 -0
  38. package/node_modules/@muse-code/sdk/dist/src/fingerprint.js +54 -0
  39. package/node_modules/@muse-code/sdk/dist/src/fold/item-store.d.ts +110 -0
  40. package/node_modules/@muse-code/sdk/dist/src/fold/item-store.js +169 -0
  41. package/node_modules/@muse-code/sdk/dist/src/fold/session-fold.d.ts +536 -0
  42. package/node_modules/@muse-code/sdk/dist/src/fold/session-fold.js +427 -0
  43. package/node_modules/@muse-code/sdk/dist/src/fold/state-store.d.ts +68 -0
  44. package/node_modules/@muse-code/sdk/dist/src/fold/state-store.js +89 -0
  45. package/node_modules/@muse-code/sdk/dist/src/index.d.ts +65 -0
  46. package/node_modules/@muse-code/sdk/dist/src/index.js +57 -0
  47. package/node_modules/@muse-code/sdk/dist/src/msp.d.ts +3380 -0
  48. package/node_modules/@muse-code/sdk/dist/src/pending/pending-command-set.d.ts +361 -0
  49. package/node_modules/@muse-code/sdk/dist/src/pending/pending-command-set.js +468 -0
  50. package/node_modules/@muse-code/sdk/package.json +47 -0
  51. package/package.json +8 -4
@@ -0,0 +1,536 @@
1
+ /**
2
+ * `SessionFold` — the SS4 client fold, bound to the generated wire types
3
+ * (spec 14990 FR-007, tasks.md T019).
4
+ *
5
+ * `ItemStore` and `SessionStateStore` are generic because they were written
6
+ * before the session-view plane entered the generated declarations. This
7
+ * module is where the generic parameters are BOUND: items are `@muse-code/msp`'s
8
+ * `Item`, state-family values are the generated `session/*` params objects,
9
+ * and every event this fold accepts is typed as the params object the wire
10
+ * actually carries. Nothing here restates a wire shape (INV-001).
11
+ *
12
+ * Beyond the two-store composition, the fold owns the parts of the view that
13
+ * are neither an item nor a state family:
14
+ *
15
+ * - the TURN LIFECYCLE — `turn/started`, `turn/completed`, `turn/retracted`,
16
+ * `turn/unqueued`, and the non-terminal `turn/retryScheduled` and
17
+ * `turn/foregroundCompleted`;
18
+ * - the APPROVAL and USER-INPUT view events as fold INPUTS — the pending
19
+ * sets and their first durable terminal. The decision flow (choosing and
20
+ * sending a resolution) is the facade's, not the fold's;
21
+ * - the DELIVERY marker `view/gap` — it seeds no store, it moves the fold's
22
+ * CURRENCY (`pendingGap`/`current`, FM-003). The recovery that fills the
23
+ * hole needs client→server I/O and is therefore the facade's (T032).
24
+ *
25
+ * INV-006 governs all of it: the fold never invents a terminal. A retract and
26
+ * a reclaim are not `TurnTerminal` values and are never rendered as one, an
27
+ * unrecognized `TurnTerminal` is kept verbatim, and a second resolution never
28
+ * displaces the first durable one.
29
+ */
30
+ import type { ApprovalRequestParams, ApprovalResolvedParams, ApprovalUpdatedParams, Item, ItemCompletedParams, ItemDeltaParams, ItemStartedParams, ItemUpdatedParams, MspNotification, SessionApprovalModeChangedParams, SessionBranchChangedParams, SessionContextUsageParams, SessionGoalChangedParams, SessionModelChangedParams, SessionModelRouteUnservedParams, SessionNameChangedParams, SessionReasoningEffortChangedParams, SessionTodoListChangedParams, SessionTokenUsageParams, TurnCompletedParams, TurnError, TurnForegroundCompletedParams, TurnRetractedParams, TurnRetryScheduledParams, TurnStartedParams, TurnTerminal, TurnUnqueuedParams, UserInputRequestParams, UserInputSettledParams, ViewGapParams } from "../msp.js";
31
+ import type { DeltaApplyOutcome, ItemApplyOutcome, TerminalUnknownItemAnnotation } from "./item-store.js";
32
+ import type { StateApplyOutcome, StateValue } from "./state-store.js";
33
+ /** The session-state families, each keyed in the store by its method name. */
34
+ export type SessionStateParams = SessionApprovalModeChangedParams | SessionBranchChangedParams | SessionContextUsageParams | SessionGoalChangedParams | SessionModelChangedParams | SessionNameChangedParams | SessionReasoningEffortChangedParams | SessionTodoListChangedParams | SessionTokenUsageParams;
35
+ /** A view notification, paired with the generated params object it carries. */
36
+ export type ViewEvent = {
37
+ readonly method: "item/started";
38
+ readonly params: ItemStartedParams;
39
+ } | {
40
+ readonly method: "item/updated";
41
+ readonly params: ItemUpdatedParams;
42
+ } | {
43
+ readonly method: "item/completed";
44
+ readonly params: ItemCompletedParams;
45
+ } | {
46
+ readonly method: "item/delta";
47
+ readonly params: ItemDeltaParams;
48
+ } | {
49
+ readonly method: "turn/started";
50
+ readonly params: TurnStartedParams;
51
+ } | {
52
+ readonly method: "turn/completed";
53
+ readonly params: TurnCompletedParams;
54
+ } | {
55
+ readonly method: "turn/foregroundCompleted";
56
+ readonly params: TurnForegroundCompletedParams;
57
+ } | {
58
+ readonly method: "turn/retracted";
59
+ readonly params: TurnRetractedParams;
60
+ } | {
61
+ readonly method: "turn/retryScheduled";
62
+ readonly params: TurnRetryScheduledParams;
63
+ } | {
64
+ readonly method: "turn/unqueued";
65
+ readonly params: TurnUnqueuedParams;
66
+ } | {
67
+ readonly method: "approval/requested";
68
+ readonly params: ApprovalRequestParams;
69
+ } | {
70
+ readonly method: "approval/updated";
71
+ readonly params: ApprovalUpdatedParams;
72
+ } | {
73
+ readonly method: "approval/resolved";
74
+ readonly params: ApprovalResolvedParams;
75
+ } | {
76
+ readonly method: "userInput/requested";
77
+ readonly params: UserInputRequestParams;
78
+ } | {
79
+ readonly method: "userInput/settled";
80
+ readonly params: UserInputSettledParams;
81
+ } | {
82
+ readonly method: "session/modelChanged";
83
+ readonly params: SessionModelChangedParams;
84
+ } | {
85
+ readonly method: "session/reasoningEffortChanged";
86
+ readonly params: SessionReasoningEffortChangedParams;
87
+ } | {
88
+ readonly method: "session/goalChanged";
89
+ readonly params: SessionGoalChangedParams;
90
+ } | {
91
+ readonly method: "session/todoListChanged";
92
+ readonly params: SessionTodoListChangedParams;
93
+ } | {
94
+ readonly method: "session/branchChanged";
95
+ readonly params: SessionBranchChangedParams;
96
+ } | {
97
+ readonly method: "session/tokenUsage";
98
+ readonly params: SessionTokenUsageParams;
99
+ } | {
100
+ readonly method: "session/contextUsage";
101
+ readonly params: SessionContextUsageParams;
102
+ } | {
103
+ readonly method: "session/approvalModeChanged";
104
+ readonly params: SessionApprovalModeChangedParams;
105
+ } | {
106
+ readonly method: "session/nameChanged";
107
+ readonly params: SessionNameChangedParams;
108
+ }
109
+ /**
110
+ * The one-shot login-swap route disclosure (#25603, tdd SS4.6.8): routed to
111
+ * its own non-storing outcome — a notice, never sticky session state.
112
+ */
113
+ | {
114
+ readonly method: "session/modelRouteUnserved";
115
+ readonly params: SessionModelRouteUnservedParams;
116
+ }
117
+ /**
118
+ * The delivery-plane marker (tdd SS4.8). A `ViewEvent` since spec 14990
119
+ * T032, and the ONE arm that changes no session state: it names a hole in
120
+ * DELIVERY rather than a change in the view, so what it moves is the fold's
121
+ * CURRENCY — see `pendingGap` below.
122
+ *
123
+ * D-24021-1 excluded it deliberately and left the flip to this lane
124
+ * ("that lane owns removing the exclusion"). The flip is recorded in
125
+ * `specs/14990-muse-sdk/decisions/23980-fold-the-view-gap-marker.md`. What
126
+ * changed is not the structural fact D-24021-1 named — the marker still
127
+ * carries no `viewCursor` and no `sourceRange`, and still seeds nothing into
128
+ * either store — but the SDK's answer to it: a frame this package fully
129
+ * recognizes may not be reported as `ignoredUnrecognizedMethod`, because
130
+ * that is the report reserved for a NEWER host's method this SDK has never
131
+ * heard of (SS1.5.4), and a consumer told that cannot tell a tolerated
132
+ * unknown from an unfilled hole.
133
+ */
134
+ | {
135
+ readonly method: "view/gap";
136
+ readonly params: ViewGapParams;
137
+ };
138
+ /**
139
+ * Compile-time coverage: every `MspNotification` except the handshake's
140
+ * `initialized` and the live host-state projections is a fold input. A #206
141
+ * enrollment that adds a view notification fails HERE rather than being
142
+ * silently ignored at runtime.
143
+ *
144
+ * The exclusions, each excluded because it is NOT a view event:
145
+ * - `initialized` is a HANDSHAKE notification, answered by `MspHandshake`
146
+ * before this fold exists. (The `view/gap` exclusion D-24021-1 recorded
147
+ * was removed by spec 14990 T032 when the marker became the `ViewEvent`
148
+ * arm above.)
149
+ * - `session/started` and `session/closed` (#33065's enrollment) are SS2.6
150
+ * control-plane lifecycle broadcasts, not view events — they carry no
151
+ * foldable view envelope (no `sourceRange`; `closed`'s `viewCursor` is a
152
+ * final session head, not view state), and a fold over session-view state
153
+ * has nothing to apply. Today a lifecycle frame keeps the pre-enrollment
154
+ * runtime answer (`ignoredUnrecognizedMethod`, pinned by the session-fold
155
+ * test); #33102 owns consciously surfacing the pair, the same sanctioned
156
+ * initial-drop shape D-24021-1 used for `view/gap` before T032 flipped it.
157
+ * - `session/viewHealthChanged` (#32557, ADR 32557) is a COMMAND-PLANE
158
+ * health push, not a view-fold event: it reports that the live view
159
+ * stream stopped, so it carries no cursor and folds into no transcript
160
+ * state. A consumer handles it out of band (mark the session view
161
+ * unhealthy), never through this fold.
162
+ * - `usage/changed` (ADR 32563 D3, tdd SS3.23) is a live HOST-STATE push
163
+ * outside the view altitude: no `viewCursor`, no `sourceRange`, nothing
164
+ * seeded into either store; it reaches consumers through the ordinary
165
+ * notification hook, not this fold.
166
+ * - `skill/changed` (ADR 32471 D3, tdd SS3.22.2) is a live host-state
167
+ * projection carrying `sessionId` only — no `viewCursor`, no
168
+ * `sourceRange`, nothing durable to fold. The SDK consumer's reaction is
169
+ * an ACTION (re-issue `skill/list`), not fold state, so it rides the
170
+ * client's notification callback rather than this fold.
171
+ */
172
+ type AssertNever<T extends never> = T;
173
+ type LiveHostStateProjection = "skill/changed" | "usage/changed" | "session/statusChanged" | "session/listChanged" | "plugin/changed" | "plugin/marketplaceChanged" | "computerUseSetup/changed";
174
+ type SessionLifecycleBroadcast = "session/started" | "session/closed";
175
+ type NonFoldNotification = "initialized" | "userInput/engaged" | "session/viewHealthChanged" | "recap/completed" | SessionLifecycleBroadcast | LiveHostStateProjection;
176
+ type UnfoldedViewNotification = Exclude<MspNotification, NonFoldNotification | ViewEvent["method"]>;
177
+ export type EveryViewNotificationIsFolded = AssertNever<UnfoldedViewNotification>;
178
+ /**
179
+ * The reverse direction: every `ViewEvent` arm names a REAL generated
180
+ * notification. `Exclude` silently ignores excluder members outside the
181
+ * union, so without this a typo'd or later-retired arm would compile clean
182
+ * as dead code (PR #23087 review round).
183
+ */
184
+ type StaleViewArm = Exclude<ViewEvent["method"], MspNotification>;
185
+ export type NoStaleViewArm = AssertNever<StaleViewArm>;
186
+ /**
187
+ * The same reverse pin for the hand-typed exclusion literals above:
188
+ * `Exclude` silently ignores excluder members outside the union, so a
189
+ * retired or renamed `initialized` — or a lifecycle name that leaves the
190
+ * union — would otherwise compile clean as dead vocabulary (the PR #23087
191
+ * rule, applied to this file's only other hand-typed method set).
192
+ */
193
+ type StaleExclusion = Exclude<NonFoldNotification, MspNotification>;
194
+ export type NoStaleExclusion = AssertNever<StaleExclusion>;
195
+ /**
196
+ * A recursively read-only view of a value.
197
+ *
198
+ * The fold's snapshot getters hand back its OWN stored objects — copying
199
+ * every read would cost more than the fold saves — and the generated wire
200
+ * types carry no `readonly`, so without this a consumer could write through
201
+ * a snapshot into fold state. This is composition over the generated types,
202
+ * never a restatement of one (INV-001).
203
+ *
204
+ * `readonly` is compile-time only; this is a type-level seal against
205
+ * accidental writes, not a runtime freeze. The alternative — deep-freezing
206
+ * or cloning on every read — would be a real cost on the hot path for a
207
+ * hazard the compiler can price at zero (PR #23087 review round).
208
+ */
209
+ export type DeepReadonly<T> = T extends (infer U)[] ? readonly DeepReadonly<U>[] : T extends ReadonlyArray<infer U> ? readonly DeepReadonly<U>[] : T extends object ? {
210
+ readonly [K in keyof T]: DeepReadonly<T[K]>;
211
+ } : T;
212
+ /** The session-state family keys: the `session/*` half of `ViewEvent`. */
213
+ export type SessionStateMethod = ViewEvent["method"] & `session/${string}`;
214
+ /**
215
+ * The methods whose arms can drop a frame as stale. Narrow rather than the
216
+ * whole `ViewEvent["method"]`: a consumer switching on a stale drop would
217
+ * otherwise have to "handle" cases like `item/delta` that no arm produces,
218
+ * and could never match exhaustively. A future arm that starts dropping
219
+ * widens this deliberately (PR #23087 review round).
220
+ */
221
+ export type StaleDroppableMethod = "turn/started" | "turn/completed" | "turn/foregroundCompleted" | "turn/retryScheduled" | "approval/requested" | "approval/updated" | "userInput/requested";
222
+ /**
223
+ * The `NoStaleViewArm` sibling for the union above: these are hand-typed
224
+ * literals, so without this pin a typo'd or later-retired member compiles
225
+ * clean and a consumer told to match `ignoredStaleFrame` exhaustively has to
226
+ * "handle" a case no arm can produce (PR #23087 review round).
227
+ */
228
+ type StrayStaleDroppable = Exclude<StaleDroppableMethod, ViewEvent["method"]>;
229
+ export type EveryStaleDroppableIsWireVocabulary = AssertNever<StrayStaleDroppable>;
230
+ /** Where a turn stands. Client fold state — not a wire vocabulary. */
231
+ export type TurnState = "running" | "settled" | "retracted" | "unqueued";
232
+ /** A turn as the fold has observed it. */
233
+ export interface TurnEntry {
234
+ readonly turnId: string;
235
+ /** The submitting command, when an event carried it. */
236
+ readonly commandId?: string;
237
+ readonly state: TurnState;
238
+ /** The server's terminal, verbatim. Absent unless `turn/completed` folded. */
239
+ readonly terminal?: TurnTerminal;
240
+ /** Present iff the terminal was `"failed"` (tdd SS4.5.1). */
241
+ readonly error?: TurnError;
242
+ /** The latest scheduled model retry; non-terminal (tdd SS4.5.1, D-026). */
243
+ readonly retryScheduled?: TurnRetryScheduledParams;
244
+ /**
245
+ * The latest foreground-completed notice; non-terminal (tdd SS4.5.12).
246
+ * Tells a renderer the answer is done while `blockingAgents` hold the
247
+ * turn; clears on the turn's terminal.
248
+ */
249
+ readonly foregroundCompleted?: TurnForegroundCompletedParams;
250
+ }
251
+ /** An approval awaiting its first durable terminal. */
252
+ export interface PendingApproval {
253
+ readonly approvalId: string;
254
+ readonly requested: ApprovalRequestParams;
255
+ /** The most recent `approval/updated` refresh, if any. */
256
+ readonly latestUpdate?: ApprovalUpdatedParams;
257
+ }
258
+ /** What one `apply` did — enough to drive a render without re-diffing. */
259
+ export type FoldOutcome = {
260
+ readonly kind: "item";
261
+ readonly outcome: ItemApplyOutcome;
262
+ } | {
263
+ readonly kind: "itemDelta";
264
+ readonly outcome: DeltaApplyOutcome;
265
+ } | {
266
+ readonly kind: "turn";
267
+ readonly turnId: string;
268
+ readonly state: TurnState;
269
+ }
270
+ /**
271
+ * `outcome` is sealed for the same reason every getter is (D-14): the
272
+ * store hands back the very object it just stored, so an unsealed
273
+ * `current` is a live handle into fold state — `out.outcome.current
274
+ * .modelId = "..."` would mutate the fold with no cast and break INV-002
275
+ * replay equality. This and `approvalPending.requested` (#36949) are the
276
+ * two `FoldOutcome` arms that carry a params object; every other arm
277
+ * carries only ids, numbers, and booleans, which is why D-14 originally
278
+ * missed this one (#23556 item 2). Both seals are pinned by
279
+ * `@ts-expect-error` write probes in `session-fold.test.ts`.
280
+ */
281
+ | {
282
+ readonly kind: "sessionState";
283
+ readonly outcome: DeepReadonly<StateApplyOutcome<SessionStateParams>>;
284
+ } | {
285
+ readonly kind: "approvalPending";
286
+ readonly approvalId: string;
287
+ /**
288
+ * The pending entry's retained request (#36949): the facade's
289
+ * `approval/updated` re-route needs the request-shape members, and
290
+ * carrying them on the verdict itself makes "the fold vouched for this
291
+ * entry" and "here is that entry" one fact instead of a re-lookup a
292
+ * contract drift could silently miss.
293
+ */
294
+ readonly requested: DeepReadonly<ApprovalRequestParams>;
295
+ } | {
296
+ readonly kind: "approvalResolved";
297
+ readonly approvalId: string;
298
+ /** False when a durable terminal had already landed; the first wins. */
299
+ readonly firstTerminal: boolean;
300
+ } | {
301
+ readonly kind: "userInputPending";
302
+ readonly userInputId: string;
303
+ } | {
304
+ readonly kind: "userInputSettled";
305
+ readonly userInputId: string;
306
+ readonly firstSettlement: boolean;
307
+ } | {
308
+ /**
309
+ * A `view/gap` folded: push delivery dropped everything in the open
310
+ * interval `(after, next)`, so this fold is no longer current until a
311
+ * sanctioned recovery fills it (tdd SS4.8, FM-003).
312
+ *
313
+ * The bounds are the FRAME's own, verbatim — the coalesced outstanding
314
+ * hole is `pendingGap`, which is what a recovery walks. Reported rather
315
+ * than dropped because the SDK recognizes this frame completely: an
316
+ * `ignoredUnrecognizedMethod` here would be indistinguishable from a
317
+ * newer host's genuinely unknown method (SS1.5.4).
318
+ */
319
+ readonly kind: "deliveryGap";
320
+ readonly after: string;
321
+ readonly next: string;
322
+ }
323
+ /**
324
+ * The one-shot login-swap route disclosure (#25603, tdd SS4.6.8): a NOTICE,
325
+ * not a state family — it seeds no store (a repair via `session/setModel`
326
+ * would never clear a stored copy, and a snapshot reseed would wipe it), so
327
+ * the params ride the outcome verbatim for the consumer to render once.
328
+ */
329
+ | {
330
+ readonly kind: "modelRouteUnserved";
331
+ readonly params: SessionModelRouteUnservedParams;
332
+ } | {
333
+ readonly kind: "ignoredUnrecognizedMethod";
334
+ readonly method: string;
335
+ } | {
336
+ /**
337
+ * A frame that carried no `params`. The generated `Notification`
338
+ * declares `params` optional ("omitted entirely when empty"), so the
339
+ * wire can legally deliver one — but no `ViewEvent` arm is foldable
340
+ * without its params object, every one of them reads at least a
341
+ * `sessionId`. Dropped rather than thrown: SS1.5.4's posture is that a
342
+ * frame this SDK cannot fold leaves the rest of the fold intact, and
343
+ * throwing here would kill the consumer's notification pump
344
+ * (PR #23087 review round).
345
+ */
346
+ readonly kind: "ignoredMissingParams";
347
+ readonly method: string;
348
+ } | {
349
+ /**
350
+ * A recognized frame the fold deliberately dropped, leaving state
351
+ * unchanged: a `turn/started` or `turn/completed` for a turn that
352
+ * already left `running`, an `approval/updated` for an approval it
353
+ * never saw requested (or whose entry a resolution already deleted),
354
+ * or a redelivered `approval/requested` / `userInput/requested` for an
355
+ * approval/prompt that already has its durable terminal. Truthful by
356
+ * contract: a "pending" kind here would make a renderer show an entry
357
+ * the fold does not hold (PR #23087 review round).
358
+ *
359
+ * SCOPE. "Dropped" means only that THIS fold's state is unchanged; it
360
+ * does not mean the frame carried nothing. The one known post-terminal
361
+ * frame that carries a first-delivery fact — an `approval/updated`
362
+ * whose `policyPersistence` reports a FAILED `localPersistent` store
363
+ * write, which the server sends AFTER `approval/resolved` (tdd
364
+ * SS5.5/SS6.8) — is dropped here with no accessor holding the reason.
365
+ * Surfacing it is deferred to the facade slice: issue #23379.
366
+ */
367
+ readonly kind: "ignoredStaleFrame";
368
+ readonly method: StaleDroppableMethod;
369
+ readonly id: string;
370
+ };
371
+ /**
372
+ * The fold's read-only view of its `ItemStore`. Every mutation goes through
373
+ * `apply()`; a directly reachable `seed`/`applyDelta` would let a consumer
374
+ * desync the composite view (items cleared, turn/pending maps not), breaking
375
+ * INV-002 replay equality (PR #23087 review round).
376
+ *
377
+ * An ALLOWLIST, stated explicitly: TypeScript never checks `Omit`'s keys
378
+ * against the type, so a renamed or newly added `ItemStore` mutator would
379
+ * land on this exported surface silently. An explicit member list admits
380
+ * only what is written here, in both drift directions.
381
+ *
382
+ * Hiding the mutator METHODS is only half the job. The values these
383
+ * accessors return ARE the fold's stored objects and the generated wire
384
+ * types carry no `readonly`, so `fold.items.get(id).revision = 0` used to
385
+ * typecheck AND stick — defeating the INV-003 revision guard and breaking
386
+ * INV-002 replay equality through the read surface the mutator allowlist
387
+ * was supposed to seal. Every accessor therefore returns `DeepReadonly`
388
+ * (PR #23087 review round).
389
+ */
390
+ export interface FoldItems {
391
+ accumulated(itemId: string, field?: string): string | undefined;
392
+ accumulatedFields(itemId: string): readonly string[];
393
+ readonly ephemeralSessionDiscarded: boolean;
394
+ get(itemId: string): DeepReadonly<Item> | undefined;
395
+ has(itemId: string): boolean;
396
+ isTerminalUnknown(itemId: string): boolean;
397
+ lastOpenedItemId(): string | undefined;
398
+ list(): readonly DeepReadonly<Item>[];
399
+ readonly size: number;
400
+ }
401
+ /**
402
+ * The fold's read-only view of its `SessionStateStore`, stated explicitly
403
+ * rather than derived: the store's `get`/`has` take a bare `string`, so
404
+ * `get("session/modelchanged")` would typecheck and silently read
405
+ * `undefined`. The family key IS protocol vocabulary, so name it — this
406
+ * surface goes public in this PR, and narrowing it later is a break.
407
+ */
408
+ export interface FoldSessionState {
409
+ /**
410
+ * GENERIC in the family, so the return type is that family's params
411
+ * object rather than the 7-way union. With the union, a wrong-family cast
412
+ * (`get("session/goalChanged") as SessionTokenUsageParams`) was a legal
413
+ * narrowing and read the wrong shape silently — the same invisible-miss
414
+ * class the key narrowing closed on the argument side. The method→params
415
+ * map already exists in `ViewEvent`; this just reuses it.
416
+ */
417
+ get<M extends SessionStateMethod>(family: M): DeepReadonly<StateValue<Extract<ViewEvent, {
418
+ method: M;
419
+ }>["params"]>> | undefined;
420
+ has(family: SessionStateMethod): boolean;
421
+ /**
422
+ * Every family that holds a value, in insertion order. Narrowed in the
423
+ * RETURN position too, so the obvious consumer loop —
424
+ * `for (const f of families()) get(f)` — round-trips against this same
425
+ * interface instead of forcing the bare-string cast the parameter
426
+ * narrowing exists to forbid.
427
+ */
428
+ families(): readonly SessionStateMethod[];
429
+ }
430
+ /**
431
+ * The whole client-side session view: items, session state, turns, and the
432
+ * pending approval/user-input sets.
433
+ */
434
+ export declare class SessionFold {
435
+ #private;
436
+ /** Items, snapshot-only: the mutators are `apply()`'s, not the consumer's. */
437
+ get items(): FoldItems;
438
+ /**
439
+ * Discharge the SS2.13.3b ephemeral host-death obligation over the item
440
+ * half: every item still in progress becomes terminal-unknown and the fold
441
+ * refuses further events (spec FM-002; slice 3's T030b).
442
+ *
443
+ * A FOLD-level method rather than a `FoldItems` entry on purpose. `items` is
444
+ * snapshot-only — an allowlist whose whole job is that a store mutator can
445
+ * never leak onto the consumer surface (PR #23087 review round) — and this
446
+ * IS a mutator. Widening the allowlist to reach it would undo that; routing
447
+ * it here keeps exactly one caller (`Session.hostExited`) and leaves the
448
+ * read surface untouched. The in-progress probe stays the caller's, so the
449
+ * store remains wire-shape-blind (INV-001).
450
+ */
451
+ markEphemeralHostDeath(isInProgress: (item: Item) => boolean): readonly TerminalUnknownItemAnnotation[];
452
+ /**
453
+ * The session-state families, keyed by notification method name. Named
454
+ * `sessionState` rather than `state` because the surface contract reserves
455
+ * `state` for the FR-008 aggregate that arrives with snapshot ingestion.
456
+ * Snapshot-only, like `items`.
457
+ */
458
+ get sessionState(): FoldSessionState;
459
+ /** The turn currently running, if one is. */
460
+ get activeTurnId(): string | undefined;
461
+ /**
462
+ * The outstanding delivery hole, or `undefined` when there is none (tdd
463
+ * SS4.8, FM-003).
464
+ *
465
+ * COALESCED, keeping the FIRST `after`: consecutive overflows are one hole
466
+ * from a filler's point of view, which is the client mirror of the server's
467
+ * own D-16487-1 bracket rule. A recovery walks `(after, next)` and calls
468
+ * `gapFilled(next)` with the target it actually reached, so a hole that grew
469
+ * while the walk was in flight cannot be reported filled.
470
+ */
471
+ get pendingGap(): DeepReadonly<ViewGapParams> | undefined;
472
+ /**
473
+ * Is this fold current with the session view?
474
+ *
475
+ * FM-003's "only then reports current": false from the moment a `view/gap`
476
+ * folds until its hole is filled. Live events keep folding meanwhile — they
477
+ * are real facts and dropping them would add a second hole — so this flag is
478
+ * the ONLY statement that the transcript has a hole in it.
479
+ */
480
+ get current(): boolean;
481
+ /**
482
+ * A recovery filled the hole up to `next`. Returns whether it cleared.
483
+ *
484
+ * EQUALITY, never a relational compare (tdd SS4.1): the argument is the
485
+ * target the walk reached, and it clears only when that is still the
486
+ * outstanding target. A gap that arrived mid-walk left a newer `next`, so
487
+ * this answers `false` and the fold stays not-current — the truthful answer,
488
+ * since the second hole is unfilled.
489
+ *
490
+ * A fold-level mutator with the same rationale as `markEphemeralHostDeath`:
491
+ * `items`/`sessionState` are snapshot-only allowlists, and this belongs to
492
+ * neither store.
493
+ */
494
+ gapFilled(next: string): boolean;
495
+ /**
496
+ * Fold one view event.
497
+ *
498
+ * The `default` arm is not defensive padding: the wire is an external
499
+ * boundary and SS1.5.4 makes a NEW notification additive evolution, so a
500
+ * host newer than this SDK really does reach it. Ignoring the frame keeps
501
+ * the rest of the fold intact, which is what tolerance means. The second
502
+ * overload is how such a frame gets in: the wire's actual shape is
503
+ * `{ method: string, params }`, and the ONE tolerance cast lives here
504
+ * rather than at every call site — a hand-written literal for a KNOWN
505
+ * method should use the `ViewEvent` overload and keep its typo checking
506
+ * (PR #23087 review round).
507
+ *
508
+ * `params` is OPTIONAL on the wide overload because the generated
509
+ * `Notification` — the exact type this package's own `NotificationHandler`
510
+ * hands consumers — declares it optional. Requiring it here would make
511
+ * `fold.apply(notification)` a TS2769 and force every wiring site to
512
+ * re-wrap the frame, which is the ceremony this overload exists to remove.
513
+ */
514
+ apply(event: ViewEvent): FoldOutcome;
515
+ apply(event: {
516
+ readonly method: string;
517
+ readonly params?: unknown;
518
+ }): FoldOutcome;
519
+ /** Turns in first-observed order. */
520
+ turns(): readonly DeepReadonly<TurnEntry>[];
521
+ turn(turnId: string): DeepReadonly<TurnEntry> | undefined;
522
+ /** Approvals awaiting a durable terminal, in first-observed order. */
523
+ pendingApprovals(): readonly DeepReadonly<PendingApproval>[];
524
+ /** The winning durable terminal per approval, in first-observed order. */
525
+ resolvedApprovals(): readonly DeepReadonly<ApprovalResolvedParams>[];
526
+ /**
527
+ * Prompts awaiting a durable settlement, in first-observed order. The
528
+ * entries ARE the generated request params — the wire shape already carries
529
+ * `userInputId`, so a wrapper would only duplicate it (unlike
530
+ * `PendingApproval`, which earns its wrapper with `latestUpdate`).
531
+ */
532
+ pendingUserInputs(): readonly DeepReadonly<UserInputRequestParams>[];
533
+ /** The winning durable settlement per prompt, in first-observed order. */
534
+ settledUserInputs(): readonly DeepReadonly<UserInputSettledParams>[];
535
+ }
536
+ export {};